summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format2
-rw-r--r--.gitattributes2
-rw-r--r--.github/CODEOWNERS4
-rw-r--r--.github/actions/godot-build/action.yml2
-rw-r--r--.github/workflows/ios_builds.yml2
-rw-r--r--.github/workflows/linux_builds.yml25
-rw-r--r--.github/workflows/macos_builds.yml11
-rw-r--r--.github/workflows/static_checks.yml4
-rw-r--r--.github/workflows/windows_builds.yml2
-rw-r--r--.mailmap3
-rw-r--r--AUTHORS.md10
-rw-r--r--DONORS.md144
-rw-r--r--SConstruct100
-rw-r--r--core/SCsub4
-rw-r--r--core/config/engine.cpp12
-rw-r--r--core/config/engine.h4
-rw-r--r--core/config/project_settings.cpp7
-rw-r--r--core/core_bind.cpp126
-rw-r--r--core/core_bind.h22
-rw-r--r--core/core_constants.cpp21
-rw-r--r--core/core_constants.h2
-rw-r--r--core/core_globals.cpp35
-rw-r--r--core/core_globals.h (renamed from servers/rendering/renderer_thread_pool.h)21
-rw-r--r--core/crypto/crypto.cpp2
-rw-r--r--core/crypto/crypto.h2
-rw-r--r--core/crypto/crypto_core.h1
-rw-r--r--core/debugger/debugger_marshalls.h6
-rw-r--r--core/debugger/engine_debugger.cpp6
-rw-r--r--core/debugger/engine_debugger.h4
-rw-r--r--core/debugger/local_debugger.cpp7
-rw-r--r--core/debugger/remote_debugger.cpp11
-rw-r--r--core/doc_data.cpp31
-rw-r--r--core/doc_data.h3
-rw-r--r--core/error/error_macros.cpp8
-rw-r--r--core/extension/extension_api_dump.cpp20
-rw-r--r--core/extension/extension_api_dump.h6
-rw-r--r--core/extension/gdnative_interface.cpp12
-rw-r--r--core/extension/gdnative_interface.h18
-rw-r--r--core/extension/native_extension.cpp32
-rw-r--r--core/extension/native_extension.h4
-rw-r--r--core/extension/native_extension_manager.h2
-rw-r--r--core/input/gamecontrollerdb.txt442
-rw-r--r--core/input/input.cpp2
-rw-r--r--core/input/input.h2
-rw-r--r--core/input/input_builders.py4
-rw-r--r--core/input/input_event.cpp19
-rw-r--r--core/input/input_event.h4
-rw-r--r--core/input/shortcut.h1
-rw-r--r--core/io/dir_access.cpp21
-rw-r--r--core/io/dir_access.h3
-rw-r--r--core/io/file_access.cpp7
-rw-r--r--core/io/file_access.h2
-rw-r--r--core/io/file_access_compressed.h32
-rw-r--r--core/io/file_access_encrypted.h38
-rw-r--r--core/io/file_access_memory.h34
-rw-r--r--core/io/file_access_network.h32
-rw-r--r--core/io/file_access_pack.h74
-rw-r--r--core/io/file_access_zip.h32
-rw-r--r--core/io/image.cpp145
-rw-r--r--core/io/image.h18
-rw-r--r--core/io/logger.cpp3
-rw-r--r--core/io/marshalls.cpp151
-rw-r--r--core/io/packet_peer.h2
-rw-r--r--core/io/resource_format_binary.cpp108
-rw-r--r--core/io/resource_format_binary.h4
-rw-r--r--core/io/resource_importer.cpp10
-rw-r--r--core/io/resource_importer.h2
-rw-r--r--core/io/resource_loader.cpp34
-rw-r--r--core/io/resource_loader.h3
-rw-r--r--core/io/resource_saver.cpp24
-rw-r--r--core/io/resource_saver.h6
-rw-r--r--core/io/resource_uid.h6
-rw-r--r--core/io/xml_parser.cpp46
-rw-r--r--core/io/xml_parser.h9
-rw-r--r--core/math/basis.cpp13
-rw-r--r--core/math/bvh.h2
-rw-r--r--core/math/bvh_public.inc6
-rw-r--r--core/math/color.h12
-rw-r--r--core/math/delaunay_3d.h4
-rw-r--r--core/math/expression.cpp2
-rw-r--r--core/math/math_fieldwise.cpp30
-rw-r--r--core/math/octree.h1271
-rw-r--r--core/math/plane.h6
-rw-r--r--core/math/projection.cpp (renamed from core/math/camera_matrix.cpp)255
-rw-r--r--core/math/projection.h (renamed from core/math/camera_matrix.h)59
-rw-r--r--core/math/quaternion.cpp64
-rw-r--r--core/math/quaternion.h4
-rw-r--r--core/math/transform_2d.cpp40
-rw-r--r--core/math/transform_2d.h9
-rw-r--r--core/math/transform_3d.cpp44
-rw-r--r--core/math/transform_3d.h9
-rw-r--r--core/math/vector3.h11
-rw-r--r--core/math/vector4.cpp172
-rw-r--r--core/math/vector4.h302
-rw-r--r--core/math/vector4i.cpp (renamed from core/templates/thread_work_pool.cpp)86
-rw-r--r--core/math/vector4i.h338
-rw-r--r--core/multiplayer/SCsub5
-rw-r--r--core/multiplayer/multiplayer.h80
-rw-r--r--core/multiplayer/multiplayer_api.cpp589
-rw-r--r--core/multiplayer/multiplayer_api.h194
-rw-r--r--core/object/class_db.cpp74
-rw-r--r--core/object/class_db.h34
-rw-r--r--core/object/message_queue.cpp2
-rw-r--r--core/object/object.cpp32
-rw-r--r--core/object/object.h102
-rw-r--r--core/object/script_language.cpp28
-rw-r--r--core/object/script_language.h10
-rw-r--r--core/object/script_language_extension.cpp4
-rw-r--r--core/object/script_language_extension.h49
-rw-r--r--core/object/worker_thread_pool.cpp474
-rw-r--r--core/object/worker_thread_pool.h198
-rw-r--r--core/os/keyboard.cpp2
-rw-r--r--core/os/memory.h9
-rw-r--r--core/os/os.cpp5
-rw-r--r--core/os/os.h7
-rw-r--r--core/os/spin_lock.h1
-rw-r--r--core/os/thread.h1
-rw-r--r--core/register_core_types.cpp27
-rw-r--r--core/string/char_range.inc1456
-rw-r--r--core/string/char_utils.h20
-rw-r--r--core/string/node_path.cpp15
-rw-r--r--core/string/node_path.h2
-rw-r--r--core/string/print_string.cpp9
-rw-r--r--core/string/print_string.h2
-rw-r--r--core/string/ustring.cpp399
-rw-r--r--core/string/ustring.h10
-rw-r--r--core/templates/bin_sorted_array.h2
-rw-r--r--core/templates/cowdata.h13
-rw-r--r--core/templates/hashfuncs.h16
-rw-r--r--core/templates/local_vector.h11
-rw-r--r--core/templates/lru.h7
-rw-r--r--core/templates/paged_allocator.h10
-rw-r--r--core/templates/paged_array.h12
-rw-r--r--core/templates/rb_map.h2
-rw-r--r--core/templates/rb_set.h2
-rw-r--r--core/templates/rid_owner.h20
-rw-r--r--core/templates/safe_refcount.h5
-rw-r--r--core/templates/thread_work_pool.h157
-rw-r--r--core/templates/vector.h4
-rw-r--r--core/variant/array.cpp10
-rw-r--r--core/variant/binder_common.h26
-rw-r--r--core/variant/callable.cpp21
-rw-r--r--core/variant/callable.h14
-rw-r--r--core/variant/callable_bind.cpp29
-rw-r--r--core/variant/callable_bind.h6
-rw-r--r--core/variant/method_ptrcall.h3
-rw-r--r--core/variant/type_info.h49
-rw-r--r--core/variant/variant.cpp331
-rw-r--r--core/variant/variant.h51
-rw-r--r--core/variant/variant_call.cpp181
-rw-r--r--core/variant/variant_construct.cpp15
-rw-r--r--core/variant/variant_construct.h3
-rw-r--r--core/variant/variant_internal.h104
-rw-r--r--core/variant/variant_op.cpp133
-rw-r--r--core/variant/variant_op.h48
-rw-r--r--core/variant/variant_parser.cpp61
-rw-r--r--core/variant/variant_setget.cpp21
-rw-r--r--core/variant/variant_setget.h15
-rw-r--r--core/variant/variant_utility.cpp166
-rw-r--r--doc/class.xsd37
-rw-r--r--doc/classes/@GlobalScope.xml356
-rw-r--r--doc/classes/AcceptDialog.xml4
-rw-r--r--doc/classes/Animation.xml4
-rw-r--r--doc/classes/AnimationNode.xml4
-rw-r--r--doc/classes/AnimationNodeAdd2.xml7
-rw-r--r--doc/classes/AnimationNodeAdd3.xml7
-rw-r--r--doc/classes/AnimationNodeBlend2.xml7
-rw-r--r--doc/classes/AnimationNodeBlend3.xml7
-rw-r--r--doc/classes/AnimationNodeBlendSpace1D.xml4
-rw-r--r--doc/classes/AnimationNodeBlendSpace2D.xml4
-rw-r--r--doc/classes/AnimationNodeOneShot.xml4
-rw-r--r--doc/classes/AnimationNodeStateMachineTransition.xml2
-rw-r--r--doc/classes/AnimationNodeSync.xml15
-rw-r--r--doc/classes/AnimationNodeTransition.xml5
-rw-r--r--doc/classes/AnimationPlayer.xml47
-rw-r--r--doc/classes/AnimationTree.xml2
-rw-r--r--doc/classes/ArrayMesh.xml2
-rw-r--r--doc/classes/AudioEffectRecord.xml6
-rw-r--r--doc/classes/AudioServer.xml6
-rw-r--r--doc/classes/AudioStream.xml18
-rw-r--r--doc/classes/AudioStreamPlayback.xml7
-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/AudioStreamWAV.xml (renamed from doc/classes/AudioStreamSample.xml)10
-rw-r--r--doc/classes/BaseMaterial3D.xml28
-rw-r--r--doc/classes/BoneMap.xml56
-rw-r--r--doc/classes/Button.xml23
-rw-r--r--doc/classes/CPUParticles2D.xml4
-rw-r--r--doc/classes/CPUParticles3D.xml4
-rw-r--r--doc/classes/Camera3D.xml14
-rw-r--r--doc/classes/CanvasItem.xml78
-rw-r--r--doc/classes/CharacterBody3D.xml4
-rw-r--r--doc/classes/CodeEdit.xml3
-rw-r--r--doc/classes/CollisionObject2D.xml7
-rw-r--r--doc/classes/CollisionObject3D.xml7
-rw-r--r--doc/classes/ColorPicker.xml25
-rw-r--r--doc/classes/ConfirmationDialog.xml3
-rw-r--r--doc/classes/Control.xml4
-rw-r--r--doc/classes/Curve.xml1
-rw-r--r--doc/classes/Decal.xml27
-rw-r--r--doc/classes/DisplayServer.xml35
-rw-r--r--doc/classes/EditorExportPlugin.xml2
-rw-r--r--doc/classes/EditorFeatureProfile.xml2
-rw-r--r--doc/classes/EditorFileDialog.xml6
-rw-r--r--doc/classes/EditorPaths.xml6
-rw-r--r--doc/classes/EditorPlugin.xml22
-rw-r--r--doc/classes/EditorProperty.xml7
-rw-r--r--doc/classes/EditorScenePostImportPlugin.xml6
-rw-r--r--doc/classes/EditorSettings.xml731
-rw-r--r--doc/classes/Engine.xml6
-rw-r--r--doc/classes/Environment.xml9
-rw-r--r--doc/classes/File.xml5
-rw-r--r--doc/classes/FileDialog.xml10
-rw-r--r--doc/classes/Font.xml297
-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/GPUParticles2D.xml4
-rw-r--r--doc/classes/GPUParticles3D.xml4
-rw-r--r--doc/classes/GPUParticlesCollisionSDF3D.xml20
-rw-r--r--doc/classes/Geometry2D.xml12
-rw-r--r--doc/classes/GeometryInstance3D.xml4
-rw-r--r--doc/classes/Gradient.xml1
-rw-r--r--doc/classes/GraphEdit.xml23
-rw-r--r--doc/classes/GraphNode.xml21
-rw-r--r--doc/classes/HTTPClient.xml3
-rw-r--r--doc/classes/HTTPRequest.xml4
-rw-r--r--doc/classes/Image.xml44
-rw-r--r--doc/classes/ImageTexture.xml26
-rw-r--r--doc/classes/ImporterMesh.xml2
-rw-r--r--doc/classes/Input.xml5
-rw-r--r--doc/classes/InputEventMouseMotion.xml4
-rw-r--r--doc/classes/ItemList.xml26
-rw-r--r--doc/classes/Label.xml25
-rw-r--r--doc/classes/Label3D.xml31
-rw-r--r--doc/classes/LabelSettings.xml29
-rw-r--r--doc/classes/Light3D.xml19
-rw-r--r--doc/classes/LightmapGI.xml2
-rw-r--r--doc/classes/LightmapGIData.xml2
-rw-r--r--doc/classes/LineEdit.xml49
-rw-r--r--doc/classes/LinkButton.xml23
-rw-r--r--doc/classes/MeshInstance3D.xml2
-rw-r--r--doc/classes/MovieWriter.xml2
-rw-r--r--doc/classes/MultiMesh.xml5
-rw-r--r--doc/classes/MultiplayerAPI.xml100
-rw-r--r--doc/classes/MultiplayerAPIExtension.xml141
-rw-r--r--doc/classes/MultiplayerPeer.xml11
-rw-r--r--doc/classes/MultiplayerPeerExtension.xml13
-rw-r--r--doc/classes/MultiplayerSpawner.xml67
-rw-r--r--doc/classes/MultiplayerSynchronizer.xml17
-rw-r--r--doc/classes/NavigationMesh.xml1
-rw-r--r--doc/classes/NavigationRegion2D.xml2
-rw-r--r--doc/classes/NavigationRegion3D.xml2
-rw-r--r--doc/classes/NavigationServer3D.xml5
-rw-r--r--doc/classes/Node.xml22
-rw-r--r--doc/classes/Node3D.xml7
-rw-r--r--doc/classes/NodePath.xml6
-rw-r--r--doc/classes/OS.xml51
-rw-r--r--doc/classes/Object.xml6
-rw-r--r--doc/classes/OccluderInstance3D.xml2
-rw-r--r--doc/classes/OptionButton.xml4
-rw-r--r--doc/classes/PackedByteArray.xml10
-rw-r--r--doc/classes/ParticlesMaterial.xml93
-rw-r--r--doc/classes/PhysicsRayQueryParameters2D.xml16
-rw-r--r--doc/classes/PhysicsRayQueryParameters3D.xml16
-rw-r--r--doc/classes/Plane.xml17
-rw-r--r--doc/classes/PopupMenu.xml24
-rw-r--r--doc/classes/ProjectSettings.xml96
-rw-r--r--doc/classes/Projection.xml273
-rw-r--r--doc/classes/Quaternion.xml20
-rw-r--r--doc/classes/RenderingDevice.xml8
-rw-r--r--doc/classes/RenderingServer.xml228
-rw-r--r--doc/classes/ResourceFormatLoader.xml6
-rw-r--r--doc/classes/ResourceFormatSaver.xml4
-rw-r--r--doc/classes/ResourceLoader.xml19
-rw-r--r--doc/classes/ResourceSaver.xml40
-rw-r--r--doc/classes/ResourceUID.xml19
-rw-r--r--doc/classes/RichTextLabel.xml9
-rw-r--r--doc/classes/RootMotionView.xml12
-rw-r--r--doc/classes/SceneTree.xml6
-rw-r--r--doc/classes/ScriptCreateDialog.xml1
-rw-r--r--doc/classes/ScriptExtension.xml4
-rw-r--r--doc/classes/ScriptLanguageExtension.xml9
-rw-r--r--doc/classes/Shader.xml2
-rw-r--r--doc/classes/ShaderInclude.xml13
-rw-r--r--doc/classes/ShaderMaterial.xml4
-rw-r--r--doc/classes/ShapeCast2D.xml18
-rw-r--r--doc/classes/ShapeCast3D.xml168
-rw-r--r--doc/classes/Skeleton3D.xml4
-rw-r--r--doc/classes/SkeletonProfile.xml193
-rw-r--r--doc/classes/SkeletonProfileHumanoid.xml16
-rw-r--r--doc/classes/SpinBox.xml3
-rw-r--r--doc/classes/SpriteBase3D.xml2
-rw-r--r--doc/classes/SpriteFrames.xml5
-rw-r--r--doc/classes/String.xml20
-rw-r--r--doc/classes/StyleBox.xml4
-rw-r--r--doc/classes/SystemFont.xml44
-rw-r--r--doc/classes/TabBar.xml24
-rw-r--r--doc/classes/TextEdit.xml26
-rw-r--r--doc/classes/TextLine.xml13
-rw-r--r--doc/classes/TextMesh.xml25
-rw-r--r--doc/classes/TextParagraph.xml35
-rw-r--r--doc/classes/TextServer.xml161
-rw-r--r--doc/classes/TextServerExtension.xml74
-rw-r--r--doc/classes/Theme.xml11
-rw-r--r--doc/classes/TileSet.xml39
-rw-r--r--doc/classes/TorusMesh.xml25
-rw-r--r--doc/classes/Transform2D.xml46
-rw-r--r--doc/classes/Transform3D.xml64
-rw-r--r--doc/classes/Tree.xml26
-rw-r--r--doc/classes/TreeItem.xml32
-rw-r--r--doc/classes/Vector4.xml377
-rw-r--r--doc/classes/Vector4i.xml214
-rw-r--r--doc/classes/VehicleBody3D.xml2
-rw-r--r--doc/classes/VehicleWheel3D.xml2
-rw-r--r--doc/classes/VideoStreamPlayer.xml2
-rw-r--r--doc/classes/Viewport.xml103
-rw-r--r--doc/classes/VisualShaderNodeTextureUniform.xml9
-rw-r--r--doc/classes/VisualShaderNodeVectorRefract.xml4
-rw-r--r--doc/classes/VoxelGI.xml1
-rw-r--r--doc/classes/VoxelGIData.xml6
-rw-r--r--doc/classes/WeakRef.xml2
-rw-r--r--doc/classes/WorkerThreadPool.xml59
-rw-r--r--doc/classes/XMLParser.xml2
-rw-r--r--doc/classes/XRCamera3D.xml2
-rw-r--r--doc/classes/XRController3D.xml2
-rw-r--r--doc/classes/XRInterface.xml2
-rw-r--r--doc/classes/XRInterfaceExtension.xml5
-rw-r--r--doc/classes/XROrigin3D.xml2
-rw-r--r--doc/classes/XRPositionalTracker.xml2
-rw-r--r--doc/classes/XRServer.xml2
-rw-r--r--doc/classes/float.xml12
-rw-r--r--doc/classes/int.xml12
-rwxr-xr-xdoc/tools/make_rst.py452
-rw-r--r--doc/translations/ar.po345
-rw-r--r--doc/translations/ca.po334
-rw-r--r--doc/translations/classes.pot334
-rw-r--r--doc/translations/cs.po343
-rw-r--r--doc/translations/de.po505
-rw-r--r--doc/translations/el.po335
-rw-r--r--doc/translations/es.po402
-rw-r--r--doc/translations/fa.po336
-rw-r--r--doc/translations/fi.po335
-rw-r--r--doc/translations/fil.po334
-rw-r--r--doc/translations/fr.po6274
-rw-r--r--doc/translations/gl.po334
-rw-r--r--doc/translations/hi.po334
-rw-r--r--doc/translations/hu.po334
-rw-r--r--doc/translations/id.po352
-rw-r--r--doc/translations/is.po334
-rw-r--r--doc/translations/it.po369
-rw-r--r--doc/translations/ja.po356
-rw-r--r--doc/translations/ko.po346
-rw-r--r--doc/translations/lt.po334
-rw-r--r--doc/translations/lv.po334
-rw-r--r--doc/translations/mr.po334
-rw-r--r--doc/translations/nb.po334
-rw-r--r--doc/translations/ne.po334
-rw-r--r--doc/translations/nl.po334
-rw-r--r--doc/translations/pl.po349
-rw-r--r--doc/translations/pt.po551
-rw-r--r--doc/translations/pt_BR.po360
-rw-r--r--doc/translations/ro.po334
-rw-r--r--doc/translations/ru.po487
-rw-r--r--doc/translations/sk.po334
-rw-r--r--doc/translations/sr_Cyrl.po334
-rw-r--r--doc/translations/sv.po345
-rw-r--r--doc/translations/th.po334
-rw-r--r--doc/translations/tl.po337
-rw-r--r--doc/translations/tr.po368
-rw-r--r--doc/translations/uk.po335
-rw-r--r--doc/translations/vi.po340
-rw-r--r--doc/translations/zh_CN.po2322
-rw-r--r--doc/translations/zh_TW.po335
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp20
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.h14
-rw-r--r--drivers/coremidi/midi_driver_coremidi.h7
-rw-r--r--drivers/gl_context/SCsub2
-rw-r--r--drivers/gles3/effects/copy_effects.cpp1
-rw-r--r--drivers/gles3/effects/copy_effects.h7
-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.h5
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp21
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h14
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp18
-rw-r--r--drivers/gles3/rasterizer_gles3.h15
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp721
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h251
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp569
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h266
-rw-r--r--drivers/gles3/shader_gles3.h11
-rw-r--r--drivers/gles3/shaders/SCsub2
-rw-r--r--drivers/gles3/shaders/canvas_uniforms_inc.glsl4
-rw-r--r--drivers/gles3/shaders/cubemap_filter.glsl88
-rw-r--r--drivers/gles3/shaders/scene.glsl21
-rw-r--r--drivers/gles3/shaders/sky.glsl4
-rw-r--r--drivers/gles3/storage/config.cpp7
-rw-r--r--drivers/gles3/storage/config.h2
-rw-r--r--drivers/gles3/storage/light_storage.cpp121
-rw-r--r--drivers/gles3/storage/light_storage.h29
-rw-r--r--drivers/gles3/storage/material_storage.cpp638
-rw-r--r--drivers/gles3/storage/material_storage.h112
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp51
-rw-r--r--drivers/gles3/storage/mesh_storage.h15
-rw-r--r--drivers/gles3/storage/particles_storage.h2
-rw-r--r--drivers/gles3/storage/texture_storage.cpp66
-rw-r--r--drivers/gles3/storage/texture_storage.h34
-rw-r--r--drivers/gles3/storage/utilities.cpp353
-rw-r--r--drivers/gles3/storage/utilities.h159
-rw-r--r--drivers/png/image_loader_png.h2
-rw-r--r--drivers/png/png_driver_common.h2
-rw-r--r--drivers/png/resource_saver_png.cpp2
-rw-r--r--drivers/png/resource_saver_png.h2
-rw-r--r--drivers/register_driver_types.h2
-rw-r--r--drivers/unix/dir_access_unix.cpp27
-rw-r--r--drivers/unix/dir_access_unix.h55
-rw-r--r--drivers/unix/file_access_unix.cpp6
-rw-r--r--drivers/unix/file_access_unix.h44
-rw-r--r--drivers/unix/ip_unix.cpp4
-rw-r--r--drivers/unix/ip_unix.h1
-rw-r--r--drivers/unix/net_socket_posix.h6
-rw-r--r--drivers/unix/os_unix.cpp9
-rw-r--r--drivers/unix/os_unix.h4
-rw-r--r--drivers/unix/syslog_logger.h4
-rw-r--r--drivers/unix/thread_posix.h2
-rw-r--r--drivers/vulkan/SCsub8
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp666
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h17
-rw-r--r--drivers/vulkan/vulkan_context.cpp301
-rw-r--r--drivers/vulkan/vulkan_context.h25
-rw-r--r--drivers/vulkan/vulkan_hooks.h2
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h1
-rw-r--r--drivers/windows/dir_access_windows.h38
-rw-r--r--drivers/windows/file_access_windows.h38
-rw-r--r--drivers/winmidi/midi_driver_winmidi.h7
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.h2
-rw-r--r--editor/SCsub3
-rw-r--r--editor/action_map_editor.cpp4
-rw-r--r--editor/action_map_editor.h2
-rw-r--r--editor/animation_bezier_editor.cpp8
-rw-r--r--editor/animation_track_editor.cpp168
-rw-r--r--editor/animation_track_editor.h12
-rw-r--r--editor/audio_stream_preview.cpp5
-rw-r--r--editor/audio_stream_preview.h2
-rw-r--r--editor/code_editor.cpp107
-rw-r--r--editor/code_editor.h3
-rw-r--r--editor/connections_dialog.cpp6
-rw-r--r--editor/connections_dialog.h2
-rw-r--r--editor/create_dialog.cpp11
-rw-r--r--editor/create_dialog.h2
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_parser.cpp1
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_parser.h2
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_protocol.cpp1
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_protocol.h2
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_server.cpp1
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_server.h2
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_types.h2
-rw-r--r--editor/debugger/editor_debugger_inspector.cpp44
-rw-r--r--editor/debugger/editor_debugger_inspector.h1
-rw-r--r--editor/debugger/editor_debugger_node.cpp20
-rw-r--r--editor/debugger/editor_debugger_node.h1
-rw-r--r--editor/debugger/editor_debugger_server.h6
-rw-r--r--editor/debugger/editor_debugger_tree.cpp35
-rw-r--r--editor/debugger/editor_debugger_tree.h3
-rw-r--r--editor/debugger/editor_network_profiler.h6
-rw-r--r--editor/debugger/editor_performance_profiler.cpp6
-rw-r--r--editor/debugger/editor_profiler.cpp2
-rw-r--r--editor/debugger/editor_profiler.h6
-rw-r--r--editor/debugger/editor_visual_profiler.cpp12
-rw-r--r--editor/debugger/editor_visual_profiler.h6
-rw-r--r--editor/debugger/script_editor_debugger.cpp21
-rw-r--r--editor/dependency_editor.cpp52
-rw-r--r--editor/dependency_editor.h1
-rw-r--r--editor/doc_tools.cpp135
-rw-r--r--editor/doc_tools.h2
-rw-r--r--editor/editor_about.h2
-rw-r--r--editor/editor_asset_installer.cpp7
-rw-r--r--editor/editor_asset_installer.h6
-rw-r--r--editor/editor_audio_buses.cpp19
-rw-r--r--editor/editor_autoload_settings.h2
-rw-r--r--editor/editor_build_profile.cpp899
-rw-r--r--editor/editor_build_profile.h191
-rw-r--r--editor/editor_command_palette.cpp9
-rw-r--r--editor/editor_command_palette.h2
-rw-r--r--editor/editor_data.cpp3
-rw-r--r--editor/editor_dir_dialog.cpp8
-rw-r--r--editor/editor_export.h532
-rw-r--r--editor/editor_feature_profile.cpp52
-rw-r--r--editor/editor_file_dialog.cpp44
-rw-r--r--editor/editor_file_dialog.h2
-rw-r--r--editor/editor_file_system.cpp24
-rw-r--r--editor/editor_file_system.h3
-rw-r--r--editor/editor_folding.cpp15
-rw-r--r--editor/editor_fonts.cpp543
-rw-r--r--editor/editor_fonts.h2
-rw-r--r--editor/editor_help.cpp197
-rw-r--r--editor/editor_help.h1
-rw-r--r--editor/editor_help_search.cpp5
-rw-r--r--editor/editor_inspector.cpp649
-rw-r--r--editor/editor_inspector.h37
-rw-r--r--editor/editor_locale_dialog.cpp2
-rw-r--r--editor/editor_log.cpp9
-rw-r--r--editor/editor_log.h2
-rw-r--r--editor/editor_node.cpp409
-rw-r--r--editor/editor_node.h14
-rw-r--r--editor/editor_path.cpp2
-rw-r--r--editor/editor_paths.cpp43
-rw-r--r--editor/editor_paths.h10
-rw-r--r--editor/editor_plugin.cpp5
-rw-r--r--editor/editor_plugin.h2
-rw-r--r--editor/editor_plugin_settings.cpp1
-rw-r--r--editor/editor_plugin_settings.h10
-rw-r--r--editor/editor_properties.cpp562
-rw-r--r--editor/editor_properties.h85
-rw-r--r--editor/editor_properties_array_dict.cpp37
-rw-r--r--editor/editor_properties_array_dict.h37
-rw-r--r--editor/editor_property_name_processor.cpp1
-rw-r--r--editor/editor_quick_open.cpp (renamed from editor/quick_open.cpp)6
-rw-r--r--editor/editor_quick_open.h (renamed from editor/quick_open.h)2
-rw-r--r--editor/editor_resource_picker.cpp341
-rw-r--r--editor/editor_resource_picker.h36
-rw-r--r--editor/editor_resource_preview.cpp10
-rw-r--r--editor/editor_resource_preview.h6
-rw-r--r--editor/editor_run.cpp2
-rw-r--r--editor/editor_run_native.cpp11
-rw-r--r--editor/editor_scale.h1
-rw-r--r--editor/editor_sectioned_inspector.h1
-rw-r--r--editor/editor_settings.cpp92
-rw-r--r--editor/editor_settings.h10
-rw-r--r--editor/editor_settings_dialog.cpp2
-rw-r--r--editor/editor_spin_slider.cpp11
-rw-r--r--editor/editor_themes.cpp101
-rw-r--r--editor/editor_themes.h2
-rw-r--r--editor/editor_toaster.cpp10
-rw-r--r--editor/editor_vcs_interface.h2
-rw-r--r--editor/export/SCsub5
-rw-r--r--editor/export/editor_export.cpp355
-rw-r--r--editor/export/editor_export.h84
-rw-r--r--editor/export/editor_export_platform.cpp (renamed from editor/editor_export.cpp)910
-rw-r--r--editor/export/editor_export_platform.h221
-rw-r--r--editor/export/editor_export_platform_pc.cpp242
-rw-r--r--editor/export/editor_export_platform_pc.h82
-rw-r--r--editor/export/editor_export_plugin.cpp201
-rw-r--r--editor/export/editor_export_plugin.h132
-rw-r--r--editor/export/editor_export_preset.cpp221
-rw-r--r--editor/export/editor_export_preset.h145
-rw-r--r--editor/export/editor_export_shared_object.h51
-rw-r--r--editor/export/export_template_manager.cpp (renamed from editor/export_template_manager.cpp)33
-rw-r--r--editor/export/export_template_manager.h (renamed from editor/export_template_manager.h)12
-rw-r--r--editor/export/project_export.cpp (renamed from editor/project_export.cpp)40
-rw-r--r--editor/export/project_export.h (renamed from editor/project_export.h)40
-rw-r--r--editor/filesystem_dock.cpp48
-rw-r--r--editor/filesystem_dock.h2
-rw-r--r--editor/find_in_files.cpp4
-rw-r--r--editor/groups_editor.cpp10
-rw-r--r--editor/groups_editor.h2
-rw-r--r--editor/icons/AudioStream.svg1
-rw-r--r--editor/icons/AudioStreamGenerator.svg1
-rw-r--r--editor/icons/AudioStreamMicrophone.svg1
-rw-r--r--editor/icons/AudioStreamOggVorbis.svg (renamed from editor/icons/AudioStreamOGGVorbis.svg)0
-rw-r--r--editor/icons/AudioStreamRandomizer.svg1
-rw-r--r--editor/icons/AudioStreamWAV.svg (renamed from editor/icons/AudioStreamSample.svg)0
-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/CodeFoldDownArrow.svg1
-rw-r--r--editor/icons/CodeFoldedRightArrow.svg1
-rw-r--r--editor/icons/ControlAlignFullRect.svg (renamed from editor/icons/ControlAlignWide.svg)0
-rw-r--r--editor/icons/CopyNodePath.svg2
-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/LabelSettings.svg1
-rw-r--r--editor/icons/MainMovieWriteEnabled.svg1
-rw-r--r--editor/icons/NodeWarnings2.svg1
-rw-r--r--editor/icons/NodeWarnings3.svg1
-rw-r--r--editor/icons/NodeWarnings4Plus.svg1
-rw-r--r--editor/icons/ShapeCast3D.svg1
-rw-r--r--editor/icons/SystemFont.svg1
-rw-r--r--editor/icons/TextEditorPlay.svg1
-rw-r--r--editor/icons/TorusMesh.svg1
-rw-r--r--editor/import/audio_stream_import_settings.cpp650
-rw-r--r--editor/import/audio_stream_import_settings.h (renamed from editor/plugins/audio_stream_editor_plugin.h)69
-rw-r--r--editor/import/dynamic_font_import_settings.cpp1019
-rw-r--r--editor/import/dynamic_font_import_settings.h90
-rw-r--r--editor/import/editor_import_collada.h2
-rw-r--r--editor/import/editor_import_plugin.h2
-rw-r--r--editor/import/post_import_plugin_skeleton_renamer.cpp190
-rw-r--r--editor/import/post_import_plugin_skeleton_renamer.h46
-rw-r--r--editor/import/post_import_plugin_skeleton_rest_fixer.cpp489
-rw-r--r--editor/import/post_import_plugin_skeleton_rest_fixer.h46
-rw-r--r--editor/import/post_import_plugin_skeleton_track_organizer.cpp127
-rw-r--r--editor/import/post_import_plugin_skeleton_track_organizer.h46
-rw-r--r--editor/import/resource_importer_bitmask.cpp2
-rw-r--r--editor/import/resource_importer_bitmask.h1
-rw-r--r--editor/import/resource_importer_bmfont.cpp14
-rw-r--r--editor/import/resource_importer_csv_translation.cpp2
-rw-r--r--editor/import/resource_importer_csv_translation.h6
-rw-r--r--editor/import/resource_importer_dynamic_font.cpp195
-rw-r--r--editor/import/resource_importer_dynamic_font.h3
-rw-r--r--editor/import/resource_importer_imagefont.cpp17
-rw-r--r--editor/import/resource_importer_imagefont.h6
-rw-r--r--editor/import/resource_importer_layered_texture.cpp8
-rw-r--r--editor/import/resource_importer_layered_texture.h2
-rw-r--r--editor/import/resource_importer_obj.cpp2
-rw-r--r--editor/import/resource_importer_obj.h6
-rw-r--r--editor/import/resource_importer_scene.cpp345
-rw-r--r--editor/import/resource_importer_scene.h12
-rw-r--r--editor/import/resource_importer_shader_file.cpp2
-rw-r--r--editor/import/resource_importer_texture.cpp2
-rw-r--r--editor/import/resource_importer_texture.h6
-rw-r--r--editor/import/resource_importer_texture_atlas.cpp22
-rw-r--r--editor/import/resource_importer_wav.cpp92
-rw-r--r--editor/import/scene_import_settings.cpp65
-rw-r--r--editor/import/scene_import_settings.h1
-rw-r--r--editor/import_defaults_editor.cpp1
-rw-r--r--editor/import_dock.cpp3
-rw-r--r--editor/import_dock.h6
-rw-r--r--editor/inspector_dock.cpp44
-rw-r--r--editor/inspector_dock.h8
-rw-r--r--editor/localization_editor.cpp103
-rw-r--r--editor/localization_editor.h5
-rw-r--r--editor/plugin_config_dialog.cpp6
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp14
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp37
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.h4
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp57
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.h3
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp21
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.h1
-rw-r--r--editor/plugins/animation_library_editor.h2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp24
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp19
-rw-r--r--editor/plugins/animation_state_machine_editor.h1
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp4
-rw-r--r--editor/plugins/animation_tree_editor_plugin.h1
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp76
-rw-r--r--editor/plugins/asset_library_editor_plugin.h7
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp285
-rw-r--r--editor/plugins/bit_map_editor_plugin.cpp6
-rw-r--r--editor/plugins/bit_map_editor_plugin.h6
-rw-r--r--editor/plugins/bone_map_editor_plugin.cpp499
-rw-r--r--editor/plugins/bone_map_editor_plugin.h180
-rw-r--r--editor/plugins/camera_3d_editor_plugin.h6
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp303
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h17
-rw-r--r--editor/plugins/cast_2d_editor_plugin.cpp (renamed from editor/plugins/ray_cast_2d_editor_plugin.cpp)56
-rw-r--r--editor/plugins/cast_2d_editor_plugin.h (renamed from editor/plugins/ray_cast_2d_editor_plugin.h)34
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h2
-rw-r--r--editor/plugins/control_editor_plugin.cpp38
-rw-r--r--editor/plugins/control_editor_plugin.h8
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/cpu_particles_3d_editor_plugin.h6
-rw-r--r--editor/plugins/curve_editor_plugin.cpp16
-rw-r--r--editor/plugins/debugger_editor_plugin.cpp1
-rw-r--r--editor/plugins/editor_preview_plugins.cpp83
-rw-r--r--editor/plugins/editor_preview_plugins.h7
-rw-r--r--editor/plugins/editor_resource_conversion_plugin.cpp64
-rw-r--r--editor/plugins/editor_resource_conversion_plugin.h54
-rw-r--r--editor/plugins/font_config_plugin.cpp1057
-rw-r--r--editor/plugins/font_config_plugin.h288
-rw-r--r--editor/plugins/font_editor_plugin.cpp106
-rw-r--r--editor/plugins/gdextension_export_plugin.h2
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp19
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.h6
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp14
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.h6
-rw-r--r--editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp2
-rw-r--r--editor/plugins/gradient_editor_plugin.cpp2
-rw-r--r--editor/plugins/gradient_texture_2d_editor_plugin.cpp10
-rw-r--r--editor/plugins/gradient_texture_2d_editor_plugin.h6
-rw-r--r--editor/plugins/lightmap_gi_editor_plugin.cpp2
-rw-r--r--editor/plugins/lightmap_gi_editor_plugin.h6
-rw-r--r--editor/plugins/material_editor_plugin.cpp59
-rw-r--r--editor/plugins/material_editor_plugin.h2
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp6
-rw-r--r--editor/plugins/mesh_editor_plugin.h2
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.h6
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp8
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp6
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.h6
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp269
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h12
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp452
-rw-r--r--editor/plugins/node_3d_editor_plugin.h34
-rw-r--r--editor/plugins/occluder_instance_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/occluder_instance_3d_editor_plugin.h2
-rw-r--r--editor/plugins/ot_features_plugin.cpp235
-rw-r--r--editor/plugins/ot_features_plugin.h102
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp10
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp7
-rw-r--r--editor/plugins/path_3d_editor_plugin.h6
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.h6
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp14
-rw-r--r--editor/plugins/polygon_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp4
-rw-r--r--editor/plugins/script_editor_plugin.cpp56
-rw-r--r--editor/plugins/script_text_editor.cpp25
-rw-r--r--editor/plugins/shader_editor_plugin.cpp583
-rw-r--r--editor/plugins/shader_editor_plugin.h45
-rw-r--r--editor/plugins/shader_file_editor_plugin.cpp3
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp92
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.h3
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp8
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.h6
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp54
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h3
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp2
-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/text_editor.cpp5
-rw-r--r--editor/plugins/texture_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/texture_3d_editor_plugin.h2
-rw-r--r--editor/plugins/texture_editor_plugin.cpp54
-rw-r--r--editor/plugins/texture_layered_editor_plugin.cpp14
-rw-r--r--editor/plugins/texture_layered_editor_plugin.h2
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp8
-rw-r--r--editor/plugins/theme_editor_plugin.cpp120
-rw-r--r--editor/plugins/theme_editor_plugin.h1
-rw-r--r--editor/plugins/theme_editor_preview.cpp5
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp8
-rw-r--r--editor/plugins/tiles/tile_atlas_view.cpp12
-rw-r--r--editor/plugins/tiles/tile_atlas_view.h2
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp21
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp4
-rw-r--r--editor/plugins/tiles/tile_map_editor.h2
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.cpp6
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp35
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp4
-rw-r--r--editor/plugins/tiles/tile_set_editor.h2
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.h2
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp31
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.h3
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp2
-rw-r--r--editor/plugins/version_control_editor_plugin.h2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp304
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h61
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.cpp2
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.h6
-rw-r--r--editor/progress_dialog.cpp4
-rw-r--r--editor/project_converter_3_to_4.cpp1843
-rw-r--r--editor/project_converter_3_to_4.h16
-rw-r--r--editor/project_manager.cpp326
-rw-r--r--editor/project_manager.h2
-rw-r--r--editor/project_settings_editor.cpp36
-rw-r--r--editor/project_settings_editor.h7
-rw-r--r--editor/property_editor.cpp1911
-rw-r--r--editor/property_editor.h184
-rw-r--r--editor/property_selector.cpp6
-rw-r--r--editor/property_selector.h14
-rw-r--r--editor/register_exporters.h2
-rw-r--r--editor/rename_dialog.cpp21
-rw-r--r--editor/reparent_dialog.cpp2
-rw-r--r--editor/scene_create_dialog.cpp4
-rw-r--r--editor/scene_tree_dock.cpp95
-rw-r--r--editor/scene_tree_dock.h2
-rw-r--r--editor/scene_tree_editor.cpp36
-rw-r--r--editor/scene_tree_editor.h3
-rw-r--r--editor/script_create_dialog.cpp19
-rw-r--r--editor/shader_create_dialog.cpp239
-rw-r--r--editor/shader_create_dialog.h13
-rw-r--r--editor/shader_globals_editor.cpp46
-rw-r--r--editor/translations/af.po177
-rw-r--r--editor/translations/ar.po563
-rw-r--r--editor/translations/az.po281
-rw-r--r--editor/translations/bg.po180
-rw-r--r--editor/translations/bn.po180
-rw-r--r--editor/translations/br.po165
-rw-r--r--editor/translations/ca.po322
-rw-r--r--editor/translations/cs.po184
-rw-r--r--editor/translations/da.po181
-rw-r--r--editor/translations/de.po223
-rw-r--r--editor/translations/editor.pot150
-rw-r--r--editor/translations/el.po184
-rw-r--r--editor/translations/en_Shaw.po165
-rw-r--r--editor/translations/eo.po177
-rw-r--r--editor/translations/es.po3141
-rw-r--r--editor/translations/es_AR.po272
-rw-r--r--editor/translations/et.po178
-rw-r--r--editor/translations/eu.po174
-rw-r--r--editor/translations/fa.po178
-rw-r--r--editor/translations/fi.po189
-rw-r--r--editor/translations/fil.po164
-rw-r--r--editor/translations/fr.po4243
-rw-r--r--editor/translations/ga.po167
-rw-r--r--editor/translations/gl.po182
-rw-r--r--editor/translations/he.po183
-rw-r--r--editor/translations/hi.po177
-rw-r--r--editor/translations/hr.po245
-rw-r--r--editor/translations/hu.po178
-rw-r--r--editor/translations/id.po251
-rw-r--r--editor/translations/is.po167
-rw-r--r--editor/translations/it.po316
-rw-r--r--editor/translations/ja.po186
-rw-r--r--editor/translations/ka.po177
-rw-r--r--editor/translations/km.po156
-rw-r--r--editor/translations/ko.po182
-rw-r--r--editor/translations/lt.po177
-rw-r--r--editor/translations/lv.po174
-rw-r--r--editor/translations/mk.po192
-rw-r--r--editor/translations/ml.po156
-rw-r--r--editor/translations/mr.po165
-rw-r--r--editor/translations/ms.po177
-rw-r--r--editor/translations/nb.po174
-rw-r--r--editor/translations/nl.po184
-rw-r--r--editor/translations/pl.po298
-rw-r--r--editor/translations/pr.po174
-rw-r--r--editor/translations/pt.po214
-rw-r--r--editor/translations/pt_BR.po2124
-rw-r--r--editor/translations/ro.po177
-rw-r--r--editor/translations/ru.po458
-rw-r--r--editor/translations/si.po165
-rw-r--r--editor/translations/sk.po177
-rw-r--r--editor/translations/sl.po177
-rw-r--r--editor/translations/sq.po177
-rw-r--r--editor/translations/sr_Cyrl.po185
-rw-r--r--editor/translations/sr_Latn.po169
-rw-r--r--editor/translations/sv.po572
-rw-r--r--editor/translations/te.po158
-rw-r--r--editor/translations/th.po183
-rw-r--r--editor/translations/tl.po175
-rw-r--r--editor/translations/tr.po570
-rw-r--r--editor/translations/uk.po284
-rw-r--r--editor/translations/ur_PK.po171
-rw-r--r--editor/translations/vi.po174
-rw-r--r--editor/translations/zh_CN.po221
-rw-r--r--editor/translations/zh_HK.po178
-rw-r--r--editor/translations/zh_TW.po2664
-rw-r--r--gles3_builders.py2
-rw-r--r--main/main.cpp148
-rw-r--r--main/performance.cpp2
-rw-r--r--methods.py82
-rw-r--r--misc/dist/ios_xcode/libgodot.ios.debug.xcframework/Info.plist (renamed from misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/Info.plist)0
-rw-r--r--misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64/empty (renamed from misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64/empty)0
-rw-r--r--misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/empty (renamed from misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64_x86_64-simulator/empty)0
-rw-r--r--misc/dist/ios_xcode/libgodot.ios.release.xcframework/Info.plist (renamed from misc/dist/ios_xcode/libgodot.iphone.release.xcframework/Info.plist)0
-rw-r--r--misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64/empty (renamed from misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64/empty)0
-rw-r--r--misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64_x86_64-simulator/empty (renamed from misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64_x86_64-simulator/empty)0
-rw-r--r--misc/dist/macos/editor.entitlements (renamed from misc/dist/osx/editor.entitlements)0
-rw-r--r--misc/dist/macos_template.app/Contents/Info.plist (renamed from misc/dist/osx_template.app/Contents/Info.plist)0
-rw-r--r--misc/dist/macos_template.app/Contents/PkgInfo (renamed from misc/dist/osx_template.app/Contents/PkgInfo)0
-rw-r--r--misc/dist/macos_template.app/Contents/Resources/icon.icns (renamed from misc/dist/osx_template.app/Contents/Resources/icon.icns)bin67500 -> 67500 bytes
-rw-r--r--misc/dist/macos_tools.app/Contents/Info.plist (renamed from misc/dist/osx_tools.app/Contents/Info.plist)0
-rw-r--r--misc/dist/macos_tools.app/Contents/PkgInfo (renamed from misc/dist/osx_tools.app/Contents/PkgInfo)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/GDScript.icns (renamed from misc/dist/osx_tools.app/Contents/Resources/GDScript.icns)bin185973 -> 185973 bytes
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/Godot.icns (renamed from misc/dist/osx_tools.app/Contents/Resources/Godot.icns)bin271163 -> 271163 bytes
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/Project.icns (renamed from misc/dist/osx_tools.app/Contents/Resources/Project.icns)bin208221 -> 208221 bytes
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/Resource.icns (renamed from misc/dist/osx_tools.app/Contents/Resources/Resource.icns)bin176973 -> 176973 bytes
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/Scene.icns (renamed from misc/dist/osx_tools.app/Contents/Resources/Scene.icns)bin150612 -> 150612 bytes
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/Shader.icns (renamed from misc/dist/osx_tools.app/Contents/Resources/Shader.icns)bin162062 -> 162062 bytes
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/af.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/af.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/az.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/az.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/br.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/br.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/da.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/da.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/de.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/de.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/el.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/el.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/en.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/en.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/es.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/es.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/et.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/et.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/he.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/he.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/id.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/id.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/is.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/is.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/it.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/it.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/km.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/km.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/or.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/or.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/si.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/si.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/te.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/te.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/th.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/th.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/macos_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings (renamed from misc/dist/osx_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings)0
-rw-r--r--misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json7
-rw-r--r--misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json7
-rwxr-xr-xmisc/scripts/file_format.sh2
-rwxr-xr-xmisc/scripts/header_guards.sh61
-rwxr-xr-xmisc/scripts/install_vulkan_sdk_macos.sh14
-rw-r--r--modules/bmp/SCsub2
-rw-r--r--modules/camera/SCsub4
-rw-r--r--modules/camera/camera_macos.h (renamed from modules/camera/camera_osx.h)12
-rw-r--r--modules/camera/camera_macos.mm (renamed from modules/camera/camera_osx.mm)36
-rw-r--r--modules/camera/camera_win.h6
-rw-r--r--modules/camera/config.py2
-rw-r--r--modules/camera/register_types.cpp8
-rw-r--r--modules/csg/SCsub3
-rw-r--r--modules/csg/csg.cpp2
-rw-r--r--modules/csg/csg_shape.cpp6
-rw-r--r--modules/cvtt/image_compress_cvtt.cpp38
-rw-r--r--modules/dds/texture_loader_dds.cpp4
-rw-r--r--modules/denoise/config.py2
-rw-r--r--modules/enet/enet_multiplayer_peer.cpp6
-rw-r--r--modules/enet/enet_multiplayer_peer.h8
-rw-r--r--modules/freetype/SCsub33
-rw-r--r--modules/freetype/config.py8
-rw-r--r--modules/freetype/uwpdef.h5
-rw-r--r--modules/gdscript/config.py1
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml159
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp52
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.h4
-rw-r--r--modules/gdscript/gdscript.cpp97
-rw-r--r--modules/gdscript/gdscript.h9
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp71
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp16
-rw-r--r--modules/gdscript/gdscript_byte_codegen.h8
-rw-r--r--modules/gdscript/gdscript_cache.cpp2
-rw-r--r--modules/gdscript/gdscript_codegen.h9
-rw-r--r--modules/gdscript/gdscript_compiler.cpp23
-rw-r--r--modules/gdscript/gdscript_disassembler.cpp6
-rw-r--r--modules/gdscript/gdscript_editor.cpp60
-rw-r--r--modules/gdscript/gdscript_function.h10
-rw-r--r--modules/gdscript/gdscript_lambda_callable.h6
-rw-r--r--modules/gdscript/gdscript_parser.cpp386
-rw-r--r--modules/gdscript/gdscript_parser.h45
-rw-r--r--modules/gdscript/gdscript_rpc_callable.cpp6
-rw-r--r--modules/gdscript/gdscript_rpc_callable.h8
-rw-r--r--modules/gdscript/gdscript_tokenizer.h2
-rw-r--r--modules/gdscript/gdscript_utility_functions.cpp1
-rw-r--r--modules/gdscript/gdscript_vm.cpp27
-rw-r--r--modules/gdscript/gdscript_warning.h6
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp8
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.h4
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp1
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.h2
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp1
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.h4
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp5
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.h4
-rw-r--r--modules/gdscript/language_server/godot_lsp.h (renamed from modules/gdscript/language_server/lsp.hpp)4
-rw-r--r--modules/gdscript/register_types.cpp2
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp5
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.h6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.out2
-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/glslang/register_types.cpp34
-rw-r--r--modules/gltf/README.md11
-rw-r--r--modules/gltf/SCsub4
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp8
-rw-r--r--modules/gltf/extensions/gltf_light.cpp (renamed from modules/gltf/gltf_light.cpp)0
-rw-r--r--modules/gltf/extensions/gltf_light.h (renamed from modules/gltf/gltf_light.h)1
-rw-r--r--modules/gltf/extensions/gltf_spec_gloss.cpp (renamed from modules/gltf/gltf_spec_gloss.cpp)0
-rw-r--r--modules/gltf/extensions/gltf_spec_gloss.h (renamed from modules/gltf/gltf_spec_gloss.h)1
-rw-r--r--modules/gltf/gltf_defines.h87
-rw-r--r--modules/gltf/gltf_document.cpp207
-rw-r--r--modules/gltf/gltf_document.h96
-rw-r--r--modules/gltf/gltf_document_extension.h3
-rw-r--r--modules/gltf/gltf_document_extension_convert_importer_mesh.h9
-rw-r--r--modules/gltf/gltf_state.cpp68
-rw-r--r--modules/gltf/gltf_state.h25
-rw-r--r--modules/gltf/gltf_template_convert.h94
-rw-r--r--modules/gltf/register_types.cpp22
-rw-r--r--modules/gltf/structures/gltf_accessor.cpp (renamed from modules/gltf/gltf_accessor.cpp)6
-rw-r--r--modules/gltf/structures/gltf_accessor.h (renamed from modules/gltf/gltf_accessor.h)5
-rw-r--r--modules/gltf/structures/gltf_animation.cpp (renamed from modules/gltf/gltf_animation.cpp)0
-rw-r--r--modules/gltf/structures/gltf_animation.h (renamed from modules/gltf/gltf_animation.h)1
-rw-r--r--modules/gltf/structures/gltf_buffer_view.cpp (renamed from modules/gltf/gltf_buffer_view.cpp)2
-rw-r--r--modules/gltf/structures/gltf_buffer_view.h (renamed from modules/gltf/gltf_buffer_view.h)3
-rw-r--r--modules/gltf/structures/gltf_camera.cpp (renamed from modules/gltf/gltf_camera.cpp)0
-rw-r--r--modules/gltf/structures/gltf_camera.h (renamed from modules/gltf/gltf_camera.h)1
-rw-r--r--modules/gltf/structures/gltf_mesh.cpp (renamed from modules/gltf/gltf_mesh.cpp)0
-rw-r--r--modules/gltf/structures/gltf_mesh.h (renamed from modules/gltf/gltf_mesh.h)0
-rw-r--r--modules/gltf/structures/gltf_node.cpp (renamed from modules/gltf/gltf_node.cpp)0
-rw-r--r--modules/gltf/structures/gltf_node.h (renamed from modules/gltf/gltf_node.h)3
-rw-r--r--modules/gltf/structures/gltf_skeleton.cpp (renamed from modules/gltf/gltf_skeleton.cpp)11
-rw-r--r--modules/gltf/structures/gltf_skeleton.h (renamed from modules/gltf/gltf_skeleton.h)3
-rw-r--r--modules/gltf/structures/gltf_skin.cpp (renamed from modules/gltf/gltf_skin.cpp)11
-rw-r--r--modules/gltf/structures/gltf_skin.h (renamed from modules/gltf/gltf_skin.h)3
-rw-r--r--modules/gltf/structures/gltf_texture.cpp (renamed from modules/gltf/gltf_texture.cpp)0
-rw-r--r--modules/gltf/structures/gltf_texture.h (renamed from modules/gltf/gltf_texture.h)2
-rw-r--r--modules/gridmap/SCsub2
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.cpp10
-rw-r--r--modules/hdr/SCsub2
-rw-r--r--modules/hdr/image_loader_hdr.h2
-rw-r--r--modules/jpg/image_loader_jpegd.h6
-rw-r--r--modules/jsonrpc/jsonrpc.h6
-rw-r--r--modules/lightmapper_rd/SCsub4
-rw-r--r--modules/lightmapper_rd/lightmapper_rd.cpp6
-rw-r--r--modules/lightmapper_rd/lightmapper_rd.h4
-rw-r--r--modules/lightmapper_rd/register_types.h2
-rw-r--r--modules/mbedtls/dtls_server_mbedtls.h6
-rw-r--r--modules/mbedtls/ssl_context_mbedtls.h6
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.h6
-rw-r--r--modules/meshoptimizer/register_types.h2
-rw-r--r--modules/minimp3/SCsub2
-rw-r--r--modules/minimp3/audio_stream_mp3.cpp71
-rw-r--r--modules/minimp3/audio_stream_mp3.h25
-rw-r--r--modules/minimp3/doc_classes/AudioStreamMP3.xml31
-rw-r--r--modules/minimp3/resource_importer_mp3.cpp48
-rw-r--r--modules/minimp3/resource_importer_mp3.h6
-rw-r--r--modules/mobile_vr/mobile_vr_interface.cpp6
-rw-r--r--modules/mobile_vr/mobile_vr_interface.h2
-rw-r--r--modules/mono/SCsub2
-rw-r--r--modules/mono/build_scripts/make_android_mono_config.py2
-rw-r--r--modules/mono/build_scripts/mono_configure.py16
-rw-r--r--modules/mono/config.py54
-rw-r--r--modules/mono/csharp_script.cpp102
-rw-r--r--modules/mono/csharp_script.h11
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs10
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs10
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs10
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs4
-rw-r--r--modules/mono/editor/bindings_generator.cpp38
-rw-r--r--modules/mono/editor/bindings_generator.h4
-rw-r--r--modules/mono/editor/code_completion.cpp2
-rw-r--r--modules/mono/editor/editor_internal_calls.cpp18
-rw-r--r--modules/mono/editor/editor_internal_calls.h6
-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/Basis.cs26
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GD.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/Plane.cs8
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs820
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs63
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs68
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs36
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs50
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs730
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs702
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj5
-rw-r--r--modules/mono/glue/callable_glue.cpp4
-rw-r--r--modules/mono/glue/glue_header.h5
-rw-r--r--modules/mono/glue/nodepath_glue.cpp5
-rw-r--r--modules/mono/godotsharp_dirs.cpp4
-rw-r--r--modules/mono/mono_gc_handle.h6
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp8
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp20
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h10
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp30
-rw-r--r--modules/mono/mono_gd/gd_mono_field.h6
-rw-r--r--modules/mono/mono_gd/gd_mono_log.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp23
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h71
-rw-r--r--modules/mono/mono_gd/gd_mono_method_thunk.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h6
-rw-r--r--modules/mono/mono_gd/support/ios_support.h4
-rw-r--r--modules/mono/mono_gd/support/ios_support.mm4
-rw-r--r--modules/mono/signal_awaiter_utils.cpp2
-rw-r--r--modules/mono/utils/macos_utils.cpp (renamed from modules/mono/utils/osx_utils.cpp)8
-rw-r--r--modules/mono/utils/macos_utils.h (renamed from modules/mono/utils/osx_utils.h)12
-rw-r--r--modules/mono/utils/macros.h6
-rw-r--r--modules/mono/utils/path_utils.cpp12
-rw-r--r--modules/mono/utils/path_utils.h6
-rw-r--r--modules/mono/utils/string_utils.cpp2
-rw-r--r--modules/mono/utils/string_utils.h6
-rw-r--r--modules/msdfgen/SCsub2
-rw-r--r--modules/msdfgen/config.py3
-rw-r--r--modules/multiplayer/SCsub14
-rw-r--r--modules/multiplayer/config.py19
-rw-r--r--modules/multiplayer/doc_classes/MultiplayerSpawner.xml84
-rw-r--r--modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml93
-rw-r--r--modules/multiplayer/doc_classes/SceneMultiplayer.xml55
-rw-r--r--modules/multiplayer/doc_classes/SceneReplicationConfig.xml (renamed from doc/classes/SceneReplicationConfig.xml)12
-rw-r--r--modules/multiplayer/editor/replication_editor_plugin.cpp (renamed from editor/plugins/replication_editor_plugin.cpp)125
-rw-r--r--modules/multiplayer/editor/replication_editor_plugin.h (renamed from editor/plugins/replication_editor_plugin.h)12
-rw-r--r--modules/multiplayer/multiplayer_spawner.cpp (renamed from scene/multiplayer/multiplayer_spawner.cpp)42
-rw-r--r--modules/multiplayer/multiplayer_spawner.h (renamed from scene/multiplayer/multiplayer_spawner.h)12
-rw-r--r--modules/multiplayer/multiplayer_synchronizer.cpp (renamed from scene/multiplayer/multiplayer_synchronizer.cpp)152
-rw-r--r--modules/multiplayer/multiplayer_synchronizer.h (renamed from scene/multiplayer/multiplayer_synchronizer.h)28
-rw-r--r--modules/multiplayer/register_types.cpp60
-rw-r--r--modules/multiplayer/register_types.h39
-rw-r--r--modules/multiplayer/scene_cache_interface.cpp (renamed from scene/multiplayer/scene_cache_interface.cpp)44
-rw-r--r--modules/multiplayer/scene_cache_interface.h (renamed from scene/multiplayer/scene_cache_interface.h)30
-rw-r--r--modules/multiplayer/scene_multiplayer.cpp332
-rw-r--r--modules/multiplayer/scene_multiplayer.h136
-rw-r--r--modules/multiplayer/scene_replication_config.cpp (renamed from scene/resources/scene_replication_config.cpp)2
-rw-r--r--modules/multiplayer/scene_replication_config.h (renamed from scene/resources/scene_replication_config.h)0
-rw-r--r--modules/multiplayer/scene_replication_interface.cpp (renamed from scene/multiplayer/scene_replication_interface.cpp)245
-rw-r--r--modules/multiplayer/scene_replication_interface.h (renamed from scene/multiplayer/scene_replication_interface.h)50
-rw-r--r--modules/multiplayer/scene_replication_state.cpp (renamed from scene/multiplayer/scene_replication_state.cpp)91
-rw-r--r--modules/multiplayer/scene_replication_state.h (renamed from scene/multiplayer/scene_replication_state.h)32
-rw-r--r--modules/multiplayer/scene_rpc_interface.cpp (renamed from scene/multiplayer/scene_rpc_interface.cpp)162
-rw-r--r--modules/multiplayer/scene_rpc_interface.h (renamed from scene/multiplayer/scene_rpc_interface.h)73
-rw-r--r--modules/navigation/godot_navigation_server.cpp20
-rw-r--r--modules/navigation/godot_navigation_server.h2
-rw-r--r--modules/navigation/nav_map.cpp85
-rw-r--r--modules/navigation/nav_map.h19
-rw-r--r--modules/navigation/nav_region.h4
-rw-r--r--modules/navigation/nav_utils.h8
-rw-r--r--modules/noise/editor/noise_editor_plugin.cpp2
-rw-r--r--modules/ogg/config.py4
-rw-r--r--modules/ogg/doc_classes/OggPacketSequence.xml (renamed from modules/ogg/doc_classes/OGGPacketSequence.xml)8
-rw-r--r--modules/ogg/doc_classes/OggPacketSequencePlayback.xml (renamed from modules/ogg/doc_classes/OGGPacketSequencePlayback.xml)2
-rw-r--r--modules/ogg/ogg_packet_sequence.cpp50
-rw-r--r--modules/ogg/ogg_packet_sequence.h28
-rw-r--r--modules/ogg/register_types.cpp4
-rw-r--r--modules/openxr/SCsub6
-rw-r--r--modules/openxr/action_map/openxr_action.h2
-rw-r--r--modules/openxr/action_map/openxr_action_map.h6
-rw-r--r--modules/openxr/action_map/openxr_action_set.h2
-rw-r--r--modules/openxr/action_map/openxr_defs.h2
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile.cpp2
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile.h2
-rw-r--r--modules/openxr/doc_classes/OpenXRIPBinding.xml2
-rw-r--r--modules/openxr/doc_classes/OpenXRInterface.xml4
-rw-r--r--modules/openxr/editor/openxr_action_editor.h2
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.cpp2
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.h2
-rw-r--r--modules/openxr/editor/openxr_action_set_editor.h2
-rw-r--r--modules/openxr/editor/openxr_editor_plugin.h2
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.cpp9
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.h2
-rw-r--r--modules/openxr/editor/openxr_select_action_dialog.cpp4
-rw-r--r--modules/openxr/editor/openxr_select_action_dialog.h2
-rw-r--r--modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp4
-rw-r--r--modules/openxr/editor/openxr_select_interaction_profile_dialog.h2
-rw-r--r--modules/openxr/extensions/openxr_android_extension.h2
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper.h6
-rw-r--r--modules/openxr/extensions/openxr_htc_vive_tracker_extension.h2
-rw-r--r--modules/openxr/extensions/openxr_vulkan_extension.cpp4
-rw-r--r--modules/openxr/extensions/openxr_vulkan_extension.h4
-rw-r--r--modules/openxr/openxr_api.cpp17
-rw-r--r--modules/openxr/openxr_api.h10
-rw-r--r--modules/openxr/openxr_interface.cpp6
-rw-r--r--modules/openxr/openxr_interface.h4
-rw-r--r--modules/openxr/openxr_util.h2
-rw-r--r--modules/raycast/lightmap_raycaster.h2
-rw-r--r--modules/raycast/raycast_occlusion_cull.cpp45
-rw-r--r--modules/raycast/raycast_occlusion_cull.h19
-rw-r--r--modules/raycast/static_raycaster.h2
-rw-r--r--modules/regex/doc_classes/RegEx.xml9
-rw-r--r--modules/regex/regex.cpp17
-rw-r--r--modules/regex/regex.h5
-rw-r--r--modules/regex/tests/test_regex.h10
-rw-r--r--modules/svg/image_loader_svg.cpp4
-rw-r--r--modules/text_server_adv/SCsub69
-rw-r--r--modules/text_server_adv/config.py8
-rw-r--r--modules/text_server_adv/gdextension_build/SConstruct34
-rw-r--r--modules/text_server_adv/gdextension_build/methods.py2
-rw-r--r--modules/text_server_adv/gdextension_build/text_server_adv.gdextension4
-rw-r--r--modules/text_server_adv/script_iterator.h2
-rw-r--r--modules/text_server_adv/text_server_adv.cpp1285
-rw-r--r--modules/text_server_adv/text_server_adv.h88
-rw-r--r--modules/text_server_fb/SCsub9
-rw-r--r--modules/text_server_fb/gdextension_build/SConstruct10
-rw-r--r--modules/text_server_fb/gdextension_build/methods.py2
-rw-r--r--modules/text_server_fb/gdextension_build/text_server_fb.gdextension4
-rw-r--r--modules/text_server_fb/text_server_fb.cpp381
-rw-r--r--modules/text_server_fb/text_server_fb.h65
-rw-r--r--modules/tga/SCsub2
-rw-r--r--modules/theora/config.py3
-rw-r--r--modules/theora/video_stream_theora.cpp2
-rw-r--r--modules/theora/video_stream_theora.h4
-rw-r--r--modules/tinyexr/image_loader_tinyexr.h2
-rw-r--r--modules/upnp/upnp.h6
-rw-r--r--modules/upnp/upnp_device.h6
-rw-r--r--modules/visual_script/editor/visual_script_editor.cpp142
-rw-r--r--modules/visual_script/editor/visual_script_editor.h32
-rw-r--r--modules/visual_script/editor/visual_script_property_selector.cpp3
-rw-r--r--modules/visual_script/editor/visual_script_property_selector.h8
-rw-r--r--modules/visual_script/visual_script.cpp44
-rw-r--r--modules/visual_script/visual_script.h7
-rw-r--r--modules/visual_script/visual_script_expression.h6
-rw-r--r--modules/visual_script/visual_script_nodes.cpp13
-rw-r--r--modules/visual_script/visual_script_nodes.h7
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp198
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.h66
-rw-r--r--modules/vorbis/config.py7
-rw-r--r--modules/vorbis/doc_classes/AudioStreamOggVorbis.xml (renamed from modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml)12
-rw-r--r--modules/vorbis/doc_classes/AudioStreamPlaybackOggVorbis.xml (renamed from modules/vorbis/doc_classes/AudioStreamPlaybackOGGVorbis.xml)2
-rw-r--r--modules/vorbis/register_types.cpp6
-rw-r--r--modules/vorbis/resource_importer_ogg_vorbis.cpp98
-rw-r--r--modules/vorbis/resource_importer_ogg_vorbis.h13
-rw-r--r--modules/webp/image_loader_webp.h2
-rw-r--r--modules/webp/resource_saver_webp.cpp2
-rw-r--r--modules/webp/resource_saver_webp.h2
-rw-r--r--modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml2
-rw-r--r--modules/webrtc/webrtc_data_channel.h1
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.cpp12
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.h8
-rw-r--r--modules/webrtc/webrtc_peer_connection.h1
-rw-r--r--modules/webrtc/webrtc_peer_connection_js.cpp2
-rw-r--r--modules/webrtc/webrtc_peer_connection_js.h2
-rw-r--r--modules/websocket/emws_client.h6
-rw-r--r--modules/websocket/emws_peer.h6
-rw-r--r--modules/websocket/emws_server.h64
-rw-r--r--modules/websocket/register_types.cpp5
-rw-r--r--modules/websocket/websocket_multiplayer_peer.h2
-rw-r--r--modules/websocket/websocket_peer.h7
-rw-r--r--modules/websocket/websocket_server.h6
-rw-r--r--modules/websocket/wsl_client.h6
-rw-r--r--modules/websocket/wsl_peer.h6
-rw-r--r--modules/websocket/wsl_server.h6
-rw-r--r--modules/webxr/godot_webxr.h2
-rw-r--r--modules/webxr/webxr_interface_js.cpp4
-rw-r--r--modules/webxr/webxr_interface_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/display_server_android.cpp10
-rw-r--r--platform/android/display_server_android.h2
-rw-r--r--platform/android/export/export.cpp4
-rw-r--r--platform/android/export/export_plugin.cpp130
-rw-r--r--platform/android/export/export_plugin.h10
-rw-r--r--platform/android/export/gradle_export_util.cpp4
-rw-r--r--platform/android/export/gradle_export_util.h10
-rw-r--r--platform/android/file_access_android.cpp12
-rw-r--r--platform/android/file_access_android.h40
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp331
-rw-r--r--platform/android/file_access_filesystem_jandroid.h98
-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.java103
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java17
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java49
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt113
-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.kt231
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt187
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessFlags.kt (renamed from modules/websocket/emws_server.cpp)119
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt203
-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_io_wrapper.cpp6
-rw-r--r--platform/android/java_godot_io_wrapper.h2
-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/java_godot_view_wrapper.h6
-rw-r--r--platform/android/os_android.cpp32
-rw-r--r--platform/android/os_android.h2
-rw-r--r--platform/ios/SCsub (renamed from platform/iphone/SCsub)18
-rw-r--r--platform/ios/api/api.cpp (renamed from platform/iphone/api/api.cpp)10
-rw-r--r--platform/ios/api/api.h (renamed from platform/iphone/api/api.h)12
-rw-r--r--platform/ios/app_delegate.h (renamed from platform/iphone/app_delegate.h)0
-rw-r--r--platform/ios/app_delegate.mm (renamed from platform/iphone/app_delegate.mm)18
-rw-r--r--platform/ios/detect.py (renamed from platform/iphone/detect.py)34
-rw-r--r--platform/ios/device_metrics.h (renamed from platform/iphone/device_metrics.h)0
-rw-r--r--platform/ios/device_metrics.m (renamed from platform/iphone/device_metrics.m)0
-rw-r--r--platform/ios/display_layer.h (renamed from platform/iphone/display_layer.h)0
-rw-r--r--platform/ios/display_layer.mm (renamed from platform/iphone/display_layer.mm)4
-rw-r--r--platform/ios/display_server_ios.h (renamed from platform/iphone/display_server_iphone.h)26
-rw-r--r--platform/ios/display_server_ios.mm (renamed from platform/iphone/display_server_iphone.mm)233
-rw-r--r--platform/ios/export/export.cpp (renamed from platform/iphone/export/export.cpp)3
-rw-r--r--platform/ios/export/export.h (renamed from platform/osx/export/export.h)8
-rw-r--r--platform/ios/export/export_plugin.cpp (renamed from platform/iphone/export/export_plugin.cpp)33
-rw-r--r--platform/ios/export/export_plugin.h (renamed from platform/iphone/export/export_plugin.h)18
-rw-r--r--platform/ios/export/godot_plugin_config.cpp (renamed from platform/iphone/export/godot_plugin_config.cpp)0
-rw-r--r--platform/ios/export/godot_plugin_config.h (renamed from platform/iphone/export/godot_plugin_config.h)6
-rw-r--r--platform/ios/godot_app_delegate.h (renamed from platform/iphone/godot_app_delegate.h)0
-rw-r--r--platform/ios/godot_app_delegate.m (renamed from platform/iphone/godot_app_delegate.m)0
-rw-r--r--platform/ios/godot_ios.mm (renamed from platform/iphone/godot_iphone.mm)23
-rw-r--r--platform/ios/godot_view.h (renamed from platform/iphone/godot_view.h)0
-rw-r--r--platform/ios/godot_view.mm (renamed from platform/iphone/godot_view.mm)46
-rw-r--r--platform/ios/godot_view_gesture_recognizer.h (renamed from platform/iphone/godot_view_gesture_recognizer.h)0
-rw-r--r--platform/ios/godot_view_gesture_recognizer.mm (renamed from platform/iphone/godot_view_gesture_recognizer.mm)0
-rw-r--r--platform/ios/godot_view_renderer.h (renamed from platform/iphone/godot_view_renderer.h)0
-rw-r--r--platform/ios/godot_view_renderer.mm (renamed from platform/iphone/godot_view_renderer.mm)10
-rw-r--r--platform/ios/ios.h (renamed from platform/iphone/ios.h)2
-rw-r--r--platform/ios/ios.mm (renamed from platform/iphone/ios.mm)0
-rw-r--r--platform/ios/joypad_ios.h (renamed from platform/iphone/joypad_iphone.h)12
-rw-r--r--platform/ios/joypad_ios.mm (renamed from platform/iphone/joypad_iphone.mm)18
-rw-r--r--platform/ios/keyboard_input_view.h (renamed from platform/iphone/keyboard_input_view.h)2
-rw-r--r--platform/ios/keyboard_input_view.mm (renamed from platform/iphone/keyboard_input_view.mm)14
-rw-r--r--platform/ios/logo.png (renamed from platform/iphone/logo.png)bin1297 -> 1297 bytes
-rw-r--r--platform/ios/main.m (renamed from platform/iphone/main.m)0
-rw-r--r--platform/ios/os_ios.h (renamed from platform/iphone/os_iphone.h)29
-rw-r--r--platform/ios/os_ios.mm (renamed from platform/iphone/os_iphone.mm)173
-rw-r--r--platform/ios/platform_config.h (renamed from platform/iphone/platform_config.h)0
-rw-r--r--platform/ios/tts_ios.h (renamed from platform/iphone/tts_ios.h)0
-rw-r--r--platform/ios/tts_ios.mm (renamed from platform/iphone/tts_ios.mm)0
-rw-r--r--platform/ios/view_controller.h (renamed from platform/iphone/view_controller.h)0
-rw-r--r--platform/ios/view_controller.mm (renamed from platform/iphone/view_controller.mm)20
-rw-r--r--platform/ios/vulkan_context_ios.h (renamed from platform/iphone/vulkan_context_iphone.h)14
-rw-r--r--platform/ios/vulkan_context_ios.mm (renamed from platform/iphone/vulkan_context_iphone.mm)12
-rw-r--r--platform/javascript/audio_driver_javascript.h2
-rw-r--r--platform/javascript/display_server_javascript.cpp18
-rw-r--r--platform/javascript/display_server_javascript.h2
-rw-r--r--platform/javascript/export/export.cpp1
-rw-r--r--platform/javascript/export/export.h2
-rw-r--r--platform/javascript/export/export_plugin.cpp12
-rw-r--r--platform/javascript/export/export_plugin.h8
-rw-r--r--platform/javascript/export/export_server.h3
-rw-r--r--platform/javascript/godot_audio.h2
-rw-r--r--platform/javascript/godot_js.h5
-rw-r--r--platform/javascript/godot_webgl2.h2
-rw-r--r--platform/javascript/http_client_javascript.h1
-rw-r--r--platform/javascript/javascript_singleton.cpp2
-rw-r--r--platform/javascript/js/engine/config.js1
-rw-r--r--platform/javascript/js/libs/library_godot_display.js47
-rw-r--r--platform/javascript/js/libs/library_godot_input.js9
-rw-r--r--platform/javascript/os_javascript.cpp4
-rw-r--r--platform/javascript/os_javascript.h4
-rw-r--r--platform/linuxbsd/SCsub16
-rw-r--r--platform/linuxbsd/crash_handler_linuxbsd.h6
-rw-r--r--platform/linuxbsd/dbus-so_wrap.c2641
-rw-r--r--platform/linuxbsd/dbus-so_wrap.h970
-rw-r--r--platform/linuxbsd/detect.py122
-rw-r--r--platform/linuxbsd/detect_prime_x11.cpp5
-rw-r--r--platform/linuxbsd/detect_prime_x11.h3
-rw-r--r--platform/linuxbsd/display_server_x11.cpp84
-rw-r--r--platform/linuxbsd/display_server_x11.h3
-rw-r--r--platform/linuxbsd/export/export.cpp10
-rw-r--r--platform/linuxbsd/export/export_plugin.cpp24
-rw-r--r--platform/linuxbsd/export/export_plugin.h6
-rw-r--r--platform/linuxbsd/fontconfig-so_wrap.c2091
-rw-r--r--platform/linuxbsd/fontconfig-so_wrap.h770
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.cpp11
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.h8
-rw-r--r--platform/linuxbsd/godot_linuxbsd.cpp4
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp105
-rw-r--r--platform/linuxbsd/os_linuxbsd.h9
-rw-r--r--platform/linuxbsd/vulkan_context_x11.h6
-rw-r--r--platform/macos/SCsub30
-rw-r--r--platform/macos/crash_handler_macos.h (renamed from platform/osx/crash_handler_osx.h)8
-rw-r--r--platform/macos/crash_handler_macos.mm (renamed from platform/osx/crash_handler_osx.mm)4
-rw-r--r--platform/macos/detect.py (renamed from platform/osx/detect.py)69
-rw-r--r--platform/macos/dir_access_macos.h (renamed from platform/osx/dir_access_osx.h)21
-rw-r--r--platform/macos/dir_access_macos.mm (renamed from platform/osx/dir_access_osx.mm)14
-rw-r--r--platform/macos/display_server_macos.h (renamed from platform/osx/display_server_osx.h)35
-rw-r--r--platform/macos/display_server_macos.mm (renamed from platform/osx/display_server_osx.mm)509
-rw-r--r--platform/macos/export/codesign.cpp (renamed from platform/osx/export/codesign.cpp)0
-rw-r--r--platform/macos/export/codesign.h (renamed from platform/osx/export/codesign.h)6
-rw-r--r--platform/macos/export/export.cpp (renamed from platform/osx/export/export.cpp)4
-rw-r--r--platform/macos/export/export.h (renamed from platform/iphone/export/export.h)8
-rw-r--r--platform/macos/export/export_plugin.cpp (renamed from platform/osx/export/export_plugin.cpp)106
-rw-r--r--platform/macos/export/export_plugin.h (renamed from platform/osx/export/export_plugin.h)26
-rw-r--r--platform/macos/export/lipo.cpp (renamed from platform/osx/export/lipo.cpp)0
-rw-r--r--platform/macos/export/lipo.h (renamed from platform/osx/export/lipo.h)6
-rw-r--r--platform/macos/export/macho.cpp (renamed from platform/osx/export/macho.cpp)0
-rw-r--r--platform/macos/export/macho.h (renamed from platform/osx/export/macho.h)6
-rw-r--r--platform/macos/export/plist.cpp (renamed from platform/osx/export/plist.cpp)0
-rw-r--r--platform/macos/export/plist.h (renamed from platform/osx/export/plist.h)6
-rw-r--r--platform/macos/gl_manager_macos_legacy.h (renamed from platform/osx/gl_manager_osx_legacy.h)19
-rw-r--r--platform/macos/gl_manager_macos_legacy.mm (renamed from platform/osx/gl_manager_osx_legacy.mm)42
-rw-r--r--platform/macos/godot_application.h (renamed from platform/osx/godot_application.h)0
-rw-r--r--platform/macos/godot_application.mm (renamed from platform/osx/godot_application.mm)4
-rw-r--r--platform/macos/godot_application_delegate.h (renamed from platform/osx/godot_application_delegate.h)1
-rw-r--r--platform/macos/godot_application_delegate.mm (renamed from platform/osx/godot_application_delegate.mm)81
-rw-r--r--platform/macos/godot_content_view.h (renamed from platform/osx/godot_content_view.h)1
-rw-r--r--platform/macos/godot_content_view.mm (renamed from platform/osx/godot_content_view.mm)137
-rw-r--r--platform/macos/godot_main_macos.mm (renamed from platform/osx/godot_main_osx.mm)19
-rw-r--r--platform/macos/godot_menu_item.h (renamed from platform/osx/godot_menu_item.h)0
-rw-r--r--platform/macos/godot_window.h (renamed from platform/osx/godot_window.h)2
-rw-r--r--platform/macos/godot_window.mm (renamed from platform/osx/godot_window.mm)12
-rw-r--r--platform/macos/godot_window_delegate.h (renamed from platform/osx/godot_window_delegate.h)2
-rw-r--r--platform/macos/godot_window_delegate.mm (renamed from platform/osx/godot_window_delegate.mm)70
-rw-r--r--platform/macos/joypad_macos.cpp (renamed from platform/osx/joypad_osx.cpp)32
-rw-r--r--platform/macos/joypad_macos.h (renamed from platform/osx/joypad_osx.h)14
-rw-r--r--platform/macos/key_mapping_macos.h (renamed from platform/osx/key_mapping_osx.h)12
-rw-r--r--platform/macos/key_mapping_macos.mm (renamed from platform/osx/key_mapping_osx.mm)24
-rw-r--r--platform/macos/logo.png (renamed from platform/osx/logo.png)bin7195 -> 7195 bytes
-rw-r--r--platform/macos/macos_terminal_logger.h (renamed from platform/osx/osx_terminal_logger.h)15
-rw-r--r--platform/macos/macos_terminal_logger.mm (renamed from platform/osx/osx_terminal_logger.mm)10
-rw-r--r--platform/macos/os_macos.h (renamed from platform/osx/os_osx.h)28
-rw-r--r--platform/macos/os_macos.mm (renamed from platform/osx/os_osx.mm)178
-rw-r--r--platform/macos/platform_config.h (renamed from platform/osx/platform_config.h)0
-rw-r--r--platform/macos/platform_macos_builders.py (renamed from platform/osx/platform_osx_builders.py)2
-rw-r--r--platform/macos/tts_macos.h (renamed from platform/osx/tts_osx.h)10
-rw-r--r--platform/macos/tts_macos.mm (renamed from platform/osx/tts_osx.mm)6
-rw-r--r--platform/macos/vulkan_context_macos.h (renamed from platform/osx/vulkan_context_osx.h)14
-rw-r--r--platform/macos/vulkan_context_macos.mm (renamed from platform/osx/vulkan_context_osx.mm)12
-rw-r--r--platform/osx/SCsub30
-rw-r--r--platform/register_platform_apis.h6
-rw-r--r--platform/uwp/app_uwp.h1
-rw-r--r--platform/uwp/export/app_packager.h4
-rw-r--r--platform/uwp/export/export.cpp1
-rw-r--r--platform/uwp/export/export_plugin.cpp72
-rw-r--r--platform/uwp/export/export_plugin.h18
-rw-r--r--platform/uwp/joypad_uwp.h2
-rw-r--r--platform/uwp/os_uwp.cpp3
-rw-r--r--platform/uwp/os_uwp.h4
-rw-r--r--platform/windows/detect.py7
-rw-r--r--platform/windows/display_server_windows.cpp90
-rw-r--r--platform/windows/display_server_windows.h18
-rw-r--r--platform/windows/export/export.cpp8
-rw-r--r--platform/windows/export/export.h2
-rw-r--r--platform/windows/export/export_plugin.cpp11
-rw-r--r--platform/windows/export/export_plugin.h4
-rw-r--r--platform/windows/godot.natvis6
-rw-r--r--platform/windows/godot_windows.cpp4
-rw-r--r--platform/windows/os_windows.cpp136
-rw-r--r--platform/windows/os_windows.h25
-rw-r--r--platform/windows/vulkan_context_win.h6
-rw-r--r--platform/windows/windows_terminal_logger.h2
-rw-r--r--scene/2d/animated_sprite_2d.cpp5
-rw-r--r--scene/2d/animated_sprite_2d.h2
-rw-r--r--scene/2d/area_2d.cpp8
-rw-r--r--scene/2d/audio_listener_2d.h6
-rw-r--r--scene/2d/audio_stream_player_2d.cpp2
-rw-r--r--scene/2d/audio_stream_player_2d.h2
-rw-r--r--scene/2d/back_buffer_copy.h6
-rw-r--r--scene/2d/camera_2d.cpp6
-rw-r--r--scene/2d/canvas_group.h6
-rw-r--r--scene/2d/canvas_modulate.h6
-rw-r--r--scene/2d/cpu_particles_2d.cpp8
-rw-r--r--scene/2d/gpu_particles_2d.cpp5
-rw-r--r--scene/2d/gpu_particles_2d.h6
-rw-r--r--scene/2d/light_occluder_2d.h6
-rw-r--r--scene/2d/line_2d.h6
-rw-r--r--scene/2d/navigation_agent_2d.h2
-rw-r--r--scene/2d/navigation_obstacle_2d.h2
-rw-r--r--scene/2d/navigation_region_2d.cpp32
-rw-r--r--scene/2d/node_2d.h6
-rw-r--r--scene/2d/path_2d.cpp1
-rw-r--r--scene/2d/physics_body_2d.cpp4
-rw-r--r--scene/2d/ray_cast_2d.cpp2
-rw-r--r--scene/2d/shape_cast_2d.cpp31
-rw-r--r--scene/2d/shape_cast_2d.h6
-rw-r--r--scene/2d/sprite_2d.h2
-rw-r--r--scene/2d/tile_map.cpp4
-rw-r--r--scene/2d/tile_map.h2
-rw-r--r--scene/2d/touch_screen_button.cpp4
-rw-r--r--scene/2d/visible_on_screen_notifier_2d.h2
-rw-r--r--scene/3d/area_3d.cpp8
-rw-r--r--scene/3d/audio_listener_3d.h6
-rw-r--r--scene/3d/audio_stream_player_3d.cpp2
-rw-r--r--scene/3d/audio_stream_player_3d.h1
-rw-r--r--scene/3d/bone_attachment_3d.cpp21
-rw-r--r--scene/3d/bone_attachment_3d.h12
-rw-r--r--scene/3d/camera_3d.cpp18
-rw-r--r--scene/3d/camera_3d.h12
-rw-r--r--scene/3d/collision_object_3d.cpp8
-rw-r--r--scene/3d/collision_object_3d.h2
-rw-r--r--scene/3d/collision_polygon_3d.h2
-rw-r--r--scene/3d/collision_shape_3d.h6
-rw-r--r--scene/3d/cpu_particles_3d.cpp11
-rw-r--r--scene/3d/cpu_particles_3d.h8
-rw-r--r--scene/3d/decal.cpp13
-rw-r--r--scene/3d/decal.h4
-rw-r--r--scene/3d/gpu_particles_3d.cpp6
-rw-r--r--scene/3d/gpu_particles_3d.h6
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp59
-rw-r--r--scene/3d/gpu_particles_collision_3d.h9
-rw-r--r--scene/3d/importer_mesh_instance_3d.h7
-rw-r--r--scene/3d/joint_3d.cpp116
-rw-r--r--scene/3d/label_3d.cpp132
-rw-r--r--scene/3d/label_3d.h32
-rw-r--r--scene/3d/light_3d.cpp10
-rw-r--r--scene/3d/light_3d.h1
-rw-r--r--scene/3d/lightmap_gi.cpp6
-rw-r--r--scene/3d/lightmap_gi.h2
-rw-r--r--scene/3d/mesh_instance_3d.h6
-rw-r--r--scene/3d/multimesh_instance_3d.h2
-rw-r--r--scene/3d/navigation_agent_3d.h6
-rw-r--r--scene/3d/navigation_obstacle_3d.h6
-rw-r--r--scene/3d/navigation_region_3d.cpp341
-rw-r--r--scene/3d/navigation_region_3d.h19
-rw-r--r--scene/3d/node_3d.cpp35
-rw-r--r--scene/3d/node_3d.h6
-rw-r--r--scene/3d/occluder_instance_3d.cpp2
-rw-r--r--scene/3d/occluder_instance_3d.h2
-rw-r--r--scene/3d/path_3d.cpp3
-rw-r--r--scene/3d/path_3d.h6
-rw-r--r--scene/3d/physics_body_3d.cpp4
-rw-r--r--scene/3d/physics_body_3d.h2
-rw-r--r--scene/3d/ray_cast_3d.h2
-rw-r--r--scene/3d/reflection_probe.h6
-rw-r--r--scene/3d/remote_transform_3d.h6
-rw-r--r--scene/3d/shape_cast_3d.cpp634
-rw-r--r--scene/3d/shape_cast_3d.h142
-rw-r--r--scene/3d/skeleton_3d.cpp26
-rw-r--r--scene/3d/skeleton_3d.h6
-rw-r--r--scene/3d/skeleton_ik_3d.h6
-rw-r--r--scene/3d/soft_dynamic_body_3d.cpp11
-rw-r--r--scene/3d/soft_dynamic_body_3d.h6
-rw-r--r--scene/3d/spring_arm_3d.h6
-rw-r--r--scene/3d/sprite_3d.cpp7
-rw-r--r--scene/3d/vehicle_body_3d.h6
-rw-r--r--scene/3d/velocity_tracker_3d.h6
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.h2
-rw-r--r--scene/3d/visual_instance_3d.cpp41
-rw-r--r--scene/3d/visual_instance_3d.h10
-rw-r--r--scene/3d/voxel_gi.cpp3
-rw-r--r--scene/3d/voxel_gi.h4
-rw-r--r--scene/3d/voxelizer.h6
-rw-r--r--scene/3d/world_environment.h6
-rw-r--r--scene/3d/xr_nodes.cpp8
-rw-r--r--scene/SCsub1
-rw-r--r--scene/animation/animation_blend_space_1d.cpp27
-rw-r--r--scene/animation/animation_blend_space_1d.h5
-rw-r--r--scene/animation/animation_blend_space_2d.cpp33
-rw-r--r--scene/animation/animation_blend_space_2d.h5
-rw-r--r--scene/animation/animation_blend_tree.cpp163
-rw-r--r--scene/animation/animation_blend_tree.h64
-rw-r--r--scene/animation/animation_node_state_machine.cpp48
-rw-r--r--scene/animation/animation_node_state_machine.h2
-rw-r--r--scene/animation/animation_player.cpp79
-rw-r--r--scene/animation/animation_player.h11
-rw-r--r--scene/animation/animation_tree.cpp64
-rw-r--r--scene/animation/animation_tree.h14
-rw-r--r--scene/animation/easing_equations.h2
-rw-r--r--scene/animation/tween.cpp15
-rw-r--r--scene/animation/tween.h2
-rw-r--r--scene/audio/audio_stream_player.cpp2
-rw-r--r--scene/debugger/scene_debugger.cpp2
-rw-r--r--scene/debugger/scene_debugger.h2
-rw-r--r--scene/gui/base_button.h2
-rw-r--r--scene/gui/button.cpp181
-rw-r--r--scene/gui/button.h15
-rw-r--r--scene/gui/code_edit.cpp81
-rw-r--r--scene/gui/code_edit.h11
-rw-r--r--scene/gui/color_mode.cpp330
-rw-r--r--scene/gui/color_mode.h143
-rw-r--r--scene/gui/color_picker.cpp582
-rw-r--r--scene/gui/color_picker.h97
-rw-r--r--scene/gui/control.cpp2943
-rw-r--r--scene/gui/control.h327
-rw-r--r--scene/gui/dialogs.cpp30
-rw-r--r--scene/gui/dialogs.h9
-rw-r--r--scene/gui/file_dialog.cpp119
-rw-r--r--scene/gui/file_dialog.h10
-rw-r--r--scene/gui/gradient_edit.cpp4
-rw-r--r--scene/gui/gradient_edit.h1
-rw-r--r--scene/gui/graph_edit.cpp38
-rw-r--r--scene/gui/graph_edit.h4
-rw-r--r--scene/gui/graph_node.cpp75
-rw-r--r--scene/gui/graph_node.h5
-rw-r--r--scene/gui/grid_container.cpp5
-rw-r--r--scene/gui/item_list.cpp47
-rw-r--r--scene/gui/item_list.h11
-rw-r--r--scene/gui/label.cpp197
-rw-r--r--scene/gui/label.h18
-rw-r--r--scene/gui/line_edit.cpp160
-rw-r--r--scene/gui/line_edit.h30
-rw-r--r--scene/gui/link_button.cpp83
-rw-r--r--scene/gui/link_button.h15
-rw-r--r--scene/gui/menu_button.cpp4
-rw-r--r--scene/gui/menu_button.h2
-rw-r--r--scene/gui/option_button.cpp61
-rw-r--r--scene/gui/option_button.h9
-rw-r--r--scene/gui/popup.h2
-rw-r--r--scene/gui/popup_menu.cpp43
-rw-r--r--scene/gui/popup_menu.h6
-rw-r--r--scene/gui/range.h2
-rw-r--r--scene/gui/rich_text_label.cpp447
-rw-r--r--scene/gui/rich_text_label.h15
-rw-r--r--scene/gui/scroll_bar.cpp4
-rw-r--r--scene/gui/scroll_bar.h2
-rw-r--r--scene/gui/scroll_container.cpp95
-rw-r--r--scene/gui/scroll_container.h6
-rw-r--r--scene/gui/separator.h2
-rw-r--r--scene/gui/slider.cpp14
-rw-r--r--scene/gui/slider.h8
-rw-r--r--scene/gui/spin_box.cpp34
-rw-r--r--scene/gui/spin_box.h7
-rw-r--r--scene/gui/subviewport_container.h6
-rw-r--r--scene/gui/tab_bar.cpp47
-rw-r--r--scene/gui/tab_bar.h5
-rw-r--r--scene/gui/tab_container.cpp11
-rw-r--r--scene/gui/tab_container.h1
-rw-r--r--scene/gui/text_edit.cpp177
-rw-r--r--scene/gui/text_edit.h17
-rw-r--r--scene/gui/texture_button.h1
-rw-r--r--scene/gui/tree.cpp129
-rw-r--r--scene/gui/tree.h15
-rw-r--r--scene/gui/video_stream_player.cpp2
-rw-r--r--scene/gui/video_stream_player.h2
-rw-r--r--scene/gui/view_panner.cpp2
-rw-r--r--scene/main/canvas_item.cpp78
-rw-r--r--scene/main/canvas_item.h14
-rw-r--r--scene/main/http_request.h6
-rw-r--r--scene/main/multiplayer_api.cpp416
-rw-r--r--scene/main/multiplayer_api.h115
-rw-r--r--scene/main/multiplayer_peer.cpp (renamed from core/multiplayer/multiplayer_peer.cpp)41
-rw-r--r--scene/main/multiplayer_peer.h (renamed from core/multiplayer/multiplayer_peer.h)31
-rw-r--r--scene/main/node.cpp97
-rw-r--r--scene/main/node.h50
-rw-r--r--scene/main/scene_tree.cpp88
-rw-r--r--scene/main/scene_tree.h4
-rw-r--r--scene/main/shader_globals_override.cpp22
-rw-r--r--scene/main/viewport.cpp167
-rw-r--r--scene/main/viewport.h51
-rw-r--r--scene/main/window.cpp2
-rw-r--r--scene/multiplayer/SCsub5
-rw-r--r--scene/register_scene_types.cpp72
-rw-r--r--scene/register_scene_types.h2
-rw-r--r--scene/resources/animation.cpp60
-rw-r--r--scene/resources/animation.h4
-rw-r--r--scene/resources/animation_library.h2
-rw-r--r--scene/resources/audio_stream_wav.cpp (renamed from scene/resources/audio_stream_sample.cpp)170
-rw-r--r--scene/resources/audio_stream_wav.h (renamed from scene/resources/audio_stream_sample.h)38
-rw-r--r--scene/resources/bone_map.cpp181
-rw-r--r--scene/resources/bone_map.h70
-rw-r--r--scene/resources/box_shape_3d.h6
-rw-r--r--scene/resources/capsule_shape_3d.h6
-rw-r--r--scene/resources/concave_polygon_shape_2d.h2
-rw-r--r--scene/resources/concave_polygon_shape_3d.h2
-rw-r--r--scene/resources/convex_polygon_shape_3d.h6
-rw-r--r--scene/resources/cylinder_shape_3d.h2
-rw-r--r--scene/resources/default_theme/default_theme.cpp63
-rw-r--r--scene/resources/default_theme/default_theme.h2
-rw-r--r--scene/resources/environment.cpp16
-rw-r--r--scene/resources/environment.h8
-rw-r--r--scene/resources/font.cpp2580
-rw-r--r--scene/resources/font.h328
-rw-r--r--scene/resources/gradient.h8
-rw-r--r--scene/resources/height_map_shape_3d.h6
-rw-r--r--scene/resources/immediate_mesh.h2
-rw-r--r--scene/resources/importer_mesh.h7
-rw-r--r--scene/resources/label_settings.cpp187
-rw-r--r--scene/resources/label_settings.h (renamed from editor/plugins/font_editor_plugin.h)74
-rw-r--r--scene/resources/material.cpp195
-rw-r--r--scene/resources/material.h17
-rw-r--r--scene/resources/mesh.cpp66
-rw-r--r--scene/resources/mesh.h5
-rw-r--r--scene/resources/mesh_library.cpp2
-rw-r--r--scene/resources/multimesh.h2
-rw-r--r--scene/resources/navigation_mesh.cpp101
-rw-r--r--scene/resources/navigation_mesh.h4
-rw-r--r--scene/resources/packed_scene.cpp8
-rw-r--r--scene/resources/packed_scene.h2
-rw-r--r--scene/resources/particles_material.cpp301
-rw-r--r--scene/resources/particles_material.h38
-rw-r--r--scene/resources/primitive_meshes.cpp246
-rw-r--r--scene/resources/primitive_meshes.h70
-rw-r--r--scene/resources/resource_format_text.cpp174
-rw-r--r--scene/resources/resource_format_text.h8
-rw-r--r--scene/resources/separation_ray_shape_2d.cpp2
-rw-r--r--scene/resources/separation_ray_shape_3d.h8
-rw-r--r--scene/resources/shader.cpp65
-rw-r--r--scene/resources/shader.h22
-rw-r--r--scene/resources/shader_include.cpp144
-rw-r--r--scene/resources/shader_include.h71
-rw-r--r--scene/resources/shape_3d.h2
-rw-r--r--scene/resources/skeleton_modification_2d.h6
-rw-r--r--scene/resources/skeleton_modification_2d_ccdik.h6
-rw-r--r--scene/resources/skeleton_modification_2d_fabrik.h6
-rw-r--r--scene/resources/skeleton_modification_2d_jiggle.h6
-rw-r--r--scene/resources/skeleton_modification_2d_lookat.h6
-rw-r--r--scene/resources/skeleton_modification_2d_physicalbones.h6
-rw-r--r--scene/resources/skeleton_modification_2d_stackholder.h6
-rw-r--r--scene/resources/skeleton_modification_2d_twoboneik.h6
-rw-r--r--scene/resources/skeleton_modification_3d.h6
-rw-r--r--scene/resources/skeleton_modification_3d_ccdik.h6
-rw-r--r--scene/resources/skeleton_modification_3d_fabrik.h6
-rw-r--r--scene/resources/skeleton_modification_3d_jiggle.h6
-rw-r--r--scene/resources/skeleton_modification_3d_lookat.h6
-rw-r--r--scene/resources/skeleton_modification_3d_stackholder.h6
-rw-r--r--scene/resources/skeleton_modification_3d_twoboneik.h6
-rw-r--r--scene/resources/skeleton_modification_stack_2d.h6
-rw-r--r--scene/resources/skeleton_modification_stack_3d.h6
-rw-r--r--scene/resources/skeleton_profile.cpp835
-rw-r--r--scene/resources/skeleton_profile.h140
-rw-r--r--scene/resources/sky_material.h2
-rw-r--r--scene/resources/sphere_shape_3d.h2
-rw-r--r--scene/resources/sprite_frames.cpp51
-rw-r--r--scene/resources/sprite_frames.h5
-rw-r--r--scene/resources/style_box.h2
-rw-r--r--scene/resources/surface_tool.h2
-rw-r--r--scene/resources/syntax_highlighter.h2
-rw-r--r--scene/resources/text_file.cpp2
-rw-r--r--scene/resources/text_file.h6
-rw-r--r--scene/resources/text_line.cpp68
-rw-r--r--scene/resources/text_line.h12
-rw-r--r--scene/resources/text_paragraph.cpp167
-rw-r--r--scene/resources/text_paragraph.h18
-rw-r--r--scene/resources/texture.cpp42
-rw-r--r--scene/resources/texture.h7
-rw-r--r--scene/resources/theme.cpp8
-rw-r--r--scene/resources/theme.h2
-rw-r--r--scene/resources/tile_set.cpp105
-rw-r--r--scene/resources/tile_set.h11
-rw-r--r--scene/resources/video_stream.h4
-rw-r--r--scene/resources/visual_shader.cpp73
-rw-r--r--scene/resources/visual_shader.h11
-rw-r--r--scene/resources/visual_shader_nodes.cpp54
-rw-r--r--scene/resources/visual_shader_nodes.h8
-rw-r--r--scene/resources/visual_shader_particle_nodes.cpp6
-rw-r--r--scene/resources/visual_shader_particle_nodes.h2
-rw-r--r--scene/resources/world_3d.cpp1
-rw-r--r--scene/resources/world_boundary_shape_3d.h3
-rw-r--r--servers/audio/audio_driver_dummy.h2
-rw-r--r--servers/audio/audio_effect.h6
-rw-r--r--servers/audio/audio_stream.cpp98
-rw-r--r--servers/audio/audio_stream.h43
-rw-r--r--servers/audio/effects/audio_effect_amplify.h6
-rw-r--r--servers/audio/effects/audio_effect_chorus.h6
-rw-r--r--servers/audio/effects/audio_effect_compressor.h6
-rw-r--r--servers/audio/effects/audio_effect_delay.h6
-rw-r--r--servers/audio/effects/audio_effect_distortion.h6
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp1
-rw-r--r--servers/audio/effects/audio_effect_eq.h8
-rw-r--r--servers/audio/effects/audio_effect_filter.h6
-rw-r--r--servers/audio/effects/audio_effect_panner.h6
-rw-r--r--servers/audio/effects/audio_effect_record.cpp20
-rw-r--r--servers/audio/effects/audio_effect_record.h16
-rw-r--r--servers/audio/effects/audio_effect_reverb.h8
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp6
-rw-r--r--servers/audio/effects/audio_stream_generator.h5
-rw-r--r--servers/audio/effects/eq_filter.cpp (renamed from servers/audio/effects/eq.cpp)6
-rw-r--r--servers/audio/effects/eq_filter.h (renamed from servers/audio/effects/eq.h)2
-rw-r--r--servers/audio/effects/reverb_filter.cpp (renamed from servers/audio/effects/reverb.cpp)4
-rw-r--r--servers/audio/effects/reverb_filter.h (renamed from servers/audio/effects/reverb.h)8
-rw-r--r--servers/audio_server.cpp16
-rw-r--r--servers/audio_server.h7
-rw-r--r--servers/debugger/servers_debugger.h4
-rw-r--r--servers/display_server.cpp21
-rw-r--r--servers/display_server.h14
-rw-r--r--servers/extensions/physics_server_3d_extension.h2
-rw-r--r--servers/movie_writer/movie_writer.cpp41
-rw-r--r--servers/movie_writer/movie_writer.h2
-rw-r--r--servers/navigation_server_3d.cpp257
-rw-r--r--servers/navigation_server_3d.h62
-rw-r--r--servers/physics_2d/godot_area_2d.cpp4
-rw-r--r--servers/physics_2d/godot_body_2d.cpp4
-rw-r--r--servers/physics_2d/godot_step_2d.cpp9
-rw-r--r--servers/physics_2d/godot_step_2d.h4
-rw-r--r--servers/physics_3d/gjk_epa.h2
-rw-r--r--servers/physics_3d/godot_area_3d.cpp4
-rw-r--r--servers/physics_3d/godot_body_3d.cpp2
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.h6
-rw-r--r--servers/physics_3d/godot_step_3d.cpp9
-rw-r--r--servers/physics_3d/godot_step_3d.h4
-rw-r--r--servers/physics_server_2d.cpp12
-rw-r--r--servers/physics_server_2d.h1
-rw-r--r--servers/physics_server_3d.cpp12
-rw-r--r--servers/physics_server_3d.h1
-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.h5
-rw-r--r--servers/rendering/dummy/rasterizer_canvas_dummy.h2
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h9
-rw-r--r--servers/rendering/dummy/rasterizer_scene_dummy.h83
-rw-r--r--servers/rendering/dummy/storage/SCsub5
-rw-r--r--servers/rendering/dummy/storage/light_storage.h2
-rw-r--r--servers/rendering/dummy/storage/material_storage.h37
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h57
-rw-r--r--servers/rendering/dummy/storage/particles_storage.h2
-rw-r--r--servers/rendering/dummy/storage/texture_storage.cpp43
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h14
-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.h6
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp49
-rw-r--r--servers/rendering/renderer_canvas_cull.h8
-rw-r--r--servers/rendering/renderer_canvas_render.cpp6
-rw-r--r--servers/rendering/renderer_canvas_render.h16
-rw-r--r--servers/rendering/renderer_compositor.cpp7
-rw-r--r--servers/rendering/renderer_compositor.h12
-rw-r--r--servers/rendering/renderer_geometry_instance.cpp138
-rw-r--r--servers/rendering/renderer_geometry_instance.h150
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h16
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.h2
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp116
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h36
-rw-r--r--servers/rendering/renderer_rd/effects/resolve.h2
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp1715
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.h508
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.h2
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp174
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.h75
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp1247
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h390
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp1205
-rw-r--r--servers/rendering/renderer_rd/environment/fog.h328
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp391
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h91
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp (renamed from servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp)323
-rw-r--r--servers/rendering/renderer_rd/environment/sky.h (renamed from servers/rendering/renderer_rd/renderer_scene_sky_rd.h)67
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp598
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h138
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp45
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h27
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp476
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h121
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp45
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h27
-rw-r--r--servers/rendering/renderer_rd/framebuffer_cache_rd.cpp (renamed from servers/rendering/renderer_thread_pool.cpp)36
-rw-r--r--servers/rendering/renderer_rd/framebuffer_cache_rd.h310
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp70
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h27
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp17
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h22
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp130
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.h167
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp2099
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h424
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h222
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/shaders/SCsub2
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/SCsub2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl (renamed from servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl)51
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl (renamed from servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl)20
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl28
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl (renamed from servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl)48
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl112
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl (renamed from servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_blur.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_interleave.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil_blur.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil_interleave.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl72
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/SCsub2
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/gi.glsl158
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl24
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sky.glsl (renamed from servers/rendering/renderer_rd/shaders/sky.glsl)4
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl (renamed from servers/rendering/renderer_rd/shaders/volumetric_fog.glsl)8
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl (renamed from servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl)10
-rw-r--r--servers/rendering/renderer_rd/shaders/light_data_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl12
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl15
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/specular_merge.glsl53
-rw-r--r--servers/rendering/renderer_rd/shaders/taa_resolve.glsl5
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp68
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h144
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp624
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h415
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp46
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h414
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp114
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h390
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp143
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h465
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.cpp (renamed from servers/rendering/renderer_rd/renderer_storage_rd.cpp)437
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.h122
-rw-r--r--servers/rendering/renderer_rd/uniform_set_cache_rd.h10
-rw-r--r--servers/rendering/renderer_scene.h150
-rw-r--r--servers/rendering/renderer_scene_cull.cpp224
-rw-r--r--servers/rendering/renderer_scene_cull.h217
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h9
-rw-r--r--servers/rendering/renderer_scene_render.cpp499
-rw-r--r--servers/rendering/renderer_scene_render.h236
-rw-r--r--servers/rendering/renderer_viewport.cpp36
-rw-r--r--servers/rendering/renderer_viewport.h48
-rw-r--r--servers/rendering/rendering_device.cpp6
-rw-r--r--servers/rendering/rendering_device.h39
-rw-r--r--servers/rendering/rendering_server_default.cpp53
-rw-r--r--servers/rendering/rendering_server_default.h57
-rw-r--r--servers/rendering/rendering_server_globals.cpp3
-rw-r--r--servers/rendering/rendering_server_globals.h5
-rw-r--r--servers/rendering/shader_compiler.cpp86
-rw-r--r--servers/rendering/shader_language.cpp444
-rw-r--r--servers/rendering/shader_language.h26
-rw-r--r--servers/rendering/shader_preprocessor.cpp1048
-rw-r--r--servers/rendering/shader_preprocessor.h200
-rw-r--r--servers/rendering/shader_types.cpp10
-rw-r--r--servers/rendering/shader_types.h6
-rw-r--r--servers/rendering/shader_warnings.h6
-rw-r--r--servers/rendering/storage/environment_storage.cpp769
-rw-r--r--servers/rendering/storage/environment_storage.h296
-rw-r--r--servers/rendering/storage/light_storage.h3
-rw-r--r--servers/rendering/storage/material_storage.h37
-rw-r--r--servers/rendering/storage/mesh_storage.h6
-rw-r--r--servers/rendering/storage/particles_storage.h3
-rw-r--r--servers/rendering/storage/texture_storage.h16
-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/rendering_server.cpp102
-rw-r--r--servers/rendering_server.h73
-rw-r--r--servers/server_wrap_mt_common.h5
-rw-r--r--servers/text/text_server_extension.cpp74
-rw-r--r--servers/text/text_server_extension.h46
-rw-r--r--servers/text_server.cpp120
-rw-r--r--servers/text_server.h48
-rw-r--r--servers/xr/xr_interface.cpp88
-rw-r--r--servers/xr/xr_interface.h11
-rw-r--r--servers/xr/xr_interface_extension.cpp20
-rw-r--r--servers/xr/xr_interface_extension.h6
-rw-r--r--servers/xr/xr_pose.h2
-rw-r--r--servers/xr_server.cpp10
-rw-r--r--servers/xr_server.h11
-rw-r--r--tests/core/input/test_input_event_key.h294
-rw-r--r--tests/core/input/test_shortcut.h235
-rw-r--r--tests/core/io/test_file_access.h23
-rw-r--r--tests/core/io/test_image.h39
-rw-r--r--tests/core/io/test_marshalls.h2
-rw-r--r--tests/core/io/test_resource.h10
-rw-r--r--tests/core/math/test_aabb.h20
-rw-r--r--tests/core/math/test_basis.h2
-rw-r--r--tests/core/math/test_plane.h172
-rw-r--r--tests/core/math/test_quaternion.h389
-rw-r--r--tests/core/math/test_transform_2d.h88
-rw-r--r--tests/core/math/test_transform_3d.h89
-rw-r--r--tests/core/math/test_vector4.h312
-rw-r--r--tests/core/math/test_vector4i.h148
-rw-r--r--tests/core/object/test_class_db.h16
-rw-r--r--tests/core/object/test_method_bind.h1
-rw-r--r--tests/core/object/test_object.h4
-rw-r--r--tests/core/os/test_os.h158
-rw-r--r--tests/core/string/test_string.h93
-rw-r--r--tests/core/templates/test_hash_set.h4
-rw-r--r--tests/core/templates/test_rid.h101
-rw-r--r--tests/core/templates/test_vector.h4
-rw-r--r--tests/core/threads/test_worker_thread_pool.h158
-rw-r--r--tests/data/line_endings_cr.test.txt1
-rw-r--r--tests/data/line_endings_crlf.test.txt4
-rw-r--r--tests/data/line_endings_lf.test.txt4
-rw-r--r--tests/scene/test_audio_stream_wav.h243
-rw-r--r--tests/scene/test_code_edit.h2
-rw-r--r--tests/scene/test_path_3d.h2
-rw-r--r--tests/scene/test_sprite_frames.h247
-rw-r--r--tests/scene/test_text_edit.h20
-rw-r--r--tests/scene/test_theme.h20
-rw-r--r--tests/servers/test_text_server.h226
-rw-r--r--tests/test_macros.h23
-rw-r--r--tests/test_main.cpp31
-rw-r--r--tests/test_validate_testing.h5
-rw-r--r--thirdparty/README.md14
-rw-r--r--thirdparty/certs/ca-certificates.crt231
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh338
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh126
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh233
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh85
-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.hh301
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ExtensionPos.hh17
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh171
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh56
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh128
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh41
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh219
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh41
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh206
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh42
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh228
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkRecord.hh52
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh46
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh193
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh328
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh189
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh99
-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.hh95
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh138
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh154
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh329
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh20
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh17
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh16
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh19
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh62
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh15
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh18
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh23
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh17
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh15
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh40
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh66
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh40
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh83
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh28
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh21
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/types.hh66
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh298
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/Glyph.hh235
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh50
-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.hh397
-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/coverage-graph.hh80
-rw-r--r--thirdparty/harfbuzz/src/graph/graph.hh1046
-rw-r--r--thirdparty/harfbuzz/src/graph/gsubgpos-context.cc71
-rw-r--r--thirdparty/harfbuzz/src/graph/gsubgpos-context.hh67
-rw-r--r--thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh351
-rw-r--r--thirdparty/harfbuzz/src/graph/pairpos-graph.hh299
-rw-r--r--thirdparty/harfbuzz/src/graph/serialize.hh249
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-common.hh20
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh10
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh11
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout.cc6
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-map.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-algs.hh59
-rw-r--r--thirdparty/harfbuzz/src/hb-array.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-atomic.hh13
-rw-r--r--thirdparty/harfbuzz/src/hb-bimap.hh9
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-page.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set-invertible.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set.hh49
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.cc18
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh431
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh572
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-serialize.cc32
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-verify.cc28
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.cc118
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.h63
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.hh62
-rw-r--r--thirdparty/harfbuzz/src/hb-cache.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-common.cc60
-rw-r--r--thirdparty/harfbuzz/src/hb-common.h3
-rw-r--r--thirdparty/harfbuzz/src/hb-config.hh18
-rw-r--r--thirdparty/harfbuzz/src/hb-coretext.cc56
-rw-r--r--thirdparty/harfbuzz/src/hb-cplusplus.hh221
-rw-r--r--thirdparty/harfbuzz/src/hb-debug.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-deprecated.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-directwrite.cc43
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.cc71
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.hh14
-rw-r--r--thirdparty/harfbuzz/src/hb-face.cc6
-rw-r--r--thirdparty/harfbuzz/src/hb-font.cc224
-rw-r--r--thirdparty/harfbuzz/src/hb-font.h26
-rw-r--r--thirdparty/harfbuzz/src/hb-font.hh81
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.cc282
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.h9
-rw-r--r--thirdparty/harfbuzz/src/hb-graphite2.cc8
-rw-r--r--thirdparty/harfbuzz/src/hb-iter.hh18
-rw-r--r--thirdparty/harfbuzz/src/hb-machinery.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-map.cc54
-rw-r--r--thirdparty/harfbuzz/src/hb-map.h8
-rw-r--r--thirdparty/harfbuzz/src/hb-map.hh192
-rw-r--r--thirdparty/harfbuzz/src/hb-meta.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-null.hh35
-rw-r--r--thirdparty/harfbuzz/src/hb-object.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-open-type.hh47
-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-colr-table.hh5
-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-color.cc8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color.h4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-font.cc194
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-glyf-table.hh1330
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh81
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-common.hh1545
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh378
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh3094
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh15
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh1267
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.cc90
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-map.cc19
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-map.hh20
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-metrics.cc12
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name-language-static.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name-table.hh32
-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-post-table.hh8
-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-complex-use-table.hh1570
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc11
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.cc57
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.hh8
-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)62
-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)14
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc)10
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-hebrew.cc)38
-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)358
-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)33
-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)82
-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)20
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh931
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh418
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc)22
-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)101
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-stat-table.hh262
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag-table.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag.cc27
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh82
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-common.hh63
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh65
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh132
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh32
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-repacker.hh1158
-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.cc46
-rw-r--r--thirdparty/harfbuzz/src/hb-set.h5
-rw-r--r--thirdparty/harfbuzz/src/hb-set.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.cc21
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.h4
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-shape.cc32
-rw-r--r--thirdparty/harfbuzz/src/hb-shaper.cc16
-rw-r--r--thirdparty/harfbuzz/src/hb-static.cc12
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff-common.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-input.cc81
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-input.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.cc364
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.hh33
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-repacker.cc15
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-repacker.h11
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.cc161
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.h18
-rw-r--r--thirdparty/harfbuzz/src/hb-ucd-table.hh5286
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh59
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.cc14
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.h8
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-vector.hh1
-rw-r--r--thirdparty/harfbuzz/src/hb-version.h6
-rw-r--r--thirdparty/harfbuzz/src/hb.hh5
-rw-r--r--thirdparty/icu4c/godot_data.json3
-rw-r--r--thirdparty/icu4c/i18n/scriptset.cpp313
-rw-r--r--thirdparty/icu4c/i18n/scriptset.h86
-rw-r--r--thirdparty/icu4c/i18n/ucln_in.cpp65
-rw-r--r--thirdparty/icu4c/i18n/ucln_in.h74
-rw-r--r--thirdparty/icu4c/i18n/unicode/uspoof.h1577
-rw-r--r--thirdparty/icu4c/i18n/uspoof.cpp839
-rw-r--r--thirdparty/icu4c/i18n/uspoof_impl.cpp959
-rw-r--r--thirdparty/icu4c/i18n/uspoof_impl.h343
-rw-r--r--thirdparty/icu4c/icudt71l.datbin4226000 -> 4271680 bytes
-rw-r--r--thirdparty/mbedtls/LICENSE205
-rw-r--r--thirdparty/mbedtls/apache-2.0.txt202
-rw-r--r--thirdparty/mbedtls/include/mbedtls/aes.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/aria.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/asn1.h12
-rw-r--r--thirdparty/mbedtls/include/mbedtls/bignum.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/blowfish.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/camellia.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/chachapoly.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/check_config.h49
-rw-r--r--thirdparty/mbedtls/include/mbedtls/config.h143
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ctr_drbg.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/debug.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecjpake.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecp.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/entropy.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/hkdf.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/hmac_drbg.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/oid.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pem.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pk.h75
-rw-r--r--thirdparty/mbedtls/include/mbedtls/platform.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/platform_time.h8
-rw-r--r--thirdparty/mbedtls/include/mbedtls/platform_util.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/rsa.h6
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl.h36
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_cache.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_cookie.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_internal.h44
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_ticket.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/version.h8
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509.h9
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509_crl.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509_crt.h15
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509_csr.h7
-rw-r--r--thirdparty/mbedtls/library/aes.c4
-rw-r--r--thirdparty/mbedtls/library/asn1write.c7
-rw-r--r--thirdparty/mbedtls/library/bignum.c4
-rw-r--r--thirdparty/mbedtls/library/cipher.c11
-rw-r--r--thirdparty/mbedtls/library/constant_time.c15
-rw-r--r--thirdparty/mbedtls/library/constant_time_internal.h7
-rw-r--r--thirdparty/mbedtls/library/ctr_drbg.c6
-rw-r--r--thirdparty/mbedtls/library/ecdh.c2
-rw-r--r--thirdparty/mbedtls/library/ecjpake.c2
-rw-r--r--thirdparty/mbedtls/library/ecp.c8
-rw-r--r--thirdparty/mbedtls/library/ecp_curves.c2
-rw-r--r--thirdparty/mbedtls/library/memory_buffer_alloc.c4
-rw-r--r--thirdparty/mbedtls/library/mps_common.h2
-rw-r--r--thirdparty/mbedtls/library/net_sockets.c2
-rw-r--r--thirdparty/mbedtls/library/pkparse.c10
-rw-r--r--thirdparty/mbedtls/library/rsa.c4
-rw-r--r--thirdparty/mbedtls/library/ssl_ciphersuites.c1
-rw-r--r--thirdparty/mbedtls/library/ssl_cli.c111
-rw-r--r--thirdparty/mbedtls/library/ssl_cookie.c3
-rw-r--r--thirdparty/mbedtls/library/ssl_msg.c131
-rw-r--r--thirdparty/mbedtls/library/ssl_srv.c99
-rw-r--r--thirdparty/mbedtls/library/ssl_ticket.c4
-rw-r--r--thirdparty/mbedtls/library/ssl_tls.c58
-rw-r--r--thirdparty/mbedtls/library/threading.c2
-rw-r--r--thirdparty/mbedtls/library/timing.c9
-rw-r--r--thirdparty/mbedtls/library/x509.c21
-rw-r--r--thirdparty/mbedtls/library/x509_crl.c2
-rw-r--r--thirdparty/mbedtls/library/x509_crt.c2
-rw-r--r--thirdparty/mbedtls/library/x509write_crt.c2
-rw-r--r--thirdparty/spirv-reflect/include/spirv/unified1/spirv.h46
-rw-r--r--thirdparty/spirv-reflect/patches/specialization-constants.patch34
-rw-r--r--thirdparty/spirv-reflect/spirv_reflect.c77
-rw-r--r--thirdparty/spirv-reflect/spirv_reflect.h11
2293 files changed, 133004 insertions, 72503 deletions
diff --git a/.clang-format b/.clang-format
index f7527b8927..1df6c35bfb 100644
--- a/.clang-format
+++ b/.clang-format
@@ -19,7 +19,7 @@ AllowAllParametersOfDeclarationOnNextLine: false
# AllowShortEnumsOnASingleLine: true
# AllowShortBlocksOnASingleLine: Never
# AllowShortCaseLabelsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: Inline
+# AllowShortFunctionsOnASingleLine: All
# AllowShortLambdasOnASingleLine: All
# AllowShortIfStatementsOnASingleLine: Never
# AllowShortLoopsOnASingleLine: false
diff --git a/.gitattributes b/.gitattributes
index 45ea6c25e8..8d2fb108ba 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -7,6 +7,8 @@ thirdparty/* linguist-vendored
* text=auto eol=lf
# Except for bat files, which are Windows only files
*.bat eol=crlf
+# And some test files where the EOL matters
+*.test.txt -text
# The above only works properly for Git 2.10+, so for older versions
# we need to manually list the binary files we don't want modified.
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index ebbbe345fd..e7e88e95d7 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -139,10 +139,10 @@ doc_classes/* @godotengine/documentation
# Platform
/platform/android/ @godotengine/android
-/platform/iphone/ @godotengine/ios
+/platform/ios/ @godotengine/ios
/platform/javascript/ @godotengine/html5
/platform/linuxbsd/ @godotengine/linux-bsd
-/platform/osx/ @godotengine/macos
+/platform/macos/ @godotengine/macos
/platform/uwp/ @godotengine/uwp
/platform/windows/ @godotengine/windows
diff --git a/.github/actions/godot-build/action.yml b/.github/actions/godot-build/action.yml
index 7af3516f71..75f3d9ab37 100644
--- a/.github/actions/godot-build/action.yml
+++ b/.github/actions/godot-build/action.yml
@@ -35,5 +35,5 @@ runs:
run: |
echo "Building with flags:" ${{ env.SCONSFLAGS }}
if ! ${{ inputs.tools }}; then rm -rf editor; fi # Ensure we don't include editor code.
- scons p=${{ inputs.platform }} target=${{ inputs.target }} tools=${{ inputs.tools }} tests=${{ inputs.tests }} --jobs=2 ${{ env.SCONSFLAGS }}
+ scons p=${{ inputs.platform }} target=${{ inputs.target }} tools=${{ inputs.tools }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }}
ls -l bin/
diff --git a/.github/workflows/ios_builds.yml b/.github/workflows/ios_builds.yml
index 40f091e234..03277edc1d 100644
--- a/.github/workflows/ios_builds.yml
+++ b/.github/workflows/ios_builds.yml
@@ -30,7 +30,7 @@ jobs:
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }}
- platform: iphone
+ platform: ios
target: release
tools: false
tests: false
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 3df4409041..0a0160326c 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -19,7 +19,7 @@ jobs:
fail-fast: false
matrix:
include:
- - name: Editor w/ Mono (target=release_debug, tools=yes, tests=yes)
+ - name: Editor w Mono (target=release_debug, tools=yes, tests=yes)
cache-name: linux-editor-mono
target: release_debug
tools: true
@@ -31,12 +31,12 @@ jobs:
proj-conv: true
artifact: true
- - name: Editor with doubles and GCC sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes)
+ - name: Editor with doubles and GCC sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes, linker=gold)
cache-name: linux-editor-double-sanitizers
target: debug
tools: true
tests: true
- sconsflags: float=64 use_asan=yes use_ubsan=yes
+ sconsflags: float=64 use_asan=yes use_ubsan=yes linker=gold
proj-test: true
# Can be turned off for PRs that intentionally break compat with godot-cpp,
# until both the upstream PR and the matching godot-cpp changes are merged.
@@ -46,12 +46,12 @@ jobs:
# Skip 2GiB artifact speeding up action.
artifact: false
- - name: Editor with clang sanitizers (target=debug, tools=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes)
+ - name: Editor with clang sanitizers (target=debug, tools=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)
cache-name: linux-editor-llvm-sanitizers
target: debug
tools: true
tests: true
- sconsflags: use_asan=yes use_ubsan=yes use_llvm=yes
+ sconsflags: use_asan=yes use_ubsan=yes use_llvm=yes linker=lld
bin: "./bin/godot.linuxbsd.tools.64.llvm.san"
build-mono: false
# Skip 2GiB artifact speeding up action.
@@ -88,7 +88,7 @@ jobs:
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev \
libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm xvfb wget unzip \
- llvm libspeechd-dev speech-dispatcher
+ llvm libspeechd-dev speech-dispatcher fontconfig libfontconfig-dev
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
@@ -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
@@ -168,12 +170,18 @@ jobs:
mv "regression-test-project-4.0" "test_project"
# Editor is quite complicated piece of software, so it is easy to introduce bug here
- - name: Open and close editor
+ - name: Open and close editor (Vulkan)
if: ${{ matrix.proj-test }}
run: |
VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy --editor --quit --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
+ - name: Open and close editor (GLES3)
+ if: ${{ matrix.proj-test }}
+ run: |
+ DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy --rendering-driver opengl3 --editor --quit --path test_project 2>&1 | tee sanitizers_log.txt || true
+ misc/scripts/check_ci_log.py sanitizers_log.txt
+
# Run test project
- name: Run project
if: ${{ matrix.proj-test }}
@@ -210,13 +218,14 @@ jobs:
if: ${{ matrix.godot-cpp-test }}
run: |
cd godot-cpp/test
- scons target=${{ matrix.target }} -j2
+ scons target=${{ matrix.target }}
cd ../..
- name: Prepare artifact
if: ${{ matrix.artifact }}
run: |
strip bin/godot.*
+ chmod +x bin/godot.*
- name: Upload artifact
uses: ./.github/actions/upload-artifact
diff --git a/.github/workflows/macos_builds.yml b/.github/workflows/macos_builds.yml
index 68623f2770..0ad0995bb7 100644
--- a/.github/workflows/macos_builds.yml
+++ b/.github/workflows/macos_builds.yml
@@ -24,7 +24,7 @@ jobs:
target: release_debug
tools: true
tests: true
- bin: "./bin/godot.osx.opt.tools.64"
+ bin: "./bin/godot.macos.opt.tools.64"
- name: Template (target=release, tools=no)
cache-name: macos-template
@@ -45,11 +45,15 @@ jobs:
- name: Setup python and scons
uses: ./.github/actions/godot-deps
+ - name: Setup Vulkan SDK
+ run: |
+ sh misc/scripts/install_vulkan_sdk_macos.sh
+
- name: Compilation
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }}
- platform: osx
+ platform: macos
target: ${{ matrix.target }}
tools: ${{ matrix.tools }}
tests: ${{ matrix.tests }}
@@ -58,11 +62,14 @@ jobs:
- name: Unit tests
if: ${{ matrix.tests }}
run: |
+ ${{ matrix.bin }} --version
+ ${{ matrix.bin }} --help
${{ matrix.bin }} --test
- name: Prepare artifact
run: |
strip bin/godot.*
+ chmod +x bin/godot.*
- name: Upload artifact
uses: ./.github/actions/upload-artifact
diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml
index d7d07b7022..81c7042663 100644
--- a/.github/workflows/static_checks.yml
+++ b/.github/workflows/static_checks.yml
@@ -37,6 +37,10 @@ jobs:
run: |
bash ./misc/scripts/clang_format.sh
+ - name: Header guards formatting checks (header_guards.sh)
+ run: |
+ bash ./misc/scripts/header_guards.sh
+
- name: Python style checks via black (black_format.sh)
run: |
bash ./misc/scripts/black_format.sh
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/.mailmap b/.mailmap
index 779c58460e..4f20e50219 100644
--- a/.mailmap
+++ b/.mailmap
@@ -40,6 +40,7 @@ FireForge <67974470+fire-forge@users.noreply.github.com> <isaacr.7.2005@gmail.co
foxydevloper <12120644+foxydevloper@users.noreply.github.com>
Fredia Huya-Kouadio <fhuyakou@gmail.com>
Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@google.com>
+Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@fb.com>
Geequlim <geequlim@gmail.com>
Gilles Roudiere <gilles.roudiere@gmail.com>
Gilles Roudiere <gilles.roudiere@gmail.com> <gilles.roudiere@laas.fr>
@@ -128,6 +129,7 @@ RaphaelHunter <raphael10241024@gmail.com> <raphael20141024@gmail.com>
Rémi Verschelde <rverschelde@gmail.com> <remi@verschelde.fr>
Rhody Lugo <rhodylugo@gmail.com> <rhodylugo@me.com>
Ricardo Subtil <ricasubtil@gmail.com>
+Rindbee <idleman@yeah.net>
Robin Hübner <profan@prfn.se> <robinhubner@gmail.com>
romulox_x <romulox_x@yahoo.com>
Ruslan Mustakov <r.mustakov@gmail.com> <ruslan.mustakov@xored.com>
@@ -139,6 +141,7 @@ Swarnim Arun <swarnimarun11@gmail.com>
Theo Hallenius <redsymbzone@hotmail.com>
Tomasz Chabora <kobewi4e@gmail.com>
Twarit <wtwarit@gmail.com>
+Vitika9 <vitika.program@gmail.com>
V.VamsiKrishna <vk@bsb.in> <vamsikrishna.v@gmail.com>
Wilhem Barbier <nounoursheureux@openmailbox.org> <wilhem.b@free.fr>
Wilhem Barbier <nounoursheureux@openmailbox.org> <schtroumps31@gmail.com>
diff --git a/AUTHORS.md b/AUTHORS.md
index 36be7c4501..a409a1cea5 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -52,7 +52,6 @@ name is available.
Bojidar Marinov (bojidar-bg)
Brian Semrau (briansemrau)
Bruno Lourenço (MadEqua)
- bruvzg
Cameron Reikes (creikey)
Camille Mohr-Daurat (pouleyKetchoupp)
Caner Demirer (cdemirer)
@@ -64,8 +63,8 @@ name is available.
Dana Olson (adolson)
Daniel J. Ramirez (djrm)
Daniel Rakos (aqnuep)
- dankan1890
Danil Alexeev (dalexeev)
+ dankan1890
David Cambré (Gallilus)
David Sichma (DavidSichma)
David Snopek (dsnopek)
@@ -85,7 +84,7 @@ name is available.
Eveline Jarosz (Marqin)
Fabian Mathews (supagu)
Fabio Alessandrelli (Faless)
- fabriceci
+ Fabrice Cipolla (fabriceci)
Ferenc Arn (tagcup)
FireForge (fire-forge)
follower
@@ -122,8 +121,8 @@ name is available.
Jérôme Gully (Nutriz)
Jia Jun Chai (SkyLucilfer)
Joan Fons Sanchez (JFonS)
- Johannes Witt (HaSa1002)
Johan Manuel (29jm)
+ Johannes Witt (HaSa1002)
Jordan Schidlowsky (winterpixelgames)
Joshua Grams (JoshuaGrams)
Juan Linietsky (reduz)
@@ -187,6 +186,7 @@ name is available.
Paul Batty (Paulb23)
Paul Joannon (paulloz)
Paul Trojahn (ptrojahn)
+ PÄvels NadtoÄajevs (bruvzg)
Paweł Fertyk (pfertyk)
Pawel Kowal (pkowal1982)
Pawel Lampe (Scony)
@@ -232,6 +232,7 @@ name is available.
Twarit Waikar (IronicallySerious)
Umang Kalra (theoway)
Vinzenz Feenstra (vinzenz)
+ Vitika Soni (Vitika9)
박한얼 (volzhs)
V. Vamsi Krishna (vkbsb)
Wilhem Barbier (nounoursheureux)
@@ -246,3 +247,4 @@ name is available.
Zak Stam (zaksnet)
Zher Huei Lee (leezh)
ZuBsPaCe
+ 风é’å±± (Rindbee)
diff --git a/DONORS.md b/DONORS.md
index a41cb750bd..74b12505be 100644
--- a/DONORS.md
+++ b/DONORS.md
@@ -21,27 +21,33 @@ generous deed immortalized in the next stable release of Godot Engine.
## Silver sponsors
+ Affray Interactive <https://scp.games/pandemic>
ASIFA-Hollywood <https://www.asifa-hollywood.org>
- ORE System <https://ore-system.com>
+ Playful Studios <https://playfulstudios.com>
+ Robot Gentleman <http://robotgentleman.com>
## Bronze sponsors
+ Basically Games
Brandon Lamb
Bri
Daniel Kaplan
Garry Newman
Gordon MacPherson
Hunter Dickson
+ Isaiah smith
+ Kenney <https://kenney.nl>
Kitcat490
Kyle Szklenski
Maxim Karsten
- Nik Rudenko
Moonwards <https://www.moonwards.com>
+ Nik Rudenko
TrampolineTales <https://trampolinetales.com>
## Mini sponsors
AD Ford
+ Albin Lundahl
Andres Hernandez
Andrew Bowen
Andrew Dunai
@@ -75,8 +81,10 @@ generous deed immortalized in the next stable release of Godot Engine.
Patrick Horn
Patrick Schmidt
Rami
- Relintai
+ René Habermann
Ronnie Cheng
+ Ryan Heath
+ Samantha
ShikadiGum
Slobodan Milnovic
Stephan Lanfermann
@@ -101,15 +109,14 @@ generous deed immortalized in the next stable release of Godot Engine.
David Snopek
Ed Morley
First Last
+ Frank Kurka
Hunter Jones
Jacobus Dens
- Jasper Brooks
Javier Roman
Joan Fons
Jonathan Wright
Jon Woodward
Karl Werf
- Kevin Vu
Klavdij Voncina
Maciej Pendolski
Manuele Finocchiaro
@@ -141,11 +148,12 @@ generous deed immortalized in the next stable release of Godot Engine.
Adam Mill
Adam Nakonieczny
Adam Nelson
+ Adam Stankiewicz
Adrian Adamiak
Alexander Erlemann
- Alexander J Maynard
Alex Khayrullin
alice gambrell
+ Alo Mis
Andrew Cunningham
Andrew Farr
Andriy
@@ -154,21 +162,19 @@ generous deed immortalized in the next stable release of Godot Engine.
Arch Henderson III
Arthur S. Muszynski
BasicIncomePlz
- BoomHorseHat
+ Brandon Hawkinson
BrizzleBrip
c64cosmin
Cameron Connolly
Charles Gray
Charlie Whitfield
- Chase Taranto
Chris Petrich
Chris Serino
- Craig Ostrin
+ Collin Rapp
Craig Scarborough
Craig Smith
Cristopher
CzechBlueBear
- D
DagobertDick
Daniel Hernández Alcojor
Daniel Tebbutt
@@ -176,12 +182,11 @@ generous deed immortalized in the next stable release of Godot Engine.
David Thomason
Daylon J Williams
Dennis Belfrage
- Dev To Be curious
Dimitri Nüscheler
Donn Eddy
Eric Brand
+ Eric Churches
Eugenio Hugo Salgüero Jáñez
- EXUREI
Felix Winterhalter
flesk
foxydevloper
@@ -200,22 +205,19 @@ generous deed immortalized in the next stable release of Godot Engine.
Horváth-Lázár Péter
Hu Hund
Hunter Barabas
- HurrieCrane
Jaap Marsman
Jamal Bencharki
James Couzens
- Jan Sælid
Jared
Jared White
Jean-Sébastien Ross
Jennifer Wilcox
- Jeremi Biernacki
Jesús Chicharro
Joel Fivat
Johnathan Kupferer
+ John Duplechain
John Stinson
Josef Stumpfegger
- Jose Malheiro
Jose Manuel Muñoz Perez
Joshie Sparks
Joshua Flores
@@ -225,6 +227,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Julian Todd
Juraj Móza
JUSTIN CARROLL
+ Justin Palmer
Kelteseth
Kevan
Khora
@@ -247,30 +250,27 @@ generous deed immortalized in the next stable release of Godot Engine.
Martin Soucek
matt
Matt Greene
+ Matthew Dana
Max Kryschi
- medecau
Michael Dürwald
Michael Policastro
- Miika Moilanen
MikadoSC
Mike Barbee
nate etan
- Nick Abousselam
- Nicola Cocchiaro
Nicolás Carrasco
+ Nikita Blizniuk
Oliver Dick
Oscar Campos
Paul Hocker
Paul Von Zimmerman
- Pavel Kotlyar
Pedro
Pete Goodwin
- Peter Richmond
Petr Malac
- PhaineOfCatz
- Rafał Michno
+ Petrus Prinsloo
+ Philip Woods
+ R
+ RaiRu
RAMupgrade
- Raymond Harris
Reilt
Rene Tailleur
Rhodochrone
@@ -278,39 +278,35 @@ generous deed immortalized in the next stable release of Godot Engine.
Rob
Robert McDermott
Rob McInroy
- Rocknight Studios
RodZilla
Romeo Disca
Ronnie Ashlock
Ronny Mühle
Russ
Ryan Breaker
- Ryan Heath
Ryan Miller
Ryan Scott
Samuel Hummerstone
Samuel Judd
- Sean Morgan
- Sebastian Hutter
+ schroedinger's possum
Serban Serafimescu
Sergey Fonaryov
- Sergey Minakov
Shishir Tandale
Sing Chun Lee
+ Skides
SKison
Song Junwoo
spacechase0
Stephan Hennion
Steven Landow
Stoned Xander
+ Sven Carstensen
Teslatech
+ Thomas Bjarnelöf
Thomas Kurz
- Tim Suess
Tobias Bocanegra
Tobias Raggl
- Todd Smith
Tom Glenn
- Tom Wor
Torbulous
toto bibi
Troy Kinsella
@@ -326,7 +322,6 @@ generous deed immortalized in the next stable release of Godot Engine.
## Silver donors
- 1D_Inc
Aaron Oldenburg
A. B.
Adam Brunnmeier
@@ -350,7 +345,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Alder Stefano
Alejandro Saucedo
AleMax
- Ales Jelovcan
Alessandro Senese
Alex Chan
Alex Clavelle
@@ -359,6 +353,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Allen Schade
Amar Šahinović
Andre Altmueller
+ Andrei Pufu
Andre Stackhouse
Andrew Groot
andrew james morris
@@ -367,7 +362,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Ano Nim
Anthony Avina
Anton Bouwer
- Antti Vesanen
Arch Toasty
Arda Erol
Arthur Brainville
@@ -380,7 +374,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Austin Miller
Azar Gurbanov
AzulCrescent
- b110110
Balázs Batári
Beau Seymour
Behzad Ghaffari
@@ -394,8 +387,9 @@ generous deed immortalized in the next stable release of Godot Engine.
Bjarne Voigtländer
Black Block
Blunderjack
- Brad Harms
+ BoiLudens
Bram
+ Brian
Brian Ford
Bronson Zgeb
Burney Waring
@@ -406,19 +400,19 @@ generous deed immortalized in the next stable release of Godot Engine.
Carlos Rios
Carl van der Geest
Casey
- Cassidy James
Chad Steadman
Checkpoint Charlie
Chris Jagusch
Chris Langford
Chris Ridenour
+ Christian Kaltenecker
Christian Mauduit
+ Christian Scholz
Christian Winter
Christoffer Dahlblom
Christophe Gagnier
- Christopher Chin
Christoph Woinke
- ClicheChloe
+ Codex404
Cody Parker
Conall O
Conner Lane
@@ -427,8 +421,11 @@ generous deed immortalized in the next stable release of Godot Engine.
Craig Post
CT
Cullen Canejo
+ cynwav
Dakota Watkins
+ Daniel H. Bahr
Danielle Cheney
+ Dare Looks
Daren Scot Wilson
Dave Walker
David Baker
@@ -437,6 +434,7 @@ generous deed immortalized in the next stable release of Godot Engine.
David Maziarka
David Rapisarda
Devin Carraway
+ Devin R
Dimitri Roche
Dmytro Korchynskyi
Dominik Wetzel
@@ -447,15 +445,14 @@ generous deed immortalized in the next stable release of Godot Engine.
Ducky
Duobix
Duodecimal
- Eduardo Teixeira
Edward Herbert
Edward Swartz
Egon Elbre
- eiki kanou
Elgenzay
Elias Nykrem
Elijah Anderson
Emerson MX
+ Ends
Ephemeral
Eric Stokes
Eric Walkingshaw
@@ -480,35 +477,29 @@ generous deed immortalized in the next stable release of Godot Engine.
George Marques
Gon Shibayama
Green Fox
- Greg Lincoln
- Greg Olson
Greyson Richey
Grid
Grominet
Guillaume Pham Ngoc
Guldoman
Guo Hongci
- gurehamu
Haplo
Hayden Foley
Heribert Hirth
+ Hylian Ensemble
Ian Richard Kunert
Ian Williams
IndustrialRobot
Inki Crow
iveks
- izzy kestrel
- Jackson Harmer
Jacob D
Jaguar
Jake D
- Jake Huxell
Jako Danar
James
James A F Manley
+ James Allen
James Gary
- James Guardino
- James Quincy
James Thomas
Jamie Massey
Janis Skuja
@@ -521,12 +512,14 @@ generous deed immortalized in the next stable release of Godot Engine.
Jeff Hungerford
Jeffrey Berube
Jennifer Graves
+ Jeramie
Jesse Dubay
- Jim Engstrand
+ João Pedro Braz
Joe Hurdle
Joe Klemmer
John Anders Stav
John Bruce
+ Johnny Deepman
Jonas
Jonas Arndt
Jonas Bernemann
@@ -537,12 +530,13 @@ generous deed immortalized in the next stable release of Godot Engine.
Jonathan Ellis
Jonathan G
Jonathan Turner
+ Jon Oakes
Jon Sully
Jordan West
Jordy Goodridge
Jorge Antunes
- Jorge Araya Navarro
Jose Francisco 'Yiro' Vera Girona
+ José Gabriel González
Joseph Catrambone
Josh P
Josh Taylor
@@ -557,6 +551,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Justin Hamilton
Justin Spedding
KaDokta
+ Kalydi Balázs
Karol Wojtasiuk (Drakonter)
Katsuomi Kobayashi
Keedong Park
@@ -577,17 +572,17 @@ generous deed immortalized in the next stable release of Godot Engine.
kycho
Kyle Burnett
Kyle Jacobs
- La diagonale du poulpe
Lasse le Dous
Laurent CHEA
Laurent Dethoor
Laxman Pradhan
+ Lech Rozanski
Leland Vakarian
Lemin
LEMMiNO
Leonardo Baumle
- Leonardo Dimano
Levi Lindsey
+ LF
Linus Lind Lundgren
Logan Apple
Ludovic DELVAL
@@ -601,7 +596,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Marcos Heitor Carvalho
Markie Music
Mark Jad
- Mark Malone
+ Mark Tyler
Markus Martin
Markus Michael Egger
Markus Strompen
@@ -617,9 +612,9 @@ generous deed immortalized in the next stable release of Godot Engine.
Maxime Santerre
Maxwell
McStuffings
- meinkush
Melissa Mears
Merlyn Morgan-Graham
+ Mert Kasar
Metal Demon 2000
mhilbrunner
Michael
@@ -643,7 +638,6 @@ generous deed immortalized in the next stable release of Godot Engine.
moulefrite
MrAZIE
Mrjemandem
- Nathan Fish
Nathaniel
neighty
Neil Blakey-Milner
@@ -654,7 +648,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Nicholas Orlowski
Nick Eldrenkamp
Nick Macholl
- Niclas Eriksen
+ Nico Greve
Nicolas Goll-Perrier
Nicolas Rosset
Nicolò Brigadoi Calamari
@@ -662,6 +656,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Nima Farid
Noel Billig
Noesis
+ obscuresteel
Okatima
Oleg Reva
Oliver Ambrose
@@ -678,7 +673,6 @@ generous deed immortalized in the next stable release of Godot Engine.
PaweÅ‚ Åyczkowski
Peter Höglund
Philip Ludington (MrPhil)
- Philip Woods
Pierre Caye
Pixel Archipel
pj
@@ -689,20 +683,17 @@ generous deed immortalized in the next stable release of Godot Engine.
pwab
RackBar Dingum
Rafa Laguna
- Raffaele Aramo
Ragnar Pettersson
Rainer Amler
Rammeow
- Recep Karademir
red1939
+ Relintai
Remi Rampin
Remtaine
Reneator
- René Habermann
Riccardo Marini
Richard Hayes
Richard Ivánek
- Richard Néveri
Riley
Robin Ward
RobotCritter
@@ -710,26 +701,25 @@ generous deed immortalized in the next stable release of Godot Engine.
Rodrigo Loli
Roger Smith
Roglozor
+ Roka
Roland RzÄ…sa
Roman Papush
Ronald Ho Hip (CrimsonZA)
- Ronan
Roy Scayged
+ Russ
Ryan Groom
+ Ryan Mueller
Rykk
- Sam Edson
Sammy Fischer
Sangeeth Pavithran
- schroedinger's possum
- Scott Longley
Sean Dee
Sebastian Michailidis
SeongWan Kim
Sessamekesh
+ Seth Drebitko
SeungJong k
Shaidak
Shane
- Shane Sicienski
Shane Spoor
Silver1063
simdee
@@ -746,11 +736,12 @@ generous deed immortalized in the next stable release of Godot Engine.
Soheib El-Harrache
Solene Waked
Sophie Winter
+ Space Hedgehog
+ Sparky
Squidgy
Squirrel
Stéphane Roussel
Stephen Rice
- Steve Cloete
Steven Drovie
summerblind
Sung soo Choi
@@ -758,10 +749,12 @@ generous deed immortalized in the next stable release of Godot Engine.
SxP
tadashi endo
Tarch
+ Techwizz
Terry
The Domis4
Theodore Lindsey
TheVoiceInMyHead
+ TheWint
Thibaut DECROMBECQUE
thomas
Thomas Bechtold
@@ -774,8 +767,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Tim Gleason
Tim Klein
Timothy B. MacDonald
- Title Plinsut
- TMoney
+ Tim Riley
Toadile
Tobias Bradtke
Tom Coxon
@@ -802,18 +794,20 @@ generous deed immortalized in the next stable release of Godot Engine.
Vitaliy Sapronenko
Vi Watch
Vladimir Savin
+ Vuli Nux
Wapiti .
- Watchinofoye
Wiley Thompson
William Bodin
William Edwards
William F Siqueira
+ Windvis
Woonki Moon
Wyatt Goodin
- yakcyll
+ Xananax
Yan Shi
- Yegor Smirnov
+ yust
Zach H.
+ Zekim
Zher Huei Lee
蕭惟å…
è²´å® å°æ¾
diff --git a/SConstruct b/SConstruct
index 28395227d2..d0d03bd8dc 100644
--- a/SConstruct
+++ b/SConstruct
@@ -138,6 +138,7 @@ env_base.__class__.CommandNoCache = methods.CommandNoCache
env_base.__class__.Run = methods.Run
env_base.__class__.disable_warnings = methods.disable_warnings
env_base.__class__.force_optimization_on_debug = methods.force_optimization_on_debug
+env_base.__class__.module_add_dependencies = methods.module_add_dependencies
env_base.__class__.module_check_dependencies = methods.module_check_dependencies
env_base["x86_libtheora_opt_gcc"] = False
@@ -195,7 +196,7 @@ opts.Add("extra_suffix", "Custom extra suffix added to the base filename of all
opts.Add(BoolVariable("vsproj", "Generate a Visual Studio solution", False))
opts.Add(BoolVariable("disable_3d", "Disable 3D nodes for a smaller executable", False))
opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and behaviors", False))
-opts.Add("disable_classes", "Disable given classes (comma separated)", "")
+opts.Add("build_feature_profile", "Path to a file containing a feature build profile", "")
opts.Add(BoolVariable("modules_enabled_by_default", "If no, disable all modules except ones explicitly enabled", True))
opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", True))
opts.Add("system_certs_path", "Use this path as SSL certificates default for editor (for package maintainers)", "")
@@ -260,7 +261,7 @@ else:
):
selected_platform = "linuxbsd"
elif sys.platform == "darwin":
- selected_platform = "osx"
+ selected_platform = "macos"
elif sys.platform == "win32":
selected_platform = "windows"
else:
@@ -272,6 +273,20 @@ else:
if selected_platform != "":
print("Automatically detected platform: " + selected_platform)
+if selected_platform in ["macos", "osx"]:
+ if selected_platform == "osx":
+ # Deprecated alias kept for compatibility.
+ print('Platform "osx" has been renamed to "macos" in Godot 4.0. Building for platform "macos".')
+ # Alias for convenience.
+ selected_platform = "macos"
+
+if selected_platform in ["ios", "iphone"]:
+ if selected_platform == "iphone":
+ # Deprecated alias kept for compatibility.
+ print('Platform "iphone" has been renamed to "ios" in Godot 4.0. Building for platform "ios".')
+ # Alias for convenience.
+ selected_platform = "ios"
+
if selected_platform in ["linux", "bsd", "x11"]:
if selected_platform == "x11":
# Deprecated alias kept for compatibility.
@@ -323,21 +338,27 @@ for path in module_search_paths:
# Add module options.
for name, path in modules_detected.items():
+ sys.path.insert(0, path)
+ import config
+
if env_base["modules_enabled_by_default"]:
enabled = True
-
- sys.path.insert(0, path)
- import config
-
try:
enabled = config.is_enabled()
except AttributeError:
pass
- sys.path.remove(path)
- sys.modules.pop("config")
else:
enabled = False
+ # Add module-specific options.
+ try:
+ for opt in config.get_opts(selected_platform):
+ opts.Add(opt)
+ except AttributeError:
+ pass
+
+ sys.path.remove(path)
+ sys.modules.pop("config")
opts.Add(BoolVariable("module_" + name + "_enabled", "Enable module '%s'" % (name,), enabled))
methods.write_modules(modules_detected)
@@ -399,6 +420,24 @@ if selected_platform in platform_list:
env = env_base.Clone()
+ # Default num_jobs to local cpu count if not user specified.
+ # SCons has a peculiarity where user-specified options won't be overridden
+ # by SetOption, so we can rely on this to know if we should use our default.
+ initial_num_jobs = env.GetOption("num_jobs")
+ altered_num_jobs = initial_num_jobs + 1
+ env.SetOption("num_jobs", altered_num_jobs)
+ if env.GetOption("num_jobs") == altered_num_jobs:
+ cpu_count = os.cpu_count()
+ if cpu_count is None:
+ print("Couldn't auto-detect CPU count to configure build parallelism. Specify it with the -j argument.")
+ else:
+ safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1
+ print(
+ "Auto-detected %d CPU cores available for build parallelism. Using %d cores by default. You can override it with the -j argument."
+ % (cpu_count, safer_cpu_count)
+ )
+ env.SetOption("num_jobs", safer_cpu_count)
+
if env["compiledb"]:
# Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later.
from SCons import __version__ as scons_raw_version
@@ -536,7 +575,7 @@ if selected_platform in platform_list:
)
# Apple LLVM versions differ from upstream LLVM version \o/, compare
# in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
- elif env["platform"] == "osx" or env["platform"] == "iphone":
+ elif env["platform"] == "macos" or env["platform"] == "ios":
vanilla = methods.is_vanilla_clang(env)
if vanilla and cc_version_major < 6:
print(
@@ -667,6 +706,7 @@ if selected_platform in platform_list:
sys.modules.pop("detect")
modules_enabled = OrderedDict()
+ env.module_dependencies = {}
env.module_icons_paths = []
env.doc_class_path = {}
@@ -678,6 +718,10 @@ if selected_platform in platform_list:
import config
if config.can_build(env, selected_platform):
+ # Disable it if a required dependency is missing.
+ if not env.module_check_dependencies(name):
+ continue
+
config.configure(env)
# Get doc classes paths (if present)
try:
@@ -700,6 +744,7 @@ if selected_platform in platform_list:
sys.modules.pop("config")
env.module_list = modules_enabled
+ methods.sort_module_list(env)
methods.update_version(env.module_version_string)
@@ -720,7 +765,27 @@ if selected_platform in platform_list:
if env["tools"]:
env.Append(CPPDEFINES=["TOOLS_ENABLED"])
- methods.write_disabled_classes(env["disable_classes"].split(","))
+
+ disabled_classes = []
+
+ if env["build_feature_profile"] != "":
+ print("Using build feature profile: " + env["build_feature_profile"])
+ import json
+
+ try:
+ ft = json.load(open(env["build_feature_profile"]))
+ if "disabled_classes" in ft:
+ disabled_classes = ft["disabled_classes"]
+ if "disabled_build_options" in ft:
+ dbo = ft["disabled_build_options"]
+ for c in dbo:
+ env[c] = dbo[c]
+ except:
+ print("Error opening feature build profile: " + env["build_feature_profile"])
+ Exit(255)
+
+ methods.write_disabled_classes(disabled_classes)
+
if env["disable_3d"]:
if env["tools"]:
print(
@@ -742,15 +807,6 @@ if selected_platform in platform_list:
if env["minizip"]:
env.Append(CPPDEFINES=["MINIZIP_ENABLED"])
- editor_module_list = []
- if env["tools"] and not env.module_check_dependencies("tools", editor_module_list):
- print(
- "Build option 'module_"
- + x
- + "_enabled=no' cannot be used with 'tools=yes' (editor), only with 'tools=no' (export template)."
- )
- Exit(255)
-
if not env["verbose"]:
methods.no_verbose(sys, env)
@@ -788,7 +844,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")
@@ -801,6 +858,9 @@ if selected_platform in platform_list:
# Microsoft Visual Studio Project Generation
if env["vsproj"]:
+ if os.name != "nt":
+ print("Error: The `vsproj` option is only usable on Windows with Visual Studio.")
+ Exit(255)
env["CPPPATH"] = [Dir(path) for path in env["CPPPATH"]]
methods.generate_vs_project(env, GetOption("num_jobs"))
methods.generate_cpp_hint_file("cpp.hint")
diff --git a/core/SCsub b/core/SCsub
index 3814c72877..d4462fa546 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", "ios", "linuxbsd", "macos"]:
# 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]
@@ -189,7 +188,6 @@ SConscript("os/SCsub")
SConscript("math/SCsub")
SConscript("crypto/SCsub")
SConscript("io/SCsub")
-SConscript("multiplayer/SCsub")
SConscript("debugger/SCsub")
SConscript("input/SCsub")
SConscript("variant/SCsub")
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 782d369ae6..1a6093869f 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -194,11 +194,11 @@ bool Engine::is_validation_layers_enabled() const {
}
void Engine::set_print_error_messages(bool p_enabled) {
- _print_error_enabled = p_enabled;
+ CoreGlobals::print_error_enabled = p_enabled;
}
bool Engine::is_printing_error_messages() const {
- return _print_error_enabled;
+ return CoreGlobals::print_error_enabled;
}
void Engine::add_singleton(const Singleton &p_singleton) {
@@ -246,6 +246,14 @@ void Engine::get_singletons(List<Singleton> *p_singletons) {
}
}
+String Engine::get_write_movie_path() const {
+ return write_movie_path;
+}
+
+void Engine::set_write_movie_path(const String &p_path) {
+ write_movie_path = p_path;
+}
+
void Engine::set_shader_cache_path(const String &p_path) {
shader_cache_path = p_path;
}
diff --git a/core/config/engine.h b/core/config/engine.h
index 82e3ee5487..68562643e7 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -76,6 +76,7 @@ private:
static Engine *singleton;
+ String write_movie_path;
String shader_cache_path;
public:
@@ -138,6 +139,9 @@ public:
Dictionary get_license_info() const;
String get_license_text() const;
+ void set_write_movie_path(const String &p_path);
+ String get_write_movie_path() const;
+
void set_shader_cache_path(const String &p_path);
String get_shader_cache_path() const;
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 7145e628c1..38db7f9190 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -488,7 +488,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// We need to test both possibilities as extensions for Linux binaries are optional
// (so both 'mygame.bin' and 'mygame' should be able to find 'mygame.pck').
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
if (!found) {
// Attempt to load PCK from macOS .app bundle resources.
found = _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_basename + ".pck")) || _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_filename + ".pck"));
@@ -511,8 +511,9 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
if (found) {
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
if (err == OK && !p_ignore_override) {
- // Load override from location of the executable.
- // Optional, we don't mind if it fails.
+ // Load overrides from the PCK and the executable location.
+ // Optional, we don't mind if either fails.
+ _load_settings_text("res://override.cfg");
_load_settings_text(exec_path.get_base_dir().plus_file("override.cfg"));
}
return err;
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index fc91f83462..56130134a0 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -46,8 +46,8 @@ namespace core_bind {
ResourceLoader *ResourceLoader::singleton = nullptr;
-Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads) {
- return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads);
+Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, CacheMode p_cache_mode) {
+ return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads, ResourceFormatLoader::CacheMode(p_cache_mode));
}
ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) {
@@ -83,6 +83,14 @@ Vector<String> ResourceLoader::get_recognized_extensions_for_type(const String &
return ret;
}
+void ResourceLoader::add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front) {
+ ::ResourceLoader::add_resource_format_loader(p_format_loader, p_at_front);
+}
+
+void ResourceLoader::remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader) {
+ ::ResourceLoader::remove_resource_format_loader(p_format_loader);
+}
+
void ResourceLoader::set_abort_on_missing_resources(bool p_abort) {
::ResourceLoader::set_abort_on_missing_resources(p_abort);
}
@@ -113,12 +121,14 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
}
void ResourceLoader::_bind_methods() {
- ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads", "cache_mode"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false), DEFVAL(CACHE_MODE_REUSE));
ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("load_threaded_get", "path"), &ResourceLoader::load_threaded_get);
ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "cache_mode"), &ResourceLoader::load, DEFVAL(""), DEFVAL(CACHE_MODE_REUSE));
ClassDB::bind_method(D_METHOD("get_recognized_extensions_for_type", "type"), &ResourceLoader::get_recognized_extensions_for_type);
+ ClassDB::bind_method(D_METHOD("add_resource_format_loader", "format_loader", "at_front"), &ResourceLoader::add_resource_format_loader, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("remove_resource_format_loader", "format_loader"), &ResourceLoader::remove_resource_format_loader);
ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources", "abort"), &ResourceLoader::set_abort_on_missing_resources);
ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &ResourceLoader::get_dependencies);
ClassDB::bind_method(D_METHOD("has_cached", "path"), &ResourceLoader::has_cached);
@@ -137,9 +147,9 @@ void ResourceLoader::_bind_methods() {
////// ResourceSaver //////
-Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t 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);
+Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, BitField<SaverFlags> p_flags) {
+ ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + p_path + "'.");
+ return ::ResourceSaver::save(p_resource, p_path, p_flags);
}
Vector<String> ResourceSaver::get_recognized_extensions(const Ref<Resource> &p_resource) {
@@ -153,20 +163,30 @@ Vector<String> ResourceSaver::get_recognized_extensions(const Ref<Resource> &p_r
return ret;
}
+void ResourceSaver::add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front) {
+ ::ResourceSaver::add_resource_format_saver(p_format_saver, p_at_front);
+}
+
+void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver) {
+ ::ResourceSaver::remove_resource_format_saver(p_format_saver);
+}
+
ResourceSaver *ResourceSaver::singleton = nullptr;
void ResourceSaver::_bind_methods() {
- ClassDB::bind_method(D_METHOD("save", "path", "resource", "flags"), &ResourceSaver::save, DEFVAL((uint32_t)FLAG_NONE));
+ ClassDB::bind_method(D_METHOD("save", "resource", "path", "flags"), &ResourceSaver::save, DEFVAL(""), DEFVAL((uint32_t)FLAG_NONE));
ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &ResourceSaver::get_recognized_extensions);
+ 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 //////
@@ -211,6 +231,14 @@ void OS::crash(const String &p_message) {
CRASH_NOW_MSG(p_message);
}
+Vector<String> OS::get_system_fonts() const {
+ return ::OS::get_singleton()->get_system_fonts();
+}
+
+String OS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
+ return ::OS::get_singleton()->get_system_font_path(p_font_name, p_bold, p_italic);
+}
+
String OS::get_executable_path() const {
return ::OS::get_singleton()->get_executable_path();
}
@@ -303,6 +331,39 @@ Vector<String> OS::get_cmdline_args() {
return cmdlinev;
}
+Vector<String> OS::get_cmdline_user_args() {
+ List<String> cmdline = ::OS::get_singleton()->get_cmdline_user_args();
+ Vector<String> cmdlinev;
+ for (const String &E : cmdline) {
+ cmdlinev.push_back(E);
+ }
+
+ return cmdlinev;
+}
+
+void OS::set_restart_on_exit(bool p_restart, const Vector<String> &p_restart_arguments) {
+ List<String> args_list;
+ for (const String &restart_argument : p_restart_arguments) {
+ args_list.push_back(restart_argument);
+ }
+
+ ::OS::get_singleton()->set_restart_on_exit(p_restart, args_list);
+}
+
+bool OS::is_restart_on_exit_set() const {
+ return ::OS::get_singleton()->is_restart_on_exit_set();
+}
+
+Vector<String> OS::get_restart_on_exit_arguments() const {
+ List<String> args = ::OS::get_singleton()->get_restart_on_exit_arguments();
+ Vector<String> args_vector;
+ for (List<String>::Element *E = args.front(); E; E = E->next()) {
+ args_vector.push_back(E->get());
+ }
+
+ return args_vector;
+}
+
String OS::get_locale() const {
return ::OS::get_singleton()->get_locale();
}
@@ -569,6 +630,8 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_processor_count"), &OS::get_processor_count);
ClassDB::bind_method(D_METHOD("get_processor_name"), &OS::get_processor_name);
+ ClassDB::bind_method(D_METHOD("get_system_fonts"), &OS::get_system_fonts);
+ ClassDB::bind_method(D_METHOD("get_system_font_path", "font_name", "bold", "italic"), &OS::get_system_font_path, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("create_process", "path", "arguments", "open_console"), &OS::create_process, DEFVAL(false));
@@ -584,6 +647,11 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_name"), &OS::get_name);
ClassDB::bind_method(D_METHOD("get_cmdline_args"), &OS::get_cmdline_args);
+ ClassDB::bind_method(D_METHOD("get_cmdline_user_args"), &OS::get_cmdline_user_args);
+
+ ClassDB::bind_method(D_METHOD("set_restart_on_exit", "restart", "arguments"), &OS::set_restart_on_exit, DEFVAL(Vector<String>()));
+ ClassDB::bind_method(D_METHOD("is_restart_on_exit_set"), &OS::is_restart_on_exit_set);
+ ClassDB::bind_method(D_METHOD("get_restart_on_exit_arguments"), &OS::get_restart_on_exit_arguments);
ClassDB::bind_method(D_METHOD("delay_usec", "usec"), &OS::delay_usec);
ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &OS::delay_msec);
@@ -865,6 +933,7 @@ Dictionary Geometry2D::make_atlas(const Vector<Size2> &p_rects) {
void Geometry2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &Geometry2D::is_point_in_circle);
+ ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_position", "circle_radius"), &Geometry2D::segment_intersects_circle);
ClassDB::bind_method(D_METHOD("segment_intersects_segment", "from_a", "to_a", "from_b", "to_b"), &Geometry2D::segment_intersects_segment);
ClassDB::bind_method(D_METHOD("line_intersects_line", "from_a", "dir_a", "from_b", "dir_b"), &Geometry2D::line_intersects_line);
@@ -1197,19 +1266,13 @@ Vector<uint8_t> File::get_buffer(int64_t p_length) const {
return data;
}
-String File::get_as_text() const {
+String File::get_as_text(bool p_skip_cr) const {
ERR_FAIL_COND_V_MSG(f.is_null(), String(), "File must be opened before use, or is lacking read-write permission.");
- String text;
uint64_t original_pos = f->get_position();
const_cast<FileAccess *>(*f)->seek(0);
- String l = get_line();
- while (!eof_reached()) {
- text += l + "\n";
- l = get_line();
- }
- text += l;
+ String text = f->get_as_utf8_string(p_skip_cr);
const_cast<FileAccess *>(*f)->seek(original_pos);
@@ -1406,7 +1469,7 @@ void File::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer", "length"), &File::get_buffer);
ClassDB::bind_method(D_METHOD("get_line"), &File::get_line);
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &File::get_csv_line, DEFVAL(","));
- ClassDB::bind_method(D_METHOD("get_as_text"), &File::get_as_text);
+ ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &File::get_as_text, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_md5", "path"), &File::get_md5);
ClassDB::bind_method(D_METHOD("get_sha256", "path"), &File::get_sha256);
ClassDB::bind_method(D_METHOD("is_big_endian"), &File::is_big_endian);
@@ -1820,13 +1883,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);
+ t->target_callable.callp(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();
@@ -2265,6 +2329,10 @@ bool Engine::is_editor_hint() const {
return ::Engine::get_singleton()->is_editor_hint();
}
+String Engine::get_write_movie_path() const {
+ return ::Engine::get_singleton()->get_write_movie_path();
+}
+
void Engine::set_print_error_messages(bool p_enabled) {
::Engine::get_singleton()->set_print_error_messages(p_enabled);
}
@@ -2314,6 +2382,8 @@ void Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_editor_hint"), &Engine::is_editor_hint);
+ ClassDB::bind_method(D_METHOD("get_write_movie_path"), &Engine::get_write_movie_path);
+
ClassDB::bind_method(D_METHOD("set_print_error_messages", "enabled"), &Engine::set_print_error_messages);
ClassDB::bind_method(D_METHOD("is_printing_error_messages"), &Engine::is_printing_error_messages);
@@ -2397,7 +2467,7 @@ Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Arra
const Variant *args[2] = { &cmd, &data };
Variant retval;
Callable::CallError err;
- capture.call(args, 2, retval, err);
+ capture.callp(args, 2, retval, err);
ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, FAILED, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(capture, args, 2, err));
ERR_FAIL_COND_V_MSG(retval.get_type() != Variant::BOOL, FAILED, "Error calling 'capture' to callable: " + String(capture) + ". Return type is not bool.");
r_captured = retval;
diff --git a/core/core_bind.h b/core/core_bind.h
index ec9bcdbc02..98bf34e07d 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -71,12 +71,14 @@ public:
static ResourceLoader *get_singleton() { return singleton; }
- Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false);
+ Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, CacheMode p_cache_mode = CACHE_MODE_REUSE);
ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = Array());
Ref<Resource> load_threaded_get(const String &p_path);
Ref<Resource> load(const String &p_path, const String &p_type_hint = "", CacheMode p_cache_mode = CACHE_MODE_REUSE);
Vector<String> get_recognized_extensions_for_type(const String &p_type);
+ void add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front);
+ void remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader);
void set_abort_on_missing_resources(bool p_abort);
PackedStringArray get_dependencies(const String &p_path);
bool has_cached(const String &p_path);
@@ -107,8 +109,10 @@ 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 Ref<Resource> &p_resource, const String &p_path, 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);
ResourceSaver() { singleton = this; }
};
@@ -166,6 +170,8 @@ public:
void alert(const String &p_alert, const String &p_title = "ALERT!");
void crash(const String &p_message);
+ Vector<String> get_system_fonts() const;
+ String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const;
String get_executable_path() const;
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false, bool p_open_console = false);
int create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console = false);
@@ -176,12 +182,17 @@ public:
bool is_process_running(int p_pid) const;
int get_process_id() const;
+ void set_restart_on_exit(bool p_restart, const Vector<String> &p_restart_arguments = Vector<String>());
+ bool is_restart_on_exit_set() const;
+ Vector<String> get_restart_on_exit_arguments() const;
+
bool has_environment(const String &p_var) const;
String get_environment(const String &p_var) const;
bool set_environment(const String &p_var, const String &p_value) const;
String get_name() const;
Vector<String> get_cmdline_args();
+ Vector<String> get_cmdline_user_args();
String get_locale() const;
String get_locale_language() const;
@@ -405,7 +416,7 @@ public:
Vector<uint8_t> get_buffer(int64_t p_length) const; // Get an array of bytes.
String get_line() const;
Vector<String> get_csv_line(const String &p_delim = ",") const;
- String get_as_text() const;
+ String get_as_text(bool p_skip_cr = false) const;
String get_md5(const String &p_path) const;
String get_sha256(const String &p_path) const;
@@ -670,6 +681,9 @@ public:
void set_editor_hint(bool p_enabled);
bool is_editor_hint() const;
+ // `set_write_movie_path()` is not exposed to the scripting API as changing it at run-time has no effect.
+ String get_write_movie_path() const;
+
void set_print_error_messages(bool p_enabled);
bool is_printing_error_messages() const;
@@ -715,7 +729,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/core_constants.cpp b/core/core_constants.cpp
index 24d8b0af6e..dc0ab72a86 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -31,7 +31,6 @@
#include "core_constants.h"
#include "core/input/input_event.h"
-#include "core/multiplayer/multiplayer.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
#include "core/variant/variant.h"
@@ -570,9 +569,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM_SUGGESTION);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXP_EASING);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LENGTH);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LINK);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_KEY_ACCEL);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FLAGS);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_RENDER);
@@ -620,15 +617,14 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORAGE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NETWORK);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_HELPER);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKABLE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKED);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_INTERNATIONALIZED);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_GROUP);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CATEGORY);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SUBGROUP);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CLASS_IS_BITFIELD);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NO_INSTANCE_STATE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE);
@@ -656,25 +652,13 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NORMAL);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_EDITOR);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NOSCRIPT);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_CONST);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_REVERSE);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL);
- BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_FROM_SCRIPT);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VARARG);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_STATIC);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_OBJECT_CORE);
BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT);
- // rpc
- BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_DISABLED", Multiplayer::RPC_MODE_DISABLED);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_ANY_PEER", Multiplayer::RPC_MODE_ANY_PEER);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_AUTHORITY", Multiplayer::RPC_MODE_AUTHORITY);
-
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE", Multiplayer::TRANSFER_MODE_UNRELIABLE);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE_ORDERED", Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_RELIABLE", Multiplayer::TRANSFER_MODE_RELIABLE);
-
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT", Variant::INT);
@@ -687,11 +671,14 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3", Variant::VECTOR3);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3I", Variant::VECTOR3I);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM2D", Variant::TRANSFORM2D);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR4", Variant::VECTOR4);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR4I", Variant::VECTOR4I);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PLANE", Variant::PLANE);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_QUATERNION", Variant::QUATERNION);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_AABB", Variant::AABB);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BASIS", Variant::BASIS);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM3D", Variant::TRANSFORM3D);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PROJECTION", Variant::PROJECTION);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_COLOR", Variant::COLOR);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING_NAME", Variant::STRING_NAME);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NODE_PATH", Variant::NODE_PATH);
diff --git a/core/core_constants.h b/core/core_constants.h
index d5b3b156b2..5e05b7a931 100644
--- a/core/core_constants.h
+++ b/core/core_constants.h
@@ -42,4 +42,4 @@ public:
static int64_t get_global_constant_value(int p_idx);
};
-#endif // GLOBAL_CONSTANTS_H
+#endif // CORE_CONSTANTS_H
diff --git a/core/core_globals.cpp b/core/core_globals.cpp
new file mode 100644
index 0000000000..45297b459f
--- /dev/null
+++ b/core/core_globals.cpp
@@ -0,0 +1,35 @@
+/*************************************************************************/
+/* core_globals.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 "core_globals.h"
+
+bool CoreGlobals::leak_reporting_enabled = true;
+bool CoreGlobals::print_line_enabled = true;
+bool CoreGlobals::print_error_enabled = true;
diff --git a/servers/rendering/renderer_thread_pool.h b/core/core_globals.h
index 4626490d32..c5e614dc0a 100644
--- a/servers/rendering/renderer_thread_pool.h
+++ b/core/core_globals.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_thread_pool.h */
+/* core_globals.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,18 +28,17 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERERTHREADPOOL_H
-#define RENDERERTHREADPOOL_H
+#ifndef CORE_GLOBALS_H
+#define CORE_GLOBALS_H
-#include "core/templates/thread_work_pool.h"
+// Home for state needed from global functions
+// that cannot be stored in Engine or OS due to e.g. circular includes
-class RendererThreadPool {
+class CoreGlobals {
public:
- ThreadWorkPool thread_work_pool;
-
- static RendererThreadPool *singleton;
- RendererThreadPool();
- ~RendererThreadPool();
+ static bool leak_reporting_enabled;
+ static bool print_line_enabled;
+ static bool print_error_enabled;
};
-#endif // RENDERERTHREADPOOL_H
+#endif // CORE_GLOBALS_H
diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp
index d0fd4feaa5..a164eb7a57 100644
--- a/core/crypto/crypto.cpp
+++ b/core/crypto/crypto.cpp
@@ -185,7 +185,7 @@ String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const
return "";
}
-Error ResourceFormatSaverCrypto::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaverCrypto::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Error err;
Ref<X509Certificate> cert = p_resource;
Ref<CryptoKey> key = p_resource;
diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h
index fb4f7dd88f..10c9564ad9 100644
--- a/core/crypto/crypto.h
+++ b/core/crypto/crypto.h
@@ -125,7 +125,7 @@ public:
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
public:
- virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
virtual bool recognize(const Ref<Resource> &p_resource) const;
};
diff --git a/core/crypto/crypto_core.h b/core/crypto/crypto_core.h
index eacef268cc..008e9e92b5 100644
--- a/core/crypto/crypto_core.h
+++ b/core/crypto/crypto_core.h
@@ -115,4 +115,5 @@ public:
static Error sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]);
static Error sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]);
};
+
#endif // CRYPTO_CORE_H
diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h
index 378c3af8aa..751e8a6371 100644
--- a/core/debugger/debugger_marshalls.h
+++ b/core/debugger/debugger_marshalls.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef DEBUGGER_MARSHARLLS_H
-#define DEBUGGER_MARSHARLLS_H
+#ifndef DEBUGGER_MARSHALLS_H
+#define DEBUGGER_MARSHALLS_H
#include "core/object/script_language.h"
@@ -69,4 +69,4 @@ struct DebuggerMarshalls {
};
};
-#endif // DEBUGGER_MARSHARLLS_H
+#endif // DEBUGGER_MARSHALLS_H
diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp
index 263c75760b..d495a8ee20 100644
--- a/core/debugger/engine_debugger.cpp
+++ b/core/debugger/engine_debugger.cpp
@@ -43,6 +43,8 @@ HashMap<StringName, EngineDebugger::Profiler> EngineDebugger::profilers;
HashMap<StringName, EngineDebugger::Capture> EngineDebugger::captures;
HashMap<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols;
+void (*EngineDebugger::allow_focus_steal_fn)();
+
void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) {
ERR_FAIL_COND_MSG(profilers.has(p_name), "Profiler already registered: " + p_name);
profilers.insert(p_name, p_func);
@@ -133,7 +135,7 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks,
singleton->poll_events(true);
}
-void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints) {
+void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints, void (*p_allow_focus_steal_fn)()) {
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more.
if (p_uri.is_empty()) {
return;
@@ -174,6 +176,8 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve
singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp));
}
+
+ allow_focus_steal_fn = p_allow_focus_steal_fn;
}
void EngineDebugger::deinitialize() {
diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h
index a8a791f9b0..236d5e5f63 100644
--- a/core/debugger/engine_debugger.h
+++ b/core/debugger/engine_debugger.h
@@ -100,13 +100,15 @@ protected:
static HashMap<StringName, Capture> captures;
static HashMap<String, CreatePeerFunc> protocols;
+ static void (*allow_focus_steal_fn)();
+
public:
_FORCE_INLINE_ static EngineDebugger *get_singleton() { return singleton; }
_FORCE_INLINE_ static bool is_active() { return singleton != nullptr && script_debugger != nullptr; }
_FORCE_INLINE_ static ScriptDebugger *get_script_debugger() { return script_debugger; };
- static void initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints);
+ static void initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints, void (*p_allow_focus_steal_fn)());
static void deinitialize();
static void register_profiler(const StringName &p_name, const Profiler &p_profiler);
static void unregister_profiler(const StringName &p_name);
diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp
index 06e08081e9..58d239ccb9 100644
--- a/core/debugger/local_debugger.cpp
+++ b/core/debugger/local_debugger.cpp
@@ -31,7 +31,7 @@
#include "local_debugger.h"
#include "core/debugger/script_debugger.h"
-#include "scene/main/scene_tree.h"
+#include "core/os/os.h"
struct LocalDebugger::ScriptsProfiler {
struct ProfileInfoSort {
@@ -273,7 +273,10 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
script_debugger->set_depth(-1);
script_debugger->set_lines_left(-1);
- SceneTree::get_singleton()->quit();
+ MainLoop *main_loop = OS::get_singleton()->get_main_loop();
+ if (main_loop->get_class() == "SceneTree") {
+ main_loop->call("quit");
+ }
break;
} else if (line.begins_with("delete")) {
if (line.get_slice_count(" ") <= 1) {
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index 508a71ece9..23ee977df4 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -297,6 +297,14 @@ void RemoteDebugger::flush_output() {
}
strings.push_back(output_string.message);
types.push_back(MESSAGE_TYPE_ERROR);
+ } else if (output_string.type == MESSAGE_TYPE_LOG_RICH) {
+ if (!joined_log_strings.is_empty()) {
+ strings.push_back(String("\n").join(joined_log_strings));
+ types.push_back(MESSAGE_TYPE_LOG_RICH);
+ joined_log_strings.clear();
+ }
+ strings.push_back(output_string.message);
+ types.push_back(MESSAGE_TYPE_LOG_RICH);
} else {
joined_log_strings.push_back(output_string.message);
}
@@ -444,6 +452,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
msg.push_back(error_str);
ERR_FAIL_COND(!script_lang);
msg.push_back(script_lang->debug_get_stack_level_count() > 0);
+ if (allow_focus_steal_fn) {
+ allow_focus_steal_fn();
+ }
send_message("debug_enter", msg);
Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode();
diff --git a/core/doc_data.cpp b/core/doc_data.cpp
index 1e72ad1090..df86cd1dc2 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());
@@ -115,6 +115,31 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met
p_method.name = p_methodinfo.name;
p_method.description = p_desc;
+ if (p_methodinfo.flags & METHOD_FLAG_VIRTUAL) {
+ p_method.qualifiers = "virtual";
+ }
+
+ if (p_methodinfo.flags & METHOD_FLAG_CONST) {
+ if (!p_method.qualifiers.is_empty()) {
+ p_method.qualifiers += " ";
+ }
+ p_method.qualifiers += "const";
+ }
+
+ if (p_methodinfo.flags & METHOD_FLAG_VARARG) {
+ if (!p_method.qualifiers.is_empty()) {
+ p_method.qualifiers += " ";
+ }
+ p_method.qualifiers += "vararg";
+ }
+
+ if (p_methodinfo.flags & METHOD_FLAG_STATIC) {
+ if (!p_method.qualifiers.is_empty()) {
+ p_method.qualifiers += " ";
+ }
+ p_method.qualifiers += "static";
+ }
+
return_doc_from_retinfo(p_method, p_methodinfo.return_val);
for (int i = 0; i < p_methodinfo.arguments.size(); i++) {
@@ -123,7 +148,7 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met
int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size());
if (default_arg_index >= 0) {
Variant default_arg = p_methodinfo.default_arguments[default_arg_index];
- argument.default_value = default_arg.get_construct_string();
+ argument.default_value = default_arg.get_construct_string().replace("\n", "");
}
p_method.arguments.push_back(argument);
}
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/error/error_macros.cpp b/core/error/error_macros.cpp
index 8add4b9a3a..f71a642b23 100644
--- a/core/error/error_macros.cpp
+++ b/core/error/error_macros.cpp
@@ -83,7 +83,13 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
// Main error printing function.
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
- OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type);
+ if (OS::get_singleton()) {
+ OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type);
+ } else {
+ // Fallback if errors happen before OS init or after it's destroyed.
+ const char *err_details = (p_message && *p_message) ? p_message : p_error;
+ fprintf(stderr, "ERROR: %s\n at: %s (%s:%i)\n", err_details, p_function, p_file, p_line);
+ }
_global_lock();
ErrorHandlerList *l = error_handler_list;
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 9d846f87c2..867b1fc637 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -46,9 +46,12 @@ 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))) {
return String("enum::") + String(p_info.class_name);
}
+ if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_BITFIELD))) {
+ return String("bitfield::") + String(p_info.class_name);
+ }
if (p_info.class_name != StringName()) {
return p_info.class_name;
}
@@ -128,11 +131,14 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
{ Variant::VECTOR3, vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
{ Variant::VECTOR3I, 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) },
{ Variant::TRANSFORM2D, 6 * sizeof(float), 6 * sizeof(float), 6 * sizeof(double), 6 * sizeof(double) },
+ { Variant::VECTOR4, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
+ { Variant::VECTOR4I, 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t) },
{ Variant::PLANE, (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(double), (vec3_elems + 1) * sizeof(double) },
{ Variant::QUATERNION, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
{ Variant::AABB, (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(double), (vec3_elems * 2) * sizeof(double) },
{ Variant::BASIS, (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) },
{ Variant::TRANSFORM3D, (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(double), (vec3_elems * 4) * sizeof(double) },
+ { Variant::PROJECTION, 4 * 4 * sizeof(float), 4 * 4 * sizeof(float), 4 * 4 * sizeof(double), 4 * 4 * sizeof(double) },
{ Variant::COLOR, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float) },
{ Variant::STRING_NAME, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
{ Variant::NODE_PATH, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
@@ -166,11 +172,14 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
static_assert(type_size_array[Variant::VECTOR3][sizeof(void *)] == sizeof(Vector3), "Size of Vector3 mismatch");
static_assert(type_size_array[Variant::VECTOR3I][sizeof(void *)] == sizeof(Vector3i), "Size of Vector3i mismatch");
static_assert(type_size_array[Variant::TRANSFORM2D][sizeof(void *)] == sizeof(Transform2D), "Size of Transform2D mismatch");
+ static_assert(type_size_array[Variant::VECTOR4][sizeof(void *)] == sizeof(Vector4), "Size of Vector4 mismatch");
+ static_assert(type_size_array[Variant::VECTOR4I][sizeof(void *)] == sizeof(Vector4i), "Size of Vector4i mismatch");
static_assert(type_size_array[Variant::PLANE][sizeof(void *)] == sizeof(Plane), "Size of Plane mismatch");
static_assert(type_size_array[Variant::QUATERNION][sizeof(void *)] == sizeof(Quaternion), "Size of Quaternion mismatch");
static_assert(type_size_array[Variant::AABB][sizeof(void *)] == sizeof(AABB), "Size of AABB mismatch");
static_assert(type_size_array[Variant::BASIS][sizeof(void *)] == sizeof(Basis), "Size of Basis mismatch");
static_assert(type_size_array[Variant::TRANSFORM3D][sizeof(void *)] == sizeof(Transform3D), "Size of Transform3D mismatch");
+ static_assert(type_size_array[Variant::PROJECTION][sizeof(void *)] == sizeof(Projection), "Size of Projection mismatch");
static_assert(type_size_array[Variant::COLOR][sizeof(void *)] == sizeof(Color), "Size of Color mismatch");
static_assert(type_size_array[Variant::STRING_NAME][sizeof(void *)] == sizeof(StringName), "Size of StringName mismatch");
static_assert(type_size_array[Variant::NODE_PATH][sizeof(void *)] == sizeof(NodePath), "Size of NodePath mismatch");
@@ -253,6 +262,14 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
{ Variant::TRANSFORM2D, "x", 0, 0, 0, 0 },
{ Variant::TRANSFORM2D, "y", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
{ Variant::TRANSFORM2D, "origin", 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
+ { Variant::VECTOR4, "x", 0, 0, 0, 0 },
+ { Variant::VECTOR4, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
+ { Variant::VECTOR4, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
+ { Variant::VECTOR4, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) },
+ { Variant::VECTOR4I, "x", 0, 0, 0, 0 },
+ { Variant::VECTOR4I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
+ { Variant::VECTOR4I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
+ { Variant::VECTOR4I, "w", 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) },
{ Variant::PLANE, "normal", 0, 0, 0, 0 },
{ Variant::PLANE, "d", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
{ Variant::QUATERNION, "x", 0, 0, 0, 0 },
@@ -665,6 +682,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/extension/extension_api_dump.h b/core/extension/extension_api_dump.h
index 7346e182f1..1bc455ea67 100644
--- a/core/extension/extension_api_dump.h
+++ b/core/extension/extension_api_dump.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef API_DUMP_H
-#define API_DUMP_H
+#ifndef EXTENSION_API_DUMP_H
+#define EXTENSION_API_DUMP_H
#include "core/extension/native_extension.h"
@@ -42,4 +42,4 @@ public:
};
#endif
-#endif // API_DUMP_H
+#endif // EXTENSION_API_DUMP_H
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index 58103e3af3..ef0b590030 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -344,6 +344,10 @@ static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_con
return VariantTypeConstructor<Vector3i>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_TRANSFORM2D:
return VariantTypeConstructor<Transform2D>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_VECTOR4:
+ return VariantTypeConstructor<Vector4>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_VECTOR4I:
+ return VariantTypeConstructor<Vector4i>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PLANE:
return VariantTypeConstructor<Plane>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_QUATERNION:
@@ -354,6 +358,8 @@ static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_con
return VariantTypeConstructor<Basis>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_TRANSFORM3D:
return VariantTypeConstructor<Transform3D>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PROJECTION:
+ return VariantTypeConstructor<Projection>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_COLOR:
return VariantTypeConstructor<Color>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_STRING_NAME:
@@ -421,6 +427,10 @@ static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_con
return VariantTypeConstructor<Vector3i>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_TRANSFORM2D:
return VariantTypeConstructor<Transform2D>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_VECTOR4:
+ return VariantTypeConstructor<Vector4>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_VECTOR4I:
+ return VariantTypeConstructor<Vector4i>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PLANE:
return VariantTypeConstructor<Plane>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_QUATERNION:
@@ -431,6 +441,8 @@ static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_con
return VariantTypeConstructor<Basis>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_TRANSFORM3D:
return VariantTypeConstructor<Transform3D>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PROJECTION:
+ return VariantTypeConstructor<Projection>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_COLOR:
return VariantTypeConstructor<Color>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_STRING_NAME:
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index ccd6fb0f7e..041a6e5112 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -67,11 +67,14 @@ typedef enum {
GDNATIVE_VARIANT_TYPE_VECTOR3,
GDNATIVE_VARIANT_TYPE_VECTOR3I,
GDNATIVE_VARIANT_TYPE_TRANSFORM2D,
+ GDNATIVE_VARIANT_TYPE_VECTOR4,
+ GDNATIVE_VARIANT_TYPE_VECTOR4I,
GDNATIVE_VARIANT_TYPE_PLANE,
GDNATIVE_VARIANT_TYPE_QUATERNION,
GDNATIVE_VARIANT_TYPE_AABB,
GDNATIVE_VARIANT_TYPE_BASIS,
GDNATIVE_VARIANT_TYPE_TRANSFORM3D,
+ GDNATIVE_VARIANT_TYPE_PROJECTION,
/* misc types */
GDNATIVE_VARIANT_TYPE_COLOR,
@@ -252,13 +255,10 @@ typedef void *GDNativeExtensionClassLibraryPtr;
typedef enum {
GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL = 1,
GDNATIVE_EXTENSION_METHOD_FLAG_EDITOR = 2,
- GDNATIVE_EXTENSION_METHOD_FLAG_NOSCRIPT = 4,
- GDNATIVE_EXTENSION_METHOD_FLAG_CONST = 8,
- GDNATIVE_EXTENSION_METHOD_FLAG_REVERSE = 16, /* used for events */
- GDNATIVE_EXTENSION_METHOD_FLAG_VIRTUAL = 32,
- GDNATIVE_EXTENSION_METHOD_FLAG_FROM_SCRIPT = 64,
- GDNATIVE_EXTENSION_METHOD_FLAG_VARARG = 128,
- GDNATIVE_EXTENSION_METHOD_FLAG_STATIC = 256,
+ GDNATIVE_EXTENSION_METHOD_FLAG_CONST = 4,
+ GDNATIVE_EXTENSION_METHOD_FLAG_VIRTUAL = 8,
+ GDNATIVE_EXTENSION_METHOD_FLAG_VARARG = 16,
+ GDNATIVE_EXTENSION_METHOD_FLAG_STATIC = 32,
GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT = GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL,
} GDNativeExtensionClassMethodFlags;
@@ -540,7 +540,7 @@ typedef struct {
void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
- void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
+ void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield);
void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
@@ -582,4 +582,4 @@ typedef GDNativeBool (*GDNativeInitializationFunction)(const GDNativeInterface *
}
#endif
-#endif
+#endif // GDNATIVE_INTERFACE_H
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index ebdfa20725..b69859b441 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -55,14 +55,7 @@ protected:
virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
GDNativePropertyInfo pinfo;
get_argument_info_func(method_userdata, p_arg, &pinfo);
- PropertyInfo ret;
- ret.type = Variant::Type(pinfo.type);
- ret.name = pinfo.name;
- ret.class_name = pinfo.class_name;
- ret.hint = PropertyHint(pinfo.hint);
- ret.usage = pinfo.usage;
- ret.class_name = pinfo.class_name;
- return ret;
+ return PropertyInfo(pinfo);
}
public:
@@ -189,7 +182,7 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl
ClassDB::bind_method_custom(class_name, method);
}
-void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value) {
+void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
@@ -197,23 +190,18 @@ void NativeExtension::_register_extension_class_integer_constant(const GDNativeE
//Extension *extension = &self->extension_classes[class_name];
- ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value);
+ ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value, p_is_bitfield);
}
void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'.");
+ String property_name = p_info->name;
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + property_name + "' for unexisting class '" + class_name + "'.");
//Extension *extension = &self->extension_classes[class_name];
- PropertyInfo pinfo;
- pinfo.type = Variant::Type(p_info->type);
- pinfo.name = p_info->name;
- pinfo.class_name = p_info->class_name;
- pinfo.hint = PropertyHint(p_info->hint);
- pinfo.hint_string = p_info->hint_string;
- pinfo.usage = p_info->usage;
+ PropertyInfo pinfo(*p_info);
ClassDB::add_property(class_name, pinfo, p_setter, p_getter);
}
@@ -245,13 +233,7 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl
MethodInfo s;
s.name = p_signal_name;
for (int i = 0; i < p_argument_count; i++) {
- PropertyInfo arg;
- arg.type = Variant::Type(p_argument_info[i].type);
- arg.name = p_argument_info[i].name;
- arg.class_name = p_argument_info[i].class_name;
- arg.hint = PropertyHint(p_argument_info[i].hint);
- arg.hint_string = p_argument_info[i].hint_string;
- arg.usage = p_argument_info[i].usage;
+ PropertyInfo arg(p_argument_info[i]);
s.arguments.push_back(arg);
}
ClassDB::add_signal(class_name, s);
diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h
index 8f106f753d..b7238d2899 100644
--- a/core/extension/native_extension.h
+++ b/core/extension/native_extension.h
@@ -49,7 +49,7 @@ class NativeExtension : public Resource {
static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
- static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
+ static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield);
static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
@@ -97,4 +97,4 @@ public:
virtual String get_resource_type(const String &p_path) const;
};
-#endif // NATIVEEXTENSION_H
+#endif // NATIVE_EXTENSION_H
diff --git a/core/extension/native_extension_manager.h b/core/extension/native_extension_manager.h
index 5594f6c0de..ed80cd6b7a 100644
--- a/core/extension/native_extension_manager.h
+++ b/core/extension/native_extension_manager.h
@@ -71,4 +71,4 @@ public:
VARIANT_ENUM_CAST(NativeExtensionManager::LoadStatus)
-#endif // NATIVEEXTENSIONMANAGER_H
+#endif // NATIVE_EXTENSION_MANAGER_H
diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt
index 5a71bcbef3..f5874a3dec 100644
--- a/core/input/gamecontrollerdb.txt
+++ b/core/input/gamecontrollerdb.txt
@@ -2,6 +2,7 @@
# Source: https://github.com/gabomdq/SDL_GameControllerDB
# Windows
+03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,
03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
@@ -10,7 +11,7 @@
03000000d0160000600a000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
03000000c82d00000031000000000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000531000000000000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
-03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
+03000000c82d00000951000000000000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows,
03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
@@ -18,24 +19,27 @@
03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000151000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
-03000000c82d00000151000000000000,8BitDo M30 Modkit,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000451000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows,
03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows,
-03000000c82d00000451000000000000,8BitDo N30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,start:b11,platform:Windows,
03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000290000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
03000000c82d00003038000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
+030000003512000012ab000000000000,8BitDo NES30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Windows,
03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000203800000900000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
-03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000851000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000361000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
@@ -43,19 +47,20 @@
03000000c82d00000231000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000331000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000431000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
-03000000c82d00002867000000000000,8BitDo S30 Modkit,a:b0,b:b1,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00002867000000000000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b10,x:b3,y:b4,platform:Windows,
03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
-03000000102800000900000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
-03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
-03000000c82d00003028000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
-03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000102800000900000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00003028000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+030000003512000020ab000000000000,8BitDo SN30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a2,rightshoulder:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
-03000000c82d00000351000000000000,8BitDo SN30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
@@ -63,21 +68,12 @@
03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
-03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
-03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000c01100000355000000000000,Acrux,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000fa190000f0ff000000000000,Acteck AGJ 3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
-030000006d0400000bc2000000000000,Logitech WingMan Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows,
03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows,
-030000006f0e00001301000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000006f0e00001302000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000006f0e00001304000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000006f0e00001413000000000000,Afterglow Xbox Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000006f0e00003901000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-03000000ab1200000103000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-03000000ad1b000000f9000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -85,6 +81,13 @@
030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00001301000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00001302000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00001304000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00001413000000000000,Afterglow Xbox Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00003901000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ab1200000103000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000000f9000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000100000008200000000000000,Akishop Customs PS360,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000007c1800000006000000000000,Alienware Dual Compatible PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
@@ -93,10 +96,8 @@
03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
-03000000ef0500000300000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
-03000000fd0500000230000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,
@@ -121,7 +122,11 @@
030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,
+030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
+030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -135,7 +140,6 @@
03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows,
030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
-030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows,
03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000c0160000e105000000000000,Dual Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows,
@@ -158,25 +162,21 @@
030000006e0500001320000000000000,Elecom U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,
+030000007d0400000640000000000000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Windows,
03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows,
03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
03000000341a00000108000000000000,EXEQ RF Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
-03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
-03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00008401000000000000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00008001000000000000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000852100000201000000000000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
-03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
-03000000380700008031000000000000,Mad Catz FightStick Alpha PS3 ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows,
03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows,
03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows,
@@ -184,15 +184,14 @@
03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,platform:Windows,
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
03000000b40400001224000000000000,Flydigi Vader 2 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,paddle3:b17,paddle4:b18,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
-030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
+030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,
03000000341a000005f7000000000000,GameCube Controller,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows,
03000000430b00000500000000000000,GameCube Controller,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows,
03000000790000004718000000000000,GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
-03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,x:b2,y:b3,start:b9,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,rightshoulder:b7,lefttrigger:a3,righttrigger:a4,platform:Windows,
+03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
030000008f0e00000d31000000000000,Gamepad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-03000000280400000140000000000000,GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000ac0500003d03000000000000,GameSir G3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000ac0500005b05000000000000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000ac0500002d02000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
@@ -217,41 +216,40 @@
030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
-030000007d0400000340000000000000,Gravis G44011 Xterminator,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a2,start:b9,x:b3,y:b4,platform:Windows,
+030000007d0400000840000000000000,Gravis Destroyer Tilt,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows,
+030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000280400000140000000000000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a3,dpup:-a4,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000008f0e00000610000000000000,GreenAsia,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
03000000ac0500006b05000000000000,GT2a,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-03000000fd0500003902000000000000,InterAct Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows,
-03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
-03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows,
-030000000d0f00004900000000000000,Hatsune Miku Sho PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00004900000000000000,Hatsune Miku Sho PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,
030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
03000000632500002605000000000000,HJD X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000000d0f00005100000000000000,Hori Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00008600000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000000d0f0000ba00000000000000,Hori Fighting Commander,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000000d0f00008500000000000000,Hori Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00002500000000000000,Hori Fighting Commander 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00008400000000000000,Hori Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005100000000000000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00008600000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f0000ba00000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00008800000000000000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
+030000000d0f00008700000000000000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00001000000000000000,Hori Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000000f0d00000010000000000000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00003200000000000000,Hori Fightstick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000c000000000000000,Hori Fightstick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000000d0f00000d00000000000000,Hori Fightstick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
030000000d0f00003701000000000000,Hori Fightstick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows,
030000000d0f00004000000000000000,Hori Fightstick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00008700000000000000,Hori Fightstick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f00008800000000000000,Hori Fightstick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
030000000d0f00002100000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00002700000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows,
+030000000d0f0000a500000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000a600000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -289,27 +287,33 @@
030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,
-03000000790000004e95000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
+03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
+03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows,
03000000696400006964000000000000,iDroidCon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
-03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000ef0500000300000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
+03000000fd0500000230000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
+03000000fd0500000030000000000000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows,
+03000000fd0500003902000000000000,InterAct Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows,
+03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
+03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows,
03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows,
03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000491900000204000000000000,Ipega PG9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000491900000304000000000000,Ipega PG9087,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows,
030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,
030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
+03000000250900000017000000000000,Joypad Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,
03000000bd12000003c0000000000000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-03000000250900000017000000000000,Joypad to Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,
03000000ff1100004033000000000000,JPD FFB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a2,start:b15,x:b3,y:b0,platform:Windows,
03000000242f00002d00000000000000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000242f00008a00000000000000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
@@ -331,6 +335,7 @@
030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000006d0400001ac2000000000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+030000006d0400000bc2000000000000,Logitech WingMan Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows,
030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -340,41 +345,44 @@
03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700008031000000000000,Mad Catz FightStick Alpha PS3 ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008134000000000000,Mad Catz Fightstick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-78696e70757403000000000000000000,Mad Catz Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,
03000000380700006252000000000000,Mad Catz Micro CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008232000000000000,Mad Catz PlayStation Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008731000000000000,Mad Catz PlayStation Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000003807000056a8000000000000,Mad Catz PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700001888000000000000,Mad Catz SFIV Fightstick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,
+03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000008f0e00001030000000000000,Mayflash Sega Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,
-0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
-03000000790000000018000000000000,Mayflash WiiU Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
+03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,
+03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000790000002418000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows,
0300000079000000ae18000000000000,Mega Drive Controller,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
-03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,leftx:a0,lefty:a1,righttrigger:b2,start:b3,platform:Windows,
+03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,righttrigger:b2,start:b3,platform:Windows,
030000005e0400002800000000000000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Windows,
030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows,
03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows,
-030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000ad1b00003ef0000000000000,MLG Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000380700006382000000000000,MLG PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -388,6 +396,7 @@
03000000c62400001b89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000efbe0000edfe000000000000,Monect Virtual Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows,
03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows,
030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -398,9 +407,8 @@
0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
0300000092120000474e000000000000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Windows,
03000000921200004b46000000000000,NES 2 port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
-03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
-03000000571d00002100000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
-03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
+03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
+03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
03000000790000004518000000000000,NEXILUX GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows,
03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows,
@@ -434,6 +442,7 @@
03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d620000013a7000000000000,PowerA Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006d04000084ca000000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -476,7 +485,6 @@
03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-03000000120c0000f10e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -494,6 +502,7 @@
03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000300f00000011000000000000,Qanba Arcade Stick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,
03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
+03000000222c00000025000000000000,Qanba Dragon Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00001211000000000000,Qanba Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
@@ -502,6 +511,7 @@
03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows,
03000000086700006626000000000000,RadioShack,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
+03000000ff1100004733000000000000,Ramox FPS Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,
030000009b2800002300000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
030000009b2800006900000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
030000009b2800000800000000000000,Raphnet Dreamcast Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows,
@@ -509,11 +519,12 @@
030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows,
030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows,
+030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows,
030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
-030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
+030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
030000009b2800000300000000000000,Raphnet SNES Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
-030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
-030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows,
030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
@@ -529,12 +540,13 @@
03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000921200004547000000000000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows,
03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000bd12000013d0000000000000,Retrolink Sega Saturn Classic Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows,
03000000bd12000015d0000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
-0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
-0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
+0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
+0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows,
030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000006b140000020d000000000000,Revolution Pro Controller 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -576,25 +588,25 @@
03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows,
03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows,
-03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
+03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows,
03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows,
03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
-0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
-0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows,
+0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
+0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows,
03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
-03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows,
+03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
-03000000571d00002000000000000000,SNES Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
-0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows,
+0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows,
03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
-03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
@@ -608,18 +620,20 @@
03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows,
03000000790000001c18000000000000,STK 7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
-03000000381000003014000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-03000000381000003114000000000000,Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000380700003847000000000000,Street Fighter Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows,
-030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
+030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+03000000341200001300000000000000,Super Racer,a:b2,b:b3,back:b8,leftshoulder:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b7,x:b0,y:b1,platform:Windows,
03000000d620000011a7000000000000,Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
-030000000d0f0000f600000000000000,Switch Hori,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000000d0f0000f600000000000000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows,
030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000e40a00000207000000000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows,
03000000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
@@ -631,12 +645,14 @@
030000004f0400000ed0000000000000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000008d0000000000000,ThrustMaster Ferrari 150 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,
-030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
030000004f04000003d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000009d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000666600000488000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
030000004f04000007d0000000000000,TMini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000571d00002100000000000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Windows,
+03000000571d00002000000000000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000c01100000055000000000000,Tronsmart,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -644,6 +660,7 @@
030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows,
03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows,
03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000151900005678000000000000,Uniplay U6,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b10,x:b3,y:b4,platform:Windows,
03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000000b0400003065000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
03000000242f00006e00000000000000,USB Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows,
@@ -664,7 +681,7 @@
030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows,
03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
-030000007e0500003003000000000000,WiiU Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
+030000007e0500003003000000000000,Wii U Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows,
@@ -683,6 +700,7 @@
03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000c6240000fdfa000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e040000a102000000000000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
@@ -716,17 +734,25 @@
03000000172700004431000000000000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows,
03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
# Mac OS X
-030000008f0e00000300000009010000,2In1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000008f0e00000300000009010000,2 In 1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000c82d00000031000001000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00000531000000020000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001151000000020000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000a30c00002400000006020000,8BitDo M30,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,guide:b9,leftshoulder:b6,lefttrigger:b5,rightshoulder:b4,righttrigger:b7,start:b8,x:b3,y:b0,platform:Mac OS X,
+03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
-03000000c82d00005106000000010000,8BitDo M30,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00005106000000010000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,lefttrigger:a5,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
030000003512000012ab000001000000,8BitDo NES30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
@@ -735,14 +761,18 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000022000000090000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000190000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000131000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000231000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000331000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000431000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
-03000000102800000900000000000000,8BitDo SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
-03000000c82d00001290000001000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Mac OS X,
+03000000102800000900000000000000,8BitDo SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001290000001000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00004028000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X,
@@ -750,14 +780,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000a00500003232000009010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
-03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
-03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
-03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X,
03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
@@ -768,8 +797,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000a306000022f6000001030000,Cyborg V3 Rumble Pad PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
-030000000d0f00008400000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
-030000000d0f00008500000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006e0500000720000010020000,Elecom JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Mac OS X,
+030000006f0e00008401000003010000,Faceoff Premiere Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle3:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Mac OS X,
03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
@@ -777,22 +806,30 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000006f0e00000102000000000000,GameStop Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
-030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
-03000000280400000140000000020000,Gravis Gamepad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000280400000140000000020000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008f0e00000300000007010000,GreenAsia Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X,
030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008400000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008500000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008800000000010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008700000000010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00004d00000000000000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X,
030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,
-03000000830500006020000000000000,iBuffalo Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,
+03000000790000004e95000000010000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X,
+03000000830500006020000000000000,iBuffalo Gamepad,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,
+03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X,
+03000000fd0500000030000010010000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Mac OS X,
030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X,
030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000242f00002d00000007010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
@@ -810,14 +847,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,
-03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,x:b8,y:b12,start:b36,rightshoulder:b28,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a20,righty:a8,lefttrigger:a12,righttrigger:a16,platform:Mac OS X,
03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X,
0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
-0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,
-03000000790000000018000000010000,Mayflash Wii U Pro Controller Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
-03000000790000000018000000000000,Mayflash WiiU Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
+0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,
+03000000790000000318000000010000,Mayflash Wii DolphinBar,a:b8,b:b12,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b44,leftshoulder:b16,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b4,platform:Mac OS X,
+03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
+03000000790000000018000000010000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X,
030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,
03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
@@ -835,18 +873,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X,
030000006f0e00000901000002010000,PDP Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,
-030000004c050000da0c000000010000,PlayStation Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000004c050000da0c000000010000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000100800000300000006010000,PS2 Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
-030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,x:b15,y:b12,back:b0,guide:b16,start:b3,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpdown:b6,dpleft:b7,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Mac OS X,
+030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+03000000222c00000225000000010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000222c00000020000000010000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
03000000321500000204000000010000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
@@ -857,6 +897,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000632500008005000000010000,Redgear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000000d0f0000c100000072050000,Retro Bit Sega Genesis 6B Controller,a:b2,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b8,rightshoulder:b6,righttrigger:b7,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000921200004547000000020000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X,
03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X,
@@ -864,31 +907,37 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
-03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Mac OS X,
+03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Mac OS X,
+03000000a30c00002500000006020000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Mac OS X,
03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,
-03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,
-030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,
+030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X,
-030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
-03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,
+03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
050000004e696d6275732b008b000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
05000000556e6b6e6f776e2048494400,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
+03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,
03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,
+030000000d0f0000f600000000010000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,
030000004f0400000ed0000000020000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,
+03000000571d00002100000021000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X,
03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000bd12000015d0000000000000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000571d00002000000021000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
+030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,
030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
@@ -912,6 +961,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000120c0000101e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
@@ -919,33 +969,42 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
# Linux
030000005e0400008e02000020010000,8BitDo Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux,
03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000650000011010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Linux,
05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux,
03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
-03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,
05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,
03000000022000000090000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux,
05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
-03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
-05000000102800000900000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
-05000000c82d00003028000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+05000000102800000900000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00003028000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,
@@ -955,9 +1014,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
-05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
+05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
-03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
050000005e040000e002000030110000,8BitDo Zero 2,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -971,7 +1030,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,
05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
-03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
05000000050b00000045000031000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
05000000050b00000045000040000000,Asus Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
@@ -986,8 +1045,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000503200000210000045010000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
05000000503200000210000046010000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
05000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:-a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux,
-03000000120c00000500000010010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
-03000000ef0500000300000000010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
@@ -1005,12 +1062,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,
03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
-030000004f04000004b3000010010000,Dual Power 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000242f00009100000000010000,EasySMX ESM-9101,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006e0500000320000010010000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,
030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
+030000007d0400000640000010010000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Linux,
03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
@@ -1025,30 +1082,33 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000f0250000c183000010010000,Goodbetterbest Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
-03000000280400000140000000010000,Gravis Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000280400000140000000010000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,
030000008f0e00001200000010010000,GreenAsia Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
06000000adde0000efbe000002010000,Hidromancer Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,
+03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,
03000000c9110000f055000011010000,HJC Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000632500002605000010010000,HJDX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000000d0f00000d00000000010000,Hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,
030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-030000000d0f00008500000010010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-030000000d0f00008600000002010000,Hori Fighting Commander,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
-030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000000d0f00008500000010010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+030000000d0f00008800000011010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00008700000011010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00001000000011010000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000ad1b000003f5000033050000,Hori Fightstick VX,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b8,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
-030000000d0f00004d00000011010000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00004d00000011010000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux,
030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f0000aa00000011010000,Hori Real Arcade Pro,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000000d0f00001100000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00002200000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -1058,14 +1118,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000000d0f0000c100000011010000,Horipad S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-050000000d0f0000f600000001000000,HORIPAD Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+050000000d0f0000f600000001000000,Horipad Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux,
03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
03000000d80400008200000003000000,IMS PCU0,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux,
-03000000fd0500000030000000010000,InterAct GoPad I73000,a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,
+03000000120c00000500000010010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
+03000000ef0500000300000000010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
+03000000fd0500000030000000010000,InterAct GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Linux,
03000000fd0500002a26000000010000,InterAct HammerHead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,
0500000049190000020400001b010000,Ipega PG 9069,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000632500007505000011010000,Ipega PG 9099,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
@@ -1109,28 +1172,29 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000380700003847000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
-03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000790000004318000010010000,Mayflash GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
+03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000242f0000f700000001010000,Mayflash Magic S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-0300000025090000e803000001010000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
-03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Linux,
+0300000025090000e803000001010000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
+03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
+03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
03000000780000000600000010010000,Microntek Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux,
030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,
-030000005e0400000700000000010000,Microsoft SideWinder Gamepad,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux,
+030000005e0400000700000000010000,Microsoft SideWinder Gamepad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux,
030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux,
030000005e0400008502000000010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
030000005e0400008e02000001000000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.1,dpleft:h0.2,dpright:h0.8,dpup:h0.4,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000004010000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000056210000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000062230000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b00000b050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000d102000001010000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000d102000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000120b000009050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-030000005e040000120b00000b050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000dd02000003020000,Microsoft Xbox One 2015,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000e302000003020000,Microsoft Xbox One Elite,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000000b000008040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -1147,14 +1211,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
-030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
+030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000853200000706000012010000,Nacon GC-100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux,
03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux,
-050000004e696d6275732b0000000000,Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux,
060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux,
03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,
@@ -1164,8 +1229,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b16,b:b15,back:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,platform:Linux,
03000000d620000013a7000011010000,Nintendo Switch PowerA Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000d620000011a7000011010000,Nintendo Switch PowerA Core Plus Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
-050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
+050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux,
05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
@@ -1189,6 +1254,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e0000b802000001010000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e0000b802000013020000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e0000d702000006640000,PDP Black Camo Wired Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b13,dpup:b14,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e00008001000011010000,PDP Faceoff Nintendo Switch Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -1203,12 +1269,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c62400001a53000000010000,PowerA Mini Pro Ex,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000c62400001a58000001010000,PowerA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d62000000220000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,
03000000d62000000228000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c62400001a54000001010000,PowerA Xbox One Mini Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -1240,9 +1308,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,
+03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux,
+03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux,
030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
@@ -1286,16 +1360,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000a30c00002500000011010000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux,
03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux,
03000000790000002201000011010000,Sega Saturn,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
-03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
-030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
+030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000632500007505000010010000,Shanwan PS3 PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000bc2000000055000010010000,Shanwan PS3 PC ,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-030000005f140000c501000010010000,Shanwan Trust,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
-030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
-050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
03000000250900000500000000010000,Sony PS2 pad with SmartJoy Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
@@ -1303,23 +1374,25 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
-03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
+03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux,
03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000ad1b000038f0000090040000,Street Fighter IV Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
-030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux,
+030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux,
03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
-0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
+0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
030000008f0e00000d31000010010000,SZMY Power 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -1332,17 +1405,19 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux,
030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux,
030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,
+030000004f04000004b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
030000004f04000026b3000002040000,Thrustmaster GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c6240000025b000002020000,Thrustmaster GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000004f04000008d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
030000004f04000009d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000004f04000007d0000000010000,Thrustmaster T Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
-030000004f04000012b3000010010000,Thrustmaster vibrating,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
+030000004f04000012b3000010010000,Thrustmaster Vibrating Gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
03000000571d00002000000010010000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
03000000bd12000015d0000010010000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000d814000007cd000011010000,Toodles 2008 Chimp PC PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000100800000100000010010000,Twin PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,
@@ -1385,6 +1460,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050000005e040000130b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000005e040000120b000007050000,Xbox Series X Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,misc1:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
050000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,
@@ -1396,22 +1472,34 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
# Android
38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
36666264316630653965636634386234,8BitDo Adapter 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
-38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
61393962646434393836356631636132,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android,
64323139346131306233636562663738,8BitDo Arcade Stick,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
64643565386136613265663236636564,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android,
+33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android,
34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android,
-05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android,
-05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android,
+38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f2038426974446f204c69,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a5,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android,
+32323161363037623637326438643634,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android,
+38426974446f204d3330204d6f646b69,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android,
64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android,
66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android,
66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android,
+33663431326134333366393233616633,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android,
+38426974446f204e3330204d6f646b69,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android,
05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38313433643131656262306631373166,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38326536643339353865323063616339,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38426974446f2050333020636c617373,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android,
38426974446f2038426974446f205072,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
38426974446f2050726f203200000000,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
@@ -1419,12 +1507,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
38386464613034326435626130396565,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
38426974446f2038426974446f205265,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
66303230343038613365623964393766,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f20533330204d6f646b69,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+66316462353561376330346462316137,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android,
-61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android,
-05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
-05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android,
+05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+38316230613931613964356666353839,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f20534e3330204d6f646b,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+65323563303231646531383162646335,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
@@ -1436,17 +1529,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
050000002028000009000000ffff3f00,8BitDo SNES30,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
050000003512000020ab000000780f00,8BitDo SNES30,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android,
-33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
-38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
-05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
-05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
+38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
+05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,
-417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,leftx:a0,lefty:a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android,
+417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android,
+32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+34313430343161653665353737323365,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android,
+4875694a6961204a432d573031550000,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android,
30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android,
05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
@@ -1464,12 +1560,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android,
64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android,
532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android,
-65346535636333663931613264643164,Joy Con,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android,
-33346566643039343630376565326335,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
-35313531613435623366313835326238,Joy Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
-38383665633039363066383334653465,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
-39363561613936303237333537383931,Joy Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android,
+33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
+35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
+38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android,
@@ -1482,22 +1578,24 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android,
-32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
-6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,x:b23,y:b24,start:b30,rightshoulder:b28,lefttrigger:b25,righttrigger:b26,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Android,
-65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,leftshoulder:b3,rightshoulder:b20,lefttrigger:b9,start:b18,guide:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,platform:Android,
-436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,leftshoulder:b3,rightshoulder:b20,lefttrigger:b9,start:b18,guide:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,platform:Android,
-31323564663862633234646330373138,Mega Drive,a:b23,b:b22,leftx:a0,lefty:a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android,
+6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android,
+436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android,
+65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android,
+535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
+30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android,
+484a5a204d6179666c61736820576969,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android,
+31323564663862633234646330373138,Mega Drive,a:b23,b:b22,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android,
37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android,
64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Android,
33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android,
-30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,leftshoulder:b20,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android,
+30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b20,lefttrigger:b9,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android,
32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
4d4f435554452d303533582d4d35312d,Mocute 053X,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android,
050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android,
-34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android,
36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android,
4e363420436f6e74726f6c6c65720000,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android,
@@ -1512,7 +1610,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
39383335313438623439373538343266,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b16,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,x:b1,y:b19,platform:Android,
4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android,
506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android,
-62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,leftshoulder:b9,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android,
+62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android,
61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android,
32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android,
050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
@@ -1540,6 +1638,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
+32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
+37363764353731323963323639666565,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
+61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
@@ -1554,22 +1656,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android,
33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android,
-66386565396238363534313863353065,Sanwa Mobile,a:b21,b:b22,leftshoulder:b23,leftx:a0,lefty:a1,rightshoulder:b24,platform:Android,
+66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android,
32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android,
37316565396364386635383230353365,Saturn,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android,
-38613865396530353338373763623431,Saturn,a:b0,b:b1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android,
+38613865396530353338373763623431,Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b10,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android,
61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android,
30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android,
66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,
66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android,
62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
-38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
-5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
+38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
+5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
-32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
-61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android,
-63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android,
+63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android,
476f6f676c65204c4c43205374616469,Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,
05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,
@@ -1579,8 +1679,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,
30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
-30386438313564306161393537333663,Wii Classic Controller,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
-33333034646336346339646538643633,Wii Classic Controller,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
+30386438313564306161393537333663,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
+33333034646336346339646538643633,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
30396232393162346330326334636566,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
38313038323730383864666463383533,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
@@ -1618,6 +1718,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS,
4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,
4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,
+050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.1,+lefty:h0.2,-leftx:h0.4,-lefty:h0.8,dpdown:b2,dpleft:b0,dpright:b3,dpup:b1,leftshoulder:b4,misc1:b6,rightshoulder:b5,platform:iOS,
+050000007e0500000e200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS,
+050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+rightx:h0.4,+righty:h0.8,-rightx:h0.1,-righty:h0.2,a:b1,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b2,platform:iOS,
+050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
diff --git a/core/input/input.cpp b/core/input/input.cpp
index da0c6cb62a..e08647f5ea 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -1187,7 +1187,7 @@ Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, J
return event;
}
-void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat, JoyEvent r_events[]) {
+void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat, JoyEvent r_events[(size_t)HatDir::MAX]) {
for (int i = 0; i < mapping.bindings.size(); i++) {
const JoyBinding binding = mapping.bindings[i];
if (binding.inputType == TYPE_HAT && binding.input.hat.hat == p_hat) {
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_builders.py b/core/input/input_builders.py
index 748ec06133..c0dac26f02 100644
--- a/core/input/input_builders.py
+++ b/core/input/input_builders.py
@@ -47,9 +47,9 @@ def make_default_controller_mappings(target, source, env):
platform_variables = {
"Linux": "#if X11_ENABLED",
"Windows": "#ifdef WINDOWS_ENABLED",
- "Mac OS X": "#ifdef OSX_ENABLED",
+ "Mac OS X": "#ifdef MACOS_ENABLED",
"Android": "#if defined(__ANDROID__)",
- "iOS": "#ifdef IPHONE_ENABLED",
+ "iOS": "#ifdef IOS_ENABLED",
"Javascript": "#ifdef JAVASCRIPT_ENABLED",
"UWP": "#ifdef UWP_ENABLED",
}
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 32e025417e..8ad2193fca 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=(%s)", 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/input/shortcut.h b/core/input/shortcut.h
index 0c9689cdcb..daec410039 100644
--- a/core/input/shortcut.h
+++ b/core/input/shortcut.h
@@ -55,4 +55,5 @@ public:
static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);
};
+
#endif // SHORTCUT_H
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
index 433a7efb21..f82d6f077f 100644
--- a/core/io/dir_access.cpp
+++ b/core/io/dir_access.cpp
@@ -34,6 +34,7 @@
#include "core/io/file_access.h"
#include "core/os/memory.h"
#include "core/os/os.h"
+#include "core/templates/local_vector.h"
String DirAccess::_get_root_path() const {
switch (_access_type) {
@@ -181,6 +182,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: {
@@ -282,11 +287,16 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to);
+ const size_t copy_buffer_limit = 65536; // 64 KB
+
fsrc->seek_end(0);
int size = fsrc->get_position();
fsrc->seek(0);
err = OK;
- while (size--) {
+ size_t buffer_size = MIN(size * sizeof(uint8_t), copy_buffer_limit);
+ LocalVector<uint8_t> buffer;
+ buffer.resize(buffer_size);
+ while (size > 0) {
if (fsrc->get_error() != OK) {
err = fsrc->get_error();
break;
@@ -296,7 +306,14 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
break;
}
- fdst->store_8(fsrc->get_8());
+ int bytes_read = fsrc->get_buffer(buffer.ptr(), buffer_size);
+ if (bytes_read <= 0) {
+ err = FAILED;
+ break;
+ }
+ fdst->store_buffer(buffer.ptr(), bytes_read);
+
+ size -= bytes_read;
}
}
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
index 0125f011b5..d5318dfb45 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>
@@ -107,6 +108,8 @@ public:
if (da->remove(p_path) != OK) {
ERR_FAIL_MSG("Cannot remove file or directory: " + p_path);
}
+ } else {
+ ERR_FAIL_MSG("Cannot remove non-existent file or directory: " + p_path);
}
}
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index 7d8da1b11c..8ed3d40c22 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -377,7 +377,7 @@ uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
return i;
}
-String FileAccess::get_as_utf8_string() const {
+String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
Vector<uint8_t> sourcef;
uint64_t len = get_length();
sourcef.resize(len + 1);
@@ -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, -1, p_skip_cr);
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/file_access.h b/core/io/file_access.h
index e2c11142d7..3386800686 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -113,7 +113,7 @@ public:
virtual String get_line() const;
virtual String get_token() const;
virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
- virtual String get_as_utf8_string() const;
+ virtual String get_as_utf8_string(bool p_skip_cr = false) const;
/**
* Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index b8382e61d9..e41491a92c 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -70,29 +70,29 @@ public:
Error open_after_magic(Ref<FileAccess> p_base);
- virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual bool is_open() const; ///< true when file is open
+ 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
- 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
- virtual uint64_t get_length() const; ///< get size of the file
+ 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; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ 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; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); ///< store a byte
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override; ///< store a byte
- virtual bool file_exists(const String &p_name); ///< return true if a file exists
+ virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
- virtual uint64_t _get_modified_time(const String &p_file);
- virtual uint32_t _get_unix_permissions(const String &p_file);
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
+ virtual uint64_t _get_modified_time(const String &p_file) override;
+ virtual uint32_t _get_unix_permissions(const String &p_file) override;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
FileAccessCompressed() {}
virtual ~FileAccessCompressed();
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index 0d1ee6a4d8..6200f87a7a 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -60,33 +60,33 @@ public:
Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true);
Error open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode);
- virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual bool is_open() const; ///< true when file is open
+ 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
- virtual String get_path() const; /// returns the path for the current open file
- virtual String get_path_absolute() const; /// returns the absolute path for the current open file
+ virtual String get_path() const override; /// returns the path for the current open file
+ virtual String get_path_absolute() const override; /// returns the absolute path for the current open file
- 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
- virtual uint64_t get_length() const; ///< get size of the file
+ 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; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ 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; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
+ 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; ///< store an array of bytes
- virtual bool file_exists(const String &p_name); ///< return true if a file exists
+ virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
- virtual uint64_t _get_modified_time(const String &p_file);
- virtual uint32_t _get_unix_permissions(const String &p_file);
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
+ virtual uint64_t _get_modified_time(const String &p_file) override;
+ virtual uint32_t _get_unix_permissions(const String &p_file) override;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
FileAccessEncrypted() {}
~FileAccessEncrypted();
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 868b8ed481..f2bd2aa832 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -45,31 +45,31 @@ public:
static void cleanup();
virtual Error open_custom(const uint8_t *p_data, uint64_t p_len); ///< open a file
- virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual bool is_open() const; ///< true when file is open
+ 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
- virtual void seek(uint64_t p_position); ///< seek to a given position
- virtual void seek_end(int64_t p_position); ///< seek from the end of file
- virtual uint64_t get_position() const; ///< get position in the file
- virtual uint64_t get_length() const; ///< get size of the file
+ virtual void seek(uint64_t p_position) override; ///< seek to a given position
+ virtual void seek_end(int64_t p_position) 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; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
+ virtual uint8_t get_8() const override; ///< get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; ///< get an array of bytes
- virtual Error get_error() const; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_byte); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_byte) override; ///< store a byte
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
- virtual bool file_exists(const String &p_name); ///< return true if a file exists
+ virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
- virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
- virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
+ virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
+ 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; }
FileAccessMemory() {}
};
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index c7431752c0..ceadc715a1 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -132,29 +132,29 @@ public:
RESPONSE_GET_MODTIME,
};
- virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual bool is_open() const; ///< true when file is open
+ 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
- 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
- virtual uint64_t get_length() const; ///< get size of the file
+ 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; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ 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; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); ///< store a byte
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override; ///< store a byte
- virtual bool file_exists(const String &p_path); ///< return true if a file exists
+ virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
- virtual uint64_t _get_modified_time(const String &p_file);
- virtual uint32_t _get_unix_permissions(const String &p_file);
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
+ virtual uint64_t _get_modified_time(const String &p_file) override;
+ virtual uint32_t _get_unix_permissions(const String &p_file) override;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
static void configure();
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index e656f6b885..023758ac0f 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -148,35 +148,35 @@ class FileAccessPack : public FileAccess {
uint64_t off;
Ref<FileAccess> f;
- virtual Error _open(const String &p_path, int p_mode_flags);
- virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
- virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
+ virtual Error _open(const String &p_path, int p_mode_flags) override;
+ virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
+ 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; }
public:
- virtual bool is_open() const;
+ virtual bool is_open() const override;
- virtual void seek(uint64_t p_position);
- virtual void seek_end(int64_t p_position = 0);
- virtual uint64_t get_position() const;
- virtual uint64_t get_length() const;
+ virtual void seek(uint64_t p_position) override;
+ virtual void seek_end(int64_t p_position = 0) override;
+ virtual uint64_t get_position() const override;
+ virtual uint64_t get_length() const override;
- virtual bool eof_reached() const;
+ virtual bool eof_reached() const override;
- virtual uint8_t get_8() const;
+ virtual uint8_t get_8() const override;
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
- virtual void set_big_endian(bool p_big_endian);
+ virtual void set_big_endian(bool p_big_endian) override;
- virtual Error get_error() const;
+ virtual Error get_error() const override;
- virtual void flush();
- virtual void store_8(uint8_t p_dest);
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override;
- virtual void store_buffer(const uint8_t *p_src, uint64_t p_length);
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
- virtual bool file_exists(const String &p_name);
+ virtual bool file_exists(const String &p_name) override;
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
};
@@ -217,33 +217,33 @@ class DirAccessPack : public DirAccess {
PackedData::PackedDir *_find_dir(String p_dir);
public:
- virtual Error list_dir_begin();
- 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;
+ 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);
- virtual String get_current_dir(bool p_include_drive = true) const;
+ virtual Error change_dir(String p_dir) override;
+ virtual String get_current_dir(bool p_include_drive = true) const override;
- 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 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;
- uint64_t get_space_left();
+ uint64_t get_space_left() 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 String get_filesystem_type() const override;
DirAccessPack();
};
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 6ea603546a..74a48192f3 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -85,29 +85,29 @@ class FileAccessZip : public FileAccess {
void _close();
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
+ 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
- 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
- virtual uint64_t get_length() const; ///< get size of the file
+ 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; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ 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; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); ///< store a byte
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override; ///< store a byte
- virtual bool file_exists(const String &p_name); ///< return true if a file exists
+ virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
- virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo
- virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
+ virtual uint64_t _get_modified_time(const String &p_file) override { return 0; } // todo
+ 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; }
FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file);
~FileAccessZip();
diff --git a/core/io/image.cpp b/core/io/image.cpp
index f065dac212..0f20aabd7e 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -1339,6 +1339,108 @@ void Image::crop(int p_width, int p_height) {
crop_from_point(0, 0, p_width, p_height);
}
+void Image::rotate_90(ClockDirection p_direction) {
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
+ ERR_FAIL_COND_MSG(width <= 1, "The Image width specified (" + itos(width) + " pixels) must be greater than 1 pixels.");
+ ERR_FAIL_COND_MSG(height <= 1, "The Image height specified (" + itos(height) + " pixels) must be greater than 1 pixels.");
+
+ int saved_width = height;
+ int saved_height = width;
+
+ if (width != height) {
+ int n = MAX(width, height);
+ resize(n, n, INTERPOLATE_NEAREST);
+ }
+
+ bool used_mipmaps = has_mipmaps();
+ if (used_mipmaps) {
+ clear_mipmaps();
+ }
+
+ {
+ uint8_t *w = data.ptrw();
+ uint8_t src[16];
+ uint8_t dst[16];
+ uint32_t pixel_size = get_format_pixel_size(format);
+
+ // Flip.
+
+ if (p_direction == CLOCKWISE) {
+ for (int y = 0; y < height / 2; y++) {
+ for (int x = 0; x < width; x++) {
+ _get_pixelb(x, y, pixel_size, w, src);
+ _get_pixelb(x, height - y - 1, pixel_size, w, dst);
+
+ _put_pixelb(x, height - y - 1, pixel_size, w, src);
+ _put_pixelb(x, y, pixel_size, w, dst);
+ }
+ }
+ } else {
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width / 2; x++) {
+ _get_pixelb(x, y, pixel_size, w, src);
+ _get_pixelb(width - x - 1, y, pixel_size, w, dst);
+
+ _put_pixelb(width - x - 1, y, pixel_size, w, src);
+ _put_pixelb(x, y, pixel_size, w, dst);
+ }
+ }
+ }
+
+ // Transpose.
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ if (x < y) {
+ _get_pixelb(x, y, pixel_size, w, src);
+ _get_pixelb(y, x, pixel_size, w, dst);
+
+ _put_pixelb(y, x, pixel_size, w, src);
+ _put_pixelb(x, y, pixel_size, w, dst);
+ }
+ }
+ }
+ }
+
+ if (saved_width != saved_height) {
+ resize(saved_width, saved_height, INTERPOLATE_NEAREST);
+ } else if (used_mipmaps) {
+ generate_mipmaps();
+ }
+}
+
+void Image::rotate_180() {
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
+ ERR_FAIL_COND_MSG(width <= 1, "The Image width specified (" + itos(width) + " pixels) must be greater than 1 pixels.");
+ ERR_FAIL_COND_MSG(height <= 1, "The Image height specified (" + itos(height) + " pixels) must be greater than 1 pixels.");
+
+ bool used_mipmaps = has_mipmaps();
+ if (used_mipmaps) {
+ clear_mipmaps();
+ }
+
+ {
+ uint8_t *w = data.ptrw();
+ uint8_t src[16];
+ uint8_t dst[16];
+ uint32_t pixel_size = get_format_pixel_size(format);
+
+ for (int y = 0; y < height / 2; y++) {
+ for (int x = 0; x < width; x++) {
+ _get_pixelb(x, y, pixel_size, w, src);
+ _get_pixelb(width - x - 1, height - y - 1, pixel_size, w, dst);
+
+ _put_pixelb(width - x - 1, height - y - 1, pixel_size, w, src);
+ _put_pixelb(x, y, pixel_size, w, dst);
+ }
+ }
+ }
+
+ if (used_mipmaps) {
+ generate_mipmaps();
+ }
+}
+
void Image::flip_y() {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in compressed or custom image formats.");
@@ -2284,6 +2386,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;
@@ -2463,15 +2580,15 @@ Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const V
create(p_width, p_height, p_mipmaps, p_format, p_data);
}
-Rect2 Image::get_used_rect() const {
+Rect2i Image::get_used_rect() const {
if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGB565) {
- return Rect2(Point2(), Size2(width, height));
+ return Rect2i(0, 0, width, height);
}
int len = data.size();
if (len == 0) {
- return Rect2();
+ return Rect2i();
}
int minx = 0xFFFFFF, miny = 0xFFFFFFF;
@@ -2497,15 +2614,15 @@ Rect2 Image::get_used_rect() const {
}
if (maxx == -1) {
- return Rect2();
+ return Rect2i();
} else {
- return Rect2(minx, miny, maxx - minx + 1, maxy - miny + 1);
+ return Rect2i(minx, miny, maxx - minx + 1, maxy - miny + 1);
}
}
-Ref<Image> Image::get_rect(const Rect2 &p_area) const {
+Ref<Image> Image::get_rect(const Rect2i &p_area) const {
Ref<Image> img = memnew(Image(p_area.size.x, p_area.size.y, mipmaps, format));
- img->blit_rect(Ref<Image>((Image *)this), p_area, Point2(0, 0));
+ img->blit_rect(Ref<Image>((Image *)this), p_area, Point2i(0, 0));
return img;
}
@@ -2542,7 +2659,7 @@ void Image::_get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2
r_clipped_dest_rect.size.y = r_clipped_src_rect.size.y;
}
-void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
+void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest) {
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
@@ -2584,7 +2701,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
}
}
-void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) {
+void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest) {
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
@@ -2634,7 +2751,7 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
}
}
-void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
+void Image::blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest) {
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
int srcdsize = p_src->data.size();
@@ -2669,7 +2786,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
}
}
-void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) {
+void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest) {
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
@@ -2741,7 +2858,7 @@ void Image::fill(const Color &p_color) {
_repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, width * height);
}
-void Image::fill_rect(const Rect2 &p_rect, const Color &p_color) {
+void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill rect in compressed or custom image formats.");
Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect.abs());
@@ -3183,6 +3300,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));
@@ -3201,6 +3319,9 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress);
ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed);
+ ClassDB::bind_method(D_METHOD("rotate_90", "direction"), &Image::rotate_90);
+ ClassDB::bind_method(D_METHOD("rotate_180"), &Image::rotate_180);
+
ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &Image::fix_alpha_edges);
ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha);
ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear);
diff --git a/core/io/image.h b/core/io/image.h
index 2cad26f3e9..46820a4c08 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -254,6 +254,9 @@ public:
void crop_from_point(int p_x, int p_y, int p_width, int p_height);
void crop(int p_width, int p_height);
+ void rotate_90(ClockDirection p_direction);
+ void rotate_180();
+
void flip_x();
void flip_y();
@@ -290,6 +293,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;
@@ -369,15 +373,15 @@ public:
Ref<Image> get_image_from_mipmap(int p_mipamp) const;
void bump_map_to_normal_map(float bump_scale = 1.0);
- void blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
- void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest);
- void blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
- void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest);
+ void blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest);
+ void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest);
+ void blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest);
+ void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest);
void fill(const Color &p_color);
- void fill_rect(const Rect2 &p_rect, const Color &p_color);
+ void fill_rect(const Rect2i &p_rect, const Color &p_color);
- Rect2 get_used_rect() const;
- Ref<Image> get_rect(const Rect2 &p_area) const;
+ Rect2i get_used_rect() const;
+ Ref<Image> get_rect(const Rect2i &p_area) const;
static void set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels));
static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels));
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index 5820ec0c09..b0f74f8db5 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -31,6 +31,7 @@
#include "logger.h"
#include "core/config/project_settings.h"
+#include "core/core_globals.h"
#include "core/io/dir_access.h"
#include "core/os/os.h"
#include "core/os/time.h"
@@ -41,7 +42,7 @@
#endif
bool Logger::should_log(bool p_err) {
- return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
+ return (!p_err || CoreGlobals::print_error_enabled) && (p_err || CoreGlobals::print_line_enabled);
}
bool Logger::_flush_stdout_on_print = true;
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index bb9606c94b..2f69c10218 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
@@ -285,6 +285,46 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
}
} break;
+ case Variant::VECTOR4: {
+ Vector4 val;
+ if (type & ENCODE_FLAG_64) {
+ ERR_FAIL_COND_V((size_t)len < sizeof(double) * 4, ERR_INVALID_DATA);
+ val.x = decode_double(&buf[0]);
+ val.y = decode_double(&buf[sizeof(double)]);
+ val.z = decode_double(&buf[sizeof(double) * 2]);
+ val.w = decode_double(&buf[sizeof(double) * 3]);
+
+ if (r_len) {
+ (*r_len) += sizeof(double) * 4;
+ }
+ } else {
+ ERR_FAIL_COND_V((size_t)len < sizeof(float) * 4, ERR_INVALID_DATA);
+ val.x = decode_float(&buf[0]);
+ val.y = decode_float(&buf[sizeof(float)]);
+ val.z = decode_float(&buf[sizeof(float) * 2]);
+ val.w = decode_float(&buf[sizeof(float) * 3]);
+
+ if (r_len) {
+ (*r_len) += sizeof(float) * 4;
+ }
+ }
+ r_variant = val;
+
+ } break;
+ case Variant::VECTOR4I: {
+ ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
+ Vector4i val;
+ val.x = decode_uint32(&buf[0]);
+ val.y = decode_uint32(&buf[4]);
+ val.z = decode_uint32(&buf[8]);
+ val.w = decode_uint32(&buf[12]);
+ r_variant = val;
+
+ if (r_len) {
+ (*r_len) += 4 * 4;
+ }
+
+ } break;
case Variant::TRANSFORM2D: {
Transform2D val;
if (type & ENCODE_FLAG_64) {
@@ -457,6 +497,33 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
r_variant = val;
} break;
+ case Variant::PROJECTION: {
+ Projection val;
+ if (type & ENCODE_FLAG_64) {
+ ERR_FAIL_COND_V((size_t)len < sizeof(double) * 16, ERR_INVALID_DATA);
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ val.matrix[i][j] = decode_double(&buf[(i * 4 + j) * sizeof(double)]);
+ }
+ }
+ if (r_len) {
+ (*r_len) += sizeof(double) * 16;
+ }
+ } else {
+ ERR_FAIL_COND_V((size_t)len < sizeof(float) * 62, ERR_INVALID_DATA);
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ val.matrix[i][j] = decode_float(&buf[(i * 4 + j) * sizeof(float)]);
+ }
+ }
+
+ if (r_len) {
+ (*r_len) += sizeof(float) * 16;
+ }
+ }
+ r_variant = val;
+
+ } break;
// misc types
case Variant::COLOR: {
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
@@ -532,7 +599,13 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::RID: {
- r_variant = RID();
+ ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
+ uint64_t id = decode_uint64(buf);
+ if (r_len) {
+ (*r_len) += 8;
+ }
+
+ r_variant = RID::from_uint64(id);
} break;
case Variant::OBJECT: {
if (type & ENCODE_FLAG_OBJECT_AS_ID) {
@@ -614,9 +687,20 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
r_variant = Callable();
} break;
case Variant::SIGNAL: {
- r_variant = Signal();
- } break;
+ String name;
+ Error err = _decode_string(buf, len, r_len, name);
+ if (err) {
+ return err;
+ }
+
+ ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
+ ObjectID id = ObjectID(decode_uint64(buf));
+ if (r_len) {
+ (*r_len) += 8;
+ }
+ r_variant = Signal(id, StringName(name));
+ } break;
case Variant::DICTIONARY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
@@ -1269,6 +1353,30 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 6 * sizeof(real_t);
} break;
+ case Variant::VECTOR4: {
+ if (buf) {
+ Vector4 v4 = p_variant;
+ encode_real(v4.x, &buf[0]);
+ encode_real(v4.y, &buf[sizeof(real_t)]);
+ encode_real(v4.z, &buf[sizeof(real_t) * 2]);
+ encode_real(v4.w, &buf[sizeof(real_t) * 3]);
+ }
+
+ r_len += 4 * sizeof(real_t);
+
+ } break;
+ case Variant::VECTOR4I: {
+ if (buf) {
+ Vector4i v4 = p_variant;
+ encode_uint32(v4.x, &buf[0]);
+ encode_uint32(v4.y, &buf[4]);
+ encode_uint32(v4.z, &buf[8]);
+ encode_uint32(v4.w, &buf[12]);
+ }
+
+ r_len += 4 * 4;
+
+ } break;
case Variant::PLANE: {
if (buf) {
Plane p = p_variant;
@@ -1337,6 +1445,19 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 12 * sizeof(real_t);
} break;
+ case Variant::PROJECTION: {
+ if (buf) {
+ Projection val = p_variant;
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ memcpy(&buf[(i * 4 + j) * sizeof(real_t)], &val.matrix[i][j], sizeof(real_t));
+ }
+ }
+ }
+
+ r_len += 16 * sizeof(real_t);
+
+ } break;
// misc types
case Variant::COLOR: {
@@ -1352,10 +1473,12 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
case Variant::RID: {
- } break;
- case Variant::CALLABLE: {
- } break;
- case Variant::SIGNAL: {
+ RID rid = p_variant;
+
+ if (buf) {
+ encode_uint64(rid.get_id(), buf);
+ }
+ r_len += 8;
} break;
case Variant::OBJECT: {
if (p_full_objects) {
@@ -1419,6 +1542,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
} break;
+ case Variant::CALLABLE: {
+ } break;
+ case Variant::SIGNAL: {
+ Signal signal = p_variant;
+
+ _encode_string(signal.get_name(), buf, r_len);
+
+ if (buf) {
+ encode_uint64(signal.get_object_id(), buf);
+ }
+ r_len += 8;
+ } break;
case Variant::DICTIONARY: {
Dictionary d = p_variant;
diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h
index 0b12640627..ec9d33aa5a 100644
--- a/core/io/packet_peer.h
+++ b/core/io/packet_peer.h
@@ -127,4 +127,4 @@ public:
PacketPeerStream();
};
-#endif // PACKET_STREAM_H
+#endif // PACKET_PEER_H
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index b1c50e829c..b731608b4f 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -81,6 +81,9 @@ enum {
VARIANT_VECTOR3I = 47,
VARIANT_PACKED_INT64_ARRAY = 48,
VARIANT_PACKED_FLOAT64_ARRAY = 49,
+ VARIANT_VECTOR4 = 50,
+ VARIANT_VECTOR4I = 51,
+ VARIANT_PROJECTION = 52,
OBJECT_EMPTY = 0,
OBJECT_EXTERNAL_RESOURCE = 1,
OBJECT_INTERNAL_RESOURCE = 2,
@@ -237,6 +240,22 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
v.z = f->get_32();
r_v = v;
} break;
+ case VARIANT_VECTOR4: {
+ Vector4 v;
+ v.x = f->get_real();
+ v.y = f->get_real();
+ v.z = f->get_real();
+ v.w = f->get_real();
+ r_v = v;
+ } break;
+ case VARIANT_VECTOR4I: {
+ Vector4i v;
+ v.x = f->get_32();
+ v.y = f->get_32();
+ v.z = f->get_32();
+ v.w = f->get_32();
+ r_v = v;
+ } break;
case VARIANT_PLANE: {
Plane v;
v.normal.x = f->get_real();
@@ -306,6 +325,26 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
v.origin.z = f->get_real();
r_v = v;
} break;
+ case VARIANT_PROJECTION: {
+ Projection v;
+ v.matrix[0].x = f->get_real();
+ v.matrix[0].y = f->get_real();
+ v.matrix[0].z = f->get_real();
+ v.matrix[0].w = f->get_real();
+ v.matrix[1].x = f->get_real();
+ v.matrix[1].y = f->get_real();
+ v.matrix[1].z = f->get_real();
+ v.matrix[1].w = f->get_real();
+ v.matrix[2].x = f->get_real();
+ v.matrix[2].y = f->get_real();
+ v.matrix[2].z = f->get_real();
+ v.matrix[2].w = f->get_real();
+ v.matrix[3].x = f->get_real();
+ v.matrix[3].y = f->get_real();
+ v.matrix[3].z = f->get_real();
+ v.matrix[3].w = f->get_real();
+ r_v = v;
+ } break;
case VARIANT_COLOR: {
Color v; // Colors should always be in single-precision.
v.r = f->get_float();
@@ -865,6 +904,22 @@ String ResourceLoaderBinary::get_unicode_string() {
return s;
}
+void ResourceLoaderBinary::get_classes_used(Ref<FileAccess> p_f, HashSet<StringName> *p_classes) {
+ open(p_f, false, true);
+ if (error) {
+ return;
+ }
+
+ for (int i = 0; i < internal_resources.size(); i++) {
+ p_f->seek(internal_resources[i].offset);
+ String t = get_unicode_string();
+ ERR_FAIL_COND(p_f->get_error() != OK);
+ if (t != String()) {
+ p_classes->insert(t);
+ }
+ }
+}
+
void ResourceLoaderBinary::get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types) {
open(p_f, false, true);
if (error) {
@@ -1212,7 +1267,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
Ref<Resource> res = loader.get_resource();
ERR_FAIL_COND_V(!res.is_valid(), ERR_FILE_CORRUPT);
- return ResourceFormatSaverBinary::singleton->save(p_path, res);
+ return ResourceFormatSaverBinary::singleton->save(res, p_path);
}
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
@@ -1337,6 +1392,16 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
return OK;
}
+void ResourceFormatLoaderBinary::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_path + "'.");
+
+ ResourceLoaderBinary loader;
+ loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+ loader.res_path = loader.local_path;
+ loader.get_classes_used(f, r_classes);
+}
+
String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
if (f.is_null()) {
@@ -1473,6 +1538,24 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_32(val.z);
} break;
+ case Variant::VECTOR4: {
+ f->store_32(VARIANT_VECTOR4);
+ Vector4 val = p_property;
+ f->store_real(val.x);
+ f->store_real(val.y);
+ f->store_real(val.z);
+ f->store_real(val.w);
+
+ } break;
+ case Variant::VECTOR4I: {
+ f->store_32(VARIANT_VECTOR4I);
+ Vector4i val = p_property;
+ f->store_32(val.x);
+ f->store_32(val.y);
+ f->store_32(val.z);
+ f->store_32(val.w);
+
+ } break;
case Variant::PLANE: {
f->store_32(VARIANT_PLANE);
Plane val = p_property;
@@ -1544,6 +1627,27 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
f->store_real(val.origin.z);
} break;
+ case Variant::PROJECTION: {
+ f->store_32(VARIANT_PROJECTION);
+ Projection val = p_property;
+ f->store_real(val.matrix[0].x);
+ f->store_real(val.matrix[0].y);
+ f->store_real(val.matrix[0].z);
+ f->store_real(val.matrix[0].w);
+ f->store_real(val.matrix[1].x);
+ f->store_real(val.matrix[1].y);
+ f->store_real(val.matrix[1].z);
+ f->store_real(val.matrix[1].w);
+ f->store_real(val.matrix[2].x);
+ f->store_real(val.matrix[2].y);
+ f->store_real(val.matrix[2].z);
+ f->store_real(val.matrix[2].w);
+ f->store_real(val.matrix[3].x);
+ f->store_real(val.matrix[3].y);
+ f->store_real(val.matrix[3].z);
+ f->store_real(val.matrix[3].w);
+
+ } break;
case Variant::COLOR: {
f->store_32(VARIANT_COLOR);
Color val = p_property;
@@ -2100,7 +2204,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
return OK;
}
-Error ResourceFormatSaverBinary::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaverBinary::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
ResourceFormatSaverBinaryInstance saver;
return saver.save(local_path, p_resource, p_flags);
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 5da880ddb8..c891a61e99 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -101,6 +101,7 @@ public:
void open(Ref<FileAccess> p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false);
String recognize(Ref<FileAccess> p_f);
void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types);
+ void get_classes_used(Ref<FileAccess> p_f, HashSet<StringName> *p_classes);
ResourceLoaderBinary() {}
};
@@ -112,6 +113,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
+ virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map);
@@ -174,7 +176,7 @@ public:
class ResourceFormatSaverBinary : public ResourceFormatSaver {
public:
static ResourceFormatSaverBinary *singleton;
- virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
virtual bool recognize(const Ref<Resource> &p_resource) const;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index 934cb780e6..e059fc842b 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -352,6 +352,16 @@ Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) cons
return pat.metadata;
}
+void ResourceFormatImporter::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
+ PathAndType pat;
+ Error err = _get_path_and_type(p_path, pat);
+
+ if (err != OK) {
+ return;
+ }
+
+ ResourceLoader::get_classes_used(pat.path, r_classes);
+}
void ResourceFormatImporter::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
PathAndType pat;
diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h
index 0c7909df06..d0ea98b598 100644
--- a/core/io/resource_importer.h
+++ b/core/io/resource_importer.h
@@ -65,12 +65,12 @@ public:
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
-
virtual Variant get_resource_metadata(const String &p_path) const;
virtual bool is_import_valid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual bool is_imported(const String &p_path) const { return recognize_path(p_path); }
virtual String get_import_group_file(const String &p_path) const;
+ virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
virtual bool exists(const String &p_path) const;
virtual int get_import_order(const String &p_path) const;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 2cd455475c..3e595557f9 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -76,6 +76,21 @@ bool ResourceFormatLoader::handles_type(const String &p_type) const {
return false;
}
+void ResourceFormatLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
+ Vector<String> ret;
+ if (GDVIRTUAL_CALL(_get_classes_used, p_path, ret)) {
+ for (int i = 0; i < ret.size(); i++) {
+ r_classes->insert(ret[i]);
+ }
+ return;
+ }
+
+ String res = get_resource_type(p_path);
+ if (!res.is_empty()) {
+ r_classes->insert(res);
+ }
+}
+
String ResourceFormatLoader::get_resource_type(const String &p_path) const {
String ret;
@@ -180,6 +195,7 @@ void ResourceFormatLoader::_bind_methods() {
GDVIRTUAL_BIND(_get_dependencies, "path", "add_types");
GDVIRTUAL_BIND(_rename_dependencies, "path", "renames");
GDVIRTUAL_BIND(_exists, "path");
+ GDVIRTUAL_BIND(_get_classes_used, "path");
GDVIRTUAL_BIND(_load, "path", "original_path", "use_sub_threads", "cache_mode");
}
@@ -730,6 +746,18 @@ Error ResourceLoader::rename_dependencies(const String &p_path, const HashMap<St
return OK; // ??
}
+void ResourceLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
+ String local_path = _validate_local_path(p_path);
+
+ for (int i = 0; i < loader_count; i++) {
+ if (!loader[i]->recognize_path(local_path)) {
+ continue;
+ }
+
+ return loader[i]->get_classes_used(p_path, r_classes);
+ }
+}
+
String ResourceLoader::get_resource_type(const String &p_path) {
String local_path = _validate_local_path(p_path);
@@ -791,6 +819,12 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
if (r_translation_remapped) {
*r_translation_remapped = true;
}
+
+ // Fallback to p_path if new_path does not exist.
+ if (!FileAccess::exists(new_path)) {
+ WARN_PRINT(vformat("Translation remap '%s' does not exist. Falling back to '%s'.", new_path, p_path));
+ new_path = p_path;
+ }
}
if (path_remaps.has(new_path)) {
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 815dd1dd72..91ba930176 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -55,6 +55,7 @@ protected:
GDVIRTUAL1RC(String, _get_resource_type, String)
GDVIRTUAL1RC(ResourceUID::ID, _get_resource_uid, String)
GDVIRTUAL2RC(Vector<String>, _get_dependencies, String, bool)
+ GDVIRTUAL1RC(Vector<String>, _get_classes_used, String)
GDVIRTUAL2RC(int64_t, _rename_dependencies, String, Dictionary)
GDVIRTUAL1RC(bool, _exists, String)
@@ -67,6 +68,7 @@ public:
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const;
virtual bool handles_type(const String &p_type) const;
+ virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
virtual String get_resource_type(const String &p_path) const;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
@@ -170,6 +172,7 @@ public:
static void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions);
static void add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front = false);
static void remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader);
+ static void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
static String get_resource_type(const String &p_path);
static ResourceUID::ID get_resource_uid(const String &p_path);
static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index 2f5c5b54dd..274316f058 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -41,9 +41,9 @@ bool ResourceSaver::timestamp_on_save = false;
ResourceSavedCallback ResourceSaver::save_callback = nullptr;
ResourceSaverGetResourceIDForPath ResourceSaver::save_get_id_for_path = nullptr;
-Error ResourceFormatSaver::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaver::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
int64_t res;
- if (GDVIRTUAL_CALL(_save, p_path, p_resource, p_flags, res)) {
+ if (GDVIRTUAL_CALL(_save, p_resource, p_path, p_flags, res)) {
return (Error)res;
}
@@ -75,8 +75,14 @@ void ResourceFormatSaver::_bind_methods() {
GDVIRTUAL_BIND(_get_recognized_extensions, "resource");
}
-Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
- String extension = p_path.get_extension();
+Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
+ String path = p_path;
+ if (path.is_empty()) {
+ path = p_resource->get_path();
+ }
+ ERR_FAIL_COND_V_MSG(path.is_empty(), ERR_INVALID_PARAMETER, "Can't save resource to empty path. Provide non-empty path or a Resource with non-empty resource_path.");
+
+ String extension = path.get_extension();
Error err = ERR_FILE_UNRECOGNIZED;
for (int i = 0; i < saver_count; i++) {
@@ -100,21 +106,21 @@ Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource,
String old_path = p_resource->get_path();
- String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+ String local_path = ProjectSettings::get_singleton()->localize_path(path);
Ref<Resource> rwcopy = p_resource;
if (p_flags & FLAG_CHANGE_PATH) {
rwcopy->set_path(local_path);
}
- err = saver[i]->save(p_path, p_resource, p_flags);
+ err = saver[i]->save(p_resource, path, p_flags);
if (err == OK) {
#ifdef TOOLS_ENABLED
((Resource *)p_resource.ptr())->set_edited(false);
if (timestamp_on_save) {
- uint64_t mt = FileAccess::get_modified_time(p_path);
+ uint64_t mt = FileAccess::get_modified_time(path);
((Resource *)p_resource.ptr())->set_last_modified_time(mt);
}
@@ -124,8 +130,8 @@ Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource,
rwcopy->set_path(old_path);
}
- if (save_callback && p_path.begins_with("res://")) {
- save_callback(p_resource, p_path);
+ if (save_callback && path.begins_with("res://")) {
+ save_callback(p_resource, path);
}
return OK;
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 088317bfbe..4fee2bcfd1 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -41,12 +41,12 @@ class ResourceFormatSaver : public RefCounted {
protected:
static void _bind_methods();
- GDVIRTUAL3R(int64_t, _save, String, Ref<Resource>, uint32_t)
+ GDVIRTUAL3R(int64_t, _save, Ref<Resource>, String, uint32_t)
GDVIRTUAL1RC(bool, _recognize, Ref<Resource>)
GDVIRTUAL1RC(Vector<String>, _get_recognized_extensions, Ref<Resource>)
public:
- virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
virtual bool recognize(const Ref<Resource> &p_resource) const;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
@@ -81,7 +81,7 @@ public:
FLAG_REPLACE_SUBRESOURCE_PATHS = 64,
};
- static Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = (uint32_t)FLAG_NONE);
+ static Error save(const Ref<Resource> &p_resource, const String &p_path = "", uint32_t p_flags = (uint32_t)FLAG_NONE);
static void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions);
static void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front = false);
static void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver);
diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h
index da42553cf5..0da37e2716 100644
--- a/core/io/resource_uid.h
+++ b/core/io/resource_uid.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RESOURCE_UUID_H
-#define RESOURCE_UUID_H
+#ifndef RESOURCE_UID_H
+#define RESOURCE_UID_H
#include "core/object/ref_counted.h"
#include "core/string/string_name.h"
@@ -85,4 +85,4 @@ public:
~ResourceUID();
};
-#endif // RESOURCEUUID_H
+#endif // RESOURCE_UID_H
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/basis.cpp b/core/math/basis.cpp
index ce5e9aa9b3..f8e7c47107 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -817,14 +817,13 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
#endif
*/
real_t angle, x, y, z; // variables for result
- real_t epsilon = 0.01; // margin to allow for rounding errors
- real_t epsilon2 = 0.1; // margin to distinguish between 0 and 180 degrees
+ real_t angle_epsilon = 0.1; // margin to distinguish between 0 and 180 degrees
- if ((Math::abs(rows[1][0] - rows[0][1]) < epsilon) && (Math::abs(rows[2][0] - rows[0][2]) < epsilon) && (Math::abs(rows[2][1] - rows[1][2]) < epsilon)) {
+ if ((Math::abs(rows[1][0] - rows[0][1]) < CMP_EPSILON) && (Math::abs(rows[2][0] - rows[0][2]) < CMP_EPSILON) && (Math::abs(rows[2][1] - rows[1][2]) < CMP_EPSILON)) {
// singularity found
// first check for identity matrix which must have +1 for all terms
// in leading diagonal and zero in other terms
- if ((Math::abs(rows[1][0] + rows[0][1]) < epsilon2) && (Math::abs(rows[2][0] + rows[0][2]) < epsilon2) && (Math::abs(rows[2][1] + rows[1][2]) < epsilon2) && (Math::abs(rows[0][0] + rows[1][1] + rows[2][2] - 3) < epsilon2)) {
+ if ((Math::abs(rows[1][0] + rows[0][1]) < angle_epsilon) && (Math::abs(rows[2][0] + rows[0][2]) < angle_epsilon) && (Math::abs(rows[2][1] + rows[1][2]) < angle_epsilon) && (Math::abs(rows[0][0] + rows[1][1] + rows[2][2] - 3) < angle_epsilon)) {
// this singularity is identity matrix so angle = 0
r_axis = Vector3(0, 1, 0);
r_angle = 0;
@@ -839,7 +838,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
real_t xz = (rows[2][0] + rows[0][2]) / 4;
real_t yz = (rows[2][1] + rows[1][2]) / 4;
if ((xx > yy) && (xx > zz)) { // rows[0][0] is the largest diagonal term
- if (xx < epsilon) {
+ if (xx < CMP_EPSILON) {
x = 0;
y = Math_SQRT12;
z = Math_SQRT12;
@@ -849,7 +848,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
z = xz / x;
}
} else if (yy > zz) { // rows[1][1] is the largest diagonal term
- if (yy < epsilon) {
+ if (yy < CMP_EPSILON) {
x = Math_SQRT12;
y = 0;
z = Math_SQRT12;
@@ -859,7 +858,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
z = yz / y;
}
} else { // rows[2][2] is the largest diagonal term so base result on this
- if (zz < epsilon) {
+ if (zz < CMP_EPSILON) {
x = Math_SQRT12;
y = Math_SQRT12;
z = 0;
diff --git a/core/math/bvh.h b/core/math/bvh.h
index 9f6ab9f736..b5f5eda3e6 100644
--- a/core/math/bvh.h
+++ b/core/math/bvh.h
@@ -302,7 +302,7 @@ public:
tree.update();
_check_for_collisions();
#ifdef BVH_INTEGRITY_CHECKS
- tree.integrity_check_all();
+ tree._integrity_check_all();
#endif
}
diff --git a/core/math/bvh_public.inc b/core/math/bvh_public.inc
index 36b0bfeb13..fc1c67a21b 100644
--- a/core/math/bvh_public.inc
+++ b/core/math/bvh_public.inc
@@ -2,7 +2,7 @@ public:
BVHHandle item_add(T *p_userdata, bool p_active, const BOUNDS &p_aabb, int32_t p_subindex, uint32_t p_tree_id, uint32_t p_tree_collision_mask, bool p_invisible = false) {
#ifdef BVH_VERBOSE_TREE
VERBOSE_PRINT("\nitem_add BEFORE");
- _debug_recursive_print_tree(0);
+ _debug_recursive_print_tree(p_tree_id);
VERBOSE_PRINT("\n");
#endif
@@ -78,8 +78,8 @@ BVHHandle item_add(T *p_userdata, bool p_active, const BOUNDS &p_aabb, int32_t p
mem += _nodes.estimate_memory_use();
String sz = _debug_aabb_to_string(abb);
- VERBOSE_PRINT("\titem_add [" + itos(ref_id) + "] " + itos(_refs.size()) + " refs,\t" + itos(_nodes.size()) + " nodes " + sz);
- VERBOSE_PRINT("mem use : " + itos(mem) + ", num nodes : " + itos(_nodes.size()));
+ VERBOSE_PRINT("\titem_add [" + itos(ref_id) + "] " + itos(_refs.used_size()) + " refs,\t" + itos(_nodes.used_size()) + " nodes " + sz);
+ VERBOSE_PRINT("mem use : " + itos(mem) + ", num nodes reserved : " + itos(_nodes.reserved_size()));
#endif
diff --git a/core/math/color.h b/core/math/color.h
index 0afa6006a8..65036f74cc 100644
--- a/core/math/color.h
+++ b/core/math/color.h
@@ -215,12 +215,12 @@ struct _NO_DISCARD_ Color {
_FORCE_INLINE_ void set_a8(int32_t a8) { a = (CLAMP(a8, 0, 255) / 255.0f); }
_FORCE_INLINE_ int32_t get_a8() const { return int32_t(CLAMP(Math::round(a * 255.0f), 0.0f, 255.0f)); }
- _FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v()); }
- _FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v()); }
- _FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v); }
- _FORCE_INLINE_ void set_ok_hsl_h(float p_h) { set_ok_hsl(p_h, get_ok_hsl_s(), get_ok_hsl_l()); }
- _FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l()); }
- _FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l); }
+ _FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v(), a); }
+ _FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v(), a); }
+ _FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v, a); }
+ _FORCE_INLINE_ void set_ok_hsl_h(float p_h) { set_ok_hsl(p_h, get_ok_hsl_s(), get_ok_hsl_l(), a); }
+ _FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); }
+ _FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); }
_FORCE_INLINE_ Color() {}
diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h
index 4ab00e1f34..898c3c2d91 100644
--- a/core/math/delaunay_3d.h
+++ b/core/math/delaunay_3d.h
@@ -33,7 +33,7 @@
#include "core/io/file_access.h"
#include "core/math/aabb.h"
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/math/vector3.h"
#include "core/string/print_string.h"
#include "core/templates/local_vector.h"
@@ -184,7 +184,7 @@ class Delaunay3D {
return true;
}
- CameraMatrix cm;
+ Projection cm;
cm.matrix[0][0] = p_points[p_simplex.points[0]].x;
cm.matrix[0][1] = p_points[p_simplex.points[1]].x;
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/math_fieldwise.cpp b/core/math/math_fieldwise.cpp
index 4be4809e3f..208f89f449 100644
--- a/core/math/math_fieldwise.cpp
+++ b/core/math/math_fieldwise.cpp
@@ -76,6 +76,36 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
return target;
}
+ case Variant::VECTOR3I: {
+ SETUP_TYPE(Vector3i)
+
+ /**/ TRY_TRANSFER_FIELD("x", x)
+ else TRY_TRANSFER_FIELD("y", y)
+ else TRY_TRANSFER_FIELD("z", z)
+
+ return target;
+ }
+ case Variant::VECTOR4: {
+ SETUP_TYPE(Vector4)
+
+ /**/ TRY_TRANSFER_FIELD("x", x)
+ else TRY_TRANSFER_FIELD("y", y)
+ else TRY_TRANSFER_FIELD("z", z)
+ else TRY_TRANSFER_FIELD("w", w)
+
+ return target;
+ }
+ case Variant::VECTOR4I: {
+ SETUP_TYPE(Vector4i)
+
+ /**/ TRY_TRANSFER_FIELD("x", x)
+ else TRY_TRANSFER_FIELD("y", y)
+ else TRY_TRANSFER_FIELD("z", z)
+ else TRY_TRANSFER_FIELD("w", w)
+
+ return target;
+ }
+
case Variant::PLANE: {
SETUP_TYPE(Plane)
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/math/plane.h b/core/math/plane.h
index 66c1741662..73babfa496 100644
--- a/core/math/plane.h
+++ b/core/math/plane.h
@@ -52,7 +52,7 @@ struct _NO_DISCARD_ Plane {
_FORCE_INLINE_ bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_point) const;
- _FORCE_INLINE_ bool has_point(const Vector3 &p_point, real_t _epsilon = CMP_EPSILON) const;
+ _FORCE_INLINE_ bool has_point(const Vector3 &p_point, real_t p_tolerance = CMP_EPSILON) const;
/* intersections */
@@ -97,10 +97,10 @@ real_t Plane::distance_to(const Vector3 &p_point) const {
return (normal.dot(p_point) - d);
}
-bool Plane::has_point(const Vector3 &p_point, real_t _epsilon) const {
+bool Plane::has_point(const Vector3 &p_point, real_t p_tolerance) const {
real_t dist = normal.dot(p_point) - d;
dist = ABS(dist);
- return (dist <= _epsilon);
+ return (dist <= p_tolerance);
}
Plane::Plane(const Vector3 &p_normal, real_t p_d) :
diff --git a/core/math/camera_matrix.cpp b/core/math/projection.cpp
index 57c53b0adb..edf8bf36cd 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/projection.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* camera_matrix.cpp */
+/* projection.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "camera_matrix.h"
+#include "projection.h"
#include "core/math/aabb.h"
#include "core/math/math_funcs.h"
@@ -37,7 +37,7 @@
#include "core/math/transform_3d.h"
#include "core/string/print_string.h"
-float CameraMatrix::determinant() const {
+float Projection::determinant() const {
return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] - matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] -
matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] + matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] +
matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] - matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] -
@@ -52,7 +52,7 @@ float CameraMatrix::determinant() const {
matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3];
}
-void CameraMatrix::set_identity() {
+void Projection::set_identity() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
matrix[i][j] = (i == j) ? 1 : 0;
@@ -60,7 +60,7 @@ void CameraMatrix::set_identity() {
}
}
-void CameraMatrix::set_zero() {
+void Projection::set_zero() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
matrix[i][j] = 0;
@@ -68,7 +68,7 @@ void CameraMatrix::set_zero() {
}
}
-Plane CameraMatrix::xform4(const Plane &p_vec4) const {
+Plane Projection::xform4(const Plane &p_vec4) const {
Plane ret;
ret.normal.x = matrix[0][0] * p_vec4.normal.x + matrix[1][0] * p_vec4.normal.y + matrix[2][0] * p_vec4.normal.z + matrix[3][0] * p_vec4.d;
@@ -78,7 +78,22 @@ Plane CameraMatrix::xform4(const Plane &p_vec4) const {
return ret;
}
-void CameraMatrix::adjust_perspective_znear(real_t p_new_znear) {
+Vector4 Projection::xform(const Vector4 &p_vec4) const {
+ return Vector4(
+ matrix[0][0] * p_vec4.x + matrix[1][0] * p_vec4.y + matrix[2][0] * p_vec4.z + matrix[3][0] * p_vec4.w,
+ matrix[0][1] * p_vec4.x + matrix[1][1] * p_vec4.y + matrix[2][1] * p_vec4.z + matrix[3][1] * p_vec4.w,
+ matrix[0][2] * p_vec4.x + matrix[1][2] * p_vec4.y + matrix[2][2] * p_vec4.z + matrix[3][2] * p_vec4.w,
+ matrix[0][3] * p_vec4.x + matrix[1][3] * p_vec4.y + matrix[2][3] * p_vec4.z + matrix[3][3] * p_vec4.w);
+}
+Vector4 Projection::xform_inv(const Vector4 &p_vec4) const {
+ return Vector4(
+ matrix[0][0] * p_vec4.x + matrix[0][1] * p_vec4.y + matrix[0][2] * p_vec4.z + matrix[0][3] * p_vec4.w,
+ matrix[1][0] * p_vec4.x + matrix[1][1] * p_vec4.y + matrix[1][2] * p_vec4.z + matrix[1][3] * p_vec4.w,
+ matrix[2][0] * p_vec4.x + matrix[2][1] * p_vec4.y + matrix[2][2] * p_vec4.z + matrix[2][3] * p_vec4.w,
+ matrix[3][0] * p_vec4.x + matrix[3][1] * p_vec4.y + matrix[3][2] * p_vec4.z + matrix[3][3] * p_vec4.w);
+}
+
+void Projection::adjust_perspective_znear(real_t p_new_znear) {
real_t zfar = get_z_far();
real_t znear = p_new_znear;
@@ -87,7 +102,154 @@ void CameraMatrix::adjust_perspective_znear(real_t p_new_znear) {
matrix[3][2] = -2 * znear * zfar / deltaZ;
}
-void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
+Projection Projection::create_depth_correction(bool p_flip_y) {
+ Projection proj;
+ proj.set_depth_correction(p_flip_y);
+ return proj;
+}
+
+Projection Projection::create_light_atlas_rect(const Rect2 &p_rect) {
+ Projection proj;
+ proj.set_light_atlas_rect(p_rect);
+ return proj;
+}
+
+Projection Projection::create_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
+ Projection proj;
+ proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov);
+ return proj;
+}
+
+Projection Projection::create_perspective_hmd(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
+ Projection proj;
+ proj.set_perspective(p_fovy_degrees, p_aspect, p_z_near, p_z_far, p_flip_fov, p_eye, p_intraocular_dist, p_convergence_dist);
+ return proj;
+}
+
+Projection Projection::create_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
+ Projection proj;
+ proj.set_for_hmd(p_eye, p_aspect, p_intraocular_dist, p_display_width, p_display_to_lens, p_oversample, p_z_near, p_z_far);
+ return proj;
+}
+
+Projection Projection::create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
+ Projection proj;
+ proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_zfar, p_zfar);
+ return proj;
+}
+
+Projection Projection::create_orthogonal_aspect(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
+ Projection proj;
+ proj.set_orthogonal(p_size, p_aspect, p_znear, p_zfar, p_flip_fov);
+ return proj;
+}
+
+Projection Projection::create_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
+ Projection proj;
+ proj.set_frustum(p_left, p_right, p_bottom, p_top, p_near, p_far);
+ return proj;
+}
+
+Projection Projection::create_frustum_aspect(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
+ Projection proj;
+ proj.set_frustum(p_size, p_aspect, p_offset, p_near, p_far, p_flip_fov);
+ return proj;
+}
+
+Projection Projection::create_fit_aabb(const AABB &p_aabb) {
+ Projection proj;
+ proj.scale_translate_to_fit(p_aabb);
+ return proj;
+}
+
+Projection Projection::perspective_znear_adjusted(real_t p_new_znear) const {
+ Projection proj = *this;
+ proj.adjust_perspective_znear(p_new_znear);
+ return proj;
+}
+
+Plane Projection::get_projection_plane(Planes p_plane) const {
+ const real_t *matrix = (const real_t *)this->matrix;
+
+ switch (p_plane) {
+ case PLANE_NEAR: {
+ Plane new_plane = Plane(matrix[3] + matrix[2],
+ matrix[7] + matrix[6],
+ matrix[11] + matrix[10],
+ matrix[15] + matrix[14]);
+
+ new_plane.normal = -new_plane.normal;
+ new_plane.normalize();
+ return new_plane;
+ } break;
+ case PLANE_FAR: {
+ Plane new_plane = Plane(matrix[3] - matrix[2],
+ matrix[7] - matrix[6],
+ matrix[11] - matrix[10],
+ matrix[15] - matrix[14]);
+
+ new_plane.normal = -new_plane.normal;
+ new_plane.normalize();
+ return new_plane;
+ } break;
+ case PLANE_LEFT: {
+ Plane new_plane = Plane(matrix[3] + matrix[0],
+ matrix[7] + matrix[4],
+ matrix[11] + matrix[8],
+ matrix[15] + matrix[12]);
+
+ new_plane.normal = -new_plane.normal;
+ new_plane.normalize();
+ return new_plane;
+ } break;
+ case PLANE_TOP: {
+ Plane new_plane = Plane(matrix[3] - matrix[1],
+ matrix[7] - matrix[5],
+ matrix[11] - matrix[9],
+ matrix[15] - matrix[13]);
+
+ new_plane.normal = -new_plane.normal;
+ new_plane.normalize();
+ return new_plane;
+ } break;
+ case PLANE_RIGHT: {
+ Plane new_plane = Plane(matrix[3] - matrix[0],
+ matrix[7] - matrix[4],
+ matrix[11] - matrix[8],
+ matrix[15] - matrix[12]);
+
+ new_plane.normal = -new_plane.normal;
+ new_plane.normalize();
+ return new_plane;
+ } break;
+ case PLANE_BOTTOM: {
+ Plane new_plane = Plane(matrix[3] + matrix[1],
+ matrix[7] + matrix[5],
+ matrix[11] + matrix[9],
+ matrix[15] + matrix[13]);
+
+ new_plane.normal = -new_plane.normal;
+ new_plane.normalize();
+ return new_plane;
+ } break;
+ }
+
+ return Plane();
+}
+
+Projection Projection::flipped_y() const {
+ Projection proj = *this;
+ proj.flip_y();
+ return proj;
+}
+
+Projection Projection ::jitter_offseted(const Vector2 &p_offset) const {
+ Projection proj = *this;
+ proj.add_jitter_offset(p_offset);
+ return proj;
+}
+
+void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
if (p_flip_fov) {
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
}
@@ -113,7 +275,7 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_
matrix[3][3] = 0;
}
-void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
+void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
if (p_flip_fov) {
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
}
@@ -145,13 +307,13 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_
set_frustum(left, right, -ymax, ymax, p_z_near, p_z_far);
// translate matrix by (modeltranslation, 0.0, 0.0)
- CameraMatrix cm;
+ Projection cm;
cm.set_identity();
cm.matrix[3][0] = modeltranslation;
*this = *this * cm;
}
-void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
+void Projection::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
// we first calculate our base frustum on our values without taking our lens magnification into account.
real_t f1 = (p_intraocular_dist * 0.5) / p_display_to_lens;
real_t f2 = ((p_display_width - p_intraocular_dist) * 0.5) / p_display_to_lens;
@@ -179,7 +341,7 @@ void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_
}
}
-void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
+void Projection::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
set_identity();
matrix[0][0] = 2.0 / (p_right - p_left);
@@ -191,7 +353,7 @@ void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom
matrix[3][3] = 1.0;
}
-void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
+void Projection::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
if (!p_flip_fov) {
p_size *= p_aspect;
}
@@ -199,7 +361,7 @@ void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear
set_orthogonal(-p_size / 2, +p_size / 2, -p_size / p_aspect / 2, +p_size / p_aspect / 2, p_znear, p_zfar);
}
-void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
+void Projection::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
ERR_FAIL_COND(p_right <= p_left);
ERR_FAIL_COND(p_top <= p_bottom);
ERR_FAIL_COND(p_far <= p_near);
@@ -231,7 +393,7 @@ void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, r
te[15] = 0;
}
-void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
+void Projection::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
if (!p_flip_fov) {
p_size *= p_aspect;
}
@@ -239,7 +401,7 @@ void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset,
set_frustum(-p_size / 2 + p_offset.x, +p_size / 2 + p_offset.x, -p_size / p_aspect / 2 + p_offset.y, +p_size / p_aspect / 2 + p_offset.y, p_near, p_far);
}
-real_t CameraMatrix::get_z_far() const {
+real_t Projection::get_z_far() const {
const real_t *matrix = (const real_t *)this->matrix;
Plane new_plane = Plane(matrix[3] - matrix[2],
matrix[7] - matrix[6],
@@ -252,7 +414,7 @@ real_t CameraMatrix::get_z_far() const {
return new_plane.d;
}
-real_t CameraMatrix::get_z_near() const {
+real_t Projection::get_z_near() const {
const real_t *matrix = (const real_t *)this->matrix;
Plane new_plane = Plane(matrix[3] + matrix[2],
matrix[7] + matrix[6],
@@ -263,7 +425,7 @@ real_t CameraMatrix::get_z_near() const {
return new_plane.d;
}
-Vector2 CameraMatrix::get_viewport_half_extents() const {
+Vector2 Projection::get_viewport_half_extents() const {
const real_t *matrix = (const real_t *)this->matrix;
///////--- Near Plane ---///////
Plane near_plane = Plane(matrix[3] + matrix[2],
@@ -291,7 +453,7 @@ Vector2 CameraMatrix::get_viewport_half_extents() const {
return Vector2(res.x, res.y);
}
-Vector2 CameraMatrix::get_far_plane_half_extents() const {
+Vector2 Projection::get_far_plane_half_extents() const {
const real_t *matrix = (const real_t *)this->matrix;
///////--- Far Plane ---///////
Plane far_plane = Plane(matrix[3] - matrix[2],
@@ -319,7 +481,7 @@ Vector2 CameraMatrix::get_far_plane_half_extents() const {
return Vector2(res.x, res.y);
}
-bool CameraMatrix::get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const {
+bool Projection::get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const {
Vector<Plane> planes = get_projection_planes(Transform3D());
const Planes intersections[8][3] = {
{ PLANE_FAR, PLANE_LEFT, PLANE_TOP },
@@ -342,7 +504,7 @@ bool CameraMatrix::get_endpoints(const Transform3D &p_transform, Vector3 *p_8poi
return true;
}
-Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform) const {
+Vector<Plane> Projection::get_projection_planes(const Transform3D &p_transform) const {
/** Fast Plane Extraction from combined modelview/projection matrices.
* References:
* https://web.archive.org/web/20011221205252/https://www.markmorley.com/opengl/frustumculling.html
@@ -425,13 +587,13 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform3D &p_transform
return planes;
}
-CameraMatrix CameraMatrix::inverse() const {
- CameraMatrix cm = *this;
+Projection Projection::inverse() const {
+ Projection cm = *this;
cm.invert();
return cm;
}
-void CameraMatrix::invert() {
+void Projection::invert() {
int i, j, k;
int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */
real_t pvt_val; /* Value of current pivot element */
@@ -529,18 +691,18 @@ void CameraMatrix::invert() {
}
}
-void CameraMatrix::flip_y() {
+void Projection::flip_y() {
for (int i = 0; i < 4; i++) {
matrix[1][i] = -matrix[1][i];
}
}
-CameraMatrix::CameraMatrix() {
+Projection::Projection() {
set_identity();
}
-CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const {
- CameraMatrix new_matrix;
+Projection Projection::operator*(const Projection &p_matrix) const {
+ Projection new_matrix;
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
@@ -555,7 +717,7 @@ CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const {
return new_matrix;
}
-void CameraMatrix::set_depth_correction(bool p_flip_y) {
+void Projection::set_depth_correction(bool p_flip_y) {
real_t *m = &matrix[0][0];
m[0] = 1;
@@ -576,7 +738,7 @@ void CameraMatrix::set_depth_correction(bool p_flip_y) {
m[15] = 1.0;
}
-void CameraMatrix::set_light_bias() {
+void Projection::set_light_bias() {
real_t *m = &matrix[0][0];
m[0] = 0.5;
@@ -597,7 +759,7 @@ void CameraMatrix::set_light_bias() {
m[15] = 1.0;
}
-void CameraMatrix::set_light_atlas_rect(const Rect2 &p_rect) {
+void Projection::set_light_atlas_rect(const Rect2 &p_rect) {
real_t *m = &matrix[0][0];
m[0] = p_rect.size.width;
@@ -618,7 +780,7 @@ void CameraMatrix::set_light_atlas_rect(const Rect2 &p_rect) {
m[15] = 1.0;
}
-CameraMatrix::operator String() const {
+Projection::operator String() const {
String str;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
@@ -629,22 +791,22 @@ CameraMatrix::operator String() const {
return str;
}
-real_t CameraMatrix::get_aspect() const {
+real_t Projection::get_aspect() const {
Vector2 vp_he = get_viewport_half_extents();
return vp_he.x / vp_he.y;
}
-int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const {
+int Projection::get_pixels_per_meter(int p_for_pixel_width) const {
Vector3 result = xform(Vector3(1, 0, -1));
return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
}
-bool CameraMatrix::is_orthogonal() const {
+bool Projection::is_orthogonal() const {
return matrix[3][3] == 1.0;
}
-real_t CameraMatrix::get_fov() const {
+real_t Projection::get_fov() const {
const real_t *matrix = (const real_t *)this->matrix;
Plane right_plane = Plane(matrix[3] - matrix[0],
@@ -667,7 +829,7 @@ real_t CameraMatrix::get_fov() const {
}
}
-float CameraMatrix::get_lod_multiplier() const {
+float Projection::get_lod_multiplier() const {
if (is_orthogonal()) {
return get_viewport_half_extents().x;
} else {
@@ -678,14 +840,14 @@ float CameraMatrix::get_lod_multiplier() const {
//usage is lod_size / (lod_distance * multiplier) < threshold
}
-void CameraMatrix::make_scale(const Vector3 &p_scale) {
+void Projection::make_scale(const Vector3 &p_scale) {
set_identity();
matrix[0][0] = p_scale.x;
matrix[1][1] = p_scale.y;
matrix[2][2] = p_scale.z;
}
-void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) {
+void Projection::scale_translate_to_fit(const AABB &p_aabb) {
Vector3 min = p_aabb.position;
Vector3 max = p_aabb.position + p_aabb.size;
@@ -710,12 +872,12 @@ void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) {
matrix[3][3] = 1;
}
-void CameraMatrix::add_jitter_offset(const Vector2 &p_offset) {
+void Projection::add_jitter_offset(const Vector2 &p_offset) {
matrix[3][0] += p_offset.x;
matrix[3][1] += p_offset.y;
}
-CameraMatrix::operator Transform3D() const {
+Projection::operator Transform3D() const {
Transform3D tr;
const real_t *m = &matrix[0][0];
@@ -737,8 +899,13 @@ CameraMatrix::operator Transform3D() const {
return tr;
}
-
-CameraMatrix::CameraMatrix(const Transform3D &p_transform) {
+Projection::Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w) {
+ matrix[0] = p_x;
+ matrix[1] = p_y;
+ matrix[2] = p_z;
+ matrix[3] = p_w;
+}
+Projection::Projection(const Transform3D &p_transform) {
const Transform3D &tr = p_transform;
real_t *m = &matrix[0][0];
@@ -760,5 +927,5 @@ CameraMatrix::CameraMatrix(const Transform3D &p_transform) {
m[15] = 1.0;
}
-CameraMatrix::~CameraMatrix() {
+Projection::~Projection() {
}
diff --git a/core/math/camera_matrix.h b/core/math/projection.h
index a4051cee3b..a3d2d7720b 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/projection.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* camera_matrix.h */
+/* projection.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,11 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CAMERA_MATRIX_H
-#define CAMERA_MATRIX_H
+#ifndef PROJECTION_H
+#define PROJECTION_H
#include "core/math/math_defs.h"
#include "core/math/vector3.h"
+#include "core/math/vector4.h"
#include "core/templates/vector.h"
struct AABB;
@@ -41,7 +42,7 @@ struct Rect2;
struct Transform3D;
struct Vector2;
-struct CameraMatrix {
+struct Projection {
enum Planes {
PLANE_NEAR,
PLANE_FAR,
@@ -51,13 +52,24 @@ struct CameraMatrix {
PLANE_BOTTOM
};
- real_t matrix[4][4];
+ Vector4 matrix[4];
+
+ _FORCE_INLINE_ const Vector4 &operator[](const int p_axis) const {
+ DEV_ASSERT((unsigned int)p_axis < 4);
+ return matrix[p_axis];
+ }
+
+ _FORCE_INLINE_ Vector4 &operator[](const int p_axis) {
+ DEV_ASSERT((unsigned int)p_axis < 4);
+ return matrix[p_axis];
+ }
float determinant() const;
void set_identity();
void set_zero();
void set_light_bias();
void set_depth_correction(bool p_flip_y = true);
+
void set_light_atlas_rect(const Rect2 &p_rect);
void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false);
void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist);
@@ -68,6 +80,21 @@ struct CameraMatrix {
void set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false);
void adjust_perspective_znear(real_t p_new_znear);
+ static Projection create_depth_correction(bool p_flip_y);
+ static Projection create_light_atlas_rect(const Rect2 &p_rect);
+ static Projection create_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false);
+ static Projection create_perspective_hmd(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist);
+ static Projection create_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far);
+ static Projection create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar);
+ static Projection create_orthogonal_aspect(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov = false);
+ static Projection create_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far);
+ static Projection create_frustum_aspect(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false);
+ static Projection create_fit_aabb(const AABB &p_aabb);
+ Projection perspective_znear_adjusted(real_t p_new_znear) const;
+ Plane get_projection_plane(Planes p_plane) const;
+ Projection flipped_y() const;
+ Projection jitter_offseted(const Vector2 &p_offset) const;
+
static real_t get_fovy(real_t p_fovx, real_t p_aspect) {
return Math::rad2deg(Math::atan(p_aspect * Math::tan(Math::deg2rad(p_fovx) * 0.5)) * 2.0);
}
@@ -85,13 +112,16 @@ struct CameraMatrix {
Vector2 get_far_plane_half_extents() const;
void invert();
- CameraMatrix inverse() const;
+ Projection inverse() const;
- CameraMatrix operator*(const CameraMatrix &p_matrix) const;
+ Projection operator*(const Projection &p_matrix) const;
Plane xform4(const Plane &p_vec4) const;
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec3) const;
+ Vector4 xform(const Vector4 &p_vec4) const;
+ Vector4 xform_inv(const Vector4 &p_vec4) const;
+
operator String() const;
void scale_translate_to_fit(const AABB &p_aabb);
@@ -102,7 +132,7 @@ struct CameraMatrix {
void flip_y();
- bool operator==(const CameraMatrix &p_cam) const {
+ bool operator==(const Projection &p_cam) const {
for (uint32_t i = 0; i < 4; i++) {
for (uint32_t j = 0; j < 4; j++) {
if (matrix[i][j] != p_cam.matrix[i][j]) {
@@ -113,18 +143,19 @@ struct CameraMatrix {
return true;
}
- bool operator!=(const CameraMatrix &p_cam) const {
+ bool operator!=(const Projection &p_cam) const {
return !(*this == p_cam);
}
float get_lod_multiplier() const;
- CameraMatrix();
- CameraMatrix(const Transform3D &p_transform);
- ~CameraMatrix();
+ Projection();
+ Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w);
+ Projection(const Transform3D &p_transform);
+ ~Projection();
};
-Vector3 CameraMatrix::xform(const Vector3 &p_vec3) const {
+Vector3 Projection::xform(const Vector3 &p_vec3) const {
Vector3 ret;
ret.x = matrix[0][0] * p_vec3.x + matrix[1][0] * p_vec3.y + matrix[2][0] * p_vec3.z + matrix[3][0];
ret.y = matrix[0][1] * p_vec3.x + matrix[1][1] * p_vec3.y + matrix[2][1] * p_vec3.z + matrix[3][1];
@@ -133,4 +164,4 @@ Vector3 CameraMatrix::xform(const Vector3 &p_vec3) const {
return ret / w;
}
-#endif // CAMERA_MATRIX_H
+#endif // PROJECTION_H
diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp
index 11bfcc1a6f..c681c60694 100644
--- a/core/math/quaternion.cpp
+++ b/core/math/quaternion.cpp
@@ -111,7 +111,7 @@ Quaternion Quaternion::log() const {
Quaternion Quaternion::exp() const {
Quaternion src = *this;
Vector3 src_v = Vector3(src.x, src.y, src.z);
- float theta = src_v.length();
+ real_t theta = src_v.length();
if (theta < CMP_EPSILON) {
return Quaternion(0, 0, 0, 1);
}
@@ -132,15 +132,9 @@ Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) con
// adjust signs (if necessary)
if (cosom < 0.0f) {
cosom = -cosom;
- to1.x = -p_to.x;
- to1.y = -p_to.y;
- to1.z = -p_to.z;
- to1.w = -p_to.w;
+ to1 = -p_to;
} else {
- to1.x = p_to.x;
- to1.y = p_to.y;
- to1.z = p_to.z;
- to1.w = p_to.w;
+ to1 = p_to;
}
// calculate coefficients
@@ -189,16 +183,54 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) c
invFactor * from.w + newFactor * p_to.w);
}
-Quaternion Quaternion::cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
+Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
#endif
- //the only way to do slerp :|
- real_t t2 = (1.0f - p_weight) * p_weight * 2;
- Quaternion sp = this->slerp(p_b, p_weight);
- Quaternion sq = p_pre_a.slerpni(p_post_b, p_weight);
- return sp.slerpni(sq, t2);
+ Quaternion from_q = *this;
+ Quaternion pre_q = p_pre_a;
+ Quaternion to_q = p_b;
+ Quaternion post_q = p_post_b;
+
+ // Align flip phases.
+ from_q = Basis(from_q).get_rotation_quaternion();
+ pre_q = Basis(pre_q).get_rotation_quaternion();
+ to_q = Basis(to_q).get_rotation_quaternion();
+ post_q = Basis(post_q).get_rotation_quaternion();
+
+ // Flip quaternions to shortest path if necessary.
+ bool flip1 = signbit(from_q.dot(pre_q));
+ pre_q = flip1 ? -pre_q : pre_q;
+ bool flip2 = signbit(from_q.dot(to_q));
+ to_q = flip2 ? -to_q : to_q;
+ bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : signbit(to_q.dot(post_q));
+ post_q = flip3 ? -post_q : post_q;
+
+ // Calc by Expmap in from_q space.
+ Quaternion ln_from = Quaternion(0, 0, 0, 0);
+ Quaternion ln_to = (from_q.inverse() * to_q).log();
+ Quaternion ln_pre = (from_q.inverse() * pre_q).log();
+ Quaternion ln_post = (from_q.inverse() * post_q).log();
+ Quaternion ln = Quaternion(0, 0, 0, 0);
+ ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight);
+ ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight);
+ ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
+ Quaternion q1 = from_q * ln.exp();
+
+ // Calc by Expmap in to_q space.
+ ln_from = (to_q.inverse() * from_q).log();
+ ln_to = Quaternion(0, 0, 0, 0);
+ ln_pre = (to_q.inverse() * pre_q).log();
+ ln_post = (to_q.inverse() * post_q).log();
+ ln = Quaternion(0, 0, 0, 0);
+ ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight);
+ ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight);
+ ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
+ Quaternion q2 = to_q * ln.exp();
+
+ // To cancel error made by Expmap ambiguity, do blends.
+ return q1.slerp(q2, p_weight);
}
Quaternion::operator String() const {
@@ -213,7 +245,7 @@ Vector3 Quaternion::get_axis() const {
return Vector3(x * r, y * r, z * r);
}
-float Quaternion::get_angle() const {
+real_t Quaternion::get_angle() const {
return 2 * Math::acos(w);
}
diff --git a/core/math/quaternion.h b/core/math/quaternion.h
index 9801746659..cb54a6f540 100644
--- a/core/math/quaternion.h
+++ b/core/math/quaternion.h
@@ -71,10 +71,10 @@ struct _NO_DISCARD_ Quaternion {
Quaternion slerp(const Quaternion &p_to, const real_t &p_weight) const;
Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const;
- Quaternion cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
+ Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
Vector3 get_axis() const;
- float get_angle() const;
+ real_t get_angle() const;
_FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
r_angle = 2 * Math::acos(w);
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index cbd2fd3fa1..226076029b 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -136,11 +136,11 @@ void Transform2D::scale_basis(const Size2 &p_scale) {
columns[1][1] *= p_scale.y;
}
-void Transform2D::translate(const real_t p_tx, const real_t p_ty) {
- translate(Vector2(p_tx, p_ty));
+void Transform2D::translate_local(const real_t p_tx, const real_t p_ty) {
+ translate_local(Vector2(p_tx, p_ty));
}
-void Transform2D::translate(const Vector2 &p_translation) {
+void Transform2D::translate_local(const Vector2 &p_translation) {
columns[2] += basis_xform(p_translation);
}
@@ -217,18 +217,24 @@ Transform2D Transform2D::operator*(const Transform2D &p_transform) const {
return t;
}
-Transform2D Transform2D::scaled(const Size2 &p_scale) const {
+Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const {
Transform2D copy = *this;
- copy.scale(p_scale);
+ copy.scale_basis(p_scale);
return copy;
}
-Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const {
+Transform2D Transform2D::scaled(const Size2 &p_scale) const {
+ // Equivalent to left multiplication
Transform2D copy = *this;
- copy.scale_basis(p_scale);
+ copy.scale(p_scale);
return copy;
}
+Transform2D Transform2D::scaled_local(const Size2 &p_scale) const {
+ // Equivalent to right multiplication
+ return Transform2D(columns[0] * p_scale.x, columns[1] * p_scale.y, columns[2]);
+}
+
Transform2D Transform2D::untranslated() const {
Transform2D copy = *this;
copy.columns[2] = Vector2();
@@ -236,15 +242,23 @@ Transform2D Transform2D::untranslated() const {
}
Transform2D Transform2D::translated(const Vector2 &p_offset) const {
- Transform2D copy = *this;
- copy.translate(p_offset);
- return copy;
+ // Equivalent to left multiplication
+ return Transform2D(columns[0], columns[1], columns[2] + p_offset);
+}
+
+Transform2D Transform2D::translated_local(const Vector2 &p_offset) const {
+ // Equivalent to right multiplication
+ return Transform2D(columns[0], columns[1], columns[2] + basis_xform(p_offset));
}
Transform2D Transform2D::rotated(const real_t p_angle) const {
- Transform2D copy = *this;
- copy.rotate(p_angle);
- return copy;
+ // Equivalent to left multiplication
+ return Transform2D(p_angle, Vector2()) * (*this);
+}
+
+Transform2D Transform2D::rotated_local(const real_t p_angle) const {
+ // Equivalent to right multiplication
+ return (*this) * Transform2D(p_angle, Vector2()); // Could be optimized, because origin transform can be skipped.
}
real_t Transform2D::basis_determinant() const {
diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h
index 72d34a5d4c..f23f32867a 100644
--- a/core/math/transform_2d.h
+++ b/core/math/transform_2d.h
@@ -74,8 +74,8 @@ struct _NO_DISCARD_ Transform2D {
void scale(const Size2 &p_scale);
void scale_basis(const Size2 &p_scale);
- void translate(const real_t p_tx, const real_t p_ty);
- void translate(const Vector2 &p_translation);
+ void translate_local(const real_t p_tx, const real_t p_ty);
+ void translate_local(const Vector2 &p_translation);
real_t basis_determinant() const;
@@ -85,10 +85,13 @@ struct _NO_DISCARD_ Transform2D {
_FORCE_INLINE_ const Vector2 &get_origin() const { return columns[2]; }
_FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { columns[2] = p_origin; }
- Transform2D scaled(const Size2 &p_scale) const;
Transform2D basis_scaled(const Size2 &p_scale) const;
+ Transform2D scaled(const Size2 &p_scale) const;
+ Transform2D scaled_local(const Size2 &p_scale) const;
Transform2D translated(const Vector2 &p_offset) const;
+ Transform2D translated_local(const Vector2 &p_offset) const;
Transform2D rotated(const real_t p_angle) const;
+ Transform2D rotated_local(const real_t p_angle) const;
Transform2D untranslated() const;
diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp
index 76b31daa76..a634faca9a 100644
--- a/core/math/transform_3d.cpp
+++ b/core/math/transform_3d.cpp
@@ -62,7 +62,15 @@ void Transform3D::rotate(const Vector3 &p_axis, real_t p_angle) {
}
Transform3D Transform3D::rotated(const Vector3 &p_axis, real_t p_angle) const {
- return Transform3D(Basis(p_axis, p_angle), Vector3()) * (*this);
+ // Equivalent to left multiplication
+ Basis p_basis(p_axis, p_angle);
+ return Transform3D(p_basis * basis, p_basis.xform(origin));
+}
+
+Transform3D Transform3D::rotated_local(const Vector3 &p_axis, real_t p_angle) const {
+ // Equivalent to right multiplication
+ Basis p_basis(p_axis, p_angle);
+ return Transform3D(basis * p_basis, origin);
}
void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) {
@@ -70,17 +78,23 @@ void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) {
}
Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(origin.is_equal_approx(p_target), Transform3D(), "The transform's origin and target can't be equal.");
+#endif
Transform3D t = *this;
t.basis = Basis::looking_at(p_target - origin, p_up);
return t;
}
void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_MSG(p_eye.is_equal_approx(p_target), "The eye and target vectors can't be equal.");
+#endif
basis = Basis::looking_at(p_target - p_eye, p_up);
origin = p_eye;
}
-Transform3D Transform3D::sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const {
+Transform3D Transform3D::spherical_interpolate_with(const Transform3D &p_transform, real_t p_c) const {
/* not sure if very "efficient" but good enough? */
Transform3D interp;
@@ -114,29 +128,37 @@ void Transform3D::scale(const Vector3 &p_scale) {
}
Transform3D Transform3D::scaled(const Vector3 &p_scale) const {
- Transform3D t = *this;
- t.scale(p_scale);
- return t;
+ // Equivalent to left multiplication
+ return Transform3D(basis.scaled(p_scale), origin * p_scale);
+}
+
+Transform3D Transform3D::scaled_local(const Vector3 &p_scale) const {
+ // Equivalent to right multiplication
+ return Transform3D(basis.scaled_local(p_scale), origin);
}
void Transform3D::scale_basis(const Vector3 &p_scale) {
basis.scale(p_scale);
}
-void Transform3D::translate(real_t p_tx, real_t p_ty, real_t p_tz) {
- translate(Vector3(p_tx, p_ty, p_tz));
+void Transform3D::translate_local(real_t p_tx, real_t p_ty, real_t p_tz) {
+ translate_local(Vector3(p_tx, p_ty, p_tz));
}
-void Transform3D::translate(const Vector3 &p_translation) {
+void Transform3D::translate_local(const Vector3 &p_translation) {
for (int i = 0; i < 3; i++) {
origin[i] += basis[i].dot(p_translation);
}
}
Transform3D Transform3D::translated(const Vector3 &p_translation) const {
- Transform3D t = *this;
- t.translate(p_translation);
- return t;
+ // Equivalent to left multiplication
+ return Transform3D(basis, origin + p_translation);
+}
+
+Transform3D Transform3D::translated_local(const Vector3 &p_translation) const {
+ // Equivalent to right multiplication
+ return Transform3D(basis, origin + basis.xform(p_translation));
}
void Transform3D::orthonormalize() {
diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h
index 25832434cd..b572e90859 100644
--- a/core/math/transform_3d.h
+++ b/core/math/transform_3d.h
@@ -46,6 +46,7 @@ struct _NO_DISCARD_ Transform3D {
Transform3D affine_inverse() const;
Transform3D rotated(const Vector3 &p_axis, real_t p_angle) const;
+ Transform3D rotated_local(const Vector3 &p_axis, real_t p_angle) const;
void rotate(const Vector3 &p_axis, real_t p_angle);
void rotate_basis(const Vector3 &p_axis, real_t p_angle);
@@ -55,10 +56,12 @@ struct _NO_DISCARD_ Transform3D {
void scale(const Vector3 &p_scale);
Transform3D scaled(const Vector3 &p_scale) const;
+ Transform3D scaled_local(const Vector3 &p_scale) const;
void scale_basis(const Vector3 &p_scale);
- void translate(real_t p_tx, real_t p_ty, real_t p_tz);
- void translate(const Vector3 &p_translation);
+ void translate_local(real_t p_tx, real_t p_ty, real_t p_tz);
+ void translate_local(const Vector3 &p_translation);
Transform3D translated(const Vector3 &p_translation) const;
+ Transform3D translated_local(const Vector3 &p_translation) const;
const Basis &get_basis() const { return basis; }
void set_basis(const Basis &p_basis) { basis = p_basis; }
@@ -100,7 +103,7 @@ struct _NO_DISCARD_ Transform3D {
void operator*=(const real_t p_val);
Transform3D operator*(const real_t p_val) const;
- Transform3D sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const;
+ Transform3D spherical_interpolate_with(const Transform3D &p_transform, real_t p_c) const;
Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const;
_FORCE_INLINE_ Transform3D inverse_xform(const Transform3D &t) const {
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 970416234d..4ce01da60e 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -217,16 +217,25 @@ Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const {
}
Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const {
+ // This method seems more complicated than it really is, since we write out
+ // the internals of some methods for efficiency (mainly, checking length).
real_t start_length_sq = length_squared();
real_t end_length_sq = p_to.length_squared();
if (unlikely(start_length_sq == 0.0f || end_length_sq == 0.0f)) {
// Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
return lerp(p_to, p_weight);
}
+ Vector3 axis = cross(p_to);
+ real_t axis_length_sq = axis.length_squared();
+ if (unlikely(axis_length_sq == 0.0f)) {
+ // Colinear vectors have no rotation axis or angle between them, so the best we can do is lerp.
+ return lerp(p_to, p_weight);
+ }
+ axis /= Math::sqrt(axis_length_sq);
real_t start_length = Math::sqrt(start_length_sq);
real_t result_length = Math::lerp(start_length, Math::sqrt(end_length_sq), p_weight);
real_t angle = angle_to(p_to);
- return rotated(cross(p_to).normalized(), angle * p_weight) * (result_length / start_length);
+ return rotated(axis, angle * p_weight) * (result_length / start_length);
}
Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const {
diff --git a/core/math/vector4.cpp b/core/math/vector4.cpp
new file mode 100644
index 0000000000..4697c311b4
--- /dev/null
+++ b/core/math/vector4.cpp
@@ -0,0 +1,172 @@
+/*************************************************************************/
+/* vector4.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 "vector4.h"
+
+#include "core/math/basis.h"
+#include "core/string/print_string.h"
+
+void Vector4::set_axis(const int p_axis, const real_t p_value) {
+ ERR_FAIL_INDEX(p_axis, 4);
+ components[p_axis] = p_value;
+}
+
+real_t Vector4::get_axis(const int p_axis) const {
+ ERR_FAIL_INDEX_V(p_axis, 4, 0);
+ return operator[](p_axis);
+}
+
+Vector4::Axis Vector4::min_axis_index() const {
+ uint32_t min_index = 0;
+ real_t min_value = x;
+ for (uint32_t i = 1; i < 4; i++) {
+ if (operator[](i) <= min_value) {
+ min_index = i;
+ min_value = operator[](i);
+ }
+ }
+ return Vector4::Axis(min_index);
+}
+
+Vector4::Axis Vector4::max_axis_index() const {
+ uint32_t max_index = 0;
+ real_t max_value = x;
+ for (uint32_t i = 1; i < 4; i++) {
+ if (operator[](i) > max_value) {
+ max_index = i;
+ max_value = operator[](i);
+ }
+ }
+ return Vector4::Axis(max_index);
+}
+
+bool Vector4::is_equal_approx(const Vector4 &p_vec4) const {
+ return Math::is_equal_approx(x, p_vec4.x) && Math::is_equal_approx(y, p_vec4.y) && Math::is_equal_approx(z, p_vec4.z) && Math::is_equal_approx(w, p_vec4.w);
+}
+
+real_t Vector4::length() const {
+ return Math::sqrt(length_squared());
+}
+
+void Vector4::normalize() {
+ *this /= length();
+}
+
+Vector4 Vector4::normalized() const {
+ return *this / length();
+}
+
+bool Vector4::is_normalized() const {
+ return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); // Use less epsilon.
+}
+
+real_t Vector4::distance_to(const Vector4 &p_to) const {
+ return (p_to - *this).length();
+}
+
+Vector4 Vector4::direction_to(const Vector4 &p_to) const {
+ Vector4 ret(p_to.x - x, p_to.y - y, p_to.z - z, p_to.w - w);
+ ret.normalize();
+ return ret;
+}
+
+Vector4 Vector4::abs() const {
+ return Vector4(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w));
+}
+
+Vector4 Vector4::sign() const {
+ return Vector4(SIGN(x), SIGN(y), SIGN(z), SIGN(w));
+}
+
+Vector4 Vector4::floor() const {
+ return Vector4(Math::floor(x), Math::floor(y), Math::floor(z), Math::floor(w));
+}
+
+Vector4 Vector4::ceil() const {
+ return Vector4(Math::ceil(x), Math::ceil(y), Math::ceil(z), Math::ceil(w));
+}
+
+Vector4 Vector4::round() const {
+ return Vector4(Math::round(x), Math::round(y), Math::round(z), Math::round(w));
+}
+
+Vector4 Vector4::lerp(const Vector4 &p_to, const real_t p_weight) const {
+ return Vector4(
+ x + (p_weight * (p_to.x - x)),
+ y + (p_weight * (p_to.y - y)),
+ z + (p_weight * (p_to.z - z)),
+ w + (p_weight * (p_to.w - w)));
+}
+
+Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const {
+ Vector4 res = *this;
+ res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight);
+ res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight);
+ res.z = Math::cubic_interpolate(res.z, p_b.z, p_pre_a.z, p_post_b.z, p_weight);
+ res.w = Math::cubic_interpolate(res.w, p_b.w, p_pre_a.w, p_post_b.w, p_weight);
+ return res;
+}
+
+Vector4 Vector4::posmod(const real_t p_mod) const {
+ return Vector4(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod), Math::fposmod(w, p_mod));
+}
+
+Vector4 Vector4::posmodv(const Vector4 &p_modv) const {
+ return Vector4(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z), Math::fposmod(w, p_modv.w));
+}
+
+void Vector4::snap(const Vector4 &p_step) {
+ x = Math::snapped(x, p_step.x);
+ y = Math::snapped(y, p_step.y);
+ z = Math::snapped(z, p_step.z);
+ w = Math::snapped(w, p_step.w);
+}
+
+Vector4 Vector4::snapped(const Vector4 &p_step) const {
+ Vector4 v = *this;
+ v.snap(p_step);
+ return v;
+}
+
+Vector4 Vector4::inverse() const {
+ return Vector4(1.0f / x, 1.0f / y, 1.0f / z, 1.0f / w);
+}
+
+Vector4 Vector4::clamp(const Vector4 &p_min, const Vector4 &p_max) const {
+ return Vector4(
+ CLAMP(x, p_min.x, p_max.x),
+ CLAMP(y, p_min.y, p_max.y),
+ CLAMP(z, p_min.z, p_max.z),
+ CLAMP(w, p_min.w, p_max.w));
+}
+
+Vector4::operator String() const {
+ return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")";
+}
diff --git a/core/math/vector4.h b/core/math/vector4.h
new file mode 100644
index 0000000000..373a6a1218
--- /dev/null
+++ b/core/math/vector4.h
@@ -0,0 +1,302 @@
+/*************************************************************************/
+/* vector4.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 VECTOR4_H
+#define VECTOR4_H
+
+#include "core/math/math_defs.h"
+#include "core/math/math_funcs.h"
+#include "core/math/vector3.h"
+#include "core/string/ustring.h"
+
+struct _NO_DISCARD_ Vector4 {
+ enum Axis {
+ AXIS_X,
+ AXIS_Y,
+ AXIS_Z,
+ AXIS_W,
+ };
+
+ union {
+ struct {
+ real_t x;
+ real_t y;
+ real_t z;
+ real_t w;
+ };
+ real_t components[4] = { 0, 0, 0, 0 };
+ };
+
+ _FORCE_INLINE_ real_t &operator[](const int p_axis) {
+ DEV_ASSERT((unsigned int)p_axis < 4);
+ return components[p_axis];
+ }
+ _FORCE_INLINE_ const real_t &operator[](const int p_axis) const {
+ DEV_ASSERT((unsigned int)p_axis < 4);
+ return components[p_axis];
+ }
+
+ _FORCE_INLINE_ void set_all(const real_t p_value);
+
+ void set_axis(const int p_axis, const real_t p_value);
+ real_t get_axis(const int p_axis) const;
+
+ Vector4::Axis min_axis_index() const;
+ Vector4::Axis max_axis_index() const;
+
+ _FORCE_INLINE_ real_t length_squared() const;
+ bool is_equal_approx(const Vector4 &p_vec4) const;
+ real_t length() const;
+ void normalize();
+ Vector4 normalized() const;
+ bool is_normalized() const;
+
+ real_t distance_to(const Vector4 &p_to) const;
+ Vector4 direction_to(const Vector4 &p_to) const;
+
+ Vector4 abs() const;
+ Vector4 sign() const;
+ Vector4 floor() const;
+ Vector4 ceil() const;
+ Vector4 round() const;
+ Vector4 lerp(const Vector4 &p_to, const real_t p_weight) const;
+ Vector4 cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const;
+
+ Vector4 posmod(const real_t p_mod) const;
+ Vector4 posmodv(const Vector4 &p_modv) const;
+ void snap(const Vector4 &p_step);
+ Vector4 snapped(const Vector4 &p_step) const;
+ Vector4 clamp(const Vector4 &p_min, const Vector4 &p_max) const;
+
+ Vector4 inverse() const;
+ _FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) const;
+
+ _FORCE_INLINE_ void operator+=(const Vector4 &p_vec4);
+ _FORCE_INLINE_ void operator-=(const Vector4 &p_vec4);
+ _FORCE_INLINE_ void operator*=(const Vector4 &p_vec4);
+ _FORCE_INLINE_ void operator/=(const Vector4 &p_vec4);
+ _FORCE_INLINE_ void operator*=(const real_t &s);
+ _FORCE_INLINE_ void operator/=(const real_t &s);
+ _FORCE_INLINE_ Vector4 operator+(const Vector4 &p_vec4) const;
+ _FORCE_INLINE_ Vector4 operator-(const Vector4 &p_vec4) const;
+ _FORCE_INLINE_ Vector4 operator*(const Vector4 &p_vec4) const;
+ _FORCE_INLINE_ Vector4 operator/(const Vector4 &p_vec4) const;
+ _FORCE_INLINE_ Vector4 operator-() const;
+ _FORCE_INLINE_ Vector4 operator*(const real_t &s) const;
+ _FORCE_INLINE_ Vector4 operator/(const real_t &s) const;
+
+ _FORCE_INLINE_ bool operator==(const Vector4 &p_vec4) const;
+ _FORCE_INLINE_ bool operator!=(const Vector4 &p_vec4) const;
+ _FORCE_INLINE_ bool operator>(const Vector4 &p_vec4) const;
+ _FORCE_INLINE_ bool operator<(const Vector4 &p_vec4) const;
+ _FORCE_INLINE_ bool operator>=(const Vector4 &p_vec4) const;
+ _FORCE_INLINE_ bool operator<=(const Vector4 &p_vec4) const;
+
+ operator String() const;
+
+ _FORCE_INLINE_ Vector4() {}
+
+ _FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
+ x(p_x),
+ y(p_y),
+ z(p_z),
+ w(p_w) {
+ }
+
+ Vector4(const Vector4 &p_vec4) :
+ x(p_vec4.x),
+ y(p_vec4.y),
+ z(p_vec4.z),
+ w(p_vec4.w) {
+ }
+
+ void operator=(const Vector4 &p_vec4) {
+ x = p_vec4.x;
+ y = p_vec4.y;
+ z = p_vec4.z;
+ w = p_vec4.w;
+ }
+};
+
+void Vector4::set_all(const real_t p_value) {
+ x = y = z = p_value;
+}
+
+real_t Vector4::dot(const Vector4 &p_vec4) const {
+ return x * p_vec4.x + y * p_vec4.y + z * p_vec4.z + w * p_vec4.w;
+}
+
+real_t Vector4::length_squared() const {
+ return dot(*this);
+}
+
+void Vector4::operator+=(const Vector4 &p_vec4) {
+ x += p_vec4.x;
+ y += p_vec4.y;
+ z += p_vec4.z;
+ w += p_vec4.w;
+}
+
+void Vector4::operator-=(const Vector4 &p_vec4) {
+ x -= p_vec4.x;
+ y -= p_vec4.y;
+ z -= p_vec4.z;
+ w -= p_vec4.w;
+}
+
+void Vector4::operator*=(const Vector4 &p_vec4) {
+ x *= p_vec4.x;
+ y *= p_vec4.y;
+ z *= p_vec4.z;
+ w *= p_vec4.w;
+}
+
+void Vector4::operator/=(const Vector4 &p_vec4) {
+ x /= p_vec4.x;
+ y /= p_vec4.y;
+ z /= p_vec4.z;
+ w /= p_vec4.w;
+}
+void Vector4::operator*=(const real_t &s) {
+ x *= s;
+ y *= s;
+ z *= s;
+ w *= s;
+}
+
+void Vector4::operator/=(const real_t &s) {
+ *this *= 1.0f / s;
+}
+
+Vector4 Vector4::operator+(const Vector4 &p_vec4) const {
+ return Vector4(x + p_vec4.x, y + p_vec4.y, z + p_vec4.z, w + p_vec4.w);
+}
+
+Vector4 Vector4::operator-(const Vector4 &p_vec4) const {
+ return Vector4(x - p_vec4.x, y - p_vec4.y, z - p_vec4.z, w - p_vec4.w);
+}
+
+Vector4 Vector4::operator*(const Vector4 &p_vec4) const {
+ return Vector4(x * p_vec4.x, y * p_vec4.y, z * p_vec4.z, w * p_vec4.w);
+}
+
+Vector4 Vector4::operator/(const Vector4 &p_vec4) const {
+ return Vector4(x / p_vec4.x, y / p_vec4.y, z / p_vec4.z, w / p_vec4.w);
+}
+
+Vector4 Vector4::operator-() const {
+ return Vector4(-x, -y, -z, -w);
+}
+
+Vector4 Vector4::operator*(const real_t &s) const {
+ return Vector4(x * s, y * s, z * s, w * s);
+}
+
+Vector4 Vector4::operator/(const real_t &s) const {
+ return *this * (1.0f / s);
+}
+
+bool Vector4::operator==(const Vector4 &p_vec4) const {
+ return x == p_vec4.x && y == p_vec4.y && z == p_vec4.z && w == p_vec4.w;
+}
+
+bool Vector4::operator!=(const Vector4 &p_vec4) const {
+ return x != p_vec4.x || y != p_vec4.y || z != p_vec4.z || w != p_vec4.w;
+}
+
+bool Vector4::operator<(const Vector4 &p_v) const {
+ if (x == p_v.x) {
+ if (y == p_v.y) {
+ if (z == p_v.z) {
+ return w < p_v.w;
+ }
+ return z < p_v.z;
+ }
+ return y < p_v.y;
+ }
+ return x < p_v.x;
+}
+
+bool Vector4::operator>(const Vector4 &p_v) const {
+ if (x == p_v.x) {
+ if (y == p_v.y) {
+ if (z == p_v.z) {
+ return w > p_v.w;
+ }
+ return z > p_v.z;
+ }
+ return y > p_v.y;
+ }
+ return x > p_v.x;
+}
+
+bool Vector4::operator<=(const Vector4 &p_v) const {
+ if (x == p_v.x) {
+ if (y == p_v.y) {
+ if (z == p_v.z) {
+ return w <= p_v.w;
+ }
+ return z < p_v.z;
+ }
+ return y < p_v.y;
+ }
+ return x < p_v.x;
+}
+
+bool Vector4::operator>=(const Vector4 &p_v) const {
+ if (x == p_v.x) {
+ if (y == p_v.y) {
+ if (z == p_v.z) {
+ return w >= p_v.w;
+ }
+ return z > p_v.z;
+ }
+ return y > p_v.y;
+ }
+ return x > p_v.x;
+}
+
+_FORCE_INLINE_ Vector4 operator*(const float p_scalar, const Vector4 &p_vec) {
+ return p_vec * p_scalar;
+}
+
+_FORCE_INLINE_ Vector4 operator*(const double p_scalar, const Vector4 &p_vec) {
+ return p_vec * p_scalar;
+}
+
+_FORCE_INLINE_ Vector4 operator*(const int32_t p_scalar, const Vector4 &p_vec) {
+ return p_vec * p_scalar;
+}
+
+_FORCE_INLINE_ Vector4 operator*(const int64_t p_scalar, const Vector4 &p_vec) {
+ return p_vec * p_scalar;
+}
+
+#endif // VECTOR4_H
diff --git a/core/templates/thread_work_pool.cpp b/core/math/vector4i.cpp
index a75fd06b9b..2dc5b74202 100644
--- a/core/templates/thread_work_pool.cpp
+++ b/core/math/vector4i.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* thread_work_pool.cpp */
+/* vector4i.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,54 +28,64 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "thread_work_pool.h"
+#include "vector4i.h"
-#include "core/os/os.h"
+#include "core/math/vector4.h"
+#include "core/string/ustring.h"
-void ThreadWorkPool::_thread_function(void *p_user) {
- ThreadData *thread = static_cast<ThreadData *>(p_user);
- while (true) {
- thread->start.wait();
- if (thread->exit.load()) {
- break;
- }
- thread->work->work();
- thread->completed.post();
- }
+void Vector4i::set_axis(const int p_axis, const int32_t p_value) {
+ ERR_FAIL_INDEX(p_axis, 4);
+ coord[p_axis] = p_value;
}
-void ThreadWorkPool::init(int p_thread_count) {
- ERR_FAIL_COND(threads != nullptr);
- if (p_thread_count < 0) {
- p_thread_count = OS::get_singleton()->get_default_thread_pool_size();
- }
-
- thread_count = p_thread_count;
- threads = memnew_arr(ThreadData, thread_count);
+int32_t Vector4i::get_axis(const int p_axis) const {
+ ERR_FAIL_INDEX_V(p_axis, 4, 0);
+ return operator[](p_axis);
+}
- for (uint32_t i = 0; i < thread_count; i++) {
- threads[i].exit.store(false);
- threads[i].thread.start(&ThreadWorkPool::_thread_function, &threads[i]);
+Vector4i::Axis Vector4i::min_axis_index() const {
+ uint32_t min_index = 0;
+ int32_t min_value = x;
+ for (uint32_t i = 1; i < 4; i++) {
+ if (operator[](i) <= min_value) {
+ min_index = i;
+ min_value = operator[](i);
+ }
}
+ return Vector4i::Axis(min_index);
}
-void ThreadWorkPool::finish() {
- if (threads == nullptr) {
- return;
+Vector4i::Axis Vector4i::max_axis_index() const {
+ uint32_t max_index = 0;
+ int32_t max_value = x;
+ for (uint32_t i = 1; i < 4; i++) {
+ if (operator[](i) > max_value) {
+ max_index = i;
+ max_value = operator[](i);
+ }
}
+ return Vector4i::Axis(max_index);
+}
- for (uint32_t i = 0; i < thread_count; i++) {
- threads[i].exit.store(true);
- threads[i].start.post();
- }
- for (uint32_t i = 0; i < thread_count; i++) {
- threads[i].thread.wait_to_finish();
- }
+Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const {
+ return Vector4i(
+ CLAMP(x, p_min.x, p_max.x),
+ CLAMP(y, p_min.y, p_max.y),
+ CLAMP(z, p_min.z, p_max.z),
+ CLAMP(w, p_min.w, p_max.w));
+}
+
+Vector4i::operator String() const {
+ return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")";
+}
- memdelete_arr(threads);
- threads = nullptr;
+Vector4i::operator Vector4() const {
+ return Vector4(x, y, z, w);
}
-ThreadWorkPool::~ThreadWorkPool() {
- finish();
+Vector4i::Vector4i(const Vector4 &p_vec4) {
+ x = p_vec4.x;
+ y = p_vec4.y;
+ z = p_vec4.z;
+ w = p_vec4.w;
}
diff --git a/core/math/vector4i.h b/core/math/vector4i.h
new file mode 100644
index 0000000000..37d905878f
--- /dev/null
+++ b/core/math/vector4i.h
@@ -0,0 +1,338 @@
+/*************************************************************************/
+/* vector4i.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 VECTOR4I_H
+#define VECTOR4I_H
+
+#include "core/error/error_macros.h"
+#include "core/math/math_funcs.h"
+
+class String;
+struct Vector4;
+
+struct _NO_DISCARD_ Vector4i {
+ enum Axis {
+ AXIS_X,
+ AXIS_Y,
+ AXIS_Z,
+ AXIS_W,
+ };
+
+ union {
+ struct {
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int32_t w;
+ };
+
+ int32_t coord[4] = { 0 };
+ };
+
+ _FORCE_INLINE_ const int32_t &operator[](const int p_axis) const {
+ DEV_ASSERT((unsigned int)p_axis < 4);
+ return coord[p_axis];
+ }
+
+ _FORCE_INLINE_ int32_t &operator[](const int p_axis) {
+ DEV_ASSERT((unsigned int)p_axis < 4);
+ return coord[p_axis];
+ }
+
+ void set_axis(const int p_axis, const int32_t p_value);
+ int32_t get_axis(const int p_axis) const;
+
+ Vector4i::Axis min_axis_index() const;
+ Vector4i::Axis max_axis_index() const;
+
+ _FORCE_INLINE_ int64_t length_squared() const;
+ _FORCE_INLINE_ double length() const;
+
+ _FORCE_INLINE_ void zero();
+
+ _FORCE_INLINE_ Vector4i abs() const;
+ _FORCE_INLINE_ Vector4i sign() const;
+ Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const;
+
+ /* Operators */
+
+ _FORCE_INLINE_ Vector4i &operator+=(const Vector4i &p_v);
+ _FORCE_INLINE_ Vector4i operator+(const Vector4i &p_v) const;
+ _FORCE_INLINE_ Vector4i &operator-=(const Vector4i &p_v);
+ _FORCE_INLINE_ Vector4i operator-(const Vector4i &p_v) const;
+ _FORCE_INLINE_ Vector4i &operator*=(const Vector4i &p_v);
+ _FORCE_INLINE_ Vector4i operator*(const Vector4i &p_v) const;
+ _FORCE_INLINE_ Vector4i &operator/=(const Vector4i &p_v);
+ _FORCE_INLINE_ Vector4i operator/(const Vector4i &p_v) const;
+ _FORCE_INLINE_ Vector4i &operator%=(const Vector4i &p_v);
+ _FORCE_INLINE_ Vector4i operator%(const Vector4i &p_v) const;
+
+ _FORCE_INLINE_ Vector4i &operator*=(const int32_t p_scalar);
+ _FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar) const;
+ _FORCE_INLINE_ Vector4i &operator/=(const int32_t p_scalar);
+ _FORCE_INLINE_ Vector4i operator/(const int32_t p_scalar) const;
+ _FORCE_INLINE_ Vector4i &operator%=(const int32_t p_scalar);
+ _FORCE_INLINE_ Vector4i operator%(const int32_t p_scalar) const;
+
+ _FORCE_INLINE_ Vector4i operator-() const;
+
+ _FORCE_INLINE_ bool operator==(const Vector4i &p_v) const;
+ _FORCE_INLINE_ bool operator!=(const Vector4i &p_v) const;
+ _FORCE_INLINE_ bool operator<(const Vector4i &p_v) const;
+ _FORCE_INLINE_ bool operator<=(const Vector4i &p_v) const;
+ _FORCE_INLINE_ bool operator>(const Vector4i &p_v) const;
+ _FORCE_INLINE_ bool operator>=(const Vector4i &p_v) const;
+
+ operator String() const;
+ operator Vector4() const;
+
+ _FORCE_INLINE_ Vector4i() {}
+ Vector4i(const Vector4 &p_vec4);
+ _FORCE_INLINE_ Vector4i(const int32_t p_x, const int32_t p_y, const int32_t p_z, const int32_t p_w) {
+ x = p_x;
+ y = p_y;
+ z = p_z;
+ w = p_w;
+ }
+};
+
+int64_t Vector4i::length_squared() const {
+ return x * (int64_t)x + y * (int64_t)y + z * (int64_t)z + w * (int64_t)w;
+}
+
+double Vector4i::length() const {
+ return Math::sqrt((double)length_squared());
+}
+
+Vector4i Vector4i::abs() const {
+ return Vector4i(ABS(x), ABS(y), ABS(z), ABS(w));
+}
+
+Vector4i Vector4i::sign() const {
+ return Vector4i(SIGN(x), SIGN(y), SIGN(z), SIGN(w));
+}
+
+/* Operators */
+
+Vector4i &Vector4i::operator+=(const Vector4i &p_v) {
+ x += p_v.x;
+ y += p_v.y;
+ z += p_v.z;
+ w += p_v.w;
+ return *this;
+}
+
+Vector4i Vector4i::operator+(const Vector4i &p_v) const {
+ return Vector4i(x + p_v.x, y + p_v.y, z + p_v.z, w + p_v.w);
+}
+
+Vector4i &Vector4i::operator-=(const Vector4i &p_v) {
+ x -= p_v.x;
+ y -= p_v.y;
+ z -= p_v.z;
+ w -= p_v.w;
+ return *this;
+}
+
+Vector4i Vector4i::operator-(const Vector4i &p_v) const {
+ return Vector4i(x - p_v.x, y - p_v.y, z - p_v.z, w - p_v.w);
+}
+
+Vector4i &Vector4i::operator*=(const Vector4i &p_v) {
+ x *= p_v.x;
+ y *= p_v.y;
+ z *= p_v.z;
+ w *= p_v.w;
+ return *this;
+}
+
+Vector4i Vector4i::operator*(const Vector4i &p_v) const {
+ return Vector4i(x * p_v.x, y * p_v.y, z * p_v.z, w * p_v.w);
+}
+
+Vector4i &Vector4i::operator/=(const Vector4i &p_v) {
+ x /= p_v.x;
+ y /= p_v.y;
+ z /= p_v.z;
+ w /= p_v.w;
+ return *this;
+}
+
+Vector4i Vector4i::operator/(const Vector4i &p_v) const {
+ return Vector4i(x / p_v.x, y / p_v.y, z / p_v.z, w / p_v.w);
+}
+
+Vector4i &Vector4i::operator%=(const Vector4i &p_v) {
+ x %= p_v.x;
+ y %= p_v.y;
+ z %= p_v.z;
+ w %= p_v.w;
+ return *this;
+}
+
+Vector4i Vector4i::operator%(const Vector4i &p_v) const {
+ return Vector4i(x % p_v.x, y % p_v.y, z % p_v.z, w % p_v.w);
+}
+
+Vector4i &Vector4i::operator*=(const int32_t p_scalar) {
+ x *= p_scalar;
+ y *= p_scalar;
+ z *= p_scalar;
+ w *= p_scalar;
+ return *this;
+}
+
+Vector4i Vector4i::operator*(const int32_t p_scalar) const {
+ return Vector4i(x * p_scalar, y * p_scalar, z * p_scalar, w * p_scalar);
+}
+
+// Multiplication operators required to workaround issues with LLVM using implicit conversion.
+
+_FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar, const Vector4i &p_vector) {
+ return p_vector * p_scalar;
+}
+
+_FORCE_INLINE_ Vector4i operator*(const int64_t p_scalar, const Vector4i &p_vector) {
+ return p_vector * p_scalar;
+}
+
+_FORCE_INLINE_ Vector4i operator*(const float p_scalar, const Vector4i &p_vector) {
+ return p_vector * p_scalar;
+}
+
+_FORCE_INLINE_ Vector4i operator*(const double p_scalar, const Vector4i &p_vector) {
+ return p_vector * p_scalar;
+}
+
+Vector4i &Vector4i::operator/=(const int32_t p_scalar) {
+ x /= p_scalar;
+ y /= p_scalar;
+ z /= p_scalar;
+ w /= p_scalar;
+ return *this;
+}
+
+Vector4i Vector4i::operator/(const int32_t p_scalar) const {
+ return Vector4i(x / p_scalar, y / p_scalar, z / p_scalar, w / p_scalar);
+}
+
+Vector4i &Vector4i::operator%=(const int32_t p_scalar) {
+ x %= p_scalar;
+ y %= p_scalar;
+ z %= p_scalar;
+ w %= p_scalar;
+ return *this;
+}
+
+Vector4i Vector4i::operator%(const int32_t p_scalar) const {
+ return Vector4i(x % p_scalar, y % p_scalar, z % p_scalar, w % p_scalar);
+}
+
+Vector4i Vector4i::operator-() const {
+ return Vector4i(-x, -y, -z, -w);
+}
+
+bool Vector4i::operator==(const Vector4i &p_v) const {
+ return (x == p_v.x && y == p_v.y && z == p_v.z && w == p_v.w);
+}
+
+bool Vector4i::operator!=(const Vector4i &p_v) const {
+ return (x != p_v.x || y != p_v.y || z != p_v.z || w != p_v.w);
+}
+
+bool Vector4i::operator<(const Vector4i &p_v) const {
+ if (x == p_v.x) {
+ if (y == p_v.y) {
+ if (z == p_v.z) {
+ return w < p_v.w;
+ } else {
+ return z < p_v.z;
+ }
+ } else {
+ return y < p_v.y;
+ }
+ } else {
+ return x < p_v.x;
+ }
+}
+
+bool Vector4i::operator>(const Vector4i &p_v) const {
+ if (x == p_v.x) {
+ if (y == p_v.y) {
+ if (z == p_v.z) {
+ return w > p_v.w;
+ } else {
+ return z > p_v.z;
+ }
+ } else {
+ return y > p_v.y;
+ }
+ } else {
+ return x > p_v.x;
+ }
+}
+
+bool Vector4i::operator<=(const Vector4i &p_v) const {
+ if (x == p_v.x) {
+ if (y == p_v.y) {
+ if (z == p_v.z) {
+ return w <= p_v.w;
+ } else {
+ return z < p_v.z;
+ }
+ } else {
+ return y < p_v.y;
+ }
+ } else {
+ return x < p_v.x;
+ }
+}
+
+bool Vector4i::operator>=(const Vector4i &p_v) const {
+ if (x == p_v.x) {
+ if (y == p_v.y) {
+ if (z == p_v.z) {
+ return w >= p_v.w;
+ } else {
+ return z > p_v.z;
+ }
+ } else {
+ return y > p_v.y;
+ }
+ } else {
+ return x > p_v.x;
+ }
+}
+
+void Vector4i::zero() {
+ x = y = z = w = 0;
+}
+
+#endif // VECTOR4I_H
diff --git a/core/multiplayer/SCsub b/core/multiplayer/SCsub
deleted file mode 100644
index 19a6549225..0000000000
--- a/core/multiplayer/SCsub
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-
-env.add_source_files(env.core_sources, "*.cpp")
diff --git a/core/multiplayer/multiplayer.h b/core/multiplayer/multiplayer.h
deleted file mode 100644
index f4c965b0f8..0000000000
--- a/core/multiplayer/multiplayer.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*************************************************************************/
-/* multiplayer.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 MULTIPLAYER_H
-#define MULTIPLAYER_H
-
-#include "core/variant/binder_common.h"
-
-#include "core/string/string_name.h"
-
-namespace Multiplayer {
-
-enum TransferMode {
- TRANSFER_MODE_UNRELIABLE,
- TRANSFER_MODE_UNRELIABLE_ORDERED,
- TRANSFER_MODE_RELIABLE
-};
-
-enum RPCMode {
- RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
- RPC_MODE_ANY_PEER, // Any peer can call this RPC
- RPC_MODE_AUTHORITY, // Only the node's multiplayer authority (server by default) can call this RPC
-};
-
-struct RPCConfig {
- StringName name;
- RPCMode rpc_mode = RPC_MODE_DISABLED;
- bool call_local = false;
- TransferMode transfer_mode = TRANSFER_MODE_RELIABLE;
- int channel = 0;
-
- bool operator==(RPCConfig const &p_other) const {
- return name == p_other.name;
- }
-};
-
-struct SortRPCConfig {
- StringName::AlphCompare compare;
- bool operator()(const RPCConfig &p_a, const RPCConfig &p_b) const {
- return compare(p_a.name, p_b.name);
- }
-};
-
-}; // namespace Multiplayer
-
-// This is needed for proper docs generation (i.e. not "Multiplayer."-prefixed).
-typedef Multiplayer::RPCMode RPCMode;
-typedef Multiplayer::TransferMode TransferMode;
-
-VARIANT_ENUM_CAST(RPCMode);
-VARIANT_ENUM_CAST(TransferMode);
-
-#endif // MULTIPLAYER_H
diff --git a/core/multiplayer/multiplayer_api.cpp b/core/multiplayer/multiplayer_api.cpp
deleted file mode 100644
index 9605647b3f..0000000000
--- a/core/multiplayer/multiplayer_api.cpp
+++ /dev/null
@@ -1,589 +0,0 @@
-/*************************************************************************/
-/* multiplayer_api.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 "multiplayer_api.h"
-
-#include "core/debugger/engine_debugger.h"
-#include "core/io/marshalls.h"
-
-#include <stdint.h>
-
-#ifdef DEBUG_ENABLED
-#include "core/os/os.h"
-#endif
-
-MultiplayerReplicationInterface *(*MultiplayerAPI::create_default_replication_interface)(MultiplayerAPI *p_multiplayer) = nullptr;
-MultiplayerRPCInterface *(*MultiplayerAPI::create_default_rpc_interface)(MultiplayerAPI *p_multiplayer) = nullptr;
-MultiplayerCacheInterface *(*MultiplayerAPI::create_default_cache_interface)(MultiplayerAPI *p_multiplayer) = nullptr;
-
-#ifdef DEBUG_ENABLED
-void MultiplayerAPI::profile_bandwidth(const String &p_inout, int p_size) {
- if (EngineDebugger::is_profiling("multiplayer")) {
- Array values;
- values.push_back(p_inout);
- values.push_back(OS::get_singleton()->get_ticks_msec());
- values.push_back(p_size);
- EngineDebugger::profiler_add_frame_data("multiplayer", values);
- }
-}
-#endif
-
-void MultiplayerAPI::poll() {
- if (!multiplayer_peer.is_valid() || multiplayer_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED) {
- return;
- }
-
- multiplayer_peer->poll();
-
- if (!multiplayer_peer.is_valid()) { // It's possible that polling might have resulted in a disconnection, so check here.
- return;
- }
-
- while (multiplayer_peer->get_available_packet_count()) {
- int sender = multiplayer_peer->get_packet_peer();
- const uint8_t *packet;
- int len;
-
- Error err = multiplayer_peer->get_packet(&packet, len);
- if (err != OK) {
- ERR_PRINT("Error getting packet!");
- return; // Something is wrong!
- }
-
- remote_sender_id = sender;
- _process_packet(sender, packet, len);
- remote_sender_id = 0;
-
- if (!multiplayer_peer.is_valid()) {
- return; // It's also possible that a packet or RPC caused a disconnection, so also check here.
- }
- }
- replicator->on_network_process();
-}
-
-void MultiplayerAPI::clear() {
- connected_peers.clear();
- packet_cache.clear();
- cache->clear();
-}
-
-void MultiplayerAPI::set_root_path(const NodePath &p_path) {
- ERR_FAIL_COND_MSG(!p_path.is_absolute() && !p_path.is_empty(), "MultiplayerAPI root path must be absolute.");
- root_path = p_path;
-}
-
-NodePath MultiplayerAPI::get_root_path() const {
- return root_path;
-}
-
-void MultiplayerAPI::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) {
- if (p_peer == multiplayer_peer) {
- return; // Nothing to do
- }
-
- ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED,
- "Supplied MultiplayerPeer must be connecting or connected.");
-
- if (multiplayer_peer.is_valid()) {
- multiplayer_peer->disconnect("peer_connected", callable_mp(this, &MultiplayerAPI::_add_peer));
- multiplayer_peer->disconnect("peer_disconnected", callable_mp(this, &MultiplayerAPI::_del_peer));
- multiplayer_peer->disconnect("connection_succeeded", callable_mp(this, &MultiplayerAPI::_connected_to_server));
- multiplayer_peer->disconnect("connection_failed", callable_mp(this, &MultiplayerAPI::_connection_failed));
- multiplayer_peer->disconnect("server_disconnected", callable_mp(this, &MultiplayerAPI::_server_disconnected));
- clear();
- }
-
- multiplayer_peer = p_peer;
-
- if (multiplayer_peer.is_valid()) {
- multiplayer_peer->connect("peer_connected", callable_mp(this, &MultiplayerAPI::_add_peer));
- multiplayer_peer->connect("peer_disconnected", callable_mp(this, &MultiplayerAPI::_del_peer));
- multiplayer_peer->connect("connection_succeeded", callable_mp(this, &MultiplayerAPI::_connected_to_server));
- multiplayer_peer->connect("connection_failed", callable_mp(this, &MultiplayerAPI::_connection_failed));
- multiplayer_peer->connect("server_disconnected", callable_mp(this, &MultiplayerAPI::_server_disconnected));
- }
- replicator->on_reset();
-}
-
-Ref<MultiplayerPeer> MultiplayerAPI::get_multiplayer_peer() const {
- return multiplayer_peer;
-}
-
-void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) {
- ERR_FAIL_COND_MSG(root_path.is_empty(), "Multiplayer root was not initialized. If you are using custom multiplayer, remember to set the root path via MultiplayerAPI.set_root_path before using it.");
- ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small.");
-
-#ifdef DEBUG_ENABLED
- profile_bandwidth("in", p_packet_len);
-#endif
-
- // Extract the `packet_type` from the LSB three bits:
- uint8_t packet_type = p_packet[0] & CMD_MASK;
-
- switch (packet_type) {
- case NETWORK_COMMAND_SIMPLIFY_PATH: {
- cache->process_simplify_path(p_from, p_packet, p_packet_len);
- } break;
-
- case NETWORK_COMMAND_CONFIRM_PATH: {
- cache->process_confirm_path(p_from, p_packet, p_packet_len);
- } break;
-
- case NETWORK_COMMAND_REMOTE_CALL: {
- rpc->process_rpc(p_from, p_packet, p_packet_len);
- } break;
-
- case NETWORK_COMMAND_RAW: {
- _process_raw(p_from, p_packet, p_packet_len);
- } break;
- case NETWORK_COMMAND_SPAWN: {
- replicator->on_spawn_receive(p_from, p_packet, p_packet_len);
- } break;
- case NETWORK_COMMAND_DESPAWN: {
- replicator->on_despawn_receive(p_from, p_packet, p_packet_len);
- } break;
- case NETWORK_COMMAND_SYNC: {
- replicator->on_sync_receive(p_from, p_packet, p_packet_len);
- } break;
- }
-}
-
-// The variant is compressed and encoded; The first byte contains all the meta
-// information and the format is:
-// - The first LSB 5 bits are used for the variant type.
-// - The next two bits are used to store the encoding mode.
-// - The most significant is used to store the boolean value.
-#define VARIANT_META_TYPE_MASK 0x1F
-#define VARIANT_META_EMODE_MASK 0x60
-#define VARIANT_META_BOOL_MASK 0x80
-#define ENCODE_8 0 << 5
-#define ENCODE_16 1 << 5
-#define ENCODE_32 2 << 5
-#define ENCODE_64 3 << 5
-Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_allow_object_decoding) {
- // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31
- CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK);
-
- uint8_t *buf = r_buffer;
- r_len = 0;
- uint8_t encode_mode = 0;
-
- switch (p_variant.get_type()) {
- case Variant::BOOL: {
- if (buf) {
- // We still have 1 free bit in the meta, so let's use it.
- buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0;
- buf[0] |= encode_mode | p_variant.get_type();
- }
- r_len += 1;
- } break;
- case Variant::INT: {
- if (buf) {
- // Reserve the first byte for the meta.
- buf += 1;
- }
- r_len += 1;
- int64_t val = p_variant;
- if (val <= (int64_t)INT8_MAX && val >= (int64_t)INT8_MIN) {
- // Use 8 bit
- encode_mode = ENCODE_8;
- if (buf) {
- buf[0] = val;
- }
- r_len += 1;
- } else if (val <= (int64_t)INT16_MAX && val >= (int64_t)INT16_MIN) {
- // Use 16 bit
- encode_mode = ENCODE_16;
- if (buf) {
- encode_uint16(val, buf);
- }
- r_len += 2;
- } else if (val <= (int64_t)INT32_MAX && val >= (int64_t)INT32_MIN) {
- // Use 32 bit
- encode_mode = ENCODE_32;
- if (buf) {
- encode_uint32(val, buf);
- }
- r_len += 4;
- } else {
- // Use 64 bit
- encode_mode = ENCODE_64;
- if (buf) {
- encode_uint64(val, buf);
- }
- r_len += 8;
- }
- // Store the meta
- if (buf) {
- buf -= 1;
- buf[0] = encode_mode | p_variant.get_type();
- }
- } break;
- default:
- // Any other case is not yet compressed.
- Error err = encode_variant(p_variant, r_buffer, r_len, p_allow_object_decoding);
- if (err != OK) {
- return err;
- }
- if (r_buffer) {
- // The first byte is not used by the marshalling, so store the type
- // so we know how to decompress and decode this variant.
- r_buffer[0] = p_variant.get_type();
- }
- }
-
- return OK;
-}
-
-Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding) {
- const uint8_t *buf = p_buffer;
- int len = p_len;
-
- ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA);
- uint8_t type = buf[0] & VARIANT_META_TYPE_MASK;
- uint8_t encode_mode = buf[0] & VARIANT_META_EMODE_MASK;
-
- ERR_FAIL_COND_V(type >= Variant::VARIANT_MAX, ERR_INVALID_DATA);
-
- switch (type) {
- case Variant::BOOL: {
- bool val = (buf[0] & VARIANT_META_BOOL_MASK) > 0;
- r_variant = val;
- if (r_len) {
- *r_len = 1;
- }
- } break;
- case Variant::INT: {
- buf += 1;
- len -= 1;
- if (r_len) {
- *r_len = 1;
- }
- if (encode_mode == ENCODE_8) {
- // 8 bits.
- ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA);
- int8_t val = buf[0];
- r_variant = val;
- if (r_len) {
- (*r_len) += 1;
- }
- } else if (encode_mode == ENCODE_16) {
- // 16 bits.
- ERR_FAIL_COND_V(len < 2, ERR_INVALID_DATA);
- int16_t val = decode_uint16(buf);
- r_variant = val;
- if (r_len) {
- (*r_len) += 2;
- }
- } else if (encode_mode == ENCODE_32) {
- // 32 bits.
- ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- int32_t val = decode_uint32(buf);
- r_variant = val;
- if (r_len) {
- (*r_len) += 4;
- }
- } else {
- // 64 bits.
- ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
- int64_t val = decode_uint64(buf);
- r_variant = val;
- if (r_len) {
- (*r_len) += 8;
- }
- }
- } break;
- default:
- Error err = decode_variant(r_variant, p_buffer, p_len, r_len, p_allow_object_decoding);
- if (err != OK) {
- return err;
- }
- }
-
- return OK;
-}
-
-Error MultiplayerAPI::encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw, bool p_allow_object_decoding) {
- r_len = 0;
- int size = 0;
-
- if (p_count == 0) {
- if (r_raw) {
- *r_raw = true;
- }
- return OK;
- }
-
- // Try raw encoding optimization.
- if (r_raw && p_count == 1) {
- *r_raw = false;
- const Variant &v = *(p_variants[0]);
- if (v.get_type() == Variant::PACKED_BYTE_ARRAY) {
- *r_raw = true;
- const PackedByteArray pba = v;
- if (p_buffer) {
- memcpy(p_buffer, pba.ptr(), pba.size());
- }
- r_len += pba.size();
- } else {
- encode_and_compress_variant(v, p_buffer, size, p_allow_object_decoding);
- r_len += size;
- }
- return OK;
- }
-
- // Regular encoding.
- for (int i = 0; i < p_count; i++) {
- const Variant &v = *(p_variants[i]);
- encode_and_compress_variant(v, p_buffer ? p_buffer + r_len : nullptr, size, p_allow_object_decoding);
- r_len += size;
- }
- return OK;
-}
-
-Error MultiplayerAPI::decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw, bool p_allow_object_decoding) {
- r_len = 0;
- int argc = r_variants.size();
- if (argc == 0 && p_raw) {
- return OK;
- }
- ERR_FAIL_COND_V(p_raw && argc != 1, ERR_INVALID_DATA);
- if (p_raw) {
- r_len = p_len;
- PackedByteArray pba;
- pba.resize(p_len);
- memcpy(pba.ptrw(), p_buffer, p_len);
- r_variants.write[0] = pba;
- return OK;
- }
-
- Vector<Variant> args;
- Vector<const Variant *> argp;
- args.resize(argc);
-
- for (int i = 0; i < argc; i++) {
- ERR_FAIL_COND_V_MSG(r_len >= p_len, ERR_INVALID_DATA, "Invalid packet received. Size too small.");
-
- int vlen;
- Error err = MultiplayerAPI::decode_and_decompress_variant(r_variants.write[i], &p_buffer[r_len], p_len - r_len, &vlen, p_allow_object_decoding);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid packet received. Unable to decode state variable.");
- r_len += vlen;
- }
- return OK;
-}
-
-void MultiplayerAPI::_add_peer(int p_id) {
- connected_peers.insert(p_id);
- cache->on_peer_change(p_id, true);
- replicator->on_peer_change(p_id, true);
- emit_signal(SNAME("peer_connected"), p_id);
-}
-
-void MultiplayerAPI::_del_peer(int p_id) {
- replicator->on_peer_change(p_id, false);
- cache->on_peer_change(p_id, false);
- connected_peers.erase(p_id);
- emit_signal(SNAME("peer_disconnected"), p_id);
-}
-
-void MultiplayerAPI::_connected_to_server() {
- emit_signal(SNAME("connected_to_server"));
-}
-
-void MultiplayerAPI::_connection_failed() {
- emit_signal(SNAME("connection_failed"));
-}
-
-void MultiplayerAPI::_server_disconnected() {
- replicator->on_reset();
- emit_signal(SNAME("server_disconnected"));
-}
-
-Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, Multiplayer::TransferMode p_mode, int p_channel) {
- ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet.");
- ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no multiplayer peer is active.");
- ERR_FAIL_COND_V_MSG(multiplayer_peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a multiplayer peer which is not connected.");
-
- if (packet_cache.size() < p_data.size() + 1) {
- packet_cache.resize(p_data.size() + 1);
- }
-
- const uint8_t *r = p_data.ptr();
- packet_cache.write[0] = NETWORK_COMMAND_RAW;
- memcpy(&packet_cache.write[1], &r[0], p_data.size());
-
- multiplayer_peer->set_target_peer(p_to);
- multiplayer_peer->set_transfer_channel(p_channel);
- multiplayer_peer->set_transfer_mode(p_mode);
-
- return multiplayer_peer->put_packet(packet_cache.ptr(), p_data.size() + 1);
-}
-
-void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) {
- ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small.");
-
- Vector<uint8_t> out;
- int len = p_packet_len - 1;
- out.resize(len);
- {
- uint8_t *w = out.ptrw();
- memcpy(&w[0], &p_packet[1], len);
- }
- emit_signal(SNAME("peer_packet"), p_from, out);
-}
-
-bool MultiplayerAPI::is_cache_confirmed(NodePath p_path, int p_peer) {
- return cache->is_cache_confirmed(p_path, p_peer);
-}
-
-bool MultiplayerAPI::send_object_cache(Object *p_obj, NodePath p_path, int p_peer_id, int &r_id) {
- return cache->send_object_cache(p_obj, p_path, p_peer_id, r_id);
-}
-
-Object *MultiplayerAPI::get_cached_object(int p_from, uint32_t p_cache_id) {
- return cache->get_cached_object(p_from, p_cache_id);
-}
-
-int MultiplayerAPI::get_unique_id() const {
- ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), 0, "No multiplayer peer is assigned. Unable to get unique ID.");
- return multiplayer_peer->get_unique_id();
-}
-
-bool MultiplayerAPI::is_server() const {
- return multiplayer_peer.is_valid() && multiplayer_peer->is_server();
-}
-
-void MultiplayerAPI::set_refuse_new_connections(bool p_refuse) {
- ERR_FAIL_COND_MSG(!multiplayer_peer.is_valid(), "No multiplayer peer is assigned. Unable to set 'refuse_new_connections'.");
- multiplayer_peer->set_refuse_new_connections(p_refuse);
-}
-
-bool MultiplayerAPI::is_refusing_new_connections() const {
- ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), false, "No multiplayer peer is assigned. Unable to get 'refuse_new_connections'.");
- return multiplayer_peer->is_refusing_new_connections();
-}
-
-Vector<int> MultiplayerAPI::get_peer_ids() const {
- ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), Vector<int>(), "No multiplayer peer is assigned. Assume no peers are connected.");
-
- Vector<int> ret;
- for (const int &E : connected_peers) {
- ret.push_back(E);
- }
-
- return ret;
-}
-
-void MultiplayerAPI::set_allow_object_decoding(bool p_enable) {
- allow_object_decoding = p_enable;
-}
-
-bool MultiplayerAPI::is_object_decoding_allowed() const {
- return allow_object_decoding;
-}
-
-String MultiplayerAPI::get_rpc_md5(const Object *p_obj) const {
- return rpc->get_rpc_md5(p_obj);
-}
-
-void MultiplayerAPI::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
- rpc->rpcp(p_obj, p_peer_id, p_method, p_arg, p_argcount);
-}
-
-Error MultiplayerAPI::spawn(Object *p_object, Variant p_config) {
- return replicator->on_spawn(p_object, p_config);
-}
-
-Error MultiplayerAPI::despawn(Object *p_object, Variant p_config) {
- return replicator->on_despawn(p_object, p_config);
-}
-
-Error MultiplayerAPI::replication_start(Object *p_object, Variant p_config) {
- return replicator->on_replication_start(p_object, p_config);
-}
-
-Error MultiplayerAPI::replication_stop(Object *p_object, Variant p_config) {
- return replicator->on_replication_stop(p_object, p_config);
-}
-
-void MultiplayerAPI::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_root_path", "path"), &MultiplayerAPI::set_root_path);
- ClassDB::bind_method(D_METHOD("get_root_path"), &MultiplayerAPI::get_root_path);
- ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode", "channel"), &MultiplayerAPI::send_bytes, DEFVAL(MultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
- ClassDB::bind_method(D_METHOD("has_multiplayer_peer"), &MultiplayerAPI::has_multiplayer_peer);
- ClassDB::bind_method(D_METHOD("get_multiplayer_peer"), &MultiplayerAPI::get_multiplayer_peer);
- ClassDB::bind_method(D_METHOD("set_multiplayer_peer", "peer"), &MultiplayerAPI::set_multiplayer_peer);
- ClassDB::bind_method(D_METHOD("get_unique_id"), &MultiplayerAPI::get_unique_id);
- ClassDB::bind_method(D_METHOD("is_server"), &MultiplayerAPI::is_server);
- ClassDB::bind_method(D_METHOD("get_remote_sender_id"), &MultiplayerAPI::get_remote_sender_id);
- ClassDB::bind_method(D_METHOD("poll"), &MultiplayerAPI::poll);
- ClassDB::bind_method(D_METHOD("clear"), &MultiplayerAPI::clear);
-
- ClassDB::bind_method(D_METHOD("get_peers"), &MultiplayerAPI::get_peer_ids);
- ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "refuse"), &MultiplayerAPI::set_refuse_new_connections);
- ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &MultiplayerAPI::is_refusing_new_connections);
- ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &MultiplayerAPI::set_allow_object_decoding);
- ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &MultiplayerAPI::is_object_decoding_allowed);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer_peer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerPeer", PROPERTY_USAGE_NONE), "set_multiplayer_peer", "get_multiplayer_peer");
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path");
- ADD_PROPERTY_DEFAULT("refuse_new_connections", false);
-
- ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id")));
- ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id")));
- ADD_SIGNAL(MethodInfo("peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "packet")));
- ADD_SIGNAL(MethodInfo("connected_to_server"));
- ADD_SIGNAL(MethodInfo("connection_failed"));
- ADD_SIGNAL(MethodInfo("server_disconnected"));
-}
-
-MultiplayerAPI::MultiplayerAPI() {
- if (create_default_replication_interface) {
- replicator = Ref<MultiplayerReplicationInterface>(create_default_replication_interface(this));
- } else {
- replicator.instantiate();
- }
- if (create_default_rpc_interface) {
- rpc = Ref<MultiplayerRPCInterface>(create_default_rpc_interface(this));
- } else {
- rpc.instantiate();
- }
- if (create_default_cache_interface) {
- cache = Ref<MultiplayerCacheInterface>(create_default_cache_interface(this));
- } else {
- cache.instantiate();
- }
-}
-
-MultiplayerAPI::~MultiplayerAPI() {
- clear();
-}
diff --git a/core/multiplayer/multiplayer_api.h b/core/multiplayer/multiplayer_api.h
deleted file mode 100644
index cc7743ccf8..0000000000
--- a/core/multiplayer/multiplayer_api.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*************************************************************************/
-/* multiplayer_api.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 MULTIPLAYER_API_H
-#define MULTIPLAYER_API_H
-
-#include "core/multiplayer/multiplayer.h"
-#include "core/multiplayer/multiplayer_peer.h"
-#include "core/object/ref_counted.h"
-
-class MultiplayerAPI;
-
-class MultiplayerReplicationInterface : public RefCounted {
- GDCLASS(MultiplayerReplicationInterface, RefCounted);
-
-public:
- virtual void on_peer_change(int p_id, bool p_connected) {}
- virtual void on_reset() {}
- virtual Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; }
- virtual Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; }
- virtual Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; }
- virtual Error on_spawn(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
- virtual Error on_despawn(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
- virtual Error on_replication_start(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
- virtual Error on_replication_stop(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
- virtual void on_network_process() {}
-
- MultiplayerReplicationInterface() {}
-};
-
-class MultiplayerRPCInterface : public RefCounted {
- GDCLASS(MultiplayerRPCInterface, RefCounted);
-
-public:
- // Called by Node.rpc
- virtual void rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {}
- virtual void process_rpc(int p_from, const uint8_t *p_packet, int p_packet_len) {}
- virtual String get_rpc_md5(const Object *p_obj) const { return String(); }
-
- MultiplayerRPCInterface() {}
-};
-
-class MultiplayerCacheInterface : public RefCounted {
- GDCLASS(MultiplayerCacheInterface, RefCounted);
-
-public:
- virtual void clear() {}
- virtual void on_peer_change(int p_id, bool p_connected) {}
- virtual void process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {}
- virtual void process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {}
-
- // Returns true if all peers have cached path.
- virtual bool send_object_cache(Object *p_obj, NodePath p_path, int p_target, int &p_id) { return false; }
- virtual Object *get_cached_object(int p_from, uint32_t p_cache_id) { return nullptr; }
- virtual bool is_cache_confirmed(NodePath p_path, int p_peer) { return false; }
-
- MultiplayerCacheInterface() {}
-};
-
-class MultiplayerAPI : public RefCounted {
- GDCLASS(MultiplayerAPI, RefCounted);
-
-public:
- enum NetworkCommands {
- NETWORK_COMMAND_REMOTE_CALL = 0,
- NETWORK_COMMAND_SIMPLIFY_PATH,
- NETWORK_COMMAND_CONFIRM_PATH,
- NETWORK_COMMAND_RAW,
- NETWORK_COMMAND_SPAWN,
- NETWORK_COMMAND_DESPAWN,
- NETWORK_COMMAND_SYNC,
- };
-
- // For each command, the 4 MSB can contain custom flags, as defined by subsystems.
- enum {
- CMD_FLAG_0_SHIFT = 4,
- CMD_FLAG_1_SHIFT = 5,
- CMD_FLAG_2_SHIFT = 6,
- CMD_FLAG_3_SHIFT = 7,
- };
-
- // This is the mask that will be used to extract the command.
- enum {
- CMD_MASK = 7, // 0x7 -> 0b00001111
- };
-
-private:
- Ref<MultiplayerPeer> multiplayer_peer;
- HashSet<int> connected_peers;
- int remote_sender_id = 0;
- int remote_sender_override = 0;
-
- Vector<uint8_t> packet_cache;
-
- NodePath root_path;
- bool allow_object_decoding = false;
-
- Ref<MultiplayerCacheInterface> cache;
- Ref<MultiplayerReplicationInterface> replicator;
- Ref<MultiplayerRPCInterface> rpc;
-
-protected:
- static void _bind_methods();
-
- void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len);
- void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
-
-public:
- static MultiplayerReplicationInterface *(*create_default_replication_interface)(MultiplayerAPI *p_multiplayer);
- static MultiplayerRPCInterface *(*create_default_rpc_interface)(MultiplayerAPI *p_multiplayer);
- static MultiplayerCacheInterface *(*create_default_cache_interface)(MultiplayerAPI *p_multiplayer);
-
- static Error encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len, bool p_allow_object_decoding);
- static Error decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding);
- static Error encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw = nullptr, bool p_allow_object_decoding = false);
- static Error decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw = false, bool p_allow_object_decoding = false);
-
- void poll();
- void clear();
- void set_root_path(const NodePath &p_path);
- NodePath get_root_path() const;
- void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer);
- Ref<MultiplayerPeer> get_multiplayer_peer() const;
-
- Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, Multiplayer::TransferMode p_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0);
-
- // RPC API
- void rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
- String get_rpc_md5(const Object *p_obj) const;
- // Replication API
- Error spawn(Object *p_object, Variant p_config);
- Error despawn(Object *p_object, Variant p_config);
- Error replication_start(Object *p_object, Variant p_config);
- Error replication_stop(Object *p_object, Variant p_config);
- // Cache API
- bool send_object_cache(Object *p_obj, NodePath p_path, int p_target, int &p_id);
- Object *get_cached_object(int p_from, uint32_t p_cache_id);
- bool is_cache_confirmed(NodePath p_path, int p_peer);
-
- void _add_peer(int p_id);
- void _del_peer(int p_id);
- void _connected_to_server();
- void _connection_failed();
- void _server_disconnected();
-
- bool has_multiplayer_peer() const { return multiplayer_peer.is_valid(); }
- Vector<int> get_peer_ids() const;
- const HashSet<int> get_connected_peers() const { return connected_peers; }
- int get_remote_sender_id() const { return remote_sender_override ? remote_sender_override : remote_sender_id; }
- void set_remote_sender_override(int p_id) { remote_sender_override = p_id; }
- int get_unique_id() const;
- bool is_server() const;
- void set_refuse_new_connections(bool p_refuse);
- bool is_refusing_new_connections() const;
-
- void set_allow_object_decoding(bool p_enable);
- bool is_object_decoding_allowed() const;
-
-#ifdef DEBUG_ENABLED
- void profile_bandwidth(const String &p_inout, int p_size);
-#endif
-
- MultiplayerAPI();
- ~MultiplayerAPI();
-};
-
-#endif // MULTIPLAYER_API_H
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index 3c9f373d12..9790cc44e3 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -305,6 +305,13 @@ void ClassDB::add_compatibility_class(const StringName &p_class, const StringNam
compat_classes[p_class] = p_fallback;
}
+StringName ClassDB::get_compatibility_class(const StringName &p_class) {
+ if (compat_classes.has(p_class)) {
+ return compat_classes[p_class];
+ }
+ return StringName();
+}
+
Object *ClassDB::instantiate(const StringName &p_class) {
ClassInfo *ti;
{
@@ -536,7 +543,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 +562,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 +654,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 +678,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 +696,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 +757,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;
@@ -935,8 +963,11 @@ void ClassDB::add_linked_property(const StringName &p_class, const String &p_pro
ERR_FAIL_COND(!type->property_map.has(p_property));
ERR_FAIL_COND(!type->property_map.has(p_linked_property));
- PropertyInfo &pinfo = type->property_map[p_property];
- pinfo.linked_properties.push_back(p_linked_property);
+ if (!type->linked_properties.has(p_property)) {
+ type->linked_properties.insert(p_property, List<StringName>());
+ }
+ type->linked_properties[p_property].push_back(p_linked_property);
+
#endif
}
@@ -964,6 +995,25 @@ void ClassDB::get_property_list(const StringName &p_class, List<PropertyInfo> *p
}
}
+void ClassDB::get_linked_properties_info(const StringName &p_class, const StringName &p_property, List<StringName> *r_properties, bool p_no_inheritance) {
+#ifdef TOOLS_ENABLED
+ ClassInfo *check = classes.getptr(p_class);
+ while (check) {
+ if (!check->linked_properties.has(p_property)) {
+ return;
+ }
+ for (const StringName &E : check->linked_properties[p_property]) {
+ r_properties->push_back(E);
+ }
+
+ if (p_no_inheritance) {
+ break;
+ }
+ check = check->inherits_ptr;
+ }
+#endif
+}
+
bool ClassDB::get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance, const Object *p_validator) {
OBJTYPE_RLOCK;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index f2f73dc674..5fba52e23e 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;
@@ -115,6 +120,7 @@ public:
List<MethodInfo> virtual_methods;
HashMap<StringName, MethodInfo> virtual_methods_map;
HashMap<StringName, Vector<Error>> method_error_values;
+ HashMap<StringName, List<StringName>> linked_properties;
#endif
HashMap<StringName, PropertySetGet> property_setget;
@@ -307,6 +313,7 @@ public:
static void add_linked_property(const StringName &p_class, const String &p_property, const String &p_linked_property);
static void get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = nullptr);
static bool get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance = false, const Object *p_validator = nullptr);
+ static void get_linked_properties_info(const StringName &p_class, const StringName &p_property, List<StringName> *r_properties, bool p_no_inheritance = false);
static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = nullptr);
static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value);
static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false);
@@ -325,15 +332,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);
@@ -350,6 +359,7 @@ public:
static bool is_resource_extension(const StringName &p_extension);
static void add_compatibility_class(const StringName &p_class, const StringName &p_fallback);
+ static StringName get_compatibility_class(const StringName &p_class);
static void set_current_api(APIType p_api);
static APIType get_current_api();
@@ -370,6 +380,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,20 +414,23 @@ _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
-#define GDREGISTER_CLASS(m_class) \
- if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
- ::ClassDB::register_class<m_class>(); \
+#define GDREGISTER_CLASS(m_class) \
+ if (m_class::_class_is_enabled) { \
+ ::ClassDB::register_class<m_class>(); \
}
-#define GDREGISTER_VIRTUAL_CLASS(m_class) \
- if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
- ::ClassDB::register_class<m_class>(true); \
+#define GDREGISTER_VIRTUAL_CLASS(m_class) \
+ if (m_class::_class_is_enabled) { \
+ ::ClassDB::register_class<m_class>(true); \
}
#define GDREGISTER_ABSTRACT_CLASS(m_class) \
- if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
+ if (m_class::_class_is_enabled) { \
::ClassDB::register_abstract_class<m_class>(); \
}
diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp
index fa1945cf79..13dc921c9f 100644
--- a/core/object/message_queue.cpp
+++ b/core/object/message_queue.cpp
@@ -226,7 +226,7 @@ void MessageQueue::_call_function(const Callable &p_callable, const Variant *p_a
Callable::CallError ce;
Variant ret;
- p_callable.call(argptrs, p_argcount, ret, ce);
+ p_callable.callp(argptrs, p_argcount, ret, ce);
if (p_show_error && ce.error != Callable::CallError::CALL_OK) {
ERR_PRINT("Error calling deferred method: " + Variant::get_callable_error_text(p_callable, argptrs, p_argcount, ce) + ".");
}
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 440da00c17..0fcd1c0e40 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -166,7 +166,6 @@ Object::Connection::operator Variant() const {
d["signal"] = signal;
d["callable"] = callable;
d["flags"] = flags;
- d["binds"] = binds;
return d;
}
@@ -189,9 +188,6 @@ Object::Connection::Connection(const Variant &p_variant) {
if (d.has("flags")) {
flags = d["flags"];
}
- if (d.has("binds")) {
- binds = d["binds"];
- }
}
bool Object::_predelete() {
@@ -476,7 +472,6 @@ Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) co
void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) const {
if (script_instance && p_reversed) {
- p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
script_instance->get_property_list(p_list);
}
@@ -493,7 +488,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
uint32_t pcount;
const GDNativePropertyInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
for (uint32_t i = 0; i < pcount; i++) {
- p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name));
+ p_list->push_back(PropertyInfo(pinfo[i]));
}
if (_extension->free_property_list) {
_extension->free_property_list(_extension_instance, pinfo);
@@ -507,7 +502,6 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
}
if (script_instance && !p_reversed) {
- p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
script_instance->get_property_list(p_list);
}
@@ -973,8 +967,6 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
OBJ_DEBUG_LOCK
- Vector<const Variant *> bind_mem;
-
Error err = OK;
for (int i = 0; i < ssize; i++) {
@@ -989,28 +981,13 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
const Variant **args = p_args;
int argc = p_argcount;
- if (c.binds.size()) {
- //handle binds
- bind_mem.resize(p_argcount + c.binds.size());
-
- for (int j = 0; j < p_argcount; j++) {
- bind_mem.write[j] = p_args[j];
- }
- for (int j = 0; j < c.binds.size(); j++) {
- bind_mem.write[p_argcount + j] = &c.binds[j];
- }
-
- args = (const Variant **)bind_mem.ptr();
- argc = bind_mem.size();
- }
-
if (c.flags & CONNECT_DEFERRED) {
MessageQueue::get_singleton()->push_callablep(c.callable, args, argc, true);
} else {
Callable::CallError ce;
_emitting = true;
Variant ret;
- c.callable.call(args, argc, ret, ce);
+ c.callable.callp(args, argc, ret, ce);
_emitting = false;
if (ce.error != Callable::CallError::CALL_OK) {
@@ -1196,7 +1173,7 @@ void Object::get_signals_connected_to_this(List<Connection> *p_connections) cons
}
}
-Error Object::connect(const StringName &p_signal, const Callable &p_callable, const Vector<Variant> &p_binds, uint32_t p_flags) {
+Error Object::connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags) {
ERR_FAIL_COND_V_MSG(p_callable.is_null(), ERR_INVALID_PARAMETER, "Cannot connect to '" + p_signal + "': the provided callable is null.");
Object *target_object = p_callable.get_object();
@@ -1244,7 +1221,6 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, co
conn.callable = target;
conn.signal = ::Signal(this, p_signal);
conn.flags = p_flags;
- conn.binds = p_binds;
slot.conn = conn;
slot.cE = target_object->connections.push_back(conn);
if (p_flags & CONNECT_REFERENCE_COUNTED) {
@@ -1492,7 +1468,7 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_signal_connection_list", "signal"), &Object::_get_signal_connection_list);
ClassDB::bind_method(D_METHOD("get_incoming_connections"), &Object::_get_incoming_connections);
- ClassDB::bind_method(D_METHOD("connect", "signal", "callable", "binds", "flags"), &Object::connect, DEFVAL(Array()), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("connect", "signal", "callable", "flags"), &Object::connect, DEFVAL(0));
ClassDB::bind_method(D_METHOD("disconnect", "signal", "callable"), &Object::disconnect);
ClassDB::bind_method(D_METHOD("is_connected", "signal", "callable"), &Object::is_connected);
diff --git a/core/object/object.h b/core/object/object.h
index e065634000..35d0aaaa7d 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -50,10 +50,8 @@ enum PropertyHint {
PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_lesser][,no_slider][,radians][,degrees][,exp][,suffix:<keyword>] range.
PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc"
PROPERTY_HINT_ENUM_SUGGESTION, ///< hint_text= "val1,val2,val3,etc"
- PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "full" to also include in/out. (ie: "attenuation,inout")
- PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer)
+ PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "positive_only" to exclude in-out and out-in. (ie: "attenuation,positive_only")
PROPERTY_HINT_LINK,
- PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer)
PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags)
PROPERTY_HINT_LAYERS_2D_RENDER,
PROPERTY_HINT_LAYERS_2D_PHYSICS,
@@ -99,40 +97,39 @@ enum PropertyHint {
enum PropertyUsageFlags {
PROPERTY_USAGE_NONE = 0,
- PROPERTY_USAGE_STORAGE = 1,
- PROPERTY_USAGE_EDITOR = 2,
- PROPERTY_USAGE_NETWORK = 4,
- PROPERTY_USAGE_EDITOR_HELPER = 8,
- PROPERTY_USAGE_CHECKABLE = 16, //used for editing global variables
- PROPERTY_USAGE_CHECKED = 32, //used for editing global variables
- PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings
- PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor
- PROPERTY_USAGE_CATEGORY = 256,
- PROPERTY_USAGE_SUBGROUP = 512,
- PROPERTY_USAGE_NO_INSTANCE_STATE = 2048,
- PROPERTY_USAGE_RESTART_IF_CHANGED = 4096,
- PROPERTY_USAGE_SCRIPT_VARIABLE = 8192,
- PROPERTY_USAGE_STORE_IF_NULL = 16384,
- PROPERTY_USAGE_ANIMATE_AS_TRIGGER = 32768,
- PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 65536,
- PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 17,
- PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 18,
- PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 19,
- PROPERTY_USAGE_INTERNAL = 1 << 20,
- PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 21, // If the object is duplicated also this property will be duplicated
- PROPERTY_USAGE_HIGH_END_GFX = 1 << 22,
- PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 23,
- PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 24,
- PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 25, // Used in inspector to increment property when keyed in animation player
- PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 26, // when loading, the resource for this property can be set at the end of loading
- PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 27, // For Object properties, instantiate them when creating in editor.
- PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 28, //for project or editor settings, show when basic settings are selected
- PROPERTY_USAGE_READ_ONLY = 1 << 29, // Mark a property as read-only in the inspector.
- PROPERTY_USAGE_ARRAY = 1 << 30, // Used in the inspector to group properties as elements of an array.
-
- PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK,
- PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED,
- PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK,
+ PROPERTY_USAGE_STORAGE = 1 << 1,
+ PROPERTY_USAGE_EDITOR = 1 << 2,
+ PROPERTY_USAGE_CHECKABLE = 1 << 3, // Used for editing global variables.
+ PROPERTY_USAGE_CHECKED = 1 << 4, // Used for editing global variables.
+ PROPERTY_USAGE_INTERNATIONALIZED = 1 << 5, // Hint for internationalized strings.
+ PROPERTY_USAGE_GROUP = 1 << 6, // Used for grouping props in the editor.
+ PROPERTY_USAGE_CATEGORY = 1 << 7,
+ PROPERTY_USAGE_SUBGROUP = 1 << 8,
+ PROPERTY_USAGE_CLASS_IS_BITFIELD = 1 << 9,
+ PROPERTY_USAGE_NO_INSTANCE_STATE = 1 << 10,
+ PROPERTY_USAGE_RESTART_IF_CHANGED = 1 << 11,
+ PROPERTY_USAGE_SCRIPT_VARIABLE = 1 << 12,
+ PROPERTY_USAGE_STORE_IF_NULL = 1 << 13,
+ PROPERTY_USAGE_ANIMATE_AS_TRIGGER = 1 << 14,
+ PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 1 << 15,
+ PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 16,
+ PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 17,
+ PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 18,
+ PROPERTY_USAGE_INTERNAL = 1 << 19,
+ PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 20, // If the object is duplicated also this property will be duplicated.
+ PROPERTY_USAGE_HIGH_END_GFX = 1 << 21,
+ PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 22,
+ PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 23,
+ PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 24, // Used in inspector to increment property when keyed in animation player.
+ PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 25, // when loading, the resource for this property can be set at the end of loading.
+ PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 26, // For Object properties, instantiate them when creating in editor.
+ PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 27, //for project or editor settings, show when basic settings are selected.
+ PROPERTY_USAGE_READ_ONLY = 1 << 28, // Mark a property as read-only in the inspector.
+ PROPERTY_USAGE_ARRAY = 1 << 29, // Used in the inspector to group properties as elements of an array.
+
+ PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR,
+ PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNATIONALIZED,
+ PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE,
};
#define ADD_SIGNAL(m_signal) ::ClassDB::add_signal(get_class_static(), m_signal)
@@ -157,9 +154,7 @@ struct PropertyInfo {
String hint_string;
uint32_t usage = PROPERTY_USAGE_DEFAULT;
-#ifdef TOOLS_ENABLED
- Vector<String> linked_properties;
-#endif
+ // If you are thinking about adding another member to this class, ask the maintainer (Juan) first.
_FORCE_INLINE_ PropertyInfo added_usage(uint32_t p_fl) const {
PropertyInfo pi = *this;
@@ -190,6 +185,14 @@ struct PropertyInfo {
type(Variant::OBJECT),
class_name(p_class_name) {}
+ explicit PropertyInfo(const GDNativePropertyInfo &pinfo) :
+ type((Variant::Type)pinfo.type),
+ name(pinfo.name),
+ class_name(pinfo.class_name), // can be null
+ hint((PropertyHint)pinfo.hint),
+ hint_string(pinfo.hint_string), // can be null
+ usage(pinfo.usage) {}
+
bool operator==(const PropertyInfo &p_info) const {
return ((type == p_info.type) &&
(name == p_info.name) &&
@@ -209,14 +212,11 @@ Array convert_property_list(const List<PropertyInfo> *p_list);
enum MethodFlags {
METHOD_FLAG_NORMAL = 1,
METHOD_FLAG_EDITOR = 2,
- METHOD_FLAG_NOSCRIPT = 4,
- METHOD_FLAG_CONST = 8,
- METHOD_FLAG_REVERSE = 16, // used for events
- METHOD_FLAG_VIRTUAL = 32,
- METHOD_FLAG_FROM_SCRIPT = 64,
- METHOD_FLAG_VARARG = 128,
- METHOD_FLAG_STATIC = 256,
- METHOD_FLAG_OBJECT_CORE = 512,
+ METHOD_FLAG_CONST = 4,
+ METHOD_FLAG_VIRTUAL = 8,
+ METHOD_FLAG_VARARG = 16,
+ METHOD_FLAG_STATIC = 32,
+ METHOD_FLAG_OBJECT_CORE = 64,
METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL,
};
@@ -356,6 +356,7 @@ private:
friend class ::ClassDB; \
\
public: \
+ static constexpr bool _class_is_enabled = !bool(GD_IS_DEFINED(ClassDB_Disable_##m_class)) && m_inherits::_class_is_enabled; \
virtual String get_class() const override { \
if (_get_extension()) { \
return _get_extension()->class_name.operator String(); \
@@ -507,7 +508,6 @@ public:
Callable callable;
uint32_t flags = 0;
- Vector<Variant> binds;
bool operator<(const Connection &p_conn) const;
operator Variant() const;
@@ -665,6 +665,8 @@ public: // Should be protected, but bug in clang++.
_FORCE_INLINE_ static void register_custom_data_to_otdb() {}
public:
+ static constexpr bool _class_is_enabled = true;
+
void notify_property_list_changed();
static void *get_class_ptr_static() {
@@ -824,7 +826,7 @@ public:
int get_persistent_signal_connection_count() const;
void get_signals_connected_to_this(List<Connection> *p_connections) const;
- Error connect(const StringName &p_signal, const Callable &p_callable, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0);
+ Error connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags = 0);
void disconnect(const StringName &p_signal, const Callable &p_callable);
bool is_connected(const StringName &p_signal, const Callable &p_callable) const;
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 4623d0e525..b06c2e8896 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -101,6 +101,31 @@ Dictionary Script::_get_script_constant_map() {
return ret;
}
+#ifdef TOOLS_ENABLED
+
+PropertyInfo Script::get_class_category() const {
+ String path = get_path();
+ String name;
+
+ if (is_built_in()) {
+ if (get_name().is_empty()) {
+ name = TTR("Built-in script");
+ } else {
+ name = vformat("%s (%s)", get_name(), TTR("Built-in"));
+ }
+ } else {
+ if (get_name().is_empty()) {
+ name = path.get_file();
+ } else {
+ name = get_name();
+ }
+ }
+
+ return PropertyInfo(Variant::NIL, name, PROPERTY_HINT_NONE, path, PROPERTY_USAGE_CATEGORY);
+}
+
+#endif // TOOLS_ENABLED
+
void Script::_bind_methods() {
ClassDB::bind_method(D_METHOD("can_instantiate"), &Script::can_instantiate);
//ClassDB::bind_method(D_METHOD("instance_create","base_object"),&Script::instance_create);
@@ -344,11 +369,14 @@ void ScriptLanguage::get_core_type_words(List<String> *p_core_type_words) const
p_core_type_words->push_back("Vector3");
p_core_type_words->push_back("Vector3i");
p_core_type_words->push_back("Transform2D");
+ p_core_type_words->push_back("Vector4");
+ p_core_type_words->push_back("Vector4i");
p_core_type_words->push_back("Plane");
p_core_type_words->push_back("Quaternion");
p_core_type_words->push_back("AABB");
p_core_type_words->push_back("Basis");
p_core_type_words->push_back("Transform3D");
+ p_core_type_words->push_back("Projection");
p_core_type_words->push_back("Color");
p_core_type_words->push_back("StringName");
p_core_type_words->push_back("NodePath");
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 776a9bfaab..f5f052b600 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -33,7 +33,6 @@
#include "core/doc_data.h"
#include "core/io/resource.h"
-#include "core/multiplayer/multiplayer.h"
#include "core/templates/pair.h"
#include "core/templates/rb_map.h"
@@ -133,6 +132,7 @@ public:
#ifdef TOOLS_ENABLED
virtual Vector<DocData::ClassDoc> get_documentation() const = 0;
+ virtual PropertyInfo get_class_category() const;
#endif // TOOLS_ENABLED
virtual bool has_method(const StringName &p_method) const = 0;
@@ -159,7 +159,7 @@ public:
virtual bool is_placeholder_fallback_enabled() const { return false; }
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const = 0;
+ virtual const Variant get_rpc_config() const = 0;
Script() {}
};
@@ -213,7 +213,7 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid);
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid);
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const { return get_script()->get_rpc_methods(); }
+ virtual const Variant get_rpc_config() const { return get_script()->get_rpc_config(); }
virtual ScriptLanguage *get_language() = 0;
virtual ~ScriptInstance();
@@ -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;
@@ -467,7 +469,7 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid = nullptr) override;
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid = nullptr) override;
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override { return Vector<Multiplayer::RPCConfig>(); }
+ virtual const Variant get_rpc_config() const override { return Variant(); }
PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner);
~PlaceHolderScriptInstance();
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
index 5af79bbea3..9de784ea7f 100644
--- a/core/object/script_language_extension.cpp
+++ b/core/object/script_language_extension.cpp
@@ -74,7 +74,7 @@ void ScriptExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_members);
GDVIRTUAL_BIND(_is_placeholder_fallback_enabled);
- GDVIRTUAL_BIND(_get_rpc_methods);
+ GDVIRTUAL_BIND(_get_rpc_config);
}
void ScriptLanguageExtension::_bind_methods() {
@@ -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 406a431a11..2869f4ad98 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -173,28 +173,12 @@ public:
EXBIND0RC(bool, is_placeholder_fallback_enabled)
- GDVIRTUAL0RC(TypedArray<Dictionary>, _get_rpc_methods)
+ GDVIRTUAL0RC(Variant, _get_rpc_config)
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override {
- TypedArray<Dictionary> ret;
- GDVIRTUAL_REQUIRED_CALL(_get_rpc_methods, ret);
- Vector<Multiplayer::RPCConfig> rpcret;
- for (int i = 0; i < ret.size(); i++) {
- Dictionary d = ret[i];
- Multiplayer::RPCConfig rpc;
- ERR_CONTINUE(!d.has("name"));
- rpc.name = d["name"];
- ERR_CONTINUE(!d.has("rpc_mode"));
- rpc.rpc_mode = Multiplayer::RPCMode(int(d["rpc_mode"]));
- ERR_CONTINUE(!d.has("call_local"));
- rpc.call_local = d["call_local"];
- ERR_CONTINUE(!d.has("transfer_mode"));
- rpc.transfer_mode = Multiplayer::TransferMode(int(d["transfer_mode"]));
- ERR_CONTINUE(!d.has("channel"));
- rpc.channel = d["channel"];
- rpcret.push_back(rpc);
- }
- return rpcret;
+ virtual const Variant get_rpc_config() const override {
+ Variant ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_rpc_config, ret);
+ return ret;
}
ScriptExtension() {}
@@ -580,6 +564,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)
@@ -670,8 +663,16 @@ public:
if (native_info->get_property_list_func) {
uint32_t pcount;
const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount);
+
+#ifdef TOOLS_ENABLED
+ Ref<Script> script = get_script();
+ if (script->is_valid() && pcount > 0) {
+ p_list->push_back(script->get_class_category());
+ }
+#endif // TOOLS_ENABLED
+
for (uint32_t i = 0; i < pcount; i++) {
- p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name));
+ p_list->push_back(PropertyInfo(pinfo[i]));
}
if (native_info->free_property_list_func) {
native_info->free_property_list_func(instance, pinfo);
@@ -716,9 +717,9 @@ public:
m.name = minfo[i].name;
m.flags = minfo[i].flags;
m.id = minfo[i].id;
- m.return_val = PropertyInfo(Variant::Type(minfo[i].return_value.type), minfo[i].return_value.class_name, PropertyHint(minfo[i].return_value.hint), minfo[i].return_value.hint_string, minfo[i].return_value.usage, minfo[i].return_value.class_name);
+ m.return_val = PropertyInfo(minfo[i].return_value);
for (uint32_t j = 0; j < minfo[i].argument_count; j++) {
- m.arguments.push_back(PropertyInfo(Variant::Type(minfo[i].arguments[j].type), minfo[i].arguments[j].class_name, PropertyHint(minfo[i].arguments[j].hint), minfo[i].arguments[j].hint_string, minfo[i].arguments[j].usage, minfo[i].arguments[j].class_name));
+ m.arguments.push_back(PropertyInfo(minfo[i].arguments[j]));
}
const Variant *def_values = (const Variant *)minfo[i].default_arguments;
for (uint32_t j = 0; j < minfo[i].default_argument_count; j++) {
diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp
new file mode 100644
index 0000000000..c770515b9e
--- /dev/null
+++ b/core/object/worker_thread_pool.cpp
@@ -0,0 +1,474 @@
+/*************************************************************************/
+/* worker_thread_pool.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 "worker_thread_pool.h"
+
+#include "core/os/os.h"
+
+void WorkerThreadPool::Task::free_template_userdata() {
+ ERR_FAIL_COND(!template_userdata);
+ ERR_FAIL_COND(native_func_userdata == nullptr);
+ BaseTemplateUserdata *btu = (BaseTemplateUserdata *)native_func_userdata;
+ memdelete(btu);
+}
+
+WorkerThreadPool *WorkerThreadPool::singleton = nullptr;
+
+void WorkerThreadPool::_process_task_queue() {
+ task_mutex.lock();
+ Task *task = task_queue.first()->self();
+ task_queue.remove(task_queue.first());
+ task_mutex.unlock();
+ _process_task(task);
+}
+
+void WorkerThreadPool::_process_task(Task *p_task) {
+ bool low_priority = p_task->low_priority;
+
+ if (p_task->group) {
+ // Handling a group
+ bool do_post = false;
+ Callable::CallError ce;
+ Variant ret;
+ Variant arg;
+ Variant *argptr = &arg;
+
+ while (true) {
+ uint32_t work_index = p_task->group->index.postincrement();
+
+ if (work_index >= p_task->group->max) {
+ break;
+ }
+ if (p_task->native_group_func) {
+ p_task->native_group_func(p_task->native_func_userdata, work_index);
+ } else if (p_task->template_userdata) {
+ p_task->template_userdata->callback_indexed(work_index);
+ } else {
+ arg = work_index;
+ p_task->callable.callp((const Variant **)&argptr, 1, ret, ce);
+ }
+
+ // This is the only way to ensure posting is done when all tasks are really complete.
+ uint32_t completed_amount = p_task->group->completed_index.increment();
+
+ if (completed_amount == p_task->group->max) {
+ do_post = true;
+ }
+ }
+
+ if (do_post && p_task->template_userdata) {
+ memdelete(p_task->template_userdata); // This is no longer needed at this point, so get rid of it.
+ }
+
+ if (low_priority && use_native_low_priority_threads) {
+ p_task->completed = true;
+ p_task->done_semaphore.post();
+ if (do_post) {
+ p_task->group->completed.set_to(true);
+ }
+ } else {
+ if (do_post) {
+ p_task->group->done_semaphore.post();
+ p_task->group->completed.set_to(true);
+ }
+ uint32_t max_users = p_task->group->tasks_used + 1; // Add 1 because the thread waiting for it is also user. Read before to avoid another thread freeing task after increment.
+ uint32_t finished_users = p_task->group->finished.increment();
+
+ if (finished_users == max_users) {
+ // Get rid of the group, because nobody else is using it.
+ task_mutex.lock();
+ group_allocator.free(p_task->group);
+ task_mutex.unlock();
+ }
+
+ // For groups, tasks get rid of themselves.
+
+ task_mutex.lock();
+ task_allocator.free(p_task);
+ task_mutex.unlock();
+ }
+ } else {
+ if (p_task->native_func) {
+ p_task->native_func(p_task->native_func_userdata);
+ } else if (p_task->template_userdata) {
+ p_task->template_userdata->callback();
+ memdelete(p_task->template_userdata);
+ } else {
+ Callable::CallError ce;
+ Variant ret;
+ p_task->callable.callp(nullptr, 0, ret, ce);
+ }
+
+ p_task->completed = true;
+ p_task->done_semaphore.post();
+ }
+
+ if (!use_native_low_priority_threads && low_priority) {
+ // A low prioriry task was freed, so see if we can move a pending one to the high priority queue.
+ bool post = false;
+ task_mutex.lock();
+ if (low_priority_task_queue.first()) {
+ Task *low_prio_task = low_priority_task_queue.first()->self();
+ low_priority_task_queue.remove(low_priority_task_queue.first());
+ task_queue.add_last(&low_prio_task->task_elem);
+ post = true;
+ } else {
+ low_priority_threads_used.decrement();
+ }
+ task_mutex.lock();
+ if (post) {
+ task_available_semaphore.post();
+ }
+ }
+}
+
+void WorkerThreadPool::_thread_function(void *p_user) {
+ while (true) {
+ singleton->task_available_semaphore.wait();
+ if (singleton->exit_threads.is_set()) {
+ break;
+ }
+ singleton->_process_task_queue();
+ }
+}
+
+void WorkerThreadPool::_native_low_priority_thread_function(void *p_user) {
+ Task *task = (Task *)p_user;
+ singleton->_process_task(task);
+}
+
+void WorkerThreadPool::_post_task(Task *p_task, bool p_high_priority) {
+ task_mutex.lock();
+ p_task->low_priority = !p_high_priority;
+ if (!p_high_priority && use_native_low_priority_threads) {
+ task_mutex.unlock();
+ p_task->low_priority_thread = native_thread_allocator.alloc();
+ p_task->low_priority_thread->start(_native_low_priority_thread_function, p_task); // Pask task directly to thread.
+
+ } else if (p_high_priority || low_priority_threads_used.get() < max_low_priority_threads) {
+ task_queue.add_last(&p_task->task_elem);
+ if (!p_high_priority) {
+ low_priority_threads_used.increment();
+ }
+ task_mutex.unlock();
+ task_available_semaphore.post();
+ } else {
+ // Too many threads using low priority, must go to queue.
+ low_priority_task_queue.add_last(&p_task->task_elem);
+ task_mutex.unlock();
+ }
+}
+
+WorkerThreadPool::TaskID WorkerThreadPool::add_native_task(void (*p_func)(void *), void *p_userdata, bool p_high_priority, const String &p_description) {
+ return _add_task(Callable(), p_func, p_userdata, nullptr, p_high_priority, p_description);
+}
+
+WorkerThreadPool::TaskID WorkerThreadPool::_add_task(const Callable &p_callable, void (*p_func)(void *), void *p_userdata, BaseTemplateUserdata *p_template_userdata, bool p_high_priority, const String &p_description) {
+ task_mutex.lock();
+ // Get a free task
+ Task *task = task_allocator.alloc();
+ TaskID id = last_task++;
+ task->callable = p_callable;
+ task->native_func = p_func;
+ task->native_func_userdata = p_userdata;
+ task->description = p_description;
+ task->template_userdata = p_template_userdata;
+ tasks.insert(id, task);
+ task_mutex.unlock();
+
+ _post_task(task, p_high_priority);
+
+ return id;
+}
+
+WorkerThreadPool::TaskID WorkerThreadPool::add_task(const Callable &p_action, bool p_high_priority, const String &p_description) {
+ return _add_task(p_action, nullptr, nullptr, nullptr, p_high_priority, p_description);
+}
+
+bool WorkerThreadPool::is_task_completed(TaskID p_task_id) const {
+ task_mutex.lock();
+ const Task *const *taskp = tasks.getptr(p_task_id);
+ if (!taskp) {
+ task_mutex.unlock();
+ ERR_FAIL_V_MSG(false, "Invalid Task ID"); // Invalid task
+ }
+
+ bool completed = (*taskp)->completed;
+ task_mutex.unlock();
+
+ return completed;
+}
+
+void WorkerThreadPool::wait_for_task_completion(TaskID p_task_id) {
+ task_mutex.lock();
+ Task **taskp = tasks.getptr(p_task_id);
+ if (!taskp) {
+ task_mutex.unlock();
+ ERR_FAIL_MSG("Invalid Task ID"); // Invalid task
+ }
+ Task *task = *taskp;
+
+ if (task->waiting) {
+ String description = task->description;
+ task_mutex.unlock();
+ if (description.is_empty()) {
+ ERR_FAIL_MSG("Another thread is waiting on this task: " + itos(p_task_id)); // Invalid task
+ } else {
+ ERR_FAIL_MSG("Another thread is waiting on this task: " + description + " (" + itos(p_task_id) + ")"); // Invalid task
+ }
+ }
+
+ task->waiting = true;
+
+ task_mutex.unlock();
+
+ if (use_native_low_priority_threads && task->low_priority) {
+ task->low_priority_thread->wait_to_finish();
+ native_thread_allocator.free(task->low_priority_thread);
+ } else {
+ int *index = thread_ids.getptr(Thread::get_caller_id());
+
+ if (index) {
+ // We are an actual process thread, we must not be blocked so continue processing stuff if available.
+ while (true) {
+ if (task->done_semaphore.try_wait()) {
+ // If done, exit
+ break;
+ }
+ if (task_available_semaphore.try_wait()) {
+ // Solve tasks while they are around.
+ _process_task_queue();
+ continue;
+ }
+ OS::get_singleton()->delay_usec(1); // Microsleep, this could be converted to waiting for multiple objects in supported platforms for a bit more performance.
+ }
+ } else {
+ task->done_semaphore.wait();
+ }
+ }
+
+ task_mutex.lock();
+ tasks.erase(p_task_id);
+ task_allocator.free(task);
+ task_mutex.unlock();
+}
+
+WorkerThreadPool::GroupID WorkerThreadPool::_add_group_task(const Callable &p_callable, void (*p_func)(void *, uint32_t), void *p_userdata, BaseTemplateUserdata *p_template_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) {
+ ERR_FAIL_COND_V(p_elements < 0, INVALID_TASK_ID);
+ if (p_tasks < 0) {
+ p_tasks = threads.size();
+ }
+
+ task_mutex.lock();
+ Group *group = group_allocator.alloc();
+ GroupID id = last_task++;
+ group->max = p_elements;
+ group->self = id;
+
+ Task **tasks_posted = nullptr;
+ if (p_elements == 0) {
+ // Should really not call it with zero Elements, but at least it should work.
+ group->completed.set_to(true);
+ group->done_semaphore.post();
+ group->tasks_used = 0;
+ p_tasks = 0;
+ if (p_template_userdata) {
+ memdelete(p_template_userdata);
+ }
+
+ } else {
+ group->tasks_used = p_tasks;
+ tasks_posted = (Task **)alloca(sizeof(Task *) * p_tasks);
+ for (int i = 0; i < p_tasks; i++) {
+ Task *task = task_allocator.alloc();
+ task->native_group_func = p_func;
+ task->native_func_userdata = p_userdata;
+ task->description = p_description;
+ task->group = group;
+ task->callable = p_callable;
+ task->template_userdata = p_template_userdata;
+ tasks_posted[i] = task;
+ // No task ID is used.
+ }
+ }
+
+ groups[id] = group;
+ task_mutex.unlock();
+
+ if (!p_high_priority && use_native_low_priority_threads) {
+ group->low_priority_native_tasks.resize(p_tasks);
+ }
+
+ for (int i = 0; i < p_tasks; i++) {
+ _post_task(tasks_posted[i], p_high_priority);
+ if (!p_high_priority && use_native_low_priority_threads) {
+ group->low_priority_native_tasks[i] = tasks_posted[i];
+ }
+ }
+
+ return id;
+}
+
+WorkerThreadPool::GroupID WorkerThreadPool::add_native_group_task(void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) {
+ return _add_group_task(Callable(), p_func, p_userdata, nullptr, p_elements, p_tasks, p_high_priority, p_description);
+}
+
+WorkerThreadPool::GroupID WorkerThreadPool::add_group_task(const Callable &p_action, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) {
+ return _add_group_task(p_action, nullptr, nullptr, nullptr, p_elements, p_tasks, p_high_priority, p_description);
+}
+
+uint32_t WorkerThreadPool::get_group_processed_element_count(GroupID p_group) const {
+ task_mutex.lock();
+ const Group *const *groupp = groups.getptr(p_group);
+ if (!groupp) {
+ task_mutex.unlock();
+ ERR_FAIL_V_MSG(0, "Invalid Group ID");
+ }
+ uint32_t elements = (*groupp)->completed_index.get();
+ task_mutex.unlock();
+ return elements;
+}
+bool WorkerThreadPool::is_group_task_completed(GroupID p_group) const {
+ task_mutex.lock();
+ const Group *const *groupp = groups.getptr(p_group);
+ if (!groupp) {
+ task_mutex.unlock();
+ ERR_FAIL_V_MSG(false, "Invalid Group ID");
+ }
+ bool completed = (*groupp)->completed.is_set();
+ task_mutex.unlock();
+ return completed;
+}
+
+void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
+ task_mutex.lock();
+ Group **groupp = groups.getptr(p_group);
+ task_mutex.unlock();
+ if (!groupp) {
+ ERR_FAIL_MSG("Invalid Group ID");
+ }
+ Group *group = *groupp;
+
+ if (group->low_priority_native_tasks.size() > 0) {
+ for (uint32_t i = 0; i < group->low_priority_native_tasks.size(); i++) {
+ group->low_priority_native_tasks[i]->low_priority_thread->wait_to_finish();
+ native_thread_allocator.free(group->low_priority_native_tasks[i]->low_priority_thread);
+ task_mutex.lock();
+ task_allocator.free(group->low_priority_native_tasks[i]);
+ task_mutex.unlock();
+ }
+
+ task_mutex.lock();
+ group_allocator.free(group);
+ task_mutex.unlock();
+ } else {
+ group->done_semaphore.wait();
+
+ uint32_t max_users = group->tasks_used + 1; // Add 1 because the thread waiting for it is also user. Read before to avoid another thread freeing task after increment.
+ uint32_t finished_users = group->finished.increment(); // fetch happens before inc, so increment later.
+
+ if (finished_users == max_users) {
+ // All tasks using this group are gone (finished before the group), so clear the gorup too.
+ task_mutex.lock();
+ group_allocator.free(group);
+ task_mutex.unlock();
+ }
+ }
+
+ groups.erase(p_group); // Threads do not access this, so safe to erase here.
+}
+
+void WorkerThreadPool::init(int p_thread_count, bool p_use_native_threads_low_priority, float p_low_priority_task_ratio) {
+ ERR_FAIL_COND(threads.size() > 0);
+ if (p_thread_count < 0) {
+ p_thread_count = OS::get_singleton()->get_default_thread_pool_size();
+ }
+
+ if (p_use_native_threads_low_priority) {
+ max_low_priority_threads = 0;
+ } else {
+ max_low_priority_threads = CLAMP(p_thread_count * p_low_priority_task_ratio, 1, p_thread_count);
+ }
+
+ use_native_low_priority_threads = p_use_native_threads_low_priority;
+
+ threads.resize(p_thread_count);
+
+ for (uint32_t i = 0; i < threads.size(); i++) {
+ threads[i].index = i;
+ threads[i].thread.start(&WorkerThreadPool::_thread_function, &threads[i]);
+ thread_ids.insert(threads[i].thread.get_id(), i);
+ }
+}
+
+void WorkerThreadPool::finish() {
+ if (threads.size() == 0) {
+ return;
+ }
+
+ task_mutex.lock();
+ SelfList<Task> *E = low_priority_task_queue.first();
+ while (E) {
+ print_error("Task waiting was never re-claimed: " + E->self()->description);
+ E = E->next();
+ }
+ task_mutex.unlock();
+
+ exit_threads.set_to(true);
+
+ for (uint32_t i = 0; i < threads.size(); i++) {
+ task_available_semaphore.post();
+ }
+
+ for (uint32_t i = 0; i < threads.size(); i++) {
+ threads[i].thread.wait_to_finish();
+ }
+
+ threads.clear();
+}
+
+void WorkerThreadPool::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("add_task", "action", "high_priority", "description"), &WorkerThreadPool::add_task, DEFVAL(false), DEFVAL(String()));
+ ClassDB::bind_method(D_METHOD("is_task_completed", "task_id"), &WorkerThreadPool::is_task_completed);
+ ClassDB::bind_method(D_METHOD("wait_for_task_completion", "task_id"), &WorkerThreadPool::wait_for_task_completion);
+
+ ClassDB::bind_method(D_METHOD("add_group_task", "action", "elements", "tasks_needed", "high_priority", "description"), &WorkerThreadPool::add_group_task, DEFVAL(-1), DEFVAL(false), DEFVAL(String()));
+ ClassDB::bind_method(D_METHOD("is_group_task_completed", "group_id"), &WorkerThreadPool::is_group_task_completed);
+ ClassDB::bind_method(D_METHOD("get_group_processed_element_count", "group_id"), &WorkerThreadPool::get_group_processed_element_count);
+ ClassDB::bind_method(D_METHOD("wait_for_group_task_completion", "group_id"), &WorkerThreadPool::wait_for_group_task_completion);
+}
+
+WorkerThreadPool::WorkerThreadPool() {
+ singleton = this;
+}
+
+WorkerThreadPool::~WorkerThreadPool() {
+ finish();
+}
diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h
new file mode 100644
index 0000000000..1debd9ca37
--- /dev/null
+++ b/core/object/worker_thread_pool.h
@@ -0,0 +1,198 @@
+/*************************************************************************/
+/* worker_thread_pool.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 WORKER_THREAD_POOL_H
+#define WORKER_THREAD_POOL_H
+
+#include "core/os/memory.h"
+#include "core/os/os.h"
+#include "core/os/semaphore.h"
+#include "core/os/thread.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/paged_allocator.h"
+#include "core/templates/rid.h"
+#include "core/templates/safe_refcount.h"
+
+class WorkerThreadPool : public Object {
+ GDCLASS(WorkerThreadPool, Object)
+public:
+ enum {
+ INVALID_TASK_ID = -1
+ };
+
+ typedef int64_t TaskID;
+ typedef int64_t GroupID;
+
+private:
+ struct Task;
+
+ struct BaseTemplateUserdata {
+ virtual void callback() {}
+ virtual void callback_indexed(uint32_t p_index) {}
+ virtual ~BaseTemplateUserdata() {}
+ };
+
+ struct Group {
+ GroupID self;
+ SafeNumeric<uint32_t> index;
+ SafeNumeric<uint32_t> completed_index;
+ uint32_t max = 0;
+ Semaphore done_semaphore;
+ SafeFlag completed;
+ SafeNumeric<uint32_t> finished;
+ uint32_t tasks_used = 0;
+ TightLocalVector<Task *> low_priority_native_tasks;
+ };
+
+ struct Task {
+ Callable callable;
+ void (*native_func)(void *) = nullptr;
+ void (*native_group_func)(void *, uint32_t) = nullptr;
+ void *native_func_userdata = nullptr;
+ String description;
+ Semaphore done_semaphore;
+ bool completed = false;
+ Group *group = nullptr;
+ SelfList<Task> task_elem;
+ bool waiting = false; // Waiting for completion
+ bool low_priority = false;
+ BaseTemplateUserdata *template_userdata = nullptr;
+ Thread *low_priority_thread = nullptr;
+
+ void free_template_userdata();
+ Task() :
+ task_elem(this) {}
+ };
+
+ PagedAllocator<Task> task_allocator;
+ PagedAllocator<Group> group_allocator;
+ PagedAllocator<Thread> native_thread_allocator;
+
+ SelfList<Task>::List low_priority_task_queue;
+ SelfList<Task>::List task_queue;
+
+ Mutex task_mutex;
+ Semaphore task_available_semaphore;
+
+ struct ThreadData {
+ uint32_t index;
+ Thread thread;
+ };
+
+ TightLocalVector<ThreadData> threads;
+ SafeFlag exit_threads;
+
+ HashMap<Thread::ID, int> thread_ids;
+ HashMap<TaskID, Task *> tasks;
+ HashMap<GroupID, Group *> groups;
+
+ bool use_native_low_priority_threads = false;
+ uint32_t max_low_priority_threads = 0;
+ SafeNumeric<uint32_t> low_priority_threads_used;
+
+ uint64_t last_task = 1;
+
+ static void _thread_function(void *p_user);
+ static void _native_low_priority_thread_function(void *p_user);
+
+ void _process_task_queue();
+ void _process_task(Task *task);
+
+ void _post_task(Task *p_task, bool p_high_priority);
+
+ static WorkerThreadPool *singleton;
+
+ TaskID _add_task(const Callable &p_callable, void (*p_func)(void *), void *p_userdata, BaseTemplateUserdata *p_template_userdata, bool p_high_priority, const String &p_description);
+ GroupID _add_group_task(const Callable &p_callable, void (*p_func)(void *, uint32_t), void *p_userdata, BaseTemplateUserdata *p_template_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description);
+
+ template <class C, class M, class U>
+ struct TaskUserData : public BaseTemplateUserdata {
+ C *instance;
+ M method;
+ U userdata;
+ virtual void callback() override {
+ (instance->*method)(userdata);
+ }
+ };
+
+ template <class C, class M, class U>
+ struct GroupUserData : public BaseTemplateUserdata {
+ C *instance;
+ M method;
+ U userdata;
+ virtual void callback_indexed(uint32_t p_index) override {
+ (instance->*method)(p_index, userdata);
+ }
+ };
+
+protected:
+ static void _bind_methods();
+
+public:
+ template <class C, class M, class U>
+ TaskID add_template_task(C *p_instance, M p_method, U p_userdata, bool p_high_priority = false, const String &p_description = String()) {
+ typedef TaskUserData<C, M, U> TUD;
+ TUD *ud = memnew(TUD);
+ ud->instance = p_instance;
+ ud->method = p_method;
+ ud->userdata = p_userdata;
+ return _add_task(Callable(), nullptr, nullptr, ud, p_high_priority, p_description);
+ }
+ TaskID add_native_task(void (*p_func)(void *), void *p_userdata, bool p_high_priority = false, const String &p_description = String());
+ TaskID add_task(const Callable &p_action, bool p_high_priority = false, const String &p_description = String());
+
+ bool is_task_completed(TaskID p_task_id) const;
+ void wait_for_task_completion(TaskID p_task_id);
+
+ template <class C, class M, class U>
+ GroupID add_template_group_task(C *p_instance, M p_method, U p_userdata, int p_elements, int p_tasks = -1, bool p_high_priority = false, const String &p_description = String()) {
+ typedef GroupUserData<C, M, U> GUD;
+ GUD *ud = memnew(GUD);
+ ud->instance = p_instance;
+ ud->method = p_method;
+ ud->userdata = p_userdata;
+ return _add_group_task(Callable(), nullptr, nullptr, ud, p_elements, p_tasks, p_high_priority, p_description);
+ }
+ GroupID add_native_group_task(void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks = -1, bool p_high_priority = false, const String &p_description = String());
+ GroupID add_group_task(const Callable &p_action, int p_elements, int p_tasks = -1, bool p_high_priority = false, const String &p_description = String());
+ uint32_t get_group_processed_element_count(GroupID p_group) const;
+ bool is_group_task_completed(GroupID p_group) const;
+ void wait_for_group_task_completion(GroupID p_group);
+
+ _FORCE_INLINE_ int get_thread_count() const { return threads.size(); }
+
+ static WorkerThreadPool *get_singleton() { return singleton; }
+ void init(int p_thread_count = -1, bool p_use_native_threads_low_priority = true, float p_low_priority_task_ratio = 0.3);
+ void finish();
+ WorkerThreadPool();
+ ~WorkerThreadPool();
+};
+
+#endif // WORKER_THREAD_POOL_H
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index 3e690991d9..a592791d06 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -61,7 +61,7 @@ static const _KeyCodeText _keycodes[] = {
{Key::PAGEDOWN ,"PageDown"},
{Key::SHIFT ,"Shift"},
{Key::CTRL ,"Ctrl"},
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
{Key::META ,"Command"},
#else
{Key::META ,"Meta"},
diff --git a/core/os/memory.h b/core/os/memory.h
index 42ba9634e2..0e1afe027e 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -36,6 +36,7 @@
#include <stddef.h>
#include <new>
+#include <type_traits>
#ifndef PAD_ALIGN
#define PAD_ALIGN 16 //must always be greater than this at much
@@ -104,7 +105,7 @@ void memdelete(T *p_class) {
if (!predelete_handler(p_class)) {
return; // doesn't want to be deleted
}
- if (!__has_trivial_destructor(T)) {
+ if (!std::is_trivially_destructible<T>::value) {
p_class->~T();
}
@@ -116,7 +117,7 @@ void memdelete_allocator(T *p_class) {
if (!predelete_handler(p_class)) {
return; // doesn't want to be deleted
}
- if (!__has_trivial_destructor(T)) {
+ if (!std::is_trivially_destructible<T>::value) {
p_class->~T();
}
@@ -146,7 +147,7 @@ T *memnew_arr_template(size_t p_elements) {
ERR_FAIL_COND_V(!mem, failptr);
*(mem - 1) = p_elements;
- if (!__has_trivial_constructor(T)) {
+ if (!std::is_trivially_constructible<T>::value) {
T *elems = (T *)mem;
/* call operator new */
@@ -173,7 +174,7 @@ template <typename T>
void memdelete_arr(T *p_class) {
uint64_t *ptr = (uint64_t *)p_class;
- if (!__has_trivial_destructor(T)) {
+ if (!std::is_trivially_destructible<T>::value) {
uint64_t elem_count = *(ptr - 1);
for (uint64_t i = 0; i < elem_count; i++) {
diff --git a/core/os/os.cpp b/core/os/os.cpp
index b9daf6fa53..1358c926d1 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -159,7 +159,7 @@ int OS::get_process_id() const {
}
void OS::vibrate_handheld(int p_duration_ms) {
- WARN_PRINT("vibrate_handheld() only works with Android and iOS");
+ WARN_PRINT("vibrate_handheld() only works with Android, iOS and HTML5");
}
bool OS::is_stdout_verbose() const {
@@ -362,9 +362,10 @@ String OS::get_model_name() const {
return "GenericDevice";
}
-void OS::set_cmdline(const char *p_execpath, const List<String> &p_args) {
+void OS::set_cmdline(const char *p_execpath, const List<String> &p_args, const List<String> &p_user_args) {
_execpath = String::utf8(p_execpath);
_cmdline = p_args;
+ _user_args = p_user_args;
}
String OS::get_unique_id() const {
diff --git a/core/os/os.h b/core/os/os.h
index af6c38cbe0..9152b797ef 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -46,6 +46,7 @@ class OS {
static uint64_t target_ticks;
String _execpath;
List<String> _cmdline;
+ List<String> _user_args;
bool _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0.
bool low_processor_usage_mode = false;
int low_processor_usage_mode_sleep_usec = 10000;
@@ -106,7 +107,7 @@ protected:
virtual void finalize() = 0;
virtual void finalize_core() = 0;
- virtual void set_cmdline(const char *p_execpath, const List<String> &p_args);
+ virtual void set_cmdline(const char *p_execpath, const List<String> &p_args, const List<String> &p_user_args);
virtual bool _check_internal_feature_support(const String &p_feature) = 0;
@@ -142,6 +143,8 @@ public:
virtual void set_low_processor_usage_mode_sleep_usec(int p_usec);
virtual int get_low_processor_usage_mode_sleep_usec() const;
+ virtual Vector<String> get_system_fonts() const { return Vector<String>(); };
+ virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const { return String(); };
virtual String get_executable_path() const;
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) = 0;
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) = 0;
@@ -160,6 +163,8 @@ public:
virtual String get_name() const = 0;
virtual List<String> get_cmdline_args() const { return _cmdline; }
+ virtual List<String> get_cmdline_user_args() const { return _user_args; }
+ 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/os/spin_lock.h b/core/os/spin_lock.h
index 6e8d7f46d5..80eeef3386 100644
--- a/core/os/spin_lock.h
+++ b/core/os/spin_lock.h
@@ -48,4 +48,5 @@ public:
locked.clear(std::memory_order_release);
}
};
+
#endif // SPIN_LOCK_H
diff --git a/core/os/thread.h b/core/os/thread.h
index 3382dd81f9..0fb283e224 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -123,4 +123,5 @@ public:
};
#endif // THREAD_H
+
#endif // PLATFORM_THREAD_OVERRIDE
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index e60d325f74..9ad6b0ca68 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -69,11 +69,10 @@
#include "core/math/geometry_3d.h"
#include "core/math/random_number_generator.h"
#include "core/math/triangle_mesh.h"
-#include "core/multiplayer/multiplayer_api.h"
-#include "core/multiplayer/multiplayer_peer.h"
#include "core/object/class_db.h"
#include "core/object/script_language_extension.h"
#include "core/object/undo_redo.h"
+#include "core/object/worker_thread_pool.h"
#include "core/os/main_loop.h"
#include "core/os/time.h"
#include "core/string/optimized_translation.h"
@@ -101,6 +100,8 @@ static IP *ip = nullptr;
static core_bind::Geometry2D *_geometry_2d = nullptr;
static core_bind::Geometry3D *_geometry_3d = nullptr;
+static WorkerThreadPool *worker_thread_pool = nullptr;
+
extern Mutex _global_mutex;
static NativeExtensionManager *native_extension_manager = nullptr;
@@ -189,6 +190,8 @@ void register_core_types() {
GDREGISTER_CLASS(PacketPeerUDP);
GDREGISTER_CLASS(UDPServer);
+ GDREGISTER_ABSTRACT_CLASS(WorkerThreadPool);
+
ClassDB::register_custom_instance_class<HTTPClient>();
// Crypto
@@ -207,9 +210,6 @@ void register_core_types() {
resource_format_loader_crypto.instantiate();
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
- GDREGISTER_ABSTRACT_CLASS(MultiplayerPeer);
- GDREGISTER_CLASS(MultiplayerPeerExtension);
- GDREGISTER_CLASS(MultiplayerAPI);
GDREGISTER_CLASS(MainLoop);
GDREGISTER_CLASS(Translation);
GDREGISTER_CLASS(OptimizedTranslation);
@@ -269,8 +269,11 @@ void register_core_types() {
_marshalls = memnew(core_bind::Marshalls);
_engine_debugger = memnew(core_bind::EngineDebugger);
+ GDREGISTER_NATIVE_STRUCT(ObjectID, "uint64_t id = 0");
GDREGISTER_NATIVE_STRUCT(AudioFrame, "float left;float right");
GDREGISTER_NATIVE_STRUCT(ScriptLanguageExtensionProfilingInfo, "StringName signature;uint64_t call_count;uint64_t total_time;uint64_t self_time");
+
+ worker_thread_pool = memnew(WorkerThreadPool);
}
void register_core_settings() {
@@ -279,9 +282,18 @@ void register_core_settings() {
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/tcp/connect_timeout_seconds", PropertyInfo(Variant::INT, "network/limits/tcp/connect_timeout_seconds", PROPERTY_HINT_RANGE, "1,1800,1"));
GLOBAL_DEF_RST("network/limits/packet_peer_stream/max_buffer_po2", (16));
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/packet_peer_stream/max_buffer_po2", PropertyInfo(Variant::INT, "network/limits/packet_peer_stream/max_buffer_po2", PROPERTY_HINT_RANGE, "0,64,1,or_greater"));
-
GLOBAL_DEF("network/ssl/certificate_bundle_override", "");
ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificate_bundle_override", PropertyInfo(Variant::STRING, "network/ssl/certificate_bundle_override", PROPERTY_HINT_FILE, "*.crt"));
+
+ int worker_threads = GLOBAL_DEF("threading/worker_pool/max_threads", -1);
+ bool low_priority_use_system_threads = GLOBAL_DEF("threading/worker_pool/use_system_threads_for_low_priority_tasks", true);
+ float low_property_ratio = GLOBAL_DEF("threading/worker_pool/low_priority_thread_ratio", 0.3);
+
+ if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) {
+ worker_thread_pool->init();
+ } else {
+ worker_thread_pool->init(worker_threads, low_priority_use_system_threads, low_property_ratio);
+ }
}
void register_core_singletons() {
@@ -319,6 +331,7 @@ void register_core_singletons() {
Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("NativeExtensionManager", NativeExtensionManager::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceUID", ResourceUID::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("WorkerThreadPool", worker_thread_pool));
}
void register_core_extensions() {
@@ -350,6 +363,8 @@ void unregister_core_types() {
memdelete(_geometry_2d);
memdelete(_geometry_3d);
+ memdelete(worker_thread_pool);
+
ResourceLoader::remove_resource_format_loader(resource_format_image);
resource_format_image.unref();
diff --git a/core/string/char_range.inc b/core/string/char_range.inc
new file mode 100644
index 0000000000..c0be9016ad
--- /dev/null
+++ b/core/string/char_range.inc
@@ -0,0 +1,1456 @@
+/*************************************************************************/
+/* char_range.inc */
+/*************************************************************************/
+/* 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 CHAR_RANGE_INC
+#define CHAR_RANGE_INC
+
+#include "core/typedefs.h"
+
+struct CharRange {
+ char32_t start;
+ char32_t end;
+};
+
+static CharRange xid_start[] = {
+ { 0x41, 0x5a },
+ { 0x5f, 0x5f },
+ { 0x61, 0x7a },
+ { 0xaa, 0xaa },
+ { 0xb5, 0xb5 },
+ { 0xba, 0xba },
+ { 0xc0, 0xd6 },
+ { 0xd8, 0xf6 },
+ { 0xf8, 0x2c1 },
+ { 0x2c6, 0x2d1 },
+ { 0x2e0, 0x2e4 },
+ { 0x2ec, 0x2ec },
+ { 0x2ee, 0x2ee },
+ { 0x370, 0x374 },
+ { 0x376, 0x377 },
+ { 0x37a, 0x37d },
+ { 0x37f, 0x37f },
+ { 0x386, 0x386 },
+ { 0x388, 0x38a },
+ { 0x38c, 0x38c },
+ { 0x38e, 0x3a1 },
+ { 0x3a3, 0x3f5 },
+ { 0x3f7, 0x481 },
+ { 0x48a, 0x52f },
+ { 0x531, 0x556 },
+ { 0x559, 0x559 },
+ { 0x560, 0x588 },
+ { 0x5d0, 0x5ea },
+ { 0x5ef, 0x5f2 },
+ { 0x620, 0x64a },
+ { 0x66e, 0x66f },
+ { 0x671, 0x6d3 },
+ { 0x6d5, 0x6d5 },
+ { 0x6e5, 0x6e6 },
+ { 0x6ee, 0x6ef },
+ { 0x6fa, 0x6fc },
+ { 0x6ff, 0x6ff },
+ { 0x710, 0x710 },
+ { 0x712, 0x72f },
+ { 0x74d, 0x7a5 },
+ { 0x7b1, 0x7b1 },
+ { 0x7ca, 0x7ea },
+ { 0x7f4, 0x7f5 },
+ { 0x7fa, 0x7fa },
+ { 0x800, 0x815 },
+ { 0x81a, 0x81a },
+ { 0x824, 0x824 },
+ { 0x828, 0x828 },
+ { 0x840, 0x858 },
+ { 0x860, 0x86a },
+ { 0x870, 0x887 },
+ { 0x889, 0x88e },
+ { 0x8a0, 0x8c9 },
+ { 0x904, 0x939 },
+ { 0x93d, 0x93d },
+ { 0x950, 0x950 },
+ { 0x958, 0x961 },
+ { 0x971, 0x980 },
+ { 0x985, 0x98c },
+ { 0x98f, 0x990 },
+ { 0x993, 0x9a8 },
+ { 0x9aa, 0x9b0 },
+ { 0x9b2, 0x9b2 },
+ { 0x9b6, 0x9b9 },
+ { 0x9bd, 0x9bd },
+ { 0x9ce, 0x9ce },
+ { 0x9dc, 0x9dd },
+ { 0x9df, 0x9e1 },
+ { 0x9f0, 0x9f1 },
+ { 0x9fc, 0x9fc },
+ { 0xa05, 0xa0a },
+ { 0xa0f, 0xa10 },
+ { 0xa13, 0xa28 },
+ { 0xa2a, 0xa30 },
+ { 0xa32, 0xa33 },
+ { 0xa35, 0xa36 },
+ { 0xa38, 0xa39 },
+ { 0xa59, 0xa5c },
+ { 0xa5e, 0xa5e },
+ { 0xa72, 0xa74 },
+ { 0xa85, 0xa8d },
+ { 0xa8f, 0xa91 },
+ { 0xa93, 0xaa8 },
+ { 0xaaa, 0xab0 },
+ { 0xab2, 0xab3 },
+ { 0xab5, 0xab9 },
+ { 0xabd, 0xabd },
+ { 0xad0, 0xad0 },
+ { 0xae0, 0xae1 },
+ { 0xaf9, 0xaf9 },
+ { 0xb05, 0xb0c },
+ { 0xb0f, 0xb10 },
+ { 0xb13, 0xb28 },
+ { 0xb2a, 0xb30 },
+ { 0xb32, 0xb33 },
+ { 0xb35, 0xb39 },
+ { 0xb3d, 0xb3d },
+ { 0xb5c, 0xb5d },
+ { 0xb5f, 0xb61 },
+ { 0xb71, 0xb71 },
+ { 0xb83, 0xb83 },
+ { 0xb85, 0xb8a },
+ { 0xb8e, 0xb90 },
+ { 0xb92, 0xb95 },
+ { 0xb99, 0xb9a },
+ { 0xb9c, 0xb9c },
+ { 0xb9e, 0xb9f },
+ { 0xba3, 0xba4 },
+ { 0xba8, 0xbaa },
+ { 0xbae, 0xbb9 },
+ { 0xbd0, 0xbd0 },
+ { 0xc05, 0xc0c },
+ { 0xc0e, 0xc10 },
+ { 0xc12, 0xc28 },
+ { 0xc2a, 0xc39 },
+ { 0xc3d, 0xc3d },
+ { 0xc58, 0xc5a },
+ { 0xc5d, 0xc5d },
+ { 0xc60, 0xc61 },
+ { 0xc80, 0xc80 },
+ { 0xc85, 0xc8c },
+ { 0xc8e, 0xc90 },
+ { 0xc92, 0xca8 },
+ { 0xcaa, 0xcb3 },
+ { 0xcb5, 0xcb9 },
+ { 0xcbd, 0xcbd },
+ { 0xcdd, 0xcde },
+ { 0xce0, 0xce1 },
+ { 0xcf1, 0xcf2 },
+ { 0xd04, 0xd0c },
+ { 0xd0e, 0xd10 },
+ { 0xd12, 0xd3a },
+ { 0xd3d, 0xd3d },
+ { 0xd4e, 0xd4e },
+ { 0xd54, 0xd56 },
+ { 0xd5f, 0xd61 },
+ { 0xd7a, 0xd7f },
+ { 0xd85, 0xd96 },
+ { 0xd9a, 0xdb1 },
+ { 0xdb3, 0xdbb },
+ { 0xdbd, 0xdbd },
+ { 0xdc0, 0xdc6 },
+ { 0xe01, 0xe30 },
+ { 0xe32, 0xe33 },
+ { 0xe40, 0xe46 },
+ { 0xe81, 0xe82 },
+ { 0xe84, 0xe84 },
+ { 0xe86, 0xe8a },
+ { 0xe8c, 0xea3 },
+ { 0xea5, 0xea5 },
+ { 0xea7, 0xeb0 },
+ { 0xeb2, 0xeb3 },
+ { 0xebd, 0xebd },
+ { 0xec0, 0xec4 },
+ { 0xec6, 0xec6 },
+ { 0xedc, 0xedf },
+ { 0xf00, 0xf00 },
+ { 0xf40, 0xf47 },
+ { 0xf49, 0xf6c },
+ { 0xf88, 0xf8c },
+ { 0x1000, 0x102a },
+ { 0x103f, 0x103f },
+ { 0x1050, 0x1055 },
+ { 0x105a, 0x105d },
+ { 0x1061, 0x1061 },
+ { 0x1065, 0x1066 },
+ { 0x106e, 0x1070 },
+ { 0x1075, 0x1081 },
+ { 0x108e, 0x108e },
+ { 0x10a0, 0x10c5 },
+ { 0x10c7, 0x10c7 },
+ { 0x10cd, 0x10cd },
+ { 0x10d0, 0x10fa },
+ { 0x10fc, 0x1248 },
+ { 0x124a, 0x124d },
+ { 0x1250, 0x1256 },
+ { 0x1258, 0x1258 },
+ { 0x125a, 0x125d },
+ { 0x1260, 0x1288 },
+ { 0x128a, 0x128d },
+ { 0x1290, 0x12b0 },
+ { 0x12b2, 0x12b5 },
+ { 0x12b8, 0x12be },
+ { 0x12c0, 0x12c0 },
+ { 0x12c2, 0x12c5 },
+ { 0x12c8, 0x12d6 },
+ { 0x12d8, 0x1310 },
+ { 0x1312, 0x1315 },
+ { 0x1318, 0x135a },
+ { 0x1380, 0x138f },
+ { 0x13a0, 0x13f5 },
+ { 0x13f8, 0x13fd },
+ { 0x1401, 0x166c },
+ { 0x166f, 0x167f },
+ { 0x1681, 0x169a },
+ { 0x16a0, 0x16ea },
+ { 0x16ee, 0x16f8 },
+ { 0x1700, 0x1711 },
+ { 0x171f, 0x1731 },
+ { 0x1740, 0x1751 },
+ { 0x1760, 0x176c },
+ { 0x176e, 0x1770 },
+ { 0x1780, 0x17b3 },
+ { 0x17d7, 0x17d7 },
+ { 0x17dc, 0x17dc },
+ { 0x1820, 0x1878 },
+ { 0x1880, 0x1884 },
+ { 0x1887, 0x18a8 },
+ { 0x18aa, 0x18aa },
+ { 0x18b0, 0x18f5 },
+ { 0x1900, 0x191e },
+ { 0x1950, 0x196d },
+ { 0x1970, 0x1974 },
+ { 0x1980, 0x19ab },
+ { 0x19b0, 0x19c9 },
+ { 0x1a00, 0x1a16 },
+ { 0x1a20, 0x1a54 },
+ { 0x1aa7, 0x1aa7 },
+ { 0x1b05, 0x1b33 },
+ { 0x1b45, 0x1b4c },
+ { 0x1b83, 0x1ba0 },
+ { 0x1bae, 0x1baf },
+ { 0x1bba, 0x1be5 },
+ { 0x1c00, 0x1c23 },
+ { 0x1c4d, 0x1c4f },
+ { 0x1c5a, 0x1c7d },
+ { 0x1c80, 0x1c88 },
+ { 0x1c90, 0x1cba },
+ { 0x1cbd, 0x1cbf },
+ { 0x1ce9, 0x1cec },
+ { 0x1cee, 0x1cf3 },
+ { 0x1cf5, 0x1cf6 },
+ { 0x1cfa, 0x1cfa },
+ { 0x1d00, 0x1dbf },
+ { 0x1e00, 0x1f15 },
+ { 0x1f18, 0x1f1d },
+ { 0x1f20, 0x1f45 },
+ { 0x1f48, 0x1f4d },
+ { 0x1f50, 0x1f57 },
+ { 0x1f59, 0x1f59 },
+ { 0x1f5b, 0x1f5b },
+ { 0x1f5d, 0x1f5d },
+ { 0x1f5f, 0x1f7d },
+ { 0x1f80, 0x1fb4 },
+ { 0x1fb6, 0x1fbc },
+ { 0x1fbe, 0x1fbe },
+ { 0x1fc2, 0x1fc4 },
+ { 0x1fc6, 0x1fcc },
+ { 0x1fd0, 0x1fd3 },
+ { 0x1fd6, 0x1fdb },
+ { 0x1fe0, 0x1fec },
+ { 0x1ff2, 0x1ff4 },
+ { 0x1ff6, 0x1ffc },
+ { 0x2071, 0x2071 },
+ { 0x207f, 0x207f },
+ { 0x2090, 0x209c },
+ { 0x2102, 0x2102 },
+ { 0x2107, 0x2107 },
+ { 0x210a, 0x2113 },
+ { 0x2115, 0x2115 },
+ { 0x2118, 0x211d },
+ { 0x2124, 0x2124 },
+ { 0x2126, 0x2126 },
+ { 0x2128, 0x2128 },
+ { 0x212a, 0x2139 },
+ { 0x213c, 0x213f },
+ { 0x2145, 0x2149 },
+ { 0x214e, 0x214e },
+ { 0x2160, 0x2188 },
+ { 0x2c00, 0x2ce4 },
+ { 0x2ceb, 0x2cee },
+ { 0x2cf2, 0x2cf3 },
+ { 0x2d00, 0x2d25 },
+ { 0x2d27, 0x2d27 },
+ { 0x2d2d, 0x2d2d },
+ { 0x2d30, 0x2d67 },
+ { 0x2d6f, 0x2d6f },
+ { 0x2d80, 0x2d96 },
+ { 0x2da0, 0x2da6 },
+ { 0x2da8, 0x2dae },
+ { 0x2db0, 0x2db6 },
+ { 0x2db8, 0x2dbe },
+ { 0x2dc0, 0x2dc6 },
+ { 0x2dc8, 0x2dce },
+ { 0x2dd0, 0x2dd6 },
+ { 0x2dd8, 0x2dde },
+ { 0x3005, 0x3007 },
+ { 0x3021, 0x3029 },
+ { 0x3031, 0x3035 },
+ { 0x3038, 0x303c },
+ { 0x3041, 0x3096 },
+ { 0x309b, 0x309f },
+ { 0x30a1, 0x30fa },
+ { 0x30fc, 0x30ff },
+ { 0x3105, 0x312f },
+ { 0x3131, 0x318e },
+ { 0x31a0, 0x31bf },
+ { 0x31f0, 0x31ff },
+ { 0x3400, 0x4dbf },
+ { 0x4e00, 0xa48c },
+ { 0xa4d0, 0xa4fd },
+ { 0xa500, 0xa60c },
+ { 0xa610, 0xa61f },
+ { 0xa62a, 0xa62b },
+ { 0xa640, 0xa66e },
+ { 0xa67f, 0xa69d },
+ { 0xa6a0, 0xa6ef },
+ { 0xa717, 0xa71f },
+ { 0xa722, 0xa788 },
+ { 0xa78b, 0xa7ca },
+ { 0xa7d0, 0xa7d1 },
+ { 0xa7d3, 0xa7d3 },
+ { 0xa7d5, 0xa7d9 },
+ { 0xa7f2, 0xa801 },
+ { 0xa803, 0xa805 },
+ { 0xa807, 0xa80a },
+ { 0xa80c, 0xa822 },
+ { 0xa840, 0xa873 },
+ { 0xa882, 0xa8b3 },
+ { 0xa8f2, 0xa8f7 },
+ { 0xa8fb, 0xa8fb },
+ { 0xa8fd, 0xa8fe },
+ { 0xa90a, 0xa925 },
+ { 0xa930, 0xa946 },
+ { 0xa960, 0xa97c },
+ { 0xa984, 0xa9b2 },
+ { 0xa9cf, 0xa9cf },
+ { 0xa9e0, 0xa9e4 },
+ { 0xa9e6, 0xa9ef },
+ { 0xa9fa, 0xa9fe },
+ { 0xaa00, 0xaa28 },
+ { 0xaa40, 0xaa42 },
+ { 0xaa44, 0xaa4b },
+ { 0xaa60, 0xaa76 },
+ { 0xaa7a, 0xaa7a },
+ { 0xaa7e, 0xaaaf },
+ { 0xaab1, 0xaab1 },
+ { 0xaab5, 0xaab6 },
+ { 0xaab9, 0xaabd },
+ { 0xaac0, 0xaac0 },
+ { 0xaac2, 0xaac2 },
+ { 0xaadb, 0xaadd },
+ { 0xaae0, 0xaaea },
+ { 0xaaf2, 0xaaf4 },
+ { 0xab01, 0xab06 },
+ { 0xab09, 0xab0e },
+ { 0xab11, 0xab16 },
+ { 0xab20, 0xab26 },
+ { 0xab28, 0xab2e },
+ { 0xab30, 0xab5a },
+ { 0xab5c, 0xab69 },
+ { 0xab70, 0xabe2 },
+ { 0xac00, 0xd7a3 },
+ { 0xd7b0, 0xd7c6 },
+ { 0xd7cb, 0xd7fb },
+ { 0xf900, 0xfa6d },
+ { 0xfa70, 0xfad9 },
+ { 0xfb00, 0xfb06 },
+ { 0xfb13, 0xfb17 },
+ { 0xfb1d, 0xfb1d },
+ { 0xfb1f, 0xfb28 },
+ { 0xfb2a, 0xfb36 },
+ { 0xfb38, 0xfb3c },
+ { 0xfb3e, 0xfb3e },
+ { 0xfb40, 0xfb41 },
+ { 0xfb43, 0xfb44 },
+ { 0xfb46, 0xfbb1 },
+ { 0xfbd3, 0xfd3d },
+ { 0xfd50, 0xfd8f },
+ { 0xfd92, 0xfdc7 },
+ { 0xfdf0, 0xfdfb },
+ { 0xfe70, 0xfe74 },
+ { 0xfe76, 0xfefc },
+ { 0xff21, 0xff3a },
+ { 0xff41, 0xff5a },
+ { 0xff66, 0xffbe },
+ { 0xffc2, 0xffc7 },
+ { 0xffca, 0xffcf },
+ { 0xffd2, 0xffd7 },
+ { 0xffda, 0xffdc },
+ { 0x10000, 0x1000b },
+ { 0x1000d, 0x10026 },
+ { 0x10028, 0x1003a },
+ { 0x1003c, 0x1003d },
+ { 0x1003f, 0x1004d },
+ { 0x10050, 0x1005d },
+ { 0x10080, 0x100fa },
+ { 0x10140, 0x10174 },
+ { 0x10280, 0x1029c },
+ { 0x102a0, 0x102d0 },
+ { 0x10300, 0x1031f },
+ { 0x1032d, 0x1034a },
+ { 0x10350, 0x10375 },
+ { 0x10380, 0x1039d },
+ { 0x103a0, 0x103c3 },
+ { 0x103c8, 0x103cf },
+ { 0x103d1, 0x103d5 },
+ { 0x10400, 0x1049d },
+ { 0x104b0, 0x104d3 },
+ { 0x104d8, 0x104fb },
+ { 0x10500, 0x10527 },
+ { 0x10530, 0x10563 },
+ { 0x10570, 0x1057a },
+ { 0x1057c, 0x1058a },
+ { 0x1058c, 0x10592 },
+ { 0x10594, 0x10595 },
+ { 0x10597, 0x105a1 },
+ { 0x105a3, 0x105b1 },
+ { 0x105b3, 0x105b9 },
+ { 0x105bb, 0x105bc },
+ { 0x10600, 0x10736 },
+ { 0x10740, 0x10755 },
+ { 0x10760, 0x10767 },
+ { 0x10780, 0x10785 },
+ { 0x10787, 0x107b0 },
+ { 0x107b2, 0x107ba },
+ { 0x10800, 0x10805 },
+ { 0x10808, 0x10808 },
+ { 0x1080a, 0x10835 },
+ { 0x10837, 0x10838 },
+ { 0x1083c, 0x1083c },
+ { 0x1083f, 0x10855 },
+ { 0x10860, 0x10876 },
+ { 0x10880, 0x1089e },
+ { 0x108e0, 0x108f2 },
+ { 0x108f4, 0x108f5 },
+ { 0x10900, 0x10915 },
+ { 0x10920, 0x10939 },
+ { 0x10980, 0x109b7 },
+ { 0x109be, 0x109bf },
+ { 0x10a00, 0x10a00 },
+ { 0x10a10, 0x10a13 },
+ { 0x10a15, 0x10a17 },
+ { 0x10a19, 0x10a35 },
+ { 0x10a60, 0x10a7c },
+ { 0x10a80, 0x10a9c },
+ { 0x10ac0, 0x10ac7 },
+ { 0x10ac9, 0x10ae4 },
+ { 0x10b00, 0x10b35 },
+ { 0x10b40, 0x10b55 },
+ { 0x10b60, 0x10b72 },
+ { 0x10b80, 0x10b91 },
+ { 0x10c00, 0x10c48 },
+ { 0x10c80, 0x10cb2 },
+ { 0x10cc0, 0x10cf2 },
+ { 0x10d00, 0x10d23 },
+ { 0x10e80, 0x10ea9 },
+ { 0x10eb0, 0x10eb1 },
+ { 0x10f00, 0x10f1c },
+ { 0x10f27, 0x10f27 },
+ { 0x10f30, 0x10f45 },
+ { 0x10f70, 0x10f81 },
+ { 0x10fb0, 0x10fc4 },
+ { 0x10fe0, 0x10ff6 },
+ { 0x11003, 0x11037 },
+ { 0x11071, 0x11072 },
+ { 0x11075, 0x11075 },
+ { 0x11083, 0x110af },
+ { 0x110d0, 0x110e8 },
+ { 0x11103, 0x11126 },
+ { 0x11144, 0x11144 },
+ { 0x11147, 0x11147 },
+ { 0x11150, 0x11172 },
+ { 0x11176, 0x11176 },
+ { 0x11183, 0x111b2 },
+ { 0x111c1, 0x111c4 },
+ { 0x111da, 0x111da },
+ { 0x111dc, 0x111dc },
+ { 0x11200, 0x11211 },
+ { 0x11213, 0x1122b },
+ { 0x11280, 0x11286 },
+ { 0x11288, 0x11288 },
+ { 0x1128a, 0x1128d },
+ { 0x1128f, 0x1129d },
+ { 0x1129f, 0x112a8 },
+ { 0x112b0, 0x112de },
+ { 0x11305, 0x1130c },
+ { 0x1130f, 0x11310 },
+ { 0x11313, 0x11328 },
+ { 0x1132a, 0x11330 },
+ { 0x11332, 0x11333 },
+ { 0x11335, 0x11339 },
+ { 0x1133d, 0x1133d },
+ { 0x11350, 0x11350 },
+ { 0x1135d, 0x11361 },
+ { 0x11400, 0x11434 },
+ { 0x11447, 0x1144a },
+ { 0x1145f, 0x11461 },
+ { 0x11480, 0x114af },
+ { 0x114c4, 0x114c5 },
+ { 0x114c7, 0x114c7 },
+ { 0x11580, 0x115ae },
+ { 0x115d8, 0x115db },
+ { 0x11600, 0x1162f },
+ { 0x11644, 0x11644 },
+ { 0x11680, 0x116aa },
+ { 0x116b8, 0x116b8 },
+ { 0x11700, 0x1171a },
+ { 0x11740, 0x11746 },
+ { 0x11800, 0x1182b },
+ { 0x118a0, 0x118df },
+ { 0x118ff, 0x11906 },
+ { 0x11909, 0x11909 },
+ { 0x1190c, 0x11913 },
+ { 0x11915, 0x11916 },
+ { 0x11918, 0x1192f },
+ { 0x1193f, 0x1193f },
+ { 0x11941, 0x11941 },
+ { 0x119a0, 0x119a7 },
+ { 0x119aa, 0x119d0 },
+ { 0x119e1, 0x119e1 },
+ { 0x119e3, 0x119e3 },
+ { 0x11a00, 0x11a00 },
+ { 0x11a0b, 0x11a32 },
+ { 0x11a3a, 0x11a3a },
+ { 0x11a50, 0x11a50 },
+ { 0x11a5c, 0x11a89 },
+ { 0x11a9d, 0x11a9d },
+ { 0x11ab0, 0x11af8 },
+ { 0x11c00, 0x11c08 },
+ { 0x11c0a, 0x11c2e },
+ { 0x11c40, 0x11c40 },
+ { 0x11c72, 0x11c8f },
+ { 0x11d00, 0x11d06 },
+ { 0x11d08, 0x11d09 },
+ { 0x11d0b, 0x11d30 },
+ { 0x11d46, 0x11d46 },
+ { 0x11d60, 0x11d65 },
+ { 0x11d67, 0x11d68 },
+ { 0x11d6a, 0x11d89 },
+ { 0x11d98, 0x11d98 },
+ { 0x11ee0, 0x11ef2 },
+ { 0x11fb0, 0x11fb0 },
+ { 0x12000, 0x12399 },
+ { 0x12400, 0x1246e },
+ { 0x12480, 0x12543 },
+ { 0x12f90, 0x12ff0 },
+ { 0x13000, 0x1342e },
+ { 0x14400, 0x14646 },
+ { 0x16800, 0x16a38 },
+ { 0x16a40, 0x16a5e },
+ { 0x16a70, 0x16abe },
+ { 0x16ad0, 0x16aed },
+ { 0x16b00, 0x16b2f },
+ { 0x16b40, 0x16b43 },
+ { 0x16b63, 0x16b77 },
+ { 0x16b7d, 0x16b8f },
+ { 0x16e40, 0x16e7f },
+ { 0x16f00, 0x16f4a },
+ { 0x16f50, 0x16f50 },
+ { 0x16f93, 0x16f9f },
+ { 0x16fe0, 0x16fe1 },
+ { 0x16fe3, 0x16fe3 },
+ { 0x17000, 0x187f7 },
+ { 0x18800, 0x18cd5 },
+ { 0x18d00, 0x18d08 },
+ { 0x1aff0, 0x1aff3 },
+ { 0x1aff5, 0x1affb },
+ { 0x1affd, 0x1affe },
+ { 0x1b000, 0x1b122 },
+ { 0x1b150, 0x1b152 },
+ { 0x1b164, 0x1b167 },
+ { 0x1b170, 0x1b2fb },
+ { 0x1bc00, 0x1bc6a },
+ { 0x1bc70, 0x1bc7c },
+ { 0x1bc80, 0x1bc88 },
+ { 0x1bc90, 0x1bc99 },
+ { 0x1d400, 0x1d454 },
+ { 0x1d456, 0x1d49c },
+ { 0x1d49e, 0x1d49f },
+ { 0x1d4a2, 0x1d4a2 },
+ { 0x1d4a5, 0x1d4a6 },
+ { 0x1d4a9, 0x1d4ac },
+ { 0x1d4ae, 0x1d4b9 },
+ { 0x1d4bb, 0x1d4bb },
+ { 0x1d4bd, 0x1d4c3 },
+ { 0x1d4c5, 0x1d505 },
+ { 0x1d507, 0x1d50a },
+ { 0x1d50d, 0x1d514 },
+ { 0x1d516, 0x1d51c },
+ { 0x1d51e, 0x1d539 },
+ { 0x1d53b, 0x1d53e },
+ { 0x1d540, 0x1d544 },
+ { 0x1d546, 0x1d546 },
+ { 0x1d54a, 0x1d550 },
+ { 0x1d552, 0x1d6a5 },
+ { 0x1d6a8, 0x1d6c0 },
+ { 0x1d6c2, 0x1d6da },
+ { 0x1d6dc, 0x1d6fa },
+ { 0x1d6fc, 0x1d714 },
+ { 0x1d716, 0x1d734 },
+ { 0x1d736, 0x1d74e },
+ { 0x1d750, 0x1d76e },
+ { 0x1d770, 0x1d788 },
+ { 0x1d78a, 0x1d7a8 },
+ { 0x1d7aa, 0x1d7c2 },
+ { 0x1d7c4, 0x1d7cb },
+ { 0x1df00, 0x1df1e },
+ { 0x1e100, 0x1e12c },
+ { 0x1e137, 0x1e13d },
+ { 0x1e14e, 0x1e14e },
+ { 0x1e290, 0x1e2ad },
+ { 0x1e2c0, 0x1e2eb },
+ { 0x1e7e0, 0x1e7e6 },
+ { 0x1e7e8, 0x1e7eb },
+ { 0x1e7ed, 0x1e7ee },
+ { 0x1e7f0, 0x1e7fe },
+ { 0x1e800, 0x1e8c4 },
+ { 0x1e900, 0x1e943 },
+ { 0x1e94b, 0x1e94b },
+ { 0x1ee00, 0x1ee03 },
+ { 0x1ee05, 0x1ee1f },
+ { 0x1ee21, 0x1ee22 },
+ { 0x1ee24, 0x1ee24 },
+ { 0x1ee27, 0x1ee27 },
+ { 0x1ee29, 0x1ee32 },
+ { 0x1ee34, 0x1ee37 },
+ { 0x1ee39, 0x1ee39 },
+ { 0x1ee3b, 0x1ee3b },
+ { 0x1ee42, 0x1ee42 },
+ { 0x1ee47, 0x1ee47 },
+ { 0x1ee49, 0x1ee49 },
+ { 0x1ee4b, 0x1ee4b },
+ { 0x1ee4d, 0x1ee4f },
+ { 0x1ee51, 0x1ee52 },
+ { 0x1ee54, 0x1ee54 },
+ { 0x1ee57, 0x1ee57 },
+ { 0x1ee59, 0x1ee59 },
+ { 0x1ee5b, 0x1ee5b },
+ { 0x1ee5d, 0x1ee5d },
+ { 0x1ee5f, 0x1ee5f },
+ { 0x1ee61, 0x1ee62 },
+ { 0x1ee64, 0x1ee64 },
+ { 0x1ee67, 0x1ee6a },
+ { 0x1ee6c, 0x1ee72 },
+ { 0x1ee74, 0x1ee77 },
+ { 0x1ee79, 0x1ee7c },
+ { 0x1ee7e, 0x1ee7e },
+ { 0x1ee80, 0x1ee89 },
+ { 0x1ee8b, 0x1ee9b },
+ { 0x1eea1, 0x1eea3 },
+ { 0x1eea5, 0x1eea9 },
+ { 0x1eeab, 0x1eebb },
+ { 0x20000, 0x2a6df },
+ { 0x2a700, 0x2b738 },
+ { 0x2b740, 0x2b81d },
+ { 0x2b820, 0x2cea1 },
+ { 0x2ceb0, 0x2ebe0 },
+ { 0x2f800, 0x2fa1d },
+ { 0x30000, 0x3134a },
+ { 0x0, 0x0 },
+};
+
+static CharRange xid_continue[] = {
+ { 0x30, 0x39 },
+ { 0x41, 0x5a },
+ { 0x5f, 0x5f },
+ { 0x61, 0x7a },
+ { 0xaa, 0xaa },
+ { 0xb5, 0xb5 },
+ { 0xb7, 0xb7 },
+ { 0xba, 0xba },
+ { 0xc0, 0xd6 },
+ { 0xd8, 0xf6 },
+ { 0xf8, 0x2c1 },
+ { 0x2c6, 0x2d1 },
+ { 0x2e0, 0x2e4 },
+ { 0x2ec, 0x2ec },
+ { 0x2ee, 0x2ee },
+ { 0x300, 0x374 },
+ { 0x376, 0x377 },
+ { 0x37a, 0x37d },
+ { 0x37f, 0x37f },
+ { 0x386, 0x38a },
+ { 0x38c, 0x38c },
+ { 0x38e, 0x3a1 },
+ { 0x3a3, 0x3f5 },
+ { 0x3f7, 0x481 },
+ { 0x483, 0x487 },
+ { 0x48a, 0x52f },
+ { 0x531, 0x556 },
+ { 0x559, 0x559 },
+ { 0x560, 0x588 },
+ { 0x591, 0x5bd },
+ { 0x5bf, 0x5bf },
+ { 0x5c1, 0x5c2 },
+ { 0x5c4, 0x5c5 },
+ { 0x5c7, 0x5c7 },
+ { 0x5d0, 0x5ea },
+ { 0x5ef, 0x5f2 },
+ { 0x610, 0x61a },
+ { 0x620, 0x669 },
+ { 0x66e, 0x6d3 },
+ { 0x6d5, 0x6dc },
+ { 0x6df, 0x6e8 },
+ { 0x6ea, 0x6fc },
+ { 0x6ff, 0x6ff },
+ { 0x710, 0x74a },
+ { 0x74d, 0x7b1 },
+ { 0x7c0, 0x7f5 },
+ { 0x7fa, 0x7fa },
+ { 0x7fd, 0x7fd },
+ { 0x800, 0x82d },
+ { 0x840, 0x85b },
+ { 0x860, 0x86a },
+ { 0x870, 0x887 },
+ { 0x889, 0x88e },
+ { 0x898, 0x8e1 },
+ { 0x8e3, 0x963 },
+ { 0x966, 0x96f },
+ { 0x971, 0x983 },
+ { 0x985, 0x98c },
+ { 0x98f, 0x990 },
+ { 0x993, 0x9a8 },
+ { 0x9aa, 0x9b0 },
+ { 0x9b2, 0x9b2 },
+ { 0x9b6, 0x9b9 },
+ { 0x9bc, 0x9c4 },
+ { 0x9c7, 0x9c8 },
+ { 0x9cb, 0x9ce },
+ { 0x9d7, 0x9d7 },
+ { 0x9dc, 0x9dd },
+ { 0x9df, 0x9e3 },
+ { 0x9e6, 0x9f1 },
+ { 0x9fc, 0x9fc },
+ { 0x9fe, 0x9fe },
+ { 0xa01, 0xa03 },
+ { 0xa05, 0xa0a },
+ { 0xa0f, 0xa10 },
+ { 0xa13, 0xa28 },
+ { 0xa2a, 0xa30 },
+ { 0xa32, 0xa33 },
+ { 0xa35, 0xa36 },
+ { 0xa38, 0xa39 },
+ { 0xa3c, 0xa3c },
+ { 0xa3e, 0xa42 },
+ { 0xa47, 0xa48 },
+ { 0xa4b, 0xa4d },
+ { 0xa51, 0xa51 },
+ { 0xa59, 0xa5c },
+ { 0xa5e, 0xa5e },
+ { 0xa66, 0xa75 },
+ { 0xa81, 0xa83 },
+ { 0xa85, 0xa8d },
+ { 0xa8f, 0xa91 },
+ { 0xa93, 0xaa8 },
+ { 0xaaa, 0xab0 },
+ { 0xab2, 0xab3 },
+ { 0xab5, 0xab9 },
+ { 0xabc, 0xac5 },
+ { 0xac7, 0xac9 },
+ { 0xacb, 0xacd },
+ { 0xad0, 0xad0 },
+ { 0xae0, 0xae3 },
+ { 0xae6, 0xaef },
+ { 0xaf9, 0xaff },
+ { 0xb01, 0xb03 },
+ { 0xb05, 0xb0c },
+ { 0xb0f, 0xb10 },
+ { 0xb13, 0xb28 },
+ { 0xb2a, 0xb30 },
+ { 0xb32, 0xb33 },
+ { 0xb35, 0xb39 },
+ { 0xb3c, 0xb44 },
+ { 0xb47, 0xb48 },
+ { 0xb4b, 0xb4d },
+ { 0xb55, 0xb57 },
+ { 0xb5c, 0xb5d },
+ { 0xb5f, 0xb63 },
+ { 0xb66, 0xb6f },
+ { 0xb71, 0xb71 },
+ { 0xb82, 0xb83 },
+ { 0xb85, 0xb8a },
+ { 0xb8e, 0xb90 },
+ { 0xb92, 0xb95 },
+ { 0xb99, 0xb9a },
+ { 0xb9c, 0xb9c },
+ { 0xb9e, 0xb9f },
+ { 0xba3, 0xba4 },
+ { 0xba8, 0xbaa },
+ { 0xbae, 0xbb9 },
+ { 0xbbe, 0xbc2 },
+ { 0xbc6, 0xbc8 },
+ { 0xbca, 0xbcd },
+ { 0xbd0, 0xbd0 },
+ { 0xbd7, 0xbd7 },
+ { 0xbe6, 0xbef },
+ { 0xc00, 0xc0c },
+ { 0xc0e, 0xc10 },
+ { 0xc12, 0xc28 },
+ { 0xc2a, 0xc39 },
+ { 0xc3c, 0xc44 },
+ { 0xc46, 0xc48 },
+ { 0xc4a, 0xc4d },
+ { 0xc55, 0xc56 },
+ { 0xc58, 0xc5a },
+ { 0xc5d, 0xc5d },
+ { 0xc60, 0xc63 },
+ { 0xc66, 0xc6f },
+ { 0xc80, 0xc83 },
+ { 0xc85, 0xc8c },
+ { 0xc8e, 0xc90 },
+ { 0xc92, 0xca8 },
+ { 0xcaa, 0xcb3 },
+ { 0xcb5, 0xcb9 },
+ { 0xcbc, 0xcc4 },
+ { 0xcc6, 0xcc8 },
+ { 0xcca, 0xccd },
+ { 0xcd5, 0xcd6 },
+ { 0xcdd, 0xcde },
+ { 0xce0, 0xce3 },
+ { 0xce6, 0xcef },
+ { 0xcf1, 0xcf2 },
+ { 0xd00, 0xd0c },
+ { 0xd0e, 0xd10 },
+ { 0xd12, 0xd44 },
+ { 0xd46, 0xd48 },
+ { 0xd4a, 0xd4e },
+ { 0xd54, 0xd57 },
+ { 0xd5f, 0xd63 },
+ { 0xd66, 0xd6f },
+ { 0xd7a, 0xd7f },
+ { 0xd81, 0xd83 },
+ { 0xd85, 0xd96 },
+ { 0xd9a, 0xdb1 },
+ { 0xdb3, 0xdbb },
+ { 0xdbd, 0xdbd },
+ { 0xdc0, 0xdc6 },
+ { 0xdca, 0xdca },
+ { 0xdcf, 0xdd4 },
+ { 0xdd6, 0xdd6 },
+ { 0xdd8, 0xddf },
+ { 0xde6, 0xdef },
+ { 0xdf2, 0xdf3 },
+ { 0xe01, 0xe3a },
+ { 0xe40, 0xe4e },
+ { 0xe50, 0xe59 },
+ { 0xe81, 0xe82 },
+ { 0xe84, 0xe84 },
+ { 0xe86, 0xe8a },
+ { 0xe8c, 0xea3 },
+ { 0xea5, 0xea5 },
+ { 0xea7, 0xebd },
+ { 0xec0, 0xec4 },
+ { 0xec6, 0xec6 },
+ { 0xec8, 0xecd },
+ { 0xed0, 0xed9 },
+ { 0xedc, 0xedf },
+ { 0xf00, 0xf00 },
+ { 0xf18, 0xf19 },
+ { 0xf20, 0xf29 },
+ { 0xf35, 0xf35 },
+ { 0xf37, 0xf37 },
+ { 0xf39, 0xf39 },
+ { 0xf3e, 0xf47 },
+ { 0xf49, 0xf6c },
+ { 0xf71, 0xf84 },
+ { 0xf86, 0xf97 },
+ { 0xf99, 0xfbc },
+ { 0xfc6, 0xfc6 },
+ { 0x1000, 0x1049 },
+ { 0x1050, 0x109d },
+ { 0x10a0, 0x10c5 },
+ { 0x10c7, 0x10c7 },
+ { 0x10cd, 0x10cd },
+ { 0x10d0, 0x10fa },
+ { 0x10fc, 0x1248 },
+ { 0x124a, 0x124d },
+ { 0x1250, 0x1256 },
+ { 0x1258, 0x1258 },
+ { 0x125a, 0x125d },
+ { 0x1260, 0x1288 },
+ { 0x128a, 0x128d },
+ { 0x1290, 0x12b0 },
+ { 0x12b2, 0x12b5 },
+ { 0x12b8, 0x12be },
+ { 0x12c0, 0x12c0 },
+ { 0x12c2, 0x12c5 },
+ { 0x12c8, 0x12d6 },
+ { 0x12d8, 0x1310 },
+ { 0x1312, 0x1315 },
+ { 0x1318, 0x135a },
+ { 0x135d, 0x135f },
+ { 0x1369, 0x1369 },
+ { 0x1371, 0x1371 },
+ { 0x1380, 0x138f },
+ { 0x13a0, 0x13f5 },
+ { 0x13f8, 0x13fd },
+ { 0x1401, 0x166c },
+ { 0x166f, 0x167f },
+ { 0x1681, 0x169a },
+ { 0x16a0, 0x16ea },
+ { 0x16ee, 0x16f8 },
+ { 0x1700, 0x1715 },
+ { 0x171f, 0x1734 },
+ { 0x1740, 0x1753 },
+ { 0x1760, 0x176c },
+ { 0x176e, 0x1770 },
+ { 0x1772, 0x1773 },
+ { 0x1780, 0x17d3 },
+ { 0x17d7, 0x17d7 },
+ { 0x17dc, 0x17dd },
+ { 0x17e0, 0x17e9 },
+ { 0x180b, 0x180d },
+ { 0x180f, 0x1819 },
+ { 0x1820, 0x1878 },
+ { 0x1880, 0x18aa },
+ { 0x18b0, 0x18f5 },
+ { 0x1900, 0x191e },
+ { 0x1920, 0x192b },
+ { 0x1930, 0x193b },
+ { 0x1946, 0x196d },
+ { 0x1970, 0x1974 },
+ { 0x1980, 0x19ab },
+ { 0x19b0, 0x19c9 },
+ { 0x19d0, 0x19da },
+ { 0x1a00, 0x1a1b },
+ { 0x1a20, 0x1a5e },
+ { 0x1a60, 0x1a7c },
+ { 0x1a7f, 0x1a89 },
+ { 0x1a90, 0x1a99 },
+ { 0x1aa7, 0x1aa7 },
+ { 0x1ab0, 0x1abd },
+ { 0x1abf, 0x1ace },
+ { 0x1b00, 0x1b4c },
+ { 0x1b50, 0x1b59 },
+ { 0x1b6b, 0x1b73 },
+ { 0x1b80, 0x1bf3 },
+ { 0x1c00, 0x1c37 },
+ { 0x1c40, 0x1c49 },
+ { 0x1c4d, 0x1c7d },
+ { 0x1c80, 0x1c88 },
+ { 0x1c90, 0x1cba },
+ { 0x1cbd, 0x1cbf },
+ { 0x1cd0, 0x1cd2 },
+ { 0x1cd4, 0x1cfa },
+ { 0x1d00, 0x1f15 },
+ { 0x1f18, 0x1f1d },
+ { 0x1f20, 0x1f45 },
+ { 0x1f48, 0x1f4d },
+ { 0x1f50, 0x1f57 },
+ { 0x1f59, 0x1f59 },
+ { 0x1f5b, 0x1f5b },
+ { 0x1f5d, 0x1f5d },
+ { 0x1f5f, 0x1f7d },
+ { 0x1f80, 0x1fb4 },
+ { 0x1fb6, 0x1fbc },
+ { 0x1fbe, 0x1fbe },
+ { 0x1fc2, 0x1fc4 },
+ { 0x1fc6, 0x1fcc },
+ { 0x1fd0, 0x1fd3 },
+ { 0x1fd6, 0x1fdb },
+ { 0x1fe0, 0x1fec },
+ { 0x1ff2, 0x1ff4 },
+ { 0x1ff6, 0x1ffc },
+ { 0x203f, 0x2040 },
+ { 0x2054, 0x2054 },
+ { 0x2071, 0x2071 },
+ { 0x207f, 0x207f },
+ { 0x2090, 0x209c },
+ { 0x20d0, 0x20dc },
+ { 0x20e1, 0x20e1 },
+ { 0x20e5, 0x20f0 },
+ { 0x2102, 0x2102 },
+ { 0x2107, 0x2107 },
+ { 0x210a, 0x2113 },
+ { 0x2115, 0x2115 },
+ { 0x2118, 0x211d },
+ { 0x2124, 0x2124 },
+ { 0x2126, 0x2126 },
+ { 0x2128, 0x2128 },
+ { 0x212a, 0x2139 },
+ { 0x213c, 0x213f },
+ { 0x2145, 0x2149 },
+ { 0x214e, 0x214e },
+ { 0x2160, 0x2188 },
+ { 0x2c00, 0x2ce4 },
+ { 0x2ceb, 0x2cf3 },
+ { 0x2d00, 0x2d25 },
+ { 0x2d27, 0x2d27 },
+ { 0x2d2d, 0x2d2d },
+ { 0x2d30, 0x2d67 },
+ { 0x2d6f, 0x2d6f },
+ { 0x2d7f, 0x2d96 },
+ { 0x2da0, 0x2da6 },
+ { 0x2da8, 0x2dae },
+ { 0x2db0, 0x2db6 },
+ { 0x2db8, 0x2dbe },
+ { 0x2dc0, 0x2dc6 },
+ { 0x2dc8, 0x2dce },
+ { 0x2dd0, 0x2dd6 },
+ { 0x2dd8, 0x2dde },
+ { 0x2de0, 0x2dff },
+ { 0x3005, 0x3007 },
+ { 0x3021, 0x302f },
+ { 0x3031, 0x3035 },
+ { 0x3038, 0x303c },
+ { 0x3041, 0x3096 },
+ { 0x3099, 0x309f },
+ { 0x30a1, 0x30fa },
+ { 0x30fc, 0x30ff },
+ { 0x3105, 0x312f },
+ { 0x3131, 0x318e },
+ { 0x31a0, 0x31bf },
+ { 0x31f0, 0x31ff },
+ { 0x3400, 0x4dbf },
+ { 0x4e00, 0xa48c },
+ { 0xa4d0, 0xa4fd },
+ { 0xa500, 0xa60c },
+ { 0xa610, 0xa62b },
+ { 0xa640, 0xa66f },
+ { 0xa674, 0xa67d },
+ { 0xa67f, 0xa6f1 },
+ { 0xa717, 0xa71f },
+ { 0xa722, 0xa788 },
+ { 0xa78b, 0xa7ca },
+ { 0xa7d0, 0xa7d1 },
+ { 0xa7d3, 0xa7d3 },
+ { 0xa7d5, 0xa7d9 },
+ { 0xa7f2, 0xa827 },
+ { 0xa82c, 0xa82c },
+ { 0xa840, 0xa873 },
+ { 0xa880, 0xa8c5 },
+ { 0xa8d0, 0xa8d9 },
+ { 0xa8e0, 0xa8f7 },
+ { 0xa8fb, 0xa8fb },
+ { 0xa8fd, 0xa92d },
+ { 0xa930, 0xa953 },
+ { 0xa960, 0xa97c },
+ { 0xa980, 0xa9c0 },
+ { 0xa9cf, 0xa9d9 },
+ { 0xa9e0, 0xa9fe },
+ { 0xaa00, 0xaa36 },
+ { 0xaa40, 0xaa4d },
+ { 0xaa50, 0xaa59 },
+ { 0xaa60, 0xaa76 },
+ { 0xaa7a, 0xaac2 },
+ { 0xaadb, 0xaadd },
+ { 0xaae0, 0xaaef },
+ { 0xaaf2, 0xaaf6 },
+ { 0xab01, 0xab06 },
+ { 0xab09, 0xab0e },
+ { 0xab11, 0xab16 },
+ { 0xab20, 0xab26 },
+ { 0xab28, 0xab2e },
+ { 0xab30, 0xab5a },
+ { 0xab5c, 0xab69 },
+ { 0xab70, 0xabea },
+ { 0xabec, 0xabed },
+ { 0xabf0, 0xabf9 },
+ { 0xac00, 0xd7a3 },
+ { 0xd7b0, 0xd7c6 },
+ { 0xd7cb, 0xd7fb },
+ { 0xf900, 0xfa6d },
+ { 0xfa70, 0xfad9 },
+ { 0xfb00, 0xfb06 },
+ { 0xfb13, 0xfb17 },
+ { 0xfb1d, 0xfb28 },
+ { 0xfb2a, 0xfb36 },
+ { 0xfb38, 0xfb3c },
+ { 0xfb3e, 0xfb3e },
+ { 0xfb40, 0xfb41 },
+ { 0xfb43, 0xfb44 },
+ { 0xfb46, 0xfbb1 },
+ { 0xfbd3, 0xfd3d },
+ { 0xfd50, 0xfd8f },
+ { 0xfd92, 0xfdc7 },
+ { 0xfdf0, 0xfdfb },
+ { 0xfe00, 0xfe0f },
+ { 0xfe20, 0xfe2f },
+ { 0xfe33, 0xfe34 },
+ { 0xfe4d, 0xfe4f },
+ { 0xfe70, 0xfe74 },
+ { 0xfe76, 0xfefc },
+ { 0xff10, 0xff19 },
+ { 0xff21, 0xff3a },
+ { 0xff3f, 0xff3f },
+ { 0xff41, 0xff5a },
+ { 0xff66, 0xffbe },
+ { 0xffc2, 0xffc7 },
+ { 0xffca, 0xffcf },
+ { 0xffd2, 0xffd7 },
+ { 0xffda, 0xffdc },
+ { 0x10000, 0x1000b },
+ { 0x1000d, 0x10026 },
+ { 0x10028, 0x1003a },
+ { 0x1003c, 0x1003d },
+ { 0x1003f, 0x1004d },
+ { 0x10050, 0x1005d },
+ { 0x10080, 0x100fa },
+ { 0x10140, 0x10174 },
+ { 0x101fd, 0x101fd },
+ { 0x10280, 0x1029c },
+ { 0x102a0, 0x102d0 },
+ { 0x102e0, 0x102e0 },
+ { 0x10300, 0x1031f },
+ { 0x1032d, 0x1034a },
+ { 0x10350, 0x1037a },
+ { 0x10380, 0x1039d },
+ { 0x103a0, 0x103c3 },
+ { 0x103c8, 0x103cf },
+ { 0x103d1, 0x103d5 },
+ { 0x10400, 0x1049d },
+ { 0x104a0, 0x104a9 },
+ { 0x104b0, 0x104d3 },
+ { 0x104d8, 0x104fb },
+ { 0x10500, 0x10527 },
+ { 0x10530, 0x10563 },
+ { 0x10570, 0x1057a },
+ { 0x1057c, 0x1058a },
+ { 0x1058c, 0x10592 },
+ { 0x10594, 0x10595 },
+ { 0x10597, 0x105a1 },
+ { 0x105a3, 0x105b1 },
+ { 0x105b3, 0x105b9 },
+ { 0x105bb, 0x105bc },
+ { 0x10600, 0x10736 },
+ { 0x10740, 0x10755 },
+ { 0x10760, 0x10767 },
+ { 0x10780, 0x10785 },
+ { 0x10787, 0x107b0 },
+ { 0x107b2, 0x107ba },
+ { 0x10800, 0x10805 },
+ { 0x10808, 0x10808 },
+ { 0x1080a, 0x10835 },
+ { 0x10837, 0x10838 },
+ { 0x1083c, 0x1083c },
+ { 0x1083f, 0x10855 },
+ { 0x10860, 0x10876 },
+ { 0x10880, 0x1089e },
+ { 0x108e0, 0x108f2 },
+ { 0x108f4, 0x108f5 },
+ { 0x10900, 0x10915 },
+ { 0x10920, 0x10939 },
+ { 0x10980, 0x109b7 },
+ { 0x109be, 0x109bf },
+ { 0x10a00, 0x10a03 },
+ { 0x10a05, 0x10a06 },
+ { 0x10a0c, 0x10a13 },
+ { 0x10a15, 0x10a17 },
+ { 0x10a19, 0x10a35 },
+ { 0x10a38, 0x10a3a },
+ { 0x10a3f, 0x10a3f },
+ { 0x10a60, 0x10a7c },
+ { 0x10a80, 0x10a9c },
+ { 0x10ac0, 0x10ac7 },
+ { 0x10ac9, 0x10ae6 },
+ { 0x10b00, 0x10b35 },
+ { 0x10b40, 0x10b55 },
+ { 0x10b60, 0x10b72 },
+ { 0x10b80, 0x10b91 },
+ { 0x10c00, 0x10c48 },
+ { 0x10c80, 0x10cb2 },
+ { 0x10cc0, 0x10cf2 },
+ { 0x10d00, 0x10d27 },
+ { 0x10d30, 0x10d39 },
+ { 0x10e80, 0x10ea9 },
+ { 0x10eab, 0x10eac },
+ { 0x10eb0, 0x10eb1 },
+ { 0x10f00, 0x10f1c },
+ { 0x10f27, 0x10f27 },
+ { 0x10f30, 0x10f50 },
+ { 0x10f70, 0x10f85 },
+ { 0x10fb0, 0x10fc4 },
+ { 0x10fe0, 0x10ff6 },
+ { 0x11000, 0x11046 },
+ { 0x11066, 0x11075 },
+ { 0x1107f, 0x110ba },
+ { 0x110c2, 0x110c2 },
+ { 0x110d0, 0x110e8 },
+ { 0x110f0, 0x110f9 },
+ { 0x11100, 0x11134 },
+ { 0x11136, 0x1113f },
+ { 0x11144, 0x11147 },
+ { 0x11150, 0x11173 },
+ { 0x11176, 0x11176 },
+ { 0x11180, 0x111c4 },
+ { 0x111c9, 0x111cc },
+ { 0x111ce, 0x111da },
+ { 0x111dc, 0x111dc },
+ { 0x11200, 0x11211 },
+ { 0x11213, 0x11237 },
+ { 0x1123e, 0x1123e },
+ { 0x11280, 0x11286 },
+ { 0x11288, 0x11288 },
+ { 0x1128a, 0x1128d },
+ { 0x1128f, 0x1129d },
+ { 0x1129f, 0x112a8 },
+ { 0x112b0, 0x112ea },
+ { 0x112f0, 0x112f9 },
+ { 0x11300, 0x11303 },
+ { 0x11305, 0x1130c },
+ { 0x1130f, 0x11310 },
+ { 0x11313, 0x11328 },
+ { 0x1132a, 0x11330 },
+ { 0x11332, 0x11333 },
+ { 0x11335, 0x11339 },
+ { 0x1133b, 0x11344 },
+ { 0x11347, 0x11348 },
+ { 0x1134b, 0x1134d },
+ { 0x11350, 0x11350 },
+ { 0x11357, 0x11357 },
+ { 0x1135d, 0x11363 },
+ { 0x11366, 0x1136c },
+ { 0x11370, 0x11374 },
+ { 0x11400, 0x1144a },
+ { 0x11450, 0x11459 },
+ { 0x1145e, 0x11461 },
+ { 0x11480, 0x114c5 },
+ { 0x114c7, 0x114c7 },
+ { 0x114d0, 0x114d9 },
+ { 0x11580, 0x115b5 },
+ { 0x115b8, 0x115c0 },
+ { 0x115d8, 0x115dd },
+ { 0x11600, 0x11640 },
+ { 0x11644, 0x11644 },
+ { 0x11650, 0x11659 },
+ { 0x11680, 0x116b8 },
+ { 0x116c0, 0x116c9 },
+ { 0x11700, 0x1171a },
+ { 0x1171d, 0x1172b },
+ { 0x11730, 0x11739 },
+ { 0x11740, 0x11746 },
+ { 0x11800, 0x1183a },
+ { 0x118a0, 0x118e9 },
+ { 0x118ff, 0x11906 },
+ { 0x11909, 0x11909 },
+ { 0x1190c, 0x11913 },
+ { 0x11915, 0x11916 },
+ { 0x11918, 0x11935 },
+ { 0x11937, 0x11938 },
+ { 0x1193b, 0x11943 },
+ { 0x11950, 0x11959 },
+ { 0x119a0, 0x119a7 },
+ { 0x119aa, 0x119d7 },
+ { 0x119da, 0x119e1 },
+ { 0x119e3, 0x119e4 },
+ { 0x11a00, 0x11a3e },
+ { 0x11a47, 0x11a47 },
+ { 0x11a50, 0x11a99 },
+ { 0x11a9d, 0x11a9d },
+ { 0x11ab0, 0x11af8 },
+ { 0x11c00, 0x11c08 },
+ { 0x11c0a, 0x11c36 },
+ { 0x11c38, 0x11c40 },
+ { 0x11c50, 0x11c59 },
+ { 0x11c72, 0x11c8f },
+ { 0x11c92, 0x11ca7 },
+ { 0x11ca9, 0x11cb6 },
+ { 0x11d00, 0x11d06 },
+ { 0x11d08, 0x11d09 },
+ { 0x11d0b, 0x11d36 },
+ { 0x11d3a, 0x11d3a },
+ { 0x11d3c, 0x11d3d },
+ { 0x11d3f, 0x11d47 },
+ { 0x11d50, 0x11d59 },
+ { 0x11d60, 0x11d65 },
+ { 0x11d67, 0x11d68 },
+ { 0x11d6a, 0x11d8e },
+ { 0x11d90, 0x11d91 },
+ { 0x11d93, 0x11d98 },
+ { 0x11da0, 0x11da9 },
+ { 0x11ee0, 0x11ef6 },
+ { 0x11fb0, 0x11fb0 },
+ { 0x12000, 0x12399 },
+ { 0x12400, 0x1246e },
+ { 0x12480, 0x12543 },
+ { 0x12f90, 0x12ff0 },
+ { 0x13000, 0x1342e },
+ { 0x14400, 0x14646 },
+ { 0x16800, 0x16a38 },
+ { 0x16a40, 0x16a5e },
+ { 0x16a60, 0x16a69 },
+ { 0x16a70, 0x16abe },
+ { 0x16ac0, 0x16ac9 },
+ { 0x16ad0, 0x16aed },
+ { 0x16af0, 0x16af4 },
+ { 0x16b00, 0x16b36 },
+ { 0x16b40, 0x16b43 },
+ { 0x16b50, 0x16b59 },
+ { 0x16b63, 0x16b77 },
+ { 0x16b7d, 0x16b8f },
+ { 0x16e40, 0x16e7f },
+ { 0x16f00, 0x16f4a },
+ { 0x16f4f, 0x16f87 },
+ { 0x16f8f, 0x16f9f },
+ { 0x16fe0, 0x16fe1 },
+ { 0x16fe3, 0x16fe4 },
+ { 0x16ff0, 0x16ff1 },
+ { 0x17000, 0x187f7 },
+ { 0x18800, 0x18cd5 },
+ { 0x18d00, 0x18d08 },
+ { 0x1aff0, 0x1aff3 },
+ { 0x1aff5, 0x1affb },
+ { 0x1affd, 0x1affe },
+ { 0x1b000, 0x1b122 },
+ { 0x1b150, 0x1b152 },
+ { 0x1b164, 0x1b167 },
+ { 0x1b170, 0x1b2fb },
+ { 0x1bc00, 0x1bc6a },
+ { 0x1bc70, 0x1bc7c },
+ { 0x1bc80, 0x1bc88 },
+ { 0x1bc90, 0x1bc99 },
+ { 0x1bc9d, 0x1bc9e },
+ { 0x1cf00, 0x1cf2d },
+ { 0x1cf30, 0x1cf46 },
+ { 0x1d165, 0x1d169 },
+ { 0x1d16d, 0x1d172 },
+ { 0x1d17b, 0x1d182 },
+ { 0x1d185, 0x1d18b },
+ { 0x1d1aa, 0x1d1ad },
+ { 0x1d242, 0x1d244 },
+ { 0x1d400, 0x1d454 },
+ { 0x1d456, 0x1d49c },
+ { 0x1d49e, 0x1d49f },
+ { 0x1d4a2, 0x1d4a2 },
+ { 0x1d4a5, 0x1d4a6 },
+ { 0x1d4a9, 0x1d4ac },
+ { 0x1d4ae, 0x1d4b9 },
+ { 0x1d4bb, 0x1d4bb },
+ { 0x1d4bd, 0x1d4c3 },
+ { 0x1d4c5, 0x1d505 },
+ { 0x1d507, 0x1d50a },
+ { 0x1d50d, 0x1d514 },
+ { 0x1d516, 0x1d51c },
+ { 0x1d51e, 0x1d539 },
+ { 0x1d53b, 0x1d53e },
+ { 0x1d540, 0x1d544 },
+ { 0x1d546, 0x1d546 },
+ { 0x1d54a, 0x1d550 },
+ { 0x1d552, 0x1d6a5 },
+ { 0x1d6a8, 0x1d6c0 },
+ { 0x1d6c2, 0x1d6da },
+ { 0x1d6dc, 0x1d6fa },
+ { 0x1d6fc, 0x1d714 },
+ { 0x1d716, 0x1d734 },
+ { 0x1d736, 0x1d74e },
+ { 0x1d750, 0x1d76e },
+ { 0x1d770, 0x1d788 },
+ { 0x1d78a, 0x1d7a8 },
+ { 0x1d7aa, 0x1d7c2 },
+ { 0x1d7c4, 0x1d7cb },
+ { 0x1d7ce, 0x1d7ff },
+ { 0x1da00, 0x1da36 },
+ { 0x1da3b, 0x1da6c },
+ { 0x1da75, 0x1da75 },
+ { 0x1da84, 0x1da84 },
+ { 0x1da9b, 0x1da9f },
+ { 0x1daa1, 0x1daaf },
+ { 0x1df00, 0x1df1e },
+ { 0x1e000, 0x1e006 },
+ { 0x1e008, 0x1e018 },
+ { 0x1e01b, 0x1e021 },
+ { 0x1e023, 0x1e024 },
+ { 0x1e026, 0x1e02a },
+ { 0x1e100, 0x1e12c },
+ { 0x1e130, 0x1e13d },
+ { 0x1e140, 0x1e149 },
+ { 0x1e14e, 0x1e14e },
+ { 0x1e290, 0x1e2ae },
+ { 0x1e2c0, 0x1e2f9 },
+ { 0x1e7e0, 0x1e7e6 },
+ { 0x1e7e8, 0x1e7eb },
+ { 0x1e7ed, 0x1e7ee },
+ { 0x1e7f0, 0x1e7fe },
+ { 0x1e800, 0x1e8c4 },
+ { 0x1e8d0, 0x1e8d6 },
+ { 0x1e900, 0x1e94b },
+ { 0x1e950, 0x1e959 },
+ { 0x1ee00, 0x1ee03 },
+ { 0x1ee05, 0x1ee1f },
+ { 0x1ee21, 0x1ee22 },
+ { 0x1ee24, 0x1ee24 },
+ { 0x1ee27, 0x1ee27 },
+ { 0x1ee29, 0x1ee32 },
+ { 0x1ee34, 0x1ee37 },
+ { 0x1ee39, 0x1ee39 },
+ { 0x1ee3b, 0x1ee3b },
+ { 0x1ee42, 0x1ee42 },
+ { 0x1ee47, 0x1ee47 },
+ { 0x1ee49, 0x1ee49 },
+ { 0x1ee4b, 0x1ee4b },
+ { 0x1ee4d, 0x1ee4f },
+ { 0x1ee51, 0x1ee52 },
+ { 0x1ee54, 0x1ee54 },
+ { 0x1ee57, 0x1ee57 },
+ { 0x1ee59, 0x1ee59 },
+ { 0x1ee5b, 0x1ee5b },
+ { 0x1ee5d, 0x1ee5d },
+ { 0x1ee5f, 0x1ee5f },
+ { 0x1ee61, 0x1ee62 },
+ { 0x1ee64, 0x1ee64 },
+ { 0x1ee67, 0x1ee6a },
+ { 0x1ee6c, 0x1ee72 },
+ { 0x1ee74, 0x1ee77 },
+ { 0x1ee79, 0x1ee7c },
+ { 0x1ee7e, 0x1ee7e },
+ { 0x1ee80, 0x1ee89 },
+ { 0x1ee8b, 0x1ee9b },
+ { 0x1eea1, 0x1eea3 },
+ { 0x1eea5, 0x1eea9 },
+ { 0x1eeab, 0x1eebb },
+ { 0x1fbf0, 0x1fbf9 },
+ { 0x20000, 0x2a6df },
+ { 0x2a700, 0x2b738 },
+ { 0x2b740, 0x2b81d },
+ { 0x2b820, 0x2cea1 },
+ { 0x2ceb0, 0x2ebe0 },
+ { 0x2f800, 0x2fa1d },
+ { 0x30000, 0x3134a },
+ { 0xe0100, 0xe01ef },
+ { 0x0, 0x0 },
+};
+
+#endif // CHAR_RANGE_INC
diff --git a/core/string/char_utils.h b/core/string/char_utils.h
index 0afd058f01..67147a4327 100644
--- a/core/string/char_utils.h
+++ b/core/string/char_utils.h
@@ -33,6 +33,26 @@
#include "core/typedefs.h"
+#include "char_range.inc"
+
+static _FORCE_INLINE_ bool is_unicode_identifier_start(char32_t c) {
+ for (int i = 0; xid_start[i].start != 0; i++) {
+ if (c >= xid_start[i].start && c <= xid_start[i].end) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static _FORCE_INLINE_ bool is_unicode_identifier_continue(char32_t c) {
+ for (int i = 0; xid_continue[i].start != 0; i++) {
+ if (c >= xid_continue[i].start && c <= xid_continue[i].end) {
+ return true;
+ }
+ }
+ return false;
+}
+
static _FORCE_INLINE_ bool is_ascii_upper_case(char32_t c) {
return (c >= 'A' && c <= 'Z');
}
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/print_string.cpp b/core/string/print_string.cpp
index f58486e0a5..592da58fe7 100644
--- a/core/string/print_string.cpp
+++ b/core/string/print_string.cpp
@@ -30,13 +30,12 @@
#include "print_string.h"
+#include "core/core_globals.h"
#include "core/os/os.h"
#include <stdio.h>
static PrintHandlerList *print_handler_list = nullptr;
-bool _print_line_enabled = true;
-bool _print_error_enabled = true;
void add_print_handler(PrintHandlerList *p_handler) {
_global_lock();
@@ -70,7 +69,7 @@ void remove_print_handler(const PrintHandlerList *p_handler) {
}
void __print_line(String p_string) {
- if (!_print_line_enabled) {
+ if (!CoreGlobals::print_line_enabled) {
return;
}
@@ -87,7 +86,7 @@ void __print_line(String p_string) {
}
void __print_line_rich(String p_string) {
- if (!_print_line_enabled) {
+ if (!CoreGlobals::print_line_enabled) {
return;
}
@@ -178,7 +177,7 @@ void __print_line_rich(String p_string) {
}
void print_error(String p_string) {
- if (!_print_error_enabled) {
+ if (!CoreGlobals::print_error_enabled) {
return;
}
diff --git a/core/string/print_string.h b/core/string/print_string.h
index 823e2c29e8..ca930a3a0f 100644
--- a/core/string/print_string.h
+++ b/core/string/print_string.h
@@ -56,8 +56,6 @@ String stringify_variants(Variant p_var, Args... p_args) {
void add_print_handler(PrintHandlerList *p_handler);
void remove_print_handler(const PrintHandlerList *p_handler);
-extern bool _print_line_enabled;
-extern bool _print_error_enabled;
extern void __print_line(String p_string);
extern void __print_line_rich(String p_string);
extern void print_error(String p_string);
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index df1aae5370..e93375bff7 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, bool p_skip_cr) {
if (!p_utf8) {
- return true;
+ return ERR_INVALID_DATA;
}
String aux;
@@ -1635,14 +1678,21 @@ 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) {
+ if (p_skip_cr && c == '\r') {
+ ptrtmp++;
+ continue;
+ }
/* Determine the number of characters in sequence */
if ((c & 0x80) == 0) {
skip = 0;
@@ -1652,20 +1702,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 +1737,95 @@ 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
- }
+ uint8_t c = *p_utf8 >= 0 ? *p_utf8 : uint8_t(256 + *p_utf8);
- /* Convert the first character */
-
- uint32_t unichar = 0;
-
- if (len == 1) {
- unichar = *p_utf8;
+ if (skip == 0) {
+ if (p_skip_cr && c == '\r') {
+ p_utf8++;
+ continue;
+ }
+ /* 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 +1844,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 +1880,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 +1915,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 +1944,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 +2042,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 +2068,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..6c3169f136 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -28,9 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+// Note: _GODOT suffix added to avoid conflict with ICU header with the same guard.
+
#ifndef USTRING_GODOT_H
#define USTRING_GODOT_H
-// Note: Renamed to avoid conflict with ICU header with the same name.
#include "core/string/char_utils.h"
#include "core/templates/cowdata.h"
@@ -271,6 +272,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 +377,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, bool p_skip_cr = false);
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/bin_sorted_array.h b/core/templates/bin_sorted_array.h
index d928bd7a82..38beb9c04d 100644
--- a/core/templates/bin_sorted_array.h
+++ b/core/templates/bin_sorted_array.h
@@ -178,4 +178,4 @@ public:
}
};
-#endif //BIN_SORTED_ARRAY_H
+#endif // BIN_SORTED_ARRAY_H
diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h
index e760fc2176..f98b2308c9 100644
--- a/core/templates/cowdata.h
+++ b/core/templates/cowdata.h
@@ -36,6 +36,7 @@
#include "core/templates/safe_refcount.h"
#include <string.h>
+#include <type_traits>
template <class T>
class Vector;
@@ -158,6 +159,7 @@ public:
return _ptr[p_index];
}
+ template <bool p_ensure_zero = false>
Error resize(int p_size);
_FORCE_INLINE_ void remove_at(int p_index) {
@@ -204,7 +206,7 @@ void CowData<T>::_unref(void *p_data) {
}
// clean up
- if (!__has_trivial_destructor(T)) {
+ if (!std::is_trivially_destructible<T>::value) {
uint32_t *count = _get_size();
T *data = (T *)(count + 1);
@@ -239,7 +241,7 @@ uint32_t CowData<T>::_copy_on_write() {
T *_data = (T *)(mem_new);
// initialize new elements
- if (__has_trivial_copy(T)) {
+ if (std::is_trivially_copyable<T>::value) {
memcpy(mem_new, _ptr, current_size * sizeof(T));
} else {
@@ -257,6 +259,7 @@ uint32_t CowData<T>::_copy_on_write() {
}
template <class T>
+template <bool p_ensure_zero>
Error CowData<T>::resize(int p_size) {
ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER);
@@ -302,16 +305,18 @@ Error CowData<T>::resize(int p_size) {
// construct the newly created elements
- if (!__has_trivial_constructor(T)) {
+ if (!std::is_trivially_constructible<T>::value) {
for (int i = *_get_size(); i < p_size; i++) {
memnew_placement(&_ptr[i], T);
}
+ } else if (p_ensure_zero) {
+ memset((void *)(_ptr + current_size), 0, (p_size - current_size) * sizeof(T));
}
*_get_size() = p_size;
} else if (p_size < current_size) {
- if (!__has_trivial_destructor(T)) {
+ if (!std::is_trivially_destructible<T>::value) {
// deinitialize no longer needed elements
for (uint32_t i = p_size; i < *_get_size(); i++) {
T *t = &_ptr[i];
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index 547534f26a..d85cdf7adc 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -40,6 +40,8 @@
#include "core/math/vector2i.h"
#include "core/math/vector3.h"
#include "core/math/vector3i.h"
+#include "core/math/vector4.h"
+#include "core/math/vector4i.h"
#include "core/object/object_id.h"
#include "core/string/node_path.h"
#include "core/string/string_name.h"
@@ -332,6 +334,13 @@ struct HashMapHasherDefault {
h = hash_murmur3_one_32(p_vec.z, h);
return hash_fmix32(h);
}
+ static _FORCE_INLINE_ uint32_t hash(const Vector4i &p_vec) {
+ uint32_t h = hash_murmur3_one_32(p_vec.x);
+ h = hash_murmur3_one_32(p_vec.y, h);
+ h = hash_murmur3_one_32(p_vec.z, h);
+ h = hash_murmur3_one_32(p_vec.w, h);
+ return hash_fmix32(h);
+ }
static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) {
uint32_t h = hash_murmur3_one_real(p_vec.x);
h = hash_murmur3_one_real(p_vec.y, h);
@@ -343,6 +352,13 @@ struct HashMapHasherDefault {
h = hash_murmur3_one_real(p_vec.z, h);
return hash_fmix32(h);
}
+ static _FORCE_INLINE_ uint32_t hash(const Vector4 &p_vec) {
+ uint32_t h = hash_murmur3_one_real(p_vec.x);
+ h = hash_murmur3_one_real(p_vec.y, h);
+ h = hash_murmur3_one_real(p_vec.z, h);
+ h = hash_murmur3_one_real(p_vec.w, h);
+ return hash_fmix32(h);
+ }
static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) {
uint32_t h = hash_murmur3_one_32(p_rect.position.x);
h = hash_murmur3_one_32(p_rect.position.y, h);
diff --git a/core/templates/local_vector.h b/core/templates/local_vector.h
index 8d687effcf..49690f2373 100644
--- a/core/templates/local_vector.h
+++ b/core/templates/local_vector.h
@@ -37,6 +37,7 @@
#include "core/templates/vector.h"
#include <initializer_list>
+#include <type_traits>
// If tight, it grows strictly as much as needed.
// Otherwise, it grows exponentially (the default and what you want in most cases).
@@ -67,7 +68,7 @@ public:
CRASH_COND_MSG(!data, "Out of memory");
}
- if (!__has_trivial_constructor(T) && !force_trivial) {
+ if (!std::is_trivially_constructible<T>::value && !force_trivial) {
memnew_placement(&data[count++], T(p_elem));
} else {
data[count++] = p_elem;
@@ -80,7 +81,7 @@ public:
for (U i = p_index; i < count; i++) {
data[i] = data[i + 1];
}
- if (!__has_trivial_destructor(T) && !force_trivial) {
+ if (!std::is_trivially_destructible<T>::value && !force_trivial) {
data[count].~T();
}
}
@@ -93,7 +94,7 @@ public:
if (count > p_index) {
data[p_index] = data[count];
}
- if (!__has_trivial_destructor(T) && !force_trivial) {
+ if (!std::is_trivially_destructible<T>::value && !force_trivial) {
data[count].~T();
}
}
@@ -134,7 +135,7 @@ public:
_FORCE_INLINE_ U size() const { return count; }
void resize(U p_size) {
if (p_size < count) {
- if (!__has_trivial_destructor(T) && !force_trivial) {
+ if (!std::is_trivially_destructible<T>::value && !force_trivial) {
for (U i = p_size; i < count; i++) {
data[i].~T();
}
@@ -151,7 +152,7 @@ public:
data = (T *)memrealloc(data, capacity * sizeof(T));
CRASH_COND_MSG(!data, "Out of memory");
}
- if (!__has_trivial_constructor(T) && !force_trivial) {
+ if (!std::is_trivially_constructible<T>::value && !force_trivial) {
for (U i = count; i < p_size; i++) {
memnew_placement(&data[i], T);
}
diff --git a/core/templates/lru.h b/core/templates/lru.h
index 48ba318b12..3a78de61db 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) {
@@ -123,4 +124,4 @@ public:
}
};
-#endif
+#endif // LRU_H
diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h
index cf5911a847..43aab052fd 100644
--- a/core/templates/paged_allocator.h
+++ b/core/templates/paged_allocator.h
@@ -31,11 +31,14 @@
#ifndef PAGED_ALLOCATOR_H
#define PAGED_ALLOCATOR_H
+#include "core/core_globals.h"
#include "core/os/memory.h"
#include "core/os/spin_lock.h"
+#include "core/string/ustring.h"
#include "core/typedefs.h"
#include <type_traits>
+#include <typeinfo>
template <class T, bool thread_safe = false>
class PagedAllocator {
@@ -132,7 +135,12 @@ public:
}
~PagedAllocator() {
- ERR_FAIL_COND_MSG(allocs_available < pages_allocated * page_size, "Pages in use exist at exit in PagedAllocator");
+ if (allocs_available < pages_allocated * page_size) {
+ if (CoreGlobals::leak_reporting_enabled) {
+ ERR_FAIL_COND_MSG(allocs_available < pages_allocated * page_size, String("Pages in use exist at exit in PagedAllocator: ") + String(typeid(T).name()));
+ }
+ return;
+ }
reset();
}
};
diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h
index 33d2757bec..f1ede556e6 100644
--- a/core/templates/paged_array.h
+++ b/core/templates/paged_array.h
@@ -35,6 +35,8 @@
#include "core/os/spin_lock.h"
#include "core/typedefs.h"
+#include <type_traits>
+
// PagedArray is used mainly for filling a very large array from multiple threads efficiently and without causing major fragmentation
// PageArrayPool manages central page allocation in a thread safe matter
@@ -197,7 +199,7 @@ public:
uint32_t page = count >> page_size_shift;
uint32_t offset = count & page_size_mask;
- if (!__has_trivial_constructor(T)) {
+ if (!std::is_trivially_constructible<T>::value) {
memnew_placement(&page_data[page][offset], T(p_value));
} else {
page_data[page][offset] = p_value;
@@ -209,7 +211,7 @@ public:
_FORCE_INLINE_ void pop_back() {
ERR_FAIL_COND(count == 0);
- if (!__has_trivial_destructor(T)) {
+ if (!std::is_trivially_destructible<T>::value) {
uint32_t page = (count - 1) >> page_size_shift;
uint32_t offset = (count - 1) & page_size_mask;
page_data[page][offset].~T();
@@ -226,7 +228,7 @@ public:
void clear() {
//destruct if needed
- if (!__has_trivial_destructor(T)) {
+ if (!std::is_trivially_destructible<T>::value) {
for (uint64_t i = 0; i < count; i++) {
uint32_t page = i >> page_size_shift;
uint32_t offset = i & page_size_mask;
@@ -309,13 +311,13 @@ public:
uint32_t to_copy = MIN(page_size - new_remainder, remainder);
for (uint32_t i = 0; i < to_copy; i++) {
- if (!__has_trivial_constructor(T)) {
+ if (!std::is_trivially_constructible<T>::value) {
memnew_placement(&dst_page[i + new_remainder], T(remainder_page[i + remainder - to_copy]));
} else {
dst_page[i + new_remainder] = remainder_page[i + remainder - to_copy];
}
- if (!__has_trivial_destructor(T)) {
+ if (!std::is_trivially_destructible<T>::value) {
remainder_page[i + remainder - to_copy].~T();
}
}
diff --git a/core/templates/rb_map.h b/core/templates/rb_map.h
index c732ccd485..3393e6dd3e 100644
--- a/core/templates/rb_map.h
+++ b/core/templates/rb_map.h
@@ -758,4 +758,4 @@ public:
}
};
-#endif // MAP_H
+#endif // RB_MAP_H
diff --git a/core/templates/rb_set.h b/core/templates/rb_set.h
index 226ea979c9..e87ea544fd 100644
--- a/core/templates/rb_set.h
+++ b/core/templates/rb_set.h
@@ -708,4 +708,4 @@ public:
}
};
-#endif // SET_H
+#endif // RB_SET_H
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index 9c74b41818..320faebe98 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -79,7 +79,7 @@ class RID_Alloc : public RID_AllocBase {
const char *description = nullptr;
- SpinLock spin_lock;
+ mutable SpinLock spin_lock;
_FORCE_INLINE_ RID _allocate_rid() {
if (THREAD_SAFE) {
@@ -220,7 +220,7 @@ public:
memnew_placement(mem, T(p_value));
}
- _FORCE_INLINE_ bool owns(const RID &p_rid) {
+ _FORCE_INLINE_ bool owns(const RID &p_rid) const {
if (THREAD_SAFE) {
spin_lock.lock();
}
@@ -292,7 +292,7 @@ public:
_FORCE_INLINE_ uint32_t get_rid_count() const {
return alloc_count;
}
- void get_owned_list(List<RID> *p_owned) {
+ void get_owned_list(List<RID> *p_owned) const {
if (THREAD_SAFE) {
spin_lock.lock();
}
@@ -308,7 +308,7 @@ public:
}
//used for fast iteration in the elements or RIDs
- void fill_owned_buffer(RID *p_rid_buffer) {
+ void fill_owned_buffer(RID *p_rid_buffer) const {
if (THREAD_SAFE) {
spin_lock.lock();
}
@@ -402,7 +402,7 @@ public:
*ptr = p_new_ptr;
}
- _FORCE_INLINE_ bool owns(const RID &p_rid) {
+ _FORCE_INLINE_ bool owns(const RID &p_rid) const {
return alloc.owns(p_rid);
}
@@ -414,11 +414,11 @@ public:
return alloc.get_rid_count();
}
- _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) {
+ _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) const {
return alloc.get_owned_list(p_owned);
}
- void fill_owned_buffer(RID *p_rid_buffer) {
+ void fill_owned_buffer(RID *p_rid_buffer) const {
alloc.fill_owned_buffer(p_rid_buffer);
}
@@ -458,7 +458,7 @@ public:
return alloc.get_or_null(p_rid);
}
- _FORCE_INLINE_ bool owns(const RID &p_rid) {
+ _FORCE_INLINE_ bool owns(const RID &p_rid) const {
return alloc.owns(p_rid);
}
@@ -470,10 +470,10 @@ public:
return alloc.get_rid_count();
}
- _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) {
+ _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) const {
return alloc.get_owned_list(p_owned);
}
- void fill_owned_buffer(RID *p_rid_buffer) {
+ void fill_owned_buffer(RID *p_rid_buffer) const {
alloc.fill_owned_buffer(p_rid_buffer);
}
diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h
index 76f76be96a..1f6551762e 100644
--- a/core/templates/safe_refcount.h
+++ b/core/templates/safe_refcount.h
@@ -111,7 +111,8 @@ public:
if (tmp >= p_value) {
return tmp; // already greater, or equal
}
- if (value.compare_exchange_weak(tmp, p_value, std::memory_order_release)) {
+
+ if (value.compare_exchange_weak(tmp, p_value, std::memory_order_acq_rel)) {
return p_value;
}
}
@@ -123,7 +124,7 @@ public:
if (c == 0) {
return 0;
}
- if (value.compare_exchange_weak(c, c + 1, std::memory_order_release)) {
+ if (value.compare_exchange_weak(c, c + 1, std::memory_order_acq_rel)) {
return c + 1;
}
}
diff --git a/core/templates/thread_work_pool.h b/core/templates/thread_work_pool.h
deleted file mode 100644
index b0cebf04f1..0000000000
--- a/core/templates/thread_work_pool.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*************************************************************************/
-/* thread_work_pool.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 THREAD_WORK_POOL_H
-#define THREAD_WORK_POOL_H
-
-#include "core/os/memory.h"
-#include "core/os/semaphore.h"
-#include "core/os/thread.h"
-
-#include <atomic>
-
-class ThreadWorkPool {
- std::atomic<uint32_t> index;
-
- struct BaseWork {
- std::atomic<uint32_t> *index = nullptr;
- uint32_t max_elements = 0;
- virtual void work() = 0;
- virtual ~BaseWork() = default;
- };
-
- template <class C, class M, class U>
- struct Work : public BaseWork {
- C *instance;
- M method;
- U userdata;
- virtual void work() override {
- while (true) {
- uint32_t work_index = index->fetch_add(1, std::memory_order_relaxed);
- if (work_index >= max_elements) {
- break;
- }
- (instance->*method)(work_index, userdata);
- }
- }
- };
-
- struct ThreadData {
- Thread thread;
- Semaphore start;
- Semaphore completed;
- std::atomic<bool> exit;
- BaseWork *work = nullptr;
- };
-
- ThreadData *threads = nullptr;
- uint32_t thread_count = 0;
- uint32_t threads_working = 0;
- BaseWork *current_work = nullptr;
-
- static void _thread_function(void *p_user);
-
-public:
- template <class C, class M, class U>
- void begin_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
- ERR_FAIL_COND(!threads); //never initialized
- ERR_FAIL_COND(current_work != nullptr);
-
- index.store(0, std::memory_order_release);
-
- Work<C, M, U> *w = memnew((Work<C, M, U>));
- w->instance = p_instance;
- w->userdata = p_userdata;
- w->method = p_method;
- w->index = &index;
- w->max_elements = p_elements;
-
- current_work = w;
-
- threads_working = MIN(p_elements, thread_count);
-
- for (uint32_t i = 0; i < threads_working; i++) {
- threads[i].work = w;
- threads[i].start.post();
- }
- }
-
- bool is_working() const {
- return current_work != nullptr;
- }
-
- bool is_done_dispatching() const {
- ERR_FAIL_COND_V(current_work == nullptr, true);
- return index.load(std::memory_order_acquire) >= current_work->max_elements;
- }
-
- uint32_t get_work_index() const {
- ERR_FAIL_COND_V(current_work == nullptr, 0);
- uint32_t idx = index.load(std::memory_order_acquire);
- return MIN(idx, current_work->max_elements);
- }
-
- void end_work() {
- ERR_FAIL_COND(current_work == nullptr);
- for (uint32_t i = 0; i < threads_working; i++) {
- threads[i].completed.wait();
- threads[i].work = nullptr;
- }
-
- threads_working = 0;
- memdelete(current_work);
- current_work = nullptr;
- }
-
- template <class C, class M, class U>
- void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
- switch (p_elements) {
- case 0:
- // Nothing to do, so do nothing.
- break;
- case 1:
- // No value in pushing the work to another thread if it's a single job
- // and we're going to wait for it to finish. Just run it right here.
- (p_instance->*p_method)(0, p_userdata);
- break;
- default:
- // Multiple jobs to do; commence threaded business.
- begin_work(p_elements, p_instance, p_method, p_userdata);
- end_work();
- }
- }
-
- _FORCE_INLINE_ int get_thread_count() const { return thread_count; }
- void init(int p_thread_count = -1);
- void finish();
- ~ThreadWorkPool();
-};
-
-#endif // THREAD_POOL_H
diff --git a/core/templates/vector.h b/core/templates/vector.h
index 2ac7c7630a..51595a75f5 100644
--- a/core/templates/vector.h
+++ b/core/templates/vector.h
@@ -89,6 +89,7 @@ public:
_FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
_FORCE_INLINE_ int size() const { return _cowdata.size(); }
Error resize(int p_size) { return _cowdata.resize(p_size); }
+ Error resize_zeroed(int p_size) { return _cowdata.template resize<true>(p_size); }
_FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata.get(p_index); }
Error insert(int p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); }
int find(const T &p_val, int p_from = 0) const { return _cowdata.find(p_val, p_from); }
@@ -145,6 +146,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/array.cpp b/core/variant/array.cpp
index af166e09a3..c1bdd6a6bc 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -441,7 +441,7 @@ Array Array::filter(const Callable &p_callable) const {
Variant result;
Callable::CallError ce;
- p_callable.call(argptrs, 1, result, ce);
+ p_callable.callp(argptrs, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(Array(), "Error calling method from 'filter': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
}
@@ -467,7 +467,7 @@ Array Array::map(const Callable &p_callable) const {
Variant result;
Callable::CallError ce;
- p_callable.call(argptrs, 1, result, ce);
+ p_callable.callp(argptrs, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(Array(), "Error calling method from 'map': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
}
@@ -493,7 +493,7 @@ Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const
Variant result;
Callable::CallError ce;
- p_callable.call(argptrs, 2, result, ce);
+ p_callable.callp(argptrs, 2, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(Variant(), "Error calling method from 'reduce': " + Variant::get_callable_error_text(p_callable, argptrs, 2, ce));
}
@@ -510,7 +510,7 @@ bool Array::any(const Callable &p_callable) const {
Variant result;
Callable::CallError ce;
- p_callable.call(argptrs, 1, result, ce);
+ p_callable.callp(argptrs, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(false, "Error calling method from 'any': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
}
@@ -532,7 +532,7 @@ bool Array::all(const Callable &p_callable) const {
Variant result;
Callable::CallError ce;
- p_callable.call(argptrs, 1, result, ce);
+ p_callable.callp(argptrs, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(false, "Error calling method from 'all': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
}
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 22a13b0fab..f0c3b1ce38 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);
@@ -113,7 +136,10 @@ VARIANT_ENUM_CAST(Vector2::Axis);
VARIANT_ENUM_CAST(Vector2i::Axis);
VARIANT_ENUM_CAST(Vector3::Axis);
VARIANT_ENUM_CAST(Vector3i::Axis);
+VARIANT_ENUM_CAST(Vector4::Axis);
+VARIANT_ENUM_CAST(Vector4i::Axis);
VARIANT_ENUM_CAST(Basis::EulerOrder);
+VARIANT_ENUM_CAST(Projection::Planes);
VARIANT_ENUM_CAST(Error);
VARIANT_ENUM_CAST(Side);
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index 5453f0d5c6..28efb43fc5 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -36,11 +36,11 @@
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
-void Callable::call_deferred(const Variant **p_arguments, int p_argcount) const {
+void Callable::call_deferredp(const Variant **p_arguments, int p_argcount) const {
MessageQueue::get_singleton()->push_callablep(*this, p_arguments, p_argcount);
}
-void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const {
+void Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const {
if (is_null()) {
r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
r_call_error.argument = 0;
@@ -63,21 +63,23 @@ void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_retu
}
}
-void Callable::rpc(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const {
+Error Callable::rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const {
if (is_null()) {
r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
r_call_error.argument = 0;
r_call_error.expected = 0;
+ return ERR_UNCONFIGURED;
} else if (!is_custom()) {
r_call_error.error = CallError::CALL_ERROR_INVALID_METHOD;
r_call_error.argument = 0;
r_call_error.expected = 0;
+ return ERR_UNCONFIGURED;
} else {
- custom->rpc(p_id, p_arguments, p_argcount, r_call_error);
+ return custom->rpc(p_id, p_arguments, p_argcount, r_call_error);
}
}
-Callable Callable::bind(const Variant **p_arguments, int p_argcount) const {
+Callable Callable::bindp(const Variant **p_arguments, int p_argcount) const {
Vector<Variant> args;
args.resize(p_argcount);
for (int i = 0; i < p_argcount; i++) {
@@ -316,10 +318,11 @@ StringName CallableCustom::get_method() const {
ERR_FAIL_V_MSG(StringName(), vformat("Can't get method on CallableCustom \"%s\".", get_as_text()));
}
-void CallableCustom::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
+Error CallableCustom::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_call_error.argument = 0;
r_call_error.expected = 0;
+ return ERR_UNCONFIGURED;
}
const Callable *CallableCustom::get_base_comparator() const {
@@ -387,7 +390,7 @@ Error Signal::connect(const Callable &p_callable, uint32_t p_flags) {
Object *object = get_object();
ERR_FAIL_COND_V(!object, ERR_UNCONFIGURED);
- return object->connect(name, p_callable, varray(), p_flags);
+ return object->connect(name, p_callable, p_flags);
}
void Signal::disconnect(const Callable &p_callable) {
@@ -435,8 +438,8 @@ bool CallableComparator::operator()(const Variant &p_l, const Variant &p_r) cons
const Variant *args[2] = { &p_l, &p_r };
Callable::CallError err;
Variant res;
- func.call(args, 2, res, err);
+ func.callp(args, 2, res, err);
ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, false,
- "Error calling compare method: " + Variant::get_callable_error_text(func, args, 1, err));
+ "Error calling compare method: " + Variant::get_callable_error_text(func, args, 2, err));
return res;
}
diff --git a/core/variant/callable.h b/core/variant/callable.h
index bbcf5427ba..1f1c983eb3 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -45,6 +45,7 @@ class CallableCustom;
// but can be optimized or customized.
// Enforce 16 bytes with `alignas` to avoid arch-specific alignment issues on x86 vs armv7.
+
class Callable {
alignas(8) StringName method;
union {
@@ -68,10 +69,10 @@ public:
int expected = 0;
};
- void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const;
- void call_deferred(const Variant **p_arguments, int p_argcount) const;
+ void callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const;
+ void call_deferredp(const Variant **p_arguments, int p_argcount) const;
- void rpc(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const;
+ Error rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const;
_FORCE_INLINE_ bool is_null() const {
return method == StringName() && object == 0;
@@ -84,7 +85,10 @@ public:
}
bool is_valid() const;
- Callable bind(const Variant **p_arguments, int p_argcount) const;
+ template <typename... VarArgs>
+ Callable bind(VarArgs... p_args);
+
+ Callable bindp(const Variant **p_arguments, int p_argcount) const;
Callable unbind(int p_argcount) const;
Object *get_object() const;
@@ -129,7 +133,7 @@ public:
virtual StringName get_method() const;
virtual ObjectID get_object() const = 0; //must always be able to provide an object
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0;
- virtual void rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
+ virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
virtual const Callable *get_base_comparator() const;
CallableCustom();
diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp
index 1a400b4360..d26aa2ae46 100644
--- a/core/variant/callable_bind.cpp
+++ b/core/variant/callable_bind.cpp
@@ -96,7 +96,7 @@ void CallableCustomBind::call(const Variant **p_arguments, int p_argcount, Varia
args[i + p_argcount] = (const Variant *)&binds[i];
}
- callable.call(args, p_argcount + binds.size(), r_return_value, r_call_error);
+ callable.callp(args, p_argcount + binds.size(), r_return_value, r_call_error);
}
CallableCustomBind::CallableCustomBind(const Callable &p_callable, const Vector<Variant> &p_binds) {
@@ -171,7 +171,7 @@ void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Var
r_call_error.expected = argcount;
return;
}
- callable.call(p_arguments, p_argcount - argcount, r_return_value, r_call_error);
+ callable.callp(p_arguments, p_argcount - argcount, r_return_value, r_call_error);
}
CallableCustomUnbind::CallableCustomUnbind(const Callable &p_callable, int p_argcount) {
@@ -181,28 +181,3 @@ CallableCustomUnbind::CallableCustomUnbind(const Callable &p_callable, int p_arg
CallableCustomUnbind::~CallableCustomUnbind() {
}
-
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1) {
- const Variant *args[1] = { &p_arg1 };
- return p_callable.bind(args, 1);
-}
-
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2) {
- const Variant *args[2] = { &p_arg1, &p_arg2 };
- return p_callable.bind(args, 2);
-}
-
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3) {
- const Variant *args[3] = { &p_arg1, &p_arg2, &p_arg3 };
- return p_callable.bind(args, 3);
-}
-
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4) {
- const Variant *args[4] = { &p_arg1, &p_arg2, &p_arg3, &p_arg4 };
- return p_callable.bind(args, 4);
-}
-
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5) {
- const Variant *args[5] = { &p_arg1, &p_arg2, &p_arg3, &p_arg4, &p_arg5 };
- return p_callable.bind(args, 5);
-}
diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h
index a5c830e109..f7351d29e0 100644
--- a/core/variant/callable_bind.h
+++ b/core/variant/callable_bind.h
@@ -84,10 +84,4 @@ public:
virtual ~CallableCustomUnbind();
};
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1);
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2);
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3);
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4);
-Callable callable_bind(const Callable &p_callable, const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5);
-
#endif // CALLABLE_BIND_H
diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h
index d0acf60c22..0ed70a5504 100644
--- a/core/variant/method_ptrcall.h
+++ b/core/variant/method_ptrcall.h
@@ -125,7 +125,10 @@ MAKE_PTRARG(Rect2);
MAKE_PTRARG(Rect2i);
MAKE_PTRARG_BY_REFERENCE(Vector3);
MAKE_PTRARG_BY_REFERENCE(Vector3i);
+MAKE_PTRARG_BY_REFERENCE(Vector4);
+MAKE_PTRARG_BY_REFERENCE(Vector4i);
MAKE_PTRARG(Transform2D);
+MAKE_PTRARG(Projection);
MAKE_PTRARG_BY_REFERENCE(Plane);
MAKE_PTRARG(Quaternion);
MAKE_PTRARG_BY_REFERENCE(AABB);
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index bacd0d19ce..7372c60754 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -144,12 +144,15 @@ MAKE_TYPE_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPE_INFO(Vector2i, Variant::VECTOR2I)
MAKE_TYPE_INFO(Rect2i, Variant::RECT2I)
MAKE_TYPE_INFO(Vector3i, Variant::VECTOR3I)
+MAKE_TYPE_INFO(Vector4, Variant::VECTOR4)
+MAKE_TYPE_INFO(Vector4i, Variant::VECTOR4I)
MAKE_TYPE_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPE_INFO(Plane, Variant::PLANE)
MAKE_TYPE_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPE_INFO(AABB, Variant::AABB)
MAKE_TYPE_INFO(Basis, Variant::BASIS)
MAKE_TYPE_INFO(Transform3D, Variant::TRANSFORM3D)
+MAKE_TYPE_INFO(Projection, Variant::PROJECTION)
MAKE_TYPE_INFO(Color, Variant::COLOR)
MAKE_TYPE_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH)
@@ -279,6 +282,52 @@ 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; }
+ _FORCE_INLINE_ operator Variant() 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.cpp b/core/variant/variant.cpp
index ae92d7b5c4..a5bc6c229d 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -39,6 +39,10 @@
#include "core/string/print_string.h"
#include "core/variant/variant_parser.h"
+PagedAllocator<Variant::Pools::BucketSmall, true> Variant::Pools::_bucket_small;
+PagedAllocator<Variant::Pools::BucketMedium, true> Variant::Pools::_bucket_medium;
+PagedAllocator<Variant::Pools::BucketLarge, true> Variant::Pools::_bucket_large;
+
String Variant::get_type_name(Variant::Type p_type) {
switch (p_type) {
case NIL: {
@@ -83,6 +87,12 @@ String Variant::get_type_name(Variant::Type p_type) {
case VECTOR3I: {
return "Vector3i";
} break;
+ case VECTOR4: {
+ return "Vector4";
+ } break;
+ case VECTOR4I: {
+ return "Vector4i";
+ } break;
case PLANE: {
return "Plane";
@@ -102,6 +112,10 @@ String Variant::get_type_name(Variant::Type p_type) {
return "Transform3D";
} break;
+ case PROJECTION: {
+ return "Projection";
+
+ } break;
// misc types
case COLOR: {
@@ -298,6 +312,24 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
valid_types = valid;
} break;
+ case VECTOR4: {
+ static const Type valid[] = {
+ VECTOR4I,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case VECTOR4I: {
+ static const Type valid[] = {
+ VECTOR4,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
case QUATERNION: {
static const Type valid[] = {
@@ -322,6 +354,16 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
TRANSFORM2D,
QUATERNION,
BASIS,
+ PROJECTION,
+ NIL
+ };
+
+ valid_types = valid;
+
+ } break;
+ case PROJECTION: {
+ static const Type valid[] = {
+ TRANSFORM3D,
NIL
};
@@ -604,6 +646,24 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
valid_types = valid;
} break;
+ case VECTOR4: {
+ static const Type valid[] = {
+ VECTOR4I,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+ case VECTOR4I: {
+ static const Type valid[] = {
+ VECTOR4,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
case QUATERNION: {
static const Type valid[] = {
@@ -628,6 +688,16 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
TRANSFORM2D,
QUATERNION,
BASIS,
+ PROJECTION,
+ NIL
+ };
+
+ valid_types = valid;
+
+ } break;
+ case PROJECTION: {
+ static const Type valid[] = {
+ TRANSFORM3D,
NIL
};
@@ -858,6 +928,14 @@ bool Variant::is_zero() const {
return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i();
} break;
+ case VECTOR4: {
+ return *reinterpret_cast<const Vector4 *>(_data._mem) == Vector4();
+
+ } break;
+ case VECTOR4I: {
+ return *reinterpret_cast<const Vector4i *>(_data._mem) == Vector4i();
+
+ } break;
case PLANE: {
return *reinterpret_cast<const Plane *>(_data._mem) == Plane();
@@ -877,6 +955,10 @@ bool Variant::is_zero() const {
return *_data._transform3d == Transform3D();
} break;
+ case PROJECTION: {
+ return *_data._projection == Projection();
+
+ } break;
// misc types
case COLOR: {
@@ -998,6 +1080,14 @@ bool Variant::is_one() const {
return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i(1, 1, 1);
} break;
+ case VECTOR4: {
+ return *reinterpret_cast<const Vector4 *>(_data._mem) == Vector4(1, 1, 1, 1);
+
+ } break;
+ case VECTOR4I: {
+ return *reinterpret_cast<const Vector4i *>(_data._mem) == Vector4i(1, 1, 1, 1);
+
+ } break;
case PLANE: {
return *reinterpret_cast<const Plane *>(_data._mem) == Plane(1, 1, 1, 1);
@@ -1076,7 +1166,8 @@ void Variant::reference(const Variant &p_variant) {
memnew_placement(_data._mem, Rect2i(*reinterpret_cast<const Rect2i *>(p_variant._data._mem)));
} break;
case TRANSFORM2D: {
- _data._transform2d = memnew(Transform2D(*p_variant._data._transform2d));
+ _data._transform2d = (Transform2D *)Pools::_bucket_small.alloc();
+ memnew_placement(_data._transform2d, Transform2D(*p_variant._data._transform2d));
} break;
case VECTOR3: {
memnew_placement(_data._mem, Vector3(*reinterpret_cast<const Vector3 *>(p_variant._data._mem)));
@@ -1084,23 +1175,33 @@ void Variant::reference(const Variant &p_variant) {
case VECTOR3I: {
memnew_placement(_data._mem, Vector3i(*reinterpret_cast<const Vector3i *>(p_variant._data._mem)));
} break;
+ case VECTOR4: {
+ memnew_placement(_data._mem, Vector4(*reinterpret_cast<const Vector4 *>(p_variant._data._mem)));
+ } break;
+ case VECTOR4I: {
+ memnew_placement(_data._mem, Vector4i(*reinterpret_cast<const Vector4i *>(p_variant._data._mem)));
+ } break;
case PLANE: {
memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem)));
} break;
-
case AABB: {
- _data._aabb = memnew(::AABB(*p_variant._data._aabb));
+ _data._aabb = (::AABB *)Pools::_bucket_small.alloc();
+ memnew_placement(_data._aabb, ::AABB(*p_variant._data._aabb));
} break;
case QUATERNION: {
memnew_placement(_data._mem, Quaternion(*reinterpret_cast<const Quaternion *>(p_variant._data._mem)));
-
} break;
case BASIS: {
- _data._basis = memnew(Basis(*p_variant._data._basis));
-
+ _data._basis = (Basis *)Pools::_bucket_medium.alloc();
+ memnew_placement(_data._basis, Basis(*p_variant._data._basis));
} break;
case TRANSFORM3D: {
- _data._transform3d = memnew(Transform3D(*p_variant._data._transform3d));
+ _data._transform3d = (Transform3D *)Pools::_bucket_medium.alloc();
+ memnew_placement(_data._transform3d, Transform3D(*p_variant._data._transform3d));
+ } break;
+ case PROJECTION: {
+ _data._projection = (Projection *)Pools::_bucket_large.alloc();
+ memnew_placement(_data._projection, Projection(*p_variant._data._projection));
} break;
// misc types
@@ -1250,6 +1351,12 @@ void Variant::zero() {
case VECTOR3I:
*reinterpret_cast<Vector3i *>(this->_data._mem) = Vector3i();
break;
+ case VECTOR4:
+ *reinterpret_cast<Vector4 *>(this->_data._mem) = Vector4();
+ break;
+ case VECTOR4I:
+ *reinterpret_cast<Vector4i *>(this->_data._mem) = Vector4i();
+ break;
case PLANE:
*reinterpret_cast<Plane *>(this->_data._mem) = Plane();
break;
@@ -1280,18 +1387,40 @@ void Variant::_clear_internal() {
RECT2
*/
case TRANSFORM2D: {
- memdelete(_data._transform2d);
+ if (_data._transform2d) {
+ _data._transform2d->~Transform2D();
+ Pools::_bucket_small.free((Pools::BucketSmall *)_data._transform2d);
+ _data._transform2d = nullptr;
+ }
} break;
case AABB: {
- memdelete(_data._aabb);
+ if (_data._aabb) {
+ _data._aabb->~AABB();
+ Pools::_bucket_small.free((Pools::BucketSmall *)_data._aabb);
+ _data._aabb = nullptr;
+ }
} break;
case BASIS: {
- memdelete(_data._basis);
+ if (_data._basis) {
+ _data._basis->~Basis();
+ Pools::_bucket_medium.free((Pools::BucketMedium *)_data._basis);
+ _data._basis = nullptr;
+ }
} break;
case TRANSFORM3D: {
- memdelete(_data._transform3d);
+ if (_data._transform3d) {
+ _data._transform3d->~Transform3D();
+ Pools::_bucket_medium.free((Pools::BucketMedium *)_data._transform3d);
+ _data._transform3d = nullptr;
+ }
+ } break;
+ case PROJECTION: {
+ if (_data._projection) {
+ _data._projection->~Projection();
+ Pools::_bucket_large.free((Pools::BucketLarge *)_data._projection);
+ _data._projection = nullptr;
+ }
} break;
-
// misc types
case STRING_NAME: {
reinterpret_cast<StringName *>(_data._mem)->~StringName();
@@ -1681,6 +1810,10 @@ String Variant::stringify(int recursion_count) const {
return operator Vector3();
case VECTOR3I:
return operator Vector3i();
+ case VECTOR4:
+ return operator Vector4();
+ case VECTOR4I:
+ return operator Vector4i();
case PLANE:
return operator Plane();
case AABB:
@@ -1691,6 +1824,8 @@ String Variant::stringify(int recursion_count) const {
return operator Basis();
case TRANSFORM3D:
return operator Transform3D();
+ case PROJECTION:
+ return operator Projection();
case STRING_NAME:
return operator StringName();
case NODE_PATH:
@@ -1812,6 +1947,10 @@ Variant::operator Vector2() const {
return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y);
} else if (type == VECTOR3I) {
return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y);
+ } else if (type == VECTOR4) {
+ return Vector2(reinterpret_cast<const Vector4 *>(_data._mem)->x, reinterpret_cast<const Vector4 *>(_data._mem)->y);
+ } else if (type == VECTOR4I) {
+ return Vector2(reinterpret_cast<const Vector4i *>(_data._mem)->x, reinterpret_cast<const Vector4i *>(_data._mem)->y);
} else {
return Vector2();
}
@@ -1826,6 +1965,10 @@ Variant::operator Vector2i() const {
return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y);
} else if (type == VECTOR3I) {
return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y);
+ } else if (type == VECTOR4) {
+ return Vector2(reinterpret_cast<const Vector4 *>(_data._mem)->x, reinterpret_cast<const Vector4 *>(_data._mem)->y);
+ } else if (type == VECTOR4I) {
+ return Vector2(reinterpret_cast<const Vector4i *>(_data._mem)->x, reinterpret_cast<const Vector4i *>(_data._mem)->y);
} else {
return Vector2i();
}
@@ -1860,6 +2003,10 @@ Variant::operator Vector3() const {
return Vector3(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0);
} else if (type == VECTOR2I) {
return Vector3(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0);
+ } else if (type == VECTOR4) {
+ return Vector3(reinterpret_cast<const Vector4 *>(_data._mem)->x, reinterpret_cast<const Vector4 *>(_data._mem)->y, reinterpret_cast<const Vector4 *>(_data._mem)->z);
+ } else if (type == VECTOR4I) {
+ return Vector3(reinterpret_cast<const Vector4i *>(_data._mem)->x, reinterpret_cast<const Vector4i *>(_data._mem)->y, reinterpret_cast<const Vector4i *>(_data._mem)->z);
} else {
return Vector3();
}
@@ -1874,11 +2021,52 @@ Variant::operator Vector3i() const {
return Vector3i(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0);
} else if (type == VECTOR2I) {
return Vector3i(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0);
+ } else if (type == VECTOR4) {
+ return Vector3i(reinterpret_cast<const Vector4 *>(_data._mem)->x, reinterpret_cast<const Vector4 *>(_data._mem)->y, reinterpret_cast<const Vector4 *>(_data._mem)->z);
+ } else if (type == VECTOR4I) {
+ return Vector3i(reinterpret_cast<const Vector4i *>(_data._mem)->x, reinterpret_cast<const Vector4i *>(_data._mem)->y, reinterpret_cast<const Vector4i *>(_data._mem)->z);
} else {
return Vector3i();
}
}
+Variant::operator Vector4() const {
+ if (type == VECTOR4) {
+ return *reinterpret_cast<const Vector4 *>(_data._mem);
+ } else if (type == VECTOR4I) {
+ return *reinterpret_cast<const Vector4i *>(_data._mem);
+ } else if (type == VECTOR2) {
+ return Vector4(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0, 0.0);
+ } else if (type == VECTOR2I) {
+ return Vector4(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0, 0.0);
+ } else if (type == VECTOR3) {
+ return Vector4(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y, reinterpret_cast<const Vector3 *>(_data._mem)->z, 0.0);
+ } else if (type == VECTOR3I) {
+ return Vector4(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y, reinterpret_cast<const Vector3i *>(_data._mem)->z, 0.0);
+ } else {
+ return Vector4();
+ }
+}
+
+Variant::operator Vector4i() const {
+ if (type == VECTOR4I) {
+ return *reinterpret_cast<const Vector4i *>(_data._mem);
+ } else if (type == VECTOR4) {
+ const Vector4 &v4 = *reinterpret_cast<const Vector4 *>(_data._mem);
+ return Vector4i(v4.x, v4.y, v4.z, v4.w);
+ } else if (type == VECTOR2) {
+ return Vector4i(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0, 0.0);
+ } else if (type == VECTOR2I) {
+ return Vector4i(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0, 0.0);
+ } else if (type == VECTOR3) {
+ return Vector4i(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y, reinterpret_cast<const Vector3 *>(_data._mem)->z, 0.0);
+ } else if (type == VECTOR3I) {
+ return Vector4i(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y, reinterpret_cast<const Vector3i *>(_data._mem)->z, 0.0);
+ } else {
+ return Vector4i();
+ }
+}
+
Variant::operator Plane() const {
if (type == PLANE) {
return *reinterpret_cast<const Plane *>(_data._mem);
@@ -1936,11 +2124,37 @@ Variant::operator Transform3D() const {
m.origin[0] = t.columns[2][0];
m.origin[1] = t.columns[2][1];
return m;
+ } else if (type == PROJECTION) {
+ return *_data._projection;
} else {
return Transform3D();
}
}
+Variant::operator Projection() const {
+ if (type == TRANSFORM3D) {
+ return *_data._transform3d;
+ } else if (type == BASIS) {
+ return Transform3D(*_data._basis, Vector3());
+ } else if (type == QUATERNION) {
+ return Transform3D(Basis(*reinterpret_cast<const Quaternion *>(_data._mem)), Vector3());
+ } else if (type == TRANSFORM2D) {
+ const Transform2D &t = *_data._transform2d;
+ Transform3D m;
+ m.basis.rows[0][0] = t.columns[0][0];
+ m.basis.rows[1][0] = t.columns[0][1];
+ m.basis.rows[0][1] = t.columns[1][0];
+ m.basis.rows[1][1] = t.columns[1][1];
+ m.origin[0] = t.columns[2][0];
+ m.origin[1] = t.columns[2][1];
+ return m;
+ } else if (type == PROJECTION) {
+ return *_data._projection;
+ } else {
+ return Projection();
+ }
+}
+
Variant::operator Transform2D() const {
if (type == TRANSFORM2D) {
return *_data._transform2d;
@@ -2384,6 +2598,16 @@ Variant::Variant(const Vector3i &p_vector3i) {
memnew_placement(_data._mem, Vector3i(p_vector3i));
}
+Variant::Variant(const Vector4 &p_vector4) {
+ type = VECTOR4;
+ memnew_placement(_data._mem, Vector4(p_vector4));
+}
+
+Variant::Variant(const Vector4i &p_vector4i) {
+ type = VECTOR4I;
+ memnew_placement(_data._mem, Vector4i(p_vector4i));
+}
+
Variant::Variant(const Vector2 &p_vector2) {
type = VECTOR2;
memnew_placement(_data._mem, Vector2(p_vector2));
@@ -2411,12 +2635,14 @@ Variant::Variant(const Plane &p_plane) {
Variant::Variant(const ::AABB &p_aabb) {
type = AABB;
- _data._aabb = memnew(::AABB(p_aabb));
+ _data._aabb = (::AABB *)Pools::_bucket_small.alloc();
+ memnew_placement(_data._aabb, ::AABB(p_aabb));
}
Variant::Variant(const Basis &p_matrix) {
type = BASIS;
- _data._basis = memnew(Basis(p_matrix));
+ _data._basis = (Basis *)Pools::_bucket_medium.alloc();
+ memnew_placement(_data._basis, Basis(p_matrix));
}
Variant::Variant(const Quaternion &p_quaternion) {
@@ -2426,12 +2652,20 @@ Variant::Variant(const Quaternion &p_quaternion) {
Variant::Variant(const Transform3D &p_transform) {
type = TRANSFORM3D;
- _data._transform3d = memnew(Transform3D(p_transform));
+ _data._transform3d = (Transform3D *)Pools::_bucket_medium.alloc();
+ memnew_placement(_data._transform3d, Transform3D(p_transform));
+}
+
+Variant::Variant(const Projection &pp_projection) {
+ type = PROJECTION;
+ _data._projection = (Projection *)Pools::_bucket_large.alloc();
+ memnew_placement(_data._projection, Projection(pp_projection));
}
Variant::Variant(const Transform2D &p_transform) {
type = TRANSFORM2D;
- _data._transform2d = memnew(Transform2D(p_transform));
+ _data._transform2d = (Transform2D *)Pools::_bucket_small.alloc();
+ memnew_placement(_data._transform2d, Transform2D(p_transform));
}
Variant::Variant(const Color &p_color) {
@@ -2656,6 +2890,12 @@ void Variant::operator=(const Variant &p_variant) {
case VECTOR3I: {
*reinterpret_cast<Vector3i *>(_data._mem) = *reinterpret_cast<const Vector3i *>(p_variant._data._mem);
} break;
+ case VECTOR4: {
+ *reinterpret_cast<Vector4 *>(_data._mem) = *reinterpret_cast<const Vector4 *>(p_variant._data._mem);
+ } break;
+ case VECTOR4I: {
+ *reinterpret_cast<Vector4i *>(_data._mem) = *reinterpret_cast<const Vector4i *>(p_variant._data._mem);
+ } break;
case PLANE: {
*reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem);
} break;
@@ -2672,6 +2912,9 @@ void Variant::operator=(const Variant &p_variant) {
case TRANSFORM3D: {
*_data._transform3d = *(p_variant._data._transform3d);
} break;
+ case PROJECTION: {
+ *_data._projection = *(p_variant._data._projection);
+ } break;
// misc types
case COLOR: {
@@ -2817,6 +3060,12 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
case VECTOR3I: {
return HashMapHasherDefault::hash(*reinterpret_cast<const Vector3i *>(_data._mem));
} break;
+ case VECTOR4: {
+ return HashMapHasherDefault::hash(*reinterpret_cast<const Vector4 *>(_data._mem));
+ } break;
+ case VECTOR4I: {
+ return HashMapHasherDefault::hash(*reinterpret_cast<const Vector4i *>(_data._mem));
+ } break;
case PLANE: {
uint32_t h = HASH_MURMUR3_SEED;
const Plane &p = *reinterpret_cast<const Plane *>(_data._mem);
@@ -2869,6 +3118,27 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
h = hash_murmur3_one_real(t.origin.z, h);
return hash_fmix32(h);
} break;
+ case PROJECTION: {
+ uint32_t h = HASH_MURMUR3_SEED;
+ const Projection &t = *_data._projection;
+ h = hash_murmur3_one_real(t.matrix[0].x, h);
+ h = hash_murmur3_one_real(t.matrix[0].y, h);
+ h = hash_murmur3_one_real(t.matrix[0].z, h);
+ h = hash_murmur3_one_real(t.matrix[0].w, h);
+ h = hash_murmur3_one_real(t.matrix[1].x, h);
+ h = hash_murmur3_one_real(t.matrix[1].y, h);
+ h = hash_murmur3_one_real(t.matrix[1].z, h);
+ h = hash_murmur3_one_real(t.matrix[1].w, h);
+ h = hash_murmur3_one_real(t.matrix[2].x, h);
+ h = hash_murmur3_one_real(t.matrix[2].y, h);
+ h = hash_murmur3_one_real(t.matrix[2].z, h);
+ h = hash_murmur3_one_real(t.matrix[2].w, h);
+ h = hash_murmur3_one_real(t.matrix[3].x, h);
+ h = hash_murmur3_one_real(t.matrix[3].y, h);
+ h = hash_murmur3_one_real(t.matrix[3].z, h);
+ h = hash_murmur3_one_real(t.matrix[3].w, h);
+ return hash_fmix32(h);
+ } break;
// misc types
case COLOR: {
uint32_t h = HASH_MURMUR3_SEED;
@@ -3062,6 +3332,11 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
(hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
(hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \
(hash_compare_scalar((p_lhs).z, (p_rhs).z))
+#define hash_compare_vector4(p_lhs, p_rhs) \
+ (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
+ (hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \
+ (hash_compare_scalar((p_lhs).z, (p_rhs).z)) && \
+ (hash_compare_scalar((p_lhs).w, (p_rhs).w))
#define hash_compare_quaternion(p_lhs, p_rhs) \
(hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
@@ -3165,6 +3440,18 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
return *l == *r;
} break;
+ case VECTOR4: {
+ const Vector4 *l = reinterpret_cast<const Vector4 *>(_data._mem);
+ const Vector4 *r = reinterpret_cast<const Vector4 *>(p_variant._data._mem);
+
+ return hash_compare_vector4(*l, *r);
+ } break;
+ case VECTOR4I: {
+ const Vector4i *l = reinterpret_cast<const Vector4i *>(_data._mem);
+ const Vector4i *r = reinterpret_cast<const Vector4i *>(p_variant._data._mem);
+
+ return *l == *r;
+ } break;
case PLANE: {
const Plane *l = reinterpret_cast<const Plane *>(_data._mem);
@@ -3215,6 +3502,18 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
return hash_compare_vector3(l->origin, r->origin);
} break;
+ case PROJECTION: {
+ const Projection *l = _data._projection;
+ const Projection *r = p_variant._data._projection;
+
+ for (int i = 0; i < 4; i++) {
+ if (!(hash_compare_vector4(l->matrix[i], r->matrix[i]))) {
+ return false;
+ }
+ }
+
+ return true;
+ } break;
case COLOR: {
const Color *l = reinterpret_cast<const Color *>(_data._mem);
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 872b374b13..212f94a9a8 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -38,6 +38,7 @@
#include "core/math/color.h"
#include "core/math/face3.h"
#include "core/math/plane.h"
+#include "core/math/projection.h"
#include "core/math/quaternion.h"
#include "core/math/rect2.h"
#include "core/math/rect2i.h"
@@ -47,10 +48,13 @@
#include "core/math/vector2i.h"
#include "core/math/vector3.h"
#include "core/math/vector3i.h"
+#include "core/math/vector4.h"
+#include "core/math/vector4i.h"
#include "core/object/object_id.h"
#include "core/os/keyboard.h"
#include "core/string/node_path.h"
#include "core/string/ustring.h"
+#include "core/templates/paged_allocator.h"
#include "core/templates/rid.h"
#include "core/variant/array.h"
#include "core/variant/callable.h"
@@ -91,11 +95,14 @@ public:
VECTOR3,
VECTOR3I,
TRANSFORM2D,
+ VECTOR4,
+ VECTOR4I,
PLANE,
QUATERNION,
AABB,
BASIS,
TRANSFORM3D,
+ PROJECTION,
// misc types
COLOR,
@@ -128,6 +135,30 @@ public:
};
private:
+ struct Pools {
+ union BucketSmall {
+ BucketSmall() {}
+ ~BucketSmall() {}
+ Transform2D _transform2d;
+ ::AABB _aabb;
+ };
+ union BucketMedium {
+ BucketMedium() {}
+ ~BucketMedium() {}
+ Basis _basis;
+ Transform3D _transform3d;
+ };
+ union BucketLarge {
+ BucketLarge() {}
+ ~BucketLarge() {}
+ Projection _projection;
+ };
+
+ static PagedAllocator<BucketSmall, true> _bucket_small;
+ static PagedAllocator<BucketMedium, true> _bucket_medium;
+ static PagedAllocator<BucketLarge, true> _bucket_large;
+ };
+
friend struct _VariantCall;
friend class VariantInternal;
// Variant takes 20 bytes when real_t is float, and 36 if double
@@ -210,6 +241,7 @@ private:
::AABB *_aabb;
Basis *_basis;
Transform3D *_transform3d;
+ Projection *_projection;
PackedArrayRefBase *packed_array;
void *_ptr; //generic pointer
uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)]{ 0 };
@@ -234,11 +266,14 @@ private:
false, //VECTOR3,
false, //VECTOR3I,
true, //TRANSFORM2D,
+ false, //VECTOR4,
+ false, //VECTOR4I,
false, //PLANE,
false, //QUATERNION,
true, //AABB,
true, //BASIS,
true, //TRANSFORM,
+ true, //PROJECTION,
// misc types
false, //COLOR,
@@ -339,12 +374,15 @@ public:
operator Rect2i() const;
operator Vector3() const;
operator Vector3i() const;
+ operator Vector4() const;
+ operator Vector4i() const;
operator Plane() const;
operator ::AABB() const;
operator Quaternion() const;
operator Basis() const;
operator Transform2D() const;
operator Transform3D() const;
+ operator Projection() const;
operator Color() const;
operator NodePath() const;
@@ -409,12 +447,15 @@ public:
Variant(const Rect2i &p_rect2i);
Variant(const Vector3 &p_vector3);
Variant(const Vector3i &p_vector3i);
+ Variant(const Vector4 &p_vector4);
+ Variant(const Vector4i &p_vector4i);
Variant(const Plane &p_plane);
Variant(const ::AABB &p_aabb);
Variant(const Quaternion &p_quat);
Variant(const Basis &p_matrix);
Variant(const Transform2D &p_transform);
Variant(const Transform3D &p_transform);
+ Variant(const Projection &p_projection);
Variant(const Color &p_color);
Variant(const NodePath &p_node_path);
Variant(const ::RID &p_rid);
@@ -768,4 +809,14 @@ const Variant::ObjData &Variant::_get_obj() const {
String vformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant());
+template <typename... VarArgs>
+Callable Callable::bind(VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ return bindp(sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+}
+
#endif // VARIANT_H
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index a4bb7630d6..5c298f9b3b 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;
}
@@ -879,17 +895,17 @@ struct _VariantCall {
static void func_Callable_call(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v);
- callable->call(p_args, p_argcount, r_ret, r_error);
+ callable->callp(p_args, p_argcount, r_ret, r_error);
}
static void func_Callable_call_deferred(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v);
- callable->call_deferred(p_args, p_argcount);
+ callable->call_deferredp(p_args, p_argcount);
}
static void func_Callable_rpc(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v);
- callable->rpc(0, p_args, p_argcount, r_error);
+ callable->rpcp(0, p_args, p_argcount, r_error);
}
static void func_Callable_rpc_id(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
@@ -904,13 +920,13 @@ struct _VariantCall {
r_error.expected = Variant::INT;
} else {
Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v);
- callable->rpc(*p_args[0], &p_args[1], p_argcount - 1, r_error);
+ callable->rpcp(*p_args[0], &p_args[1], p_argcount - 1, r_error);
}
}
static void func_Callable_bind(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v);
- r_ret = callable->bind(p_args, p_argcount);
+ r_ret = callable->bindp(p_args, p_argcount);
}
static void func_Signal_emit(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
@@ -1709,14 +1725,49 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3i, abs, sarray(), varray());
bind_method(Vector3i, clamp, sarray("min", "max"), varray());
+ /* Vector4 */
+
+ bind_method(Vector4, min_axis_index, sarray(), varray());
+ bind_method(Vector4, max_axis_index, sarray(), varray());
+ bind_method(Vector4, length, sarray(), varray());
+ bind_method(Vector4, length_squared, sarray(), varray());
+ bind_method(Vector4, abs, sarray(), varray());
+ bind_method(Vector4, sign, sarray(), varray());
+ bind_method(Vector4, floor, sarray(), varray());
+ bind_method(Vector4, ceil, sarray(), varray());
+ bind_method(Vector4, round, sarray(), varray());
+ bind_method(Vector4, lerp, sarray("to", "weight"), varray());
+ bind_method(Vector4, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray());
+ bind_method(Vector4, posmod, sarray("mod"), varray());
+ bind_method(Vector4, posmodv, sarray("modv"), varray());
+ bind_method(Vector4, snapped, sarray("step"), varray());
+ bind_method(Vector4, clamp, sarray("min", "max"), varray());
+ bind_method(Vector4, normalized, sarray(), varray());
+ bind_method(Vector4, is_normalized, sarray(), varray());
+ bind_method(Vector4, direction_to, sarray("to"), varray());
+ bind_method(Vector4, distance_to, sarray("to"), varray());
+ bind_method(Vector4, dot, sarray("with"), varray());
+ bind_method(Vector4, inverse, sarray(), varray());
+ bind_method(Vector4, is_equal_approx, sarray("with"), varray());
+
+ /* Vector4i */
+
+ bind_method(Vector4i, min_axis_index, sarray(), varray());
+ bind_method(Vector4i, max_axis_index, sarray(), varray());
+ bind_method(Vector4i, length, sarray(), varray());
+ bind_method(Vector4i, length_squared, sarray(), varray());
+ bind_method(Vector4i, sign, sarray(), varray());
+ bind_method(Vector4i, abs, sarray(), varray());
+ bind_method(Vector4i, clamp, sarray("min", "max"), varray());
+
/* Plane */
bind_method(Plane, normalized, sarray(), varray());
bind_method(Plane, center, sarray(), varray());
bind_method(Plane, is_equal_approx, sarray("to_plane"), varray());
- bind_method(Plane, is_point_over, sarray("plane"), varray());
+ bind_method(Plane, is_point_over, sarray("point"), varray());
bind_method(Plane, distance_to, sarray("point"), varray());
- bind_method(Plane, has_point, sarray("point", "epsilon"), varray(CMP_EPSILON));
+ bind_method(Plane, has_point, sarray("point", "tolerance"), varray(CMP_EPSILON));
bind_method(Plane, project, sarray("point"), varray());
bind_methodv(Plane, intersect_3, &Plane::intersect_3_bind, sarray("b", "c"), varray());
bind_methodv(Plane, intersects_ray, &Plane::intersects_ray_bind, sarray("from", "dir"), varray());
@@ -1736,7 +1787,7 @@ static void _register_variant_builtin_methods() {
bind_method(Quaternion, dot, sarray("with"), varray());
bind_method(Quaternion, slerp, sarray("to", "weight"), varray());
bind_method(Quaternion, slerpni, sarray("to", "weight"), varray());
- bind_method(Quaternion, cubic_slerp, sarray("b", "pre_a", "post_b", "weight"), varray());
+ bind_method(Quaternion, spherical_cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray());
bind_method(Quaternion, get_euler, sarray(), varray());
bind_method(Quaternion, get_axis, sarray(), varray());
bind_method(Quaternion, get_angle, sarray(), varray());
@@ -1790,6 +1841,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());
@@ -1836,8 +1888,11 @@ static void _register_variant_builtin_methods() {
bind_method(Transform2D, get_skew, sarray(), varray());
bind_method(Transform2D, orthonormalized, sarray(), varray());
bind_method(Transform2D, rotated, sarray("angle"), varray());
+ bind_method(Transform2D, rotated_local, sarray("angle"), varray());
bind_method(Transform2D, scaled, sarray("scale"), varray());
+ bind_method(Transform2D, scaled_local, sarray("scale"), varray());
bind_method(Transform2D, translated, sarray("offset"), varray());
+ bind_method(Transform2D, translated_local, sarray("offset"), varray());
bind_method(Transform2D, basis_xform, sarray("v"), varray());
bind_method(Transform2D, basis_xform_inv, sarray("v"), varray());
bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray());
@@ -1901,13 +1956,50 @@ static void _register_variant_builtin_methods() {
bind_method(Transform3D, affine_inverse, sarray(), varray());
bind_method(Transform3D, orthonormalized, sarray(), varray());
bind_method(Transform3D, rotated, sarray("axis", "angle"), varray());
+ bind_method(Transform3D, rotated_local, sarray("axis", "angle"), varray());
bind_method(Transform3D, scaled, sarray("scale"), varray());
+ bind_method(Transform3D, scaled_local, sarray("scale"), varray());
bind_method(Transform3D, translated, sarray("offset"), varray());
+ bind_method(Transform3D, translated_local, sarray("offset"), varray());
bind_method(Transform3D, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0)));
- bind_method(Transform3D, sphere_interpolate_with, sarray("xform", "weight"), varray());
+ bind_method(Transform3D, spherical_interpolate_with, sarray("xform", "weight"), varray());
bind_method(Transform3D, interpolate_with, sarray("xform", "weight"), varray());
bind_method(Transform3D, is_equal_approx, sarray("xform"), varray());
+ /* Projection */
+
+ bind_static_method(Projection, create_depth_correction, sarray("flip_y"), varray());
+ bind_static_method(Projection, create_light_atlas_rect, sarray("rect"), varray());
+ bind_static_method(Projection, create_perspective, sarray("fovy", "aspect", "z_near", "z_far", "flip_fov"), varray(false));
+ bind_static_method(Projection, create_perspective_hmd, sarray("fovy", "aspect", "z_near", "z_far", "flip_fov", "eye", "intraocular_dist", " convergence_dist"), varray());
+ bind_static_method(Projection, create_for_hmd, sarray("eye", "aspect", "intraocular_dist", "display_width", "display_to_lens", "oversample", "z_near", "z_far"), varray());
+ bind_static_method(Projection, create_orthogonal, sarray("left", "right", "bottom", "top", "z_near", "z_far"), varray());
+ bind_static_method(Projection, create_orthogonal_aspect, sarray("size", "aspect", "z_near", "z_far", "flip_fov"), varray(false));
+ bind_static_method(Projection, create_frustum, sarray("left", "right", "bottom", "top", "z_near", "z_far"), varray());
+ bind_static_method(Projection, create_frustum_aspect, sarray("size", "aspect", "offset", "z_near", "z_far", "flip_fov"), varray(false));
+ bind_static_method(Projection, create_fit_aabb, sarray("aabb"), varray());
+
+ bind_method(Projection, determinant, sarray(), varray());
+ bind_method(Projection, perspective_znear_adjusted, sarray("new_znear"), varray());
+ bind_method(Projection, get_projection_plane, sarray("plane"), varray());
+ bind_method(Projection, flipped_y, sarray(), varray());
+ bind_method(Projection, jitter_offseted, sarray("offset"), varray());
+
+ bind_static_method(Projection, get_fovy, sarray("fovx", "aspect"), varray());
+
+ bind_method(Projection, get_z_far, sarray(), varray());
+ bind_method(Projection, get_z_near, sarray(), varray());
+ bind_method(Projection, get_aspect, sarray(), varray());
+ bind_method(Projection, get_fov, sarray(), varray());
+ bind_method(Projection, is_orthogonal, sarray(), varray());
+
+ bind_method(Projection, get_viewport_half_extents, sarray(), varray());
+ bind_method(Projection, get_far_plane_half_extents, sarray(), varray());
+
+ bind_method(Projection, inverse, sarray(), varray());
+ bind_method(Projection, get_pixels_per_meter, sarray("for_pixel_width"), varray());
+ bind_method(Projection, get_lod_multiplier, sarray(), varray());
+
/* Dictionary */
bind_method(Dictionary, size, sarray(), varray());
@@ -1974,7 +2066,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedByteArray, remove_at, sarray("index"), varray());
bind_method(PackedByteArray, insert, sarray("at_index", "value"), varray());
bind_method(PackedByteArray, fill, sarray("value"), varray());
- bind_method(PackedByteArray, resize, sarray("new_size"), varray());
+ bind_methodv(PackedByteArray, resize, &PackedByteArray::resize_zeroed, sarray("new_size"), varray());
bind_method(PackedByteArray, has, sarray("value"), varray());
bind_method(PackedByteArray, reverse, sarray(), varray());
bind_method(PackedByteArray, slice, sarray("begin", "end"), varray(INT_MAX));
@@ -2038,7 +2130,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt32Array, remove_at, sarray("index"), varray());
bind_method(PackedInt32Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedInt32Array, fill, sarray("value"), varray());
- bind_method(PackedInt32Array, resize, sarray("new_size"), varray());
+ bind_methodv(PackedInt32Array, resize, &PackedInt32Array::resize_zeroed, sarray("new_size"), varray());
bind_method(PackedInt32Array, has, sarray("value"), varray());
bind_method(PackedInt32Array, reverse, sarray(), varray());
bind_method(PackedInt32Array, slice, sarray("begin", "end"), varray(INT_MAX));
@@ -2061,7 +2153,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt64Array, remove_at, sarray("index"), varray());
bind_method(PackedInt64Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedInt64Array, fill, sarray("value"), varray());
- bind_method(PackedInt64Array, resize, sarray("new_size"), varray());
+ bind_methodv(PackedInt64Array, resize, &PackedInt64Array::resize_zeroed, sarray("new_size"), varray());
bind_method(PackedInt64Array, has, sarray("value"), varray());
bind_method(PackedInt64Array, reverse, sarray(), varray());
bind_method(PackedInt64Array, slice, sarray("begin", "end"), varray(INT_MAX));
@@ -2084,7 +2176,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat32Array, remove_at, sarray("index"), varray());
bind_method(PackedFloat32Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedFloat32Array, fill, sarray("value"), varray());
- bind_method(PackedFloat32Array, resize, sarray("new_size"), varray());
+ bind_methodv(PackedFloat32Array, resize, &PackedFloat32Array::resize_zeroed, sarray("new_size"), varray());
bind_method(PackedFloat32Array, has, sarray("value"), varray());
bind_method(PackedFloat32Array, reverse, sarray(), varray());
bind_method(PackedFloat32Array, slice, sarray("begin", "end"), varray(INT_MAX));
@@ -2107,7 +2199,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat64Array, remove_at, sarray("index"), varray());
bind_method(PackedFloat64Array, insert, sarray("at_index", "value"), varray());
bind_method(PackedFloat64Array, fill, sarray("value"), varray());
- bind_method(PackedFloat64Array, resize, sarray("new_size"), varray());
+ bind_methodv(PackedFloat64Array, resize, &PackedFloat64Array::resize_zeroed, sarray("new_size"), varray());
bind_method(PackedFloat64Array, has, sarray("value"), varray());
bind_method(PackedFloat64Array, reverse, sarray(), varray());
bind_method(PackedFloat64Array, slice, sarray("begin", "end"), varray(INT_MAX));
@@ -2236,6 +2328,19 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, -1));
_VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1));
+ _VariantCall::add_constant(Variant::VECTOR4, "AXIS_X", Vector4::AXIS_X);
+ _VariantCall::add_constant(Variant::VECTOR4, "AXIS_Y", Vector4::AXIS_Y);
+ _VariantCall::add_constant(Variant::VECTOR4, "AXIS_Z", Vector4::AXIS_Z);
+ _VariantCall::add_constant(Variant::VECTOR4, "AXIS_W", Vector4::AXIS_W);
+
+ _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_X", Vector4::AXIS_X);
+ _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_Y", Vector4::AXIS_Y);
+ _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_Z", Vector4::AXIS_Z);
+ _VariantCall::add_enum_constant(Variant::VECTOR4, "Axis", "AXIS_W", Vector4::AXIS_W);
+ _VariantCall::add_variant_constant(Variant::VECTOR4, "ZERO", Vector4(0, 0, 0, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR4, "ONE", Vector4(1, 1, 1, 1));
+ _VariantCall::add_variant_constant(Variant::VECTOR4, "INF", Vector4(INFINITY, INFINITY, INFINITY, INFINITY));
+
_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_X", Vector3i::AXIS_X);
_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Y", Vector3i::AXIS_Y);
_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Z", Vector3i::AXIS_Z);
@@ -2244,6 +2349,19 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_Y", Vector3i::AXIS_Y);
_VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_Z", Vector3i::AXIS_Z);
+ _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_X", Vector4i::AXIS_X);
+ _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_Y", Vector4i::AXIS_Y);
+ _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_Z", Vector4i::AXIS_Z);
+ _VariantCall::add_constant(Variant::VECTOR4I, "AXIS_W", Vector4i::AXIS_W);
+
+ _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_X", Vector4i::AXIS_X);
+ _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_Y", Vector4i::AXIS_Y);
+ _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_Z", Vector4i::AXIS_Z);
+ _VariantCall::add_enum_constant(Variant::VECTOR4I, "Axis", "AXIS_W", Vector4i::AXIS_W);
+
+ _VariantCall::add_variant_constant(Variant::VECTOR4I, "ZERO", Vector4i(0, 0, 0, 0));
+ _VariantCall::add_variant_constant(Variant::VECTOR4I, "ONE", Vector4i(1, 1, 1, 1));
+
_VariantCall::add_variant_constant(Variant::VECTOR3I, "ZERO", Vector3i(0, 0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR3I, "ONE", Vector3i(1, 1, 1));
_VariantCall::add_variant_constant(Variant::VECTOR3I, "LEFT", Vector3i(-1, 0, 0));
@@ -2321,6 +2439,25 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XY", Plane(Vector3(0, 0, 1), 0));
_VariantCall::add_variant_constant(Variant::QUATERNION, "IDENTITY", Quaternion(0, 0, 0, 1));
+
+ _VariantCall::add_constant(Variant::PROJECTION, "PLANE_NEAR", Projection::PLANE_NEAR);
+ _VariantCall::add_constant(Variant::PROJECTION, "PLANE_FAR", Projection::PLANE_FAR);
+ _VariantCall::add_constant(Variant::PROJECTION, "PLANE_LEFT", Projection::PLANE_LEFT);
+ _VariantCall::add_constant(Variant::PROJECTION, "PLANE_TOP", Projection::PLANE_TOP);
+ _VariantCall::add_constant(Variant::PROJECTION, "PLANE_RIGHT", Projection::PLANE_RIGHT);
+ _VariantCall::add_constant(Variant::PROJECTION, "PLANE_BOTTOM", Projection::PLANE_BOTTOM);
+
+ _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_NEAR", Projection::PLANE_NEAR);
+ _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_FAR", Projection::PLANE_FAR);
+ _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_LEFT", Projection::PLANE_LEFT);
+ _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_TOP", Projection::PLANE_TOP);
+ _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_RIGHT", Projection::PLANE_RIGHT);
+ _VariantCall::add_enum_constant(Variant::PROJECTION, "Planes", "PLANE_BOTTOM", Projection::PLANE_BOTTOM);
+
+ Projection p;
+ _VariantCall::add_variant_constant(Variant::PROJECTION, "IDENTITY", p);
+ p.set_zero();
+ _VariantCall::add_variant_constant(Variant::PROJECTION, "ZERO", p);
}
void Variant::_register_variant_methods() {
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index 78d5433d8c..3a0b6c1bb9 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -111,6 +111,16 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructor<Vector3i, Vector3>>(sarray("from"));
add_constructor<VariantConstructor<Vector3i, int64_t, int64_t, int64_t>>(sarray("x", "y", "z"));
+ add_constructor<VariantConstructNoArgs<Vector4>>(sarray());
+ add_constructor<VariantConstructor<Vector4, Vector4>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector4, Vector4i>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector4, double, double, double, double>>(sarray("x", "y", "z", "w"));
+
+ add_constructor<VariantConstructNoArgs<Vector4i>>(sarray());
+ add_constructor<VariantConstructor<Vector4i, Vector4i>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector4i, Vector4>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector4i, int64_t, int64_t, int64_t, int64_t>>(sarray("x", "y", "z", "w"));
+
add_constructor<VariantConstructNoArgs<Transform2D>>(sarray());
add_constructor<VariantConstructor<Transform2D, Transform2D>>(sarray("from"));
add_constructor<VariantConstructor<Transform2D, float, Vector2>>(sarray("rotation", "position"));
@@ -147,6 +157,11 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructor<Transform3D, Transform3D>>(sarray("from"));
add_constructor<VariantConstructor<Transform3D, Basis, Vector3>>(sarray("basis", "origin"));
add_constructor<VariantConstructor<Transform3D, Vector3, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis", "origin"));
+ add_constructor<VariantConstructor<Transform3D, Projection>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<Projection>>(sarray());
+ add_constructor<VariantConstructor<Projection, Projection>>(sarray("from"));
+ add_constructor<VariantConstructor<Projection, Transform3D>>(sarray("from"));
add_constructor<VariantConstructNoArgs<Color>>(sarray());
add_constructor<VariantConstructor<Color, Color>>(sarray("from"));
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index 638c0136f3..58a0f34c1e 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -63,12 +63,15 @@ MAKE_PTRCONSTRUCT(Rect2);
MAKE_PTRCONSTRUCT(Rect2i);
MAKE_PTRCONSTRUCT(Vector3);
MAKE_PTRCONSTRUCT(Vector3i);
+MAKE_PTRCONSTRUCT(Vector4);
+MAKE_PTRCONSTRUCT(Vector4i);
MAKE_PTRCONSTRUCT(Transform2D);
MAKE_PTRCONSTRUCT(Plane);
MAKE_PTRCONSTRUCT(Quaternion);
MAKE_PTRCONSTRUCT(AABB);
MAKE_PTRCONSTRUCT(Basis);
MAKE_PTRCONSTRUCT(Transform3D);
+MAKE_PTRCONSTRUCT(Projection);
MAKE_PTRCONSTRUCT(Color);
MAKE_PTRCONSTRUCT(StringName);
MAKE_PTRCONSTRUCT(NodePath);
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index e0cfb42e1e..874a183d29 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -36,6 +36,8 @@
// For use when you want to access the internal pointer of a Variant directly.
// Use with caution. You need to be sure that the type is correct.
class VariantInternal {
+ friend class Variant;
+
public:
// Set type.
_FORCE_INLINE_ static void initialize(Variant *v, Variant::Type p_type) {
@@ -138,6 +140,10 @@ public:
_FORCE_INLINE_ static const Vector3 *get_vector3(const Variant *v) { return reinterpret_cast<const Vector3 *>(v->_data._mem); }
_FORCE_INLINE_ static Vector3i *get_vector3i(Variant *v) { return reinterpret_cast<Vector3i *>(v->_data._mem); }
_FORCE_INLINE_ static const Vector3i *get_vector3i(const Variant *v) { return reinterpret_cast<const Vector3i *>(v->_data._mem); }
+ _FORCE_INLINE_ static Vector4 *get_vector4(Variant *v) { return reinterpret_cast<Vector4 *>(v->_data._mem); }
+ _FORCE_INLINE_ static const Vector4 *get_vector4(const Variant *v) { return reinterpret_cast<const Vector4 *>(v->_data._mem); }
+ _FORCE_INLINE_ static Vector4i *get_vector4i(Variant *v) { return reinterpret_cast<Vector4i *>(v->_data._mem); }
+ _FORCE_INLINE_ static const Vector4i *get_vector4i(const Variant *v) { return reinterpret_cast<const Vector4i *>(v->_data._mem); }
_FORCE_INLINE_ static Transform2D *get_transform2d(Variant *v) { return v->_data._transform2d; }
_FORCE_INLINE_ static const Transform2D *get_transform2d(const Variant *v) { return v->_data._transform2d; }
_FORCE_INLINE_ static Plane *get_plane(Variant *v) { return reinterpret_cast<Plane *>(v->_data._mem); }
@@ -150,6 +156,8 @@ public:
_FORCE_INLINE_ static const Basis *get_basis(const Variant *v) { return v->_data._basis; }
_FORCE_INLINE_ static Transform3D *get_transform(Variant *v) { return v->_data._transform3d; }
_FORCE_INLINE_ static const Transform3D *get_transform(const Variant *v) { return v->_data._transform3d; }
+ _FORCE_INLINE_ static Projection *get_projection(Variant *v) { return v->_data._projection; }
+ _FORCE_INLINE_ static const Projection *get_projection(const Variant *v) { return v->_data._projection; }
// Misc types.
_FORCE_INLINE_ static Color *get_color(Variant *v) { return reinterpret_cast<Color *>(v->_data._mem); }
@@ -209,21 +217,30 @@ public:
}
_FORCE_INLINE_ static void init_transform2d(Variant *v) {
- v->_data._transform2d = memnew(Transform2D);
+ v->_data._transform2d = (Transform2D *)Variant::Pools::_bucket_small.alloc();
+ memnew_placement(v->_data._transform2d, Transform2D);
v->type = Variant::TRANSFORM2D;
}
_FORCE_INLINE_ static void init_aabb(Variant *v) {
- v->_data._aabb = memnew(AABB);
+ v->_data._aabb = (AABB *)Variant::Pools::_bucket_small.alloc();
+ memnew_placement(v->_data._aabb, AABB);
v->type = Variant::AABB;
}
_FORCE_INLINE_ static void init_basis(Variant *v) {
- v->_data._basis = memnew(Basis);
+ v->_data._basis = (Basis *)Variant::Pools::_bucket_medium.alloc();
+ memnew_placement(v->_data._basis, Basis);
v->type = Variant::BASIS;
}
_FORCE_INLINE_ static void init_transform(Variant *v) {
- v->_data._transform3d = memnew(Transform3D);
+ v->_data._transform3d = (Transform3D *)Variant::Pools::_bucket_medium.alloc();
+ memnew_placement(v->_data._transform3d, Transform3D);
v->type = Variant::TRANSFORM3D;
}
+ _FORCE_INLINE_ static void init_projection(Variant *v) {
+ v->_data._projection = (Projection *)Variant::Pools::_bucket_large.alloc();
+ memnew_placement(v->_data._projection, Projection);
+ v->type = Variant::PROJECTION;
+ }
_FORCE_INLINE_ static void init_string_name(Variant *v) {
memnew_placement(v->_data._mem, StringName);
v->type = Variant::STRING_NAME;
@@ -331,12 +348,18 @@ public:
return get_vector3(v);
case Variant::VECTOR3I:
return get_vector3i(v);
+ case Variant::VECTOR4:
+ return get_vector4(v);
+ case Variant::VECTOR4I:
+ return get_vector4i(v);
case Variant::RECT2:
return get_rect2(v);
case Variant::RECT2I:
return get_rect2i(v);
case Variant::TRANSFORM3D:
return get_transform(v);
+ case Variant::PROJECTION:
+ return get_projection(v);
case Variant::TRANSFORM2D:
return get_transform2d(v);
case Variant::QUATERNION:
@@ -409,12 +432,18 @@ public:
return get_vector3(v);
case Variant::VECTOR3I:
return get_vector3i(v);
+ case Variant::VECTOR4:
+ return get_vector4(v);
+ case Variant::VECTOR4I:
+ return get_vector4i(v);
case Variant::RECT2:
return get_rect2(v);
case Variant::RECT2I:
return get_rect2i(v);
case Variant::TRANSFORM3D:
return get_transform(v);
+ case Variant::PROJECTION:
+ return get_projection(v);
case Variant::TRANSFORM2D:
return get_transform2d(v);
case Variant::QUATERNION:
@@ -599,6 +628,17 @@ struct VariantGetInternalPtr<Vector3i> {
};
template <>
+struct VariantGetInternalPtr<Vector4> {
+ static Vector4 *get_ptr(Variant *v) { return VariantInternal::get_vector4(v); }
+ static const Vector4 *get_ptr(const Variant *v) { return VariantInternal::get_vector4(v); }
+};
+
+template <>
+struct VariantGetInternalPtr<Vector4i> {
+ static Vector4i *get_ptr(Variant *v) { return VariantInternal::get_vector4i(v); }
+ static const Vector4i *get_ptr(const Variant *v) { return VariantInternal::get_vector4i(v); }
+};
+template <>
struct VariantGetInternalPtr<Transform2D> {
static Transform2D *get_ptr(Variant *v) { return VariantInternal::get_transform2d(v); }
static const Transform2D *get_ptr(const Variant *v) { return VariantInternal::get_transform2d(v); }
@@ -611,6 +651,12 @@ struct VariantGetInternalPtr<Transform3D> {
};
template <>
+struct VariantGetInternalPtr<Projection> {
+ static Projection *get_ptr(Variant *v) { return VariantInternal::get_projection(v); }
+ static const Projection *get_ptr(const Variant *v) { return VariantInternal::get_projection(v); }
+};
+
+template <>
struct VariantGetInternalPtr<Plane> {
static Plane *get_ptr(Variant *v) { return VariantInternal::get_plane(v); }
static const Plane *get_ptr(const Variant *v) { return VariantInternal::get_plane(v); }
@@ -772,6 +818,10 @@ VARIANT_ACCESSOR_NUMBER(Vector2::Axis)
VARIANT_ACCESSOR_NUMBER(Vector2i::Axis)
VARIANT_ACCESSOR_NUMBER(Vector3::Axis)
VARIANT_ACCESSOR_NUMBER(Vector3i::Axis)
+VARIANT_ACCESSOR_NUMBER(Vector4::Axis)
+VARIANT_ACCESSOR_NUMBER(Vector4i::Axis)
+
+VARIANT_ACCESSOR_NUMBER(Projection::Planes)
template <>
struct VariantInternalAccessor<Basis::EulerOrder> {
@@ -840,6 +890,17 @@ struct VariantInternalAccessor<Vector3i> {
};
template <>
+struct VariantInternalAccessor<Vector4> {
+ static _FORCE_INLINE_ const Vector4 &get(const Variant *v) { return *VariantInternal::get_vector4(v); }
+ static _FORCE_INLINE_ void set(Variant *v, const Vector4 &p_value) { *VariantInternal::get_vector4(v) = p_value; }
+};
+
+template <>
+struct VariantInternalAccessor<Vector4i> {
+ static _FORCE_INLINE_ const Vector4i &get(const Variant *v) { return *VariantInternal::get_vector4i(v); }
+ static _FORCE_INLINE_ void set(Variant *v, const Vector4i &p_value) { *VariantInternal::get_vector4i(v) = p_value; }
+};
+template <>
struct VariantInternalAccessor<Transform2D> {
static _FORCE_INLINE_ const Transform2D &get(const Variant *v) { return *VariantInternal::get_transform2d(v); }
static _FORCE_INLINE_ void set(Variant *v, const Transform2D &p_value) { *VariantInternal::get_transform2d(v) = p_value; }
@@ -852,6 +913,12 @@ struct VariantInternalAccessor<Transform3D> {
};
template <>
+struct VariantInternalAccessor<Projection> {
+ static _FORCE_INLINE_ const Projection &get(const Variant *v) { return *VariantInternal::get_projection(v); }
+ static _FORCE_INLINE_ void set(Variant *v, const Projection &p_value) { *VariantInternal::get_projection(v) = p_value; }
+};
+
+template <>
struct VariantInternalAccessor<Plane> {
static _FORCE_INLINE_ const Plane &get(const Variant *v) { return *VariantInternal::get_plane(v); }
static _FORCE_INLINE_ void set(Variant *v, const Plane &p_value) { *VariantInternal::get_plane(v) = p_value; }
@@ -1041,6 +1108,8 @@ INITIALIZER_INT(Vector2::Axis)
INITIALIZER_INT(Vector2i::Axis)
INITIALIZER_INT(Vector3::Axis)
INITIALIZER_INT(Vector3i::Axis)
+INITIALIZER_INT(Vector4::Axis)
+INITIALIZER_INT(Vector4i::Axis)
template <>
struct VariantInitializer<double> {
@@ -1086,8 +1155,16 @@ template <>
struct VariantInitializer<Vector3i> {
static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector3i>(v); }
};
+template <>
+struct VariantInitializer<Vector4> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector4>(v); }
+};
template <>
+struct VariantInitializer<Vector4i> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector4i>(v); }
+};
+template <>
struct VariantInitializer<Transform2D> {
static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform2d(v); }
};
@@ -1116,6 +1193,10 @@ template <>
struct VariantInitializer<Transform3D> {
static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform(v); }
};
+template <>
+struct VariantInitializer<Projection> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_projection(v); }
+};
template <>
struct VariantInitializer<Color> {
@@ -1267,6 +1348,16 @@ struct VariantZeroAssigner<Vector3i> {
};
template <>
+struct VariantZeroAssigner<Vector4> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector4(v) = Vector4(); }
+};
+
+template <>
+struct VariantZeroAssigner<Vector4i> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector4i(v) = Vector4i(); }
+};
+
+template <>
struct VariantZeroAssigner<Transform2D> {
static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_transform2d(v) = Transform2D(); }
};
@@ -1297,6 +1388,11 @@ struct VariantZeroAssigner<Transform3D> {
};
template <>
+struct VariantZeroAssigner<Projection> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_projection(v) = Projection(); }
+};
+
+template <>
struct VariantZeroAssigner<Color> {
static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_color(v) = Color(); }
};
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index adace2b534..6cca7955ae 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -165,6 +165,70 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<Vector3>::VARIANT_TYPE; }
};
+//
+
+template <>
+class OperatorEvaluatorMul<Vector4, Vector4i, double> {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_left);
+ const double &b = *VariantGetInternalPtr<double>::get_ptr(&p_right);
+ *r_ret = Vector4(a.x, a.y, a.z, a.w) * b;
+ r_valid = true;
+ }
+ static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ *VariantGetInternalPtr<Vector4>::get_ptr(r_ret) = Vector4(VariantGetInternalPtr<Vector4i>::get_ptr(left)->x, VariantGetInternalPtr<Vector4i>::get_ptr(left)->y, VariantGetInternalPtr<Vector4i>::get_ptr(left)->z, VariantGetInternalPtr<Vector4i>::get_ptr(left)->w) * *VariantGetInternalPtr<double>::get_ptr(right);
+ }
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ PtrToArg<Vector4>::encode(Vector4(PtrToArg<Vector4i>::convert(left).x, PtrToArg<Vector4i>::convert(left).y, PtrToArg<Vector4i>::convert(left).z, PtrToArg<Vector4i>::convert(left).w) * PtrToArg<double>::convert(right), r_ret);
+ }
+ static Variant::Type get_return_type() { return GetTypeInfo<Vector4>::VARIANT_TYPE; }
+};
+
+template <>
+class OperatorEvaluatorMul<Vector4, double, Vector4i> {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_right);
+ const double &b = *VariantGetInternalPtr<double>::get_ptr(&p_left);
+ *r_ret = Vector4(a.x, a.y, a.z, a.w) * b;
+ r_valid = true;
+ }
+ static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ *VariantGetInternalPtr<Vector4>::get_ptr(r_ret) = Vector4(VariantGetInternalPtr<Vector4i>::get_ptr(right)->x, VariantGetInternalPtr<Vector4i>::get_ptr(right)->y, VariantGetInternalPtr<Vector4i>::get_ptr(right)->z, VariantGetInternalPtr<Vector4i>::get_ptr(right)->w) * *VariantGetInternalPtr<double>::get_ptr(left);
+ }
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ PtrToArg<Vector4>::encode(Vector4(PtrToArg<Vector4i>::convert(right).x, PtrToArg<Vector4i>::convert(right).y, PtrToArg<Vector4i>::convert(right).z, PtrToArg<Vector4i>::convert(right).w) * PtrToArg<double>::convert(left), r_ret);
+ }
+ static Variant::Type get_return_type() { return GetTypeInfo<Vector4>::VARIANT_TYPE; }
+};
+
+template <>
+class OperatorEvaluatorDivNZ<Vector4, Vector4i, double> {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_left);
+ const double &b = *VariantGetInternalPtr<double>::get_ptr(&p_right);
+ if (unlikely(b == 0)) {
+ r_valid = false;
+ *r_ret = "Division by zero error";
+ return;
+ }
+ *r_ret = Vector4(a.x, a.y, a.z, a.w) / b;
+ r_valid = true;
+ }
+
+ static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ *VariantGetInternalPtr<Vector4>::get_ptr(r_ret) = Vector4(VariantGetInternalPtr<Vector4i>::get_ptr(left)->x, VariantGetInternalPtr<Vector4i>::get_ptr(left)->y, VariantGetInternalPtr<Vector4i>::get_ptr(left)->z, VariantGetInternalPtr<Vector4i>::get_ptr(left)->w) / *VariantGetInternalPtr<double>::get_ptr(right);
+ }
+
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ PtrToArg<Vector4>::encode(Vector4(PtrToArg<Vector4i>::convert(left).x, PtrToArg<Vector4i>::convert(left).y, PtrToArg<Vector4i>::convert(left).z, PtrToArg<Vector4i>::convert(left).w) / PtrToArg<double>::convert(right), r_ret);
+ }
+
+ static Variant::Type get_return_type() { return GetTypeInfo<Vector4>::VARIANT_TYPE; }
+};
+
void Variant::_register_variant_operators() {
memset(operator_return_type_table, 0, sizeof(operator_return_type_table));
memset(operator_evaluator_table, 0, sizeof(operator_evaluator_table));
@@ -182,6 +246,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorAdd<Vector2i, Vector2i, Vector2i>>(Variant::OP_ADD, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorAdd<Vector3, Vector3, Vector3>>(Variant::OP_ADD, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorAdd<Vector3i, Vector3i, Vector3i>>(Variant::OP_ADD, Variant::VECTOR3I, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorAdd<Vector4, Vector4, Vector4>>(Variant::OP_ADD, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorAdd<Vector4i, Vector4i, Vector4i>>(Variant::OP_ADD, Variant::VECTOR4I, Variant::VECTOR4I);
register_op<OperatorEvaluatorAdd<Quaternion, Quaternion, Quaternion>>(Variant::OP_ADD, Variant::QUATERNION, Variant::QUATERNION);
register_op<OperatorEvaluatorAdd<Color, Color, Color>>(Variant::OP_ADD, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorAddArray>(Variant::OP_ADD, Variant::ARRAY, Variant::ARRAY);
@@ -203,6 +269,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorSub<Vector2i, Vector2i, Vector2i>>(Variant::OP_SUBTRACT, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorSub<Vector3, Vector3, Vector3>>(Variant::OP_SUBTRACT, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorSub<Vector3i, Vector3i, Vector3i>>(Variant::OP_SUBTRACT, Variant::VECTOR3I, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorSub<Vector4, Vector4, Vector4>>(Variant::OP_SUBTRACT, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorSub<Vector4i, Vector4i, Vector4i>>(Variant::OP_SUBTRACT, Variant::VECTOR4I, Variant::VECTOR4I);
register_op<OperatorEvaluatorSub<Quaternion, Quaternion, Quaternion>>(Variant::OP_SUBTRACT, Variant::QUATERNION, Variant::QUATERNION);
register_op<OperatorEvaluatorSub<Color, Color, Color>>(Variant::OP_SUBTRACT, Variant::COLOR, Variant::COLOR);
@@ -212,6 +280,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorMul<Vector2i, int64_t, Vector2i>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR2I);
register_op<OperatorEvaluatorMul<Vector3, int64_t, Vector3>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR3);
register_op<OperatorEvaluatorMul<Vector3i, int64_t, Vector3i>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorMul<Vector4, int64_t, Vector4>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR4);
+ register_op<OperatorEvaluatorMul<Vector4i, int64_t, Vector4i>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR4I);
register_op<OperatorEvaluatorMul<double, double, double>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::FLOAT);
register_op<OperatorEvaluatorMul<double, double, int64_t>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::INT);
@@ -219,6 +289,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorMul<Vector2, double, Vector2i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2I);
register_op<OperatorEvaluatorMul<Vector3, double, Vector3>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3);
register_op<OperatorEvaluatorMul<Vector3, double, Vector3i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorMul<Vector4, double, Vector4>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR4);
+ register_op<OperatorEvaluatorMul<Vector4, double, Vector4i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR4I);
register_op<OperatorEvaluatorMul<Vector2, Vector2, Vector2>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::VECTOR2);
register_op<OperatorEvaluatorMul<Vector2, Vector2, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::INT);
@@ -236,6 +308,14 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorMul<Vector3i, Vector3i, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::INT);
register_op<OperatorEvaluatorMul<Vector3, Vector3i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::FLOAT);
+ register_op<OperatorEvaluatorMul<Vector4, Vector4, Vector4>>(Variant::OP_MULTIPLY, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorMul<Vector4, Vector4, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR4, Variant::INT);
+ register_op<OperatorEvaluatorMul<Vector4, Vector4, double>>(Variant::OP_MULTIPLY, Variant::VECTOR4, Variant::FLOAT);
+
+ register_op<OperatorEvaluatorMul<Vector4i, Vector4i, Vector4i>>(Variant::OP_MULTIPLY, Variant::VECTOR4I, Variant::VECTOR4I);
+ register_op<OperatorEvaluatorMul<Vector4i, Vector4i, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR4I, Variant::INT);
+ register_op<OperatorEvaluatorMul<Vector4, Vector4i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR4I, Variant::FLOAT);
+
register_op<OperatorEvaluatorMul<Quaternion, Quaternion, Quaternion>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::QUATERNION);
register_op<OperatorEvaluatorMul<Quaternion, Quaternion, int64_t>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::INT);
register_op<OperatorEvaluatorMul<Quaternion, Quaternion, double>>(Variant::OP_MULTIPLY, Variant::QUATERNION, Variant::FLOAT);
@@ -261,9 +341,16 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Transform3D>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::TRANSFORM3D);
register_op<OperatorEvaluatorXForm<::AABB, Transform3D, ::AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::AABB);
register_op<OperatorEvaluatorXFormInv<::AABB, ::AABB, Transform3D>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorXForm<Plane, Transform3D, Plane>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::PLANE);
+ register_op<OperatorEvaluatorXFormInv<Plane, Plane, Transform3D>>(Variant::OP_MULTIPLY, Variant::PLANE, Variant::TRANSFORM3D);
register_op<OperatorEvaluatorXForm<Vector<Vector3>, Transform3D, Vector<Vector3>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::PACKED_VECTOR3_ARRAY);
register_op<OperatorEvaluatorXFormInv<Vector<Vector3>, Vector<Vector3>, Transform3D>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR3_ARRAY, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorXForm<Vector4, Projection, Vector4>>(Variant::OP_MULTIPLY, Variant::PROJECTION, Variant::VECTOR4);
+ register_op<OperatorEvaluatorXFormInv<Vector4, Vector4, Projection>>(Variant::OP_MULTIPLY, Variant::VECTOR4, Variant::PROJECTION);
+
+ register_op<OperatorEvaluatorMul<Projection, Projection, Projection>>(Variant::OP_MULTIPLY, Variant::PROJECTION, Variant::PROJECTION);
+
register_op<OperatorEvaluatorMul<Basis, Basis, Basis>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::BASIS);
register_op<OperatorEvaluatorMul<Basis, Basis, int64_t>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::INT);
register_op<OperatorEvaluatorMul<Basis, Basis, double>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::FLOAT);
@@ -309,6 +396,14 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorDivNZ<Vector3, Vector3i, double>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::FLOAT);
register_op<OperatorEvaluatorDivNZ<Vector3i, Vector3i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::INT);
+ register_op<OperatorEvaluatorDiv<Vector4, Vector4, Vector4>>(Variant::OP_DIVIDE, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorDiv<Vector4, Vector4, double>>(Variant::OP_DIVIDE, Variant::VECTOR4, Variant::FLOAT);
+ register_op<OperatorEvaluatorDiv<Vector4, Vector4, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR4, Variant::INT);
+
+ register_op<OperatorEvaluatorDivNZ<Vector4i, Vector4i, Vector4i>>(Variant::OP_DIVIDE, Variant::VECTOR4I, Variant::VECTOR4I);
+ register_op<OperatorEvaluatorDivNZ<Vector4, Vector4i, double>>(Variant::OP_DIVIDE, Variant::VECTOR4I, Variant::FLOAT);
+ register_op<OperatorEvaluatorDivNZ<Vector4i, Vector4i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR4I, Variant::INT);
+
register_op<OperatorEvaluatorDiv<Quaternion, Quaternion, double>>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::FLOAT);
register_op<OperatorEvaluatorDiv<Quaternion, Quaternion, int64_t>>(Variant::OP_DIVIDE, Variant::QUATERNION, Variant::INT);
@@ -323,6 +418,9 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorModNZ<Vector3i, Vector3i, Vector3i>>(Variant::OP_MODULE, Variant::VECTOR3I, Variant::VECTOR3I);
register_op<OperatorEvaluatorModNZ<Vector3i, Vector3i, int64_t>>(Variant::OP_MODULE, Variant::VECTOR3I, Variant::INT);
+ register_op<OperatorEvaluatorModNZ<Vector4i, Vector4i, Vector4i>>(Variant::OP_MODULE, Variant::VECTOR4I, Variant::VECTOR4I);
+ register_op<OperatorEvaluatorModNZ<Vector4i, Vector4i, int64_t>>(Variant::OP_MODULE, Variant::VECTOR4I, Variant::INT);
+
register_op<OperatorEvaluatorStringModNil>(Variant::OP_MODULE, Variant::STRING, Variant::NIL);
register_op<OperatorEvaluatorStringModT<bool>>(Variant::OP_MODULE, Variant::STRING, Variant::BOOL);
@@ -335,12 +433,15 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorStringModT<Rect2i>>(Variant::OP_MODULE, Variant::STRING, Variant::RECT2I);
register_op<OperatorEvaluatorStringModT<Vector3>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR3);
register_op<OperatorEvaluatorStringModT<Vector3i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorStringModT<Vector4>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR4);
+ register_op<OperatorEvaluatorStringModT<Vector4i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR4I);
register_op<OperatorEvaluatorStringModT<Transform2D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorStringModT<Plane>>(Variant::OP_MODULE, Variant::STRING, Variant::PLANE);
register_op<OperatorEvaluatorStringModT<Quaternion>>(Variant::OP_MODULE, Variant::STRING, Variant::QUATERNION);
register_op<OperatorEvaluatorStringModT<::AABB>>(Variant::OP_MODULE, Variant::STRING, Variant::AABB);
register_op<OperatorEvaluatorStringModT<Basis>>(Variant::OP_MODULE, Variant::STRING, Variant::BASIS);
register_op<OperatorEvaluatorStringModT<Transform3D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorStringModT<Projection>>(Variant::OP_MODULE, Variant::STRING, Variant::PROJECTION);
register_op<OperatorEvaluatorStringModT<Color>>(Variant::OP_MODULE, Variant::STRING, Variant::COLOR);
register_op<OperatorEvaluatorStringModT<StringName>>(Variant::OP_MODULE, Variant::STRING, Variant::STRING_NAME);
@@ -372,6 +473,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorNeg<Vector2i, Vector2i>>(Variant::OP_NEGATE, Variant::VECTOR2I, Variant::NIL);
register_op<OperatorEvaluatorNeg<Vector3, Vector3>>(Variant::OP_NEGATE, Variant::VECTOR3, Variant::NIL);
register_op<OperatorEvaluatorNeg<Vector3i, Vector3i>>(Variant::OP_NEGATE, Variant::VECTOR3I, Variant::NIL);
+ register_op<OperatorEvaluatorNeg<Vector4, Vector4>>(Variant::OP_NEGATE, Variant::VECTOR4, Variant::NIL);
+ register_op<OperatorEvaluatorNeg<Vector4i, Vector4i>>(Variant::OP_NEGATE, Variant::VECTOR4I, Variant::NIL);
register_op<OperatorEvaluatorNeg<Quaternion, Quaternion>>(Variant::OP_NEGATE, Variant::QUATERNION, Variant::NIL);
register_op<OperatorEvaluatorNeg<Plane, Plane>>(Variant::OP_NEGATE, Variant::PLANE, Variant::NIL);
register_op<OperatorEvaluatorNeg<Color, Color>>(Variant::OP_NEGATE, Variant::COLOR, Variant::NIL);
@@ -382,6 +485,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorPos<Vector2i, Vector2i>>(Variant::OP_POSITIVE, Variant::VECTOR2I, Variant::NIL);
register_op<OperatorEvaluatorPos<Vector3, Vector3>>(Variant::OP_POSITIVE, Variant::VECTOR3, Variant::NIL);
register_op<OperatorEvaluatorPos<Vector3i, Vector3i>>(Variant::OP_POSITIVE, Variant::VECTOR3I, Variant::NIL);
+ register_op<OperatorEvaluatorPos<Vector4, Vector4>>(Variant::OP_POSITIVE, Variant::VECTOR4, Variant::NIL);
+ register_op<OperatorEvaluatorPos<Vector4i, Vector4i>>(Variant::OP_POSITIVE, Variant::VECTOR4I, Variant::NIL);
register_op<OperatorEvaluatorPos<Quaternion, Quaternion>>(Variant::OP_POSITIVE, Variant::QUATERNION, Variant::NIL);
register_op<OperatorEvaluatorPos<Plane, Plane>>(Variant::OP_POSITIVE, Variant::PLANE, Variant::NIL);
register_op<OperatorEvaluatorPos<Color, Color>>(Variant::OP_POSITIVE, Variant::COLOR, Variant::NIL);
@@ -409,11 +514,14 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorEqual<Vector3, Vector3>>(Variant::OP_EQUAL, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorEqual<Vector3i, Vector3i>>(Variant::OP_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I);
register_op<OperatorEvaluatorEqual<Transform2D, Transform2D>>(Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D);
+ register_op<OperatorEvaluatorEqual<Vector4, Vector4>>(Variant::OP_EQUAL, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorEqual<Vector4i, Vector4i>>(Variant::OP_EQUAL, Variant::VECTOR4I, Variant::VECTOR4I);
register_op<OperatorEvaluatorEqual<Plane, Plane>>(Variant::OP_EQUAL, Variant::PLANE, Variant::PLANE);
register_op<OperatorEvaluatorEqual<Quaternion, Quaternion>>(Variant::OP_EQUAL, Variant::QUATERNION, Variant::QUATERNION);
register_op<OperatorEvaluatorEqual<::AABB, ::AABB>>(Variant::OP_EQUAL, Variant::AABB, Variant::AABB);
register_op<OperatorEvaluatorEqual<Basis, Basis>>(Variant::OP_EQUAL, Variant::BASIS, Variant::BASIS);
register_op<OperatorEvaluatorEqual<Transform3D, Transform3D>>(Variant::OP_EQUAL, Variant::TRANSFORM3D, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorEqual<Projection, Projection>>(Variant::OP_EQUAL, Variant::PROJECTION, Variant::PROJECTION);
register_op<OperatorEvaluatorEqual<Color, Color>>(Variant::OP_EQUAL, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorEqual<StringName, String>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::STRING);
@@ -451,6 +559,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::RECT2I, Variant::NIL>>(Variant::OP_EQUAL, Variant::RECT2I, Variant::NIL);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR3, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR3, Variant::NIL);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR3I, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR3I, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR4, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR4, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::VECTOR4I, Variant::NIL>>(Variant::OP_EQUAL, Variant::VECTOR4I, Variant::NIL);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::NIL>>(Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::NIL);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PLANE, Variant::NIL>>(Variant::OP_EQUAL, Variant::PLANE, Variant::NIL);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::QUATERNION, Variant::NIL>>(Variant::OP_EQUAL, Variant::QUATERNION, Variant::NIL);
@@ -485,6 +595,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::RECT2I>>(Variant::OP_EQUAL, Variant::NIL, Variant::RECT2I);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3I>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR4>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR4);
+ register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR4I>>(Variant::OP_EQUAL, Variant::NIL, Variant::VECTOR4I);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::TRANSFORM2D>>(Variant::OP_EQUAL, Variant::NIL, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PLANE>>(Variant::OP_EQUAL, Variant::NIL, Variant::PLANE);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::QUATERNION>>(Variant::OP_EQUAL, Variant::NIL, Variant::QUATERNION);
@@ -522,12 +634,15 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorNotEqual<Rect2i, Rect2i>>(Variant::OP_NOT_EQUAL, Variant::RECT2I, Variant::RECT2I);
register_op<OperatorEvaluatorNotEqual<Vector3, Vector3>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorNotEqual<Vector3i, Vector3i>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorNotEqual<Vector4, Vector4>>(Variant::OP_NOT_EQUAL, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorNotEqual<Vector4i, Vector4i>>(Variant::OP_NOT_EQUAL, Variant::VECTOR4I, Variant::VECTOR4I);
register_op<OperatorEvaluatorNotEqual<Transform2D, Transform2D>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorNotEqual<Plane, Plane>>(Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::PLANE);
register_op<OperatorEvaluatorNotEqual<Quaternion, Quaternion>>(Variant::OP_NOT_EQUAL, Variant::QUATERNION, Variant::QUATERNION);
register_op<OperatorEvaluatorNotEqual<::AABB, ::AABB>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::AABB);
register_op<OperatorEvaluatorNotEqual<Basis, Basis>>(Variant::OP_NOT_EQUAL, Variant::BASIS, Variant::BASIS);
register_op<OperatorEvaluatorNotEqual<Transform3D, Transform3D>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM3D, Variant::TRANSFORM3D);
+ register_op<OperatorEvaluatorNotEqual<Projection, Projection>>(Variant::OP_NOT_EQUAL, Variant::PROJECTION, Variant::PROJECTION);
register_op<OperatorEvaluatorNotEqual<Color, Color>>(Variant::OP_NOT_EQUAL, Variant::COLOR, Variant::COLOR);
register_op<OperatorEvaluatorNotEqual<StringName, String>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::STRING);
@@ -566,6 +681,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR3, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3, Variant::NIL);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::NIL);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR4, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR4, Variant::NIL);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::VECTOR4I, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::VECTOR4I, Variant::NIL);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::NIL);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::QUATERNION, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::QUATERNION, Variant::NIL);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::AABB, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::NIL);
@@ -599,6 +716,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RECT2I>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::RECT2I);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3I>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR4>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR4);
+ register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR4I>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::VECTOR4I);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::TRANSFORM2D>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PLANE>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PLANE);
register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::QUATERNION>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::QUATERNION);
@@ -634,6 +753,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorLess<Vector2i, Vector2i>>(Variant::OP_LESS, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorLess<Vector3, Vector3>>(Variant::OP_LESS, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorLess<Vector3i, Vector3i>>(Variant::OP_LESS, Variant::VECTOR3I, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorLess<Vector4, Vector4>>(Variant::OP_LESS, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorLess<Vector4i, Vector4i>>(Variant::OP_LESS, Variant::VECTOR4I, Variant::VECTOR4I);
register_op<OperatorEvaluatorLess<::RID, ::RID>>(Variant::OP_LESS, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorLess<Array, Array>>(Variant::OP_LESS, Variant::ARRAY, Variant::ARRAY);
@@ -647,6 +768,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorLessEqual<Vector2i, Vector2i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorLessEqual<Vector3, Vector3>>(Variant::OP_LESS_EQUAL, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorLessEqual<Vector3i, Vector3i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorLessEqual<Vector4, Vector4>>(Variant::OP_LESS_EQUAL, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorLessEqual<Vector4i, Vector4i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR4I, Variant::VECTOR4I);
register_op<OperatorEvaluatorLessEqual<::RID, ::RID>>(Variant::OP_LESS_EQUAL, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorLessEqual<Array, Array>>(Variant::OP_LESS_EQUAL, Variant::ARRAY, Variant::ARRAY);
@@ -661,6 +784,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorGreater<Vector2i, Vector2i>>(Variant::OP_GREATER, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorGreater<Vector3, Vector3>>(Variant::OP_GREATER, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorGreater<Vector3i, Vector3i>>(Variant::OP_GREATER, Variant::VECTOR3I, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorGreater<Vector4, Vector4>>(Variant::OP_GREATER, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorGreater<Vector4i, Vector4i>>(Variant::OP_GREATER, Variant::VECTOR4I, Variant::VECTOR4I);
register_op<OperatorEvaluatorGreater<::RID, ::RID>>(Variant::OP_GREATER, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorGreater<Array, Array>>(Variant::OP_GREATER, Variant::ARRAY, Variant::ARRAY);
@@ -674,6 +799,8 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorGreaterEqual<Vector2i, Vector2i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorGreaterEqual<Vector3, Vector3>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorGreaterEqual<Vector3i, Vector3i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I);
+ register_op<OperatorEvaluatorGreaterEqual<Vector4, Vector4>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR4, Variant::VECTOR4);
+ register_op<OperatorEvaluatorGreaterEqual<Vector4i, Vector4i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR4I, Variant::VECTOR4I);
register_op<OperatorEvaluatorGreaterEqual<::RID, ::RID>>(Variant::OP_GREATER_EQUAL, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorGreaterEqual<Array, Array>>(Variant::OP_GREATER_EQUAL, Variant::ARRAY, Variant::ARRAY);
@@ -788,12 +915,15 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorInDictionaryHas<Rect2i>>(Variant::OP_IN, Variant::RECT2I, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Vector3>>(Variant::OP_IN, Variant::VECTOR3, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Vector3i>>(Variant::OP_IN, Variant::VECTOR3I, Variant::DICTIONARY);
+ register_op<OperatorEvaluatorInDictionaryHas<Vector4>>(Variant::OP_IN, Variant::VECTOR4, Variant::DICTIONARY);
+ register_op<OperatorEvaluatorInDictionaryHas<Vector4i>>(Variant::OP_IN, Variant::VECTOR4I, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Transform2D>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Plane>>(Variant::OP_IN, Variant::PLANE, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Quaternion>>(Variant::OP_IN, Variant::QUATERNION, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<::AABB>>(Variant::OP_IN, Variant::AABB, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Basis>>(Variant::OP_IN, Variant::BASIS, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Transform3D>>(Variant::OP_IN, Variant::TRANSFORM3D, Variant::DICTIONARY);
+ register_op<OperatorEvaluatorInDictionaryHas<Projection>>(Variant::OP_IN, Variant::PROJECTION, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Color>>(Variant::OP_IN, Variant::COLOR, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::DICTIONARY);
@@ -825,12 +955,15 @@ void Variant::_register_variant_operators() {
register_op<OperatorEvaluatorInArrayFind<Rect2i, Array>>(Variant::OP_IN, Variant::RECT2I, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Vector3, Array>>(Variant::OP_IN, Variant::VECTOR3, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Vector3i, Array>>(Variant::OP_IN, Variant::VECTOR3I, Variant::ARRAY);
+ register_op<OperatorEvaluatorInArrayFind<Vector4, Array>>(Variant::OP_IN, Variant::VECTOR4, Variant::ARRAY);
+ register_op<OperatorEvaluatorInArrayFind<Vector4i, Array>>(Variant::OP_IN, Variant::VECTOR4I, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Transform2D, Array>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Plane, Array>>(Variant::OP_IN, Variant::PLANE, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Quaternion, Array>>(Variant::OP_IN, Variant::QUATERNION, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<::AABB, Array>>(Variant::OP_IN, Variant::AABB, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Basis, Array>>(Variant::OP_IN, Variant::BASIS, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Transform3D, Array>>(Variant::OP_IN, Variant::TRANSFORM3D, Variant::ARRAY);
+ register_op<OperatorEvaluatorInArrayFind<Projection, Array>>(Variant::OP_IN, Variant::PROJECTION, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Color, Array>>(Variant::OP_IN, Variant::COLOR, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<StringName, Array>>(Variant::OP_IN, Variant::STRING_NAME, Variant::ARRAY);
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index 3e9bae1078..ec1ce67445 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -234,6 +234,30 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<Vector3i>::VARIANT_TYPE; }
};
+template <>
+class OperatorEvaluatorDivNZ<Vector4i, Vector4i, Vector4i> {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_left);
+ const Vector4i &b = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_right);
+ if (unlikely(b.x == 0 || b.y == 0 || b.z == 0 || b.w == 0)) {
+ r_valid = false;
+ *r_ret = "Division by zero error";
+ return;
+ }
+ *r_ret = a / b;
+ r_valid = true;
+ }
+ static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<Vector4i>::change(r_ret);
+ *VariantGetInternalPtr<Vector4i>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector4i>::get_ptr(left) / *VariantGetInternalPtr<Vector4i>::get_ptr(right);
+ }
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ PtrToArg<Vector4i>::encode(PtrToArg<Vector4i>::convert(left) / PtrToArg<Vector4i>::convert(right), r_ret);
+ }
+ static Variant::Type get_return_type() { return GetTypeInfo<Vector4i>::VARIANT_TYPE; }
+};
+
template <class R, class A, class B>
class OperatorEvaluatorMod {
public:
@@ -323,6 +347,30 @@ public:
static Variant::Type get_return_type() { return GetTypeInfo<Vector3i>::VARIANT_TYPE; }
};
+template <>
+class OperatorEvaluatorModNZ<Vector4i, Vector4i, Vector4i> {
+public:
+ static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+ const Vector4i &a = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_left);
+ const Vector4i &b = *VariantGetInternalPtr<Vector4i>::get_ptr(&p_right);
+ if (unlikely(b.x == 0 || b.y == 0 || b.z == 0 || b.w == 0)) {
+ r_valid = false;
+ *r_ret = "Module by zero error";
+ return;
+ }
+ *r_ret = a % b;
+ r_valid = true;
+ }
+ static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<Vector4i>::change(r_ret);
+ *VariantGetInternalPtr<Vector4i>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector4i>::get_ptr(left) % *VariantGetInternalPtr<Vector4i>::get_ptr(right);
+ }
+ static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+ PtrToArg<Vector4i>::encode(PtrToArg<Vector4i>::convert(left) % PtrToArg<Vector4i>::convert(right), r_ret);
+ }
+ static Variant::Type get_return_type() { return GetTypeInfo<Vector4i>::VARIANT_TYPE; }
+};
+
template <class R, class A>
class OperatorEvaluatorNeg {
public:
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index 259ca8a60d..34653310b1 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -649,6 +649,32 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = Vector3i(args[0], args[1], args[2]);
+ } else if (id == "Vector4") {
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
+ if (err) {
+ return err;
+ }
+
+ if (args.size() != 4) {
+ r_err_str = "Expected 4 arguments for constructor";
+ return ERR_PARSE_ERROR;
+ }
+
+ value = Vector4(args[0], args[1], args[2], args[3]);
+ } else if (id == "Vector4i") {
+ Vector<int32_t> args;
+ Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
+ if (err) {
+ return err;
+ }
+
+ if (args.size() != 4) {
+ r_err_str = "Expected 4 arguments for constructor";
+ return ERR_PARSE_ERROR;
+ }
+
+ value = Vector4i(args[0], args[1], args[2], args[3]);
} else if (id == "Transform2D" || id == "Matrix32") { //compatibility
Vector<real_t> args;
Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
@@ -731,6 +757,19 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
}
value = Transform3D(Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]), Vector3(args[9], args[10], args[11]));
+ } else if (id == "Projection") { // "Transform" kept for compatibility with Godot <4.
+ Vector<real_t> args;
+ Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
+ if (err) {
+ return err;
+ }
+
+ if (args.size() != 16) {
+ r_err_str = "Expected 16 arguments for constructor";
+ return ERR_PARSE_ERROR;
+ }
+
+ value = Projection(Vector4(args[0], args[1], args[2], args[3]), Vector4(args[4], args[5], args[6], args[7]), Vector4(args[8], args[9], args[10], args[11]), Vector4(args[12], args[13], args[14], args[15]));
} else if (id == "Color") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);
@@ -1534,6 +1573,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
Vector3i v = p_variant;
p_store_string_func(p_store_string_ud, "Vector3i(" + itos(v.x) + ", " + itos(v.y) + ", " + itos(v.z) + ")");
} break;
+ case Variant::VECTOR4: {
+ Vector4 v = p_variant;
+ p_store_string_func(p_store_string_ud, "Vector4(" + rtos_fix(v.x) + ", " + rtos_fix(v.y) + ", " + rtos_fix(v.z) + ", " + rtos_fix(v.w) + ")");
+ } break;
+ case Variant::VECTOR4I: {
+ Vector4i v = p_variant;
+ p_store_string_func(p_store_string_ud, "Vector4i(" + itos(v.x) + ", " + itos(v.y) + ", " + itos(v.z) + ", " + itos(v.w) + ")");
+ } break;
case Variant::PLANE: {
Plane p = p_variant;
p_store_string_func(p_store_string_ud, "Plane(" + rtos_fix(p.normal.x) + ", " + rtos_fix(p.normal.y) + ", " + rtos_fix(p.normal.z) + ", " + rtos_fix(p.d) + ")");
@@ -1596,6 +1643,20 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, s + ")");
} break;
+ case Variant::PROJECTION: {
+ String s = "Projection(";
+ Projection t = p_variant;
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ if (i != 0 || j != 0) {
+ s += ", ";
+ }
+ s += rtos_fix(t.matrix[i][j]);
+ }
+ }
+
+ p_store_string_func(p_store_string_ud, s + ")");
+ } break;
// misc types
case Variant::COLOR: {
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 3839da495f..57b953f7f0 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -77,6 +77,16 @@ void register_named_setters_getters() {
REGISTER_MEMBER(Vector3i, y);
REGISTER_MEMBER(Vector3i, z);
+ REGISTER_MEMBER(Vector4, x);
+ REGISTER_MEMBER(Vector4, y);
+ REGISTER_MEMBER(Vector4, z);
+ REGISTER_MEMBER(Vector4, w);
+
+ REGISTER_MEMBER(Vector4i, x);
+ REGISTER_MEMBER(Vector4i, y);
+ REGISTER_MEMBER(Vector4i, z);
+ REGISTER_MEMBER(Vector4i, w);
+
REGISTER_MEMBER(Rect2, position);
REGISTER_MEMBER(Rect2, size);
REGISTER_MEMBER(Rect2, end);
@@ -111,6 +121,11 @@ void register_named_setters_getters() {
REGISTER_MEMBER(Transform3D, basis);
REGISTER_MEMBER(Transform3D, origin);
+ REGISTER_MEMBER(Projection, x);
+ REGISTER_MEMBER(Projection, y);
+ REGISTER_MEMBER(Projection, z);
+ REGISTER_MEMBER(Projection, w);
+
REGISTER_MEMBER(Color, r);
REGISTER_MEMBER(Color, g);
REGISTER_MEMBER(Color, b);
@@ -804,11 +819,14 @@ INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2, double, real_t, 2)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2i, int64_t, int32_t, 2)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3, double, real_t, 3)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3i, int64_t, int32_t, 3)
+INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector4, double, real_t, 4)
+INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector4i, int64_t, int32_t, 4)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Quaternion, double, real_t, 4)
INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Color, double, float, 4)
INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Transform2D, Vector2, .columns, 3)
INDEXED_SETGET_STRUCT_BULTIN_FUNC(Basis, Vector3, set_column, get_column, 3)
+INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Projection, Vector4, .matrix, 4)
INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedByteArray, int64_t, uint8_t)
INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedInt32Array, int64_t, int32_t)
@@ -867,10 +885,13 @@ void register_indexed_setters_getters() {
REGISTER_INDEXED_MEMBER(Vector2i);
REGISTER_INDEXED_MEMBER(Vector3);
REGISTER_INDEXED_MEMBER(Vector3i);
+ REGISTER_INDEXED_MEMBER(Vector4);
+ REGISTER_INDEXED_MEMBER(Vector4i);
REGISTER_INDEXED_MEMBER(Quaternion);
REGISTER_INDEXED_MEMBER(Color);
REGISTER_INDEXED_MEMBER(Transform2D);
REGISTER_INDEXED_MEMBER(Basis);
+ REGISTER_INDEXED_MEMBER(Projection);
REGISTER_INDEXED_MEMBER(PackedByteArray);
REGISTER_INDEXED_MEMBER(PackedInt32Array);
diff --git a/core/variant/variant_setget.h b/core/variant/variant_setget.h
index bc4dc4b408..570277dc7a 100644
--- a/core/variant/variant_setget.h
+++ b/core/variant/variant_setget.h
@@ -281,6 +281,16 @@ SETGET_NUMBER_STRUCT(Vector3i, int64_t, x)
SETGET_NUMBER_STRUCT(Vector3i, int64_t, y)
SETGET_NUMBER_STRUCT(Vector3i, int64_t, z)
+SETGET_NUMBER_STRUCT(Vector4, double, x)
+SETGET_NUMBER_STRUCT(Vector4, double, y)
+SETGET_NUMBER_STRUCT(Vector4, double, z)
+SETGET_NUMBER_STRUCT(Vector4, double, w)
+
+SETGET_NUMBER_STRUCT(Vector4i, int64_t, x)
+SETGET_NUMBER_STRUCT(Vector4i, int64_t, y)
+SETGET_NUMBER_STRUCT(Vector4i, int64_t, z)
+SETGET_NUMBER_STRUCT(Vector4i, int64_t, w)
+
SETGET_STRUCT(Rect2, Vector2, position)
SETGET_STRUCT(Rect2, Vector2, size)
SETGET_STRUCT_FUNC(Rect2, Vector2, end, set_end, get_end)
@@ -315,6 +325,11 @@ SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_column, get_column, 2)
SETGET_STRUCT(Transform3D, Basis, basis)
SETGET_STRUCT(Transform3D, Vector3, origin)
+SETGET_STRUCT_CUSTOM(Projection, Vector4, x, matrix[0])
+SETGET_STRUCT_CUSTOM(Projection, Vector4, y, matrix[1])
+SETGET_STRUCT_CUSTOM(Projection, Vector4, z, matrix[2])
+SETGET_STRUCT_CUSTOM(Projection, Vector4, w, matrix[3])
+
SETGET_NUMBER_STRUCT(Color, double, r)
SETGET_NUMBER_STRUCT(Color, double, g)
SETGET_NUMBER_STRUCT(Color, double, b)
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 2bca5f8284..1f1439ab24 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -99,18 +99,105 @@ struct VariantUtilityFunctions {
return Math::posmod(b, r);
}
- static inline double floor(double x) {
+ static inline Variant floor(Variant x, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ switch (x.get_type()) {
+ case Variant::INT: {
+ return VariantInternalAccessor<int64_t>::get(&x);
+ } break;
+ case Variant::FLOAT: {
+ return Math::floor(VariantInternalAccessor<double>::get(&x));
+ } break;
+ case Variant::VECTOR2: {
+ return VariantInternalAccessor<Vector2>::get(&x).floor();
+ } break;
+ case Variant::VECTOR3: {
+ return VariantInternalAccessor<Vector3>::get(&x).floor();
+ } break;
+ case Variant::VECTOR4: {
+ return VariantInternalAccessor<Vector4>::get(&x).floor();
+ } break;
+ default: {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+ }
+ }
+
+ static inline double floorf(double x) {
return Math::floor(x);
}
- static inline double ceil(double x) {
+ static inline int floori(double x) {
+ return int(x);
+ }
+
+ static inline Variant ceil(Variant x, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ switch (x.get_type()) {
+ case Variant::INT: {
+ return VariantInternalAccessor<int64_t>::get(&x);
+ } break;
+ case Variant::FLOAT: {
+ return Math::ceil(VariantInternalAccessor<double>::get(&x));
+ } break;
+ case Variant::VECTOR2: {
+ return VariantInternalAccessor<Vector2>::get(&x).ceil();
+ } break;
+ case Variant::VECTOR3: {
+ return VariantInternalAccessor<Vector3>::get(&x).ceil();
+ } break;
+ case Variant::VECTOR4: {
+ return VariantInternalAccessor<Vector4>::get(&x).ceil();
+ } break;
+ default: {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+ }
+ }
+
+ static inline double ceilf(double x) {
return Math::ceil(x);
}
- static inline double round(double x) {
+ static inline int ceili(double x) {
+ return int(Math::ceil(x));
+ }
+
+ static inline Variant round(Variant x, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ switch (x.get_type()) {
+ case Variant::INT: {
+ return VariantInternalAccessor<int64_t>::get(&x);
+ } break;
+ case Variant::FLOAT: {
+ return Math::round(VariantInternalAccessor<double>::get(&x));
+ } break;
+ case Variant::VECTOR2: {
+ return VariantInternalAccessor<Vector2>::get(&x).round();
+ } break;
+ case Variant::VECTOR3: {
+ return VariantInternalAccessor<Vector3>::get(&x).round();
+ } break;
+ case Variant::VECTOR4: {
+ return VariantInternalAccessor<Vector4>::get(&x).round();
+ } break;
+ default: {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+ }
+ }
+
+ static inline double roundf(double x) {
return Math::round(x);
}
+ static inline int roundi(double x) {
+ return int(Math::round(x));
+ }
+
static inline Variant abs(const Variant &x, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_OK;
switch (x.get_type()) {
@@ -132,6 +219,12 @@ struct VariantUtilityFunctions {
case Variant::VECTOR3I: {
return VariantInternalAccessor<Vector3i>::get(&x).abs();
} break;
+ case Variant::VECTOR4: {
+ return VariantInternalAccessor<Vector4>::get(&x).abs();
+ } break;
+ case Variant::VECTOR4I: {
+ return VariantInternalAccessor<Vector4i>::get(&x).abs();
+ } break;
default: {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
@@ -168,6 +261,12 @@ struct VariantUtilityFunctions {
case Variant::VECTOR3I: {
return VariantInternalAccessor<Vector3i>::get(&x).sign();
} break;
+ case Variant::VECTOR4: {
+ return VariantInternalAccessor<Vector4>::get(&x).sign();
+ } break;
+ case Variant::VECTOR4I: {
+ return VariantInternalAccessor<Vector4i>::get(&x).sign();
+ } break;
default: {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
@@ -223,7 +322,44 @@ struct VariantUtilityFunctions {
return Math::snapped(value, step);
}
- static inline double lerp(double from, double to, double weight) {
+ static inline Variant lerp(const Variant &from, const Variant &to, double weight, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ if (from.get_type() != to.get_type()) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ return Variant();
+ }
+
+ switch (from.get_type()) {
+ case Variant::FLOAT: {
+ return lerpf(VariantInternalAccessor<double>::get(&from), to, weight);
+ } break;
+ case Variant::VECTOR2: {
+ return VariantInternalAccessor<Vector2>::get(&from).lerp(VariantInternalAccessor<Vector2>::get(&to), weight);
+ } break;
+ case Variant::VECTOR3: {
+ return VariantInternalAccessor<Vector3>::get(&from).lerp(VariantInternalAccessor<Vector3>::get(&to), weight);
+ } break;
+ case Variant::VECTOR4: {
+ return VariantInternalAccessor<Vector4>::get(&from).lerp(VariantInternalAccessor<Vector4>::get(&to), weight);
+ } break;
+ case Variant::QUATERNION: {
+ return VariantInternalAccessor<Quaternion>::get(&from).slerp(VariantInternalAccessor<Quaternion>::get(&to), weight);
+ } break;
+ case Variant::BASIS: {
+ return VariantInternalAccessor<Basis>::get(&from).slerp(VariantInternalAccessor<Basis>::get(&to), weight);
+ } break;
+ case Variant::COLOR: {
+ return VariantInternalAccessor<Color>::get(&from).lerp(VariantInternalAccessor<Color>::get(&to), weight);
+ } break;
+ default: {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+ }
+ }
+
+ static inline double lerpf(double from, double to, double weight) {
return Math::lerp(from, to, weight);
}
@@ -1240,17 +1376,24 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(fmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(fposmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(posmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH);
- FUNCBINDR(floor, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
- FUNCBINDR(ceil, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
- FUNCBINDR(round, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
- FUNCBINDVR(abs, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDVR(floor, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(floorf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(floori, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDVR(ceil, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(ceilf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(ceili, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDVR(round, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(roundf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(roundi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDVR(abs, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(absf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(absi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDVR(sign, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
-
FUNCBINDR(signf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(signi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
@@ -1268,7 +1411,8 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(snapped, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH);
- FUNCBINDR(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDVR3(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(lerpf, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(cubic_interpolate, sarray("from", "to", "pre", "post", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
@@ -1288,12 +1432,10 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(wrapf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDVARARG(max, sarray(), Variant::UTILITY_FUNC_TYPE_MATH);
-
FUNCBINDR(maxi, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(maxf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDVARARG(min, sarray(), Variant::UTILITY_FUNC_TYPE_MATH);
-
FUNCBINDR(mini, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(minf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH);
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/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index 1943221309..658a13d05b 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -134,15 +134,32 @@
</description>
</method>
<method name="ceil">
- <return type="float" />
- <argument index="0" name="x" type="float" />
+ <return type="Variant" />
+ <argument index="0" name="x" type="Variant" />
<description>
- Rounds [code]x[/code] upward (towards positive infinity), returning the smallest whole number that is not less than [code]x[/code].
+ Rounds [code]x[/code] upward (towards positive infinity), returning the smallest whole number that is not less than [code]x[/code]. Supported types: [int], [float], [Vector2], [Vector3], [Vector4].
[codeblock]
var i = ceil(1.45) # i is 2.0
i = ceil(1.001) # i is 2.0
[/codeblock]
See also [method floor], [method round], and [method snapped].
+ [b]Note:[/b] For better type safety, you can use [method ceilf], [method ceili], [method Vector2.ceil], [method Vector3.ceil] or [method Vector4.ceil] instead.
+ </description>
+ </method>
+ <method name="ceilf">
+ <return type="float" />
+ <argument index="0" name="x" type="float" />
+ <description>
+ Rounds [code]x[/code] upward (towards positive infinity), returning the smallest whole number that is not less than [code]x[/code].
+ A type-safe version of [method ceil], specialzied in floats.
+ </description>
+ </method>
+ <method name="ceili">
+ <return type="int" />
+ <argument index="0" name="x" type="float" />
+ <description>
+ Rounds [code]x[/code] upward (towards positive infinity), returning the smallest whole number that is not less than [code]x[/code].
+ A type-safe version of [method ceil] that returns integer.
</description>
</method>
<method name="clamp">
@@ -300,10 +317,10 @@
</description>
</method>
<method name="floor">
- <return type="float" />
- <argument index="0" name="x" type="float" />
+ <return type="Variant" />
+ <argument index="0" name="x" type="Variant" />
<description>
- Rounds [code]x[/code] downward (towards negative infinity), returning the largest whole number that is not more than [code]x[/code].
+ Rounds [code]x[/code] downward (towards negative infinity), returning the largest whole number that is not more than [code]x[/code]. Supported types: [int], [float], [Vector2], [Vector3], [Vector4].
[codeblock]
# a is 2.0
var a = floor(2.99)
@@ -311,7 +328,23 @@
a = floor(-2.99)
[/codeblock]
See also [method ceil], [method round], and [method snapped].
- [b]Note:[/b] This method returns a float. If you need an integer, you can use [code]int(x)[/code] directly.
+ [b]Note:[/b] For better type safety, you can use [method floorf], [method floori], [method Vector2.floor], [method Vector3.floor] or [method Vector4.floor] instead.
+ </description>
+ </method>
+ <method name="floorf">
+ <return type="float" />
+ <argument index="0" name="x" type="float" />
+ <description>
+ Rounds [code]x[/code] downward (towards negative infinity), returning the largest whole number that is not more than [code]x[/code].
+ A type-safe version of [method floor], specialzied in floats.
+ </description>
+ </method>
+ <method name="floori">
+ <return type="int" />
+ <argument index="0" name="x" type="float" />
+ <description>
+ Rounds [code]x[/code] downward (towards negative infinity), returning the largest whole number that is not more than [code]x[/code].
+ Equivalent of doing [code]int(x)[/code].
</description>
</method>
<method name="fmod">
@@ -380,7 +413,7 @@
<argument index="1" name="to" type="float" />
<argument index="2" name="weight" type="float" />
<description>
- Returns an interpolation or extrapolation factor considering the range specified in [code]from[/code] and [code]to[/code], and the interpolated value specified in [code]weight[/code]. The returned value will be between [code]0.0[/code] and [code]1.0[/code] if [code]weight[/code] is between [code]from[/code] and [code]to[/code] (inclusive). If [code]weight[/code] is located outside this range, then an extrapolation factor will be returned (return value lower than [code]0.0[/code] or greater than [code]1.0[/code]).
+ Returns an interpolation or extrapolation factor considering the range specified in [code]from[/code] and [code]to[/code], and the interpolated value specified in [code]weight[/code]. The returned value will be between [code]0.0[/code] and [code]1.0[/code] if [code]weight[/code] is between [code]from[/code] and [code]to[/code] (inclusive). If [code]weight[/code] is located outside this range, then an extrapolation factor will be returned (return value lower than [code]0.0[/code] or greater than [code]1.0[/code]). Use [method clamp] on the result of [method inverse_lerp] if this is not desired.
[codeblock]
# The interpolation ratio in the `lerp()` call below is 0.75.
var middle = lerp(20, 30, 0.75)
@@ -389,7 +422,7 @@
var ratio = inverse_lerp(20, 30, 27.5)
# `ratio` is now 0.75.
[/codeblock]
- See also [method lerp] which performs the reverse of this operation.
+ See also [method lerp] which performs the reverse of this operation, and [method range_lerp] to map a continuous series of values to another.
</description>
</method>
<method name="is_equal_approx">
@@ -439,16 +472,18 @@
</description>
</method>
<method name="lerp">
- <return type="float" />
- <argument index="0" name="from" type="float" />
- <argument index="1" name="to" type="float" />
- <argument index="2" name="weight" type="float" />
+ <return type="Variant" />
+ <argument index="0" name="from" type="Variant" />
+ <argument index="1" name="to" type="Variant" />
+ <argument index="2" name="weight" type="Variant" />
<description>
- Linearly interpolates between two values by the factor defined in [code]weight[/code]. To perform interpolation, [code]weight[/code] should be between [code]0.0[/code] and [code]1.0[/code] (inclusive). However, values outside this range are allowed and can be used to perform [i]extrapolation[/i].
+ Linearly interpolates between two values by the factor defined in [code]weight[/code]. To perform interpolation, [code]weight[/code] should be between [code]0.0[/code] and [code]1.0[/code] (inclusive). However, values outside this range are allowed and can be used to perform [i]extrapolation[/i]. Use [method clamp] on the result of [method lerp] if this is not desired.
+ Both [code]from[/code] and [code]to[/code] must have matching types. Supported types: [float], [Vector2], [Vector3], [Vector4], [Color], [Quaternion], [Basis].
[codeblock]
lerp(0, 4, 0.75) # Returns 3.0
[/codeblock]
- See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep].
+ See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep]. See also [method range_lerp] to map a continuous series of values to another.
+ [b]Note:[/b] For better type safety, you can use [method lerpf], [method Vector2.lerp], [method Vector3.lerp], [method Vector4.lerp], [method Color.lerp], [method Quaternion.slerp] or [method Basis.slerp] instead.
</description>
</method>
<method name="lerp_angle">
@@ -471,6 +506,19 @@
[b]Note:[/b] This method lerps through the shortest path between [code]from[/code] and [code]to[/code]. However, when these two angles are approximately [code]PI + k * TAU[/code] apart for any integer [code]k[/code], it's not obvious which way they lerp due to floating-point precision errors. For example, [code]lerp_angle(0, PI, weight)[/code] lerps counter-clockwise, while [code]lerp_angle(0, PI + 5 * TAU, weight)[/code] lerps clockwise.
</description>
</method>
+ <method name="lerpf">
+ <return type="float" />
+ <argument index="0" name="from" type="float" />
+ <argument index="1" name="to" type="float" />
+ <argument index="2" name="weight" type="float" />
+ <description>
+ Linearly interpolates between two values by the factor defined in [code]weight[/code]. To perform interpolation, [code]weight[/code] should be between [code]0.0[/code] and [code]1.0[/code] (inclusive). However, values outside this range are allowed and can be used to perform [i]extrapolation[/i].
+ [codeblock]
+ lerp(0, 4, 0.75) # Returns 3.0
+ [/codeblock]
+ See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep].
+ </description>
+ </method>
<method name="linear2db">
<return type="float" />
<argument index="0" name="lin" type="float" />
@@ -807,10 +855,11 @@
<argument index="3" name="ostart" type="float" />
<argument index="4" name="ostop" type="float" />
<description>
- Maps a [code]value[/code] from range [code][istart, istop][/code] to [code][ostart, ostop][/code].
+ Maps a [code]value[/code] from range [code][istart, istop][/code] to [code][ostart, ostop][/code]. See also [method lerp] and [method inverse_lerp]. If [code]value[/code] is outside [code][istart, istop][/code], then the resulting value will also be outside [code][ostart, ostop][/code]. Use [method clamp] on the result of [method range_lerp] if this is not desired.
[codeblock]
range_lerp(75, 0, 100, -1, 1) # Returns 0.5
[/codeblock]
+ For complex use cases where you need multiple ranges, consider using [Curve] or [Gradient] instead.
</description>
</method>
<method name="rid_allocate_id">
@@ -827,14 +876,33 @@
</description>
</method>
<method name="round">
- <return type="float" />
- <argument index="0" name="x" type="float" />
+ <return type="Variant" />
+ <argument index="0" name="x" type="Variant" />
<description>
- Rounds [code]x[/code] to the nearest whole number, with halfway cases rounded away from zero.
+ Rounds [code]x[/code] to the nearest whole number, with halfway cases rounded away from zero. Supported types: [int], [float], [Vector2], [Vector3], [Vector4].
[codeblock]
+ round(2.4) # Returns 2
+ round(2.5) # Returns 3
round(2.6) # Returns 3
[/codeblock]
See also [method floor], [method ceil], and [method snapped].
+ [b]Note:[/b] For better type safety, you can use [method roundf], [method roundi], [method Vector2.round], [method Vector3.round] or [method Vector4.round] instead.
+ </description>
+ </method>
+ <method name="roundf">
+ <return type="float" />
+ <argument index="0" name="x" type="float" />
+ <description>
+ Rounds [code]x[/code] to the nearest whole number, with halfway cases rounded away from zero.
+ A type-safe version of [method round], specialzied in floats.
+ </description>
+ </method>
+ <method name="roundi">
+ <return type="int" />
+ <argument index="0" name="x" type="float" />
+ <description>
+ Rounds [code]x[/code] to the nearest whole number, with halfway cases rounded away from zero.
+ A type-safe version of [method round] that returns integer.
</description>
</method>
<method name="seed">
@@ -1209,6 +1277,7 @@
The [ResourceSaver] singleton.
</member>
<member name="ResourceUID" type="ResourceUID" setter="" getter="">
+ The [ResourceUID] singleton.
</member>
<member name="TextServerManager" type="TextServerManager" setter="" getter="">
The [TextServerManager] singleton.
@@ -1222,6 +1291,8 @@
<member name="VisualScriptCustomNodes" type="VisualScriptCustomNodes" setter="" getter="">
The [VisualScriptCustomNodes] singleton.
</member>
+ <member name="WorkerThreadPool" type="WorkerThreadPool" setter="" getter="">
+ </member>
<member name="XRServer" type="XRServer" setter="" getter="">
The [XRServer] singleton.
</member>
@@ -2515,72 +2586,66 @@
<constant name="PROPERTY_HINT_EXP_EASING" value="4" enum="PropertyHint">
Hints that a float property should be edited via an exponential easing function. The hint string can include [code]"attenuation"[/code] to flip the curve horizontally and/or [code]"inout"[/code] to also include in/out easing.
</constant>
- <constant name="PROPERTY_HINT_LENGTH" value="5" enum="PropertyHint">
- Deprecated hint, unused.
- </constant>
- <constant name="PROPERTY_HINT_LINK" value="6" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LINK" value="5" enum="PropertyHint">
Hints that a vector property should allow linking values (e.g. to edit both [code]x[/code] and [code]y[/code] together).
</constant>
- <constant name="PROPERTY_HINT_KEY_ACCEL" value="7" enum="PropertyHint">
- Deprecated hint, unused.
- </constant>
- <constant name="PROPERTY_HINT_FLAGS" value="8" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_FLAGS" value="6" enum="PropertyHint">
Hints that an integer property is a bitmask with named bit flags. For example, to allow toggling bits 0, 1, 2 and 4, the hint could be something like [code]"Bit0,Bit1,Bit2,,Bit4"[/code].
</constant>
- <constant name="PROPERTY_HINT_LAYERS_2D_RENDER" value="9" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_2D_RENDER" value="7" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named 2D render layers.
</constant>
- <constant name="PROPERTY_HINT_LAYERS_2D_PHYSICS" value="10" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_2D_PHYSICS" value="8" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named 2D physics layers.
</constant>
- <constant name="PROPERTY_HINT_LAYERS_2D_NAVIGATION" value="11" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_2D_NAVIGATION" value="9" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named 2D navigation layers.
</constant>
- <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="12" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_3D_RENDER" value="10" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named 3D render layers.
</constant>
- <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="13" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_3D_PHYSICS" value="11" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named 3D physics layers.
</constant>
- <constant name="PROPERTY_HINT_LAYERS_3D_NAVIGATION" value="14" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LAYERS_3D_NAVIGATION" value="12" enum="PropertyHint">
Hints that an integer property is a bitmask using the optionally named 3D navigation layers.
</constant>
- <constant name="PROPERTY_HINT_FILE" value="15" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_FILE" value="13" enum="PropertyHint">
Hints that a string property is a path to a file. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code].
</constant>
- <constant name="PROPERTY_HINT_DIR" value="16" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_DIR" value="14" enum="PropertyHint">
Hints that a string property is a path to a directory. Editing it will show a file dialog for picking the path.
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_FILE" value="17" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_FILE" value="15" enum="PropertyHint">
Hints that a string property is an absolute path to a file outside the project folder. Editing it will show a file dialog for picking the path. The hint string can be a set of filters with wildcards like [code]"*.png,*.jpg"[/code].
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_DIR" value="18" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_DIR" value="16" enum="PropertyHint">
Hints that a string property is an absolute path to a directory outside the project folder. Editing it will show a file dialog for picking the path.
</constant>
- <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="19" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="17" enum="PropertyHint">
Hints that a property is an instance of a [Resource]-derived type, optionally specified via the hint string (e.g. [code]"Texture2D"[/code]). Editing it will show a popup menu of valid resource types to instantiate.
</constant>
- <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="20" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="18" enum="PropertyHint">
Hints that a string property is text with line breaks. Editing it will show a text input field where line breaks can be typed.
</constant>
- <constant name="PROPERTY_HINT_EXPRESSION" value="21" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_EXPRESSION" value="19" enum="PropertyHint">
Hints that a string property is an [Expression].
</constant>
- <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="22" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PLACEHOLDER_TEXT" value="20" enum="PropertyHint">
Hints that a string property should have a placeholder text visible on its input field, whenever the property is empty. The hint string is the placeholder text to use.
</constant>
- <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="23" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="21" enum="PropertyHint">
Hints that a color property should be edited without changing its alpha component, i.e. only R, G and B channels are edited.
</constant>
- <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="24" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="22" enum="PropertyHint">
Hints that an image is compressed using lossy compression.
</constant>
- <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="25" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="23" enum="PropertyHint">
Hints that an image is compressed using lossless compression.
</constant>
- <constant name="PROPERTY_HINT_OBJECT_ID" value="26" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_OBJECT_ID" value="24" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_TYPE_STRING" value="27" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_TYPE_STRING" value="25" enum="PropertyHint">
Hint that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types. For instance:
[codeblock]
hint_string = "%s:" % [TYPE_INT] # Array of inteters.
@@ -2590,128 +2655,124 @@
[/codeblock]
[b]Note:[/b] The final colon is required to specify for properly detecting built-in types.
</constant>
- <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="28" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="26" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="29" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="27" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="30" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="28" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="31" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="29" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="32" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="30" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="33" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="31" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="34" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="32" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="35" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="33" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="36" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="34" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="37" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="35" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="38" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="36" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_SAVE_FILE" value="39" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_SAVE_FILE" value="37" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="40" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="38" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="41" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="39" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_INT_IS_POINTER" value="43" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_INT_IS_POINTER" value="41" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_ARRAY_TYPE" value="42" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_ARRAY_TYPE" value="40" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_LOCALE_ID" value="44" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LOCALE_ID" value="42" enum="PropertyHint">
Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country.
</constant>
- <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="45" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="43" enum="PropertyHint">
Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings.
</constant>
- <constant name="PROPERTY_HINT_NODE_TYPE" value="46" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_TYPE" value="44" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_MAX" value="47" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_MAX" value="45" enum="PropertyHint">
</constant>
<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_STORAGE" value="1" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_STORAGE" value="2" enum="PropertyUsageFlags">
The property is serialized and saved in the scene file (default).
</constant>
- <constant name="PROPERTY_USAGE_EDITOR" value="2" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_EDITOR" value="4" enum="PropertyUsageFlags">
The property is shown in the editor inspector (default).
</constant>
- <constant name="PROPERTY_USAGE_NETWORK" value="4" enum="PropertyUsageFlags">
- Deprecated usage flag, unused.
- </constant>
- <constant name="PROPERTY_USAGE_EDITOR_HELPER" value="8" enum="PropertyUsageFlags">
- Deprecated usage flag, unused.
- </constant>
- <constant name="PROPERTY_USAGE_CHECKABLE" value="16" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_CHECKABLE" value="8" enum="PropertyUsageFlags">
The property can be checked in the editor inspector.
</constant>
- <constant name="PROPERTY_USAGE_CHECKED" value="32" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_CHECKED" value="16" enum="PropertyUsageFlags">
The property is checked in the editor inspector.
</constant>
- <constant name="PROPERTY_USAGE_INTERNATIONALIZED" value="64" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_INTERNATIONALIZED" value="32" enum="PropertyUsageFlags">
The property is a translatable string.
</constant>
- <constant name="PROPERTY_USAGE_GROUP" value="128" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_GROUP" value="64" enum="PropertyUsageFlags">
Used to group properties together in the editor. See [EditorInspector].
</constant>
- <constant name="PROPERTY_USAGE_CATEGORY" value="256" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_CATEGORY" value="128" enum="PropertyUsageFlags">
Used to categorize properties together in the editor.
</constant>
- <constant name="PROPERTY_USAGE_SUBGROUP" value="512" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_SUBGROUP" value="256" enum="PropertyUsageFlags">
Used to group properties together in the editor in a subgroup (under a group). See [EditorInspector].
</constant>
- <constant name="PROPERTY_USAGE_NO_INSTANCE_STATE" value="2048" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_CLASS_IS_BITFIELD" value="512" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_NO_INSTANCE_STATE" value="1024" enum="PropertyUsageFlags">
The property does not save its state in [PackedScene].
</constant>
- <constant name="PROPERTY_USAGE_RESTART_IF_CHANGED" value="4096" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_RESTART_IF_CHANGED" value="2048" enum="PropertyUsageFlags">
Editing the property prompts the user for restarting the editor.
</constant>
- <constant name="PROPERTY_USAGE_SCRIPT_VARIABLE" value="8192" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_SCRIPT_VARIABLE" value="4096" enum="PropertyUsageFlags">
The property is a script variable which should be serialized and saved in the scene file.
</constant>
- <constant name="PROPERTY_USAGE_STORE_IF_NULL" value="16384" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_STORE_IF_NULL" value="8192" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_ANIMATE_AS_TRIGGER" value="32768" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_ANIMATE_AS_TRIGGER" value="16384" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED" value="65536" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED" value="32768" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="131072" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="65536" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="262144" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="131072" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="524288" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="262144" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_INTERNAL" value="1048576" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_INTERNAL" value="524288" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE" value="2097152" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE" value="1048576" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_HIGH_END_GFX" value="4194304" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_HIGH_END_GFX" value="2097152" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT" value="8388608" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT" value="4194304" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT" value="16777216" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT" value="8388608" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_KEYING_INCREMENTS" value="33554432" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_KEYING_INCREMENTS" value="16777216" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_DEFERRED_SET_RESOURCE" value="67108864" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_DEFERRED_SET_RESOURCE" value="33554432" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT" value="134217728" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT" value="67108864" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_EDITOR_BASIC_SETTING" value="268435456" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_EDITOR_BASIC_SETTING" value="134217728" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_ARRAY" value="1073741824" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_ARRAY" value="536870912" enum="PropertyUsageFlags">
</constant>
- <constant name="PROPERTY_USAGE_DEFAULT" value="7" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_DEFAULT" value="6" enum="PropertyUsageFlags">
Default usage (storage, editor and network).
</constant>
- <constant name="PROPERTY_USAGE_DEFAULT_INTL" value="71" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_DEFAULT_INTL" value="38" enum="PropertyUsageFlags">
Default usage for translatable strings (storage, editor, network and internationalized).
</constant>
- <constant name="PROPERTY_USAGE_NO_EDITOR" value="5" enum="PropertyUsageFlags">
+ <constant name="PROPERTY_USAGE_NO_EDITOR" value="2" enum="PropertyUsageFlags">
Default usage but without showing the property in the editor (storage, network).
</constant>
<constant name="METHOD_FLAG_NORMAL" value="1" enum="MethodFlags">
@@ -2720,49 +2781,22 @@
<constant name="METHOD_FLAG_EDITOR" value="2" enum="MethodFlags">
Flag for an editor method.
</constant>
- <constant name="METHOD_FLAG_NOSCRIPT" value="4" enum="MethodFlags">
- Deprecated method flag, unused.
- </constant>
- <constant name="METHOD_FLAG_CONST" value="8" enum="MethodFlags">
+ <constant name="METHOD_FLAG_CONST" value="4" enum="MethodFlags">
Flag for a constant method.
</constant>
- <constant name="METHOD_FLAG_REVERSE" value="16" enum="MethodFlags">
- Deprecated method flag, unused.
- </constant>
- <constant name="METHOD_FLAG_VIRTUAL" value="32" enum="MethodFlags">
+ <constant name="METHOD_FLAG_VIRTUAL" value="8" enum="MethodFlags">
Flag for a virtual method.
</constant>
- <constant name="METHOD_FLAG_FROM_SCRIPT" value="64" enum="MethodFlags">
- Deprecated method flag, unused.
- </constant>
- <constant name="METHOD_FLAG_VARARG" value="128" enum="MethodFlags">
+ <constant name="METHOD_FLAG_VARARG" value="16" enum="MethodFlags">
</constant>
- <constant name="METHOD_FLAG_STATIC" value="256" enum="MethodFlags">
+ <constant name="METHOD_FLAG_STATIC" value="32" enum="MethodFlags">
</constant>
- <constant name="METHOD_FLAG_OBJECT_CORE" value="512" enum="MethodFlags">
+ <constant name="METHOD_FLAG_OBJECT_CORE" value="64" enum="MethodFlags">
Used internally. Allows to not dump core virtuals such as [code]_notification[/code] to the JSON API.
</constant>
<constant name="METHOD_FLAGS_DEFAULT" value="1" enum="MethodFlags">
Default method flags.
</constant>
- <constant name="RPC_MODE_DISABLED" value="0" enum="RPCMode">
- Used with [method Node.rpc_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods.
- </constant>
- <constant name="RPC_MODE_ANY_PEER" value="1" enum="RPCMode">
- Used with [method Node.rpc_config] to set a method to be callable remotely by any peer. Analogous to the [code]@rpc(any)[/code] annotation. Calls are accepted from all remote peers, no matter if they are node's authority or not.
- </constant>
- <constant name="RPC_MODE_AUTHORITY" value="2" enum="RPCMode">
- Used with [method Node.rpc_config] to set a method to be callable remotely only by the current multiplayer authority (which is the server by default). Analogous to the [code]@rpc(authority)[/code] annotation. See [method Node.set_multiplayer_authority].
- </constant>
- <constant name="TRANSFER_MODE_UNRELIABLE" value="0" enum="TransferMode">
- Packets are not acknowledged, no resend attempts are made for lost packets. Packets may arrive in any order. Potentially faster than [constant TRANSFER_MODE_UNRELIABLE_ORDERED]. Use for non-critical data, and always consider whether the order matters.
- </constant>
- <constant name="TRANSFER_MODE_UNRELIABLE_ORDERED" value="1" enum="TransferMode">
- Packets are not acknowledged, no resend attempts are made for lost packets. Packets are received in the order they were sent in. Potentially faster than [constant TRANSFER_MODE_RELIABLE]. Use for non-critical data or data that would be outdated if received late due to resend attempt(s) anyway, for example movement and positional data.
- </constant>
- <constant name="TRANSFER_MODE_RELIABLE" value="2" enum="TransferMode">
- Packets must be received and resend attempts should be made until the packets are acknowledged. Packets must be received in the order they were sent in. Most reliable transfer mode, but potentially the slowest due to the overhead. Use for critical data that must be transmitted and arrive in order, for example an ability being triggered or a chat message. Consider carefully if the information really is critical, and use sparingly.
- </constant>
<constant name="TYPE_NIL" value="0" enum="Variant.Type">
Variable is [code]null[/code].
</constant>
@@ -2799,76 +2833,82 @@
<constant name="TYPE_TRANSFORM2D" value="11" enum="Variant.Type">
Variable is of type [Transform2D].
</constant>
- <constant name="TYPE_PLANE" value="12" enum="Variant.Type">
+ <constant name="TYPE_VECTOR4" value="12" enum="Variant.Type">
+ </constant>
+ <constant name="TYPE_VECTOR4I" value="13" enum="Variant.Type">
+ </constant>
+ <constant name="TYPE_PLANE" value="14" enum="Variant.Type">
Variable is of type [Plane].
</constant>
- <constant name="TYPE_QUATERNION" value="13" enum="Variant.Type">
+ <constant name="TYPE_QUATERNION" value="15" enum="Variant.Type">
Variable is of type [Quaternion].
</constant>
- <constant name="TYPE_AABB" value="14" enum="Variant.Type">
+ <constant name="TYPE_AABB" value="16" enum="Variant.Type">
Variable is of type [AABB].
</constant>
- <constant name="TYPE_BASIS" value="15" enum="Variant.Type">
+ <constant name="TYPE_BASIS" value="17" enum="Variant.Type">
Variable is of type [Basis].
</constant>
- <constant name="TYPE_TRANSFORM3D" value="16" enum="Variant.Type">
+ <constant name="TYPE_TRANSFORM3D" value="18" enum="Variant.Type">
Variable is of type [Transform3D].
</constant>
- <constant name="TYPE_COLOR" value="17" enum="Variant.Type">
+ <constant name="TYPE_PROJECTION" value="19" enum="Variant.Type">
+ </constant>
+ <constant name="TYPE_COLOR" value="20" enum="Variant.Type">
Variable is of type [Color].
</constant>
- <constant name="TYPE_STRING_NAME" value="18" enum="Variant.Type">
+ <constant name="TYPE_STRING_NAME" value="21" enum="Variant.Type">
Variable is of type [StringName].
</constant>
- <constant name="TYPE_NODE_PATH" value="19" enum="Variant.Type">
+ <constant name="TYPE_NODE_PATH" value="22" enum="Variant.Type">
Variable is of type [NodePath].
</constant>
- <constant name="TYPE_RID" value="20" enum="Variant.Type">
+ <constant name="TYPE_RID" value="23" enum="Variant.Type">
Variable is of type [RID].
</constant>
- <constant name="TYPE_OBJECT" value="21" enum="Variant.Type">
+ <constant name="TYPE_OBJECT" value="24" enum="Variant.Type">
Variable is of type [Object].
</constant>
- <constant name="TYPE_CALLABLE" value="22" enum="Variant.Type">
+ <constant name="TYPE_CALLABLE" value="25" enum="Variant.Type">
Variable is of type [Callable].
</constant>
- <constant name="TYPE_SIGNAL" value="23" enum="Variant.Type">
+ <constant name="TYPE_SIGNAL" value="26" enum="Variant.Type">
Variable is of type [Signal].
</constant>
- <constant name="TYPE_DICTIONARY" value="24" enum="Variant.Type">
+ <constant name="TYPE_DICTIONARY" value="27" enum="Variant.Type">
Variable is of type [Dictionary].
</constant>
- <constant name="TYPE_ARRAY" value="25" enum="Variant.Type">
+ <constant name="TYPE_ARRAY" value="28" enum="Variant.Type">
Variable is of type [Array].
</constant>
- <constant name="TYPE_PACKED_BYTE_ARRAY" value="26" enum="Variant.Type">
+ <constant name="TYPE_PACKED_BYTE_ARRAY" value="29" enum="Variant.Type">
Variable is of type [PackedByteArray].
</constant>
- <constant name="TYPE_PACKED_INT32_ARRAY" value="27" enum="Variant.Type">
+ <constant name="TYPE_PACKED_INT32_ARRAY" value="30" enum="Variant.Type">
Variable is of type [PackedInt32Array].
</constant>
- <constant name="TYPE_PACKED_INT64_ARRAY" value="28" enum="Variant.Type">
+ <constant name="TYPE_PACKED_INT64_ARRAY" value="31" enum="Variant.Type">
Variable is of type [PackedInt64Array].
</constant>
- <constant name="TYPE_PACKED_FLOAT32_ARRAY" value="29" enum="Variant.Type">
+ <constant name="TYPE_PACKED_FLOAT32_ARRAY" value="32" enum="Variant.Type">
Variable is of type [PackedFloat32Array].
</constant>
- <constant name="TYPE_PACKED_FLOAT64_ARRAY" value="30" enum="Variant.Type">
+ <constant name="TYPE_PACKED_FLOAT64_ARRAY" value="33" enum="Variant.Type">
Variable is of type [PackedFloat64Array].
</constant>
- <constant name="TYPE_PACKED_STRING_ARRAY" value="31" enum="Variant.Type">
+ <constant name="TYPE_PACKED_STRING_ARRAY" value="34" enum="Variant.Type">
Variable is of type [PackedStringArray].
</constant>
- <constant name="TYPE_PACKED_VECTOR2_ARRAY" value="32" enum="Variant.Type">
+ <constant name="TYPE_PACKED_VECTOR2_ARRAY" value="35" enum="Variant.Type">
Variable is of type [PackedVector2Array].
</constant>
- <constant name="TYPE_PACKED_VECTOR3_ARRAY" value="33" enum="Variant.Type">
+ <constant name="TYPE_PACKED_VECTOR3_ARRAY" value="36" enum="Variant.Type">
Variable is of type [PackedVector3Array].
</constant>
- <constant name="TYPE_PACKED_COLOR_ARRAY" value="34" enum="Variant.Type">
+ <constant name="TYPE_PACKED_COLOR_ARRAY" value="37" enum="Variant.Type">
Variable is of type [PackedColorArray].
</constant>
- <constant name="TYPE_MAX" value="35" enum="Variant.Type">
+ <constant name="TYPE_MAX" value="38" enum="Variant.Type">
Represents the size of the [enum Variant.Type] enum.
</constant>
<constant name="OP_EQUAL" value="0" enum="Variant.Operator">
diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml
index c1e28ffba3..0009c82548 100644
--- a/doc/classes/AcceptDialog.xml
+++ b/doc/classes/AcceptDialog.xml
@@ -62,6 +62,7 @@
Sets autowrapping for the text in the dialog.
</member>
<member name="dialog_close_on_escape" type="bool" setter="set_close_on_escape" getter="get_close_on_escape" default="true">
+ If [code]true[/code], the dialog will be hidden when the escape key ([constant @GlobalScope.KEY_ESCAPE]) is pressed.
</member>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" default="true">
If [code]true[/code], the dialog is hidden when the OK button is pressed. You can set it to [code]false[/code] if you want to do e.g. input validation when receiving the [signal confirmed] signal, and handle hiding the dialog in your own logic.
@@ -71,6 +72,9 @@
The text displayed by the dialog.
</member>
<member name="exclusive" type="bool" setter="set_exclusive" getter="is_exclusive" overrides="Window" default="true" />
+ <member name="ok_button_text" type="String" setter="set_ok_button_text" getter="get_ok_button_text" default="&quot;OK&quot;">
+ The text displayed by the OK button (see [method get_ok_button]).
+ </member>
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default="&quot;Alert!&quot;" />
<member name="transient" type="bool" setter="set_transient" getter="is_transient" overrides="Window" default="true" />
<member name="visible" type="bool" setter="set_visible" getter="is_visible" overrides="Window" default="false" />
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index a92b237624..f40f11944d 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -391,13 +391,13 @@
</description>
</method>
<method name="track_insert_key">
- <return type="void" />
+ <return type="int" />
<argument index="0" name="track_idx" type="int" />
<argument index="1" name="time" type="float" />
<argument index="2" name="key" type="Variant" />
<argument index="3" name="transition" type="float" default="1" />
<description>
- Insert a generic key in a given track.
+ Inserts a generic key in a given track. Returns the key index.
</description>
</method>
<method name="track_is_compressed" qualifiers="const">
diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml
index 9026aa6a34..189e30b5f2 100644
--- a/doc/classes/AnimationNode.xml
+++ b/doc/classes/AnimationNode.xml
@@ -88,7 +88,7 @@
<argument index="3" name="seek_root" type="bool" />
<argument index="4" name="blend" type="float" />
<argument index="5" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" />
- <argument index="6" name="optimize" type="bool" default="true" />
+ <argument index="6" name="sync" type="bool" default="true" />
<description>
Blend an input. This is only useful for nodes created for an [AnimationNodeBlendTree]. The [code]time[/code] parameter is a relative delta, unless [code]seek[/code] is [code]true[/code], in which case it is absolute. A filter mode may be optionally passed (see [enum FilterAction] for options).
</description>
@@ -102,7 +102,7 @@
<argument index="4" name="seek_root" type="bool" />
<argument index="5" name="blend" type="float" />
<argument index="6" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" />
- <argument index="7" name="optimize" type="bool" default="true" />
+ <argument index="7" name="sync" type="bool" default="true" />
<description>
Blend another animation node (in case this node contains children animation nodes). This function is only useful if you inherit from [AnimationRootNode] instead, else editors will not display your node for addition.
</description>
diff --git a/doc/classes/AnimationNodeAdd2.xml b/doc/classes/AnimationNodeAdd2.xml
index ca117e3ecd..e6ac1dd963 100644
--- a/doc/classes/AnimationNodeAdd2.xml
+++ b/doc/classes/AnimationNodeAdd2.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimationNodeAdd2" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="AnimationNodeAdd2" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Blends two animations additively inside of an [AnimationNodeBlendTree].
</brief_description>
@@ -9,9 +9,4 @@
<tutorials>
<link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link>
</tutorials>
- <members>
- <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
- If [code]true[/code], sets the [code]optimization[/code] to [code]false[/code] when calling [method AnimationNode.blend_input], forcing the blended animations to update every frame.
- </member>
- </members>
</class>
diff --git a/doc/classes/AnimationNodeAdd3.xml b/doc/classes/AnimationNodeAdd3.xml
index 91e030a6ae..f290032e11 100644
--- a/doc/classes/AnimationNodeAdd3.xml
+++ b/doc/classes/AnimationNodeAdd3.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimationNodeAdd3" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="AnimationNodeAdd3" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Blends two of three animations additively inside of an [AnimationNodeBlendTree].
</brief_description>
@@ -14,9 +14,4 @@
<link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link>
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
- <members>
- <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
- If [code]true[/code], sets the [code]optimization[/code] to [code]false[/code] when calling [method AnimationNode.blend_input], forcing the blended animations to update every frame.
- </member>
- </members>
</class>
diff --git a/doc/classes/AnimationNodeBlend2.xml b/doc/classes/AnimationNodeBlend2.xml
index f17163e155..5001e3ba24 100644
--- a/doc/classes/AnimationNodeBlend2.xml
+++ b/doc/classes/AnimationNodeBlend2.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimationNodeBlend2" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="AnimationNodeBlend2" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Blends two animations linearly inside of an [AnimationNodeBlendTree].
</brief_description>
@@ -11,9 +11,4 @@
<link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link>
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
- <members>
- <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
- If [code]true[/code], sets the [code]optimization[/code] to [code]false[/code] when calling [method AnimationNode.blend_input], forcing the blended animations to update every frame.
- </member>
- </members>
</class>
diff --git a/doc/classes/AnimationNodeBlend3.xml b/doc/classes/AnimationNodeBlend3.xml
index 6bc7a20823..93947c2462 100644
--- a/doc/classes/AnimationNodeBlend3.xml
+++ b/doc/classes/AnimationNodeBlend3.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimationNodeBlend3" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="AnimationNodeBlend3" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Blends two of three animations linearly inside of an [AnimationNodeBlendTree].
</brief_description>
@@ -13,9 +13,4 @@
<tutorials>
<link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link>
</tutorials>
- <members>
- <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
- If [code]true[/code], sets the [code]optimization[/code] to [code]false[/code] when calling [method AnimationNode.blend_input], forcing the blended animations to update every frame.
- </member>
- </members>
</class>
diff --git a/doc/classes/AnimationNodeBlendSpace1D.xml b/doc/classes/AnimationNodeBlendSpace1D.xml
index 6ded3a7ff9..7bb136308d 100644
--- a/doc/classes/AnimationNodeBlendSpace1D.xml
+++ b/doc/classes/AnimationNodeBlendSpace1D.xml
@@ -76,6 +76,10 @@
<member name="snap" type="float" setter="set_snap" getter="get_snap" default="0.1">
Position increment to snap to when moving a point on the axis.
</member>
+ <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
+ If [code]false[/code], the blended animations' frame are stopped when the blend value is [code]0[/code].
+ If [code]true[/code], forcing the blended animations to advance frame.
+ </member>
<member name="value_label" type="String" setter="set_value_label" getter="get_value_label" default="&quot;value&quot;">
Label of the virtual axis of the blend space.
</member>
diff --git a/doc/classes/AnimationNodeBlendSpace2D.xml b/doc/classes/AnimationNodeBlendSpace2D.xml
index 9e0e408ac5..eb2249d2d2 100644
--- a/doc/classes/AnimationNodeBlendSpace2D.xml
+++ b/doc/classes/AnimationNodeBlendSpace2D.xml
@@ -113,6 +113,10 @@
<member name="snap" type="Vector2" setter="set_snap" getter="get_snap" default="Vector2(0.1, 0.1)">
Position increment to snap to when moving a point.
</member>
+ <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
+ If [code]false[/code], the blended animations' frame are stopped when the blend value is [code]0[/code].
+ If [code]true[/code], forcing the blended animations to advance frame.
+ </member>
<member name="x_label" type="String" setter="set_x_label" getter="get_x_label" default="&quot;x&quot;">
Name of the blend space's X axis.
</member>
diff --git a/doc/classes/AnimationNodeOneShot.xml b/doc/classes/AnimationNodeOneShot.xml
index de2414cd43..14abc34992 100644
--- a/doc/classes/AnimationNodeOneShot.xml
+++ b/doc/classes/AnimationNodeOneShot.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimationNodeOneShot" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="AnimationNodeOneShot" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Plays an animation once in [AnimationNodeBlendTree].
</brief_description>
@@ -26,8 +26,6 @@
</member>
<member name="mix_mode" type="int" setter="set_mix_mode" getter="get_mix_mode" enum="AnimationNodeOneShot.MixMode" default="0">
</member>
- <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
- </member>
</members>
<constants>
<constant name="MIX_MODE_BLEND" value="0" enum="MixMode">
diff --git a/doc/classes/AnimationNodeStateMachineTransition.xml b/doc/classes/AnimationNodeStateMachineTransition.xml
index 206164d675..0badb831de 100644
--- a/doc/classes/AnimationNodeStateMachineTransition.xml
+++ b/doc/classes/AnimationNodeStateMachineTransition.xml
@@ -23,7 +23,7 @@
Use an expression as a condition for state machine transitions. It is possible to create complex animation advance conditions for switching between states and gives much greater flexibility for creating complex state machines by directly interfacing with the script code.
</member>
<member name="advance_expression_base_node" type="NodePath" setter="set_advance_expression_base_node" getter="get_advance_expression_base_node" default="NodePath(&quot;&quot;)">
- The path to the [Node] used to evaluate an [Expression] if one is not explictly specified internally.
+ The path to the [Node] used to evaluate an [Expression] if one is not explicitly specified internally.
</member>
<member name="auto_advance" type="bool" setter="set_auto_advance" getter="has_auto_advance" default="false">
Turn on the transition automatically when this state is reached. This works best with [constant SWITCH_MODE_AT_END].
diff --git a/doc/classes/AnimationNodeSync.xml b/doc/classes/AnimationNodeSync.xml
new file mode 100644
index 0000000000..21cac11d50
--- /dev/null
+++ b/doc/classes/AnimationNodeSync.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="AnimationNodeSync" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
+ If [code]false[/code], the blended animations' frame are stopped when the blend value is [code]0[/code].
+ If [code]true[/code], forcing the blended animations to advance frame.
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/AnimationNodeTransition.xml b/doc/classes/AnimationNodeTransition.xml
index 70c874d251..7e757d4640 100644
--- a/doc/classes/AnimationNodeTransition.xml
+++ b/doc/classes/AnimationNodeTransition.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimationNodeTransition" inherits="AnimationNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="AnimationNodeTransition" inherits="AnimationNodeSync" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A generic animation transition node for [AnimationTree].
</brief_description>
@@ -40,6 +40,9 @@
</method>
</methods>
<members>
+ <member name="from_start" type="bool" setter="set_from_start" getter="is_from_start" default="true">
+ If [code]true[/code], the destination animation is played back from the beginning when switched.
+ </member>
<member name="input_count" type="int" setter="set_enabled_inputs" getter="get_enabled_inputs" default="0">
The number of available input ports for this node.
</member>
diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml
index 653607610d..d3c8bdac3a 100644
--- a/doc/classes/AnimationPlayer.xml
+++ b/doc/classes/AnimationPlayer.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AnimationPlayer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Container and player of [Animation] resources.
+ Player of [Animation] resources.
</brief_description>
<description>
- An animation player is used for general-purpose playback of [Animation] resources. It contains a dictionary of animations (referenced by name) and custom blend times between their transitions. Additionally, animations can be played and blended in different channels.
- [AnimationPlayer] is more suited than [Tween] for animations where you know the final values in advance. For example, fading a screen in and out is more easily done with an [AnimationPlayer] node thanks to the animation tools provided by the editor. That particular example can also be implemented with a [Tween] node, but it requires doing everything by code.
+ An animation player is used for general-purpose playback of [Animation] resources. It contains a dictionary of [AnimationLibrary] resources and custom blend times between animation transitions.
+ Some methods and properties use a single key to refence an animation directly. These keys are formatted as the key for the library, followed by a forward slash, then the key for the animation whithin the library, for example [code]"movement/run"[/code]. If the library's key is an empty string (known as the default library), the forward slash is omitted, being the same key used by the library.
+ [AnimationPlayer] is more suited than [Tween] for animations where you know the final values in advance. For example, fading a screen in and out is more easily done with an [AnimationPlayer] node thanks to the animation tools provided by the editor. That particular example can also be implemented with a [Tween], but it requires doing everything by code.
Updating the target properties of animations occurs at process time.
</description>
<tutorials>
@@ -19,6 +20,7 @@
<argument index="0" name="name" type="StringName" />
<argument index="1" name="library" type="AnimationLibrary" />
<description>
+ Adds [code]library[/code] to the animation player, under the key [code]name[/code].
</description>
</method>
<method name="advance">
@@ -32,7 +34,7 @@
<return type="StringName" />
<argument index="0" name="anim_from" type="StringName" />
<description>
- Returns the name of the next animation in the queue.
+ Returns the key of the animation which is queued to play after the [code]anim_from[/code] animation.
</description>
</method>
<method name="animation_set_next">
@@ -59,13 +61,14 @@
<return type="StringName" />
<argument index="0" name="animation" type="Animation" />
<description>
- Returns the name of [code]animation[/code] or an empty string if not found.
+ Returns the key of [code]animation[/code] or an empty [StringName] if not found.
</description>
</method>
<method name="find_animation_library" qualifiers="const">
<return type="StringName" />
<argument index="0" name="animation" type="Animation" />
<description>
+ Returns the key for the [AnimationLibrary] that contains [code]animation[/code] or an empty [StringName] if not found.
</description>
</method>
<method name="get_animation" qualifiers="const">
@@ -79,17 +82,19 @@
<return type="AnimationLibrary" />
<argument index="0" name="name" type="StringName" />
<description>
+ Returns the first [AnimationLibrary] with key [code]name[/code] or [code]null[/code] if not found.
</description>
</method>
<method name="get_animation_library_list" qualifiers="const">
<return type="StringName[]" />
<description>
+ Returns the list of stored library keys.
</description>
</method>
<method name="get_animation_list" qualifiers="const">
<return type="PackedStringArray" />
<description>
- Returns the list of stored animation names.
+ Returns the list of stored animation keys.
</description>
</method>
<method name="get_blend_time" qualifiers="const">
@@ -97,7 +102,7 @@
<argument index="0" name="anim_from" type="StringName" />
<argument index="1" name="anim_to" type="StringName" />
<description>
- Gets the blend time (in seconds) between two animations, referenced by their names.
+ Gets the blend time (in seconds) between two animations, referenced by their keys.
</description>
</method>
<method name="get_playing_speed" qualifiers="const">
@@ -109,7 +114,7 @@
<method name="get_queue">
<return type="PackedStringArray" />
<description>
- Returns a list of the animation names that are currently queued to play.
+ Returns a list of the animation keys that are currently queued to play.
</description>
</method>
<method name="has_animation" qualifiers="const">
@@ -123,6 +128,7 @@
<return type="bool" />
<argument index="0" name="name" type="StringName" />
<description>
+ Returns [code]true[/code] if the [AnimationPlayer] stores an [AnimationLibrary] with key [code]name[/code].
</description>
</method>
<method name="is_playing" qualifiers="const">
@@ -164,6 +170,7 @@
<return type="void" />
<argument index="0" name="name" type="StringName" />
<description>
+ Removes the [AnimationLibrary] assosiated with the key [code]name[/code].
</description>
</method>
<method name="rename_animation_library">
@@ -171,6 +178,7 @@
<argument index="0" name="name" type="StringName" />
<argument index="1" name="newname" type="StringName" />
<description>
+ Moves the [AnimationLibrary] associated with the key [code]name[/code] to the key [code]newname[/code].
</description>
</method>
<method name="seek">
@@ -188,7 +196,7 @@
<argument index="1" name="anim_to" type="StringName" />
<argument index="2" name="sec" type="float" />
<description>
- Specifies a blend time (in seconds) between two animations, referenced by their names.
+ Specifies a blend time (in seconds) between two animations, referenced by their keys.
</description>
</method>
<method name="stop">
@@ -202,17 +210,17 @@
</methods>
<members>
<member name="assigned_animation" type="String" setter="set_assigned_animation" getter="get_assigned_animation">
- If playing, the current animation; otherwise, the animation last played. When set, would change the animation, but would not play it unless currently playing. See also [member current_animation].
+ If playing, the the current animation's key, otherwise, the animation last played. When set, this changes the animation, but will not play it unless already playing. See also [member current_animation].
</member>
<member name="autoplay" type="String" setter="set_autoplay" getter="get_autoplay" default="&quot;&quot;">
- The name of the animation to play when the scene loads.
+ The key of the animation to play when the scene loads.
</member>
<member name="current_animation" type="String" setter="set_current_animation" getter="get_current_animation" default="&quot;&quot;">
- The name of the currently playing animation. If no animation is playing, the property's value is an empty string. Changing this value does not restart the animation. See [method play] for more information on playing animations.
+ The key of the currently playing animation. If no animation is playing, the property's value is an empty string. Changing this value does not restart the animation. See [method play] for more information on playing animations.
[b]Note:[/b] while this property appears in the inspector, it's not meant to be edited, and it's not saved in the scene. This property is mainly used to get the currently playing animation, and internally for animation playback tracks. For more information, see [Animation].
</member>
<member name="current_animation_length" type="float" setter="" getter="get_current_animation_length">
- The length (in seconds) of the currently being played animation.
+ The length (in seconds) of the currently playing animation.
</member>
<member name="current_animation_position" type="float" setter="" getter="get_current_animation_position">
The position (in seconds) of the currently playing animation.
@@ -220,6 +228,10 @@
<member name="method_call_mode" type="int" setter="set_method_call_mode" getter="get_method_call_mode" enum="AnimationPlayer.AnimationMethodCallMode" default="0">
The call mode to use for Call Method tracks.
</member>
+ <member name="movie_quit_on_finish" type="bool" setter="set_movie_quit_on_finish_enabled" getter="is_movie_quit_on_finish_enabled" default="false">
+ If [code]true[/code] and the engine is running in Movie Maker mode (see [MovieWriter]), exits the engine with [method SceneTree.quit] as soon as an animation is done playing in this [AnimationPlayer]. A message is printed when the engine quits for this reason.
+ [b]Note:[/b] This obeys the same logic as the [signal animation_finished] signal, so it will not quit the engine if the animation is set to be looping.
+ </member>
<member name="playback_active" type="bool" setter="set_active" getter="is_active">
If [code]true[/code], updates animations in response to process-related notifications.
</member>
@@ -233,8 +245,8 @@
The speed scaling ratio. For instance, if this value is 1, then the animation plays at normal speed. If it's 0.5, then it plays at half speed. If it's 2, then it plays at double speed.
</member>
<member name="reset_on_save" type="bool" setter="set_reset_on_save_enabled" getter="is_reset_on_save_enabled" default="true">
- This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation applied (as if it had been seeked to time 0), then reverted after saving.
- In other words, the saved scene file will contain the "default pose", as defined by the reset animation, if any, with the editor keeping the values that the nodes had before saving.
+ This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation (the animation with the key [code]"RESET"[/code]) applied as if it had been seeked to time 0, with the editor keeping the values that the scene had before saving.
+ This makes it more convenient to preview and edit animations in the editor, as changes to the scene will not be saved as long as they are set in the reset animation.
</member>
<member name="root_node" type="NodePath" setter="set_root" getter="get_root" default="NodePath(&quot;..&quot;)">
The node from which node path references will travel.
@@ -245,14 +257,15 @@
<argument index="0" name="old_name" type="StringName" />
<argument index="1" name="new_name" type="StringName" />
<description>
- Emitted when a queued animation plays after the previous animation was finished. See [method queue].
- [b]Note:[/b] The signal is not emitted when the animation is changed via [method play] or from [AnimationTree].
+ Emitted when a queued animation plays after the previous animation finished. See [method queue].
+ [b]Note:[/b] The signal is not emitted when the animation is changed via [method play] or by an [AnimationTree].
</description>
</signal>
<signal name="animation_finished">
<argument index="0" name="anim_name" type="StringName" />
<description>
Notifies when an animation finished playing.
+ [b]Note:[/b] This signal is not emitted if an animation is looping.
</description>
</signal>
<signal name="animation_started">
diff --git a/doc/classes/AnimationTree.xml b/doc/classes/AnimationTree.xml
index ecac228a26..45d9152564 100644
--- a/doc/classes/AnimationTree.xml
+++ b/doc/classes/AnimationTree.xml
@@ -38,7 +38,7 @@
If [code]true[/code], the [AnimationTree] will be processing.
</member>
<member name="advance_expression_base_node" type="NodePath" setter="set_advance_expression_base_node" getter="get_advance_expression_base_node" default="NodePath(&quot;.&quot;)">
- The path to the [Node] used to evaluate the AnimationNode [Expression] if one is not explictly specified internally.
+ The path to the [Node] used to evaluate the AnimationNode [Expression] if one is not explicitly specified internally.
</member>
<member name="anim_player" type="NodePath" setter="set_animation_player" getter="get_animation_player" default="NodePath(&quot;&quot;)">
The path to the [AnimationPlayer] used for animating.
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index 0f2dd6587a..f5c799d4de 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -67,7 +67,7 @@
<description>
Creates a new surface.
Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines, or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface.
- The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used.
+ The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array (or be an exact multiple of the vertex array's length, when multiple elements of a sub-array correspond to a single vertex) or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used.
</description>
</method>
<method name="clear_blend_shapes">
diff --git a/doc/classes/AudioEffectRecord.xml b/doc/classes/AudioEffectRecord.xml
index 9728011bb2..32a6aea340 100644
--- a/doc/classes/AudioEffectRecord.xml
+++ b/doc/classes/AudioEffectRecord.xml
@@ -14,7 +14,7 @@
</tutorials>
<methods>
<method name="get_recording" qualifiers="const">
- <return type="AudioStreamSample" />
+ <return type="AudioStreamWAV" />
<description>
Returns the recorded sample.
</description>
@@ -34,8 +34,8 @@
</method>
</methods>
<members>
- <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamSample.Format" default="1">
- Specifies the format in which the sample will be recorded. See [enum AudioStreamSample.Format] for available formats.
+ <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamWAV.Format" default="1">
+ Specifies the format in which the sample will be recorded. See [enum AudioStreamWAV.Format] for available formats.
</member>
</members>
</class>
diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml
index 1e076654fb..28dcd2794e 100644
--- a/doc/classes/AudioServer.xml
+++ b/doc/classes/AudioServer.xml
@@ -275,6 +275,12 @@
Sets the volume of the bus at index [code]bus_idx[/code] to [code]volume_db[/code].
</description>
</method>
+ <method name="set_enable_tagging_used_audio_streams">
+ <return type="void" />
+ <argument index="0" name="enable" type="bool" />
+ <description>
+ </description>
+ </method>
<method name="swap_bus_effects">
<return type="void" />
<argument index="0" name="bus_idx" type="int" />
diff --git a/doc/classes/AudioStream.xml b/doc/classes/AudioStream.xml
index 6343da6eed..7645cafe86 100644
--- a/doc/classes/AudioStream.xml
+++ b/doc/classes/AudioStream.xml
@@ -4,7 +4,7 @@
Base class for audio streams.
</brief_description>
<description>
- Base class for audio streams. Audio streams are used for sound effects and music playback, and support WAV (via [AudioStreamSample]) and OGG (via [AudioStreamOGGVorbis]) file formats.
+ Base class for audio streams. Audio streams are used for sound effects and music playback, and support WAV (via [AudioStreamWAV]) and Ogg (via [AudioStreamOggVorbis]) file formats.
</description>
<tutorials>
<link title="Audio streams">$DOCS_URL/tutorials/audio/audio_streams.html</link>
@@ -13,6 +13,16 @@
<link title="Audio Spectrum Demo">https://godotengine.org/asset-library/asset/528</link>
</tutorials>
<methods>
+ <method name="_get_beat_count" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_bpm" qualifiers="virtual const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
<method name="_get_length" qualifiers="virtual const">
<return type="float" />
<description>
@@ -23,7 +33,7 @@
<description>
</description>
</method>
- <method name="_instance_playback" qualifiers="virtual const">
+ <method name="_instantiate_playback" qualifiers="virtual const">
<return type="AudioStreamPlayback" />
<description>
</description>
@@ -39,10 +49,10 @@
Returns the length of the audio stream in seconds.
</description>
</method>
- <method name="instance_playback">
+ <method name="instantiate_playback">
<return type="AudioStreamPlayback" />
<description>
- Returns an AudioStreamPlayback. Useful for when you want to extend `_instance_playback` but call `instance_playback` from an internally held AudioStream subresource. An example of this can be found in the source files for `AudioStreamRandomPitch::instance_playback`.
+ Returns an AudioStreamPlayback. Useful for when you want to extend [method _instantiate_playback] but call [method instantiate_playback] from an internally held AudioStream subresource. An example of this can be found in the source files for [code]AudioStreamRandomPitch::instantiate_playback[/code].
</description>
</method>
<method name="is_monophonic" qualifiers="const">
diff --git a/doc/classes/AudioStreamPlayback.xml b/doc/classes/AudioStreamPlayback.xml
index 1909c4b621..f1a1c18c1c 100644
--- a/doc/classes/AudioStreamPlayback.xml
+++ b/doc/classes/AudioStreamPlayback.xml
@@ -4,7 +4,7 @@
Meta class for playing back audio.
</brief_description>
<description>
- Can play, loop, pause a scroll through audio. See [AudioStream] and [AudioStreamOGGVorbis] for usage.
+ Can play, loop, pause a scroll through audio. See [AudioStream] and [AudioStreamOggVorbis] for usage.
</description>
<tutorials>
<link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link>
@@ -50,5 +50,10 @@
<description>
</description>
</method>
+ <method name="_tag_used_streams" qualifiers="virtual">
+ <return type="void" />
+ <description>
+ </description>
+ </method>
</methods>
</class>
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/AudioStreamSample.xml b/doc/classes/AudioStreamWAV.xml
index 62f27ce876..17595aec2f 100644
--- a/doc/classes/AudioStreamSample.xml
+++ b/doc/classes/AudioStreamWAV.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamSample" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="AudioStreamWAV" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Stores audio data loaded from WAV files.
</brief_description>
<description>
- AudioStreamSample stores sound samples loaded from WAV files. To play the stored sound, use an [AudioStreamPlayer] (for non-positional audio) or [AudioStreamPlayer2D]/[AudioStreamPlayer3D] (for positional audio). The sound can be looped.
+ AudioStreamWAV stores sound samples loaded from WAV files. To play the stored sound, use an [AudioStreamPlayer] (for non-positional audio) or [AudioStreamPlayer2D]/[AudioStreamPlayer3D] (for positional audio). The sound can be looped.
This class can also be used to store dynamically-generated PCM audio data. See also [AudioStreamGenerator] for procedural audio generation.
</description>
<tutorials>
@@ -14,7 +14,7 @@
<return type="int" enum="Error" />
<argument index="0" name="path" type="String" />
<description>
- Saves the AudioStreamSample as a WAV file to [code]path[/code]. Samples with IMA ADPCM format can't be saved.
+ Saves the AudioStreamWAV as a WAV file to [code]path[/code]. Samples with IMA ADPCM format can't be saved.
[b]Note:[/b] A [code].wav[/code] extension is automatically appended to [code]path[/code] if it is missing.
</description>
</method>
@@ -24,7 +24,7 @@
Contains the audio data in bytes.
[b]Note:[/b] This property expects signed PCM8 data. To convert unsigned PCM8 to signed PCM8, subtract 128 from each byte.
</member>
- <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamSample.Format" default="0">
+ <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamWAV.Format" default="0">
Audio format. See [enum Format] constants for values.
</member>
<member name="loop_begin" type="int" setter="set_loop_begin" getter="get_loop_begin" default="0">
@@ -33,7 +33,7 @@
<member name="loop_end" type="int" setter="set_loop_end" getter="get_loop_end" default="0">
The loop end point (in number of samples, relative to the beginning of the sample). This information will be imported automatically from the WAV file if present.
</member>
- <member name="loop_mode" type="int" setter="set_loop_mode" getter="get_loop_mode" enum="AudioStreamSample.LoopMode" default="0">
+ <member name="loop_mode" type="int" setter="set_loop_mode" getter="get_loop_mode" enum="AudioStreamWAV.LoopMode" default="0">
The loop mode. This information will be imported automatically from the WAV file if present. See [enum LoopMode] constants for values.
</member>
<member name="mix_rate" type="int" setter="set_mix_rate" getter="get_mix_rate" default="44100">
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index d3ae85101d..d0290ff5fd 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -218,30 +218,44 @@
Grows object vertices in the direction of their normals.
</member>
<member name="heightmap_deep_parallax" type="bool" setter="set_heightmap_deep_parallax" getter="is_heightmap_deep_parallax_enabled" default="false">
+ If [code]true[/code], uses parallax occlusion mapping to represent depth in the material instead of simple offset mapping (see [member heightmap_enabled]). This results in a more convincing depth effect, but is much more expensive on the GPU. Only enable this on materials where it makes a significant visual difference.
</member>
<member name="heightmap_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
- If [code]true[/code], height mapping is enabled (also called "parallax mapping" or "depth mapping"). See also [member normal_enabled].
+ If [code]true[/code], height mapping is enabled (also called "parallax mapping" or "depth mapping"). See also [member normal_enabled]. Height mapping is a demanding feature on the GPU, so it should only be used on materials where it makes a significant visual difference.
[b]Note:[/b] Height mapping is not supported if triplanar mapping is used on the same material. The value of [member heightmap_enabled] will be ignored if [member uv1_triplanar] is enabled.
</member>
<member name="heightmap_flip_binormal" type="bool" setter="set_heightmap_deep_parallax_flip_binormal" getter="get_heightmap_deep_parallax_flip_binormal" default="false">
+ If [code]true[/code], flips the mesh's binormal vectors when interpreting the height map. If the heightmap effect looks strange when the camera moves (even with a reasonable [member heightmap_scale]), try setting this to [code]true[/code].
</member>
<member name="heightmap_flip_tangent" type="bool" setter="set_heightmap_deep_parallax_flip_tangent" getter="get_heightmap_deep_parallax_flip_tangent" default="false">
+ If [code]true[/code], flips the mesh's tangent vectors when interpreting the height map. If the heightmap effect looks strange when the camera moves (even with a reasonable [member heightmap_scale]), try setting this to [code]true[/code].
</member>
<member name="heightmap_flip_texture" type="bool" setter="set_flag" getter="get_flag" default="false">
+ If [code]true[/code], interprets the height map texture as a depth map, with brighter values appearing to be "lower" in altitude compared to darker values.
+ This can be enabled for compatibility with some materials authored for Godot 3.x. This is not necessary if the Invert import option was used to invert the depth map in Godot 3.x, in which case [member heightmap_flip_texture] should remain [code]false[/code].
</member>
<member name="heightmap_max_layers" type="int" setter="set_heightmap_deep_parallax_max_layers" getter="get_heightmap_deep_parallax_max_layers">
+ The number of layers to use for parallax occlusion mapping when the camera is up close to the material. Higher values result in a more convincing depth effect, especially in materials that have steep height changes. Higher values have a significant cost on the GPU, so it should only be increased on materials where it makes a significant visual difference.
+ [b]Note:[/b] Only effective if [member heightmap_deep_parallax] is [code]true[/code].
</member>
<member name="heightmap_min_layers" type="int" setter="set_heightmap_deep_parallax_min_layers" getter="get_heightmap_deep_parallax_min_layers">
+ The number of layers to use for parallax occlusion mapping when the camera is far away from the material. Higher values result in a more convincing depth effect, especially in materials that have steep height changes. Higher values have a significant cost on the GPU, so it should only be increased on materials where it makes a significant visual difference.
+ [b]Note:[/b] Only effective if [member heightmap_deep_parallax] is [code]true[/code].
</member>
- <member name="heightmap_scale" type="float" setter="set_heightmap_scale" getter="get_heightmap_scale" default="0.05">
+ <member name="heightmap_scale" type="float" setter="set_heightmap_scale" getter="get_heightmap_scale" default="5.0">
+ The heightmap scale to use for the parallax effect (see [member heightmap_enabled]). The default value is tuned so that the highest point (value = 255) appears to be 5 cm higher than the lowest point (value = 0). Higher values result in a deeper appearance, but may result in artifacts appearing when looking at the material from oblique angles, especially when the camera moves. Negative values can be used to invert the parallax effect, but this is different from inverting the texture using [member heightmap_flip_texture] as the material will also appear to be "closer" to the camera. In most cases, [member heightmap_scale] should be kept to a positive value.
+ [b]Note:[/b] If the height map effect looks strange regardless of this value, try adjusting [member heightmap_flip_binormal] and [member heightmap_flip_tangent]. See also [member heightmap_texture] for recommendations on authoring heightmap textures, as the way the heightmap texture is authored affects how [member heightmap_scale] behaves.
</member>
<member name="heightmap_texture" type="Texture2D" setter="set_texture" getter="get_texture">
+ The texture to use as a height map. See also [member heightmap_enabled].
+ For best results, the texture should be normalized (with [member heightmap_scale] reduced to compensate). In [url=https://gimp.org]GIMP[/url], this can be done using [b]Colors &gt; Auto &gt; Equalize[/b]. If the texture only uses a small part of its available range, the parallax effect may look strange, especially when the camera moves.
+ [b]Note:[/b] To reduce memory usage and improve loading times, you may be able to use a lower-resolution heightmap texture as most heightmaps are only comprised of low-frequency data.
</member>
<member name="metallic" type="float" setter="set_metallic" getter="get_metallic" default="0.0">
A high value makes the material appear more like a metal. Non-metals use their albedo as the diffuse color and add diffuse to the specular reflection. With non-metals, the reflection appears on top of the albedo color. Metals use their albedo as a multiplier to the specular reflection and set the diffuse color to black resulting in a tinted reflection. Materials work better when fully metal or fully non-metal, values between [code]0[/code] and [code]1[/code] should only be used for blending between metal and non-metal sections. To alter the amount of reflection use [member roughness].
</member>
<member name="metallic_specular" type="float" setter="set_specular" getter="get_specular" default="0.5">
- Sets the size of the specular lobe. The specular lobe is the bright spot that is reflected from light sources.
+ Adjusts the strength of specular reflections. Specular reflections are composed of scene reflections and the specular lobe which is the bright spot that is reflected from light sources. When set to [code]0.0[/code], no specular reflections will be visible. This differs from the [constant SPECULAR_DISABLED] [enum SpecularMode] as [constant SPECULAR_DISABLED] only applies to the specular lobe from the light source.
[b]Note:[/b] Unlike [member metallic], this is not energy-conserving, so it should be left at [code]0.5[/code] in most cases. See also [member roughness].
</member>
<member name="metallic_texture" type="Texture2D" setter="set_texture" getter="get_texture">
@@ -374,10 +388,10 @@
[b]Note:[/b] This is only effective for objects whose geometry is point-based rather than triangle-based. See also [member point_size].
</member>
<member name="uv1_offset" type="Vector3" setter="set_uv1_offset" getter="get_uv1_offset" default="Vector3(0, 0, 0)">
- How much to offset the [code]UV[/code] coordinates. This amount will be added to [code]UV[/code] in the vertex function. This can be used to offset a texture.
+ How much to offset the [code]UV[/code] coordinates. This amount will be added to [code]UV[/code] in the vertex function. This can be used to offset a texture. The Z component is used when [member uv1_triplanar] is enabled, but it is not used anywhere else.
</member>
<member name="uv1_scale" type="Vector3" setter="set_uv1_scale" getter="get_uv1_scale" default="Vector3(1, 1, 1)">
- How much to scale the [code]UV[/code] coordinates. This is multiplied by [code]UV[/code] in the vertex function.
+ How much to scale the [code]UV[/code] coordinates. This is multiplied by [code]UV[/code] in the vertex function. The Z component is used when [member uv1_triplanar] is enabled, but it is not used anywhere else.
</member>
<member name="uv1_triplanar" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], instead of using [code]UV[/code] textures will use a triplanar texture lookup to determine how to apply textures. Triplanar uses the orientation of the object's surface to blend between texture coordinates. It reads from the source texture 3 times, once for each axis and then blends between the results based on how closely the pixel aligns with each axis. This is often used for natural features to get a realistic blend of materials. Because triplanar texturing requires many more texture reads per-pixel it is much slower than normal UV texturing. Additionally, because it is blending the texture between the three axes, it is unsuitable when you are trying to achieve crisp texturing.
@@ -389,10 +403,10 @@
If [code]true[/code], triplanar mapping for [code]UV[/code] is calculated in world space rather than object local space. See also [member uv1_triplanar].
</member>
<member name="uv2_offset" type="Vector3" setter="set_uv2_offset" getter="get_uv2_offset" default="Vector3(0, 0, 0)">
- How much to offset the [code]UV2[/code] coordinates. This amount will be added to [code]UV2[/code] in the vertex function. This can be used to offset a texture.
+ How much to offset the [code]UV2[/code] coordinates. This amount will be added to [code]UV2[/code] in the vertex function. This can be used to offset a texture. The Z component is used when [member uv2_triplanar] is enabled, but it is not used anywhere else.
</member>
<member name="uv2_scale" type="Vector3" setter="set_uv2_scale" getter="get_uv2_scale" default="Vector3(1, 1, 1)">
- How much to scale the [code]UV2[/code] coordinates. This is multiplied by [code]UV2[/code] in the vertex function.
+ How much to scale the [code]UV2[/code] coordinates. This is multiplied by [code]UV2[/code] in the vertex function. The Z component is used when [member uv2_triplanar] is enabled, but it is not used anywhere else.
</member>
<member name="uv2_triplanar" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], instead of using [code]UV2[/code] textures will use a triplanar texture lookup to determine how to apply textures. Triplanar uses the orientation of the object's surface to blend between texture coordinates. It reads from the source texture 3 times, once for each axis and then blends between the results based on how closely the pixel aligns with each axis. This is often used for natural features to get a realistic blend of materials. Because triplanar texturing requires many more texture reads per-pixel it is much slower than normal UV texturing. Additionally, because it is blending the texture between the three axes, it is unsuitable when you are trying to achieve crisp texturing.
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/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml
index dacdca1cee..b0282e4107 100644
--- a/doc/classes/CPUParticles2D.xml
+++ b/doc/classes/CPUParticles2D.xml
@@ -192,8 +192,8 @@
</member>
<member name="linear_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
</member>
- <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="true">
- If [code]true[/code], particles use the parent node's coordinate space. If [code]false[/code], they use global coordinates.
+ <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="false">
+ If [code]true[/code], particles use the parent node's coordinate space (known as local coordinates). This will cause particles to move and rotate along the [CPUParticles2D] node (and its parents) when it is moved or rotated. If [code]false[/code], particles use global coordinates; they will not move or rotate along the [CPUParticles2D] node (and its parents) when it is moved or rotated.
</member>
<member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot" default="false">
If [code]true[/code], only one emission cycle occurs. If set [code]true[/code] during a cycle, emission will stop at the cycle's end.
diff --git a/doc/classes/CPUParticles3D.xml b/doc/classes/CPUParticles3D.xml
index f2a0040ed4..d8faf8e91d 100644
--- a/doc/classes/CPUParticles3D.xml
+++ b/doc/classes/CPUParticles3D.xml
@@ -224,8 +224,8 @@
<member name="linear_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
Minimum linear acceleration.
</member>
- <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="true">
- If [code]true[/code], particles use the parent node's coordinate space. If [code]false[/code], they use global coordinates.
+ <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="false">
+ If [code]true[/code], particles use the parent node's coordinate space (known as local coordinates). This will cause particles to move and rotate along the [CPUParticles3D] node (and its parents) when it is moved or rotated. If [code]false[/code], particles use global coordinates; they will not move or rotate along the [CPUParticles3D] node (and its parents) when it is moved or rotated.
</member>
<member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh">
The [Mesh] used for each particle. If [code]null[/code], particles will be spheres.
diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml
index 56e5ce1522..643351efc0 100644
--- a/doc/classes/Camera3D.xml
+++ b/doc/classes/Camera3D.xml
@@ -113,7 +113,7 @@
<argument index="2" name="z_near" type="float" />
<argument index="3" name="z_far" type="float" />
<description>
- Sets the camera projection to frustum mode (see [constant PROJECTION_FRUSTUM]), by specifying a [code]size[/code], an [code]offset[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units.
+ Sets the camera projection to frustum mode (see [constant PROJECTION_FRUSTUM]), by specifying a [code]size[/code], an [code]offset[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units. See also [member frustum_offset].
</description>
</method>
<method name="set_orthogonal">
@@ -144,7 +144,7 @@
# This code block is part of a script that inherits from Node3D.
# `control` is a reference to a node inheriting from Control.
control.visible = not get_viewport().get_camera_3d().is_position_behind(global_transform.origin)
- control.rect_position = get_viewport().get_camera_3d().unproject_position(global_transform.origin)
+ control.position = get_viewport().get_camera_3d().unproject_position(global_transform.origin)
[/codeblock]
</description>
</method>
@@ -155,6 +155,7 @@
</member>
<member name="current" type="bool" setter="set_current" getter="is_current" default="false">
If [code]true[/code], the ancestor [Viewport] is currently using this camera.
+ If multiple cameras are in the scene, one will always be made current. For example, if two [Camera3D] nodes are present in the scene and only one is current, setting one camera's [member current] to [code]false[/code] will cause the other camera to be made current.
</member>
<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="Camera3D.DopplerTracking" default="0">
If not [constant DOPPLER_TRACKING_DISABLED], this camera will simulate the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] for objects changed in particular [code]_process[/code] methods. See [enum DopplerTracking] for possible values.
@@ -178,6 +179,7 @@
</member>
<member name="frustum_offset" type="Vector2" setter="set_frustum_offset" getter="get_frustum_offset" default="Vector2(0, 0)">
The camera's frustum offset. This can be changed from the default to create "tilted frustum" effects such as [url=https://zdoom.org/wiki/Y-shearing]Y-shearing[/url].
+ [b]Note:[/b] Only effective if [member projection] is [constant PROJECTION_FRUSTUM].
</member>
<member name="h_offset" type="float" setter="set_h_offset" getter="get_h_offset" default="0.0">
The horizontal (X) offset of the camera viewport.
@@ -188,7 +190,7 @@
<member name="near" type="float" setter="set_near" getter="get_near" default="0.05">
The distance to the near culling boundary for this camera relative to its local Z axis.
</member>
- <member name="projection" type="int" setter="set_projection" getter="get_projection" enum="Camera3D.Projection" default="0">
+ <member name="projection" type="int" setter="set_projection" getter="get_projection" enum="Camera3D.ProjectionType" default="0">
The camera's projection mode. In [constant PROJECTION_PERSPECTIVE] mode, objects' Z distance from the camera's local space scales their perceived size.
</member>
<member name="size" type="float" setter="set_size" getter="get_size" default="1.0">
@@ -199,13 +201,13 @@
</member>
</members>
<constants>
- <constant name="PROJECTION_PERSPECTIVE" value="0" enum="Projection">
+ <constant name="PROJECTION_PERSPECTIVE" value="0" enum="ProjectionType">
Perspective projection. Objects on the screen becomes smaller when they are far away.
</constant>
- <constant name="PROJECTION_ORTHOGONAL" value="1" enum="Projection">
+ <constant name="PROJECTION_ORTHOGONAL" value="1" enum="ProjectionType">
Orthogonal projection, also known as orthographic projection. Objects remain the same size on the screen no matter how far away they are.
</constant>
- <constant name="PROJECTION_FRUSTUM" value="2" enum="Projection">
+ <constant name="PROJECTION_FRUSTUM" value="2" enum="ProjectionType">
Frustum projection. This mode allows adjusting [member frustum_offset] to create "tilted frustum" effects.
</constant>
<constant name="KEEP_WIDTH" value="0" enum="KeepAspect">
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 98a498d719..2d68ae6902 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,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="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" />
+ <argument index="9" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" />
+ <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 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="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" />
+ <argument index="10" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" />
+ <argument index="11" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="12" 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 +279,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="jst_flags" type="int" enum="TextServer.JustificationFlag" 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 +308,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="jst_flags" type="int" enum="TextServer.JustificationFlag" 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/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml
index 6c5cd62fe1..795bd7a429 100644
--- a/doc/classes/CharacterBody3D.xml
+++ b/doc/classes/CharacterBody3D.xml
@@ -159,10 +159,10 @@
Sets the behavior to apply when you leave a moving platform. By default, to be physically accurate, when you leave the last platform velocity is applied. See [enum MovingPlatformApplyVelocityOnLeave] constants for available behavior.
</member>
<member name="moving_platform_floor_layers" type="int" setter="set_moving_platform_floor_layers" getter="get_moving_platform_floor_layers" default="4294967295">
- Collision layers that will be included for detecting floor bodies that will act as moving platforms to be followed by the [CharacterBody2D]. By default, all floor bodies are detected and propagate their velocity.
+ Collision layers that will be included for detecting floor bodies that will act as moving platforms to be followed by the [CharacterBody3D]. By default, all floor bodies are detected and propagate their velocity.
</member>
<member name="moving_platform_wall_layers" type="int" setter="set_moving_platform_wall_layers" getter="get_moving_platform_wall_layers" default="0">
- Collision layers that will be included for detecting wall bodies that will act as moving platforms to be followed by the [CharacterBody2D]. By default, all wall bodies are ignored.
+ Collision layers that will be included for detecting wall bodies that will act as moving platforms to be followed by the [CharacterBody3D]. By default, all wall bodies are ignored.
</member>
<member name="slide_on_ceiling" type="bool" setter="set_slide_on_ceiling_enabled" getter="is_slide_on_ceiling_enabled" default="true">
If [code]true[/code], during a jump against the ceiling, the body will slide, if [code]false[/code] it will be stopped and will fall vertically.
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/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index 5d025985cc..95d99855f6 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -16,7 +16,8 @@
<argument index="1" name="event" type="InputEvent" />
<argument index="2" name="shape_idx" type="int" />
<description>
- Accepts unhandled [InputEvent]s. Requires [member input_pickable] to be [code]true[/code]. [code]shape_idx[/code] is the child index of the clicked [Shape2D]. Connect to the [code]input_event[/code] signal to easily pick up these events.
+ Accepts unhandled [InputEvent]s. [code]shape_idx[/code] is the child index of the clicked [Shape2D]. Connect to the [code]input_event[/code] signal to easily pick up these events.
+ [b]Note:[/b] [method _input_event] requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set.
</description>
</method>
<method name="create_shape_owner">
@@ -218,17 +219,19 @@
<argument index="1" name="event" type="InputEvent" />
<argument index="2" name="shape_idx" type="int" />
<description>
- Emitted when an input event occurs. Requires [member input_pickable] to be [code]true[/code] and at least one [code]collision_layer[/code] bit to be set. See [method _input_event] for details.
+ Emitted when an input event occurs. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. See [method _input_event] for details.
</description>
</signal>
<signal name="mouse_entered">
<description>
Emitted when the mouse pointer enters any of this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. Note that moving between different shapes within a single [CollisionObject2D] won't cause this signal to be emitted.
+ [b]Note:[/b] Due to the lack of continuous collision detection, this signal may not be emitted in the expected order if the mouse moves fast enough and the [CollisionObject2D]'s area is small. This signal may also not be emitted if another [CollisionObject2D] is overlapping the [CollisionObject2D] in question.
</description>
</signal>
<signal name="mouse_exited">
<description>
Emitted when the mouse pointer exits all this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. Note that moving between different shapes within a single [CollisionObject2D] won't cause this signal to be emitted.
+ [b]Note:[/b] Due to the lack of continuous collision detection, this signal may not be emitted in the expected order if the mouse moves fast enough and the [CollisionObject2D]'s area is small. This signal may also not be emitted if another [CollisionObject2D] is overlapping the [CollisionObject2D] in question.
</description>
</signal>
<signal name="mouse_shape_entered">
diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml
index 2aac5528f4..7284a7e341 100644
--- a/doc/classes/CollisionObject3D.xml
+++ b/doc/classes/CollisionObject3D.xml
@@ -18,6 +18,7 @@
<argument index="4" name="shape_idx" type="int" />
<description>
Receives unhandled [InputEvent]s. [code]position[/code] is the location in world space of the mouse pointer on the surface of the shape with index [code]shape_idx[/code] and [code]normal[/code] is the normal vector of the surface at that point. Connect to the [signal input_event] signal to easily pick up these events.
+ [b]Note:[/b] [method _input_event] requires [member input_ray_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set.
</description>
</method>
<method name="create_shape_owner">
@@ -199,12 +200,14 @@
</signal>
<signal name="mouse_entered">
<description>
- Emitted when the mouse pointer enters any of this object's shapes.
+ Emitted when the mouse pointer enters any of this object's shapes. Requires [member input_ray_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set.
+ [b]Note:[/b] Due to the lack of continuous collision detection, this signal may not be emitted in the expected order if the mouse moves fast enough and the [CollisionObject2D]'s area is small. This signal may also not be emitted if another [CollisionObject2D] is overlapping the [CollisionObject2D] in question.
</description>
</signal>
<signal name="mouse_exited">
<description>
- Emitted when the mouse pointer exits all this object's shapes.
+ Emitted when the mouse pointer exits all this object's shapes. Requires [member input_ray_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set.
+ [b]Note:[/b] Due to the lack of continuous collision detection, this signal may not be emitted in the expected order if the mouse moves fast enough and the [CollisionObject2D]'s area is small. This signal may also not be emitted if another [CollisionObject2D] is overlapping the [CollisionObject2D] in question.
</description>
</signal>
</signals>
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/ConfirmationDialog.xml b/doc/classes/ConfirmationDialog.xml
index 2316e32b5d..d4c503857d 100644
--- a/doc/classes/ConfirmationDialog.xml
+++ b/doc/classes/ConfirmationDialog.xml
@@ -27,6 +27,9 @@
</method>
</methods>
<members>
+ <member name="cancel_button_text" type="String" setter="set_cancel_button_text" getter="get_cancel_button_text" default="&quot;Cancel&quot;">
+ The text displayed by the cancel button (see [method get_cancel_button]).
+ </member>
<member name="min_size" type="Vector2i" setter="set_min_size" getter="get_min_size" overrides="Window" default="Vector2i(200, 70)" />
<member name="size" type="Vector2i" setter="set_size" getter="get_size" overrides="Window" default="Vector2i(200, 100)" />
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default="&quot;Please Confirm...&quot;" />
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 2846b564b4..9fc80e1aab 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -1281,8 +1281,8 @@
<constant name="PRESET_HCENTER_WIDE" value="14" enum="LayoutPreset">
Snap all 4 anchors to a horizontal line that cuts the parent control in half. Use with [method set_anchors_preset].
</constant>
- <constant name="PRESET_WIDE" value="15" enum="LayoutPreset">
- Snap all 4 anchors to the respective corners of the parent control. Set all 4 offsets to 0 after you applied this preset and the [Control] will fit its parent control. This is equivalent to the "Full Rect" layout option in the editor. Use with [method set_anchors_preset].
+ <constant name="PRESET_FULL_RECT" value="15" enum="LayoutPreset">
+ Snap all 4 anchors to the respective corners of the parent control. Set all 4 offsets to 0 after you applied this preset and the [Control] will fit its parent control. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_MODE_MINSIZE" value="0" enum="LayoutPresetMode">
The control will be resized to its minimum size.
diff --git a/doc/classes/Curve.xml b/doc/classes/Curve.xml
index 383d33532b..179b0344c2 100644
--- a/doc/classes/Curve.xml
+++ b/doc/classes/Curve.xml
@@ -5,6 +5,7 @@
</brief_description>
<description>
A curve that can be saved and re-used for other objects. By default, it 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.
+ See also [Gradient] which is designed for color interpolation. See also [Curve2D] and [Curve3D].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Decal.xml b/doc/classes/Decal.xml
index c0ad61b77e..3322ab4c66 100644
--- a/doc/classes/Decal.xml
+++ b/doc/classes/Decal.xml
@@ -58,49 +58,56 @@
</methods>
<members>
<member name="albedo_mix" type="float" setter="set_albedo_mix" getter="get_albedo_mix" default="1.0">
- Blends the albedo [Color] of the decal with albedo [Color] of the underlying mesh.
+ Blends the albedo [Color] of the decal with albedo [Color] of the underlying mesh. This can be set to [code]0.0[/code] to create a decal that only affects normal or ORM. In this case, an albedo texture is still required as its alpha channel will determine where the normal and ORM will be overridden. See also [member modulate].
</member>
<member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="1048575">
Specifies which [member VisualInstance3D.layers] this decal will project on. By default, Decals affect all layers. This is used so you can specify which types of objects receive the Decal and which do not. This is especially useful so you can ensure that dynamic objects don't accidentally receive a Decal intended for the terrain under them.
</member>
- <member name="distance_fade_begin" type="float" setter="set_distance_fade_begin" getter="get_distance_fade_begin" default="10.0">
- Distance from the camera at which the Decal begins to fade away.
+ <member name="distance_fade_begin" type="float" setter="set_distance_fade_begin" getter="get_distance_fade_begin" default="40.0">
+ The distance from the camera at which the Decal begins to fade away (in 3D units).
</member>
<member name="distance_fade_enabled" type="bool" setter="set_enable_distance_fade" getter="is_distance_fade_enabled" default="false">
- If [code]true[/code], decals will smoothly fade away when far from the active [Camera3D] starting at [member distance_fade_begin]. The Decal will fade out over [member distance_fade_length], after which it will be culled and not sent to the shader at all. Use this to reduce the number of active Decals in a scene and thus improve performance.
+ If [code]true[/code], decals will smoothly fade away when far from the active [Camera3D] starting at [member distance_fade_begin]. The Decal will fade out over [member distance_fade_begin] + [member distance_fade_length], after which it will be culled and not sent to the shader at all. Use this to reduce the number of active Decals in a scene and thus improve performance.
</member>
- <member name="distance_fade_length" type="float" setter="set_distance_fade_length" getter="get_distance_fade_length" default="1.0">
- Distance over which the Decal fades. The Decal becomes slowly more transparent over this distance and is completely invisible at the end.
+ <member name="distance_fade_length" type="float" setter="set_distance_fade_length" getter="get_distance_fade_length" default="10.0">
+ The distance over which the Decal fades (in 3D units). The Decal becomes slowly more transparent over this distance and is completely invisible at the end. Higher values result in a smoother fade-out transition, which is more suited when the camera moves fast.
</member>
<member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy" default="1.0">
- Energy multiplier for the emission texture. This will make the decal emit light at a higher intensity.
+ Energy multiplier for the emission texture. This will make the decal emit light at a higher or lower intensity, independently of the albedo color. See also [member modulate].
</member>
<member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)">
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]). See also [member upper_fade].
</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.
+ Changes the [Color] of the Decal by multiplying the albedo and emission colors with this value. The alpha component is only taken into account when multiplying the albedo color, not the emission color. See also [member emission_energy] and [member albedo_mix] to change the emission and albedo intensity independently of each other.
</member>
<member name="normal_fade" type="float" setter="set_normal_fade" getter="get_normal_fade" default="0.0">
Fades the Decal if the angle between the Decal's [AABB] and the target surface becomes too large. A value of [code]0[/code] projects the Decal regardless of angle, a value of [code]1[/code] limits the Decal to surfaces that are nearly perpendicular.
+ [b]Note:[/b] Setting [member normal_fade] to a value greater than [code]0.0[/code] has a small performance cost due to the added normal angle computations.
</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].
+ [b]Note:[/b] Setting this texture alone will not result in a visible decal, as [member texture_albedo] must also be set. To create a normal-only decal, load an albedo texture into [member texture_albedo] and set [member albedo_mix] to [code]0.0[/code]. The albedo texture's alpha channel will be used to determine where the underlying surface's normal map should be overridden (and its intensity).
</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].
+ [b]Note:[/b] Setting this texture alone will not result in a visible decal, as [member texture_albedo] must also be set. To create a ORM-only decal, load an albedo texture into [member texture_albedo] and set [member albedo_mix] to [code]0.0[/code]. The albedo texture's alpha channel will be used to determine where the underlying surface's ORM map should be overridden (and its intensity).
</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]). See also [member lower_fade].
</member>
</members>
<constants>
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index cec504584c..bc6cd88fa5 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -930,7 +930,7 @@
<return type="void" />
<argument index="0" name="existing_text" type="String" />
<argument index="1" name="position" type="Rect2" default="Rect2(0, 0, 0, 0)" />
- <argument index="2" name="multiline" type="bool" default="false" />
+ <argument index="2" name="type" type="int" enum="DisplayServer.VirtualKeyboardType" default="0" />
<argument index="3" name="max_length" type="int" default="-1" />
<argument index="4" name="cursor_start" type="int" default="-1" />
<argument index="5" name="cursor_end" type="int" default="-1" />
@@ -938,11 +938,11 @@
Shows the virtual keyboard if the platform has one.
[code]existing_text[/code] parameter is useful for implementing your own [LineEdit] or [TextEdit], as it tells the virtual keyboard what text has already been typed (the virtual keyboard uses it for auto-correct and predictions).
[code]position[/code] parameter is the screen space [Rect2] of the edited text.
- [code]multiline[/code] parameter needs to be set to [code]true[/code] to be able to enter multiple lines of text, as in [TextEdit].
+ [code]type[/code] parameter allows configuring which type of virtual keyboard to show.
[code]max_length[/code] limits the number of characters that can be entered if different from [code]-1[/code].
[code]cursor_start[/code] can optionally define the current text cursor position if [code]cursor_end[/code] is not set.
[code]cursor_start[/code] and [code]cursor_end[/code] can optionally define the current text selection.
- [b]Note:[/b] This method is implemented on Android, iOS and UWP.
+ [b]Note:[/b] This method is implemented on Android, iOS and HTML5.
</description>
</method>
<method name="warp_mouse">
@@ -1049,7 +1049,7 @@
<return type="int" enum="DisplayServer.VSyncMode" />
<argument index="0" name="window_id" type="int" default="0" />
<description>
- Returns the VSync mode of the given window.
+ Returns the V-Sync mode of the given window.
</description>
</method>
<method name="window_move_to_foreground">
@@ -1234,7 +1234,7 @@
<argument index="0" name="vsync_mode" type="int" enum="DisplayServer.VSyncMode" />
<argument index="1" name="window_id" type="int" default="0" />
<description>
- Sets the VSync mode of the given window.
+ Sets the V-Sync mode of the given window.
See [enum DisplayServer.VSyncMode] for possible values and how they affect the behavior of your application.
Depending on the platform and used renderer, the engine will fall back to [constant VSYNC_ENABLED], if the desired mode is not supported.
</description>
@@ -1323,6 +1323,31 @@
</constant>
<constant name="SCREEN_SENSOR" value="6" enum="ScreenOrientation">
</constant>
+ <constant name="KEYBOARD_TYPE_DEFAULT" value="0" enum="VirtualKeyboardType">
+ Default text virtual keyboard.
+ </constant>
+ <constant name="KEYBOARD_TYPE_MULTILINE" value="1" enum="VirtualKeyboardType">
+ Multiline virtual keyboard.
+ </constant>
+ <constant name="KEYBOARD_TYPE_NUMBER" value="2" enum="VirtualKeyboardType">
+ Virtual number keypad, useful for PIN entry.
+ </constant>
+ <constant name="KEYBOARD_TYPE_NUMBER_DECIMAL" value="3" enum="VirtualKeyboardType">
+ Virtual number keypad, useful for entering fractional numbers.
+ </constant>
+ <constant name="KEYBOARD_TYPE_PHONE" value="4" enum="VirtualKeyboardType">
+ Virtual phone number keypad.
+ </constant>
+ <constant name="KEYBOARD_TYPE_EMAIL_ADDRESS" value="5" enum="VirtualKeyboardType">
+ Virtual keyboard with additional keys to assist with typing email addresses.
+ </constant>
+ <constant name="KEYBOARD_TYPE_PASSWORD" value="6" enum="VirtualKeyboardType">
+ Virtual keyboard for entering a password. On most platforms, this should disable autocomplete and autocapitalization.
+ [b]Note:[/b] This is not supported on HTML5. Instead, this behaves identically to [constant KEYBOARD_TYPE_DEFAULT].
+ </constant>
+ <constant name="KEYBOARD_TYPE_URL" value="7" enum="VirtualKeyboardType">
+ Virtual keyboard with additional keys to assist with typing URLs.
+ </constant>
<constant name="CURSOR_ARROW" value="0" enum="CursorShape">
</constant>
<constant name="CURSOR_IBEAM" value="1" enum="CursorShape">
diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml
index 8aa2db2cf8..f217fbaf48 100644
--- a/doc/classes/EditorExportPlugin.xml
+++ b/doc/classes/EditorExportPlugin.xml
@@ -96,7 +96,7 @@
Adds a static lib from the given [code]path[/code] to the iOS project.
</description>
</method>
- <method name="add_osx_plugin_file">
+ <method name="add_macos_plugin_file">
<return type="void" />
<argument index="0" name="path" type="String" />
<description>
diff --git a/doc/classes/EditorFeatureProfile.xml b/doc/classes/EditorFeatureProfile.xml
index 2ab87b0dd1..a6bdc294ac 100644
--- a/doc/classes/EditorFeatureProfile.xml
+++ b/doc/classes/EditorFeatureProfile.xml
@@ -57,7 +57,7 @@
<return type="int" enum="Error" />
<argument index="0" name="path" type="String" />
<description>
- Saves the editor feature profile to a file in JSON format. It can then be imported using the feature profile manager's [b]Import[/b] button or the [method load_from_file] button.
+ Saves the editor feature profile to a file in JSON format. It can then be imported using the feature profile manager's [b]Import[/b] button or the [method load_from_file] method.
</description>
</method>
<method name="set_disable_class">
diff --git a/doc/classes/EditorFileDialog.xml b/doc/classes/EditorFileDialog.xml
index b1fd7b4e76..6fd5abe369 100644
--- a/doc/classes/EditorFileDialog.xml
+++ b/doc/classes/EditorFileDialog.xml
@@ -11,9 +11,11 @@
<method name="add_filter">
<return type="void" />
<argument index="0" name="filter" type="String" />
+ <argument index="1" name="description" type="String" default="&quot;&quot;" />
<description>
- Adds a comma-delimited file extension filter option to the [EditorFileDialog] with an optional semi-colon-delimited label.
- For example, [code]"*.tscn, *.scn; Scenes"[/code] results in filter text "Scenes (*.tscn, *.scn)".
+ Adds a comma-delimited file name [code]filter[/code] option to the [EditorFileDialog] with an optional [code]description[/code], which restricts what files can be picked.
+ A [code]filter[/code] should be of the form [code]"filename.extension"[/code], where filename and extension can be [code]*[/code] to match any string. Filters starting with [code].[/code] (i.e. empty filenames) are not allowed.
+ For example, a [code]filter[/code] of [code]"*.tscn, *.scn"[/code] and a [code]description[/code] of [code]"Scenes"[/code] results in filter text "Scenes (*.tscn, *.scn)".
</description>
</method>
<method name="clear_filters">
diff --git a/doc/classes/EditorPaths.xml b/doc/classes/EditorPaths.xml
index d44c08cb0f..2975ea6d75 100644
--- a/doc/classes/EditorPaths.xml
+++ b/doc/classes/EditorPaths.xml
@@ -48,6 +48,12 @@
[/codeblock]
</description>
</method>
+ <method name="get_project_settings_dir" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the project-specific editor settings path. Projects all have a unique subdirectory inside the settings path where project-specific editor settings are saved.
+ </description>
+ </method>
<method name="get_self_contained_file" qualifiers="const">
<return type="String" />
<description>
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index 1514b82ff8..2930c2ec22 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -296,6 +296,28 @@
<return type="bool" />
<description>
Returns [code]true[/code] if this is a main screen editor plugin (it goes in the workspace selector together with [b]2D[/b], [b]3D[/b], [b]Script[/b] and [b]AssetLib[/b]).
+ When the plugin's workspace is selected, other main screen plugins will be hidden, but your plugin will not appear automatically. It needs to be added as a child of [method EditorInterface.get_base_control] and made visible inside [method _make_visible].
+ Use [method _get_plugin_name] and [method _get_plugin_icon] to customize the plugin button's appearance.
+ [codeblock]
+ var plugin_control
+
+ func _enter_tree():
+ plugin_control = preload("my_plugin_control.tscn").instantiate()
+ get_editor_interface().get_editor_main_control().add_child(plugin_control)
+ plugin_control.hide()
+
+ func _has_main_screen():
+ return true
+
+ func _make_visible(visible):
+ plugin_control.visible = visible
+
+ func _get_plugin_name():
+ return "My Super Cool Plugin 3000"
+
+ func _get_plugin_icon():
+ return get_editor_interface().get_base_control().get_theme_icon("Node", "EditorIcons")
+ [/codeblock]
</description>
</method>
<method name="_make_visible" qualifiers="virtual">
diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml
index 84f8523da3..586458bd28 100644
--- a/doc/classes/EditorProperty.xml
+++ b/doc/classes/EditorProperty.xml
@@ -101,6 +101,13 @@
Used by sub-inspectors. Emit it if what was selected was an Object ID.
</description>
</signal>
+ <signal name="property_can_revert_changed">
+ <argument index="0" name="property" type="StringName" />
+ <argument index="1" name="can_revert" type="bool" />
+ <description>
+ Emitted when the revertability (i.e., whether it has a non-default value and thus is displayed with a revert icon) of a property has changed.
+ </description>
+ </signal>
<signal name="property_changed">
<argument index="0" name="property" type="StringName" />
<argument index="1" name="value" type="Variant" />
diff --git a/doc/classes/EditorScenePostImportPlugin.xml b/doc/classes/EditorScenePostImportPlugin.xml
index 0fdbd5db1e..44d644411d 100644
--- a/doc/classes/EditorScenePostImportPlugin.xml
+++ b/doc/classes/EditorScenePostImportPlugin.xml
@@ -88,7 +88,7 @@
<argument index="2" name="default_value" type="Variant" />
<argument index="3" name="hint" type="int" enum="PropertyHint" default="0" />
<argument index="4" name="hint_string" type="String" default="&quot;&quot;" />
- <argument index="5" name="usage_flags" type="int" default="7" />
+ <argument index="5" name="usage_flags" type="int" default="6" />
<description>
Add a specific import option. This function can only be called from [method _get_import_options] and [method _get_internal_import_options].
</description>
@@ -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/EditorSettings.xml b/doc/classes/EditorSettings.xml
index ac2250ab6d..ade7bc1256 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -105,12 +105,6 @@
Returns project-specific metadata for the [code]section[/code] and [code]key[/code] specified. If the metadata doesn't exist, [code]default[/code] will be returned instead. See also [method set_project_metadata].
</description>
</method>
- <method name="get_project_settings_dir" qualifiers="const">
- <return type="String" />
- <description>
- Returns the project-specific settings path. Projects all have a unique subdirectory inside the settings path where project-specific settings are saved.
- </description>
- </method>
<method name="get_recent_dirs" qualifiers="const">
<return type="PackedStringArray" />
<description>
@@ -157,6 +151,7 @@
<argument index="0" name="name" type="String" />
<argument index="1" name="actions_list" type="Array" />
<description>
+ Overrides the built-in editor action [code]name[/code] with the input actions defined in [code]actions_list[/code].
</description>
</method>
<method name="set_favorites">
@@ -200,6 +195,730 @@
</description>
</method>
</methods>
+ <members>
+ <member name="debugger/profiler_frame_history_size" type="int" setter="" getter="">
+ The size of the profiler's frame history. The default value (3600) allows seeing up to 60 seconds of profiling if the project renders at a constant 60 FPS. Higher values allow viewing longer periods of profiling in the graphs, especially when the project is running at high framerates.
+ </member>
+ <member name="docks/filesystem/always_show_folders" type="bool" setter="" getter="">
+ If [code]true[/code], displays folders in the FileSystem dock's bottom pane when split mode is enabled. If [code]false[/code], only files will be displayed in the bottom pane. Split mode can be toggled by pressing the icon next to the [code]res://[/code] folder path.
+ [b]Note:[/b] This setting has no effect when split mode is disabled (which is the default).
+ </member>
+ <member name="docks/filesystem/textfile_extensions" type="String" setter="" getter="">
+ List of file extensions to consider as editable text files in the FileSystem dock (by double-clicking on the files).
+ </member>
+ <member name="docks/filesystem/thumbnail_size" type="int" setter="" getter="">
+ The thumbnail size to use in the FileSystem dock (in pixels). See also [member filesystem/file_dialog/thumbnail_size].
+ </member>
+ <member name="docks/property_editor/auto_refresh_interval" type="float" setter="" getter="">
+ The refresh interval to use for the inspector dock's properties. The effect of this setting is mainly noticeable when adjusting gizmos in the 2D/3D editor and looking at the inspector at the same time. Lower values make the inspector more often, but take up more CPU time.
+ </member>
+ <member name="docks/property_editor/subresource_hue_tint" type="float" setter="" getter="">
+ The tint intensity to use for the subresources background in the inspector dock. The tint is used to distinguish between different subresources in the inspector. Higher values result in a more noticeable background color difference.
+ </member>
+ <member name="docks/scene_tree/auto_expand_to_selected" type="bool" setter="" getter="">
+ If [code]true[/code], the scene tree dock will automatically unfold nodes when a node that has folded parents is selected.
+ </member>
+ <member name="docks/scene_tree/start_create_dialog_fully_expanded" type="bool" setter="" getter="">
+ If [code]true[/code], the Create dialog (Create New Node/Create New Resource) will start with all its sections expanded. Otherwise, sections will be collapsed until the user starts searching (which will automatically expand sections as needed).
+ </member>
+ <member name="editors/2d/bone_color1" type="Color" setter="" getter="">
+ The "start" stop of the color gradient to use for bones in the 2D skeleton editor.
+ </member>
+ <member name="editors/2d/bone_color2" type="Color" setter="" getter="">
+ The "end" stop of the color gradient to use for bones in the 2D skeleton editor.
+ </member>
+ <member name="editors/2d/bone_ik_color" type="Color" setter="" getter="">
+ The color to use for inverse kinematics-enabled bones in the 2D skeleton editor.
+ </member>
+ <member name="editors/2d/bone_outline_color" type="Color" setter="" getter="">
+ The outline color to use for non-selected bones in the 2D skeleton editor. See also [member editors/2d/bone_selected_color].
+ </member>
+ <member name="editors/2d/bone_outline_size" type="int" setter="" getter="">
+ The outline size in the 2D skeleton editor (in pixels). See also [member editors/2d/bone_width].
+ </member>
+ <member name="editors/2d/bone_selected_color" type="Color" setter="" getter="">
+ The color to use for selected bones in the 2D skeleton editor. See also [member editors/2d/bone_outline_color].
+ </member>
+ <member name="editors/2d/bone_width" type="int" setter="" getter="">
+ The bone width in the 2D skeleton editor (in pixels). See also [member editors/2d/bone_outline_size].
+ </member>
+ <member name="editors/2d/constrain_editor_view" type="bool" setter="" getter="">
+ If [code]true[/code], prevents the 2D editor viewport from leaving the scene. Limits are calculated dynamically based on nodes present in the current scene. If [code]false[/code], the 2D editor viewport will be able to move freely, but you risk getting lost when zooming out too far. You can refocus on the scene by selecting a node then pressing [kbd]F[/kbd].
+ </member>
+ <member name="editors/2d/grid_color" type="Color" setter="" getter="">
+ The grid color to use in the 2D editor.
+ </member>
+ <member name="editors/2d/guides_color" type="Color" setter="" getter="">
+ The guides color to use in the 2D editor. Guides can be created by dragging the mouse cursor from the rulers.
+ </member>
+ <member name="editors/2d/smart_snapping_line_color" type="Color" setter="" getter="">
+ The color to use when drawing smart snapping lines in the 2D editor. The smart snapping lines will automatically display when moving 2D nodes if smart snapping is enabled in the Snapping Options menu at the top of the 2D editor viewport.
+ </member>
+ <member name="editors/2d/viewport_border_color" type="Color" setter="" getter="">
+ The color of the viewport border in the 2D editor. This border represents the viewport's size at the base resolution defined in the Project Settings. Objects placed outside this border will not be visible unless a [Camera2D] node is used, or unless the window is resized and the stretch mode is set to [code]disabled[/code].
+ </member>
+ <member name="editors/3d/default_fov" type="float" setter="" getter="">
+ The default camera field of view to use in the 3D editor (in degrees). The camera field of view can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera field of view adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a Camera3D node is being previewed in the editor.
+ </member>
+ <member name="editors/3d/default_z_far" type="float" setter="" getter="">
+ The default camera far clip distance to use in the 3D editor (in degrees). Higher values make it possible to view objects placed further away from the camera, at the cost of lower precision in the depth buffer (which can result in visible Z-fighting in the distance). The camera far clip distance can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera far clip distance adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a Camera3D node is being previewed in the editor.
+ </member>
+ <member name="editors/3d/default_z_near" type="float" setter="" getter="">
+ The default camera near clip distance to use in the 3D editor (in degrees). Lower values make it possible to view objects placed closer to the camera, at the cost of lower precision in the depth buffer (which can result in visible Z-fighting in the distance). The camera near clip distance can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera near clip distance adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a Camera3D node is being previewed in the editor.
+ </member>
+ <member name="editors/3d/freelook/freelook_activation_modifier" type="int" setter="" getter="">
+ The modifier key to use to enable freelook in the 3D editor (on top of pressing the right mouse button).
+ [b]Note:[/b] Regardless of this setting, the freelook toggle keyboard shortcut ([kbd]Shift + F[/kbd] by default) is always available.
+ [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
+ </member>
+ <member name="editors/3d/freelook/freelook_base_speed" type="float" setter="" getter="">
+ The base 3D freelook speed in units per second. This can be adjusted by using the mouse wheel while in freelook mode, or by holding down the "fast" or "slow" modifier keys ([kbd]Shift[/kbd] and [kbd]Alt[/kbd] by default, respectively).
+ </member>
+ <member name="editors/3d/freelook/freelook_inertia" type="float" setter="" getter="">
+ The inertia of the 3D freelook camera. Higher values make the camera start and stop slower, which looks smoother but adds latency.
+ </member>
+ <member name="editors/3d/freelook/freelook_navigation_scheme" type="int" setter="" getter="">
+ The navigation scheme to use when freelook is enabled in the 3D editor. Some of the navigation schemes below may be more convenient when designing specific levels in the 3D editor.
+ - [b]Default:[/b] The "Freelook Forward", "Freelook Backward", "Freelook Up" and "Freelook Down" keys will move relative to the camera, taking its pitch angle into account for the movement.
+ - [b]Partially Axis-Locked:[/b] The "Freelook Forward" and "Freelook Backward" keys will move relative to the camera, taking its pitch angle into account for the movement. The "Freelook Up" and "Freelook Down" keys will move in an "absolute" manner, [i]not[/i] taking the camera's pitch angle into account for the movement.
+ - [b]Fully Axis-Locked:[/b] The "Freelook Forward", "Freelook Backward", "Freelook Up" and "Freelook Down" keys will move in an "absolute" manner, [i]not[/i] taking the camera's pitch angle into account for the movement.
+ See also [member editors/3d/navigation/navigation_scheme].
+ </member>
+ <member name="editors/3d/freelook/freelook_sensitivity" type="float" setter="" getter="">
+ The mouse sensitivity to use while freelook mode is active in the 3D editor. See also [member editors/3d/navigation_feel/orbit_sensitivity].
+ </member>
+ <member name="editors/3d/freelook/freelook_speed_zoom_link" type="bool" setter="" getter="">
+ If [code]true[/code], freelook speed is linked to the zoom value used in the camera orbit mode in the 3D editor.
+ </member>
+ <member name="editors/3d/grid_division_level_bias" type="float" setter="" getter="">
+ The grid division bias to use in the 3D editor. Negative values will cause small grid divisions to appear earlier, whereas positive values will cause small grid divisions to appear later.
+ </member>
+ <member name="editors/3d/grid_division_level_max" type="int" setter="" getter="">
+ The smallest grid division to use in the 3D editor, specified as a power of 2. The grid will not be able to get larger than [code]1 ^ grid_division_level_max[/code] units. By default, this means grid divisions cannot get smaller than 100 units each, no matter how far away the camera is from the grid.
+ </member>
+ <member name="editors/3d/grid_division_level_min" type="int" setter="" getter="">
+ The smallest grid division to use in the 3D editor, specified as a power of 2. The grid will not be able to get smaller than [code]1 ^ grid_division_level_min[/code] units. By default, this means grid divisions cannot get smaller than 1 unit each, no matter how close the camera is from the grid.
+ </member>
+ <member name="editors/3d/grid_size" type="int" setter="" getter="">
+ The grid size in units. Higher values prevent the grid from appearing "cut off" at certain angles, but make the grid more demanding to render. Depending on the camera's position, the grid may not be fully visible since a shader is used to fade it progressively.
+ </member>
+ <member name="editors/3d/grid_xy_plane" type="bool" setter="" getter="">
+ If [code]true[/code], render the grid on an XY plane. This can be useful for 3D side-scrolling games.
+ </member>
+ <member name="editors/3d/grid_xz_plane" type="bool" setter="" getter="">
+ If [code]true[/code], render the grid on an XZ plane.
+ </member>
+ <member name="editors/3d/grid_yz_plane" type="bool" setter="" getter="">
+ If [code]true[/code], render the grid on an YZ plane. This can be useful for 3D side-scrolling games.
+ </member>
+ <member name="editors/3d/navigation/emulate_3_button_mouse" type="bool" setter="" getter="">
+ If [code]true[/code], enables 3-button mouse emulation mode. This is useful on laptops when using a trackpad.
+ When 3-button mouse emulation mode is enabled, the pan, zoom and orbit modifiers can always be used in the 3D editor viewport, even when not holding down any mouse button.
+ [b]Note:[/b] No matter the orbit modifier configured in [member editors/3d/navigation/orbit_modifier], [kbd]Alt[/kbd] will always remain usable for orbiting in this mode to improve usability with graphics tablets.
+ </member>
+ <member name="editors/3d/navigation/emulate_numpad" type="bool" setter="" getter="">
+ If [code]true[/code], allows using the top row [kbd]0[/kbd]-[kbd]9[/kbd] keys to function as their equivalent numpad keys for 3D editor navigation. This should be enabled on keyboards that have no numeric keypad available.
+ </member>
+ <member name="editors/3d/navigation/invert_x_axis" type="bool" setter="" getter="">
+ If [code]true[/code], invert the horizontal mouse axis when panning or orbiting in the 3D editor. This setting does [i]not[/i] apply to freelook mode.
+ </member>
+ <member name="editors/3d/navigation/invert_y_axis" type="bool" setter="" getter="">
+ If [code]true[/code], invert the vertical mouse axis when panning, orbiting, or using freelook mode in the 3D editor.
+ </member>
+ <member name="editors/3d/navigation/navigation_scheme" type="int" setter="" getter="">
+ The navigation scheme to use in the 3D editor. Changing this setting will affect the mouse buttons that must be held down to perform certain operations in the 3D editor viewport.
+ - [b]Godot[/b] Middle mouse button to orbit, [kbd]Shift + Middle mouse button[/kbd] to pan. [kbd]Mouse wheel[/kbd] to zoom.
+ - [b]Maya:[/b] [kbd]Alt + Left mouse buttton[/kbd] to orbit. [kbd]Middle mouse button[/kbd] to pan, [kbd]Shift + Middle mouse button[/kbd] to pan 10 times faster. [kbd]Mouse wheel[/kbd] to zoom.
+ - [b]Modo:[/b] [kbd]Alt + Left mouse buttton[/kbd] to orbit. [kbd]Alt + Shift + Left mouse button[/kbd] to pan. [kbd]Ctrl + Alt + Left mouse button[/kbd] to zoom.
+ See also [member editors/3d/freelook/freelook_navigation_scheme].
+ [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
+ </member>
+ <member name="editors/3d/navigation/orbit_modifier" type="int" setter="" getter="">
+ The modifier key that must be held to orbit in the 3D editor.
+ [b]Note:[/b] If [member editors/3d/navigation/emulate_3_button_mouse] is [code]true[/code], [kbd]Alt[/kbd] will always remain usable for orbiting to improve usability with graphics tablets.
+ [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
+ </member>
+ <member name="editors/3d/navigation/pan_modifier" type="int" setter="" getter="">
+ The modifier key that must be held to pan in the 3D editor.
+ [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
+ </member>
+ <member name="editors/3d/navigation/warped_mouse_panning" type="bool" setter="" getter="">
+ If [code]true[/code], warps the mouse around the 3D viewport while panning in the 3D editor. This makes it possible to pan over a large area without having to exit panning then mouse the mouse back constantly.
+ </member>
+ <member name="editors/3d/navigation/zoom_modifier" type="int" setter="" getter="">
+ The modifier key that must be held to zoom in the 3D editor.
+ [b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
+ </member>
+ <member name="editors/3d/navigation/zoom_style" type="int" setter="" getter="">
+ The mouse cursor movement direction to use when zooming by moving the mouse. This does not affect zooming with the mouse wheel.
+ </member>
+ <member name="editors/3d/navigation_feel/orbit_inertia" type="float" setter="" getter="">
+ The inertia to use when orbiting in the 3D editor. Higher values make the camera start and stop slower, which looks smoother but adds latency.
+ </member>
+ <member name="editors/3d/navigation_feel/orbit_sensitivity" type="float" setter="" getter="">
+ The mouse sensitivity to use when orbiting in the 3D editor. See also [member editors/3d/freelook/freelook_sensitivity].
+ </member>
+ <member name="editors/3d/navigation_feel/translation_inertia" type="float" setter="" getter="">
+ The inertia to use when panning in the 3D editor. Higher values make the camera start and stop slower, which looks smoother but adds latency.
+ </member>
+ <member name="editors/3d/navigation_feel/zoom_inertia" type="float" setter="" getter="">
+ The inertia to use when zooming in the 3D editor. Higher values make the camera start and stop slower, which looks smoother but adds latency.
+ </member>
+ <member name="editors/3d/primary_grid_color" type="Color" setter="" getter="">
+ The color to use for the primary 3D grid. The color's alpha channel affects the grid's opacity.
+ </member>
+ <member name="editors/3d/primary_grid_steps" type="int" setter="" getter="">
+ If set above 0, where a primary grid line should be drawn. By default, primary lines are configured to be more visible than secondary lines. This helps with measurements in the 3D editor. See also [member editors/3d/primary_grid_color] and [member editors/3d/secondary_grid_color].
+ </member>
+ <member name="editors/3d/secondary_grid_color" type="Color" setter="" getter="">
+ The color to use for the secondary 3D grid. This is generally a less visible color than [member editors/3d/primary_grid_color]. The color's alpha channel affects the grid's opacity.
+ </member>
+ <member name="editors/3d/selection_box_color" type="Color" setter="" getter="">
+ The color to use for the selection box that surrounds selected nodes in the 3D editor viewport. The color's alpha channel influences the selection box's opacity.
+ </member>
+ <member name="editors/3d_gizmos/gizmo_colors/instantiated" type="Color" setter="" getter="">
+ The color override to use for 3D editor gizmos if the [Node3D] in question is part of an instanced scene file (from the perspective of the current scene).
+ </member>
+ <member name="editors/3d_gizmos/gizmo_colors/joint" type="Color" setter="" getter="">
+ The 3D editor gizmo color for [Joint3D]s and [PhysicalBone3D]s.
+ </member>
+ <member name="editors/3d_gizmos/gizmo_colors/shape" type="Color" setter="" getter="">
+ The 3D editor gizmo color for [CollisionShape3D]s, [VehicleWheel3D]s, [RayCast3D]s and [SpringArm3D]s.
+ </member>
+ <member name="editors/animation/autorename_animation_tracks" type="bool" setter="" getter="">
+ If [code]true[/code], automatically updates animation tracks' target paths when renaming or reparenting nodes in the Scene tree dock.
+ </member>
+ <member name="editors/animation/confirm_insert_track" type="bool" setter="" getter="">
+ If [code]true[/code], display a confirmation dialog when adding a new track to an animation by pressing the "key" icon next to a property.
+ </member>
+ <member name="editors/animation/default_create_bezier_tracks" type="bool" setter="" getter="">
+ If [code]true[/code], create a Bezier track instead of a standard track when pressing the "key" icon next to a property. Bezier tracks provide more control over animation curves, but are more difficult to adjust quickly.
+ </member>
+ <member name="editors/animation/default_create_reset_tracks" type="bool" setter="" getter="">
+ If [code]true[/code], create a [code]RESET[/code] track when creating a new animation track. This track can be used to restore the animation to a "default" state.
+ </member>
+ <member name="editors/animation/onion_layers_future_color" type="Color" setter="" getter="">
+ The modulate color to use for "future" frames displayed in the animation editor's onion skinning feature.
+ </member>
+ <member name="editors/animation/onion_layers_past_color" type="Color" setter="" getter="">
+ The modulate color to use for "past" frames displayed in the animation editor's onion skinning feature.
+ </member>
+ <member name="editors/grid_map/pick_distance" type="float" setter="" getter="">
+ The maximum distance at which tiles can be placed on a GridMap, relative to the camera position (in 3D units).
+ </member>
+ <member name="editors/panning/2d_editor_pan_speed" type="int" setter="" getter="">
+ The panning speed when using the mouse wheel or touchscreen events in the 2D editor. This setting does not apply to panning by holding down the middle or right mouse buttons.
+ </member>
+ <member name="editors/panning/2d_editor_panning_scheme" type="int" setter="" getter="">
+ Controls whether the mouse wheel scroll zooms or pans in the 2D editor. See also [member editors/panning/sub_editors_panning_scheme] and [member editors/panning/animation_editors_panning_scheme].
+ </member>
+ <member name="editors/panning/animation_editors_panning_scheme" type="int" setter="" getter="">
+ Controls whether the mouse wheel scroll zooms or pans in the animation track and Bezier editors. See also [member editors/panning/2d_editor_panning_scheme] and [member editors/panning/sub_editors_panning_scheme] (which controls the animation blend tree editor's pan behavior).
+ </member>
+ <member name="editors/panning/simple_panning" type="bool" setter="" getter="">
+ If [code]true[/code], allows panning by holding down [kbd]Space[/kbd] in the 2D editor viewport (in addition to panning with the middle or right mouse buttons). If [code]false[/code], the left mouse button must be held down while holding down [kbd]Space[/kbd] to pan in the 2D editor viewport.
+ </member>
+ <member name="editors/panning/sub_editors_panning_scheme" type="int" setter="" getter="">
+ Controls whether the mouse wheel scroll zooms or pans in subeditors. The list of affected subeditors is: animation blend tree editor, [Polygon2D] editor, tileset editor, texture region editor, visual shader editor and visual script editor. See also [member editors/panning/2d_editor_panning_scheme] and [member editors/panning/animation_editors_panning_scheme].
+ </member>
+ <member name="editors/panning/warped_mouse_panning" type="bool" setter="" getter="">
+ If [code]true[/code], warps the mouse around the 2D viewport while panning in the 2D editor. This makes it possible to pan over a large area without having to exit panning then mouse the mouse back constantly.
+ </member>
+ <member name="editors/polygon_editor/point_grab_radius" type="int" setter="" getter="">
+ The radius in which points can be selected in the [Polygon2D] and [CollisionPolygon2D] editors (in pixels). Higher values make it easier to select points quickly, but can make it more difficult to select the expected point when several points are located close to each other.
+ </member>
+ <member name="editors/polygon_editor/show_previous_outline" type="bool" setter="" getter="">
+ If [code]true[/code], displays the polygon's previous shape in the 2D polygon editors with an opaque gray outline. This outline is displayed while dragging a point until the left mouse button is released.
+ </member>
+ <member name="editors/tiles_editor/display_grid" type="bool" setter="" getter="">
+ If [code]true[/code], displays a grid while the TileMap editor is active. See also [member editors/tiles_editor/grid_color].
+ </member>
+ <member name="editors/tiles_editor/grid_color" type="Color" setter="" getter="">
+ The color to use for the TileMap editor's grid.
+ [b]Note:[/b] Only effective if [member editors/tiles_editor/display_grid] is [code]true[/code].
+ </member>
+ <member name="editors/visual_editors/lines_curvature" type="float" setter="" getter="">
+ The curvature to use for connection lines in the visual script and visual shader editors. Higher values will make connection lines appear more curved, with values above [code]0.5[/code] resulting in more "angular" turns in the middle of connection lines.
+ </member>
+ <member name="editors/visual_editors/minimap_opacity" type="float" setter="" getter="">
+ The opacity of the minimap displayed in the bottom-right corner of the visual script and visual shader editors.
+ </member>
+ <member name="editors/visual_editors/visual_shader/port_preview_size" type="int" setter="" getter="">
+ The size to use for port previews in the visual shader uniforms (toggled by clicking the "eye" icon next to an output). The value is defined in pixels at 100% zoom, and will scale with zoom automatically.
+ </member>
+ <member name="filesystem/directories/autoscan_project_path" type="String" setter="" getter="">
+ The folder where projects should be scanned for (recursively), in a way similar to the project manager's [b]Scan[/b]button. This can be set to the same value as [member filesystem/directories/default_project_path] for convenience.
+ [b]Note:[/b] Setting this path to a folder with very large amounts of files/folders can slow down the project manager startup significantly. To keep the project manager quick to start up, it is recommended to set this value to a folder as "specific" as possible.
+ </member>
+ <member name="filesystem/directories/default_project_path" type="String" setter="" getter="">
+ The folder where new projects should be created by default when clicking the project manager's [b]New Project[/b] button. This can be set to the same value as [member filesystem/directories/autoscan_project_path] for convenience.
+ </member>
+ <member name="filesystem/file_dialog/display_mode" type="int" setter="" getter="">
+ The display mode to use in the editor's file dialogs.
+ - [b]Thumbnails[/b] takes more space, but displays dynamic resource thumbnails, making resources easier to preview without having to open them.
+ - [b]List[/b] is more compact but doesn't display dynamic resource thumbnails. Instead, it displays static icons based on the file extension.
+ </member>
+ <member name="filesystem/file_dialog/show_hidden_files" type="bool" setter="" getter="">
+ If [code]true[/code], display hidden files in the editor's file dialogs. Files that have names starting with [code].[/code] are considered hidden (e.g. [code].hidden_file[/code]).
+ </member>
+ <member name="filesystem/file_dialog/thumbnail_size" type="int" setter="" getter="">
+ The thumbnail size to use in the editor's file dialogs (in pixels). See also [member docks/filesystem/thumbnail_size].
+ </member>
+ <member name="filesystem/on_save/compress_binary_resources" type="bool" setter="" getter="">
+ If [code]true[/code], uses lossless compression for binary resources.
+ </member>
+ <member name="filesystem/on_save/safe_save_on_backup_then_rename" type="bool" setter="" getter="">
+ If [code]true[/code], when saving a file, the editor will rename the old file to a different name, save a new file, then only remove the old file once the new file has been saved. This makes loss of data less likely to happen if the editor or operating system exits unexpectedly while saving (e.g. due to a crash or power outage).
+ [b]Note:[/b] On Windows, this feature can interact negatively with certain antivirus programs. In this case, you may have to set this to [code]false[/code] to prevent file locking issues.
+ </member>
+ <member name="interface/editor/automatically_open_screenshots" type="bool" setter="" getter="">
+ If [code]true[/code], automatically opens screenshots with the default program associated to [code].png[/code] files after a screenshot is taken using the [b]Editor &gt; Take Screenshot[/b] action.
+ </member>
+ <member name="interface/editor/code_font" type="String" setter="" getter="">
+ The font to use for the script editor. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file.
+ </member>
+ <member name="interface/editor/code_font_contextual_ligatures" type="int" setter="" getter="">
+ The font ligatures to enable for the currently configured code font. Not all fonts include support for ligatures.
+ [b]Note:[/b] The default editor code font (Hack) does not have contextual ligatures in its font file.
+ </member>
+ <member name="interface/editor/code_font_custom_opentype_features" type="String" setter="" getter="">
+ List of custom OpenType features to use, if supported by the currently configured code font. Not all fonts include support for custom OpenType features. The string should follow the OpenType specification.
+ [b]Note:[/b] The default editor code font (Hack) does not have custom OpenType features in its font file.
+ </member>
+ <member name="interface/editor/code_font_custom_variations" type="String" setter="" getter="">
+ List of alternative characters to use, if supported by the currently configured code font. Not all fonts include support for custom variations. The string should follow the OpenType specification.
+ [b]Note:[/b] The default editor code font (Hack) does not have alternate characters in its font file.
+ </member>
+ <member name="interface/editor/code_font_size" type="int" setter="" getter="">
+ The size of the font in the script editor. This setting does not impact the font size of the Output panel (see [member run/output/font_size]).
+ </member>
+ <member name="interface/editor/custom_display_scale" type="float" setter="" getter="">
+ The custom editor scale factor to use. This can be used for displays with very high DPI where a scale factor of 200% is not sufficient.
+ [b]Note:[/b] Only effective if [member interface/editor/display_scale] is set to [b]Custom[/b].
+ </member>
+ <member name="interface/editor/debug/enable_pseudolocalization" type="bool" setter="" getter="">
+ If [code]true[/code], lengthens the editor's localizable strings and replaces their characters with accented variants. This allows spotting non-localizable strings easily, while also ensuring the UI layout doesn't break when strings are made longer (as many languages require strings to be longer).
+ This is a debugging feature and should only be enabled when working on the editor itself.
+ </member>
+ <member name="interface/editor/display_scale" type="int" setter="" getter="">
+ The display scale factor to use for the editor interface. Higher values are more suited to hiDPI/Retina displays.
+ If set to [b]Auto[/b], the editor scale is automatically determined based on the screen resolution and reported display DPI. This heuristic is not always ideal, which means you can get better results by setting the editor scale manually.
+ If set to [b]Custom[/b], the scaling value in [member interface/editor/custom_display_scale] will be used.
+ </member>
+ <member name="interface/editor/editor_language" type="String" setter="" getter="">
+ The language to use for the editor interface.
+ Translations are provided by the community. If you spot a mistake, [url=https://docs.godotengine.org/en/latest/community/contributing/editor_and_docs_localization.html]contribute to editor translations on Weblate![/url]
+ </member>
+ <member name="interface/editor/font_antialiased" type="bool" setter="" getter="">
+ If [code]true[/code], enables FreeType's font antialiasing on the editor fonts. Most fonts are not designed to look good with antialiasing disabled, so it's recommended to leave this enabled unless you're using a pixel art font.
+ </member>
+ <member name="interface/editor/font_hinting" type="int" setter="" getter="">
+ The font hinting mode to use for the editor fonts. FreeType supports the following font hinting modes:
+ - [b]None:[/b] Don't use font hinting when rasterizing the font. This results in a smooth font, but it can look blurry.
+ - [b]Light:[/b] Use hinting on the X axis only. This is a compromise between font sharpness and smoothness.
+ - [b]Normal:[/b] Use hinting on both X and Y axes. This results in a sharp font, but it doesn't look very smooth.
+ If set to [b]Auto[/b], the font hinting mode will be set to match the current operating system in use. This means the [b]Light[/b] hinting mode will be used on Windows and Linux, and the [b]None[/b] hinting mode will be used on macOS.
+ </member>
+ <member name="interface/editor/font_subpixel_positioning" type="int" setter="" getter="">
+ The subpixel positioning mode to use when rendering editor font glyphs. This affects both the main and code fonts. [b]Disabled[/b] is the fastest to render and uses the least memory. [b]Auto[/b] only uses subpixel positioning for small font sizes (where the benefit is the most noticeable). [b]One half of a pixel[/b] and [b]One quarter of a pixel[/b] force the same subpixel positioning mode for all editor fonts, regardless of their size (with [b]One quarter of a pixel[/b] being the highest-quality option).
+ </member>
+ <member name="interface/editor/low_processor_mode_sleep_usec" type="float" setter="" getter="">
+ The amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU/GPU usage, which can improve battery life on laptops. However, higher values will result in a less responsive editor. The default value is set to allow for maximum smoothness on monitors up to 144 Hz. See also [member interface/editor/unfocused_low_processor_mode_sleep_usec].
+ </member>
+ <member name="interface/editor/main_font" type="String" setter="" getter="">
+ The font to use for the editor interface. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file.
+ </member>
+ <member name="interface/editor/main_font_bold" type="String" setter="" getter="">
+ The font to use for bold text in the editor interface. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file.
+ </member>
+ <member name="interface/editor/main_font_size" type="int" setter="" getter="">
+ The size of the font in the editor interface.
+ </member>
+ <member name="interface/editor/mouse_extra_buttons_navigate_history" type="bool" setter="" getter="">
+ If [code]true[/code], the mouse's additional side buttons will be usable to navigate in the script editor's file history. Set this to [code]false[/code] if you're using the side buttons for other purposes (such as a push-to-talk button in a VoIP program).
+ </member>
+ <member name="interface/editor/save_each_scene_on_quit" type="bool" setter="" getter="">
+ If [code]true[/code], the editor will save all scenes when confirming the [b]Save[/b] action when quitting the editor or quitting to the project list. If [code]false[/code], the editor will ask to save each scene individually.
+ </member>
+ <member name="interface/editor/separate_distraction_mode" type="bool" setter="" getter="">
+ If [code]true[/code], the editor's Script tab will have a separate distraction mode setting from the 2D/3D/AssetLib tabs. If [code]false[/code], the distraction-free mode toggle is shared between all tabs.
+ </member>
+ <member name="interface/editor/show_internal_errors_in_toast_notifications" type="int" setter="" getter="">
+ If enabled, displays internal engine errors in toast notifications (toggleable by clicking the "bell" icon at the bottom of the editor). No matter the value of this setting, non-internal engine errors will always be visible in toast notifications.
+ The default [b]Auto[/b] value will only enable this if the editor was compiled with the [code]dev=yes[/code] option (the default is [code]dev=no[/code]).
+ </member>
+ <member name="interface/editor/single_window_mode" type="bool" setter="" getter="">
+ If [code]true[/code], embed modal windows such as docks inside the main editor window. When single-window mode is enabled, tooltips will also be embedded inside the main editor window, which means they can't be displayed outside of the editor window.
+ </member>
+ <member name="interface/editor/unfocused_low_processor_mode_sleep_usec" type="float" setter="" getter="">
+ When the editor window is unfocused, the amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU/GPU usage, which can improve battery life on laptops (in addition to improving the running project's performance if the editor has to redraw continuously). However, higher values will result in a less responsive editor. The default value is set to limit the editor to 20 FPS when the editor window is unfocused. See also [member interface/editor/low_processor_mode_sleep_usec].
+ </member>
+ <member name="interface/inspector/max_array_dictionary_items_per_page" type="int" setter="" getter="">
+ The number of [Array] or [Dictionary] items to display on each "page" in the inspector. Higher values allow viewing more values per page, but take more time to load. This increased load time is noticeable when selecting nodes that have array or dictionary properties in the editor.
+ </member>
+ <member name="interface/inspector/show_low_level_opentype_features" type="bool" setter="" getter="">
+ If [code]true[/code], display OpenType features marked as [code]hidden[/code] by the font file in the [Font] editor.
+ </member>
+ <member name="interface/scene_tabs/display_close_button" type="int" setter="" getter="">
+ Controls when the Close (X) button is displayed on scene tabs at the top of the editor.
+ </member>
+ <member name="interface/scene_tabs/maximum_width" type="int" setter="" getter="">
+ The maximum width of each scene tab at the top editor (in pixels).
+ </member>
+ <member name="interface/scene_tabs/show_script_button" type="bool" setter="" getter="">
+ If [code]true[/code], show a button next to each scene tab that opens the scene's "dominant" script when clicked. The "dominant" script is the one that is at the highest level in the scene's hierarchy.
+ </member>
+ <member name="interface/scene_tabs/show_thumbnail_on_hover" type="bool" setter="" getter="">
+ If [code]true[/code], display an automatically-generated thumbnail when hovering scene tabs with the mouse. Scene thumbnails are generated when saving the scene.
+ </member>
+ <member name="interface/theme/accent_color" type="Color" setter="" getter="">
+ The color to use for "highlighted" user interface elements in the editor (pressed and hovered items).
+ </member>
+ <member name="interface/theme/additional_spacing" type="float" setter="" getter="">
+ The spacing to add for buttons and list items in the editor (in pixels). Increasing this value is useful to improve usability on touch screens, at the cost of reducing the amount of usable screen real estate.
+ </member>
+ <member name="interface/theme/base_color" type="Color" setter="" getter="">
+ The base color to use for user interface elements in the editor. Secondary colors (such as darker/lighter variants) are derived from this color.
+ </member>
+ <member name="interface/theme/border_size" type="int" setter="" getter="">
+ The border size to use for interface elements (in pixels).
+ </member>
+ <member name="interface/theme/contrast" type="float" setter="" getter="">
+ The contrast factor to use when deriving the editor theme's base color (see [member interface/theme/base_color]). When using a positive values, the derived colors will be [i]darker[/i] than the base color. This contrast factor can be set to a negative value, which will make the derived colors [i]brighter[/i] than the base color. Negative contrast rates often look better for light themes.
+ </member>
+ <member name="interface/theme/corner_radius" type="int" setter="" getter="">
+ The corner radius to use for interface elements (in pixels). [code]0[/code] is square.
+ </member>
+ <member name="interface/theme/custom_theme" type="String" setter="" getter="">
+ The custom theme resource to use for the editor. Must be a Godot theme resource in [code].tres[/code] or [code].res[/code] format.
+ </member>
+ <member name="interface/theme/icon_and_font_color" type="int" setter="" getter="">
+ The icon and font color scheme to use in the editor.
+ - [b]Auto[/b] determines the color scheme to use automatically based on [member interface/theme/base_color].
+ - [b]Dark[/b] makes fonts and icons light (suitable for dark themes).
+ - [b]Light[/b] makes fonts and icons dark (suitable for light themes). Icon colors are automatically converted by the editor following [url=https://github.com/godotengine/godot/blob/master/editor/editor_themes.cpp#L135]this set of rules[/url].
+ </member>
+ <member name="interface/theme/icon_saturation" type="float" setter="" getter="">
+ The saturation to use for editor icons. Higher values result in more vibrant colors.
+ [b]Note:[/b] The default editor icon saturation was increased by 30% in Godot 4.0 and later. To get Godot 3.x's icon saturation back, set [member interface/theme/icon_saturation] to [code]0.77[/code].
+ </member>
+ <member name="interface/theme/preset" type="String" setter="" getter="">
+ The editor theme preset to use.
+ </member>
+ <member name="interface/theme/relationship_line_opacity" type="float" setter="" getter="">
+ The opacity to use when drawing relationship lines in the editor's [Tree]-based GUIs (such as the Scene tree dock).
+ </member>
+ <member name="network/debug/remote_host" type="String" setter="" getter="">
+ The address to listen to when starting the remote debugger. This can be set to [code]0.0.0.0[/code] to allow external clients to connect to the remote debugger (instead of restricting the remote debugger to connections from [code]localhost[/code]).
+ </member>
+ <member name="network/debug/remote_port" type="int" setter="" getter="">
+ The port to listen to when starting the remote debugger. Godot will try to use port numbers above the configured number if the configured number is already taken by another application.
+ </member>
+ <member name="network/http_proxy/host" type="String" setter="" getter="">
+ The host to use to contact the HTTP and HTTPS proxy in the editor (for the asset library and export template downloads). See also [member network/http_proxy/port].
+ [b]Note:[/b] Godot currently doesn't automatically use system proxy settings, so you have to enter them manually here if needed.
+ </member>
+ <member name="network/http_proxy/port" type="int" setter="" getter="">
+ The port number to use to contact the HTTP and HTTPS proxy in the editor (for the asset library and export template downloads). See also [member network/http_proxy/host].
+ [b]Note:[/b] Godot currently doesn't automatically use system proxy settings, so you have to enter them manually here if needed.
+ </member>
+ <member name="network/ssl/editor_ssl_certificates" type="String" setter="" getter="">
+ The SSL certificate bundle to use for HTTP requests made within the editor (e.g. from the AssetLib tab). If left empty, the [url=https://github.com/godotengine/godot/blob/master/thirdparty/certs/ca-certificates.crt]included Mozilla certificate bundle[/url] will be used.
+ </member>
+ <member name="project_manager/sorting_order" type="int" setter="" getter="">
+ The sorting order to use in the project manager. When changing the sorting order in the project manager, this setting is set permanently in the editor settings.
+ </member>
+ <member name="run/auto_save/save_before_running" type="bool" setter="" getter="">
+ If [code]true[/code], saves all scenes and scripts automatically before running the project. Setting this to [code]false[/code] prevents the editor from saving if there are no changes which can speed up the project startup slightly, but it makes it possible to run a project that has unsaved changes. (Unsaved changes will not be visible in the running project.)
+ </member>
+ <member name="run/output/always_clear_output_on_play" type="bool" setter="" getter="">
+ If [code]true[/code], the editor will clear the Output panel when running the project.
+ </member>
+ <member name="run/output/always_close_output_on_stop" type="bool" setter="" getter="">
+ If [code]true[/code], the editor will collapse the Output panel when stopping the project.
+ </member>
+ <member name="run/output/always_open_output_on_play" type="bool" setter="" getter="">
+ If [code]true[/code], the editor will expand the Output panel when running the project.
+ </member>
+ <member name="run/output/font_size" type="int" setter="" getter="">
+ The size of the font in the [b]Output[/b] panel at the bottom of the editor. This setting does not impact the font size of the script editor (see [member interface/editor/code_font_size]).
+ </member>
+ <member name="run/window_placement/rect" type="int" setter="" getter="">
+ The window mode to use to display the project when starting the project from the editor.
+ </member>
+ <member name="run/window_placement/rect_custom_position" type="Vector2" setter="" getter="">
+ The custom position to use when starting the project from the editor (in pixels from the top-left corner). Only effective if [member run/window_placement/rect] is set to [b]Custom Position[/b].
+ </member>
+ <member name="run/window_placement/screen" type="int" setter="" getter="">
+ The monitor to display the project on when starting the project from the editor.
+ </member>
+ <member name="text_editor/appearance/caret/caret_blink" type="bool" setter="" getter="">
+ If [code]true[/code], makes the caret blink according to [member text_editor/appearance/caret/caret_blink_speed]. Disabling this setting can improve battery life on laptops if you spend long amounts of time in the script editor, since it will reduce the frequency at which the editor needs to be redrawn.
+ </member>
+ <member name="text_editor/appearance/caret/caret_blink_speed" type="float" setter="" getter="">
+ The interval at which to blink the caret (in seconds). See also [member text_editor/appearance/caret/caret_blink].
+ </member>
+ <member name="text_editor/appearance/caret/highlight_all_occurrences" type="bool" setter="" getter="">
+ If [code]true[/code], highlights all occurrences of the currently selected text in the script editor. See also [member text_editor/theme/highlighting/word_highlighted_color].
+ </member>
+ <member name="text_editor/appearance/caret/highlight_current_line" type="bool" setter="" getter="">
+ If [code]true[/code], colors the background of the line the caret is currently on with [member text_editor/theme/highlighting/current_line_color].
+ </member>
+ <member name="text_editor/appearance/caret/type" type="int" setter="" getter="">
+ The shape of the caret to use in the script editor. [b]Line[/b] displays a vertical line to the left of the current character, whereas [b]Block[/b] displays a outline over the current character.
+ </member>
+ <member name="text_editor/appearance/guidelines/line_length_guideline_hard_column" type="int" setter="" getter="">
+ The column at which to display a subtle line as a line length guideline for scripts. This should generally be greater than [member text_editor/appearance/guidelines/line_length_guideline_soft_column].
+ </member>
+ <member name="text_editor/appearance/guidelines/line_length_guideline_soft_column" type="int" setter="" getter="">
+ The column at which to display a [i]very[/i] subtle line as a line length guideline for scripts. This should generally be lower than [member text_editor/appearance/guidelines/line_length_guideline_hard_column].
+ </member>
+ <member name="text_editor/appearance/guidelines/show_line_length_guidelines" type="bool" setter="" getter="">
+ If [code]true[/code], displays line length guidelines to help you keep line lengths in check. See also [member text_editor/appearance/guidelines/line_length_guideline_soft_column] and [member text_editor/appearance/guidelines/line_length_guideline_hard_column].
+ </member>
+ <member name="text_editor/appearance/gutters/highlight_type_safe_lines" type="bool" setter="" getter="">
+ If [code]true[/code], highlights type-safe lines by displaying their line number color with [member text_editor/theme/highlighting/safe_line_number_color] instead of [member text_editor/theme/highlighting/line_number_color]. Type-safe lines are lines of code where the type of all variables is known at compile-time. These type-safe lines will run faster in Godot 4.0 and later thanks to typed instructions.
+ </member>
+ <member name="text_editor/appearance/gutters/line_numbers_zero_padded" type="bool" setter="" getter="">
+ If [code]true[/code], displays line numbers with zero padding (e.g. [code]007[/code] instead of [code]7[/code]).
+ </member>
+ <member name="text_editor/appearance/gutters/show_bookmark_gutter" type="bool" setter="" getter="">
+ If [code]true[/code], displays a gutter at the left containing icons for bookmarks.
+ </member>
+ <member name="text_editor/appearance/gutters/show_info_gutter" type="bool" setter="" getter="">
+ If [code]true[/code], displays a gutter at the left containing icons for methods with signal connections.
+ </member>
+ <member name="text_editor/appearance/gutters/show_line_numbers" type="bool" setter="" getter="">
+ If [code]true[/code], displays line numbers in the gutter at the left.
+ </member>
+ <member name="text_editor/appearance/lines/code_folding" type="bool" setter="" getter="">
+ If [code]true[/code], displays the folding arrows next to indented code sections and allows code folding. If [code]false[/code], hides the folding arrows next to indented code sections and disallows code folding.
+ </member>
+ <member name="text_editor/appearance/lines/word_wrap" type="int" setter="" getter="">
+ If [code]true[/code], wraps long lines over multiple lines to avoid horizontal scrolling. This is a display-only feature; it does not actually insert line breaks in your scripts.
+ </member>
+ <member name="text_editor/appearance/minimap/minimap_width" type="int" setter="" getter="">
+ The width of the minimap in the script editor (in pixels).
+ </member>
+ <member name="text_editor/appearance/minimap/show_minimap" type="bool" setter="" getter="">
+ If [code]true[/code], draws an overview of the script near the scroll bar. The minimap can be left-clicked to scroll directly to a location in an "absolute" manner.
+ </member>
+ <member name="text_editor/appearance/whitespace/draw_spaces" type="bool" setter="" getter="">
+ If [code]true[/code], draws space characters as centered points.
+ </member>
+ <member name="text_editor/appearance/whitespace/draw_tabs" type="bool" setter="" getter="">
+ If [code]true[/code], draws tab characters as chevrons.
+ </member>
+ <member name="text_editor/appearance/whitespace/line_spacing" type="int" setter="" getter="">
+ The space to add between lines (in pixels). Greater line spacing can help improve readability at the cost of displaying less lines on screen.
+ </member>
+ <member name="text_editor/behavior/files/auto_reload_scripts_on_external_change" type="bool" setter="" getter="">
+ If [code]true[/code], automatically reloads scripts in the editor when they have been modified and saved by external editors.
+ </member>
+ <member name="text_editor/behavior/files/autosave_interval_secs" type="int" setter="" getter="">
+ If set to a value greater than [code]0[/code], automatically saves the current script following the specified interval (in seconds). This can be used to prevent data loss if the editor crashes.
+ </member>
+ <member name="text_editor/behavior/files/convert_indent_on_save" type="bool" setter="" getter="">
+ If [code]true[/code], converts indentation to match the script editor's indentation settings when saving a script. See also [member text_editor/behavior/indent/type].
+ </member>
+ <member name="text_editor/behavior/files/restore_scripts_on_load" type="bool" setter="" getter="">
+ If [code]true[/code], reopens scripts that were opened in the last session when the editor is reopened on a given project.
+ </member>
+ <member name="text_editor/behavior/files/trim_trailing_whitespace_on_save" type="bool" setter="" getter="">
+ If [code]true[/code], trims trailing whitespace when saving a script. Trailing whitespace refers to tab and space characters placed at the end of lines. Since these serve no practical purpose, they can and should be removed to make version control diffs less noisy.
+ </member>
+ <member name="text_editor/behavior/indent/auto_indent" type="bool" setter="" getter="">
+ If [code]true[/code], automatically indents code when pressing the [kbd]Enter[/kbd] key based on blocks above the new line.
+ </member>
+ <member name="text_editor/behavior/indent/size" type="int" setter="" getter="">
+ When using tab indentation, determines the length of each tab. When using space indentation, determines how many spaces are inserted when pressing [kbd]Tab[/kbd] and when automatic indentation is performed.
+ </member>
+ <member name="text_editor/behavior/indent/type" type="int" setter="" getter="">
+ The indentation style to use (tabs or spaces).
+ [b]Note:[/b] The [url=https://docs.godotengine.org/en/latest/getting_started/scripting/gdscript/gdscript_styleguide.html]GDScript style guide[/url] recommends using tabs for indentation. It is advised to change this setting only if you need to work on a project that currently uses spaces for indentation.
+ </member>
+ <member name="text_editor/behavior/navigation/drag_and_drop_selection" type="bool" setter="" getter="">
+ If [code]true[/code], allows drag-and-dropping text in the script editor to move text. Disable this if you find yourself accidentally drag-and-dropping text in the script editor.
+ </member>
+ <member name="text_editor/behavior/navigation/move_caret_on_right_click" type="bool" setter="" getter="">
+ If [code]true[/code], the caret will be moved when right-clicking somewhere in the script editor (like when left-clicking or middle-clicking). If [code]false[/code], the caret will only be moved when left-clicking or middle-clicking somewhere.
+ </member>
+ <member name="text_editor/behavior/navigation/scroll_past_end_of_file" type="bool" setter="" getter="">
+ If [code]true[/code], allows scrolling past the end of the file.
+ </member>
+ <member name="text_editor/behavior/navigation/smooth_scrolling" type="bool" setter="" getter="">
+ If [code]true[/code], allows scrolling in sub-line intervals and enables a smooth scrolling animation when using the mouse wheel to scroll.
+ [b]Note:[/b] [member text_editor/behavior/navigation/smooth_scrolling] currently behaves poorly in projects where [member ProjectSettings.physics/common/physics_ticks_per_second] has been increased significantly from its default value ([code]60[/code]). In this case, it is recommended to disable this setting.
+ </member>
+ <member name="text_editor/behavior/navigation/stay_in_script_editor_on_node_selected" type="bool" setter="" getter="">
+ If [code]true[/code], prevents automatically switching between the Script and 2D/3D screens when selecting a node in the Scene tree dock.
+ </member>
+ <member name="text_editor/behavior/navigation/v_scroll_speed" type="int" setter="" getter="">
+ The number of pixels to scroll with every mouse wheel increment. Higher values make the script scroll by faster when using the mouse wheel.
+ [b]Note:[/b] You can hold down [kbd]Alt[/kbd] while using the mouse wheel to temporarily scroll 5 times faster.
+ </member>
+ <member name="text_editor/completion/add_type_hints" type="bool" setter="" getter="">
+ If [code]true[/code], adds static typing hints such as [code]-&gt; void[/code] and [code]: int[/code] when performing method definition autocompletion.
+ </member>
+ <member name="text_editor/completion/auto_brace_complete" type="bool" setter="" getter="">
+ If [code]true[/code], automatically completes braces when making use of code completion.
+ </member>
+ <member name="text_editor/completion/code_complete_delay" type="float" setter="" getter="">
+ The delay in seconds after which autocompletion suggestions should be displayed when the user stops typing.
+ </member>
+ <member name="text_editor/completion/complete_file_paths" type="bool" setter="" getter="">
+ If [code]true[/code], provides autocompletion suggestions for file paths in methods such as [code]load()[/code] and [code]preload()[/code].
+ </member>
+ <member name="text_editor/completion/idle_parse_delay" type="float" setter="" getter="">
+ The delay in seconds after which the script editor should check for errors when the user stops typing.
+ </member>
+ <member name="text_editor/completion/put_callhint_tooltip_below_current_line" type="bool" setter="" getter="">
+ If [code]true[/code], the code completion tooltip will appear below the current line unless there is no space on screen below the current line. If [code]false[/code], the code completion tooltip will appear above the current line.
+ </member>
+ <member name="text_editor/completion/use_single_quotes" type="bool" setter="" getter="">
+ If [code]true[/code], performs string autocompletion with single quotes. If [code]false[/code], performs string autocompletion with double quotes (which matches the [url=https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/gdscript_styleguide.html]GDScript style guide[/url]).
+ </member>
+ <member name="text_editor/help/class_reference_examples" type="int" setter="" getter="">
+ Controls which multi-line code blocks should be displayed in the editor help. This setting does not affect single-line code literals in the editor help.
+ </member>
+ <member name="text_editor/help/help_font_size" type="int" setter="" getter="">
+ The font size to use for the editor help (built-in class reference).
+ </member>
+ <member name="text_editor/help/help_source_font_size" type="int" setter="" getter="">
+ The font size to use for code samples in the editor help (built-in class reference).
+ </member>
+ <member name="text_editor/help/help_title_font_size" type="int" setter="" getter="">
+ The font size to use for headings in the editor help (built-in class reference).
+ </member>
+ <member name="text_editor/help/show_help_index" type="bool" setter="" getter="">
+ If [code]true[/code], displays a table of contents at the left of the editor help (at the location where the members overview would appear when editing a script).
+ </member>
+ <member name="text_editor/script_list/show_members_overview" type="bool" setter="" getter="">
+ If [code]true[/code], displays an overview of the current script's member variables and functions at the left of the script editor. See also [member text_editor/script_list/sort_members_outline_alphabetically].
+ </member>
+ <member name="text_editor/script_list/sort_members_outline_alphabetically" type="bool" setter="" getter="">
+ If [code]true[/code], sorts the members outline (located at the left of the script editor) using alphabetical order. If [code]false[/code], sorts the members outline depending on the order in which members are found in the script.
+ [b]Note:[/b] Only effective if [member text_editor/script_list/show_members_overview] is [code]true[/code].
+ </member>
+ <member name="text_editor/theme/color_theme" type="String" setter="" getter="">
+ The syntax theme to use in the script editor.
+ You can save your own syntax theme from your current settings by using [b]File &gt; Theme &gt; Save As...[/b] at the top of the script editor. The syntax theme will then be available locally in the list of color themes.
+ You can find additional syntax themes to install in the [url=https://github.com/godotengine/godot-syntax-themes]godot-syntax-themes[/url] repository.
+ </member>
+ <member name="text_editor/theme/highlighting/background_color" type="Color" setter="" getter="">
+ The script editor's background color. If set to a translucent color, the editor theme's base color will be visible behind.
+ </member>
+ <member name="text_editor/theme/highlighting/base_type_color" type="Color" setter="" getter="">
+ The script editor's base type color (used for types like [Vector2], [Vector3], ...).
+ </member>
+ <member name="text_editor/theme/highlighting/bookmark_color" type="Color" setter="" getter="">
+ The script editor's bookmark icon color (displayed in the gutter).
+ </member>
+ <member name="text_editor/theme/highlighting/brace_mismatch_color" type="Color" setter="" getter="">
+ The script editor's brace mismatch color. Used when the caret is currently on a mismatched brace, parenthesis or bracket character.
+ </member>
+ <member name="text_editor/theme/highlighting/breakpoint_color" type="Color" setter="" getter="">
+ The script editor's breakpoint icon color (displayed in the gutter).
+ </member>
+ <member name="text_editor/theme/highlighting/caret_background_color" type="Color" setter="" getter="">
+ The script editor's caret background color.
+ [b]Note:[/b] This setting has no effect as it's currently unused.
+ </member>
+ <member name="text_editor/theme/highlighting/caret_color" type="Color" setter="" getter="">
+ The script editor's caret color.
+ </member>
+ <member name="text_editor/theme/highlighting/code_folding_color" type="Color" setter="" getter="">
+ The script editor's color for the code folding icon (displayed in the gutter).
+ </member>
+ <member name="text_editor/theme/highlighting/comment_color" type="Color" setter="" getter="">
+ The script editor's comment color.
+ [b]Note:[/b] In GDScript, unlike Python, multiline strings are not considered to be comments, and will use the string highlighting color instead.
+ </member>
+ <member name="text_editor/theme/highlighting/completion_background_color" type="Color" setter="" getter="">
+ The script editor's autocompletion box background color.
+ </member>
+ <member name="text_editor/theme/highlighting/completion_existing_color" type="Color" setter="" getter="">
+ The script editor's autocompletion box background color to highlight existing characters in the completion results. This should be a translucent color so that [member text_editor/theme/highlighting/completion_selected_color] can be seen behind.
+ </member>
+ <member name="text_editor/theme/highlighting/completion_font_color" type="Color" setter="" getter="">
+ The script editor's autocompletion box text color.
+ </member>
+ <member name="text_editor/theme/highlighting/completion_scroll_color" type="Color" setter="" getter="">
+ The script editor's autocompletion box scroll bar color.
+ </member>
+ <member name="text_editor/theme/highlighting/completion_scroll_hovered_color" type="Color" setter="" getter="">
+ The script editor's autocompletion box scroll bar color when hovered or pressed with the mouse.
+ </member>
+ <member name="text_editor/theme/highlighting/completion_selected_color" type="Color" setter="" getter="">
+ The script editor's autocompletion box background color for the currently selected line.
+ </member>
+ <member name="text_editor/theme/highlighting/control_flow_keyword_color" type="Color" setter="" getter="">
+ The script editor's control flow keyword color (used for keywords like [code]if[/code], [code]for[/code], [code]return[/code], ...).
+ </member>
+ <member name="text_editor/theme/highlighting/current_line_color" type="Color" setter="" getter="">
+ The script editor's background color for the line the caret is currently on. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/theme/highlighting/mark_color].
+ </member>
+ <member name="text_editor/theme/highlighting/engine_type_color" type="Color" setter="" getter="">
+ The script editor's engine type color ([Vector2], [Vector3], [Color], ...).
+ </member>
+ <member name="text_editor/theme/highlighting/executing_line_color" type="Color" setter="" getter="">
+ The script editor's color for the debugger's executing line icon (displayed in the gutter).
+ </member>
+ <member name="text_editor/theme/highlighting/function_color" type="Color" setter="" getter="">
+ The script editor's function call color.
+ [b]Note:[/b] When using the GDScript syntax highlighter, this is replaced by the function declaration color configured in the syntax theme for function declarations (e.g. [code]func _ready():[/code]).
+ </member>
+ <member name="text_editor/theme/highlighting/keyword_color" type="Color" setter="" getter="">
+ The script editor's non-control flow keyword color (used for keywords like [code]var[/code], [code]func[/code], some built-in methods, ...).
+ </member>
+ <member name="text_editor/theme/highlighting/line_length_guideline_color" type="Color" setter="" getter="">
+ The script editor's color for the line length guideline. The "hard" line length guideline will be drawn with this color, whereas the "soft" line length guideline will be drawn with an opacity twice as low.
+ </member>
+ <member name="text_editor/theme/highlighting/line_number_color" type="Color" setter="" getter="">
+ The script editor's color for line numbers. See also [member text_editor/theme/highlighting/safe_line_number_color].
+ </member>
+ <member name="text_editor/theme/highlighting/mark_color" type="Color" setter="" getter="">
+ The script editor's background color for lines with errors. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/theme/highlighting/current_line_color].
+ </member>
+ <member name="text_editor/theme/highlighting/member_variable_color" type="Color" setter="" getter="">
+ The script editor's color for member variables on objects (e.g. [code]self.some_property[/code]).
+ [b]Note:[/b] This color is not used for local variable declaration and access.
+ </member>
+ <member name="text_editor/theme/highlighting/number_color" type="Color" setter="" getter="">
+ The script editor's color for numbers (integer and floating-point).
+ </member>
+ <member name="text_editor/theme/highlighting/safe_line_number_color" type="Color" setter="" getter="">
+ The script editor's color for type-safe line numbers. See also [member text_editor/theme/highlighting/line_number_color].
+ [b]Note:[/b] Only displayed if [member text_editor/appearance/gutters/highlight_type_safe_lines] is [code]true[/code].
+ </member>
+ <member name="text_editor/theme/highlighting/search_result_border_color" type="Color" setter="" getter="">
+ The script editor's color for the border of search results. This border helps bring further attention to the search result. Set this color's opacity to 0 to disable the border.
+ </member>
+ <member name="text_editor/theme/highlighting/search_result_color" type="Color" setter="" getter="">
+ The script editor's background color for search results.
+ </member>
+ <member name="text_editor/theme/highlighting/selection_color" type="Color" setter="" getter="">
+ The script editor's background color for the currently selected text.
+ </member>
+ <member name="text_editor/theme/highlighting/string_color" type="Color" setter="" getter="">
+ The script editor's color for strings (single-line and multi-line).
+ </member>
+ <member name="text_editor/theme/highlighting/symbol_color" type="Color" setter="" getter="">
+ The script editor's color for operators ([code]( ) [ ] { } + - * /[/code], ...).
+ </member>
+ <member name="text_editor/theme/highlighting/text_color" type="Color" setter="" getter="">
+ The script editor's color for text not highlighted by any syntax highlighting rule.
+ </member>
+ <member name="text_editor/theme/highlighting/text_selected_color" type="Color" setter="" getter="">
+ The script editor's background color for text. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/theme/highlighting/current_line_color].
+ </member>
+ <member name="text_editor/theme/highlighting/user_type_color" type="Color" setter="" getter="">
+ The script editor's color for user-defined types (using [code]@class_name[/code]).
+ </member>
+ <member name="text_editor/theme/highlighting/word_highlighted_color" type="Color" setter="" getter="">
+ The script editor's color for words highlighted by selecting them. Only visible if [member text_editor/appearance/caret/highlight_all_occurrences] is [code]true[/code].
+ </member>
+ </members>
<signals>
<signal name="settings_changed">
<description>
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index 506992e3af..36dfee833b 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -151,6 +151,12 @@
[/codeblocks]
</description>
</method>
+ <method name="get_write_movie_path" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the path to the [MovieWriter]'s output file, or an empty string if the engine wasn't started in Movie Maker mode. This path can be absolute or relative depending on how the user specified it.
+ </description>
+ </method>
<method name="has_singleton" qualifiers="const">
<return type="bool" />
<argument index="0" name="name" type="StringName" />
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 9da360915b..f662a07825 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -97,7 +97,7 @@
Blend factor between the fog's color and the color of the background [Sky]. Must have [member background_mode] set to [constant BG_SKY].
This is useful to simulate [url=https://en.wikipedia.org/wiki/Aerial_perspective]aerial perspective[/url] in large scenes with low density fog. However, it is not very useful for high-density fog, as the sky will shine through. When set to [code]1.0[/code], the fog color comes completely from the [Sky]. If set to [code]0.0[/code], aerial perspective is disabled.
</member>
- <member name="fog_density" type="float" setter="set_fog_density" getter="get_fog_density" default="0.001">
+ <member name="fog_density" type="float" setter="set_fog_density" getter="get_fog_density" default="0.01">
The exponential fog density to use. Higher values result in a more dense fog.
</member>
<member name="fog_enabled" type="bool" setter="set_fog_enabled" getter="is_fog_enabled" default="false">
@@ -109,7 +109,7 @@
<member name="fog_height_density" type="float" setter="set_fog_height_density" getter="get_fog_height_density" default="0.0">
The density used to increase fog as height decreases. To make fog increase as height increases, use a negative value.
</member>
- <member name="fog_light_color" type="Color" setter="set_fog_light_color" getter="get_fog_light_color" default="Color(0.5, 0.6, 0.7, 1)">
+ <member name="fog_light_color" type="Color" setter="set_fog_light_color" getter="get_fog_light_color" default="Color(0.518, 0.553, 0.608, 1)">
The fog's color.
</member>
<member name="fog_light_energy" type="float" setter="set_fog_light_energy" getter="get_fog_light_energy" default="1.0">
@@ -320,8 +320,9 @@
<member name="volumetric_fog_enabled" type="bool" setter="set_volumetric_fog_enabled" getter="is_volumetric_fog_enabled" default="false">
Enables the volumetric fog effect. Volumetric fog uses a screen-aligned froxel buffer to calculate accurate volumetric scattering in the short to medium range. Volumetric fog interacts with [FogVolume]s and lights to calculate localized and global fog. Volumetric fog uses a PBR single-scattering model based on extinction, scattering, and emission which it exposes to users as density, albedo, and emission.
</member>
- <member name="volumetric_fog_gi_inject" type="float" setter="set_volumetric_fog_gi_inject" getter="get_volumetric_fog_gi_inject" default="0.0">
- Scales the strength of Global Illumination used in the volumetric fog. A value of [code]0[/code] means that Global Illumination will not impact the volumetric fog.
+ <member name="volumetric_fog_gi_inject" type="float" setter="set_volumetric_fog_gi_inject" getter="get_volumetric_fog_gi_inject" default="1.0">
+ Scales the strength of Global Illumination used in the volumetric fog. A value of [code]0.0[/code] means that Global Illumination will not impact the volumetric fog.
+ [b]Note:[/b] Only [VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) are taken into account when using [member volumetric_fog_gi_inject]. Global illumination from [LightmapGI], [ReflectionProbe] and SSIL (see [member ssil_enabled]) will be ignored by volumetric fog.
</member>
<member name="volumetric_fog_length" type="float" setter="set_volumetric_fog_length" getter="get_volumetric_fog_length" default="64.0">
The distance over which the volumetric fog is computed. Increase to compute fog over a greater range, decrease to add more detail when a long range is not needed. For best quality fog, keep this as low as possible.
diff --git a/doc/classes/File.xml b/doc/classes/File.xml
index 0b4a8fa46e..3a2776ff21 100644
--- a/doc/classes/File.xml
+++ b/doc/classes/File.xml
@@ -115,9 +115,10 @@
</method>
<method name="get_as_text" qualifiers="const">
<return type="String" />
+ <argument index="0" name="skip_cr" type="bool" default="false" />
<description>
- Returns the whole file as a [String].
- Text is interpreted as being UTF-8 encoded.
+ Returns the whole file as a [String]. Text is interpreted as being UTF-8 encoded.
+ If [code]skip_cr[/code] is [code]true[/code], carriage return characters ([code]\r[/code], CR) will be ignored when parsing the UTF-8, so that only line feed characters ([code]\n[/code], LF) represent a new line (Unix convention).
</description>
</method>
<method name="get_buffer" qualifiers="const">
diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml
index 9d55704604..f45031cea8 100644
--- a/doc/classes/FileDialog.xml
+++ b/doc/classes/FileDialog.xml
@@ -12,10 +12,11 @@
<method name="add_filter">
<return type="void" />
<argument index="0" name="filter" type="String" />
+ <argument index="1" name="description" type="String" default="&quot;&quot;" />
<description>
- Adds [code]filter[/code] to the list of filters, which restricts what files can be picked.
- A [code]filter[/code] should be of the form [code]"filename.extension ; Description"[/code], where filename and extension can be [code]*[/code] to match any string. Filters starting with [code].[/code] (i.e. empty filenames) are not allowed.
- Example filters: [code]"*.png ; PNG Images"[/code], [code]"project.godot ; Godot Project"[/code].
+ Adds a comma-delimited file name [code]filter[/code] option to the [FileDialog] with an optional [code]description[/code], which restricts what files can be picked.
+ A [code]filter[/code] should be of the form [code]"filename.extension"[/code], where filename and extension can be [code]*[/code] to match any string. Filters starting with [code].[/code] (i.e. empty filenames) are not allowed.
+ For example, a [code]filter[/code] of [code]"*.png, *.jpg"[/code] and a [code]description[/code] of [code]"Images"[/code] results in filter text "Images (*.png, *.jpg)".
</description>
</method>
<method name="clear_filters">
@@ -75,6 +76,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..ec2776f636 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="font_size" type="int" />
+ <argument index="4" name="modulate" 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="3" name="font_size" type="int" />
+ <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>
- 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,38 @@
<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="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" />
+ <argument index="9" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" />
+ <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 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="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" />
+ <argument index="10" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" />
+ <argument index="11" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="12" 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 +80,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="jst_flags" type="int" enum="TextServer.JustificationFlag" 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="jst_flags" type="int" enum="TextServer.JustificationFlag" 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 +129,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="font_size" 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" enum="TextServer.FontStyle" />
+ <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 +184,29 @@
<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="brk_flags" type="int" enum="TextServer.LineBreakFlag" default="3" />
+ <argument index="6" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" />
+ <argument index="7" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="8" 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,14 +219,19 @@
<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="4" name="flags" type="int" default="3" />
+ <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="jst_flags" type="int" enum="TextServer.JustificationFlag" 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.
+ Returns the size of a bounding box of a single-line string, taking kerning and advance into account. See also [method get_multiline_string_size] and [method draw_string].
+ For example, to get the string size as displayed by a single-line Label, use:
+ [codeblock]
+ var string_size = $Label.get_theme_font("font").get_string_size($Label.text, HORIZONTAL_ALIGNMENT_LEFT, -1, $Label.get_theme_font_size("font_size"))
+ [/codeblock]
[b]Note:[/b] Real height of the string is context-dependent and can be significantly different from the value returned by [method get_height].
- See also [method draw_string].
</description>
</method>
<method name="get_supported_chars" qualifiers="const">
@@ -224,9 +241,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 +264,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 +277,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..dc2cbdde63 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.
+ </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.
@@ -586,7 +558,7 @@
<member name="font_name" type="String" setter="set_font_name" getter="get_font_name" default="&quot;&quot;">
Font family name.
</member>
- <member name="font_style" type="int" setter="set_font_style" getter="get_font_style" default="0">
+ <member name="font_style" type="int" setter="set_font_style" getter="get_font_style" enum="TextServer.FontStyle" default="0">
Font style flags, see [enum TextServer.FontStyle].
</member>
<member name="force_autohinter" type="bool" setter="set_force_autohinter" getter="is_force_autohinter" default="false">
@@ -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/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml
index 53894bad87..e60ab094c6 100644
--- a/doc/classes/GPUParticles2D.xml
+++ b/doc/classes/GPUParticles2D.xml
@@ -63,8 +63,8 @@
<member name="lifetime" type="float" setter="set_lifetime" getter="get_lifetime" default="1.0">
Amount of time each particle will exist.
</member>
- <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="true">
- If [code]true[/code], particles use the parent node's coordinate space. If [code]false[/code], they use global coordinates.
+ <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="false">
+ If [code]true[/code], particles use the parent node's coordinate space (known as local coordinates). This will cause particles to move and rotate along the [GPUParticles2D] node (and its parents) when it is moved or rotated. If [code]false[/code], particles use global coordinates; they will not move or rotate along the [GPUParticles2D] node (and its parents) when it is moved or rotated.
</member>
<member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot" default="false">
If [code]true[/code], only one emission cycle occurs. If set [code]true[/code] during a cycle, emission will stop at the cycle's end.
diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml
index c4bd18db69..b415c56154 100644
--- a/doc/classes/GPUParticles3D.xml
+++ b/doc/classes/GPUParticles3D.xml
@@ -95,8 +95,8 @@
<member name="lifetime" type="float" setter="set_lifetime" getter="get_lifetime" default="1.0">
Amount of time each particle will exist.
</member>
- <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="true">
- If [code]true[/code], particles use the parent node's coordinate space. If [code]false[/code], they use global coordinates.
+ <member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="false">
+ If [code]true[/code], particles use the parent node's coordinate space (known as local coordinates). This will cause particles to move and rotate along the [GPUParticles3D] node (and its parents) when it is moved or rotated. If [code]false[/code], particles use global coordinates; they will not move or rotate along the [GPUParticles3D] node (and its parents) when it is moved or rotated.
</member>
<member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot" default="false">
If [code]true[/code], only [code]amount[/code] particles will be emitted.
diff --git a/doc/classes/GPUParticlesCollisionSDF3D.xml b/doc/classes/GPUParticlesCollisionSDF3D.xml
index c9af07288e..bc8b3c7c11 100644
--- a/doc/classes/GPUParticlesCollisionSDF3D.xml
+++ b/doc/classes/GPUParticlesCollisionSDF3D.xml
@@ -13,7 +13,27 @@
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="get_bake_mask_value" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="layer_number" type="int" />
+ <description>
+ Returns whether or not the specified layer of the [member bake_mask] is enabled, given a [code]layer_number[/code] between 1 and 32.
+ </description>
+ </method>
+ <method name="set_bake_mask_value">
+ <return type="void" />
+ <argument index="0" name="layer_number" type="int" />
+ <argument index="1" name="value" type="bool" />
+ <description>
+ Based on [code]value[/code], enables or disables the specified layer in the [member bake_mask], given a [code]layer_number[/code] between 1 and 32.
+ </description>
+ </method>
+ </methods>
<members>
+ <member name="bake_mask" type="int" setter="set_bake_mask" getter="get_bake_mask" default="4294967295">
+ The visual layers to account for when baking the particle collision SDF. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated particle collision SDF. By default, all objects are taken into account for the particle collision SDF baking.
+ </member>
<member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)">
The collision SDF's extents in 3D units. To improve SDF quality, the [member extents] should be set as small as possible while covering the parts of the scene you need.
</member>
diff --git a/doc/classes/Geometry2D.xml b/doc/classes/Geometry2D.xml
index b84e221d1c..a4cfa1ddff 100644
--- a/doc/classes/Geometry2D.xml
+++ b/doc/classes/Geometry2D.xml
@@ -126,7 +126,7 @@
<return type="Dictionary" />
<argument index="0" name="sizes" type="PackedVector2Array" />
<description>
- Given an array of [Vector2]s representing tiles, builds an atlas. The returned dictionary has two keys: [code]points[/code] is a vector of [Vector2] that specifies the positions of each tile, [code]size[/code] contains the overall size of the whole atlas as [Vector2].
+ Given an array of [Vector2]s representing tiles, builds an atlas. The returned dictionary has two keys: [code]points[/code] is an array of [Vector2] that specifies the positions of each tile, [code]size[/code] contains the overall size of the whole atlas as [Vector2].
</description>
</method>
<method name="merge_polygons">
@@ -188,6 +188,16 @@
Returns if [code]point[/code] is inside the triangle specified by [code]a[/code], [code]b[/code] and [code]c[/code].
</description>
</method>
+ <method name="segment_intersects_circle">
+ <return type="float" />
+ <argument index="0" name="segment_from" type="Vector2" />
+ <argument index="1" name="segment_to" type="Vector2" />
+ <argument index="2" name="circle_position" type="Vector2" />
+ <argument index="3" name="circle_radius" type="float" />
+ <description>
+ Given the 2D segment ([code]segment_from[/code], [code]segment_to[/code]), returns the position on the segment (as a number between 0 and 1) at which the segment hits the circle that is located at position [code]circle_position[/code] and has radius [code]circle_radius[/code]. If the segment does not intersect the circle, -1 is returned (this is also the case if the line extending the segment would intersect the circle, but the segment does not).
+ </description>
+ </method>
<method name="segment_intersects_segment">
<return type="Variant" />
<argument index="0" name="from_a" type="Vector2" />
diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml
index c803f43fb0..365efa6761 100644
--- a/doc/classes/GeometryInstance3D.xml
+++ b/doc/classes/GeometryInstance3D.xml
@@ -9,7 +9,7 @@
<tutorials>
</tutorials>
<methods>
- <method name="get_shader_instance_uniform" qualifiers="const">
+ <method name="get_instance_shader_uniform" qualifiers="const">
<return type="Variant" />
<argument index="0" name="uniform" type="StringName" />
<description>
@@ -22,7 +22,7 @@
Overrides the bounding box of this node with a custom one. To remove it, set an [AABB] with all fields set to zero.
</description>
</method>
- <method name="set_shader_instance_uniform">
+ <method name="set_instance_shader_uniform">
<return type="void" />
<argument index="0" name="uniform" type="StringName" />
<argument index="1" name="value" type="Variant" />
diff --git a/doc/classes/Gradient.xml b/doc/classes/Gradient.xml
index 89c968cc9e..8c5373216a 100644
--- a/doc/classes/Gradient.xml
+++ b/doc/classes/Gradient.xml
@@ -5,6 +5,7 @@
</brief_description>
<description>
Given a set of colors, this resource will interpolate them in order. This means that if you have color 1, color 2 and color 3, the gradient will interpolate from color 1 to color 2 and from color 2 to color 3. The gradient will initially have 2 colors (black and white), one (black) at gradient lower offset 0 and the other (white) at the gradient higher offset 1.
+ See also [Curve] which supports more complex easing methods, but does not support colors.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml
index 965dbe7449..33145dccd0 100644
--- a/doc/classes/GraphEdit.xml
+++ b/doc/classes/GraphEdit.xml
@@ -55,6 +55,29 @@
[/codeblock]
</description>
</method>
+ <method name="_is_node_hover_valid" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="from" type="StringName" />
+ <argument index="1" name="from_slot" type="int" />
+ <argument index="2" name="to" type="StringName" />
+ <argument index="3" name="to_slot" type="int" />
+ <description>
+ This virtual method can be used to insert additional error detection while the user is dragging a connection over a valid port.
+ Return [code]true[/code] if the connection is indeed valid or return [code]false[/code] if the connection is impossible. If the connection is impossible, no snapping to the port and thus no connection request to that port will happen.
+ In this example a connection to same node is suppressed:
+ [codeblocks]
+ [gdscript]
+ func _is_node_hover_valid(from, from_slot, to, to_slot):
+ return from != to
+ [/gdscript]
+ [csharp]
+ public override bool _IsNodeHoverValid(String from, int fromSlot, String to, int toSlot) {
+ return from != to;
+ }
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
<method name="add_valid_connection_type">
<return type="void" />
<argument index="0" name="from_type" type="int" />
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/HTTPClient.xml b/doc/classes/HTTPClient.xml
index 5a9d12d01b..fb437b6d8e 100644
--- a/doc/classes/HTTPClient.xml
+++ b/doc/classes/HTTPClient.xml
@@ -4,7 +4,8 @@
Low-level hyper-text transfer protocol client.
</brief_description>
<description>
- Hyper-text transfer protocol client (sometimes called "User Agent"). Used to make HTTP requests to download web content, upload files and other data or to communicate with various services, among other use cases. [b]See the [HTTPRequest] node for a higher-level alternative.[/b]
+ Hyper-text transfer protocol client (sometimes called "User Agent"). Used to make HTTP requests to download web content, upload files and other data or to communicate with various services, among other use cases.
+ See the [HTTPRequest] node for a higher-level alternative.
[b]Note:[/b] This client only needs to connect to a host once (see [method connect_to_host]) to send multiple requests. Because of this, methods that take URLs usually take just the part after the host instead of the full URL, as the client is already connected to a host. See [method request] for a full example and to get started.
A [HTTPClient] should be reused between multiple requests or to connect to different hosts instead of creating one client per request. Supports SSL and SSL server certificate verification. HTTP status codes in the 2xx range indicate success, 3xx redirection (i.e. "try again, but over here"), 4xx something was wrong with the request, and 5xx something went wrong on the server's side.
For more information on HTTP, see https://developer.mozilla.org/en-US/docs/Web/HTTP (or read RFC 2616 to get it straight from the source: https://tools.ietf.org/html/rfc2616).
diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml
index 166923314f..3d2e9449e2 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()
@@ -252,6 +251,7 @@
Maximum number of allowed redirects.
</member>
<member name="timeout" type="float" setter="set_timeout" getter="get_timeout" default="0.0">
+ If set to a value greater than [code]0.0[/code] before the request starts, the HTTP request will time out after [code]timeout[/code] seconds have passed and the request is not [i]completed[/i] yet. For small HTTP requests such as REST API usage, set [member timeout] to a value between [code]10.0[/code] and [code]30.0[/code] to prevent the application from getting stuck if the request fails to get a response in a timely manner. For file downloads, leave this to [code]0.0[/code] to prevent the download from failing if it takes too much time.
</member>
<member name="use_threads" type="bool" setter="set_use_threads" getter="is_using_threads" default="false">
If [code]true[/code], multithreading is used to improve performance.
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 43b03ce65e..a927345e79 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -23,8 +23,8 @@
<method name="blend_rect">
<return type="void" />
<argument index="0" name="src" type="Image" />
- <argument index="1" name="src_rect" type="Rect2" />
- <argument index="2" name="dst" type="Vector2" />
+ <argument index="1" name="src_rect" type="Rect2i" />
+ <argument index="2" name="dst" type="Vector2i" />
<description>
Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dest[/code], clipped accordingly to both image bounds. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src_rect[/code] with not positive size is treated as empty.
</description>
@@ -33,8 +33,8 @@
<return type="void" />
<argument index="0" name="src" type="Image" />
<argument index="1" name="mask" type="Image" />
- <argument index="2" name="src_rect" type="Rect2" />
- <argument index="3" name="dst" type="Vector2" />
+ <argument index="2" name="src_rect" type="Rect2i" />
+ <argument index="3" name="dst" type="Vector2i" />
<description>
Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image using [code]mask[/code] image at coordinates [code]dst[/code], clipped accordingly to both image bounds. Alpha channels are required for both [code]src[/code] and [code]mask[/code]. [code]dst[/code] pixels and [code]src[/code] pixels will blend if the corresponding mask pixel's alpha value is not 0. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats. [code]src_rect[/code] with not positive size is treated as empty.
</description>
@@ -42,8 +42,8 @@
<method name="blit_rect">
<return type="void" />
<argument index="0" name="src" type="Image" />
- <argument index="1" name="src_rect" type="Rect2" />
- <argument index="2" name="dst" type="Vector2" />
+ <argument index="1" name="src_rect" type="Rect2i" />
+ <argument index="2" name="dst" type="Vector2i" />
<description>
Copies [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dst[/code], clipped accordingly to both image bounds. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src_rect[/code] with not positive size is treated as empty.
</description>
@@ -52,8 +52,8 @@
<return type="void" />
<argument index="0" name="src" type="Image" />
<argument index="1" name="mask" type="Image" />
- <argument index="2" name="src_rect" type="Rect2" />
- <argument index="3" name="dst" type="Vector2" />
+ <argument index="2" name="src_rect" type="Rect2i" />
+ <argument index="3" name="dst" type="Vector2i" />
<description>
Blits [code]src_rect[/code] area from [code]src[/code] image to this image at the coordinates given by [code]dst[/code], clipped accordingly to both image bounds. [code]src[/code] pixel is copied onto [code]dst[/code] if the corresponding [code]mask[/code] pixel's alpha value is not 0. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats. [code]src_rect[/code] with not positive size is treated as empty.
</description>
@@ -168,7 +168,7 @@
</method>
<method name="fill_rect">
<return type="void" />
- <argument index="0" name="rect" type="Rect2" />
+ <argument index="0" name="rect" type="Rect2i" />
<argument index="1" name="color" type="Color" />
<description>
Fills [code]rect[/code] with [code]color[/code].
@@ -244,7 +244,7 @@
</method>
<method name="get_rect" qualifiers="const">
<return type="Image" />
- <argument index="0" name="rect" type="Rect2" />
+ <argument index="0" name="rect" type="Rect2i" />
<description>
Returns a new image that is a copy of the image's area specified with [code]rect[/code].
</description>
@@ -256,9 +256,9 @@
</description>
</method>
<method name="get_used_rect" qualifiers="const">
- <return type="Rect2" />
+ <return type="Rect2i" />
<description>
- Returns a [Rect2] enclosing the visible portion of the image, considering each pixel with a non-zero alpha channel as visible.
+ Returns a [Rect2i] enclosing the visible portion of the image, considering each pixel with a non-zero alpha channel as visible.
</description>
</method>
<method name="get_width" qualifiers="const">
@@ -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" />
@@ -371,6 +378,19 @@
Converts a standard RGBE (Red Green Blue Exponent) image to an sRGB image.
</description>
</method>
+ <method name="rotate_180">
+ <return type="void" />
+ <description>
+ Rotates the image by [code]180[/code] degrees. The width and height of the image must be greater than [code]1[/code].
+ </description>
+ </method>
+ <method name="rotate_90">
+ <return type="void" />
+ <argument index="0" name="direction" type="int" enum="ClockDirection" />
+ <description>
+ Rotates the image in the specified [code]direction[/code] by [code]90[/code] degrees. The width and height of the image must be greater than [code]1[/code]. If the width and height are not equal, the image will be resized.
+ </description>
+ </method>
<method name="save_exr" qualifiers="const">
<return type="int" enum="Error" />
<argument index="0" name="path" type="String" />
diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml
index aecb4fc4b6..084bf7e809 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">
@@ -44,9 +42,17 @@
Returns the format of the texture, one of [enum Image.Format].
</description>
</method>
+ <method name="set_image">
+ <return type="void" />
+ <argument index="0" name="image" type="Image" />
+ <description>
+ Replaces the texture's data with a new [Image]. This will re-allocate new memory for the texture.
+ If you want to update the image, but don't need to change its parameters (format, size), use [method update] instead for better performance.
+ </description>
+ </method>
<method name="set_size_override">
<return type="void" />
- <argument index="0" name="size" type="Vector2" />
+ <argument index="0" name="size" type="Vector2i" />
<description>
Resizes the texture to the specified dimensions.
</description>
@@ -56,8 +62,8 @@
<argument index="0" name="image" type="Image" />
<description>
Replaces the texture's data with a new [Image].
- [b]Note:[/b] The texture has to be initialized first with the [method create_from_image] method before it can be updated. The new image dimensions, format, and mipmaps configuration should match the existing texture's image configuration, otherwise it has to be re-created with the [method create_from_image] method.
- Use this method over [method create_from_image] if you need to update the texture frequently, which is faster than allocating additional memory for a new texture each time.
+ [b]Note:[/b] The texture has to be created using [method create_from_image] or initialized first with the [method set_image] method before it can be updated. The new image dimensions, format, and mipmaps configuration should match the existing texture's image configuration.
+ Use this method over [method set_image] if you need to update the texture frequently, which is faster than allocating additional memory for a new texture each time.
</description>
</method>
</methods>
diff --git a/doc/classes/ImporterMesh.xml b/doc/classes/ImporterMesh.xml
index 00601cec75..201c0ddd38 100644
--- a/doc/classes/ImporterMesh.xml
+++ b/doc/classes/ImporterMesh.xml
@@ -30,7 +30,7 @@
<description>
Creates a new surface, analogous to [method ArrayMesh.add_surface_from_arrays].
Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines, or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface.
- The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used.
+ The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array (or be an exact multiple of the vertex array's length, when multiple elements of a sub-array correspond to a single vertex) or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used.
</description>
</method>
<method name="clear">
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index 66683fa0ee..796a80873f 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -354,9 +354,11 @@
<return type="void" />
<argument index="0" name="duration_ms" type="int" default="500" />
<description>
- Vibrate Android and iOS devices.
+ Vibrate handheld devices.
+ [b]Note:[/b] This method is implemented on Android, iOS, and HTML5.
[b]Note:[/b] For Android, it requires enabling the [code]VIBRATE[/code] permission in the export preset.
[b]Note:[/b] For iOS, specifying the duration is supported in iOS 13 and later.
+ [b]Note:[/b] Some web browsers such as Safari and Firefox for Android do not support this method.
</description>
</method>
<method name="warp_mouse">
@@ -375,6 +377,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..97ee946acd 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" />
@@ -469,7 +445,7 @@
<theme_item name="font_selected_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
Text [Color] used when the item is selected.
</theme_item>
- <theme_item name="guide_color" data_type="color" type="Color" default="Color(0, 0, 0, 0.1)">
+ <theme_item name="guide_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 0.25)">
[Color] of the guideline. The guideline is a line drawn between each row of items.
</theme_item>
<theme_item name="h_separation" data_type="constant" type="int" default="4">
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index b5f045621b..1ebf770f7e 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">
@@ -70,6 +49,8 @@
<member name="horizontal_alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="0">
Controls the text's horizontal alignment. Supports left, center, right, and fill, or justify. Set it to one of the [enum HorizontalAlignment] constants.
</member>
+ <member name="label_settings" type="LabelSettings" setter="set_label_settings" getter="get_label_settings">
+ </member>
<member name="language" type="String" setter="set_language" getter="get_language" default="&quot;&quot;">
Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
</member>
@@ -119,7 +100,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..5ba0a2d79a 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,11 +75,11 @@
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.
- [b]Node:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value).
+ [b]Note:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value).
[b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority).
</member>
<member name="outline_size" type="int" setter="set_outline_size" getter="get_outline_size" default="0">
@@ -111,7 +90,7 @@
</member>
<member name="render_priority" type="int" setter="set_render_priority" getter="get_render_priority" default="0">
Sets the render priority for the text. Higher priority objects will be sorted in front of lower priority objects.
- [b]Node:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value).
+ [b]Note:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value).
[b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority).
</member>
<member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
@@ -147,7 +126,7 @@
If set, lights in the environment affect the label.
</constant>
<constant name="FLAG_DOUBLE_SIDED" value="1" enum="DrawFlags">
- If set, text can be seen from the back as well. If not, the texture is invisible when looking at it from behind.
+ If set, text can be seen from the back as well. If not, the text is invisible when looking at it from behind.
</constant>
<constant name="FLAG_DISABLE_DEPTH_TEST" value="2" enum="DrawFlags">
Disables the depth test, so this object is drawn on top of all others. However, objects drawn after it in the draw order may cover it.
diff --git a/doc/classes/LabelSettings.xml b/doc/classes/LabelSettings.xml
new file mode 100644
index 0000000000..aa972f2cf3
--- /dev/null
+++ b/doc/classes/LabelSettings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="LabelSettings" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="font" type="Font" setter="set_font" getter="get_font">
+ </member>
+ <member name="font_color" type="Color" setter="set_font_color" getter="get_font_color" default="Color(1, 1, 1, 1)">
+ </member>
+ <member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16">
+ </member>
+ <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="3.0">
+ </member>
+ <member name="outline_color" type="Color" setter="set_outline_color" getter="get_outline_color" default="Color(1, 1, 1, 1)">
+ </member>
+ <member name="outline_size" type="int" setter="set_outline_size" getter="get_outline_size" default="0">
+ </member>
+ <member name="shadow_color" type="Color" setter="set_shadow_color" getter="get_shadow_color" default="Color(0, 0, 0, 0)">
+ </member>
+ <member name="shadow_offset" type="Vector2" setter="set_shadow_offset" getter="get_shadow_offset" default="Vector2(1, 1)">
+ </member>
+ <member name="shadow_size" type="int" setter="set_shadow_size" getter="get_shadow_size" default="1">
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml
index 4d8fd63257..46c3e57547 100644
--- a/doc/classes/Light3D.xml
+++ b/doc/classes/Light3D.xml
@@ -37,13 +37,12 @@
[b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D].
</member>
<member name="distance_fade_length" type="float" setter="set_distance_fade_length" getter="get_distance_fade_length" default="10.0">
- Distance over which the light fades. The light's energy is progressively reduced over this distance and is completely invisible at the end.
+ Distance over which the light and its shadow fades. The light's energy and shadow's opacity is progressively reduced over this distance and is completely invisible at the end.
[b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D].
</member>
<member name="distance_fade_shadow" type="float" setter="set_distance_fade_shadow" getter="get_distance_fade_shadow" default="50.0">
The distance from the camera at which the light's shadow cuts off (in 3D units). Set this to a value lower than [member distance_fade_begin] + [member distance_fade_length] to further improve performance, as shadow rendering is often more expensive than light rendering itself.
[b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D], and only when [member shadow_enabled] is [code]true[/code].
- [b]Note:[/b] Due to a rendering engine limitation, shadows will be disabled instantly instead of fading smoothly according to [member distance_fade_length]. This may result in visible pop-in depending on the scene topography.
</member>
<member name="editor_only" type="bool" setter="set_editor_only" getter="is_editor_only" default="false">
If [code]true[/code], the light only appears in the editor and will not be visible at runtime.
@@ -73,6 +72,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.
@@ -94,6 +94,9 @@
<member name="shadow_normal_bias" type="float" setter="set_param" getter="get_param" default="1.0">
Offsets the lookup into the shadow map by the object's normal. This can be used to reduce self-shadowing artifacts without using [member shadow_bias]. In practice, this value should be tweaked along with [member shadow_bias] to reduce artifacts as much as possible.
</member>
+ <member name="shadow_opacity" type="float" setter="set_param" getter="get_param" default="1.0">
+ The opacity to use when rendering the light's shadow map. Values lower than [code]1.0[/code] make the light appear through shadows. This can be used to fake global illumination at a low performance cost.
+ </member>
<member name="shadow_reverse_cull_face" type="bool" setter="set_shadow_reverse_cull_face" getter="get_shadow_reverse_cull_face" default="false">
If [code]true[/code], reverses the backface culling of the mesh. This can be useful when you have a flat mesh that has a light behind it. If you need to cast a shadow on both sides of the mesh, set the mesh to use double-sided shadows with [constant GeometryInstance3D.SHADOW_CASTING_SETTING_DOUBLE_SIDED].
</member>
@@ -149,15 +152,19 @@
<constant name="PARAM_SHADOW_PANCAKE_SIZE" value="15" enum="Param">
Constant for accessing [member DirectionalLight3D.directional_shadow_pancake_size].
</constant>
- <constant name="PARAM_SHADOW_BLUR" value="16" enum="Param">
+ <constant name="PARAM_SHADOW_OPACITY" value="16" enum="Param">
+ Constant for accessing [member shadow_opacity].
+ </constant>
+ <constant name="PARAM_SHADOW_BLUR" value="17" enum="Param">
Constant for accessing [member shadow_blur].
</constant>
- <constant name="PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="17" enum="Param">
+ <constant name="PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="18" enum="Param">
+ Constant for accessing [member shadow_fog_fade].
</constant>
- <constant name="PARAM_TRANSMITTANCE_BIAS" value="18" enum="Param">
+ <constant name="PARAM_TRANSMITTANCE_BIAS" value="19" enum="Param">
Constant for accessing [member shadow_transmittance_bias].
</constant>
- <constant name="PARAM_MAX" value="19" enum="Param">
+ <constant name="PARAM_MAX" value="20" enum="Param">
Represents the size of the [enum Param] enum.
</constant>
<constant name="BAKE_DISABLED" value="0" enum="BakeMode">
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/LightmapGIData.xml b/doc/classes/LightmapGIData.xml
index 20113ac309..13f44150d7 100644
--- a/doc/classes/LightmapGIData.xml
+++ b/doc/classes/LightmapGIData.xml
@@ -22,7 +22,7 @@
<method name="clear_users">
<return type="void" />
<description>
- Clear all objects that are considred baked within this [LightmapGIData].
+ Clear all objects that are considered baked within this [LightmapGIData].
</description>
</method>
<method name="get_user_count" qualifiers="const">
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 55e012ee0c..2ff13a676b 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">
@@ -267,6 +246,9 @@
<member name="virtual_keyboard_enabled" type="bool" setter="set_virtual_keyboard_enabled" getter="is_virtual_keyboard_enabled" default="true">
If [code]true[/code], the native virtual keyboard is shown when focused on platforms that support it.
</member>
+ <member name="virtual_keyboard_type" type="int" setter="set_virtual_keyboard_type" getter="get_virtual_keyboard_type" enum="LineEdit.VirtualKeyboardType" default="0">
+ Specifies the type of virtual keyboard to show.
+ </member>
</members>
<signals>
<signal name="text_change_rejected">
@@ -377,6 +359,31 @@
<constant name="MENU_MAX" value="28" enum="MenuItems">
Represents the size of the [enum MenuItems] enum.
</constant>
+ <constant name="KEYBOARD_TYPE_DEFAULT" value="0" enum="VirtualKeyboardType">
+ Default text virtual keyboard.
+ </constant>
+ <constant name="KEYBOARD_TYPE_MULTILINE" value="1" enum="VirtualKeyboardType">
+ Multiline virtual keyboard.
+ </constant>
+ <constant name="KEYBOARD_TYPE_NUMBER" value="2" enum="VirtualKeyboardType">
+ Virtual number keypad, useful for PIN entry.
+ </constant>
+ <constant name="KEYBOARD_TYPE_NUMBER_DECIMAL" value="3" enum="VirtualKeyboardType">
+ Virtual number keypad, useful for entering fractional numbers.
+ </constant>
+ <constant name="KEYBOARD_TYPE_PHONE" value="4" enum="VirtualKeyboardType">
+ Virtual phone number keypad.
+ </constant>
+ <constant name="KEYBOARD_TYPE_EMAIL_ADDRESS" value="5" enum="VirtualKeyboardType">
+ Virtual keyboard with additional keys to assist with typing email addresses.
+ </constant>
+ <constant name="KEYBOARD_TYPE_PASSWORD" value="6" enum="VirtualKeyboardType">
+ Virtual keyboard for entering a password. On most platforms, this should disable autocomplete and autocapitalization.
+ [b]Note:[/b] This is not supported on HTML5. Instead, this behaves identically to [constant KEYBOARD_TYPE_DEFAULT].
+ </constant>
+ <constant name="KEYBOARD_TYPE_URL" value="7" enum="VirtualKeyboardType">
+ Virtual keyboard with additional keys to assist with typing URLs.
+ </constant>
</constants>
<theme_items>
<theme_item name="caret_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)">
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/MeshInstance3D.xml b/doc/classes/MeshInstance3D.xml
index f368190a29..24f1f9918b 100644
--- a/doc/classes/MeshInstance3D.xml
+++ b/doc/classes/MeshInstance3D.xml
@@ -4,7 +4,7 @@
Node that instances meshes into a scenario.
</brief_description>
<description>
- MeshInstance3D is a node that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used render 3D geometry and can be used to instance a single [Mesh] in many places. This allows reuse of geometry which can save on resources. When a [Mesh] has to be instantiated more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance3D] instead.
+ MeshInstance3D is a node that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used render 3D geometry and can be used to instance a single [Mesh] in many places. This allows reusing geometry, which can save on resources. When a [Mesh] has to be instantiated more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance3D] instead.
</description>
<tutorials>
<link title="3D Material Testers Demo">https://godotengine.org/asset-library/asset/123</link>
diff --git a/doc/classes/MovieWriter.xml b/doc/classes/MovieWriter.xml
index bc702adde6..d47e52d7c0 100644
--- a/doc/classes/MovieWriter.xml
+++ b/doc/classes/MovieWriter.xml
@@ -68,7 +68,7 @@
<return type="void" />
<argument index="0" name="writer" type="MovieWriter" />
<description>
- Adds a writer to be usable by the engine. The supported file extensions can be set by overridding [method _handles_file].
+ Adds a writer to be usable by the engine. The supported file extensions can be set by overriding [method _handles_file].
[b]Note:[/b] [method add_writer] must be called early enough in the engine initialization to work, as movie writing is designed to start at the same time as the rest of the engine.
</description>
</method>
diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml
index 631b2ea050..3431a3347b 100644
--- a/doc/classes/MultiMesh.xml
+++ b/doc/classes/MultiMesh.xml
@@ -54,7 +54,7 @@
<argument index="1" name="color" type="Color" />
<description>
Sets the color of a specific instance by [i]multiplying[/i] the mesh's existing vertex colors.
- For the color to take effect, ensure that [member use_colors] is [code]true[/code] on the [MultiMesh] and [member BaseMaterial3D.vertex_color_use_as_albedo] is [code]true[/code] on the material.
+ For the color to take effect, ensure that [member use_colors] is [code]true[/code] on the [MultiMesh] and [member BaseMaterial3D.vertex_color_use_as_albedo] is [code]true[/code] on the material. If the color doesn't look as expected, make sure the material's albedo color is set to pure white ([code]Color(1, 1, 1)[/code]).
</description>
</method>
<method name="set_instance_custom_data">
@@ -91,7 +91,8 @@
<member name="custom_data_array" type="PackedColorArray" setter="_set_custom_data_array" getter="_get_custom_data_array">
</member>
<member name="instance_count" type="int" setter="set_instance_count" getter="get_instance_count" default="0">
- Number of instances that will get drawn. This clears and (re)sizes the buffers. By default, all instances are drawn but you can limit this with [member visible_instance_count].
+ Number of instances that will get drawn. This clears and (re)sizes the buffers. Setting data format or flags afterwards will have no effect.
+ By default, all instances are drawn but you can limit this with [member visible_instance_count].
</member>
<member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh">
Mesh to be drawn.
diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml
index 059d147979..06658bf004 100644
--- a/doc/classes/MultiplayerAPI.xml
+++ b/doc/classes/MultiplayerAPI.xml
@@ -1,88 +1,108 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="MultiplayerAPI" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- High-level multiplayer API.
+ High-level multiplayer API interface.
</brief_description>
<description>
- This class implements the high-level multiplayer API. See also [MultiplayerPeer].
- By default, [SceneTree] has a reference to this class that is used to provide multiplayer capabilities (i.e. RPCs) across the whole scene.
+ Base class for high-level multiplayer API implementations. See also [MultiplayerPeer].
+ By default, [SceneTree] has a reference to an implementation of this class and uses it to provide multiplayer capabilities (i.e. RPCs) across the whole scene.
It is possible to override the MultiplayerAPI instance used by specific tree branches by calling the [method SceneTree.set_multiplayer] method, effectively allowing to run both client and server in the same scene.
- [b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice.
- [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android.
+ It is also possible to extend or replace the default implementation via scripting or native extensions. See [MultiplayerAPIExtension] for details about extensions, [SceneMultiplayer] for the details about the default implementation.
</description>
<tutorials>
</tutorials>
<methods>
- <method name="clear">
- <return type="void" />
+ <method name="create_default_interface" qualifiers="static">
+ <return type="MultiplayerAPI" />
+ <description>
+ Returns a new instance of the default MultiplayerAPI.
+ </description>
+ </method>
+ <method name="get_default_interface" qualifiers="static">
+ <return type="StringName" />
<description>
- Clears the current MultiplayerAPI network state (you shouldn't call this unless you know what you are doing).
+ Returns the default MultiplayerAPI implementation class name. This is usually [code]"SceneMultiplayer"[/code] when [SceneMultiplayer] is available. See [method set_default_interface].
</description>
</method>
- <method name="get_peers" qualifiers="const">
+ <method name="get_peers">
<return type="PackedInt32Array" />
<description>
Returns the peer IDs of all connected peers of this MultiplayerAPI's [member multiplayer_peer].
</description>
</method>
- <method name="get_remote_sender_id" qualifiers="const">
+ <method name="get_remote_sender_id">
<return type="int" />
<description>
Returns the sender's peer ID for the RPC currently being executed.
[b]Note:[/b] If not inside an RPC this method will return 0.
</description>
</method>
- <method name="get_unique_id" qualifiers="const">
+ <method name="get_unique_id">
<return type="int" />
<description>
Returns the unique peer ID of this MultiplayerAPI's [member multiplayer_peer].
</description>
</method>
- <method name="has_multiplayer_peer" qualifiers="const">
+ <method name="has_multiplayer_peer">
<return type="bool" />
<description>
Returns [code]true[/code] if there is a [member multiplayer_peer] set.
</description>
</method>
- <method name="is_server" qualifiers="const">
+ <method name="is_server">
<return type="bool" />
<description>
Returns [code]true[/code] if this MultiplayerAPI's [member multiplayer_peer] is valid and in server mode (listening for connections).
</description>
</method>
+ <method name="object_configuration_add">
+ <return type="int" enum="Error" />
+ <argument index="0" name="object" type="Object" />
+ <argument index="1" name="configuration" type="Variant" />
+ <description>
+ Notifies the MultiplayerAPI of a new [code]configuration[/code] for the given [code]object[/code]. This method is used internally by [SceneTree] to configure the root path for this MultiplayerAPI (passing [code]null[/code] and a valid [NodePath] as [code]configuration[/code]). This method can be further used by MultiplayerAPI implementations to provide additional features, refer to specific implementation (e.g. [SceneMultiplayer]) for details on how they use it.
+ [b]Note:[/b] This method is mostly relevant when extending or overriding the MultiplayerAPI behavior via [MultiplayerAPIExtension].
+ </description>
+ </method>
+ <method name="object_configuration_remove">
+ <return type="int" enum="Error" />
+ <argument index="0" name="object" type="Object" />
+ <argument index="1" name="configuration" type="Variant" />
+ <description>
+ Notifies the MultiplayerAPI to remove a [code]configuration[/code] for the given [code]object[/code]. This method is used internally by [SceneTree] to configure the root path for this MultiplayerAPI (passing [code]null[/code] and an empty [NodePath] as [code]configuration[/code]). This method can be further used by MultiplayerAPI implementations to provide additional features, refer to specific implementation (e.g. [SceneMultiplayer]) for details on how they use it.
+ [b]Note:[/b] This method is mostly relevant when extending or overriding the MultiplayerAPI behavior via [MultiplayerAPIExtension].
+ </description>
+ </method>
<method name="poll">
- <return type="void" />
+ <return type="int" enum="Error" />
<description>
Method used for polling the MultiplayerAPI. You only need to worry about this if you set [member SceneTree.multiplayer_poll] to [code]false[/code]. By default, [SceneTree] will poll its MultiplayerAPI(s) for you.
[b]Note:[/b] This method results in RPCs being called, so they will be executed in the same context of this function (e.g. [code]_process[/code], [code]physics[/code], [Thread]).
</description>
</method>
- <method name="send_bytes">
+ <method name="rpc">
<return type="int" enum="Error" />
- <argument index="0" name="bytes" type="PackedByteArray" />
- <argument index="1" name="id" type="int" default="0" />
- <argument index="2" name="mode" type="int" enum="TransferMode" default="2" />
- <argument index="3" name="channel" type="int" default="0" />
+ <argument index="0" name="peer" type="int" />
+ <argument index="1" name="object" type="Object" />
+ <argument index="2" name="method" type="StringName" />
+ <argument index="3" name="arguments" type="Array" default="[]" />
+ <description>
+ Sends an RPC to the target [code]peer[/code]. The given [code]method[/code] will be called on the remote [code]object[/code] with the provided [code]arguments[/code]. The RPC may also be called locally depending on the implementation and RPC configuration. See [method Node.rpc] and [method Node.rpc_config].
+ [b]Note:[/b] Prefer using [method Node.rpc], [method Node.rpc_id], or [code]my_method.rpc(peer, arg1, arg2, ...)[/code] (in GDScript), since they are faster. This method is mostly useful in conjunction with [MultiplayerAPIExtension] when augmenting or replacing the multiplayer capabilities.
+ </description>
+ </method>
+ <method name="set_default_interface" qualifiers="static">
+ <return type="void" />
+ <argument index="0" name="interface_name" type="StringName" />
<description>
- Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method MultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
+ Sets the default MultiplayerAPI implementation class. This method can be used by modules and extensions to configure which implementation will be used by [SceneTree] when the engine starts.
</description>
</method>
</methods>
<members>
- <member name="allow_object_decoding" type="bool" setter="set_allow_object_decoding" getter="is_object_decoding_allowed" default="false">
- If [code]true[/code], the MultiplayerAPI will allow encoding and decoding of object during RPCs.
- [b]Warning:[/b] Deserialized objects can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threats such as remote code execution.
- </member>
<member name="multiplayer_peer" type="MultiplayerPeer" setter="set_multiplayer_peer" getter="get_multiplayer_peer">
The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the MultiplayerAPI will become a network server (check with [method is_server]) and will set root node's network mode to authority, or it will become a regular client peer. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to MultiplayerAPI's signals.
</member>
- <member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" default="false">
- If [code]true[/code], the MultiplayerAPI's [member multiplayer_peer] refuses new incoming connections.
- </member>
- <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath(&quot;&quot;)">
- The root path to use for RPCs and replication. Instead of an absolute path, a relative path will be used to find the node upon which the RPC should be executed.
- This effectively allows to have different branches of the scene tree to be managed by different MultiplayerAPI, allowing for example to run both client and server in the same scene.
- </member>
</members>
<signals>
<signal name="connected_to_server">
@@ -107,17 +127,21 @@
Emitted when this MultiplayerAPI's [member multiplayer_peer] disconnects from a peer. Clients get notified when other clients disconnect from the same server.
</description>
</signal>
- <signal name="peer_packet">
- <argument index="0" name="id" type="int" />
- <argument index="1" name="packet" type="PackedByteArray" />
- <description>
- Emitted when this MultiplayerAPI's [member multiplayer_peer] receives a [code]packet[/code] with custom data (see [method send_bytes]). ID is the peer ID of the peer that sent the packet.
- </description>
- </signal>
<signal name="server_disconnected">
<description>
Emitted when this MultiplayerAPI's [member multiplayer_peer] disconnects from server. Only emitted on clients.
</description>
</signal>
</signals>
+ <constants>
+ <constant name="RPC_MODE_DISABLED" value="0" enum="RPCMode">
+ Used with [method Node.rpc_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods.
+ </constant>
+ <constant name="RPC_MODE_ANY_PEER" value="1" enum="RPCMode">
+ Used with [method Node.rpc_config] to set a method to be callable remotely by any peer. Analogous to the [code]@rpc(any)[/code] annotation. Calls are accepted from all remote peers, no matter if they are node's authority or not.
+ </constant>
+ <constant name="RPC_MODE_AUTHORITY" value="2" enum="RPCMode">
+ Used with [method Node.rpc_config] to set a method to be callable remotely only by the current multiplayer authority (which is the server by default). Analogous to the [code]@rpc(authority)[/code] annotation. See [method Node.set_multiplayer_authority].
+ </constant>
+ </constants>
</class>
diff --git a/doc/classes/MultiplayerAPIExtension.xml b/doc/classes/MultiplayerAPIExtension.xml
new file mode 100644
index 0000000000..c369977d57
--- /dev/null
+++ b/doc/classes/MultiplayerAPIExtension.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="MultiplayerAPIExtension" inherits="MultiplayerAPI" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Base class used for extending the [MultiplayerAPI].
+ </brief_description>
+ <description>
+ This class can be used to augment or replace the default [MultiplayerAPI] implementation via script or extensions.
+ The following example augment the default implemenation ([SceneMultiplayer]) by logging every RPC being made, and every object being configured for replication.
+ [codeblocks]
+ [gdscript]
+ extends MultiplayerAPIExtension
+ class_name LogMultiplayer
+
+ # We want to augment the default SceneMultiplayer.
+ var base_multiplayer = SceneMultiplayer.new()
+
+ func _init():
+ # Just passthourgh base signals (copied to var to avoid cyclic reference)
+ var cts = connected_to_server
+ var cf = connection_failed
+ var pc = peer_connected
+ var pd = peer_disconnected
+ base_multiplayer.connected_to_server.connect(func(): cts.emit())
+ base_multiplayer.connection_failed.connect(func(): cf.emit())
+ base_multiplayer.peer_connected.connect(func(id): pc.emit(id))
+ base_multiplayer.peer_disconnected.connect(func(id): pd.emit(id))
+
+ # Log RPC being made and forward it to the default multiplayer.
+ func _rpc(peer: int, object: Object, method: StringName, args: Array) -&gt; int: # Error
+ print("Got RPC for %d: %s::%s(%s)" % [peer, object, method, args])
+ return base_multiplayer.rpc(peer, object, method, args)
+
+ # Log configuration add. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom.
+ func _object_configuration_add(object, config: Variant) -&gt; int: # Error
+ if config is MultiplayerSynchronizer:
+ print("Adding synchronization configuration for %s. Synchronizer: %s" % [object, config])
+ elif config is MultiplayerSpawner:
+ print("Adding node %s to the spawn list. Spawner: %s" % [object, config])
+ return base_multiplayer.object_configuration_add(object, config)
+
+ # Log configuration remove. E.g. root path (nullptr, NodePath), replication (Node, Spawner|Synchronizer), custom.
+ func _object_configuration_remove(object, config: Variant) -&gt; int: # Error
+ if config is MultiplayerSynchronizer:
+ print("Removing synchronization configuration for %s. Synchronizer: %s" % [object, config])
+ elif config is MultiplayerSpawner:
+ print("Removing node %s from the spawn list. Spawner: %s" % [object, config])
+ return base_multiplayer.object_configuration_remove(object, config)
+
+ # These can be optional, but in our case we want to augment SceneMultiplayer, so forward everything.
+ func _set_multiplayer_peer(p_peer: MultiplayerPeer):
+ base_multiplayer.multiplayer_peer = p_peer
+
+ func _get_multiplayer_peer() -&gt; MultiplayerPeer:
+ return base_multiplayer.multiplayer_peer
+
+ func _get_unique_id() -&gt; int:
+ return base_multiplayer.get_unique_id()
+
+ func _get_peer_ids() -&gt; PackedInt32Array:
+ return base_multiplayer.get_peers()
+ [/gdscript]
+ [/codeblocks]
+ Then in your main scene or in an autoload call [method SceneTree.set_multiplayer] to start using your custom [MultiplayerAPI]:
+ [codeblocks]
+ [gdscript]
+ # autoload.gd
+ func _enter_tree():
+ # Sets our custom multiplayer as the main one in SceneTree.
+ get_tree().set_multiplayer(LogMultiplayer.new())
+ [/gdscript]
+ [/codeblocks]
+ Native extensions can alternatively use the [method MultiplayerAPI.set_default_interface] method during initialization to configure themselves as the default implementation.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="_get_multiplayer_peer" qualifiers="virtual">
+ <return type="MultiplayerPeer" />
+ <description>
+ Called when the [member MultiplayerAPI.multiplayer_peer] is retrieved.
+ </description>
+ </method>
+ <method name="_get_peer_ids" qualifiers="virtual const">
+ <return type="PackedInt32Array" />
+ <description>
+ Callback for [method MultiplayerAPI.get_peers].
+ </description>
+ </method>
+ <method name="_get_remote_sender_id" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ Callback for [method MultiplayerAPI.get_remote_sender_id].
+ </description>
+ </method>
+ <method name="_get_unique_id" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ Callback for [method MultiplayerAPI.get_unique_id].
+ </description>
+ </method>
+ <method name="_object_configuration_add" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="object" type="Object" />
+ <argument index="1" name="configuration" type="Variant" />
+ <description>
+ Callback for [method MultiplayerAPI.object_configuration_add].
+ </description>
+ </method>
+ <method name="_object_configuration_remove" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="object" type="Object" />
+ <argument index="1" name="configuration" type="Variant" />
+ <description>
+ Callback for [method MultiplayerAPI.object_configuration_remove].
+ </description>
+ </method>
+ <method name="_poll" qualifiers="virtual">
+ <return type="int" />
+ <description>
+ Callback for [method MultiplayerAPI.poll].
+ </description>
+ </method>
+ <method name="_rpc" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="peer" type="int" />
+ <argument index="1" name="object" type="Object" />
+ <argument index="2" name="method" type="StringName" />
+ <argument index="3" name="args" type="Array" />
+ <description>
+ Callback for [method MultiplayerAPI.rpc].
+ </description>
+ </method>
+ <method name="_set_multiplayer_peer" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="multiplayer_peer" type="MultiplayerPeer" />
+ <description>
+ Called when the [member MultiplayerAPI.multiplayer_peer] is set.
+ </description>
+ </method>
+ </methods>
+</class>
diff --git a/doc/classes/MultiplayerPeer.xml b/doc/classes/MultiplayerPeer.xml
index 4a3559b0f7..6dde40f018 100644
--- a/doc/classes/MultiplayerPeer.xml
+++ b/doc/classes/MultiplayerPeer.xml
@@ -60,7 +60,7 @@
The channel to use to send packets. Many network APIs such as ENet and WebRTC allow the creation of multiple independent channels which behaves, in a way, like separate connections. This means that reliable data will only block delivery of other packets on that channel, and ordering will only be in respect to the channel the packet is being sent on. Using different channels to send [b]different and independent[/b] state updates is a common way to optimize network usage and decrease latency in fast-paced games.
[b]Note:[/b] The default channel ([code]0[/code]) actually works as 3 separate channels (one for each [enum TransferMode]) so that [constant TRANSFER_MODE_RELIABLE] and [constant TRANSFER_MODE_UNRELIABLE_ORDERED] does not interact with each other by default. Refer to the specific network API documentation (e.g. ENet or WebRTC) to learn how to set up channels correctly.
</member>
- <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" enum="TransferMode" default="2">
+ <member name="transfer_mode" type="int" setter="set_transfer_mode" getter="get_transfer_mode" enum="MultiplayerPeer.TransferMode" default="2">
The manner in which to send packets to the [code]target_peer[/code]. See [enum TransferMode].
</member>
</members>
@@ -109,5 +109,14 @@
<constant name="TARGET_PEER_SERVER" value="1">
Packets are sent to the server alone.
</constant>
+ <constant name="TRANSFER_MODE_UNRELIABLE" value="0" enum="TransferMode">
+ Packets are not acknowledged, no resend attempts are made for lost packets. Packets may arrive in any order. Potentially faster than [constant TRANSFER_MODE_UNRELIABLE_ORDERED]. Use for non-critical data, and always consider whether the order matters.
+ </constant>
+ <constant name="TRANSFER_MODE_UNRELIABLE_ORDERED" value="1" enum="TransferMode">
+ Packets are not acknowledged, no resend attempts are made for lost packets. Packets are received in the order they were sent in. Potentially faster than [constant TRANSFER_MODE_RELIABLE]. Use for non-critical data or data that would be outdated if received late due to resend attempt(s) anyway, for example movement and positional data.
+ </constant>
+ <constant name="TRANSFER_MODE_RELIABLE" value="2" enum="TransferMode">
+ Packets must be received and resend attempts should be made until the packets are acknowledged. Packets must be received in the order they were sent in. Most reliable transfer mode, but potentially the slowest due to the overhead. Use for critical data that must be transmitted and arrive in order, for example an ability being triggered or a chat message. Consider carefully if the information really is critical, and use sparingly.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/MultiplayerPeerExtension.xml b/doc/classes/MultiplayerPeerExtension.xml
index bd11c76039..f837171e2f 100644
--- a/doc/classes/MultiplayerPeerExtension.xml
+++ b/doc/classes/MultiplayerPeerExtension.xml
@@ -41,6 +41,12 @@
Called when the ID of the [MultiplayerPeer] who sent the most recent packet is requested (see [method MultiplayerPeer.get_packet_peer]).
</description>
</method>
+ <method name="_get_packet_script" qualifiers="virtual">
+ <return type="PackedByteArray" />
+ <description>
+ Called when a packet needs to be received by the [MultiplayerAPI], if [method _get_packet] isn't implemented. Use this when extending this class via GDScript.
+ </description>
+ </method>
<method name="_get_transfer_channel" qualifiers="virtual const">
<return type="int" />
<description>
@@ -85,6 +91,13 @@
Called when a packet needs to be sent by the [MultiplayerAPI], with [code]p_buffer_size[/code] being the size of the binary [code]p_buffer[/code] in bytes.
</description>
</method>
+ <method name="_put_packet_script" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="p_buffer" type="PackedByteArray" />
+ <description>
+ Called when a packet needs to be sent by the [MultiplayerAPI], if [method _put_packet] isn't implemented. Use this when extending this class via GDScript.
+ </description>
+ </method>
<method name="_set_refuse_new_connections" qualifiers="virtual">
<return type="void" />
<argument index="0" name="p_enable" type="bool" />
diff --git a/doc/classes/MultiplayerSpawner.xml b/doc/classes/MultiplayerSpawner.xml
deleted file mode 100644
index 4ca92728ff..0000000000
--- a/doc/classes/MultiplayerSpawner.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiplayerSpawner" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <methods>
- <method name="_spawn_custom" qualifiers="virtual">
- <return type="Object" />
- <argument index="0" name="data" type="Variant" />
- <description>
- </description>
- </method>
- <method name="add_spawnable_scene">
- <return type="void" />
- <argument index="0" name="path" type="String" />
- <description>
- </description>
- </method>
- <method name="clear_spawnable_scenes">
- <return type="void" />
- <description>
- </description>
- </method>
- <method name="get_spawnable_scene" qualifiers="const">
- <return type="String" />
- <argument index="0" name="path" type="int" />
- <description>
- </description>
- </method>
- <method name="get_spawnable_scene_count" qualifiers="const">
- <return type="int" />
- <description>
- </description>
- </method>
- <method name="spawn">
- <return type="Node" />
- <argument index="0" name="data" type="Variant" default="null" />
- <description>
- </description>
- </method>
- </methods>
- <members>
- <member name="auto_spawn" type="bool" setter="set_auto_spawning" getter="is_auto_spawning" default="false">
- </member>
- <member name="spawn_limit" type="int" setter="set_spawn_limit" getter="get_spawn_limit" default="0">
- </member>
- <member name="spawn_path" type="NodePath" setter="set_spawn_path" getter="get_spawn_path" default="NodePath(&quot;&quot;)">
- </member>
- </members>
- <signals>
- <signal name="despawned">
- <argument index="0" name="scene_id" type="int" />
- <argument index="1" name="node" type="Node" />
- <description>
- </description>
- </signal>
- <signal name="spawned">
- <argument index="0" name="scene_id" type="int" />
- <argument index="1" name="node" type="Node" />
- <description>
- </description>
- </signal>
- </signals>
-</class>
diff --git a/doc/classes/MultiplayerSynchronizer.xml b/doc/classes/MultiplayerSynchronizer.xml
deleted file mode 100644
index ac067791e6..0000000000
--- a/doc/classes/MultiplayerSynchronizer.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiplayerSynchronizer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <members>
- <member name="replication_config" type="SceneReplicationConfig" setter="set_replication_config" getter="get_replication_config">
- </member>
- <member name="replication_interval" type="float" setter="set_replication_interval" getter="get_replication_interval" default="0.0">
- </member>
- <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath(&quot;..&quot;)">
- </member>
- </members>
-</class>
diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml
index 966f964b12..33d2535ca2 100644
--- a/doc/classes/NavigationMesh.xml
+++ b/doc/classes/NavigationMesh.xml
@@ -28,6 +28,7 @@
<argument index="0" name="mesh" type="Mesh" />
<description>
Initializes the navigation mesh by setting the vertices and indices according to a [Mesh].
+ [b]Note:[/b] The given [code]mesh[/code] must be of type [constant Mesh.PRIMITIVE_TRIANGLES] and have an index array.
</description>
</method>
<method name="get_collision_mask_value" qualifiers="const">
diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml
index c48ca18e9e..75b6544827 100644
--- a/doc/classes/NavigationRegion2D.xml
+++ b/doc/classes/NavigationRegion2D.xml
@@ -8,7 +8,7 @@
Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer2D.map_set_edge_connection_margin].
[b]Note:[/b] Overlapping two regions' polygons is not enough for connecting two regions. They must share a similar edge.
The pathfinding cost of entering this region from another region can be controlled with the [member enter_cost] value.
- [b]Note[/b]: This value is not added to the path cost when the start position is already inside this region.
+ [b]Note:[/b] This value is not added to the path cost when the start position is already inside this region.
The pathfinding cost of traveling distances inside this region can be controlled with the [member travel_cost] multiplier.
</description>
<tutorials>
diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml
index 9f4feee072..f5824a24fd 100644
--- a/doc/classes/NavigationRegion3D.xml
+++ b/doc/classes/NavigationRegion3D.xml
@@ -8,7 +8,7 @@
Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer3D.map_set_edge_connection_margin].
[b]Note:[/b] Overlapping two regions' navmeshes is not enough for connecting two regions. They must share a similar edge.
The cost of entering this region from another region can be controlled with the [member enter_cost] value.
- [b]Note[/b]: This value is not added to the path cost when the start position is already inside this region.
+ [b]Note:[/b] This value is not added to the path cost when the start position is already inside this region.
The cost of traveling distances inside this region can be controlled with the [member travel_cost] multiplier.
</description>
<tutorials>
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 5185b353bc..8600c2643a 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -415,5 +415,10 @@
Emitted when a navigation map is updated, when a region moves or is modified.
</description>
</signal>
+ <signal name="navigation_debug_changed">
+ <description>
+ Emitted when navigation debug settings are changed. Only available in debug builds.
+ </description>
+ </signal>
</signals>
</class>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index b7591ed4f4..8cc8498609 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -622,7 +622,7 @@
</description>
</method>
<method name="rpc" qualifiers="vararg">
- <return type="void" />
+ <return type="int" enum="Error" />
<argument index="0" name="method" type="StringName" />
<description>
Sends a remote procedure call request for the given [code]method[/code] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behaviour depends on the RPC configuration for the given method, see [method rpc_config]. Methods are not exposed to RPCs by default. Returns [code]null[/code].
@@ -630,18 +630,24 @@
</description>
</method>
<method name="rpc_config">
- <return type="int" />
+ <return type="void" />
<argument index="0" name="method" type="StringName" />
- <argument index="1" name="rpc_mode" type="int" enum="RPCMode" />
- <argument index="2" name="call_local" type="bool" default="false" />
- <argument index="3" name="transfer_mode" type="int" enum="TransferMode" default="2" />
- <argument index="4" name="channel" type="int" default="0" />
+ <argument index="1" name="config" type="Variant" />
<description>
- Changes the RPC mode for the given [code]method[/code] to the given [code]rpc_mode[/code], optionally specifying the [code]transfer_mode[/code] and [code]channel[/code] (on supported peers). See [enum RPCMode] and [enum TransferMode]. An alternative is annotating methods and properties with the corresponding annotation ([code]@rpc(any)[/code], [code]@rpc(authority)[/code]). By default, methods are not exposed to networking (and RPCs).
+ Changes the RPC mode for the given [code]method[/code] with the given [code]config[/code] which should be [code]null[/code] (to disable) or a [Dictionary] in the form:
+ [codeblock]
+ {
+ rpc_mode = MultiplayerAPI.RPCMode,
+ transfer_mode = MultiplayerPeer.TranferMode,
+ call_local = false,
+ channel = 0,
+ }
+ [/codeblock]
+ See [enum MultiplayerAPI.RPCMode] and [enum MultiplayerPeer.TransferMode]. An alternative is annotating methods and properties with the corresponding annotation ([code]@rpc(any)[/code], [code]@rpc(authority)[/code]). By default, methods are not exposed to networking (and RPCs).
</description>
</method>
<method name="rpc_id" qualifiers="vararg">
- <return type="void" />
+ <return type="int" enum="Error" />
<argument index="0" name="peer_id" type="int" />
<argument index="1" name="method" type="StringName" />
<description>
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/OS.xml b/doc/classes/OS.xml
index aaf08dec2f..75cd52787a 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -198,6 +198,17 @@
}
[/csharp]
[/codeblocks]
+ [b]Note:[/b] Passing custom user arguments directly is not recommended, as the engine may discard or modify them. Instead, the best way is to use the standard UNIX double dash ([code]--[/code]) and then pass custom arguments, which the engine itself will ignore. These can be read via [method get_cmdline_user_args].
+ </description>
+ </method>
+ <method name="get_cmdline_user_args">
+ <return type="PackedStringArray" />
+ <description>
+ Similar to [method get_cmdline_args], but this returns the user arguments (any argument passed after the double dash [code]--[/code] argument). These are left untouched by Godot for the user.
+ For example, in the command line below, [code]--fullscreen[/code] will not be returned in [method get_cmdline_user_args] and [code]--level 1[/code] will only be returned in [method get_cmdline_user_args]:
+ [codeblock]
+ godot --fullscreen -- --level 1
+ [/codeblock]
</description>
</method>
<method name="get_config_dir" qualifiers="const">
@@ -363,6 +374,12 @@
[b]Note:[/b] This method is only implemented on Windows, macOS, Linux and iOS. On Android, HTML5 and UWP, [method get_processor_name] returns an empty string.
</description>
</method>
+ <method name="get_restart_on_exit_arguments" qualifiers="const">
+ <return type="PackedStringArray" />
+ <description>
+ Returns the list of command line arguments that will be used when the project automatically restarts using [method set_restart_on_exit]. See also [method is_restart_on_exit_set].
+ </description>
+ </method>
<method name="get_static_memory_peak_usage" qualifiers="const">
<return type="int" />
<description>
@@ -385,6 +402,23 @@
[b]Note:[/b] Shared storage is implemented on Android and allows to differentiate between app specific and shared directories. Shared directories have additional restrictions on Android.
</description>
</method>
+ <method name="get_system_font_path" qualifiers="const">
+ <return type="String" />
+ <argument index="0" name="font_name" type="String" />
+ <argument index="1" name="bold" type="bool" default="false" />
+ <argument index="2" name="italic" type="bool" default="false" />
+ <description>
+ Returns path to the system font file with [code]font_name[/code] and style. Return empty string if no matching fonts found.
+ [b]Note:[/b] This method is implemented on iOS, Linux, macOS and Windows.
+ </description>
+ </method>
+ <method name="get_system_fonts" qualifiers="const">
+ <return type="PackedStringArray" />
+ <description>
+ Returns list of font family names available.
+ [b]Note:[/b] This method is implemented on iOS, Linux, macOS and Windows.
+ </description>
+ </method>
<method name="get_thread_caller_id" qualifiers="const">
<return type="int" />
<description>
@@ -453,6 +487,12 @@
[b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
</description>
</method>
+ <method name="is_restart_on_exit_set" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the project will automatically restart when it exits for any reason, [code]false[/code] otherwise. See also [method set_restart_on_exit] and [method get_restart_on_exit_arguments].
+ </description>
+ </method>
<method name="is_stdout_verbose" qualifiers="const">
<return type="bool" />
<description>
@@ -544,6 +584,17 @@
[b]Note:[/b] Double-check the casing of [code]variable[/code]. Environment variable names are case-sensitive on all platforms except Windows.
</description>
</method>
+ <method name="set_restart_on_exit">
+ <return type="void" />
+ <argument index="0" name="restart" type="bool" />
+ <argument index="1" name="arguments" type="PackedStringArray" default="PackedStringArray()" />
+ <description>
+ If [code]restart[/code] is [code]true[/code], restarts the project automatically when it is exited with [method SceneTree.quit] or [constant Node.NOTIFICATION_WM_CLOSE_REQUEST]. Command line [code]arguments[/code] can be supplied. To restart the project with the same command line arguments as originally used to run the project, pass [method get_cmdline_args] as the value for [code]arguments[/code].
+ [method set_restart_on_exit] can be used to apply setting changes that require a restart. See also [method is_restart_on_exit_set] and [method get_restart_on_exit_arguments].
+ [b]Note:[/b] This method is only effective on desktop platforms, and only when the project isn't started from the editor. It will have no effect on mobile and Web platforms, or when the project is started from the editor.
+ [b]Note:[/b] If the project process crashes or is [i]killed[/i] by the user (by sending [code]SIGKILL[/code] instead of the usual [code]SIGTERM[/code]), the project won't restart automatically.
+ </description>
+ </method>
<method name="set_thread_name">
<return type="int" enum="Error" />
<argument index="0" name="name" type="String" />
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 11ae7cc2b0..061b32bfdf 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -152,11 +152,9 @@
<return type="int" enum="Error" />
<argument index="0" name="signal" type="StringName" />
<argument index="1" name="callable" type="Callable" />
- <argument index="2" name="binds" type="Array" default="[]" />
- <argument index="3" name="flags" type="int" default="0" />
+ <argument index="2" name="flags" type="int" default="0" />
<description>
- Connects a [code]signal[/code] to a [code]callable[/code]. Pass optional [code]binds[/code] to the call as an [Array] of parameters. These parameters will be passed to the [Callable]'s method after any parameter used in the call to [method emit_signal]. Use [code]flags[/code] to set deferred or one-shot connections. See [enum ConnectFlags] constants.
- [b]Note:[/b] This method is the legacy implementation for connecting signals. The recommended modern approach is to use [method Signal.connect] and to use [method Callable.bind] to add and validate parameter binds. Both syntaxes are shown below.
+ Connects a [code]signal[/code] to a [code]callable[/code]. Use [code]flags[/code] to set deferred or one-shot connections. See [enum ConnectFlags] constants.
A signal can only be connected once to a [Callable]. It will print an error if already connected, unless the signal was connected with [constant CONNECT_REFERENCE_COUNTED]. To avoid this, first, use [method is_connected] to check for existing connections.
If the callable's target is destroyed in the game's lifecycle, the connection will be lost.
[b]Examples with recommended syntax:[/b]
diff --git a/doc/classes/OccluderInstance3D.xml b/doc/classes/OccluderInstance3D.xml
index abd99dd3aa..08d12341cd 100644
--- a/doc/classes/OccluderInstance3D.xml
+++ b/doc/classes/OccluderInstance3D.xml
@@ -31,7 +31,7 @@
</methods>
<members>
<member name="bake_mask" type="int" setter="set_bake_mask" getter="get_bake_mask" default="4294967295">
- The visual layers to account for when baking for occluders. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated occluder mesh. By default, all objects are taken into account for the occluder baking.
+ The visual layers to account for when baking for occluders. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated occluder mesh. By default, all objects with [i]opaque[/i] materials are taken into account for the occluder baking.
To improve performance and avoid artifacts, it is recommended to exclude dynamic objects, small objects and fixtures from the baking process by moving them to a separate visual layer and excluding this layer in [member bake_mask].
</member>
<member name="bake_simplification_distance" type="float" setter="set_bake_simplification_distance" getter="get_bake_simplification_distance" default="0.1">
diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml
index a7b1f0ea33..737662fe69 100644
--- a/doc/classes/OptionButton.xml
+++ b/doc/classes/OptionButton.xml
@@ -194,6 +194,10 @@
<members>
<member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" overrides="BaseButton" enum="BaseButton.ActionMode" default="0" />
<member name="alignment" type="int" setter="set_text_alignment" getter="get_text_alignment" overrides="Button" enum="HorizontalAlignment" default="0" />
+ <member name="fit_to_longest_item" type="bool" setter="set_fit_to_longest_item" getter="is_fit_to_longest_item" default="true">
+ If [code]true[/code], minimum size will be determined by the longest item's text, instead of the currently selected one's.
+ [b]Note:[/b] For performance reasons, the minimum size doesn't update immediately when adding, removing or modifying items.
+ </member>
<member name="item_count" type="int" setter="set_item_count" getter="get_item_count" default="0">
The number of items to select from.
</member>
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..7badd826d9 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,46 @@
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>
+ <member name="turbulence_enabled" type="bool" setter="set_turbulence_enabled" getter="get_turbulence_enabled" default="false">
+ Enables and disables Turbulence for the particle system.
+ </member>
+ <member name="turbulence_influence_max" type="float" setter="set_param_max" getter="get_param_max" default="0.1">
+ Minimum turbulence influence on each particle.
+ The actual amount of turbulence influence on each particle is calculated as a random value between [member turbulence_influence_min] and [member turbulence_influence_max] and multiplied by the amount of turbulence influence from [member turbulence_influence_over_life].
+ </member>
+ <member name="turbulence_influence_min" type="float" setter="set_param_min" getter="get_param_min" default="0.1">
+ Maximum turbulence influence on each particle.
+ The actual amount of turbulence influence on each particle is calculated as a random value between [member turbulence_influence_min] and [member turbulence_influence_max] and multiplied by the amount of turbulence influence from [member turbulence_influence_over_life].
+ </member>
+ <member name="turbulence_influence_over_life" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
+ Each particle's amount of turbulence will be influenced along this [CurveTexture] over its life time.
+ </member>
+ <member name="turbulence_initial_displacement_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
+ Maximum displacement of each particles spawn position by the turbulence.
+ The actual amount of displacement will be a factor of the underlying turbulence multiplied by a random value between [member turbulence_initial_displacement_min] and [member turbulence_initial_displacement_max].
+ </member>
+ <member name="turbulence_initial_displacement_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
+ Minimum displacement of each particles spawn position by the turbulence.
+ The actual amount of displacement will be a factor of the underlying turbulence multiplied by a random value between [member turbulence_initial_displacement_min] and [member turbulence_initial_displacement_max].
+ </member>
+ <member name="turbulence_noise_scale" type="float" setter="set_turbulence_noise_scale" getter="get_turbulence_noise_scale" default="9.0">
+ This value controls the overall scale/frequency of the turbulence noise pattern.
+ A small scale will result in smaller features with more detail while a high scale will result in smoother noise with larger features.
+ </member>
+ <member name="turbulence_noise_speed" type="Vector3" setter="set_turbulence_noise_speed" getter="get_turbulence_noise_speed" default="Vector3(0.5, 0.5, 0.5)">
+ The movement speed of the turbulence pattern. This changes how quickly the noise changes over time.
+ A value of [code]Vector3(0.0, 0.0, 0.0)[/code] will freeze the turbulence pattern in place.
+ </member>
+ <member name="turbulence_noise_speed_random" type="float" setter="set_turbulence_noise_speed_random" getter="get_turbulence_noise_speed_random" default="0.0">
+ Use to influence the noise speed in a random pattern. This helps to break up visible movement patterns.
+ </member>
+ <member name="turbulence_noise_strength" type="float" setter="set_turbulence_noise_strength" getter="get_turbulence_noise_strength" default="1.0">
+ The turbulence noise strength. Increasing this will result in a stronger, more contrasting, noise pattern.
</member>
</members>
<constants>
@@ -304,7 +345,7 @@
<constant name="PARAM_ANIM_OFFSET" value="11" enum="Parameter">
Use with [method set_param_min], [method set_param_max], and [method set_param_texture] to set animation offset properties.
</constant>
- <constant name="PARAM_MAX" value="12" enum="Parameter">
+ <constant name="PARAM_MAX" value="15" enum="Parameter">
Represents the size of the [enum Parameter] enum.
</constant>
<constant name="PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY" value="0" enum="ParticleFlags">
@@ -343,6 +384,15 @@
<constant name="EMISSION_SHAPE_MAX" value="7" enum="EmissionShape">
Represents the size of the [enum EmissionShape] enum.
</constant>
+ <constant name="PARAM_TURB_VEL_INFLUENCE" value="13" enum="Parameter">
+ Use with [method set_param_min] and [method set_param_max] to set the turbulence minimum und maximum influence on each particles velocity.
+ </constant>
+ <constant name="PARAM_TURB_INIT_DISPLACEMENT" value="14" enum="Parameter">
+ Use with [method set_param_min] and [method set_param_max] to set the turbulence minimum and maximum displacement of the particles spawn position.
+ </constant>
+ <constant name="PARAM_TURB_INFLUENCE_OVER_LIFE" value="12" enum="Parameter">
+ Use with [method set_param_texture] to set the turbulence influence over the particles life time.
+ </constant>
<constant name="SUB_EMITTER_DISABLED" value="0" enum="SubEmitterMode">
</constant>
<constant name="SUB_EMITTER_CONSTANT" value="1" enum="SubEmitterMode">
@@ -352,6 +402,7 @@
<constant name="SUB_EMITTER_AT_COLLISION" value="3" enum="SubEmitterMode">
</constant>
<constant name="SUB_EMITTER_MAX" value="4" enum="SubEmitterMode">
+ Represents the size of the [enum SubEmitterMode] enum.
</constant>
</constants>
</class>
diff --git a/doc/classes/PhysicsRayQueryParameters2D.xml b/doc/classes/PhysicsRayQueryParameters2D.xml
index 36933ef9a2..1cfc6caadf 100644
--- a/doc/classes/PhysicsRayQueryParameters2D.xml
+++ b/doc/classes/PhysicsRayQueryParameters2D.xml
@@ -8,6 +8,22 @@
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="create" qualifiers="static">
+ <return type="PhysicsRayQueryParameters2D" />
+ <argument index="0" name="from" type="Vector2" />
+ <argument index="1" name="to" type="Vector2" />
+ <argument index="2" name="collision_mask" type="int" default="4294967295" />
+ <argument index="3" name="exclude" type="Array" default="[]" />
+ <description>
+ Returns a new, pre-configured [PhysicsRayQueryParameters2D] object. Use it to quickly create query parameters using the most common options.
+ [codeblock]
+ var query = PhysicsRayQueryParameters2D.create(global_position, global_position + Vector2(0, 100))
+ var collision = get_world_2d().direct_space_state.intersect_ray(query)
+ [/codeblock]
+ </description>
+ </method>
+ </methods>
<members>
<member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false">
If [code]true[/code], the query will take [Area2D]s into account.
diff --git a/doc/classes/PhysicsRayQueryParameters3D.xml b/doc/classes/PhysicsRayQueryParameters3D.xml
index 4244ec785f..e9216a8300 100644
--- a/doc/classes/PhysicsRayQueryParameters3D.xml
+++ b/doc/classes/PhysicsRayQueryParameters3D.xml
@@ -8,6 +8,22 @@
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="create" qualifiers="static">
+ <return type="PhysicsRayQueryParameters3D" />
+ <argument index="0" name="from" type="Vector3" />
+ <argument index="1" name="to" type="Vector3" />
+ <argument index="2" name="collision_mask" type="int" default="4294967295" />
+ <argument index="3" name="exclude" type="Array" default="[]" />
+ <description>
+ Returns a new, pre-configured [PhysicsRayQueryParameters3D] object. Use it to quickly create query parameters using the most common options.
+ [codeblock]
+ var query = PhysicsRayQueryParameters3D.create(position, position + Vector3(0, -10, 0))
+ var collision = get_world_3d().direct_space_state.intersect_ray(query)
+ [/codeblock]
+ </description>
+ </method>
+ </methods>
<members>
<member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false">
If [code]true[/code], the query will take [Area3D]s into account.
diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml
index a42ceba777..df9d25902b 100644
--- a/doc/classes/Plane.xml
+++ b/doc/classes/Plane.xml
@@ -77,15 +77,15 @@
<return type="float" />
<argument index="0" name="point" type="Vector3" />
<description>
- Returns the shortest distance from the plane to the position [code]point[/code].
+ Returns the shortest distance from the plane to the position [code]point[/code]. If the point is above the plane, the distance will be positive. If below, the distance will be negative.
</description>
</method>
<method name="has_point" qualifiers="const">
<return type="bool" />
<argument index="0" name="point" type="Vector3" />
- <argument index="1" name="epsilon" type="float" default="1e-05" />
+ <argument index="1" name="tolerance" type="float" default="1e-05" />
<description>
- Returns [code]true[/code] if [code]point[/code] is inside the plane. Comparison uses a custom minimum [code]epsilon[/code] threshold.
+ Returns [code]true[/code] if [code]point[/code] is inside the plane. Comparison uses a custom minimum [code]tolerance[/code] threshold.
</description>
</method>
<method name="intersect_3" qualifiers="const">
@@ -109,7 +109,7 @@
<argument index="0" name="from" type="Vector3" />
<argument index="1" name="to" type="Vector3" />
<description>
- Returns the intersection point of a segment from position [code]begin[/code] to position [code]end[/code] with this plane. If no intersection is found, [code]null[/code] is returned.
+ Returns the intersection point of a segment from position [code]from[/code] to position [code]to[/code] with this plane. If no intersection is found, [code]null[/code] is returned.
</description>
</method>
<method name="is_equal_approx" qualifiers="const">
@@ -121,7 +121,7 @@
</method>
<method name="is_point_over" qualifiers="const">
<return type="bool" />
- <argument index="0" name="plane" type="Vector3" />
+ <argument index="0" name="point" type="Vector3" />
<description>
Returns [code]true[/code] if [code]point[/code] is located above the plane.
</description>
@@ -179,6 +179,13 @@
[b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable.
</description>
</operator>
+ <operator name="operator *">
+ <return type="Plane" />
+ <argument index="0" name="right" type="Transform3D" />
+ <description>
+ Inversely transforms (multiplies) the [Plane] by the given [Transform3D] transformation matrix.
+ </description>
+ </operator>
<operator name="operator ==">
<return type="bool" />
<argument index="0" name="right" type="Plane" />
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..40477d27d4 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>
@@ -491,9 +494,39 @@
<member name="debug/shapes/navigation/disabled_geometry_color" type="Color" setter="" getter="" default="Color(1, 0.7, 0.1, 0.4)">
Color of the disabled navigation geometry, visible when "Visible Navigation" is enabled in the Debug menu.
</member>
+ <member name="debug/shapes/navigation/edge_connection_color" type="Color" setter="" getter="" default="Color(1, 0, 1, 1)">
+ Color to display edge connections between navigation regions, visible when "Visible Navigation" is enabled in the Debug menu.
+ </member>
+ <member name="debug/shapes/navigation/enable_edge_connections" type="bool" setter="" getter="" default="true">
+ If enabled, displays edge connections between navigation regions when "Visible Navigation" is enabled in the Debug menu.
+ </member>
+ <member name="debug/shapes/navigation/enable_edge_connections_xray" type="bool" setter="" getter="" default="true">
+ If enabled, displays edge connections between navigation regions through geometry when "Visible Navigation" is enabled in the Debug menu.
+ </member>
+ <member name="debug/shapes/navigation/enable_edge_lines" type="bool" setter="" getter="" default="true">
+ If enabled, displays navigation mesh polygon edges when "Visible Navigation" is enabled in the Debug menu.
+ </member>
+ <member name="debug/shapes/navigation/enable_edge_lines_xray" type="bool" setter="" getter="" default="true">
+ If enabled, displays navigation mesh polygon edges through geometry when "Visible Navigation" is enabled in the Debug menu.
+ </member>
+ <member name="debug/shapes/navigation/enable_geometry_face_random_color" type="bool" setter="" getter="" default="true">
+ If enabled, colorizes each navigation mesh polygon face with a random color when "Visible Navigation" is enabled in the Debug menu.
+ </member>
<member name="debug/shapes/navigation/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)">
Color of the navigation geometry, visible when "Visible Navigation" is enabled in the Debug menu.
</member>
+ <member name="debug/shapes/navigation/geometry_edge_color" type="Color" setter="" getter="" default="Color(0.5, 1, 1, 1)">
+ Color to display enabled navigation mesh polygon edges, visible when "Visible Navigation" is enabled in the Debug menu.
+ </member>
+ <member name="debug/shapes/navigation/geometry_edge_disabled_color" type="Color" setter="" getter="" default="Color(0.5, 0.5, 0.5, 1)">
+ Color to display disabled navigation mesh polygon edges, visible when "Visible Navigation" is enabled in the Debug menu.
+ </member>
+ <member name="debug/shapes/navigation/geometry_face_color" type="Color" setter="" getter="" default="Color(0.5, 1, 1, 0.4)">
+ Color to display enabled navigation mesh polygon faces, visible when "Visible Navigation" is enabled in the Debug menu.
+ </member>
+ <member name="debug/shapes/navigation/geometry_face_disabled_color" type="Color" setter="" getter="" default="Color(0.5, 0.5, 0.5, 0.4)">
+ Color to display disabled navigation mesh polygon faces, visible when "Visible Navigation" is enabled in the Debug menu.
+ </member>
<member name="debug/shapes/paths/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)">
Color of the curve path geometry, visible when "Visible Paths" is enabled in the Debug menu.
</member>
@@ -555,7 +588,7 @@
[b]Note:[/b] By default, or when set to 0, the initial window width is the viewport [member display/window/size/viewport_width]. This setting is ignored on iOS, Android, and HTML5.
</member>
<member name="display/window/vsync/vsync_mode" type="int" setter="" getter="" default="1">
- Sets the VSync mode for the main game window.
+ Sets the V-Sync mode for the main game window.
See [enum DisplayServer.VSyncMode] for possible values and how they affect the behavior of your application.
Depending on the platform and used renderer, the engine will fall back to [code]Enabled[/code], if the desired mode is not supported.
</member>
@@ -628,7 +661,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 +669,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 +677,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>
@@ -1629,13 +1662,13 @@
Sets the number of MSAA samples to use (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware. See also bilinear scaling 3d [member rendering/scaling_3d/mode] for supersampling, which provides higher quality but is much more expensive.
</member>
<member name="rendering/anti_aliasing/quality/screen_space_aa" type="int" setter="" getter="" default="0">
- Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry.
+ Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. The blurriness can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]).
Another way to combat specular aliasing is to enable [member rendering/anti_aliasing/screen_space_roughness_limiter/enabled].
</member>
<member name="rendering/anti_aliasing/quality/use_debanding" type="bool" setter="" getter="" default="false">
</member>
<member name="rendering/anti_aliasing/quality/use_taa" type="bool" setter="" getter="" default="false">
- Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion.
+ Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. Enabling TAA can make the image blurrier, which can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]).
[b]Note:[/b] The implementation is not complete yet, some visual instances such as particles and skinned meshes may show artifacts.
</member>
<member name="rendering/anti_aliasing/screen_space_roughness_limiter/amount" type="float" setter="" getter="" default="0.25">
@@ -1853,9 +1886,6 @@
<member name="rendering/reflections/sky_reflections/texture_array_reflections.mobile" type="bool" setter="" getter="" default="false">
Lower-end override for [member rendering/reflections/sky_reflections/texture_array_reflections] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/scaling_3d/fsr_mipmap_bias" type="float" setter="" getter="" default="0.0">
- Affects the final texture sharpness by reading from a lower or higher mipmap. Negative values make textures sharper, while positive values make textures blurrier. When using FSR, this value is used to adjust the mipmap bias calculated internally which is based on the selected quality. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]
- </member>
<member name="rendering/scaling_3d/fsr_sharpness" type="float" setter="" getter="" default="0.2">
Determines how sharp the upscaled image will be when using the FSR upscaling mode. Sharpness halves with every whole number. Values go from 0.0 (sharpest) to 2.0. Values above 2.0 won't make a visible difference.
</member>
@@ -1895,53 +1925,61 @@
<member name="rendering/shadows/directional_shadow/size.mobile" type="int" setter="" getter="" default="2048">
Lower-end override for [member rendering/shadows/directional_shadow/size] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/shadows/directional_shadow/soft_shadow_quality" type="int" setter="" getter="" default="2">
+ <member name="rendering/shadows/directional_shadow/soft_shadow_filter_quality" type="int" setter="" getter="" default="2">
Quality setting for shadows cast by [DirectionalLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
[b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance].
[b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply [i]constant[/i] shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows.
</member>
- <member name="rendering/shadows/directional_shadow/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
- Lower-end override for [member rendering/shadows/directional_shadow/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/shadows/directional_shadow/soft_shadow_filter_quality.mobile" type="int" setter="" getter="" default="0">
+ Lower-end override for [member rendering/shadows/directional_shadow/soft_shadow_filter_quality] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/shadows/shadow_atlas/16_bits" type="bool" setter="" getter="" default="true">
+ <member name="rendering/shadows/positional_shadow/atlas_16_bits" type="bool" setter="" getter="" default="true">
</member>
- <member name="rendering/shadows/shadow_atlas/quadrant_0_subdiv" type="int" setter="" getter="" default="2">
+ <member name="rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv" type="int" setter="" getter="" default="2">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
- <member name="rendering/shadows/shadow_atlas/quadrant_1_subdiv" type="int" setter="" getter="" default="2">
+ <member name="rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv" type="int" setter="" getter="" default="2">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
- <member name="rendering/shadows/shadow_atlas/quadrant_2_subdiv" type="int" setter="" getter="" default="3">
+ <member name="rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv" type="int" setter="" getter="" default="3">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
- <member name="rendering/shadows/shadow_atlas/quadrant_3_subdiv" type="int" setter="" getter="" default="4">
+ <member name="rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv" type="int" setter="" getter="" default="4">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
- <member name="rendering/shadows/shadow_atlas/size" type="int" setter="" getter="" default="4096">
+ <member name="rendering/shadows/positional_shadow/atlas_size" type="int" setter="" getter="" default="4096">
Size for shadow atlas (used for OmniLights and SpotLights). See documentation.
</member>
- <member name="rendering/shadows/shadow_atlas/size.mobile" type="int" setter="" getter="" default="2048">
- Lower-end override for [member rendering/shadows/shadow_atlas/size] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/shadows/positional_shadow/atlas_size.mobile" type="int" setter="" getter="" default="2048">
+ Lower-end override for [member rendering/shadows/positional_shadow/atlas_size] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/shadows/shadows/soft_shadow_quality" type="int" setter="" getter="" default="2">
+ <member name="rendering/shadows/positional_shadow/soft_shadow_filter_quality" type="int" setter="" getter="" default="2">
Quality setting for shadows cast by [OmniLight3D]s and [SpotLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
[b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance].
[b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows.
</member>
- <member name="rendering/shadows/shadows/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
- Lower-end override for [member rendering/shadows/shadows/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
+ <member name="rendering/shadows/positional_shadow/soft_shadow_filter_quality.mobile" type="int" setter="" getter="" default="0">
+ Lower-end override for [member rendering/shadows/positional_shadow/soft_shadow_filter_quality] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/textures/decals/filter" type="int" setter="" getter="" default="3">
+ The filtering quality to use for [Decal] nodes. When using one of the anisotropic filtering modes, the anisotropic filtering level is controlled by [member rendering/textures/default_filters/anisotropic_filtering_level].
</member>
<member name="rendering/textures/default_filters/anisotropic_filtering_level" type="int" setter="" getter="" default="2">
Sets the maximum number of samples to take when using anisotropic filtering on textures (as a power of two). A higher sample count will result in sharper textures at oblique angles, but is more expensive to compute. A value of [code]0[/code] forcibly disables anisotropic filtering, even on materials where it is enabled.
+ The anisotropic filtering level also affects decals and light projectors if they are configured to use anisotropic filtering. See [member rendering/textures/decals/filter] and [member rendering/textures/light_projectors/filter].
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time.
</member>
+ <member name="rendering/textures/default_filters/texture_mipmap_bias" type="float" setter="" getter="" default="0.0">
+ Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias.
+ [b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code].
+ [b]Note:[/b] This property is only read when the project starts. To change the mipmap LOD bias at run-time, set [member Viewport.texture_mipmap_bias] instead.
+ </member>
<member name="rendering/textures/default_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false">
If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used.
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time.
</member>
<member name="rendering/textures/light_projectors/filter" type="int" setter="" getter="" default="3">
+ The filtering quality to use for [OmniLight3D] and [SpotLight3D] projectors. When using one of the anisotropic filtering modes, the anisotropic filtering level is controlled by [member rendering/textures/default_filters/anisotropic_filtering_level].
</member>
<member name="rendering/textures/lossless_compression/force_png" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP.
@@ -1965,6 +2003,12 @@
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
+ <member name="rendering/vrs/mode" type="int" setter="" getter="" default="0">
+ Set the default Variable Rate Shading (VRS) mode for the main viewport. See [member Viewport.vrs_mode] to change this at runtime, and [enum Viewport.VRSMode] for possible values.
+ </member>
+ <member name="rendering/vrs/texture" type="String" setter="" getter="" default="&quot;&quot;">
+ If [member rendering/vrs/mode] is set to texture, this is the path to default texture loaded as the VRS image.
+ </member>
<member name="rendering/vulkan/descriptor_pools/max_descriptors_per_pool" type="int" setter="" getter="" default="64">
</member>
<member name="rendering/vulkan/rendering/back_end" type="int" setter="" getter="" default="0">
@@ -1977,6 +2021,12 @@
</member>
<member name="rendering/vulkan/staging_buffer/texture_upload_region_size_px" type="int" setter="" getter="" default="64">
</member>
+ <member name="threading/worker_pool/low_priority_thread_ratio" type="float" setter="" getter="" default="0.3">
+ </member>
+ <member name="threading/worker_pool/max_threads" type="int" setter="" getter="" default="-1">
+ </member>
+ <member name="threading/worker_pool/use_system_threads_for_low_priority_tasks" type="bool" setter="" getter="" default="true">
+ </member>
<member name="xr/openxr/default_action_map" type="String" setter="" getter="" default="&quot;res://openxr_action_map.tres&quot;">
Action map configuration to load by default.
</member>
diff --git a/doc/classes/Projection.xml b/doc/classes/Projection.xml
new file mode 100644
index 0000000000..2bbfd04e9e
--- /dev/null
+++ b/doc/classes/Projection.xml
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="Projection" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <constructors>
+ <constructor name="Projection">
+ <return type="Projection" />
+ <description>
+ </description>
+ </constructor>
+ <constructor name="Projection">
+ <return type="Projection" />
+ <argument index="0" name="from" type="Projection" />
+ <description>
+ </description>
+ </constructor>
+ <constructor name="Projection">
+ <return type="Projection" />
+ <argument index="0" name="from" type="Transform3D" />
+ <description>
+ </description>
+ </constructor>
+ </constructors>
+ <methods>
+ <method name="create_depth_correction" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="flip_y" type="bool" />
+ <description>
+ </description>
+ </method>
+ <method name="create_fit_aabb" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="aabb" type="AABB" />
+ <description>
+ </description>
+ </method>
+ <method name="create_for_hmd" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="eye" type="int" />
+ <argument index="1" name="aspect" type="float" />
+ <argument index="2" name="intraocular_dist" type="float" />
+ <argument index="3" name="display_width" type="float" />
+ <argument index="4" name="display_to_lens" type="float" />
+ <argument index="5" name="oversample" type="float" />
+ <argument index="6" name="z_near" type="float" />
+ <argument index="7" name="z_far" type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="create_frustum" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="left" type="float" />
+ <argument index="1" name="right" type="float" />
+ <argument index="2" name="bottom" type="float" />
+ <argument index="3" name="top" type="float" />
+ <argument index="4" name="z_near" type="float" />
+ <argument index="5" name="z_far" type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="create_frustum_aspect" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="size" type="float" />
+ <argument index="1" name="aspect" type="float" />
+ <argument index="2" name="offset" type="Vector2" />
+ <argument index="3" name="z_near" type="float" />
+ <argument index="4" name="z_far" type="float" />
+ <argument index="5" name="flip_fov" type="bool" default="false" />
+ <description>
+ </description>
+ </method>
+ <method name="create_light_atlas_rect" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="rect" type="Rect2" />
+ <description>
+ </description>
+ </method>
+ <method name="create_orthogonal" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="left" type="float" />
+ <argument index="1" name="right" type="float" />
+ <argument index="2" name="bottom" type="float" />
+ <argument index="3" name="top" type="float" />
+ <argument index="4" name="z_near" type="float" />
+ <argument index="5" name="z_far" type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="create_orthogonal_aspect" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="size" type="float" />
+ <argument index="1" name="aspect" type="float" />
+ <argument index="2" name="z_near" type="float" />
+ <argument index="3" name="z_far" type="float" />
+ <argument index="4" name="flip_fov" type="bool" default="false" />
+ <description>
+ </description>
+ </method>
+ <method name="create_perspective" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="fovy" type="float" />
+ <argument index="1" name="aspect" type="float" />
+ <argument index="2" name="z_near" type="float" />
+ <argument index="3" name="z_far" type="float" />
+ <argument index="4" name="flip_fov" type="bool" default="false" />
+ <description>
+ </description>
+ </method>
+ <method name="create_perspective_hmd" qualifiers="static">
+ <return type="Projection" />
+ <argument index="0" name="fovy" type="float" />
+ <argument index="1" name="aspect" type="float" />
+ <argument index="2" name="z_near" type="float" />
+ <argument index="3" name="z_far" type="float" />
+ <argument index="4" name="flip_fov" type="bool" />
+ <argument index="5" name="eye" type="int" />
+ <argument index="6" name="intraocular_dist" type="float" />
+ <argument index="7" name=" convergence_dist" type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="determinant" qualifiers="const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="flipped_y" qualifiers="const">
+ <return type="Projection" />
+ <description>
+ </description>
+ </method>
+ <method name="get_aspect" qualifiers="const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="get_far_plane_half_extents" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ </description>
+ </method>
+ <method name="get_fov" qualifiers="const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="get_fovy" qualifiers="static">
+ <return type="float" />
+ <argument index="0" name="fovx" type="float" />
+ <argument index="1" name="aspect" type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="get_lod_multiplier" qualifiers="const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="get_pixels_per_meter" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="for_pixel_width" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="get_projection_plane" qualifiers="const">
+ <return type="Plane" />
+ <argument index="0" name="plane" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="get_viewport_half_extents" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ </description>
+ </method>
+ <method name="get_z_far" qualifiers="const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="get_z_near" qualifiers="const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="inverse" qualifiers="const">
+ <return type="Projection" />
+ <description>
+ </description>
+ </method>
+ <method name="is_orthogonal" qualifiers="const">
+ <return type="bool" />
+ <description>
+ </description>
+ </method>
+ <method name="jitter_offseted" qualifiers="const">
+ <return type="Projection" />
+ <argument index="0" name="offset" type="Vector2" />
+ <description>
+ </description>
+ </method>
+ <method name="perspective_znear_adjusted" qualifiers="const">
+ <return type="Projection" />
+ <argument index="0" name="new_znear" type="float" />
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="w" type="Vector4" setter="" getter="" default="Vector4(0, 0, 0, 1)">
+ </member>
+ <member name="x" type="Vector4" setter="" getter="" default="Vector4(1, 0, 0, 0)">
+ </member>
+ <member name="y" type="Vector4" setter="" getter="" default="Vector4(0, 1, 0, 0)">
+ </member>
+ <member name="z" type="Vector4" setter="" getter="" default="Vector4(0, 0, 1, 0)">
+ </member>
+ </members>
+ <constants>
+ <constant name="PLANE_NEAR" value="0">
+ </constant>
+ <constant name="PLANE_FAR" value="1">
+ </constant>
+ <constant name="PLANE_LEFT" value="2">
+ </constant>
+ <constant name="PLANE_TOP" value="3">
+ </constant>
+ <constant name="PLANE_RIGHT" value="4">
+ </constant>
+ <constant name="PLANE_BOTTOM" value="5">
+ </constant>
+ <constant name="IDENTITY" value="Projection(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)">
+ </constant>
+ <constant name="ZERO" value="Projection(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)">
+ </constant>
+ </constants>
+ <operators>
+ <operator name="operator !=">
+ <return type="bool" />
+ <argument index="0" name="right" type="Projection" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Projection" />
+ <argument index="0" name="right" type="Projection" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator ==">
+ <return type="bool" />
+ <argument index="0" name="right" type="Projection" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator []">
+ <return type="Vector4" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </operator>
+ </operators>
+</class>
diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml
index 48e6317b11..30e96607da 100644
--- a/doc/classes/Quaternion.xml
+++ b/doc/classes/Quaternion.xml
@@ -74,16 +74,6 @@
[b]Note:[/b] This method has an abnormally high amount of floating-point error, so methods such as [code]is_zero_approx[/code] will not work reliably.
</description>
</method>
- <method name="cubic_slerp" qualifiers="const">
- <return type="Quaternion" />
- <argument index="0" name="b" type="Quaternion" />
- <argument index="1" name="pre_a" type="Quaternion" />
- <argument index="2" name="post_b" type="Quaternion" />
- <argument index="3" name="weight" type="float" />
- <description>
- Performs a cubic spherical interpolation between quaternions [code]pre_a[/code], this vector, [code]b[/code], and [code]post_b[/code], by the given amount [code]weight[/code].
- </description>
- </method>
<method name="dot" qualifiers="const">
<return type="float" />
<argument index="0" name="with" type="Quaternion" />
@@ -171,6 +161,16 @@
Returns the result of the spherical linear interpolation between this quaternion and [code]to[/code] by amount [code]weight[/code], but without checking if the rotation path is not bigger than 90 degrees.
</description>
</method>
+ <method name="spherical_cubic_interpolate" qualifiers="const">
+ <return type="Quaternion" />
+ <argument index="0" name="b" type="Quaternion" />
+ <argument index="1" name="pre_a" type="Quaternion" />
+ <argument index="2" name="post_b" type="Quaternion" />
+ <argument index="3" name="weight" type="float" />
+ <description>
+ Performs a spherical cubic interpolation between quaternions [code]pre_a[/code], this vector, [code]b[/code], and [code]post_b[/code], by the given amount [code]weight[/code].
+ </description>
+ </method>
</methods>
<members>
<member name="w" type="float" setter="" getter="" default="1.0">
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index 0d121a29d2..3962f309de 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -305,6 +305,12 @@
<description>
</description>
</method>
+ <method name="framebuffer_is_valid" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="framebuffer" type="RID" />
+ <description>
+ </description>
+ </method>
<method name="free_rid">
<return type="void" />
<argument index="0" name="rid" type="RID" />
@@ -395,7 +401,7 @@
<description>
</description>
</method>
- <method name="limit_get">
+ <method name="limit_get" qualifiers="const">
<return type="int" />
<argument index="0" name="limit" type="int" enum="RenderingDevice.Limit" />
<description>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index d92121a950..c06b2e1d98 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -890,7 +890,7 @@
<description>
</description>
</method>
- <method name="directional_shadow_quality_set">
+ <method name="directional_soft_shadow_filter_set_quality">
<return type="void" />
<argument index="0" name="quality" type="int" enum="RenderingServer.ShadowQuality" />
<description>
@@ -1293,45 +1293,45 @@
If [code]half_resolution[/code] is [code]true[/code], renders [VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) buffers at halved resolution (e.g. 960×540 when the viewport size is 1920×1080). This improves performance significantly when VoxelGI or SDFGI is enabled, at the cost of artifacts that may be visible on polygon edges. The loss in quality becomes less noticeable as the viewport resolution increases. [LightmapGI] rendering is not affected by this setting. See also [member ProjectSettings.rendering/global_illumination/gi/use_half_resolution].
</description>
</method>
- <method name="global_variable_add">
+ <method name="global_shader_uniform_add">
<return type="void" />
<argument index="0" name="name" type="StringName" />
- <argument index="1" name="type" type="int" enum="RenderingServer.GlobalVariableType" />
+ <argument index="1" name="type" type="int" enum="RenderingServer.GlobalShaderUniformType" />
<argument index="2" name="default_value" type="Variant" />
<description>
</description>
</method>
- <method name="global_variable_get" qualifiers="const">
+ <method name="global_shader_uniform_get" qualifiers="const">
<return type="Variant" />
<argument index="0" name="name" type="StringName" />
<description>
</description>
</method>
- <method name="global_variable_get_list" qualifiers="const">
+ <method name="global_shader_uniform_get_list" qualifiers="const">
<return type="PackedStringArray" />
<description>
</description>
</method>
- <method name="global_variable_get_type" qualifiers="const">
- <return type="int" enum="RenderingServer.GlobalVariableType" />
+ <method name="global_shader_uniform_get_type" qualifiers="const">
+ <return type="int" enum="RenderingServer.GlobalShaderUniformType" />
<argument index="0" name="name" type="StringName" />
<description>
</description>
</method>
- <method name="global_variable_remove">
+ <method name="global_shader_uniform_remove">
<return type="void" />
<argument index="0" name="name" type="StringName" />
<description>
</description>
</method>
- <method name="global_variable_set">
+ <method name="global_shader_uniform_set">
<return type="void" />
<argument index="0" name="name" type="StringName" />
<argument index="1" name="value" type="Variant" />
<description>
</description>
</method>
- <method name="global_variable_set_override">
+ <method name="global_shader_uniform_set_override">
<return type="void" />
<argument index="0" name="name" type="StringName" />
<argument index="1" name="value" type="Variant" />
@@ -1391,21 +1391,21 @@
Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
- <method name="instance_geometry_get_shader_parameter" qualifiers="const">
+ <method name="instance_geometry_get_shader_uniform" qualifiers="const">
<return type="Variant" />
<argument index="0" name="instance" type="RID" />
<argument index="1" name="parameter" type="StringName" />
<description>
</description>
</method>
- <method name="instance_geometry_get_shader_parameter_default_value" qualifiers="const">
+ <method name="instance_geometry_get_shader_uniform_default_value" qualifiers="const">
<return type="Variant" />
<argument index="0" name="instance" type="RID" />
<argument index="1" name="parameter" type="StringName" />
<description>
</description>
</method>
- <method name="instance_geometry_get_shader_parameter_list" qualifiers="const">
+ <method name="instance_geometry_get_shader_uniform_list" qualifiers="const">
<return type="Array" />
<argument index="0" name="instance" type="RID" />
<description>
@@ -1460,7 +1460,7 @@
Sets a material that will override the material for all surfaces on the mesh associated with this instance. Equivalent to [member GeometryInstance3D.material_override].
</description>
</method>
- <method name="instance_geometry_set_shader_parameter">
+ <method name="instance_geometry_set_shader_uniform">
<return type="void" />
<argument index="0" name="instance" type="RID" />
<argument index="1" name="parameter" type="StringName" />
@@ -2519,6 +2519,12 @@
If [code]true[/code], particles use local coordinates. If [code]false[/code] they use global coordinates. Equivalent to [member GPUParticles3D.local_coords].
</description>
</method>
+ <method name="positional_soft_shadow_filter_set_quality">
+ <return type="void" />
+ <argument index="0" name="quality" type="int" enum="RenderingServer.ShadowQuality" />
+ <description>
+ </description>
+ </method>
<method name="reflection_probe_create">
<return type="RID" />
<description>
@@ -2735,13 +2741,20 @@
<description>
</description>
</method>
- <method name="shader_get_param_list" qualifiers="const">
+ <method name="shader_get_shader_uniform_list" qualifiers="const">
<return type="Dictionary[]" />
<argument index="0" name="shader" type="RID" />
<description>
Returns the parameters of a shader.
</description>
</method>
+ <method name="shader_set_code">
+ <return type="void" />
+ <argument index="0" name="shader" type="RID" />
+ <argument index="1" name="code" type="String" />
+ <description>
+ </description>
+ </method>
<method name="shader_set_default_texture_param">
<return type="void" />
<argument index="0" name="shader" type="RID" />
@@ -2753,9 +2766,10 @@
[b]Note:[/b] If the sampler array is used use [code]index[/code] to access the specified texture.
</description>
</method>
- <method name="shadows_quality_set">
+ <method name="shader_set_path_hint">
<return type="void" />
- <argument index="0" name="quality" type="int" enum="RenderingServer.ShadowQuality" />
+ <argument index="0" name="shader" type="RID" />
+ <argument index="1" name="path" type="String" />
<description>
</description>
</method>
@@ -3161,14 +3175,6 @@
If [code]true[/code], rendering of a viewport's environment is disabled.
</description>
</method>
- <method name="viewport_set_fsr_mipmap_bias">
- <return type="void" />
- <argument index="0" name="viewport" type="RID" />
- <argument index="1" name="mipmap_bias" type="float" />
- <description>
- Affects the final texture sharpness by reading from a lower or higher mipmap. Negative values make textures sharper, while positive values make textures blurrier. When using FSR, this value is used to adjust the mipmap bias calculated internally which is based on the selected quality. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]
- </description>
- </method>
<method name="viewport_set_fsr_sharpness">
<return type="void" />
<argument index="0" name="viewport" type="RID" />
@@ -3220,6 +3226,25 @@
Sets the viewport's parent to another viewport.
</description>
</method>
+ <method name="viewport_set_positional_shadow_atlas_quadrant_subdivision">
+ <return type="void" />
+ <argument index="0" name="viewport" type="RID" />
+ <argument index="1" name="quadrant" type="int" />
+ <argument index="2" name="subdivision" type="int" />
+ <description>
+ Sets the shadow atlas quadrant's subdivision.
+ </description>
+ </method>
+ <method name="viewport_set_positional_shadow_atlas_size">
+ <return type="void" />
+ <argument index="0" name="viewport" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="use_16_bits" type="bool" default="false" />
+ <description>
+ Sets the size of the shadow atlas's images (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
+ [b]Note:[/b] If this is set to [code]0[/code], no shadows will be visible at all (including directional shadows).
+ </description>
+ </method>
<method name="viewport_set_render_direct_to_screen">
<return type="void" />
<argument index="0" name="viewport" type="RID" />
@@ -3269,24 +3294,6 @@
<description>
</description>
</method>
- <method name="viewport_set_shadow_atlas_quadrant_subdivision">
- <return type="void" />
- <argument index="0" name="viewport" type="RID" />
- <argument index="1" name="quadrant" type="int" />
- <argument index="2" name="subdivision" type="int" />
- <description>
- Sets the shadow atlas quadrant's subdivision.
- </description>
- </method>
- <method name="viewport_set_shadow_atlas_size">
- <return type="void" />
- <argument index="0" name="viewport" type="RID" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="use_16_bits" type="bool" default="false" />
- <description>
- Sets the size of the shadow atlas's images (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
- </description>
- </method>
<method name="viewport_set_size">
<return type="void" />
<argument index="0" name="viewport" type="RID" />
@@ -3310,6 +3317,15 @@
<description>
</description>
</method>
+ <method name="viewport_set_texture_mipmap_bias">
+ <return type="void" />
+ <argument index="0" name="viewport" type="RID" />
+ <argument index="1" name="mipmap_bias" type="float" />
+ <description>
+ Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member ProjectSettings.rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias.
+ [b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code].
+ </description>
+ </method>
<method name="viewport_set_transparent_background">
<return type="void" />
<argument index="0" name="viewport" type="RID" />
@@ -3356,6 +3372,22 @@
If [code]true[/code], the viewport uses augmented or virtual reality technologies. See [XRInterface].
</description>
</method>
+ <method name="viewport_set_vrs_mode">
+ <return type="void" />
+ <argument index="0" name="viewport" type="RID" />
+ <argument index="1" name="mode" type="int" enum="RenderingServer.ViewportVRSMode" />
+ <description>
+ Sets the Variable Rate Shading (VRS) mode for the viewport. Note, if hardware does not support VRS this property is ignored.
+ </description>
+ </method>
+ <method name="viewport_set_vrs_texture">
+ <return type="void" />
+ <argument index="0" name="viewport" type="RID" />
+ <argument index="1" name="texture" type="RID" />
+ <description>
+ Texture to use when the VRS mode is set to [constant RenderingServer.VIEWPORT_VRS_TEXTURE].
+ </description>
+ </method>
<method name="visibility_notifier_create">
<return type="RID" />
<description>
@@ -3715,14 +3747,22 @@
Use [Transform3D] to store MultiMesh transform.
</constant>
<constant name="LIGHT_PROJECTOR_FILTER_NEAREST" value="0" enum="LightProjectorFilter">
+ Nearest-neighbor filter for light projectors (use for pixel art light projectors). No mipmaps are used for rendering, which means light projectors at a distance will look sharp but grainy. This has roughly the same performance cost as using mipmaps.
</constant>
- <constant name="LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS" value="1" enum="LightProjectorFilter">
+ <constant name="LIGHT_PROJECTOR_FILTER_LINEAR" value="1" enum="LightProjectorFilter">
+ Linear filter for light projectors (use for non-pixel art light projectors). No mipmaps are used for rendering, which means light projectors at a distance will look smooth but blurry. This has roughly the same performance cost as using mipmaps.
</constant>
- <constant name="LIGHT_PROJECTOR_FILTER_LINEAR" value="2" enum="LightProjectorFilter">
+ <constant name="LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS" value="2" enum="LightProjectorFilter">
+ Nearest-neighbor filter for light projectors (use for pixel art light projectors). Isotropic mipmaps are used for rendering, which means light projectors at a distance will look smooth but blurry. This has roughly the same performance cost as not using mipmaps.
</constant>
<constant name="LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS" value="3" enum="LightProjectorFilter">
+ Linear filter for light projectors (use for non-pixel art light projectors). Isotropic mipmaps are used for rendering, which means light projectors at a distance will look smooth but blurry. This has roughly the same performance cost as not using mipmaps.
+ </constant>
+ <constant name="LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC" value="4" enum="LightProjectorFilter">
+ Nearest-neighbor filter for light projectors (use for pixel art light projectors). Anisotropic mipmaps are used for rendering, which means light projectors at a distance will look smooth and sharp when viewed from oblique angles. This looks better compared to isotropic mipmaps, but is slower. The level of anisotropic filtering is defined by [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
</constant>
- <constant name="LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="4" enum="LightProjectorFilter">
+ <constant name="LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="5" enum="LightProjectorFilter">
+ Linear filter for light projectors (use for non-pixel art light projectors). Anisotropic mipmaps are used for rendering, which means light projectors at a distance will look smooth and sharp when viewed from oblique angles. This looks better compared to isotropic mipmaps, but is slower. The level of anisotropic filtering is defined by [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
</constant>
<constant name="LIGHT_DIRECTIONAL" value="0" enum="LightType">
Is a directional (sun) light.
@@ -3737,6 +3777,7 @@
The light's energy.
</constant>
<constant name="LIGHT_PARAM_INDIRECT_ENERGY" value="1" enum="LightParam">
+ The light's indirect energy multiplier (final indirect energy is [constant LIGHT_PARAM_ENERGY] * [constant LIGHT_PARAM_INDIRECT_ENERGY]).
</constant>
<constant name="LIGHT_PARAM_SPECULAR" value="2" enum="LightParam">
The light's influence on specularity.
@@ -3780,14 +3821,17 @@
<constant name="LIGHT_PARAM_SHADOW_PANCAKE_SIZE" value="15" enum="LightParam">
Sets the size of the directional shadow pancake. The pancake offsets the start of the shadow's camera frustum to provide a higher effective depth resolution for the shadow. However, a high pancake size can cause artifacts in the shadows of large objects that are close to the edge of the frustum. Reducing the pancake size can help. Setting the size to [code]0[/code] turns off the pancaking effect.
</constant>
- <constant name="LIGHT_PARAM_SHADOW_BLUR" value="16" enum="LightParam">
+ <constant name="LIGHT_PARAM_SHADOW_OPACITY" value="16" enum="LightParam">
+ The light's shadow opacity. Values lower than [code]1.0[/code] make the light appear through shadows. This can be used to fake global illumination at a low performance cost.
+ </constant>
+ <constant name="LIGHT_PARAM_SHADOW_BLUR" value="17" enum="LightParam">
Blurs the edges of the shadow. Can be used to hide pixel artifacts in low resolution shadow maps. A high value can make shadows appear grainy and can cause other unwanted artifacts. Try to keep as near default as possible.
</constant>
- <constant name="LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="17" enum="LightParam">
+ <constant name="LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE" value="18" enum="LightParam">
</constant>
- <constant name="LIGHT_PARAM_TRANSMITTANCE_BIAS" value="18" enum="LightParam">
+ <constant name="LIGHT_PARAM_TRANSMITTANCE_BIAS" value="19" enum="LightParam">
</constant>
- <constant name="LIGHT_PARAM_MAX" value="19" enum="LightParam">
+ <constant name="LIGHT_PARAM_MAX" value="20" enum="LightParam">
Represents the size of the [enum LightParam] enum.
</constant>
<constant name="LIGHT_BAKE_DISABLED" value="0" enum="LightBakeMode">
@@ -3864,14 +3908,22 @@
<constant name="DECAL_TEXTURE_MAX" value="4" enum="DecalTexture">
</constant>
<constant name="DECAL_FILTER_NEAREST" value="0" enum="DecalFilter">
+ Nearest-neighbor filter for decals (use for pixel art decals). No mipmaps are used for rendering, which means decals at a distance will look sharp but grainy. This has roughly the same performance cost as using mipmaps.
</constant>
- <constant name="DECAL_FILTER_NEAREST_MIPMAPS" value="1" enum="DecalFilter">
+ <constant name="DECAL_FILTER_LINEAR" value="1" enum="DecalFilter">
+ Linear filter for decals (use for non-pixel art decals). No mipmaps are used for rendering, which means decals at a distance will look smooth but blurry. This has roughly the same performance cost as using mipmaps.
</constant>
- <constant name="DECAL_FILTER_LINEAR" value="2" enum="DecalFilter">
+ <constant name="DECAL_FILTER_NEAREST_MIPMAPS" value="2" enum="DecalFilter">
+ Nearest-neighbor filter for decals (use for pixel art decals). Isotropic mipmaps are used for rendering, which means decals at a distance will look smooth but blurry. This has roughly the same performance cost as not using mipmaps.
</constant>
<constant name="DECAL_FILTER_LINEAR_MIPMAPS" value="3" enum="DecalFilter">
+ Linear filter for decals (use for non-pixel art decals). Isotropic mipmaps are used for rendering, which means decals at a distance will look smooth but blurry. This has roughly the same performance cost as not using mipmaps.
+ </constant>
+ <constant name="DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC" value="4" enum="DecalFilter">
+ Nearest-neighbor filter for decals (use for pixel art decals). Anisotropic mipmaps are used for rendering, which means decals at a distance will look smooth and sharp when viewed from oblique angles. This looks better compared to isotropic mipmaps, but is slower. The level of anisotropic filtering is defined by [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
</constant>
- <constant name="DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="4" enum="DecalFilter">
+ <constant name="DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC" value="5" enum="DecalFilter">
+ Linear filter for decals (use for non-pixel art decals). Anisotropic mipmaps are used for rendering, which means decals at a distance will look smooth and sharp when viewed from oblique angles. This looks better compared to isotropic mipmaps, but is slower. The level of anisotropic filtering is defined by [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
</constant>
<constant name="VOXEL_GI_QUALITY_LOW" value="0" enum="VoxelGIQuality">
</constant>
@@ -4115,6 +4167,18 @@
</constant>
<constant name="VIEWPORT_DEBUG_DRAW_MOTION_VECTORS" value="25" enum="ViewportDebugDraw">
</constant>
+ <constant name="VIEWPORT_VRS_DISABLED" value="0" enum="ViewportVRSMode">
+ VRS is disabled.
+ </constant>
+ <constant name="VIEWPORT_VRS_TEXTURE" value="1" enum="ViewportVRSMode">
+ VRS uses a texture. Note, for stereoscopic use a texture atlas with a texture for each view.
+ </constant>
+ <constant name="VIEWPORT_VRS_XR" value="2" enum="ViewportVRSMode">
+ VRS texture is supplied by the primary [XRInterface].
+ </constant>
+ <constant name="VIEWPORT_VRS_MAX" value="3" enum="ViewportVRSMode">
+ Represents the size of the [enum ViewportVRSMode] enum.
+ </constant>
<constant name="SKY_MODE_AUTOMATIC" value="0" enum="SkyMode">
</constant>
<constant name="SKY_MODE_QUALITY" value="1" enum="SkyMode">
@@ -4493,63 +4557,63 @@
<constant name="CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE" value="2" enum="CanvasOccluderPolygonCullMode">
Culling of the canvas occluder is counterclockwise.
</constant>
- <constant name="GLOBAL_VAR_TYPE_BOOL" value="0" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_BOOL" value="0" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_BVEC2" value="1" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_BVEC2" value="1" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_BVEC3" value="2" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_BVEC3" value="2" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_BVEC4" value="3" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_BVEC4" value="3" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_INT" value="4" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_INT" value="4" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_IVEC2" value="5" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_IVEC2" value="5" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_IVEC3" value="6" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_IVEC3" value="6" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_IVEC4" value="7" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_IVEC4" value="7" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_RECT2I" value="8" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_RECT2I" value="8" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_UINT" value="9" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_UINT" value="9" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_UVEC2" value="10" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_UVEC2" value="10" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_UVEC3" value="11" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_UVEC3" value="11" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_UVEC4" value="12" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_UVEC4" value="12" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_FLOAT" value="13" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_FLOAT" value="13" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_VEC2" value="14" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_VEC2" value="14" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_VEC3" value="15" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_VEC3" value="15" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_VEC4" value="16" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_VEC4" value="16" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_COLOR" value="17" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_COLOR" value="17" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_RECT2" value="18" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_RECT2" value="18" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_MAT2" value="19" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_MAT2" value="19" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_MAT3" value="20" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_MAT3" value="20" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_MAT4" value="21" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_MAT4" value="21" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_TRANSFORM_2D" value="22" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_TRANSFORM_2D" value="22" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_TRANSFORM" value="23" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_TRANSFORM" value="23" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_SAMPLER2D" value="24" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_SAMPLER2D" value="24" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_SAMPLER2DARRAY" value="25" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_SAMPLER2DARRAY" value="25" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_SAMPLER3D" value="26" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_SAMPLER3D" value="26" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_SAMPLERCUBE" value="27" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_SAMPLERCUBE" value="27" enum="GlobalShaderUniformType">
</constant>
- <constant name="GLOBAL_VAR_TYPE_MAX" value="28" enum="GlobalVariableType">
+ <constant name="GLOBAL_VAR_TYPE_MAX" value="28" enum="GlobalShaderUniformType">
</constant>
<constant name="RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME" value="0" enum="RenderingInfo">
</constant>
diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml
index 36b64f5a86..fef94b5f3b 100644
--- a/doc/classes/ResourceFormatLoader.xml
+++ b/doc/classes/ResourceFormatLoader.xml
@@ -17,6 +17,12 @@
<description>
</description>
</method>
+ <method name="_get_classes_used" qualifiers="virtual const">
+ <return type="PackedStringArray" />
+ <argument index="0" name="path" type="String" />
+ <description>
+ </description>
+ </method>
<method name="_get_dependencies" qualifiers="virtual const">
<return type="PackedStringArray" />
<argument index="0" name="path" type="String" />
diff --git a/doc/classes/ResourceFormatSaver.xml b/doc/classes/ResourceFormatSaver.xml
index c156814a1d..f9c4ca0d49 100644
--- a/doc/classes/ResourceFormatSaver.xml
+++ b/doc/classes/ResourceFormatSaver.xml
@@ -26,8 +26,8 @@
</method>
<method name="_save" qualifiers="virtual">
<return type="int" />
- <argument index="0" name="path" type="String" />
- <argument index="1" name="resource" type="Resource" />
+ <argument index="0" name="path" type="Resource" />
+ <argument index="1" name="resource" type="String" />
<argument index="2" name="flags" type="int" />
<description>
Saves the given resource object to a file at the target [code]path[/code]. [code]flags[/code] is a bitmask composed with [enum ResourceSaver.SaverFlags] constants.
diff --git a/doc/classes/ResourceLoader.xml b/doc/classes/ResourceLoader.xml
index 1ffb0dba5c..729058c9b3 100644
--- a/doc/classes/ResourceLoader.xml
+++ b/doc/classes/ResourceLoader.xml
@@ -6,11 +6,21 @@
<description>
Singleton used to load resource files from the filesystem.
It uses the many [ResourceFormatLoader] classes registered in the engine (either built-in or from a plugin) to load files into memory and convert them to a format that can be used by the engine.
+ [b]Note:[/b] You have to import the files into the engine first to load them using [method load]. If you want to load [Image]s at run-time, you may use [method Image.load]. If you want to import audio files, you can use the snippet described in [member AudioStreamMP3.data].
</description>
<tutorials>
<link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link>
</tutorials>
<methods>
+ <method name="add_resource_format_loader">
+ <return type="void" />
+ <argument index="0" name="format_loader" type="ResourceFormatLoader" />
+ <argument index="1" name="at_front" type="bool" default="false" />
+ <description>
+ Registers a new [ResourceFormatLoader]. The ResourceLoader will use the ResourceFormatLoader as described in [method load].
+ This method is performed implicitly for ResourceFormatLoaders written in GDScript (see [ResourceFormatLoader] for more information).
+ </description>
+ </method>
<method name="exists">
<return type="bool" />
<argument index="0" name="path" type="String" />
@@ -85,8 +95,17 @@
<argument index="0" name="path" type="String" />
<argument index="1" name="type_hint" type="String" default="&quot;&quot;" />
<argument index="2" name="use_sub_threads" type="bool" default="false" />
+ <argument index="3" name="cache_mode" type="int" enum="ResourceLoader.CacheMode" default="1" />
<description>
Loads the resource using threads. If [code]use_sub_threads[/code] is [code]true[/code], multiple threads will be used to load the resource, which makes loading faster, but may affect the main thread (and thus cause game slowdowns).
+ The [code]cache_mode[/code] property defines whether and how the cache should be used or updated when loading the resource. See [enum CacheMode] for details.
+ </description>
+ </method>
+ <method name="remove_resource_format_loader">
+ <return type="void" />
+ <argument index="0" name="format_loader" type="ResourceFormatLoader" />
+ <description>
+ Unregisters the given [ResourceFormatLoader].
</description>
</method>
<method name="set_abort_on_missing_resources">
diff --git a/doc/classes/ResourceSaver.xml b/doc/classes/ResourceSaver.xml
index a029fb9acf..10387a4f14 100644
--- a/doc/classes/ResourceSaver.xml
+++ b/doc/classes/ResourceSaver.xml
@@ -10,6 +10,15 @@
<tutorials>
</tutorials>
<methods>
+ <method name="add_resource_format_saver">
+ <return type="void" />
+ <argument index="0" name="format_saver" type="ResourceFormatSaver" />
+ <argument index="1" name="at_front" type="bool" default="false" />
+ <description>
+ Registers a new [ResourceFormatSaver]. The ResourceSaver will use the ResourceFormatSaver as described in [method save].
+ This method is performed implicitly for ResourceFormatSavers written in GDScript (see [ResourceFormatSaver] for more information).
+ </description>
+ </method>
<method name="get_recognized_extensions">
<return type="PackedStringArray" />
<argument index="0" name="type" type="Resource" />
@@ -17,41 +26,48 @@
Returns the list of extensions available for saving a resource of a given type.
</description>
</method>
+ <method name="remove_resource_format_saver">
+ <return type="void" />
+ <argument index="0" name="format_saver" type="ResourceFormatSaver" />
+ <description>
+ Unregisters the given [ResourceFormatSaver].
+ </description>
+ </method>
<method name="save">
<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="0" name="resource" type="Resource" />
+ <argument index="1" name="path" type="String" default="&quot;&quot;" />
+ <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.
+ Saves a resource to disk to the given path, using a [ResourceFormatSaver] that recognizes the resource object. If [code]path[/code] is empty, [ResourceSaver] will try to use [member Resource.resource_path].
The [code]flags[/code] bitmask can be specified to customize the save behavior using [enum SaverFlags] flags.
Returns [constant OK] on success.
</description>
</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/ResourceUID.xml b/doc/classes/ResourceUID.xml
index f91c39b512..782a8a2968 100644
--- a/doc/classes/ResourceUID.xml
+++ b/doc/classes/ResourceUID.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ResourceUID" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Singleton for managing a cache of resource UIDs within a project.
</brief_description>
<description>
+ Resources can not only be referenced using their resource paths [code]res://[/code], but alternatively through a unique identifier specified via [code]uid://[/code].
+ Using UIDs allows for the engine to keep references between resources intact, even if the files get renamed or moved.
+ This singleton is responsible for keeping track of all registered resource UIDs of a project, generating new UIDs and converting between the string and integer representation.
</description>
<tutorials>
</tutorials>
@@ -12,35 +16,45 @@
<argument index="0" name="id" type="int" />
<argument index="1" name="path" type="String" />
<description>
+ Adds a new UID value which is mapped to the given resource path.
+ Fails with an error if the UID already exists, so be sure to check [method has_id] beforehand, or use [method set_id] instead.
</description>
</method>
<method name="create_id">
<return type="int" />
<description>
+ Generates a random resource UID which is guaranteed to be unique within the list of currently loaded UIDs.
+ In order for this UID to be registered, you must call [method add_id] or [method set_id].
</description>
</method>
<method name="get_id_path" qualifiers="const">
<return type="String" />
<argument index="0" name="id" type="int" />
<description>
+ Returns the path that the given UID value refers to.
+ Fails with an error if the UID does not exist, so be sure to check [method has_id] beforehand.
</description>
</method>
<method name="has_id" qualifiers="const">
<return type="bool" />
<argument index="0" name="id" type="int" />
<description>
+ Returns whether the given UID value is known to the cache.
</description>
</method>
<method name="id_to_text" qualifiers="const">
<return type="String" />
<argument index="0" name="id" type="int" />
<description>
+ Converts the given UID to a [code]uid://[/code] string value.
</description>
</method>
<method name="remove_id">
<return type="void" />
<argument index="0" name="id" type="int" />
<description>
+ Removes a loaded UID value from the cache.
+ Fails with an error if the UID does not exist, so be sure to check [method has_id] beforehand.
</description>
</method>
<method name="set_id">
@@ -48,17 +62,22 @@
<argument index="0" name="id" type="int" />
<argument index="1" name="path" type="String" />
<description>
+ Updates the resource path of an existing UID.
+ Fails with an error if the UID does not exist, so be sure to check [method has_id] beforehand, or use [method add_id] instead.
</description>
</method>
<method name="text_to_id" qualifiers="const">
<return type="int" />
<argument index="0" name="text_id" type="String" />
<description>
+ Extracts the UID value from the given [code]uid://[/code] string.
</description>
</method>
</methods>
<constants>
<constant name="INVALID_ID" value="-1">
+ The value to use for an invalid UID, for example if the resource could not be loaded.
+ Its text representation is [code]uid://&lt;invalid&gt;[/code].
</constant>
</constants>
</class>
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 1294e5b58a..8228bcc442 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -272,22 +272,15 @@
<method name="push_font">
<return type="void" />
<argument index="0" name="font" type="Font" />
+ <argument index="1" name="font_size" type="int" />
<description>
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/RootMotionView.xml b/doc/classes/RootMotionView.xml
index 88b8f2cd03..3f3b00e2cb 100644
--- a/doc/classes/RootMotionView.xml
+++ b/doc/classes/RootMotionView.xml
@@ -5,25 +5,25 @@
</brief_description>
<description>
[i]Root motion[/i] refers to an animation technique where a mesh's skeleton is used to give impulse to a character. When working with 3D animations, a popular technique is for animators to use the root skeleton bone to give motion to the rest of the skeleton. This allows animating characters in a way where steps actually match the floor below. It also allows precise interaction with objects during cinematics. See also [AnimationTree].
- [b]Note:[/b] [RootMotionView] is only visible in the editor. It will be hidden automatically in the running project, and will also be converted to a plain [Node] in the running project. This means a script attached to a [RootMotionView] node [i]must[/i] have [code]extends Node[/code] instead of [code]extends RootMotionView[/code]. Additionally, it must not be a [code]@tool[/code] script.
+ [b]Note:[/b] [RootMotionView] is only visible in the editor. It will be hidden automatically in the running project.
</description>
<tutorials>
<link title="Using AnimationTree - Root motion">$DOCS_URL/tutorials/animation/animation_tree.html#root-motion</link>
</tutorials>
<members>
- <member name="animation_path" type="NodePath" setter="set_animation_path" getter="get_animation_path">
+ <member name="animation_path" type="NodePath" setter="set_animation_path" getter="get_animation_path" default="NodePath(&quot;&quot;)">
Path to an [AnimationTree] node to use as a basis for root motion.
</member>
- <member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size">
+ <member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="1.0">
The grid's cell size in 3D units.
</member>
- <member name="color" type="Color" setter="set_color" getter="get_color">
+ <member name="color" type="Color" setter="set_color" getter="get_color" default="Color(0.5, 0.5, 1, 1)">
The grid's color.
</member>
- <member name="radius" type="float" setter="set_radius" getter="get_radius">
+ <member name="radius" type="float" setter="set_radius" getter="get_radius" default="10.0">
The grid's radius in 3D units. The grid's opacity will fade gradually as the distance from the origin increases until this [member radius] is reached.
</member>
- <member name="zero_y" type="bool" setter="set_zero_y" getter="get_zero_y">
+ <member name="zero_y" type="bool" setter="set_zero_y" getter="get_zero_y" default="true">
If [code]true[/code], the grid's points will all be on the same Y coordinate ([i]local[/i] Y = 0). If [code]false[/code], the points' original Y coordinate is preserved.
</member>
</members>
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index cf6ab977db..9982cc0d60 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -18,8 +18,7 @@
<argument index="0" name="group" type="StringName" />
<argument index="1" name="method" type="StringName" />
<description>
- Calls [code]method[/code] on each member of the given group. You can pass arguments to [code]method[/code] by specifying them at the end of the method call.
- [b]Note:[/b] Due to design limitations, [method call_group] will fail silently if one of the arguments is [code]null[/code].
+ Calls [code]method[/code] on each member of the given group. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. If a node doesn't have the given method or the argument list does not match (either in count or in types), it will be skipped.
[b]Note:[/b] [method call_group] will call methods immediately on all members at once, which can cause stuttering if an expensive method is called on lots of members. To wait for one frame after [method call_group] was called, use [method call_group_flags] with the [constant GROUP_CALL_DEFERRED] flag.
</description>
</method>
@@ -29,12 +28,11 @@
<argument index="1" name="group" type="StringName" />
<argument index="2" name="method" type="StringName" />
<description>
- Calls [code]method[/code] on each member of the given group, respecting the given [enum GroupCallFlags]. You can pass arguments to [code]method[/code] by specifying them at the end of the method call.
+ Calls [code]method[/code] on each member of the given group, respecting the given [enum GroupCallFlags]. You can pass arguments to [code]method[/code] by specifying them at the end of the method call. If a node doesn't have the given method or the argument list does not match (either in count or in types), it will be skipped.
[codeblock]
# Call the method in a deferred manner and in reverse order.
get_tree().call_group_flags(SceneTree.GROUP_CALL_DEFERRED | SceneTree.GROUP_CALL_REVERSE)
[/codeblock]
- [b]Note:[/b] Due to design limitations, [method call_group_flags] will fail silently if one of the arguments is [code]null[/code].
[b]Note:[/b] Group call flags are used to control the method calling behavior. By default, methods will be called immediately in a way similar to [method call_group]. However, if the [constant GROUP_CALL_DEFERRED] flag is present in the [code]flags[/code] argument, methods will be called with a one-frame delay in a way similar to [method Object.set_deferred].
</description>
</method>
diff --git a/doc/classes/ScriptCreateDialog.xml b/doc/classes/ScriptCreateDialog.xml
index e21fac2d32..79ee95719d 100644
--- a/doc/classes/ScriptCreateDialog.xml
+++ b/doc/classes/ScriptCreateDialog.xml
@@ -40,6 +40,7 @@
</methods>
<members>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" />
+ <member name="ok_button_text" type="String" setter="set_ok_button_text" getter="get_ok_button_text" overrides="AcceptDialog" default="&quot;Create&quot;" />
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default="&quot;Attach Node Script&quot;" />
</members>
<signals>
diff --git a/doc/classes/ScriptExtension.xml b/doc/classes/ScriptExtension.xml
index 91fa6206d7..4e432ca9a8 100644
--- a/doc/classes/ScriptExtension.xml
+++ b/doc/classes/ScriptExtension.xml
@@ -65,8 +65,8 @@
<description>
</description>
</method>
- <method name="_get_rpc_methods" qualifiers="virtual const">
- <return type="Dictionary[]" />
+ <method name="_get_rpc_config" qualifiers="virtual const">
+ <return type="Variant" />
<description>
</description>
</method>
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/Shader.xml b/doc/classes/Shader.xml
index 10deaf1c41..1921c5b91d 100644
--- a/doc/classes/Shader.xml
+++ b/doc/classes/Shader.xml
@@ -26,7 +26,7 @@
Returns the shader mode for the shader, either [constant MODE_CANVAS_ITEM], [constant MODE_SPATIAL] or [constant MODE_PARTICLES].
</description>
</method>
- <method name="has_param" qualifiers="const">
+ <method name="has_uniform" qualifiers="const">
<return type="bool" />
<argument index="0" name="name" type="StringName" />
<description>
diff --git a/doc/classes/ShaderInclude.xml b/doc/classes/ShaderInclude.xml
new file mode 100644
index 0000000000..40072a933b
--- /dev/null
+++ b/doc/classes/ShaderInclude.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="ShaderInclude" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="code" type="String" setter="set_code" getter="get_code" default="&quot;&quot;">
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/ShaderMaterial.xml b/doc/classes/ShaderMaterial.xml
index 672b660c34..1208b93a62 100644
--- a/doc/classes/ShaderMaterial.xml
+++ b/doc/classes/ShaderMaterial.xml
@@ -10,7 +10,7 @@
<link title="Shaders documentation index">$DOCS_URL/tutorials/shaders/index.html</link>
</tutorials>
<methods>
- <method name="get_shader_param" qualifiers="const">
+ <method name="get_shader_uniform" qualifiers="const">
<return type="Variant" />
<argument index="0" name="param" type="StringName" />
<description>
@@ -31,7 +31,7 @@
Returns the default value of the material property with given [code]name[/code].
</description>
</method>
- <method name="set_shader_param">
+ <method name="set_shader_uniform">
<return type="void" />
<argument index="0" name="param" type="StringName" />
<argument index="1" name="value" type="Variant" />
diff --git a/doc/classes/ShapeCast2D.xml b/doc/classes/ShapeCast2D.xml
index 5fcb60dd09..70da03dc6e 100644
--- a/doc/classes/ShapeCast2D.xml
+++ b/doc/classes/ShapeCast2D.xml
@@ -6,7 +6,7 @@
<description>
Shape casting allows to detect collision objects by sweeping the [member shape] along the cast direction determined by [member target_position] (useful for things like beam weapons).
Immediate collision overlaps can be done with the [member target_position] set to [code]Vector2(0, 0)[/code] and by calling [method force_shapecast_update] within the same [b]physics_frame[/b]. This also helps to overcome some limitations of [Area2D] when used as a continuous detection area, often requiring waiting a couple of frames before collision information is available to [Area2D] nodes, and when using the signals creates unnecessary complexity.
- The node can detect multiple collision objects, but usually the first detected collision
+ The node can detect multiple collision objects, but it's usually used to detect the first collision.
[b]Note:[/b] shape casting is more computationally expensive compared to ray casting.
</description>
<tutorials>
@@ -42,27 +42,27 @@
<method name="get_closest_collision_safe_fraction" qualifiers="const">
<return type="float" />
<description>
- The fraction of the motion (between 0 and 1) of how far the shape can move without triggering a collision. The motion is determined by [member target_position].
+ The fraction from the [ShapeCast2D]'s origin to its [member target_position] (between 0 and 1) of how far the shape can move without triggering a collision.
</description>
</method>
<method name="get_closest_collision_unsafe_fraction" qualifiers="const">
<return type="float" />
<description>
- The fraction of the motion (between 0 and 1) when the shape triggers a collision. The motion is determined by [member target_position].
+ The fraction from the [ShapeCast2D]'s origin to its [member target_position] (between 0 and 1) of how far the shape must move to trigger a collision.
</description>
</method>
<method name="get_collider" qualifiers="const">
<return type="Object" />
<argument index="0" name="index" type="int" />
<description>
- Returns the [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
+ Returns the collided [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
</description>
</method>
<method name="get_collider_shape" qualifiers="const">
<return type="int" />
<argument index="0" name="index" type="int" />
<description>
- Returns the shape ID of one of the multiple collisions at [code]index[/code] that the shape intersects, or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
+ Returns the shape ID of the colliding shape of one of the multiple collisions at [code]index[/code], or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
</description>
</method>
<method name="get_collision_count" qualifiers="const">
@@ -82,14 +82,14 @@
<return type="Vector2" />
<argument index="0" name="index" type="int" />
<description>
- Returns the normal containing one of the multiple collisions at [code]index[/code] of the intersecting object.
+ Returns the normal of one of the multiple collisions at [code]index[/code] of the intersecting object.
</description>
</method>
<method name="get_collision_point" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="index" type="int" />
<description>
- Returns the collision point containing one of the multiple collisions at [code]index[/code] at which the shape intersects the object.
+ Returns the collision point of one of the multiple collisions at [code]index[/code] where the shape intersects the colliding object.
[b]Note:[/b] this point is in the [b]global[/b] coordinate system.
</description>
</method>
@@ -133,7 +133,7 @@
The shape's collision mask. Only objects in at least one collision layer enabled in the mask will be detected.
</member>
<member name="collision_result" type="Array" setter="" getter="_get_collision_result" default="[]">
- A complete collision information. The data returned is the same as in the [method PhysicsDirectSpaceState2D.get_rest_info] method.
+ Returns the complete collision information from the collision sweep. The data returned is the same as in the [method PhysicsDirectSpaceState2D.get_rest_info] method.
</member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
If [code]true[/code], collisions will be reported.
@@ -148,7 +148,7 @@
The number of intersections can be limited with this parameter, to reduce the processing time.
</member>
<member name="shape" type="Shape2D" setter="set_shape" getter="get_shape">
- Any [Shape2D] derived shape used for collision queries.
+ The [Shape2D]-derived shape to be used for collision queries.
</member>
<member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2(0, 50)">
The shape's destination point, relative to this node's [code]position[/code].
diff --git a/doc/classes/ShapeCast3D.xml b/doc/classes/ShapeCast3D.xml
new file mode 100644
index 0000000000..085bc9acd1
--- /dev/null
+++ b/doc/classes/ShapeCast3D.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="ShapeCast3D" inherits="Node3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Node for physics collision sweep and immediate overlap queries. Similar to the [RayCast3D] node.
+ </brief_description>
+ <description>
+ Shape casting allows to detect collision objects by sweeping the [member shape] along the cast direction determined by [member target_position] (useful for things like beam weapons).
+ Immediate collision overlaps can be done with the [member target_position] set to [code]Vector3(0, 0, 0)[/code] and by calling [method force_shapecast_update] within the same [b]physics_frame[/b]. This also helps to overcome some limitations of [Area3D] when used as a continuous detection area, often requiring waiting a couple of frames before collision information is available to [Area3D] nodes, and when using the signals creates unnecessary complexity.
+ The node can detect multiple collision objects, but it's usually used to detect the first collision.
+ [b]Note:[/b] Shape casting is more computationally expensive compared to ray casting.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_exception">
+ <return type="void" />
+ <argument index="0" name="node" type="Object" />
+ <description>
+ Adds a collision exception so the shape does not report collisions with the specified [CollisionObject3D] node.
+ </description>
+ </method>
+ <method name="add_exception_rid">
+ <return type="void" />
+ <argument index="0" name="rid" type="RID" />
+ <description>
+ Adds a collision exception so the shape does not report collisions with the specified [RID].
+ </description>
+ </method>
+ <method name="clear_exceptions">
+ <return type="void" />
+ <description>
+ Removes all collision exceptions for this [ShapeCast3D].
+ </description>
+ </method>
+ <method name="force_shapecast_update">
+ <return type="void" />
+ <description>
+ Updates the collision information for the shape. Use this method to update the collision information immediately instead of waiting for the next [code]_physics_process[/code] call, for example if the shape or its parent has changed state.
+ [b]Note:[/b] [code]enabled == true[/code] is not required for this to work.
+ </description>
+ </method>
+ <method name="get_closest_collision_safe_fraction" qualifiers="const">
+ <return type="float" />
+ <description>
+ The fraction from the [ShapeCast3D]'s origin to its [member target_position] (between 0 and 1) of how far the shape can move without triggering a collision.
+ </description>
+ </method>
+ <method name="get_closest_collision_unsafe_fraction" qualifiers="const">
+ <return type="float" />
+ <description>
+ The fraction from the [ShapeCast3D]'s origin to its [member target_position] (between 0 and 1) of how far the shape must move to trigger a collision.
+ </description>
+ </method>
+ <method name="get_collider" qualifiers="const">
+ <return type="Object" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ Returns the collided [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
+ </description>
+ </method>
+ <method name="get_collider_shape" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ Returns the shape ID of the colliding shape of one of the multiple collisions at [code]index[/code], or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
+ </description>
+ </method>
+ <method name="get_collision_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ The number of collisions detected at the point of impact. Use this to iterate over multiple collisions as provided by [method get_collider], [method get_collider_shape], [method get_collision_point], and [method get_collision_normal] methods.
+ </description>
+ </method>
+ <method name="get_collision_mask_value" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="layer_number" type="int" />
+ <description>
+ Returns whether or not the specified layer of the [member collision_mask] is enabled, given a [code]layer_number[/code] between 1 and 32.
+ </description>
+ </method>
+ <method name="get_collision_normal" qualifiers="const">
+ <return type="Vector3" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ Returns the normal of one of the multiple collisions at [code]index[/code] of the intersecting object.
+ </description>
+ </method>
+ <method name="get_collision_point" qualifiers="const">
+ <return type="Vector3" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ Returns the collision point of one of the multiple collisions at [code]index[/code] where the shape intersects the colliding object.
+ [b]Note:[/b] this point is in the [b]global[/b] coordinate system.
+ </description>
+ </method>
+ <method name="is_colliding" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns whether any object is intersecting with the shape's vector (considering the vector length).
+ </description>
+ </method>
+ <method name="remove_exception">
+ <return type="void" />
+ <argument index="0" name="node" type="Object" />
+ <description>
+ Removes a collision exception so the shape does report collisions with the specified [CollisionObject3D] node.
+ </description>
+ </method>
+ <method name="remove_exception_rid">
+ <return type="void" />
+ <argument index="0" name="rid" type="RID" />
+ <description>
+ Removes a collision exception so the shape does report collisions with the specified [RID].
+ </description>
+ </method>
+ <method name="resource_changed">
+ <return type="void" />
+ <argument index="0" name="resource" type="Resource" />
+ <description>
+ This method is used internally to update the debug gizmo in the editor. Any code placed in this function will be called whenever the [member shape] resource is modified.
+ </description>
+ </method>
+ <method name="set_collision_mask_value">
+ <return type="void" />
+ <argument index="0" name="layer_number" type="int" />
+ <argument index="1" name="value" type="bool" />
+ <description>
+ Based on [code]value[/code], enables or disables the specified layer in the [member collision_mask], given a [code]layer_number[/code] between 1 and 32.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false">
+ If [code]true[/code], collision with [Area3D]s will be reported.
+ </member>
+ <member name="collide_with_bodies" type="bool" setter="set_collide_with_bodies" getter="is_collide_with_bodies_enabled" default="true">
+ If [code]true[/code], collision with [PhysicsBody3D]s will be reported.
+ </member>
+ <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1">
+ The shape's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
+ </member>
+ <member name="collision_result" type="Array" setter="" getter="_get_collision_result" default="[]">
+ Returns the complete collision information from the collision sweep. The data returned is the same as in the [method PhysicsDirectSpaceState3D.get_rest_info] method.
+ </member>
+ <member name="debug_shape_custom_color" type="Color" setter="set_debug_shape_custom_color" getter="get_debug_shape_custom_color" default="Color(0, 0, 0, 1)">
+ The custom color to use to draw the shape in the editor and at run-time if [b]Visible Collision Shapes[/b] is enabled in the [b]Debug[/b] menu. This color will be highlighted at run-time if the [ShapeCast3D] is colliding with something.
+ If set to [code]Color(0.0, 0.0, 0.0)[/code] (by default), the color set in [member ProjectSettings.debug/shapes/collision/shape_color] is used.
+ </member>
+ <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
+ If [code]true[/code], collisions will be reported.
+ </member>
+ <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true">
+ If [code]true[/code], the parent node will be excluded from collision detection.
+ </member>
+ <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.0">
+ The collision margin for the shape. A larger margin helps detecting collisions more consistently, at the cost of precision.
+ </member>
+ <member name="max_results" type="int" setter="set_max_results" getter="get_max_results" default="32">
+ The number of intersections can be limited with this parameter, to reduce the processing time.
+ </member>
+ <member name="shape" type="Shape3D" setter="set_shape" getter="get_shape">
+ The [Shape3D]-derived shape to be used for collision queries.
+ </member>
+ <member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3(0, -1, 0)">
+ The shape's destination point, relative to this node's [code]position[/code].
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml
index f271220989..6295724aa2 100644
--- a/doc/classes/Skeleton3D.xml
+++ b/doc/classes/Skeleton3D.xml
@@ -392,6 +392,10 @@
<members>
<member name="animate_physical_bones" type="bool" setter="set_animate_physical_bones" getter="get_animate_physical_bones" default="true">
</member>
+ <member name="motion_scale" type="float" setter="set_motion_scale" getter="get_motion_scale" default="1.0">
+ Multiplies the position 3D track animation.
+ [b]Note:[/b] Unless this value is [code]1.0[/code], the key value in animation will not match the actual position value.
+ </member>
<member name="show_rest_only" type="bool" setter="set_show_rest_only" getter="is_show_rest_only" default="false">
</member>
</members>
diff --git a/doc/classes/SkeletonProfile.xml b/doc/classes/SkeletonProfile.xml
new file mode 100644
index 0000000000..5c2d0eefb4
--- /dev/null
+++ b/doc/classes/SkeletonProfile.xml
@@ -0,0 +1,193 @@
+<?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="find_bone" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="bone_name" type="StringName" />
+ <description>
+ Returns the bone index that matches [code]bone_name[/code] as its name.
+ </description>
+ </method>
+ <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_bone_parent" qualifiers="const">
+ <return type="StringName" />
+ <argument index="0" name="bone_idx" type="int" />
+ <description>
+ Returns the name of the bone which is the parent to the bone at [code]bone_idx[/code]. The result is empty if the bone has no parent.
+ </description>
+ </method>
+ <method name="get_bone_tail" qualifiers="const">
+ <return type="StringName" />
+ <argument index="0" name="bone_idx" type="int" />
+ <description>
+ Returns the name of the bone which is the tail of the bone at [code]bone_idx[/code].
+ </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_reference_pose" qualifiers="const">
+ <return type="Transform3D" />
+ <argument index="0" name="bone_idx" type="int" />
+ <description>
+ Returns the reference pose transform for bone [code]bone_idx[/code].
+ </description>
+ </method>
+ <method name="get_tail_direction" qualifiers="const">
+ <return type="int" enum="SkeletonProfile.TailDirection" />
+ <argument index="0" name="bone_idx" type="int" />
+ <description>
+ Returns the tail direction of the bone at [code]bone_idx[/code].
+ </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_bone_parent">
+ <return type="void" />
+ <argument index="0" name="bone_idx" type="int" />
+ <argument index="1" name="bone_parent" type="StringName" />
+ <description>
+ Sets the bone with name [code]bone_parent[/code] as the parent of the bone at [code]bone_idx[/code]. If an empty string is passed, then the bone has no parent.
+ </description>
+ </method>
+ <method name="set_bone_tail">
+ <return type="void" />
+ <argument index="0" name="bone_idx" type="int" />
+ <argument index="1" name="bone_tail" type="StringName" />
+ <description>
+ Sets the bone with name [code]bone_tail[/code] as the tail of the bone at [code]bone_idx[/code].
+ </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_reference_pose">
+ <return type="void" />
+ <argument index="0" name="bone_idx" type="int" />
+ <argument index="1" name="bone_name" type="Transform3D" />
+ <description>
+ Sets the reference pose transform for bone [code]bone_idx[/code].
+ </description>
+ </method>
+ <method name="set_tail_direction">
+ <return type="void" />
+ <argument index="0" name="bone_idx" type="int" />
+ <argument index="1" name="tail_direction" type="int" enum="SkeletonProfile.TailDirection" />
+ <description>
+ Sets the tail direction of the bone at [code]bone_idx[/code].
+ [b]Note:[/b] This only specifies the method of calculation. The actual coordinates required should be stored in an external skeleton, so the calculation itself needs to be done externally.
+ </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>
+ <member name="root_bone" type="StringName" setter="set_root_bone" getter="get_root_bone" default="&amp;&quot;&quot;">
+ A name of bone that will be used as the root bone in [AnimationTree].
+ [b]Note:[/b] In most cases, it is the bone of the parent of the hips that exists at the world origin in the humanoid model.
+ </member>
+ <member name="scale_base_bone" type="StringName" setter="set_scale_base_bone" getter="get_scale_base_bone" default="&amp;&quot;&quot;">
+ A name of bone which height will be used as the coefficient for normalization.
+ [b]Note:[/b] In most cases, it is hips in the humanoid model.
+ </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>
+ <constants>
+ <constant name="TAIL_DIRECTION_AVERAGE_CHILDREN" value="0" enum="TailDirection">
+ Direction to the average coordinates of bone children.
+ </constant>
+ <constant name="TAIL_DIRECTION_SPECIFIC_CHILD" value="1" enum="TailDirection">
+ Direction to the coordinates of specified bone child.
+ </constant>
+ <constant name="TAIL_DIRECTION_END" value="2" enum="TailDirection">
+ Direction is not calculated.
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/SkeletonProfileHumanoid.xml b/doc/classes/SkeletonProfileHumanoid.xml
new file mode 100644
index 0000000000..11f0521718
--- /dev/null
+++ b/doc/classes/SkeletonProfileHumanoid.xml
@@ -0,0 +1,16 @@
+<?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" />
+ <member name="root_bone" type="StringName" setter="set_root_bone" getter="get_root_bone" overrides="SkeletonProfile" default="&amp;&quot;Root&quot;" />
+ <member name="scale_base_bone" type="StringName" setter="set_scale_base_bone" getter="get_scale_base_bone" overrides="SkeletonProfile" default="&amp;&quot;Hips&quot;" />
+ </members>
+</class>
diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml
index e84f9c38ff..8df039794a 100644
--- a/doc/classes/SpinBox.xml
+++ b/doc/classes/SpinBox.xml
@@ -47,6 +47,9 @@
<members>
<member name="alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="0">
</member>
+ <member name="custom_arrow_step" type="float" setter="set_custom_arrow_step" getter="get_custom_arrow_step" default="0.0">
+ If not [code]0[/code], [code]value[/code] will always be rounded to a multiple of [code]custom_arrow_step[/code] when interacting with the arrow buttons of the [SpinBox].
+ </member>
<member name="editable" type="bool" setter="set_editable" getter="is_editable" default="true">
If [code]true[/code], the [SpinBox] will be editable. Otherwise, it will be read only.
</member>
diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml
index 41b02b6dc9..bc381578d9 100644
--- a/doc/classes/SpriteBase3D.xml
+++ b/doc/classes/SpriteBase3D.xml
@@ -77,7 +77,7 @@
</member>
<member name="render_priority" type="int" setter="set_render_priority" getter="get_render_priority" default="0">
Sets the render priority for the sprite. Higher priority objects will be sorted in front of lower priority objects.
- [b]Node:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value).
+ [b]Note:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value).
[b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority).
</member>
<member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
diff --git a/doc/classes/SpriteFrames.xml b/doc/classes/SpriteFrames.xml
index b0d1e1efcf..0d423630d4 100644
--- a/doc/classes/SpriteFrames.xml
+++ b/doc/classes/SpriteFrames.xml
@@ -130,9 +130,4 @@
</description>
</method>
</methods>
- <members>
- <member name="frames" type="Array" setter="_set_frames" getter="_get_frames">
- Compatibility property, always equals to an empty array.
- </member>
- </members>
</class>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index f4d453700c..35ad5f03ab 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">
@@ -625,6 +640,7 @@
<description>
Splits the string by a [code]delimiter[/code] string and returns an array of the substrings, starting from right.
The splits in the returned array are sorted in the same order as the original string, from left to right.
+ If [code]allow_empty[/code] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position.
If [code]maxsplit[/code] is specified, it defines the number of splits to do from the right up to [code]maxsplit[/code]. The default value of 0 means that all items are split, thus giving the same result as [method split].
Example:
[codeblocks]
@@ -699,6 +715,7 @@
<argument index="2" name="maxsplit" type="int" default="0" />
<description>
Splits the string by a [code]delimiter[/code] string and returns an array of the substrings. The [code]delimiter[/code] can be of any length.
+ If [code]allow_empty[/code] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position.
If [code]maxsplit[/code] is specified, it defines the number of splits to do from the left up to [code]maxsplit[/code]. The default value of [code]0[/code] means that all items are split.
If you need only one element from the array at a specific index, [method get_slice] is a more performant option.
Example:
@@ -727,6 +744,7 @@
<description>
Splits the string in floats by using a delimiter string and returns an array of the substrings.
For example, [code]"1,2.5,3"[/code] will return [code][1,2.5,3][/code] if split by [code]","[/code].
+ If [code]allow_empty[/code] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position.
</description>
</method>
<method name="strip_edges" 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/SystemFont.xml b/doc/classes/SystemFont.xml
new file mode 100644
index 0000000000..b1b78f1705
--- /dev/null
+++ b/doc/classes/SystemFont.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SystemFont" inherits="Font" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Font loaded from a system font.
+ [b]Note:[/b] This class is implemented on iOS, Linux, macOS and Windows, on other platforms it will fallback to default theme font.
+ </brief_description>
+ <description>
+ [SystemFont] loads a font from a system font with the first matching name from [member font_names].
+ It will attempt to match font style, but it's not guaranteed.
+ The returned font might be part of a font collection or be a variable font with OpenType "weight" and/or "italic" features set.
+ You can create [FontVariation] of the system font for fine control over its features.
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true">
+ If set to [code]true[/code], font 8-bit anitialiased glyph rendering is supported and enabled.
+ </member>
+ <member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
+ Array of fallback [Font]s.
+ </member>
+ <member name="font_names" type="PackedStringArray" setter="set_font_names" getter="get_font_names" default="PackedStringArray()">
+ Array of font family names to search, first matching font found is used.
+ </member>
+ <member name="font_style" type="int" setter="set_font_style" getter="get_font_style" enum="TextServer.FontStyle" default="0">
+ Font style flags, see [enum TextServer.FontStyle].
+ </member>
+ <member name="force_autohinter" type="bool" setter="set_force_autohinter" getter="is_force_autohinter" default="false">
+ If set to [code]true[/code], auto-hinting is supported and preferred over font built-in hinting.
+ </member>
+ <member name="generate_mipmaps" type="bool" setter="set_generate_mipmaps" getter="get_generate_mipmaps" default="false">
+ If set to [code]true[/code], generate mipmaps for the font textures.
+ </member>
+ <member name="hinting" type="int" setter="set_hinting" getter="get_hinting" enum="TextServer.Hinting" default="1">
+ Font hinting mode.
+ </member>
+ <member name="oversampling" type="float" setter="set_oversampling" getter="get_oversampling" default="0.0">
+ Font oversampling factor, if set to [code]0.0[/code] global oversampling factor is used instead.
+ </member>
+ <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>
+ </members>
+</class>
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..601650db2e 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>
@@ -149,8 +148,8 @@
<member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0">
Text writing direction.
</member>
- <member name="flags" type="int" setter="set_flags" getter="get_flags" default="3">
- Line Alignment rules. For more info see [TextServer].
+ <member name="flags" type="int" setter="set_flags" getter="get_flags" enum="TextServer.JustificationFlag" default="3">
+ Line alignment rules. For more info see [TextServer].
</member>
<member name="orientation" type="int" setter="set_orientation" getter="get_orientation" enum="TextServer.Orientation" default="0">
Text orientation.
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..c733d8fcee 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>
@@ -277,14 +263,17 @@
<member name="alignment" type="int" setter="set_alignment" getter="get_alignment" enum="HorizontalAlignment" default="0">
Paragraph horizontal alignment.
</member>
+ <member name="break_flags" type="int" setter="set_break_flags" getter="get_break_flags" enum="TextServer.LineBreakFlag" default="3">
+ Line breaking rules. For more info see [TextServer].
+ </member>
<member name="custom_punctuation" type="String" setter="set_custom_punctuation" getter="get_custom_punctuation" default="&quot;&quot;">
Custom punctuation character list, used for word breaking. If set to empty string, server defaults are used.
</member>
<member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0">
Text writing direction.
</member>
- <member name="flags" type="int" setter="set_flags" getter="get_flags" default="99">
- Line breaking and alignment rules. For more info see [TextServer].
+ <member name="justification_flags" type="int" setter="set_justification_flags" getter="get_justification_flags" enum="TextServer.JustificationFlag" default="3">
+ Line alignment rules. For more info see [TextServer].
</member>
<member name="max_lines_visible" type="int" setter="set_max_lines_visible" getter="get_max_lines_visible" default="-1">
Limits the lines of text shown.
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index ca1aec19ea..b54536f897 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -355,17 +355,8 @@
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" />
+ <return type="int" enum="TextServer.FontStyle" />
<argument index="0" name="font_rid" type="RID" />
<description>
Returns font style flags, see [enum FontStyle].
@@ -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,20 +783,10 @@
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" />
- <argument index="1" name="style" type="int" />
+ <argument index="1" name="style" type="int" enum="TextServer.FontStyle" />
<description>
Sets the font style flags, see [enum FontStyle].
</description>
@@ -956,6 +937,16 @@
Returns [code]true[/code] if the server supports a feature.
</description>
</method>
+ <method name="is_confusable" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="string" type="String" />
+ <argument index="1" name="dict" type="PackedStringArray" />
+ <description>
+ Returns index of the first string in [code]dict[/dict] which is visually confusable with the [code]string[/string], or [code]-1[/code] if none is found.
+ [b]Note:[/b] This method doesn't detect invisible characters, for spoof detection use it in combination with [method spoof_check].
+ [b]Note:[/b] Always returns [code]-1[/code] if the server does not support the [constant FEATURE_UNICODE_SECURITY] feature.
+ </description>
+ </method>
<method name="is_locale_right_to_left" qualifiers="const">
<return type="bool" />
<argument index="0" name="locale" type="String" />
@@ -963,6 +954,21 @@
Returns [code]true[/code] if locale is right-to-left.
</description>
</method>
+ <method name="is_valid_identifier" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="string" type="String" />
+ <description>
+ Returns [code]true[/code] is [code]string[/code] is a valid identifier.
+ If the text server supports the [constant FEATURE_UNICODE_IDENTIFIERS] feature, a valid identifier must:
+ - Conform to normalization form C.
+ - Begin with a Unicode character of class XID_Start or [code]"_"[/code].
+ - May contain Unicode characters of class XID_Continue in the other positions.
+ - Use UAX #31 recommended scripts only (mixed scripts are allowed).
+ If the [constant FEATURE_UNICODE_IDENTIFIERS] feature is not supported, a valid identifier must:
+ - Begin with a Unicode character of class XID_Start or [code]"_"[/code].
+ - May contain Unicode characters of class XID_Continue in the other positions.
+ </description>
+ </method>
<method name="load_support_data">
<return type="bool" />
<argument index="0" name="filename" type="String" />
@@ -1096,7 +1102,7 @@
<return type="float" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="width" type="float" />
- <argument index="2" name="jst_flags" type="int" default="3" />
+ <argument index="2" name="jst_flags" type="int" enum="TextServer.JustificationFlag" default="3" />
<description>
Adjusts text with to fit to specified width, returns new text width.
</description>
@@ -1203,7 +1209,7 @@
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="width" type="float" />
<argument index="2" name="start" type="int" default="0" />
- <argument index="3" name="break_flags" type="int" default="96" />
+ <argument index="3" name="break_flags" type="int" enum="TextServer.LineBreakFlag" default="3" />
<description>
Breaks text to the lines and returns character ranges for each line.
</description>
@@ -1214,7 +1220,7 @@
<argument index="1" name="width" type="PackedFloat32Array" />
<argument index="2" name="start" type="int" default="0" />
<argument index="3" name="once" type="bool" default="true" />
- <argument index="4" name="break_flags" type="int" default="96" />
+ <argument index="4" name="break_flags" type="int" enum="TextServer.LineBreakFlag" default="3" />
<description>
Breaks text to the lines and columns. Returns character ranges for each segment.
</description>
@@ -1286,6 +1292,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" />
@@ -1317,7 +1331,7 @@
<method name="shaped_text_get_word_breaks" qualifiers="const">
<return type="PackedInt32Array" />
<argument index="0" name="shaped" type="RID" />
- <argument index="1" name="grapheme_flags" type="int" default="264" />
+ <argument index="1" name="grapheme_flags" type="int" enum="TextServer.GraphemeFlag" default="264" />
<description>
Breaks text into words and returns array of character ranges. Use [code]grapheme_flags[/code] to set what characters are used for breaking (see [enum GraphemeFlag]).
</description>
@@ -1357,7 +1371,7 @@
<return type="void" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="width" type="float" default="0" />
- <argument index="2" name="overrun_trim_flags" type="int" default="0" />
+ <argument index="2" name="overrun_trim_flags" type="int" enum="TextServer.TextOverrunFlag" default="0" />
<description>
Trims text if it exceeds the given width.
</description>
@@ -1431,6 +1445,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" />
@@ -1463,6 +1486,14 @@
Aligns shaped text to the given tab-stops.
</description>
</method>
+ <method name="spoof_check" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="string" type="String" />
+ <description>
+ Returns [code]true[/code] if [code]string[/code] is likely to be an attempt at confusing the reader.
+ [b]Note:[/b] Always returns [code]false[/code] if the server does not support the [constant FEATURE_UNICODE_SECURITY] feature.
+ </description>
+ </method>
<method name="string_get_word_breaks" qualifiers="const">
<return type="PackedInt32Array" />
<argument index="0" name="string" type="String" />
@@ -1524,22 +1555,22 @@
Left to right text is written vertically from top to bottom.
Right to left text is written vertically from bottom to top.
</constant>
- <constant name="JUSTIFICATION_NONE" value="0" enum="JustificationFlag">
+ <constant name="JUSTIFICATION_NONE" value="0" enum="JustificationFlag" is_bitfield="true">
Do not justify text.
</constant>
- <constant name="JUSTIFICATION_KASHIDA" value="1" enum="JustificationFlag">
+ <constant name="JUSTIFICATION_KASHIDA" value="1" enum="JustificationFlag" is_bitfield="true">
Justify text by adding and removing kashidas.
</constant>
- <constant name="JUSTIFICATION_WORD_BOUND" value="2" enum="JustificationFlag">
+ <constant name="JUSTIFICATION_WORD_BOUND" value="2" enum="JustificationFlag" is_bitfield="true">
Justify text by changing width of the spaces between the words.
</constant>
- <constant name="JUSTIFICATION_TRIM_EDGE_SPACES" value="4" enum="JustificationFlag">
+ <constant name="JUSTIFICATION_TRIM_EDGE_SPACES" value="4" enum="JustificationFlag" is_bitfield="true">
Remove trailing and leading spaces from the justified text.
</constant>
- <constant name="JUSTIFICATION_AFTER_LAST_TAB" value="8" enum="JustificationFlag">
+ <constant name="JUSTIFICATION_AFTER_LAST_TAB" value="8" enum="JustificationFlag" is_bitfield="true">
Only apply justification to the part of the text after the last tab.
</constant>
- <constant name="JUSTIFICATION_CONSTRAIN_ELLIPSIS" value="16" enum="JustificationFlag">
+ <constant name="JUSTIFICATION_CONSTRAIN_ELLIPSIS" value="16" enum="JustificationFlag" is_bitfield="true">
Apply justification to the trimmed line with ellipsis.
</constant>
<constant name="AUTOWRAP_OFF" value="0" enum="AutowrapMode">
@@ -1554,20 +1585,19 @@
<constant name="AUTOWRAP_WORD_SMART" value="3" enum="AutowrapMode">
Behaves similarly to [constant AUTOWRAP_WORD], but force-breaks a word if that single word does not fit in one line.
</constant>
- <constant name="BREAK_NONE" value="0" enum="LineBreakFlag">
+ <constant name="BREAK_NONE" value="0" enum="LineBreakFlag" is_bitfield="true">
Do not break the line.
</constant>
- <constant name="BREAK_MANDATORY" value="32" enum="LineBreakFlag">
+ <constant name="BREAK_MANDATORY" value="1" enum="LineBreakFlag" is_bitfield="true">
Break the line at the line mandatory break characters (e.g. [code]"\n"[/code]).
</constant>
- <constant name="BREAK_WORD_BOUND" value="64" enum="LineBreakFlag">
+ <constant name="BREAK_WORD_BOUND" value="2" enum="LineBreakFlag" is_bitfield="true">
Break the line between the words.
</constant>
- <constant name="BREAK_GRAPHEME_BOUND" value="128" enum="LineBreakFlag">
+ <constant name="BREAK_GRAPHEME_BOUND" value="4" enum="LineBreakFlag" is_bitfield="true">
Break the line between any unconnected graphemes.
</constant>
- <constant name="BREAK_WORD_BOUND_ADAPTIVE" value="320" enum="LineBreakFlag">
- Break the line between the words, or any unconnected graphemes if line is too short to fit the whole word.
+ <constant name="BREAK_ADAPTIVE" value="8" enum="LineBreakFlag" is_bitfield="true">
</constant>
<constant name="VC_CHARS_BEFORE_SHAPING" value="0" enum="VisibleCharactersBehavior">
Trims text before the shaping. e.g, increasing [member Label.visible_characters] or [member RichTextLabel.visible_characters] value is visually identical to typing the text.
@@ -1599,56 +1629,59 @@
<constant name="OVERRUN_TRIM_WORD_ELLIPSIS" value="4" enum="OverrunBehavior">
Trims the text per word and adds an ellipsis to indicate that parts are hidden.
</constant>
- <constant name="OVERRUN_NO_TRIM" value="0" enum="TextOverrunFlag">
+ <constant name="OVERRUN_NO_TRIM" value="0" enum="TextOverrunFlag" is_bitfield="true">
No trimming is performed.
</constant>
- <constant name="OVERRUN_TRIM" value="1" enum="TextOverrunFlag">
+ <constant name="OVERRUN_TRIM" value="1" enum="TextOverrunFlag" is_bitfield="true">
Trims the text when it exceeds the given width.
</constant>
- <constant name="OVERRUN_TRIM_WORD_ONLY" value="2" enum="TextOverrunFlag">
+ <constant name="OVERRUN_TRIM_WORD_ONLY" value="2" enum="TextOverrunFlag" is_bitfield="true">
Trims the text per word instead of per grapheme.
</constant>
- <constant name="OVERRUN_ADD_ELLIPSIS" value="4" enum="TextOverrunFlag">
+ <constant name="OVERRUN_ADD_ELLIPSIS" value="4" enum="TextOverrunFlag" is_bitfield="true">
Determines whether an ellipsis should be added at the end of the text.
</constant>
- <constant name="OVERRUN_ENFORCE_ELLIPSIS" value="8" enum="TextOverrunFlag">
+ <constant name="OVERRUN_ENFORCE_ELLIPSIS" value="8" enum="TextOverrunFlag" is_bitfield="true">
Determines whether the ellipsis at the end of the text is enforced and may not be hidden.
</constant>
- <constant name="OVERRUN_JUSTIFICATION_AWARE" value="16" enum="TextOverrunFlag">
+ <constant name="OVERRUN_JUSTIFICATION_AWARE" value="16" enum="TextOverrunFlag" is_bitfield="true">
</constant>
- <constant name="GRAPHEME_IS_VALID" value="1" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_VALID" value="1" enum="GraphemeFlag" is_bitfield="true">
Grapheme is supported by the font, and can be drawn.
</constant>
- <constant name="GRAPHEME_IS_RTL" value="2" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_RTL" value="2" enum="GraphemeFlag" is_bitfield="true">
Grapheme is part of right-to-left or bottom-to-top run.
</constant>
- <constant name="GRAPHEME_IS_VIRTUAL" value="4" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_VIRTUAL" value="4" enum="GraphemeFlag" is_bitfield="true">
Grapheme is not part of source text, it was added by justification process.
</constant>
- <constant name="GRAPHEME_IS_SPACE" value="8" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_SPACE" value="8" enum="GraphemeFlag" is_bitfield="true">
Grapheme is whitespace.
</constant>
- <constant name="GRAPHEME_IS_BREAK_HARD" value="16" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_BREAK_HARD" value="16" enum="GraphemeFlag" is_bitfield="true">
Grapheme is mandatory break point (e.g. [code]"\n"[/code]).
</constant>
- <constant name="GRAPHEME_IS_BREAK_SOFT" value="32" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_BREAK_SOFT" value="32" enum="GraphemeFlag" is_bitfield="true">
Grapheme is optional break point (e.g. space).
</constant>
- <constant name="GRAPHEME_IS_TAB" value="64" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_TAB" value="64" enum="GraphemeFlag" is_bitfield="true">
Grapheme is the tabulation character.
</constant>
- <constant name="GRAPHEME_IS_ELONGATION" value="128" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_ELONGATION" value="128" enum="GraphemeFlag" is_bitfield="true">
Grapheme is kashida.
</constant>
- <constant name="GRAPHEME_IS_PUNCTUATION" value="256" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_PUNCTUATION" value="256" enum="GraphemeFlag" is_bitfield="true">
Grapheme is punctuation character.
</constant>
- <constant name="GRAPHEME_IS_UNDERSCORE" value="512" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_UNDERSCORE" value="512" enum="GraphemeFlag" is_bitfield="true">
Grapheme is underscore character.
</constant>
- <constant name="GRAPHEME_IS_CONNECTED" value="1024" enum="GraphemeFlag">
+ <constant name="GRAPHEME_IS_CONNECTED" value="1024" enum="GraphemeFlag" is_bitfield="true">
Grapheme is connected to the previous grapheme. Breaking line before this grapheme is not safe.
</constant>
+ <constant name="GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL" value="2048" enum="GraphemeFlag" is_bitfield="true">
+ It is safe to insert a U+0640 before this grapheme for elongation.
+ </constant>
<constant name="HINTING_NONE" value="0" enum="Hinting">
Disables font hinting (smoother but less crisp).
</constant>
@@ -1716,7 +1749,13 @@
TextServer supports locale dependent and context sensitive case conversion.
</constant>
<constant name="FEATURE_USE_SUPPORT_DATA" value="4096" enum="Feature">
- TextServer require external data file for some features.
+ TextServer require external data file for some features, see [method load_support_data].
+ </constant>
+ <constant name="FEATURE_UNICODE_IDENTIFIERS" value="8192" enum="Feature">
+ TextServer supports UAX #31 identifier validation, see [method is_valid_identifier].
+ </constant>
+ <constant name="FEATURE_UNICODE_SECURITY" value="16384" enum="Feature">
+ TextServer supports [url=https://unicode.org/reports/tr36/]Unicode Technical Report #36[/url] and [url=https://unicode.org/reports/tr39/]Unicode Technical Standard #39[/url] based spoof detection features.
</constant>
<constant name="CONTOUR_CURVE_TAG_ON" value="1" enum="ContourPointTag">
Contour point is on the curve.
@@ -1739,13 +1778,15 @@
<constant name="SPACING_BOTTOM" value="3" enum="SpacingType">
Spacing at the bottom of the line.
</constant>
- <constant name="FONT_BOLD" value="1" enum="FontStyle">
+ <constant name="SPACING_MAX" value="4" enum="SpacingType">
+ </constant>
+ <constant name="FONT_BOLD" value="1" enum="FontStyle" is_bitfield="true">
Font is bold.
</constant>
- <constant name="FONT_ITALIC" value="2" enum="FontStyle">
+ <constant name="FONT_ITALIC" value="2" enum="FontStyle" is_bitfield="true">
Font is italic or oblique.
</constant>
- <constant name="FONT_FIXED_WIDTH" value="4" enum="FontStyle">
+ <constant name="FONT_FIXED_WIDTH" value="4" enum="FontStyle" is_bitfield="true">
Font have fixed-width characters.
</constant>
<constant name="STRUCTURED_TEXT_DEFAULT" value="0" enum="StructuredTextParser">
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
index b3be858ca1..c686a06e5e 100644
--- a/doc/classes/TextServerExtension.xml
+++ b/doc/classes/TextServerExtension.xml
@@ -345,17 +345,8 @@
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" />
+ <return type="int" enum="TextServer.FontStyle" />
<argument index="0" name="font_rid" type="RID" />
<description>
Returns font style flags, see [enum TextServer.FontStyle].
@@ -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,20 +779,10 @@
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" />
- <argument index="1" name="style" type="int" />
+ <argument index="1" name="style" type="int" enum="TextServer.FontStyle" />
<description>
Sets the font style flags, see [enum TextServer.FontStyle].
</description>
@@ -953,6 +934,14 @@
Returns [code]true[/code] if the server supports a feature.
</description>
</method>
+ <method name="is_confusable" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="string" type="String" />
+ <argument index="1" name="dict" type="PackedStringArray" />
+ <description>
+ Returns index of the first string in [code]dict[/dict] which is visually confusable with the [code]string[/string], or [code]-1[/code] if none is found.
+ </description>
+ </method>
<method name="is_locale_right_to_left" qualifiers="virtual const">
<return type="bool" />
<argument index="0" name="locale" type="String" />
@@ -960,6 +949,13 @@
Returns [code]true[/code] if locale is right-to-left.
</description>
</method>
+ <method name="is_valid_identifier" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="string" type="String" />
+ <description>
+ Returns [code]true[/code] is [code]string[/code] is a valid identifier.
+ </description>
+ </method>
<method name="load_support_data" qualifiers="virtual">
<return type="bool" />
<argument index="0" name="filename" type="String" />
@@ -1093,7 +1089,7 @@
<return type="float" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="width" type="float" />
- <argument index="2" name="jst_flags" type="int" />
+ <argument index="2" name="jst_flags" type="int" enum="TextServer.JustificationFlag" />
<description>
Adjusts text with to fit to specified width, returns new text width.
</description>
@@ -1202,7 +1198,7 @@
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="width" type="float" />
<argument index="2" name="start" type="int" />
- <argument index="3" name="break_flags" type="int" />
+ <argument index="3" name="break_flags" type="int" enum="TextServer.LineBreakFlag" />
<description>
Breaks text to the lines and returns character ranges for each line.
[b]Note:[/b] If this method is not implemented in the plugin, the default implementation will be used.
@@ -1214,7 +1210,7 @@
<argument index="1" name="width" type="PackedFloat32Array" />
<argument index="2" name="start" type="int" />
<argument index="3" name="once" type="bool" />
- <argument index="4" name="break_flags" type="int" />
+ <argument index="4" name="break_flags" type="int" enum="TextServer.LineBreakFlag" />
<description>
Breaks text to the lines and columns. Returns character ranges for each segment.
[b]Note:[/b] If this method is not implemented in the plugin, the default implementation will be used.
@@ -1288,6 +1284,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" />
@@ -1319,7 +1323,7 @@
<method name="shaped_text_get_word_breaks" qualifiers="virtual const">
<return type="PackedInt32Array" />
<argument index="0" name="shaped" type="RID" />
- <argument index="1" name="grapheme_flags" type="int" />
+ <argument index="1" name="grapheme_flags" type="int" enum="TextServer.GraphemeFlag" />
<description>
Breaks text into words and returns array of character ranges.
[b]Note:[/b] If this method is not implemented in the plugin, the default implementation will be used.
@@ -1363,7 +1367,7 @@
<return type="void" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="width" type="float" />
- <argument index="2" name="trim_flags" type="int" />
+ <argument index="2" name="trim_flags" type="int" enum="TextServer.TextOverrunFlag" />
<description>
Trims text if it exceeds the given width.
</description>
@@ -1436,6 +1440,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" />
@@ -1483,6 +1496,13 @@
[b]Note:[/b] This method is used by default line/word breaking methods, and its implementation might be omitted if custom line breaking in implemented.
</description>
</method>
+ <method name="spoof_check" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="string" type="String" />
+ <description>
+ Returns [code]true[/code] if [code]string[/code] is likely to be an attempt at confusing the reader.
+ </description>
+ </method>
<method name="string_get_word_breaks" qualifiers="virtual const">
<return type="PackedInt32Array" />
<argument index="0" name="string" type="String" />
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/TileSet.xml b/doc/classes/TileSet.xml
index 10ccad973f..180e868ef8 100644
--- a/doc/classes/TileSet.xml
+++ b/doc/classes/TileSet.xml
@@ -117,6 +117,27 @@
If the TileSet has no proxy for the given identifiers, returns an empty Array.
</description>
</method>
+ <method name="get_custom_data_layer_by_name" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="layer_name" type="String" />
+ <description>
+ Returns the index of the custom data layer identified by the given name.
+ </description>
+ </method>
+ <method name="get_custom_data_layer_name" qualifiers="const">
+ <return type="String" />
+ <argument index="0" name="layer_index" type="int" />
+ <description>
+ Returns the name of the custom data layer identified by the given index.
+ </description>
+ </method>
+ <method name="get_custom_data_layer_type" qualifiers="const">
+ <return type="int" enum="Variant.Type" />
+ <argument index="0" name="layer_index" type="int" />
+ <description>
+ Returns the type of the custom data layer identified by the given index.
+ </description>
+ </method>
<method name="get_custom_data_layers_count" qualifiers="const">
<return type="int" />
<description>
@@ -464,6 +485,22 @@
Proxied tiles can be automatically replaced in TileMap nodes using the editor.
</description>
</method>
+ <method name="set_custom_data_layer_name">
+ <return type="void" />
+ <argument index="0" name="layer_index" type="int" />
+ <argument index="1" name="layer_name" type="String" />
+ <description>
+ Sets the name of the custom data layer identified by the given index. Names are identifiers of the layer therefore if the name is already taken it will fail and raise an error.
+ </description>
+ </method>
+ <method name="set_custom_data_layer_type">
+ <return type="void" />
+ <argument index="0" name="layer_index" type="int" />
+ <argument index="1" name="layer_type" type="int" enum="Variant.Type" />
+ <description>
+ Sets the type of the custom data layer identified by the given index.
+ </description>
+ </method>
<method name="set_navigation_layer_layers">
<return type="void" />
<argument index="0" name="layer_index" type="int" />
@@ -591,7 +628,7 @@
Tile coordinates layout where both axis stay consistent with their respective local horizontal and vertical axis.
</constant>
<constant name="TILE_LAYOUT_STACKED_OFFSET" value="1" enum="TileLayout">
- Same as [code]TILE_LAYOUT_STAKED[/code], but the first half-offset is negative instead of positive.
+ Same as [constant TILE_LAYOUT_STACKED], but the first half-offset is negative instead of positive.
</constant>
<constant name="TILE_LAYOUT_STAIRS_RIGHT" value="2" enum="TileLayout">
Tile coordinates layout where the horizontal axis stay horizontal, and the vertical one goes down-right.
diff --git a/doc/classes/TorusMesh.xml b/doc/classes/TorusMesh.xml
new file mode 100644
index 0000000000..6b83152793
--- /dev/null
+++ b/doc/classes/TorusMesh.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="TorusMesh" inherits="PrimitiveMesh" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Class representing a torus [PrimitiveMesh].
+ </brief_description>
+ <description>
+ Class representing a torus [PrimitiveMesh].
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="inner_radius" type="float" setter="set_inner_radius" getter="get_inner_radius" default="0.5">
+ The inner radius of the torus.
+ </member>
+ <member name="outer_radius" type="float" setter="set_outer_radius" getter="get_outer_radius" default="1.0">
+ The outer radius of the torus.
+ </member>
+ <member name="ring_segments" type="int" setter="set_ring_segments" getter="get_ring_segments" default="32">
+ The number of edges each ring of the torus is constructed of.
+ </member>
+ <member name="rings" type="int" setter="set_rings" getter="get_rings" default="64">
+ The number of slices the torus is constructed of.
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index e1f7ff21d0..9979a73527 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -141,14 +141,40 @@
<return type="Transform2D" />
<argument index="0" name="angle" type="float" />
<description>
- Returns a copy of the transform rotated by the given [code]angle[/code] (in radians), using matrix multiplication.
+ Returns a copy of the transform rotated by the given [code]angle[/code] (in radians).
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding rotation transform [code]R[/code] from the left, i.e., [code]R * X[/code].
+ This can be seen as transforming with respect to the global/parent frame.
+ </description>
+ </method>
+ <method name="rotated_local" qualifiers="const">
+ <return type="Transform2D" />
+ <argument index="0" name="angle" type="float" />
+ <description>
+ Returns a copy of the transform rotated by the given [code]angle[/code] (in radians).
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding rotation transform [code]R[/code] from the right, i.e., [code]X * R[/code].
+ This can be seen as transforming with respect to the local frame.
</description>
</method>
<method name="scaled" qualifiers="const">
<return type="Transform2D" />
<argument index="0" name="scale" type="Vector2" />
<description>
- Returns a copy of the transform scaled by the given [code]scale[/code] factor, using matrix multiplication.
+ Returns a copy of the transform scaled by the given [code]scale[/code] factor.
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding scaling transform [code]S[/code] from the left, i.e., [code]S * X[/code].
+ This can be seen as transforming with respect to the global/parent frame.
+ </description>
+ </method>
+ <method name="scaled_local" qualifiers="const">
+ <return type="Transform2D" />
+ <argument index="0" name="scale" type="Vector2" />
+ <description>
+ Returns a copy of the transform scaled by the given [code]scale[/code] factor.
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding scaling transform [code]S[/code] from the right, i.e., [code]X * S[/code].
+ This can be seen as transforming with respect to the local frame.
</description>
</method>
<method name="set_rotation">
@@ -177,8 +203,20 @@
<return type="Transform2D" />
<argument index="0" name="offset" type="Vector2" />
<description>
- Returns a copy of the transform translated by the given [code]offset[/code], relative to the transform's basis vectors.
- Unlike [method rotated] and [method scaled], this does not use matrix multiplication.
+ Returns a copy of the transform translated by the given [code]offset[/code].
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding translation transform [code]T[/code] from the left, i.e., [code]T * X[/code].
+ This can be seen as transforming with respect to the global/parent frame.
+ </description>
+ </method>
+ <method name="translated_local" qualifiers="const">
+ <return type="Transform2D" />
+ <argument index="0" name="offset" type="Vector2" />
+ <description>
+ Returns a copy of the transform translated by the given [code]offset[/code].
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding translation transform [code]T[/code] from the right, i.e., [code]X * T[/code].
+ This can be seen as transforming with respect to the local frame.
</description>
</method>
</methods>
diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml
index afd11b6c77..cefc74867c 100644
--- a/doc/classes/Transform3D.xml
+++ b/doc/classes/Transform3D.xml
@@ -39,6 +39,12 @@
</constructor>
<constructor name="Transform3D">
<return type="Transform3D" />
+ <argument index="0" name="from" type="Projection" />
+ <description>
+ </description>
+ </constructor>
+ <constructor name="Transform3D">
+ <return type="Transform3D" />
<argument index="0" name="x_axis" type="Vector3" />
<argument index="1" name="y_axis" type="Vector3" />
<argument index="2" name="z_axis" type="Vector3" />
@@ -96,17 +102,46 @@
<argument index="0" name="axis" type="Vector3" />
<argument index="1" name="angle" type="float" />
<description>
- Returns a copy of the transform rotated around the given [code]axis[/code] by the given [code]angle[/code] (in radians), using matrix multiplication. The [code]axis[/code] must be a normalized vector.
+ Returns a copy of the transform rotated around the given [code]axis[/code] by the given [code]angle[/code] (in radians).
+ The [code]axis[/code] must be a normalized vector.
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding rotation transform [code]R[/code] from the left, i.e., [code]R * X[/code].
+ This can be seen as transforming with respect to the global/parent frame.
+ </description>
+ </method>
+ <method name="rotated_local" qualifiers="const">
+ <return type="Transform3D" />
+ <argument index="0" name="axis" type="Vector3" />
+ <argument index="1" name="angle" type="float" />
+ <description>
+ Returns a copy of the transform rotated around the given [code]axis[/code] by the given [code]angle[/code] (in radians).
+ The [code]axis[/code] must be a normalized vector.
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding rotation transform [code]R[/code] from the right, i.e., [code]X * R[/code].
+ This can be seen as transforming with respect to the local frame.
</description>
</method>
<method name="scaled" qualifiers="const">
<return type="Transform3D" />
<argument index="0" name="scale" type="Vector3" />
<description>
- Returns a copy of the transform with its basis and origin scaled by the given [code]scale[/code] factor, using matrix multiplication.
+ Returns a copy of the transform scaled by the given [code]scale[/code] factor.
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding scaling transform [code]S[/code] from the left, i.e., [code]S * X[/code].
+ This can be seen as transforming with respect to the global/parent frame.
</description>
</method>
- <method name="sphere_interpolate_with" qualifiers="const">
+ <method name="scaled_local" qualifiers="const">
+ <return type="Transform3D" />
+ <argument index="0" name="scale" type="Vector3" />
+ <description>
+ Returns a copy of the transform scaled by the given [code]scale[/code] factor.
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding scaling transform [code]S[/code] from the right, i.e., [code]X * S[/code].
+ This can be seen as transforming with respect to the local frame.
+ </description>
+ </method>
+ <method name="spherical_interpolate_with" qualifiers="const">
<return type="Transform3D" />
<argument index="0" name="xform" type="Transform3D" />
<argument index="1" name="weight" type="float" />
@@ -118,8 +153,20 @@
<return type="Transform3D" />
<argument index="0" name="offset" type="Vector3" />
<description>
- Returns a copy of the transform translated by the given [code]offset[/code], relative to the transform's basis vectors.
- Unlike [method rotated] and [method scaled], this does not use matrix multiplication.
+ Returns a copy of the transform translated by the given [code]offset[/code].
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding translation transform [code]T[/code] from the left, i.e., [code]T * X[/code].
+ This can be seen as transforming with respect to the global/parent frame.
+ </description>
+ </method>
+ <method name="translated_local" qualifiers="const">
+ <return type="Transform3D" />
+ <argument index="0" name="offset" type="Vector3" />
+ <description>
+ Returns a copy of the transform translated by the given [code]offset[/code].
+ This method is an optimized version of multiplying the given transform [code]X[/code]
+ with a corresponding translation transform [code]T[/code] from the right, i.e., [code]X * T[/code].
+ This can be seen as transforming with respect to the local frame.
</description>
</method>
</methods>
@@ -169,6 +216,13 @@
</description>
</operator>
<operator name="operator *">
+ <return type="Plane" />
+ <argument index="0" name="right" type="Plane" />
+ <description>
+ Transforms (multiplies) the [Plane] by the given [Transform3D] transformation matrix.
+ </description>
+ </operator>
+ <operator name="operator *">
<return type="Transform3D" />
<argument index="0" name="right" type="Transform3D" />
<description>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 8a30364ebe..f326948e9c 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">
@@ -485,7 +461,7 @@
<theme_item name="custom_button_font_highlight" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)">
Text [Color] for a [constant TreeItem.CELL_MODE_CUSTOM] mode cell when it's hovered.
</theme_item>
- <theme_item name="drop_position_color" data_type="color" type="Color" default="Color(1, 0.3, 0.2, 1)">
+ <theme_item name="drop_position_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
[Color] used to draw possible drop locations. See [enum DropModeFlags] constants for further description of drop locations.
</theme_item>
<theme_item name="font_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 1)">
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/Vector4.xml b/doc/classes/Vector4.xml
new file mode 100644
index 0000000000..ee9d97019e
--- /dev/null
+++ b/doc/classes/Vector4.xml
@@ -0,0 +1,377 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="Vector4" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Vector used for 4D math using floating point coordinates.
+ </brief_description>
+ <description>
+ 4-element structure that can be used to represent any quadruplet of numeric values.
+ It uses floating-point coordinates. See [Vector4i] for its integer counterpart.
+ [b]Note:[/b] In a boolean context, a Vector4 will evaluate to [code]false[/code] if it's equal to [code]Vector4(0, 0, 0, 0)[/code]. Otherwise, a Vector4 will always evaluate to [code]true[/code].
+ </description>
+ <tutorials>
+ </tutorials>
+ <constructors>
+ <constructor name="Vector4">
+ <return type="Vector4" />
+ <description>
+ Constructs a default-initialized [Vector4] with all components set to [code]0[/code].
+ </description>
+ </constructor>
+ <constructor name="Vector4">
+ <return type="Vector4" />
+ <argument index="0" name="from" type="Vector4" />
+ <description>
+ Constructs a [Vector4] as a copy of the given [Vector4].
+ </description>
+ </constructor>
+ <constructor name="Vector4">
+ <return type="Vector4" />
+ <argument index="0" name="from" type="Vector4i" />
+ <description>
+ Constructs a new [Vector4] from [Vector4i].
+ </description>
+ </constructor>
+ <constructor name="Vector4">
+ <return type="Vector4" />
+ <argument index="0" name="x" type="float" />
+ <argument index="1" name="y" type="float" />
+ <argument index="2" name="z" type="float" />
+ <argument index="3" name="w" type="float" />
+ <description>
+ Returns a [Vector4] with the given components.
+ </description>
+ </constructor>
+ </constructors>
+ <methods>
+ <method name="abs" qualifiers="const">
+ <return type="Vector4" />
+ <description>
+ Returns a new vector with all components in absolute values (i.e. positive).
+ </description>
+ </method>
+ <method name="ceil" qualifiers="const">
+ <return type="Vector4" />
+ <description>
+ Returns a new vector with all components rounded up (towards positive infinity).
+ </description>
+ </method>
+ <method name="clamp" qualifiers="const">
+ <return type="Vector4" />
+ <argument index="0" name="min" type="Vector4" />
+ <argument index="1" name="max" type="Vector4" />
+ <description>
+ Returns a new vector with all components clamped between the components of [code]min[/code] and [code]max[/code], by running [method @GlobalScope.clamp] on each component.
+ </description>
+ </method>
+ <method name="cubic_interpolate" qualifiers="const">
+ <return type="Vector4" />
+ <argument index="0" name="b" type="Vector4" />
+ <argument index="1" name="pre_a" type="Vector4" />
+ <argument index="2" name="post_b" type="Vector4" />
+ <argument index="3" name="weight" type="float" />
+ <description>
+ Performs a cubic interpolation between this vector and [code]b[/code] using [code]pre_a[/code] and [code]post_b[/code] as handles, and returns the result at position [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation.
+ </description>
+ </method>
+ <method name="direction_to" qualifiers="const">
+ <return type="Vector4" />
+ <argument index="0" name="to" type="Vector4" />
+ <description>
+ Returns the normalized vector pointing from this vector to [code]to[/code]. This is equivalent to using [code](b - a).normalized()[/code].
+ </description>
+ </method>
+ <method name="distance_to" qualifiers="const">
+ <return type="float" />
+ <argument index="0" name="to" type="Vector4" />
+ <description>
+ Returns the distance between this vector and [code]to[/code].
+ </description>
+ </method>
+ <method name="dot" qualifiers="const">
+ <return type="float" />
+ <argument index="0" name="with" type="Vector4" />
+ <description>
+ Returns the dot product of this vector and [code]with[/code].
+ </description>
+ </method>
+ <method name="floor" qualifiers="const">
+ <return type="Vector4" />
+ <description>
+ Returns a new vector with all components rounded down (towards negative infinity).
+ </description>
+ </method>
+ <method name="inverse" qualifiers="const">
+ <return type="Vector4" />
+ <description>
+ Returns the inverse of the vector. This is the same as [code]Vector4(1.0 / v.x, 1.0 / v.y, 1.0 / v.z, 1.0 / v.w)[/code].
+ </description>
+ </method>
+ <method name="is_equal_approx" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="with" type="Vector4" />
+ <description>
+ Returns [code]true[/code] if this vector and [code]v[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component.
+ </description>
+ </method>
+ <method name="is_normalized" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the vector is normalized, i.e. its length is equal to 1.
+ </description>
+ </method>
+ <method name="length" qualifiers="const">
+ <return type="float" />
+ <description>
+ Returns the length (magnitude) of this vector.
+ </description>
+ </method>
+ <method name="length_squared" qualifiers="const">
+ <return type="float" />
+ <description>
+ Returns the squared length (squared magnitude) of this vector. This method runs faster than [method length].
+ </description>
+ </method>
+ <method name="lerp" qualifiers="const">
+ <return type="Vector4" />
+ <argument index="0" name="to" type="Vector4" />
+ <argument index="1" name="weight" type="float" />
+ <description>
+ Returns the result of the linear interpolation between this vector and [code]to[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of [code]0.0[/code] to [code]1.0[/code], representing the amount of interpolation.
+ </description>
+ </method>
+ <method name="max_axis_index" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the axis of the vector's highest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_X].
+ </description>
+ </method>
+ <method name="min_axis_index" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the axis of the vector's lowest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_W].
+ </description>
+ </method>
+ <method name="normalized" qualifiers="const">
+ <return type="Vector4" />
+ <description>
+ Returns the vector scaled to unit length. Equivalent to [code]v / v.length()[/code].
+ </description>
+ </method>
+ <method name="posmod" qualifiers="const">
+ <return type="Vector4" />
+ <argument index="0" name="mod" type="float" />
+ <description>
+ Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [code]mod[/code].
+ </description>
+ </method>
+ <method name="posmodv" qualifiers="const">
+ <return type="Vector4" />
+ <argument index="0" name="modv" type="Vector4" />
+ <description>
+ Returns a vector composed of the [method @GlobalScope.fposmod] of this vector's components and [code]modv[/code]'s components.
+ </description>
+ </method>
+ <method name="round" qualifiers="const">
+ <return type="Vector4" />
+ <description>
+ Returns a new vector with all components rounded to the nearest integer, with halfway cases rounded away from zero.
+ </description>
+ </method>
+ <method name="sign" qualifiers="const">
+ <return type="Vector4" />
+ <description>
+ Returns a new vector with each component set to one or negative one, depending on the signs of the components, or zero if the component is zero, by calling [method @GlobalScope.sign] on each component.
+ </description>
+ </method>
+ <method name="snapped" qualifiers="const">
+ <return type="Vector4" />
+ <argument index="0" name="step" type="Vector4" />
+ <description>
+ Returns this vector with each component snapped to the nearest multiple of [code]step[/code]. This can also be used to round to an arbitrary number of decimals.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="w" type="float" setter="" getter="" default="0.0">
+ The vector's W component. Also accessible by using the index position [code][3][/code].
+ </member>
+ <member name="x" type="float" setter="" getter="" default="0.0">
+ The vector's X component. Also accessible by using the index position [code][0][/code].
+ </member>
+ <member name="y" type="float" setter="" getter="" default="0.0">
+ The vector's Y component. Also accessible by using the index position [code][1][/code].
+ </member>
+ <member name="z" type="float" setter="" getter="" default="0.0">
+ The vector's Z component. Also accessible by using the index position [code][2][/code].
+ </member>
+ </members>
+ <constants>
+ <constant name="AXIS_X" value="0">
+ Enumerated value for the X axis. Returned by [method max_axis_index] and [method min_axis_index].
+ </constant>
+ <constant name="AXIS_Y" value="1">
+ Enumerated value for the Y axis. Returned by [method max_axis_index] and [method min_axis_index].
+ </constant>
+ <constant name="AXIS_Z" value="2">
+ Enumerated value for the Z axis. Returned by [method max_axis_index] and [method min_axis_index].
+ </constant>
+ <constant name="AXIS_W" value="3">
+ Enumerated value for the W axis. Returned by [method max_axis_index] and [method min_axis_index].
+ </constant>
+ <constant name="ZERO" value="Vector4(0, 0, 0, 0)">
+ Zero vector, a vector with all components set to [code]0[/code].
+ </constant>
+ <constant name="ONE" value="Vector4(1, 1, 1, 1)">
+ One vector, a vector with all components set to [code]1[/code].
+ </constant>
+ <constant name="INF" value="Vector4(inf, inf, inf, inf)">
+ Infinity vector, a vector with all components set to [constant @GDScript.INF].
+ </constant>
+ </constants>
+ <operators>
+ <operator name="operator !=">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Returns [code]true[/code] if the vectors are not equal.
+ [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable.
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="Projection" />
+ <description>
+ Inversely transforms (multiplies) the [Vector4] by the given [Projection] matrix.
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Multiplies each component of the [Vector4] by the components of the given [Vector4].
+ [codeblock]
+ print(Vector4(10, 20, 30, 40) * Vector4(3, 4, 5, 6)) # Prints "(30, 80, 150, 240)"
+ [/codeblock]
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="float" />
+ <description>
+ Multiplies each component of the [Vector4] by the given [float].
+ [codeblock]
+ print(Vector4(10, 20, 30, 40) * 2) # Prints "(20, 40, 60, 80)"
+ [/codeblock]
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="int" />
+ <description>
+ Multiplies each component of the [Vector4] by the given [int].
+ </description>
+ </operator>
+ <operator name="operator +">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Adds each component of the [Vector4] by the components of the given [Vector4].
+ [codeblock]
+ print(Vector4(10, 20, 30, 40) + Vector4(3, 4, 5, 6)) # Prints "(13, 24, 35, 46)"
+ [/codeblock]
+ </description>
+ </operator>
+ <operator name="operator -">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Subtracts each component of the [Vector4] by the components of the given [Vector4].
+ [codeblock]
+ print(Vector4(10, 20, 30, 40) - Vector4(3, 4, 5, 6)) # Prints "(7, 16, 25, 34)"
+ [/codeblock]
+ </description>
+ </operator>
+ <operator name="operator /">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Divides each component of the [Vector4] by the components of the given [Vector4].
+ [codeblock]
+ print(Vector4(10, 20, 30, 40) / Vector4(2, 5, 3, 4)) # Prints "(5, 4, 10, 10)"
+ [/codeblock]
+ </description>
+ </operator>
+ <operator name="operator /">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="float" />
+ <description>
+ Divides each component of the [Vector4] by the given [float].
+ [codeblock]
+ print(Vector4(10, 20, 30, 40) / 2 # Prints "(5, 10, 15, 20)"
+ [/codeblock]
+ </description>
+ </operator>
+ <operator name="operator /">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="int" />
+ <description>
+ Divides each component of the [Vector4] by the given [int].
+ </description>
+ </operator>
+ <operator name="operator &lt;">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Compares two [Vector4] vectors by first checking if the X value of the left vector is less than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors.
+ </description>
+ </operator>
+ <operator name="operator &lt;=">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Compares two [Vector4] vectors by first checking if the X value of the left vector is less than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors.
+ </description>
+ </operator>
+ <operator name="operator ==">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Returns [code]true[/code] if the vectors are exactly equal.
+ [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable.
+ </description>
+ </operator>
+ <operator name="operator &gt;">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Compares two [Vector4] vectors by first checking if the X value of the left vector is greater than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, Z values of the two vectors, and then with the W values. This operator is useful for sorting vectors.
+ </description>
+ </operator>
+ <operator name="operator &gt;=">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ Access vector components using their index. [code]v[0][/code] is equivalent to [code]v.x[/code], [code]v[1][/code] is equivalent to [code]v.y[/code], and [code]v[2][/code] is equivalent to [code]v.z[/code].
+ </description>
+ </operator>
+ <operator name="operator []">
+ <return type="float" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ Access vector components using their index. [code]v[0][/code] is equivalent to [code]v.x[/code], [code]v[1][/code] is equivalent to [code]v.y[/code], [code]v[2][/code] is equivalent to [code]v.z[/code], and [code]v[3][/code] is equivalent to [code]v.w[/code].
+ </description>
+ </operator>
+ <operator name="operator unary+">
+ <return type="Vector4" />
+ <description>
+ Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable.
+ </description>
+ </operator>
+ <operator name="operator unary-">
+ <return type="Vector4" />
+ <description>
+ Returns the negative value of the [Vector4]. This is the same as writing [code]Vector4(-v.x, -v.y, -v.z, -v.w)[/code]. This operation flips the direction of the vector while keeping the same magnitude. With floats, the number zero can be either positive or negative.
+ </description>
+ </operator>
+ </operators>
+</class>
diff --git a/doc/classes/Vector4i.xml b/doc/classes/Vector4i.xml
new file mode 100644
index 0000000000..6acce12e9f
--- /dev/null
+++ b/doc/classes/Vector4i.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="Vector4i" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <constructors>
+ <constructor name="Vector4i">
+ <return type="Vector4i" />
+ <description>
+ </description>
+ </constructor>
+ <constructor name="Vector4i">
+ <return type="Vector4i" />
+ <argument index="0" name="from" type="Vector4i" />
+ <description>
+ </description>
+ </constructor>
+ <constructor name="Vector4i">
+ <return type="Vector4i" />
+ <argument index="0" name="from" type="Vector4" />
+ <description>
+ </description>
+ </constructor>
+ <constructor name="Vector4i">
+ <return type="Vector4i" />
+ <argument index="0" name="x" type="int" />
+ <argument index="1" name="y" type="int" />
+ <argument index="2" name="z" type="int" />
+ <argument index="3" name="w" type="int" />
+ <description>
+ </description>
+ </constructor>
+ </constructors>
+ <methods>
+ <method name="abs" qualifiers="const">
+ <return type="Vector4i" />
+ <description>
+ </description>
+ </method>
+ <method name="clamp" qualifiers="const">
+ <return type="Vector4i" />
+ <argument index="0" name="min" type="Vector4i" />
+ <argument index="1" name="max" type="Vector4i" />
+ <description>
+ </description>
+ </method>
+ <method name="length" qualifiers="const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="length_squared" qualifiers="const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="max_axis_index" qualifiers="const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="min_axis_index" qualifiers="const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="sign" qualifiers="const">
+ <return type="Vector4i" />
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="w" type="int" setter="" getter="" default="0">
+ </member>
+ <member name="x" type="int" setter="" getter="" default="0">
+ </member>
+ <member name="y" type="int" setter="" getter="" default="0">
+ </member>
+ <member name="z" type="int" setter="" getter="" default="0">
+ </member>
+ </members>
+ <constants>
+ <constant name="AXIS_X" value="0">
+ </constant>
+ <constant name="AXIS_Y" value="1">
+ </constant>
+ <constant name="AXIS_Z" value="2">
+ </constant>
+ <constant name="AXIS_W" value="3">
+ </constant>
+ <constant name="ZERO" value="Vector4i(0, 0, 0, 0)">
+ </constant>
+ <constant name="ONE" value="Vector4i(1, 1, 1, 1)">
+ </constant>
+ </constants>
+ <operators>
+ <operator name="operator !=">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator %">
+ <return type="Vector4i" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator %">
+ <return type="Vector4i" />
+ <argument index="0" name="right" type="int" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4i" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="float" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4i" />
+ <argument index="0" name="right" type="int" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator +">
+ <return type="Vector4i" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator -">
+ <return type="Vector4i" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator /">
+ <return type="Vector4i" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator /">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="float" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator /">
+ <return type="Vector4i" />
+ <argument index="0" name="right" type="int" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator &lt;">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator &lt;=">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator ==">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator &gt;">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator &gt;=">
+ <return type="bool" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator []">
+ <return type="int" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator unary+">
+ <return type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator unary-">
+ <return type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ </operators>
+</class>
diff --git a/doc/classes/VehicleBody3D.xml b/doc/classes/VehicleBody3D.xml
index 330a405d5f..08309a8ecc 100644
--- a/doc/classes/VehicleBody3D.xml
+++ b/doc/classes/VehicleBody3D.xml
@@ -16,7 +16,7 @@
Slows down the vehicle by applying a braking force. The vehicle is only slowed down if the wheels are in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidDynamicBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking.
</member>
<member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force" default="0.0">
- Accelerates the vehicle by applying an engine force. The vehicle is only speed up if the wheels that have [member VehicleWheel3D.use_as_traction] set to [code]true[/code] and are in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration.
+ Accelerates the vehicle by applying an engine force. The vehicle is only sped up if the wheels that have [member VehicleWheel3D.use_as_traction] set to [code]true[/code] and are in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration.
[b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears.
A negative value will result in the vehicle reversing.
</member>
diff --git a/doc/classes/VehicleWheel3D.xml b/doc/classes/VehicleWheel3D.xml
index 1c164d7c9a..ac126f824e 100644
--- a/doc/classes/VehicleWheel3D.xml
+++ b/doc/classes/VehicleWheel3D.xml
@@ -48,7 +48,7 @@
The damping applied to the spring when relaxing. This value should be between 0.0 (no damping) and 1.0. This value should always be slightly higher than the [member damping_compression] property. For a [member damping_compression] value of 0.3, try a relaxation value of 0.5.
</member>
<member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force" default="0.0">
- Accelerates the wheel by applying an engine force. The wheel is only speed up if it is in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration.
+ Accelerates the wheel by applying an engine force. The wheel is only sped up if it is in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration.
[b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears.
A negative value will result in the wheel reversing.
</member>
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/Viewport.xml b/doc/classes/Viewport.xml
index 4727bc389e..0808a8f1cf 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -57,6 +57,13 @@
Returns the mouse's position in this [Viewport] using the coordinate system of this [Viewport].
</description>
</method>
+ <method name="get_positional_shadow_atlas_quadrant_subdiv" qualifiers="const">
+ <return type="int" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" />
+ <argument index="0" name="quadrant" type="int" />
+ <description>
+ Returns the [enum PositionalShadowAtlasQuadrantSubdiv] of the specified quadrant.
+ </description>
+ </method>
<method name="get_render_info">
<return type="int" />
<argument index="0" name="type" type="int" enum="Viewport.RenderInfoType" />
@@ -64,13 +71,6 @@
<description>
</description>
</method>
- <method name="get_shadow_atlas_quadrant_subdiv" qualifiers="const">
- <return type="int" enum="Viewport.ShadowAtlasQuadrantSubdiv" />
- <argument index="0" name="quadrant" type="int" />
- <description>
- Returns the [enum ShadowAtlasQuadrantSubdiv] of the specified quadrant.
- </description>
- </method>
<method name="get_texture" qualifiers="const">
<return type="ViewportTexture" />
<description>
@@ -158,10 +158,10 @@
Stops the input from propagating further down the [SceneTree].
</description>
</method>
- <method name="set_shadow_atlas_quadrant_subdiv">
+ <method name="set_positional_shadow_atlas_quadrant_subdiv">
<return type="void" />
<argument index="0" name="quadrant" type="int" />
- <argument index="1" name="subdiv" type="int" enum="Viewport.ShadowAtlasQuadrantSubdiv" />
+ <argument index="1" name="subdiv" type="int" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" />
<description>
Sets the number of subdivisions to use in the specified quadrant. A higher number of subdivisions allows you to have more shadows in the scene at once, but reduces the quality of the shadows. A good practice is to have quadrants with a varying number of subdivisions and to have as few subdivisions as possible.
</description>
@@ -196,10 +196,6 @@
<member name="disable_3d" type="bool" setter="set_disable_3d" getter="is_3d_disabled" default="false">
Disable 3D rendering (but keep 2D rendering).
</member>
- <member name="fsr_mipmap_bias" type="float" setter="set_fsr_mipmap_bias" getter="get_fsr_mipmap_bias" default="0.0">
- Affects the final texture sharpness by reading from a lower or higher mipmap when using FSR. Mipmap bias does nothing when FSR is not being used. Negative values make textures sharper, while positive values make textures blurrier. This value is used to adjust the mipmap bias calculated internally which is based on the selected quality. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code]. This updates the rendering server's mipmap bias when called
- To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/fsr_mipmap_bias] project setting.
- </member>
<member name="fsr_sharpness" type="float" setter="set_fsr_sharpness" getter="get_fsr_sharpness" default="0.2">
Determines how sharp the upscaled image will be when using the FSR upscaling mode. Sharpness halves with every whole number. Values go from 0.0 (sharpest) to 2.0. Values above 2.0 won't make a visible difference.
To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/fsr_sharpness] project setting.
@@ -232,6 +228,24 @@
<member name="physics_object_picking" type="bool" setter="set_physics_object_picking" getter="get_physics_object_picking" default="false">
If [code]true[/code], the objects rendered by viewport become subjects of mouse picking process.
</member>
+ <member name="positional_shadow_atlas_16_bits" type="bool" setter="set_positional_shadow_atlas_16_bits" getter="get_positional_shadow_atlas_16_bits" default="true">
+ </member>
+ <member name="positional_shadow_atlas_quad_0" type="int" setter="set_positional_shadow_atlas_quadrant_subdiv" getter="get_positional_shadow_atlas_quadrant_subdiv" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" default="2">
+ The subdivision amount of the first quadrant on the shadow atlas.
+ </member>
+ <member name="positional_shadow_atlas_quad_1" type="int" setter="set_positional_shadow_atlas_quadrant_subdiv" getter="get_positional_shadow_atlas_quadrant_subdiv" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" default="2">
+ The subdivision amount of the second quadrant on the shadow atlas.
+ </member>
+ <member name="positional_shadow_atlas_quad_2" type="int" setter="set_positional_shadow_atlas_quadrant_subdiv" getter="get_positional_shadow_atlas_quadrant_subdiv" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" default="3">
+ The subdivision amount of the third quadrant on the shadow atlas.
+ </member>
+ <member name="positional_shadow_atlas_quad_3" type="int" setter="set_positional_shadow_atlas_quadrant_subdiv" getter="get_positional_shadow_atlas_quadrant_subdiv" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" default="4">
+ The subdivision amount of the fourth quadrant on the shadow atlas.
+ </member>
+ <member name="positional_shadow_atlas_size" type="int" setter="set_positional_shadow_atlas_size" getter="get_positional_shadow_atlas_size" default="2048">
+ The shadow atlas' resolution (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
+ [b]Note:[/b] If this is set to [code]0[/code], no shadows will be visible at all (including directional shadows).
+ </member>
<member name="scaling_3d_mode" type="int" setter="set_scaling_3d_mode" getter="get_scaling_3d_mode" enum="Viewport.Scaling3DMode" default="0">
Sets scaling 3d mode. Bilinear scaling renders at different resolution to either undersample or supersample the viewport. FidelityFX Super Resolution 1.0, abbreviated to FSR, is an upscaling technology that produces high quality images at fast framerates by using a spatially aware upscaling algorithm. FSR is slightly more expensive than bilinear, but it produces significantly higher image quality. FSR should be used where possible.
To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/mode] project setting.
@@ -248,28 +262,15 @@
</member>
<member name="sdf_scale" type="int" setter="set_sdf_scale" getter="get_sdf_scale" enum="Viewport.SDFScale" default="1">
</member>
- <member name="shadow_atlas_16_bits" type="bool" setter="set_shadow_atlas_16_bits" getter="get_shadow_atlas_16_bits" default="true">
- </member>
- <member name="shadow_atlas_quad_0" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="2">
- The subdivision amount of the first quadrant on the shadow atlas.
- </member>
- <member name="shadow_atlas_quad_1" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="2">
- The subdivision amount of the second quadrant on the shadow atlas.
- </member>
- <member name="shadow_atlas_quad_2" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="3">
- The subdivision amount of the third quadrant on the shadow atlas.
- </member>
- <member name="shadow_atlas_quad_3" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="4">
- The subdivision amount of the fourth quadrant on the shadow atlas.
- </member>
- <member name="shadow_atlas_size" type="int" setter="set_shadow_atlas_size" getter="get_shadow_atlas_size" default="2048">
- The shadow atlas' resolution (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
- [b]Note:[/b] If this is set to 0, shadows won't be visible.
- </member>
<member name="snap_2d_transforms_to_pixel" type="bool" setter="set_snap_2d_transforms_to_pixel" getter="is_snap_2d_transforms_to_pixel_enabled" default="false">
</member>
<member name="snap_2d_vertices_to_pixel" type="bool" setter="set_snap_2d_vertices_to_pixel" getter="is_snap_2d_vertices_to_pixel_enabled" default="false">
</member>
+ <member name="texture_mipmap_bias" type="float" setter="set_texture_mipmap_bias" getter="get_texture_mipmap_bias" default="0.0">
+ Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member ProjectSettings.rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias.
+ [b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code].
+ To control this property on the root viewport, set the [member ProjectSettings.rendering/textures/default_filters/texture_mipmap_bias] project setting.
+ </member>
<member name="transparent_bg" type="bool" setter="set_transparent_background" getter="has_transparent_background" default="false">
If [code]true[/code], the viewport should render its background as transparent.
</member>
@@ -286,6 +287,12 @@
<member name="use_xr" type="bool" setter="set_use_xr" getter="is_using_xr" default="false">
If [code]true[/code], the viewport will use the primary XR interface to render XR output. When applicable this can result in a stereoscopic image and the resulting render being output to a headset.
</member>
+ <member name="vrs_mode" type="int" setter="set_vrs_mode" getter="get_vrs_mode" enum="Viewport.VRSMode" default="0">
+ The Variable Rate Shading (VRS) mode that is used for this viewport. Note, if hardware does not support VRS this property is ignored.
+ </member>
+ <member name="vrs_texture" type="Texture2D" setter="set_vrs_texture" getter="get_vrs_texture">
+ Texture to use when [member vrs_mode] is set to [constant Viewport.VRS_TEXTURE].
+ </member>
<member name="world_2d" type="World2D" setter="set_world_2d" getter="get_world_2d">
The custom [World2D] which can be used as 2D environment source.
</member>
@@ -307,29 +314,29 @@
</signal>
</signals>
<constants>
- <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED" value="0" enum="ShadowAtlasQuadrantSubdiv">
+ <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED" value="0" enum="PositionalShadowAtlasQuadrantSubdiv">
This quadrant will not be used.
</constant>
- <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_1" value="1" enum="ShadowAtlasQuadrantSubdiv">
+ <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_1" value="1" enum="PositionalShadowAtlasQuadrantSubdiv">
This quadrant will only be used by one shadow map.
</constant>
- <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_4" value="2" enum="ShadowAtlasQuadrantSubdiv">
+ <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_4" value="2" enum="PositionalShadowAtlasQuadrantSubdiv">
This quadrant will be split in 4 and used by up to 4 shadow maps.
</constant>
- <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_16" value="3" enum="ShadowAtlasQuadrantSubdiv">
+ <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_16" value="3" enum="PositionalShadowAtlasQuadrantSubdiv">
This quadrant will be split 16 ways and used by up to 16 shadow maps.
</constant>
- <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_64" value="4" enum="ShadowAtlasQuadrantSubdiv">
+ <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_64" value="4" enum="PositionalShadowAtlasQuadrantSubdiv">
This quadrant will be split 64 ways and used by up to 64 shadow maps.
</constant>
- <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_256" value="5" enum="ShadowAtlasQuadrantSubdiv">
- This quadrant will be split 256 ways and used by up to 256 shadow maps. Unless the [member shadow_atlas_size] is very high, the shadows in this quadrant will be very low resolution.
+ <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_256" value="5" enum="PositionalShadowAtlasQuadrantSubdiv">
+ This quadrant will be split 256 ways and used by up to 256 shadow maps. Unless the [member positional_shadow_atlas_size] is very high, the shadows in this quadrant will be very low resolution.
</constant>
- <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_1024" value="6" enum="ShadowAtlasQuadrantSubdiv">
- This quadrant will be split 1024 ways and used by up to 1024 shadow maps. Unless the [member shadow_atlas_size] is very high, the shadows in this quadrant will be very low resolution.
+ <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_1024" value="6" enum="PositionalShadowAtlasQuadrantSubdiv">
+ This quadrant will be split 1024 ways and used by up to 1024 shadow maps. Unless the [member positional_shadow_atlas_size] is very high, the shadows in this quadrant will be very low resolution.
</constant>
- <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_MAX" value="7" enum="ShadowAtlasQuadrantSubdiv">
- Represents the size of the [enum ShadowAtlasQuadrantSubdiv] enum.
+ <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_MAX" value="7" enum="PositionalShadowAtlasQuadrantSubdiv">
+ Represents the size of the [enum PositionalShadowAtlasQuadrantSubdiv] enum.
</constant>
<constant name="SCALING_3D_MODE_BILINEAR" value="0" enum="Scaling3DMode">
Use bilinear scaling for the viewport's 3D buffer. The amount of scaling can be set using [member scaling_3d_scale]. Values less then [code]1.0[/code] will result in undersampling while values greater than [code]1.0[/code] will result in supersampling. A value of [code]1.0[/code] disables scaling.
@@ -492,5 +499,17 @@
</constant>
<constant name="SDF_SCALE_MAX" value="3" enum="SDFScale">
</constant>
+ <constant name="VRS_DISABLED" value="0" enum="VRSMode">
+ VRS is disabled.
+ </constant>
+ <constant name="VRS_TEXTURE" value="1" enum="VRSMode">
+ VRS uses a texture. Note, for stereoscopic use a texture atlas with a texture for each view.
+ </constant>
+ <constant name="VRS_XR" value="2" enum="VRSMode">
+ VRS texture is supplied by the primary [XRInterface].
+ </constant>
+ <constant name="VRS_MAX" value="3" enum="VRSMode">
+ Represents the size of the [enum VRSMode] enum.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/VisualShaderNodeTextureUniform.xml b/doc/classes/VisualShaderNodeTextureUniform.xml
index bff6f2015d..9014f79f54 100644
--- a/doc/classes/VisualShaderNodeTextureUniform.xml
+++ b/doc/classes/VisualShaderNodeTextureUniform.xml
@@ -39,12 +39,15 @@
Represents the size of the [enum TextureType] enum.
</constant>
<constant name="COLOR_DEFAULT_WHITE" value="0" enum="ColorDefault">
- Defaults to white color.
+ Defaults to fully opaque white color.
</constant>
<constant name="COLOR_DEFAULT_BLACK" value="1" enum="ColorDefault">
- Defaults to black color.
+ Defaults to fully opaque black color.
</constant>
- <constant name="COLOR_DEFAULT_MAX" value="2" enum="ColorDefault">
+ <constant name="COLOR_DEFAULT_TRANSPARENT" value="2" enum="ColorDefault">
+ Defaults to fully transparent black color.
+ </constant>
+ <constant name="COLOR_DEFAULT_MAX" value="3" enum="ColorDefault">
Represents the size of the [enum ColorDefault] enum.
</constant>
<constant name="FILTER_DEFAULT" value="0" enum="TextureFilter">
diff --git a/doc/classes/VisualShaderNodeVectorRefract.xml b/doc/classes/VisualShaderNodeVectorRefract.xml
index d12188ea55..003b505671 100644
--- a/doc/classes/VisualShaderNodeVectorRefract.xml
+++ b/doc/classes/VisualShaderNodeVectorRefract.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualShaderNodeVectorRefract" inherits="VisualShaderNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="VisualShaderNodeVectorRefract" inherits="VisualShaderNodeVectorBase" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Returns the [Vector3] that points in the direction of refraction. For use within the visual shader graph.
+ Returns the vector that points in the direction of refraction. For use within the visual shader graph.
</brief_description>
<description>
Translated to [code]refract(I, N, eta)[/code] in the shader language, where [code]I[/code] is the incident vector, [code]N[/code] is the normal vector and [code]eta[/code] is the ratio of the indices of the refraction.
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/VoxelGIData.xml b/doc/classes/VoxelGIData.xml
index b8d424b5fe..9198da4bc6 100644
--- a/doc/classes/VoxelGIData.xml
+++ b/doc/classes/VoxelGIData.xml
@@ -72,10 +72,10 @@
<member name="normal_bias" type="float" setter="set_normal_bias" getter="get_normal_bias" default="0.0">
The normal bias to use for indirect lighting and reflections. Higher values reduce self-reflections visible in non-rough materials, at the cost of more visible light leaking and flatter-looking indirect lighting. See also [member bias]. To prioritize hiding self-reflections over lighting quality, set [member bias] to [code]0.0[/code] and [member normal_bias] to a value between [code]1.0[/code] and [code]2.0[/code].
</member>
- <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="0.7">
- If indirect lighting looks too flat, try decreasing [member propagation] while increasing [member energy] at the same time. See also [member use_two_bounces] which influences the indirect lighting's effective brightness.
+ <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="0.5">
+ The multiplier to use when light bounces off a surface. Higher values result in brighter indirect lighting. If indirect lighting looks too flat, try decreasing [member propagation] while increasing [member energy] at the same time. See also [member use_two_bounces] which influences the indirect lighting's effective brightness.
</member>
- <member name="use_two_bounces" type="bool" setter="set_use_two_bounces" getter="is_using_two_bounces" default="false">
+ <member name="use_two_bounces" type="bool" setter="set_use_two_bounces" getter="is_using_two_bounces" default="true">
If [code]true[/code], performs two bounces of indirect lighting instead of one. This makes indirect lighting look more natural and brighter at a small performance cost. The second bounce is also visible in reflections. If the scene appears too bright after enabling [member use_two_bounces], adjust [member propagation] and [member energy].
</member>
</members>
diff --git a/doc/classes/WeakRef.xml b/doc/classes/WeakRef.xml
index f80381acda..ea520178c7 100644
--- a/doc/classes/WeakRef.xml
+++ b/doc/classes/WeakRef.xml
@@ -12,7 +12,7 @@
<method name="get_ref" qualifiers="const">
<return type="Variant" />
<description>
- Returns the [Object] this weakref is referring to.
+ Returns the [Object] this weakref is referring to. Returns [code]null[/code] if that object no longer exists.
</description>
</method>
</methods>
diff --git a/doc/classes/WorkerThreadPool.xml b/doc/classes/WorkerThreadPool.xml
new file mode 100644
index 0000000000..4f614bdadb
--- /dev/null
+++ b/doc/classes/WorkerThreadPool.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="WorkerThreadPool" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_group_task">
+ <return type="int" />
+ <argument index="0" name="action" type="Callable" />
+ <argument index="1" name="elements" type="int" />
+ <argument index="2" name="tasks_needed" type="int" default="-1" />
+ <argument index="3" name="high_priority" type="bool" default="false" />
+ <argument index="4" name="description" type="String" default="&quot;&quot;" />
+ <description>
+ </description>
+ </method>
+ <method name="add_task">
+ <return type="int" />
+ <argument index="0" name="action" type="Callable" />
+ <argument index="1" name="high_priority" type="bool" default="false" />
+ <argument index="2" name="description" type="String" default="&quot;&quot;" />
+ <description>
+ </description>
+ </method>
+ <method name="get_group_processed_element_count" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="group_id" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="is_group_task_completed" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="group_id" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="is_task_completed" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="task_id" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="wait_for_group_task_completion">
+ <return type="void" />
+ <argument index="0" name="group_id" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="wait_for_task_completion">
+ <return type="void" />
+ <argument index="0" name="task_id" type="int" />
+ <description>
+ </description>
+ </method>
+ </methods>
+</class>
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/classes/XRCamera3D.xml b/doc/classes/XRCamera3D.xml
index e0fc016a7d..4d6baa327b 100644
--- a/doc/classes/XRCamera3D.xml
+++ b/doc/classes/XRCamera3D.xml
@@ -8,6 +8,6 @@
The position and orientation of this node is automatically updated by the XR Server to represent the location of the HMD if such tracking is available and can thus be used by game logic. Note that, in contrast to the XR Controller, the render thread has access to the most up-to-date tracking data of the HMD and the location of the XRCamera3D can lag a few milliseconds behind what is used for rendering as a result.
</description>
<tutorials>
- <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link>
+ <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link>
</tutorials>
</class>
diff --git a/doc/classes/XRController3D.xml b/doc/classes/XRController3D.xml
index deea888b8f..ff4aec46e1 100644
--- a/doc/classes/XRController3D.xml
+++ b/doc/classes/XRController3D.xml
@@ -10,7 +10,7 @@
As many XR runtimes now use a configurable action map all inputs are named.
</description>
<tutorials>
- <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link>
+ <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link>
</tutorials>
<methods>
<method name="get_axis" qualifiers="const">
diff --git a/doc/classes/XRInterface.xml b/doc/classes/XRInterface.xml
index 0f4159cbbf..26b7699af2 100644
--- a/doc/classes/XRInterface.xml
+++ b/doc/classes/XRInterface.xml
@@ -8,7 +8,7 @@
Interfaces should be written in such a way that simply enabling them will give us a working setup. You can query the available interfaces through [XRServer].
</description>
<tutorials>
- <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link>
+ <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link>
</tutorials>
<methods>
<method name="get_camera_feed_id">
diff --git a/doc/classes/XRInterfaceExtension.xml b/doc/classes/XRInterfaceExtension.xml
index 71f6a44724..1642ae61f7 100644
--- a/doc/classes/XRInterfaceExtension.xml
+++ b/doc/classes/XRInterfaceExtension.xml
@@ -106,6 +106,11 @@
Returns the number of views this interface requires, 1 for mono, 2 for stereoscopic.
</description>
</method>
+ <method name="_get_vrs_texture" qualifiers="virtual">
+ <return type="RID" />
+ <description>
+ </description>
+ </method>
<method name="_initialize" qualifiers="virtual">
<return type="bool" />
<description>
diff --git a/doc/classes/XROrigin3D.xml b/doc/classes/XROrigin3D.xml
index b7811f4d53..7acee097e7 100644
--- a/doc/classes/XROrigin3D.xml
+++ b/doc/classes/XROrigin3D.xml
@@ -10,7 +10,7 @@
For example, if your character is driving a car, the XROrigin3D node should be a child node of this car. Or, if you're implementing a teleport system to move your character, you should change the position of this node.
</description>
<tutorials>
- <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link>
+ <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link>
</tutorials>
<members>
<member name="world_scale" type="float" setter="set_world_scale" getter="get_world_scale" default="1.0">
diff --git a/doc/classes/XRPositionalTracker.xml b/doc/classes/XRPositionalTracker.xml
index d15558c9e8..c146b27fcb 100644
--- a/doc/classes/XRPositionalTracker.xml
+++ b/doc/classes/XRPositionalTracker.xml
@@ -9,7 +9,7 @@
The [XRController3D] and [XRAnchor3D] both consume objects of this type and should be used in your project. The positional trackers are just under-the-hood objects that make this all work. These are mostly exposed so that GDExtension-based interfaces can interact with them.
</description>
<tutorials>
- <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link>
+ <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link>
</tutorials>
<methods>
<method name="get_input" qualifiers="const">
diff --git a/doc/classes/XRServer.xml b/doc/classes/XRServer.xml
index a322a3c5c9..d3cb958cbc 100644
--- a/doc/classes/XRServer.xml
+++ b/doc/classes/XRServer.xml
@@ -7,7 +7,7 @@
The AR/VR server is the heart of our Advanced and Virtual Reality solution and handles all the processing.
</description>
<tutorials>
- <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link>
+ <link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link>
</tutorials>
<methods>
<method name="add_interface">
diff --git a/doc/classes/float.xml b/doc/classes/float.xml
index f36b1fddeb..a7c6533ef5 100644
--- a/doc/classes/float.xml
+++ b/doc/classes/float.xml
@@ -111,6 +111,18 @@
</description>
</operator>
<operator name="operator *">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator *">
<return type="float" />
<argument index="0" name="right" type="float" />
<description>
diff --git a/doc/classes/int.xml b/doc/classes/int.xml
index 2eceba40fa..6b492ca923 100644
--- a/doc/classes/int.xml
+++ b/doc/classes/int.xml
@@ -158,6 +158,18 @@
</description>
</operator>
<operator name="operator *">
+ <return type="Vector4" />
+ <argument index="0" name="right" type="Vector4" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator *">
+ <return type="Vector4i" />
+ <argument index="0" name="right" type="Vector4i" />
+ <description>
+ </description>
+ </operator>
+ <operator name="operator *">
<return type="float" />
<argument index="0" name="right" type="float" />
<description>
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index ce09361dfa..196a26ef77 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -9,9 +9,12 @@ import re
import sys
import xml.etree.ElementTree as ET
from collections import OrderedDict
+from typing import List, Dict, TextIO, Tuple, Optional, Any, Union
-# Uncomment to do type checks. I have it commented out so it works below Python 3.5
-# from typing import List, Dict, TextIO, Tuple, Iterable, Optional, DefaultDict, Any, Union
+# Import hardcoded version information from version.py
+root_directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../")
+sys.path.append(root_directory) # Include the root directory
+import version
# $DOCS_URL/path/to/page.html(#fragment-tag)
GODOT_DOCS_PATTERN = re.compile(r"^\$DOCS_URL/(.*)\.html(#.*)?$")
@@ -36,6 +39,7 @@ BASE_STRINGS = [
"Signals",
"Enumerations",
"Constants",
+ "Annotations",
"Property Descriptions",
"Constructor Descriptions",
"Method Descriptions",
@@ -55,123 +59,18 @@ BASE_STRINGS = [
"This method doesn't need an instance to be called, so it can be called directly using the class name.",
"This method describes a valid operator to use with this type as left-hand operand.",
]
-strings_l10n = {}
+strings_l10n: Dict[str, str] = {}
-STYLES = {}
-
-
-def print_error(error, state): # type: (str, State) -> None
- print("{}{}ERROR:{} {}{}".format(STYLES["red"], STYLES["bold"], STYLES["regular"], error, STYLES["reset"]))
- state.num_errors += 1
-
-
-class TypeName:
- def __init__(self, type_name, enum=None): # type: (str, Optional[str]) -> None
- self.type_name = type_name
- self.enum = enum
-
- def to_rst(self, state): # type: ("State") -> str
- if self.enum is not None:
- return make_enum(self.enum, state)
- elif self.type_name == "void":
- return "void"
- else:
- return make_type(self.type_name, state)
-
- @classmethod
- def from_element(cls, element): # type: (ET.Element) -> "TypeName"
- return cls(element.attrib["type"], element.get("enum"))
-
-
-class PropertyDef:
- def __init__(
- self, name, type_name, setter, getter, text, default_value, overrides
- ): # type: (str, TypeName, Optional[str], Optional[str], Optional[str], Optional[str], Optional[str]) -> None
- self.name = name
- self.type_name = type_name
- self.setter = setter
- self.getter = getter
- self.text = text
- self.default_value = default_value
- self.overrides = overrides
-
-
-class ParameterDef:
- def __init__(self, name, type_name, default_value): # type: (str, TypeName, Optional[str]) -> None
- self.name = name
- self.type_name = type_name
- self.default_value = default_value
-
-
-class SignalDef:
- def __init__(self, name, parameters, description): # type: (str, List[ParameterDef], Optional[str]) -> None
- self.name = name
- self.parameters = parameters
- self.description = description
-
-
-class MethodDef:
- def __init__(
- self, name, return_type, parameters, description, qualifiers
- ): # type: (str, TypeName, List[ParameterDef], Optional[str], Optional[str]) -> None
- self.name = name
- self.return_type = return_type
- self.parameters = parameters
- self.description = description
- self.qualifiers = qualifiers
-
-
-class ConstantDef:
- def __init__(self, name, value, text): # type: (str, str, Optional[str]) -> None
- self.name = name
- self.value = value
- self.text = text
-
-
-class EnumDef:
- def __init__(self, name): # type: (str) -> None
- self.name = name
- self.values = OrderedDict() # type: OrderedDict[str, ConstantDef]
-
-
-class ThemeItemDef:
- def __init__(
- self, name, type_name, data_name, text, default_value
- ): # type: (str, TypeName, str, Optional[str], Optional[str]) -> None
- self.name = name
- self.type_name = type_name
- self.data_name = data_name
- self.text = text
- self.default_value = default_value
-
-
-class ClassDef:
- def __init__(self, name): # type: (str) -> None
- self.name = name
- self.constants = OrderedDict() # type: OrderedDict[str, ConstantDef]
- self.enums = OrderedDict() # type: OrderedDict[str, EnumDef]
- self.properties = OrderedDict() # type: OrderedDict[str, PropertyDef]
- self.constructors = OrderedDict() # type: OrderedDict[str, List[MethodDef]]
- self.methods = OrderedDict() # type: OrderedDict[str, List[MethodDef]]
- self.operators = OrderedDict() # type: OrderedDict[str, List[MethodDef]]
- self.signals = OrderedDict() # type: OrderedDict[str, SignalDef]
- self.theme_items = OrderedDict() # type: OrderedDict[str, ThemeItemDef]
- self.inherits = None # type: Optional[str]
- self.brief_description = None # type: Optional[str]
- self.description = None # type: Optional[str]
- self.tutorials = [] # type: List[Tuple[str, str]]
-
- # Used to match the class with XML source for output filtering purposes.
- self.filepath = "" # type: str
+STYLES: Dict[str, str] = {}
class State:
- def __init__(self): # type: () -> None
+ def __init__(self) -> None:
self.num_errors = 0
- self.classes = OrderedDict() # type: OrderedDict[str, ClassDef]
- self.current_class = "" # type: str
+ self.classes: OrderedDict[str, ClassDef] = OrderedDict()
+ self.current_class: str = ""
- def parse_class(self, class_root, filepath): # type: (ET.Element, str) -> None
+ def parse_class(self, class_root: ET.Element, filepath: str) -> None:
class_name = class_root.attrib["name"]
class_def = ClassDef(class_name)
@@ -224,7 +123,6 @@ class State:
return_element = constructor.find("return")
if return_element is not None:
return_type = TypeName.from_element(return_element)
-
else:
return_type = TypeName("void")
@@ -305,7 +203,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") == "true"
+ 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 +217,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 = AnnotationDef(annotation_name, 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:
@@ -382,13 +302,147 @@ class State:
if link.text is not None:
class_def.tutorials.append((link.text.strip(), link.get("title", "")))
- def sort_classes(self): # type: () -> None
+ def sort_classes(self) -> None:
self.classes = OrderedDict(sorted(self.classes.items(), key=lambda t: t[0]))
-def parse_arguments(root): # type: (ET.Element) -> List[ParameterDef]
+class TypeName:
+ def __init__(self, type_name: str, enum: Optional[str] = None) -> None:
+ self.type_name = type_name
+ self.enum = enum
+
+ def to_rst(self, state: State) -> str:
+ if self.enum is not None:
+ return make_enum(self.enum, state)
+ elif self.type_name == "void":
+ return "void"
+ else:
+ return make_type(self.type_name, state)
+
+ @classmethod
+ def from_element(cls, element: ET.Element) -> "TypeName":
+ return cls(element.attrib["type"], element.get("enum"))
+
+
+class PropertyDef:
+ def __init__(
+ self,
+ name: str,
+ type_name: TypeName,
+ setter: Optional[str],
+ getter: Optional[str],
+ text: Optional[str],
+ default_value: Optional[str],
+ overrides: Optional[str],
+ ) -> None:
+ self.name = name
+ self.type_name = type_name
+ self.setter = setter
+ self.getter = getter
+ self.text = text
+ self.default_value = default_value
+ self.overrides = overrides
+
+
+class ParameterDef:
+ def __init__(self, name: str, type_name: TypeName, default_value: Optional[str]) -> None:
+ self.name = name
+ self.type_name = type_name
+ self.default_value = default_value
+
+
+class SignalDef:
+ def __init__(self, name: str, parameters: List[ParameterDef], description: Optional[str]) -> None:
+ self.name = name
+ self.parameters = parameters
+ self.description = description
+
+
+class AnnotationDef:
+ def __init__(
+ self,
+ name: str,
+ parameters: List[ParameterDef],
+ description: Optional[str],
+ qualifiers: Optional[str],
+ ) -> None:
+ self.name = name
+ self.parameters = parameters
+ self.description = description
+ self.qualifiers = qualifiers
+
+
+class MethodDef:
+ def __init__(
+ self,
+ name: str,
+ return_type: TypeName,
+ parameters: List[ParameterDef],
+ description: Optional[str],
+ qualifiers: Optional[str],
+ ) -> None:
+ self.name = name
+ self.return_type = return_type
+ self.parameters = parameters
+ self.description = description
+ self.qualifiers = qualifiers
+
+
+class ConstantDef:
+ def __init__(self, name: str, value: str, text: Optional[str], bitfield: bool) -> None:
+ self.name = name
+ self.value = value
+ self.text = text
+ self.is_bitfield = bitfield
+
+
+class EnumDef:
+ def __init__(self, name: str, bitfield: bool) -> None:
+ self.name = name
+ self.values: OrderedDict[str, ConstantDef] = OrderedDict()
+ self.is_bitfield = bitfield
+
+
+class ThemeItemDef:
+ def __init__(
+ self, name: str, type_name: TypeName, data_name: str, text: Optional[str], default_value: Optional[str]
+ ) -> None:
+ self.name = name
+ self.type_name = type_name
+ self.data_name = data_name
+ self.text = text
+ self.default_value = default_value
+
+
+class ClassDef:
+ def __init__(self, name: str) -> None:
+ self.name = name
+ self.constants: OrderedDict[str, ConstantDef] = OrderedDict()
+ self.enums: OrderedDict[str, EnumDef] = OrderedDict()
+ self.properties: OrderedDict[str, PropertyDef] = OrderedDict()
+ self.constructors: OrderedDict[str, List[MethodDef]] = OrderedDict()
+ self.methods: OrderedDict[str, List[MethodDef]] = OrderedDict()
+ self.operators: OrderedDict[str, List[MethodDef]] = OrderedDict()
+ self.signals: OrderedDict[str, SignalDef] = OrderedDict()
+ self.annotations: OrderedDict[str, List[AnnotationDef]] = OrderedDict()
+ self.theme_items: OrderedDict[str, ThemeItemDef] = OrderedDict()
+ self.inherits: Optional[str] = None
+ self.brief_description: Optional[str] = None
+ self.description: Optional[str] = None
+ self.tutorials: List[Tuple[str, str]] = []
+
+ # Used to match the class with XML source for output filtering purposes.
+ self.filepath: str = ""
+
+
+def print_error(error: str, state: State) -> None:
+ print("{}{}ERROR:{} {}{}".format(STYLES["red"], STYLES["bold"], STYLES["regular"], error, STYLES["reset"]))
+ state.num_errors += 1
+
+
+def parse_arguments(root: ET.Element) -> List[ParameterDef]:
param_elements = root.findall("argument")
- params = [None] * len(param_elements) # type: Any
+ params: Any = [None] * len(param_elements)
for param_element in param_elements:
param_name = param_element.attrib["name"]
index = int(param_element.attrib["index"])
@@ -397,16 +451,16 @@ def parse_arguments(root): # type: (ET.Element) -> List[ParameterDef]
params[index] = ParameterDef(param_name, type_name, default)
- cast = params # type: List[ParameterDef]
+ cast: List[ParameterDef] = params
return cast
-def main(): # type: () -> None
+def main() -> None:
# Enable ANSI escape code support on Windows 10 and later (for colored console output).
# <https://bugs.python.org/issue29059>
if platform.system().lower() == "windows":
- from ctypes import windll, c_int, byref
+ from ctypes import windll, c_int, byref # type: ignore
stdout_handle = windll.kernel32.GetStdHandle(c_int(-11))
mode = c_int(0)
@@ -460,7 +514,7 @@ def main(): # type: () -> None
print("Checking for errors in the XML class reference...")
- file_list = [] # type: List[str]
+ file_list: List[str] = []
for path in args.path:
# Cut off trailing slashes so os.path.basename doesn't choke.
@@ -484,7 +538,7 @@ def main(): # type: () -> None
file_list.append(path)
- classes = {} # type: Dict[str, ET.Element]
+ classes: Dict[str, Tuple[ET.Element, str]] = {}
state = State()
for cur_file in file_list:
@@ -545,7 +599,7 @@ def main(): # type: () -> None
exit(1)
-def translate(string): # type: (str) -> str
+def translate(string: str) -> str:
"""Translate a string based on translations sourced from `doc/translations/*.po`
for a language if defined via the --lang command line argument.
Returns the original string if no translation exists.
@@ -553,7 +607,7 @@ def translate(string): # type: (str) -> str
return strings_l10n.get(string, string)
-def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, State, bool, str) -> None
+def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir: str) -> None:
class_name = class_def.name
if dry_run:
@@ -561,12 +615,26 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
else:
f = open(os.path.join(output_dir, "class_" + class_name.lower() + ".rst"), "w", encoding="utf-8")
- # Warn contributors not to edit this file directly
+ # Remove the "Edit on Github" button from the online docs page.
f.write(":github_url: hide\n\n")
- f.write(".. Generated automatically by doc/tools/make_rst.py in Godot's source tree.\n")
- f.write(".. DO NOT EDIT THIS FILE, but the " + class_name + ".xml source instead.\n")
- f.write(".. The source is found in doc/classes or modules/<name>/doc_classes.\n\n")
+ # Warn contributors not to edit this file directly.
+ # Also provide links to the source files for reference.
+
+ git_branch = "master"
+ if hasattr(version, "docs") and version.docs != "latest":
+ git_branch = version.docs
+
+ source_xml_path = os.path.relpath(class_def.filepath, root_directory).replace("\\", "/")
+ source_github_url = "https://github.com/godotengine/godot/tree/{}/{}".format(git_branch, source_xml_path)
+ generator_github_url = "https://github.com/godotengine/godot/tree/{}/doc/tools/make_rst.py".format(git_branch)
+
+ f.write(".. DO NOT EDIT THIS FILE!!!\n")
+ f.write(".. Generated automatically from Godot engine sources.\n")
+ f.write(".. Generator: " + generator_github_url + ".\n")
+ f.write(".. XML source: " + source_github_url + ".\n\n")
+
+ # Document reference id and header.
f.write(".. _class_" + class_name + ":\n\n")
f.write(make_heading(class_name, "=", False))
@@ -590,8 +658,8 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
break
f.write("\n\n")
- # Descendents
- inherited = []
+ # Descendants
+ inherited: List[str] = []
for c in state.classes.values():
if c.inherits and c.inherits.strip() == class_name:
inherited.append(c.name)
@@ -622,7 +690,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
# Properties overview
if len(class_def.properties) > 0:
f.write(make_heading("Properties", "-"))
- ml = [] # type: List[Tuple[str, str, str]]
+ ml: List[Tuple[Optional[str], ...]] = []
for property_def in class_def.properties.values():
type_rst = property_def.type_name.to_rst(state)
default = property_def.default_value
@@ -638,7 +706,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
# Constructors, Methods, Operators overview
if len(class_def.constructors) > 0:
f.write(make_heading("Constructors", "-"))
- ml = []
+ ml: List[Tuple[Optional[str], ...]] = []
for method_list in class_def.constructors.values():
for m in method_list:
ml.append(make_method_signature(class_def, m, "constructor", state))
@@ -646,7 +714,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
if len(class_def.methods) > 0:
f.write(make_heading("Methods", "-"))
- ml = []
+ ml: List[Tuple[Optional[str], ...]] = []
for method_list in class_def.methods.values():
for m in method_list:
ml.append(make_method_signature(class_def, m, "method", state))
@@ -654,7 +722,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
if len(class_def.operators) > 0:
f.write(make_heading("Operators", "-"))
- ml = []
+ ml: List[Tuple[Optional[str], ...]] = []
for method_list in class_def.operators.values():
for m in method_list:
ml.append(make_method_signature(class_def, m, "operator", state))
@@ -663,7 +731,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
# Theme properties
if len(class_def.theme_items) > 0:
f.write(make_heading("Theme Properties", "-"))
- pl = []
+ pl: List[Tuple[Optional[str], ...]] = []
for theme_item_def in class_def.theme_items.values():
ref = ":ref:`{0}<class_{2}_theme_{1}_{0}>`".format(
theme_item_def.name, theme_item_def.data_name, class_name
@@ -706,7 +774,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 +804,27 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
f.write("\n\n")
+ # Annotations
+ 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("@")))
+
+ _, signature = make_method_signature(class_def, m, "", state)
+ f.write("- {}\n\n".format(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", "-"))
@@ -747,7 +840,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
f.write(".. _class_{}_property_{}:\n\n".format(class_name, property_def.name))
f.write("- {} **{}**\n\n".format(property_def.type_name.to_rst(state), property_def.name))
- info = []
+ info: List[Tuple[Optional[str], ...]] = []
# Not using translate() for now as it breaks table formatting.
if property_def.default_value is not None:
info.append(("*" + "Default" + "*", property_def.default_value))
@@ -857,7 +950,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
f.write(make_footer())
-def escape_rst(text, until_pos=-1): # type: (str) -> str
+def escape_rst(text: str, until_pos: int = -1) -> str:
# Escape \ character, otherwise it ends up as an escape character in rst
pos = 0
while True:
@@ -891,7 +984,7 @@ def escape_rst(text, until_pos=-1): # type: (str) -> str
return text
-def format_codeblock(code_type, post_text, indent_level, state): # types: str, str, int, state
+def format_codeblock(code_type: str, post_text: str, indent_level: int, state: State) -> Union[Tuple[str, int], None]:
end_pos = post_text.find("[/" + code_type + "]")
if end_pos == -1:
print_error("{}.xml: [" + code_type + "] without a closing tag.".format(state.current_class), state)
@@ -925,10 +1018,10 @@ def format_codeblock(code_type, post_text, indent_level, state): # types: str,
else:
code_text = code_text[:code_pos] + "\n " + code_text[code_pos + to_skip + 1 :]
code_pos += 5 - to_skip
- return ["\n[" + code_type + "]" + code_text + post_text, len("\n[" + code_type + "]" + code_text)]
+ return ("\n[" + code_type + "]" + code_text + post_text, len("\n[" + code_type + "]" + code_text))
-def rstize_text(text, state): # type: (str, State) -> str
+def rstize_text(text: str, state: State) -> str:
# Linebreak + tabs in the XML should become two line breaks unless in a "codeblock"
pos = 0
while True:
@@ -968,7 +1061,6 @@ def rstize_text(text, state): # type: (str, State) -> str
inside_code = False
pos = 0
tag_depth = 0
- previous_pos = 0
while True:
pos = text.find("[", pos)
if pos == -1:
@@ -1065,6 +1157,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
@@ -1130,7 +1227,6 @@ def rstize_text(text, state): # type: (str, State) -> str
text = pre_text + tag_text + post_text
pos = len(pre_text) + len(tag_text)
- previous_pos = pos
continue
elif cmd == "center":
tag_depth += 1
@@ -1236,7 +1332,6 @@ def rstize_text(text, state): # type: (str, State) -> str
text = pre_text + tag_text + post_text
pos = len(pre_text) + len(tag_text)
- previous_pos = pos
if tag_depth > 0:
print_error(
@@ -1246,7 +1341,7 @@ def rstize_text(text, state): # type: (str, State) -> str
return text
-def format_table(f, data, remove_empty_columns=False): # type: (TextIO, Iterable[Tuple[str, ...]]) -> None
+def format_table(f: TextIO, data: List[Tuple[Optional[str], ...]], remove_empty_columns: bool = False) -> None:
if len(data) == 0:
return
@@ -1277,7 +1372,7 @@ def format_table(f, data, remove_empty_columns=False): # type: (TextIO, Iterabl
f.write("\n")
-def make_type(klass, state): # type: (str, State) -> str
+def make_type(klass: str, state: State) -> str:
if klass.find("*") != -1: # Pointer, ignore
return klass
link_type = klass
@@ -1289,7 +1384,7 @@ def make_type(klass, state): # type: (str, State) -> str
return klass
-def make_enum(t, state): # type: (str, State) -> str
+def make_enum(t: str, state: State) -> str:
p = t.find(".")
if p >= 0:
c = t[0:p]
@@ -1315,31 +1410,36 @@ def make_enum(t, state): # type: (str, State) -> str
def make_method_signature(
- class_def, method_def, ref_type, state
-): # type: (ClassDef, Union[MethodDef, SignalDef], str, State) -> Tuple[str, str]
- ret_type = " "
+ class_def: ClassDef, definition: Union[AnnotationDef, MethodDef, SignalDef], ref_type: str, state: State
+) -> Tuple[str, str]:
+ ret_type = ""
- if isinstance(method_def, MethodDef):
- ret_type = method_def.return_type.to_rst(state)
+ is_method_def = isinstance(definition, MethodDef)
+ if is_method_def:
+ ret_type = definition.return_type.to_rst(state)
+
+ qualifiers = None
+ if is_method_def or isinstance(definition, AnnotationDef):
+ qualifiers = definition.qualifiers
out = ""
- if ref_type != "":
+ if is_method_def and ref_type != "":
if ref_type == "operator":
out += ":ref:`{0}<class_{1}_{2}_{3}_{4}>` ".format(
- method_def.name,
+ definition.name.replace("<", "\\<"), # So operator "<" gets correctly displayed.
class_def.name,
ref_type,
- sanitize_operator_name(method_def.name, state),
- method_def.return_type.type_name,
+ sanitize_operator_name(definition.name, state),
+ definition.return_type.type_name,
)
else:
- out += ":ref:`{0}<class_{1}_{2}_{0}>` ".format(method_def.name, class_def.name, ref_type)
+ out += ":ref:`{0}<class_{1}_{2}_{0}>` ".format(definition.name, class_def.name, ref_type)
else:
- out += "**{}** ".format(method_def.name)
+ out += "**{}** ".format(definition.name)
out += "**(**"
- for i, arg in enumerate(method_def.parameters):
+ for i, arg in enumerate(definition.parameters):
if i > 0:
out += ", "
else:
@@ -1350,24 +1450,24 @@ def make_method_signature(
if arg.default_value is not None:
out += "=" + arg.default_value
- if isinstance(method_def, MethodDef) and method_def.qualifiers is not None and "vararg" in method_def.qualifiers:
- if len(method_def.parameters) > 0:
+ if qualifiers is not None and "vararg" in qualifiers:
+ if len(definition.parameters) > 0:
out += ", ..."
else:
out += " ..."
out += " **)**"
- if isinstance(method_def, MethodDef) and method_def.qualifiers is not None:
+ if qualifiers is not None:
# Use substitutions for abbreviations. This is used to display tooltips on hover.
# See `make_footer()` for descriptions.
- for qualifier in method_def.qualifiers.split():
+ for qualifier in qualifiers.split():
out += " |" + qualifier + "|"
return ret_type, out
-def make_heading(title, underline, l10n=True): # type: (str, str, bool) -> str
+def make_heading(title: str, underline: str, l10n: bool = True) -> str:
if l10n:
new_title = translate(title)
if new_title != title:
@@ -1376,7 +1476,7 @@ def make_heading(title, underline, l10n=True): # type: (str, str, bool) -> str
return title + "\n" + (underline * len(title)) + "\n\n"
-def make_footer(): # type: () -> str
+def make_footer() -> str:
# Generate reusable abbreviation substitutions.
# This way, we avoid bloating the generated rST with duplicate abbreviations.
# fmt: off
@@ -1391,7 +1491,7 @@ def make_footer(): # type: () -> str
# fmt: on
-def make_link(url, title): # type: (str, str) -> str
+def make_link(url: str, title: str) -> str:
match = GODOT_DOCS_PATTERN.search(url)
if match:
groups = match.groups()
@@ -1408,15 +1508,15 @@ def make_link(url, title): # type: (str, str) -> str
if title != "":
return ":doc:`" + title + " <../" + groups[0] + ">`"
return ":doc:`../" + groups[0] + "`"
- else:
- # External link, for example:
- # `http://enet.bespin.org/usergroup0.html`
- if title != "":
- return "`" + title + " <" + url + ">`__"
- return "`" + url + " <" + url + ">`__"
+
+ # External link, for example:
+ # `http://enet.bespin.org/usergroup0.html`
+ if title != "":
+ return "`" + title + " <" + url + ">`__"
+ return "`" + url + " <" + url + ">`__"
-def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str
+def sanitize_operator_name(dirty_name: str, state: State) -> str:
clear_name = dirty_name.replace("operator ", "")
if clear_name == "!=":
@@ -1474,7 +1574,7 @@ def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str
return clear_name
-def indent_bullets(text): # type: (str) -> str
+def indent_bullets(text: str) -> str:
# Take the text and check each line for a bullet point represented by "-".
# Where found, indent the given line by a further "\t".
# Used to properly indent bullet points contained in the description for enum values.
diff --git a/doc/translations/ar.po b/doc/translations/ar.po
index dcfbccb71c..43e62ecab2 100644
--- a/doc/translations/ar.po
+++ b/doc/translations/ar.po
@@ -19,12 +19,14 @@
# Hamza Kalash <mogo.gogo170@gmail.com>, 2022.
# ywmaa <ywmaa.personal@gmail.com>, 2022.
# TabbyDev <Mandomody25@gmail.com>, 2022.
+# عبد الرحمن أبو سعدة ||Abd Alrahman abo saada <abdalrahmanabs2005@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-05-31 22:35+0000\n"
-"Last-Translator: TabbyDev <Mandomody25@gmail.com>\n"
+"PO-Revision-Date: 2022-07-23 03:56+0000\n"
+"Last-Translator: عبد الرحمن أبو سعدة ||Abd Alrahman abo saada "
+"<abdalrahmanabs2005@gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/ar/>\n"
"Language: ar\n"
@@ -33,7 +35,7 @@ msgstr ""
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -1004,7 +1006,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7850,8 +7859,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10132,7 +10141,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10297,7 +10312,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11910,7 +11931,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12308,10 +12334,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 +19635,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 +19655,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 +19676,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
@@ -20325,7 +20361,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23717,7 +23753,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25554,7 +25590,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28597,13 +28633,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30018,7 +30055,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30592,10 +30632,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30607,6 +30651,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30919,6 +30969,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 ""
@@ -32638,7 +32693,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32654,7 +32709,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32684,7 +32739,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36350,7 +36405,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 +36518,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 ""
@@ -36810,7 +36873,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37073,7 +37136,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37191,6 +37254,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -37745,7 +37854,7 @@ msgstr ""
#: doc/classes/Node.xml
msgid "Nodes and Scenes"
-msgstr ""
+msgstr "العقد و المشاهد"
#: doc/classes/Node.xml
msgid "All Demos"
@@ -39888,7 +39997,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39900,7 +40015,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45531,6 +45647,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50081,8 +50204,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
@@ -54460,7 +54583,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54500,15 +54624,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55984,11 +56109,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57658,7 +57802,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58455,7 +58599,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 +59220,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
@@ -60533,8 +60703,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60599,6 +60769,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."
@@ -64161,13 +64336,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64179,13 +64355,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65995,11 +66172,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66079,8 +66256,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66687,9 +66864,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 +66896,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
@@ -71089,7 +71271,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71174,6 +71360,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/ca.po b/doc/translations/ca.po
index 8576fd5bf3..2fce9a4d08 100644
--- a/doc/translations/ca.po
+++ b/doc/translations/ca.po
@@ -960,7 +960,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7797,8 +7804,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10078,7 +10085,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10243,7 +10256,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11854,7 +11873,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12252,10 +12276,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 +19563,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 +19583,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 +19604,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
@@ -20255,7 +20289,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23644,7 +23678,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25475,7 +25509,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28516,13 +28550,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29935,7 +29970,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30509,10 +30547,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30524,6 +30566,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30835,6 +30883,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 ""
@@ -32552,7 +32605,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32568,7 +32621,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32598,7 +32651,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36235,7 +36288,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 +36399,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 ""
@@ -36690,7 +36751,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36951,7 +37012,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37065,6 +37126,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39762,7 +39869,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39774,7 +39887,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45378,6 +45492,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49925,8 +50046,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
@@ -54302,7 +54423,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54342,15 +54464,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55826,11 +55949,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57500,7 +57642,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58295,7 +58437,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 +59058,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
@@ -60365,8 +60533,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60431,6 +60599,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."
@@ -63985,13 +64157,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64003,13 +64176,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65817,11 +65991,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65901,8 +66075,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66505,9 +66679,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 +66711,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
@@ -70890,7 +71069,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70975,6 +71158,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/classes.pot b/doc/translations/classes.pot
index dba0a87744..b8187d24d5 100644
--- a/doc/translations/classes.pot
+++ b/doc/translations/classes.pot
@@ -840,7 +840,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7677,8 +7684,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9958,7 +9965,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10123,7 +10136,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11734,7 +11753,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12132,10 +12156,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 +19443,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 +19463,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 +19484,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
@@ -20135,7 +20169,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23521,7 +23555,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25352,7 +25386,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28393,13 +28427,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29812,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30386,10 +30424,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30401,6 +30443,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30712,6 +30760,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 ""
@@ -32429,7 +32482,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32445,7 +32498,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32475,7 +32528,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36112,7 +36165,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 +36276,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 ""
@@ -36567,7 +36628,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36828,7 +36889,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36942,6 +37003,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39639,7 +39746,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39651,7 +39764,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45255,6 +45369,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49802,8 +49923,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
@@ -54179,7 +54300,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54219,15 +54341,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55703,11 +55826,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57377,7 +57519,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58172,7 +58314,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 +58935,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
@@ -60242,8 +60410,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60308,6 +60476,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."
@@ -63862,13 +64034,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63880,13 +64053,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65694,11 +65868,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65778,8 +65952,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66382,9 +66556,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 +66588,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
@@ -70767,7 +70946,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70852,6 +71035,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/cs.po b/doc/translations/cs.po
index e6d0fc8c49..878b7e9aae 100644
--- a/doc/translations/cs.po
+++ b/doc/translations/cs.po
@@ -1230,8 +1230,15 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
-msgstr "Jako [method print], ale tiskne pouze pokud je použita v debug módu."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
+msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -8187,8 +8194,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10475,7 +10482,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10640,7 +10653,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -12254,7 +12273,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12653,10 +12677,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 +20011,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 +20031,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 +20052,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
@@ -20703,7 +20737,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -24101,7 +24135,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25938,7 +25972,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28986,13 +29020,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30408,7 +30443,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30982,10 +31020,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30996,6 +31038,15 @@ msgid "Mouse and input coordinates"
msgstr ""
#: doc/classes/InputEventMouseMotion.xml
+#, fuzzy
+msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+"Vrací [code]true[/code] pokud si jsou [code]a[/code] a [code]b[/code] "
+"přiblížně rovny."
+
+#: doc/classes/InputEventMouseMotion.xml
msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
@@ -31309,6 +31360,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 ""
@@ -33030,7 +33086,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33046,7 +33102,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33077,7 +33133,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36749,7 +36805,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 +36918,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 ""
@@ -37212,7 +37276,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37475,7 +37539,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37593,6 +37657,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -40293,7 +40403,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40305,7 +40421,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45947,6 +46064,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50499,8 +50623,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
@@ -54886,7 +55010,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54926,15 +55051,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56411,11 +56537,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -58086,7 +58231,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58889,7 +59034,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 +59655,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
@@ -60976,8 +61147,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -61043,6 +61214,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."
@@ -64629,13 +64805,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64647,13 +64824,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -66468,11 +66646,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66552,8 +66730,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -67164,9 +67342,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 +67374,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
@@ -71572,9 +71755,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
-msgstr "Vrátí [code] true [/code], pokud je vektor normalizován, jinak false."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -71658,6 +71844,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/de.po b/doc/translations/de.po
index 14a4d14da6..0cf8d9ae17 100644
--- a/doc/translations/de.po
+++ b/doc/translations/de.po
@@ -35,7 +35,7 @@
# spoadr <spoadr@gmx.ch>, 2021.
# Tim <tim14speckenwirth@gmail.com>, 2021.
# user <online141@gmx.de>, 2021.
-# Jummit <jummit@web.de>, 2021.
+# Jummit <jummit@web.de>, 2021, 2022.
# Bastian <bastian.ike@gmail.com>, 2021.
# KuhnChris <kuhnchris@kuhnchris.eu>, 2021.
# Rémi Verschelde <remi@godotengine.org>, 2021.
@@ -52,7 +52,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-22 23:17+0000\n"
+"PO-Revision-Date: 2022-07-23 03:56+0000\n"
"Last-Translator: Hans Peter <figefi6308@runqx.com>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/de/>\n"
@@ -61,7 +61,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.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -534,7 +534,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"
@@ -566,9 +565,9 @@ msgstr ""
"- Für [code]Array[/code]s, [code]==[/code] werden die Arrays elementweise "
"mit [code]==[/code] verglichen. Der Elemente-Vergleich ist also wieder "
"einfach, nicht tief.\n"
-"Zusammengefasst, immer wenn ein [code]Dictionary[/code] potentiell "
-"involviert ist, und du einen wahren Inhaltsvergleich brauchst, musst du "
-"[code]deep_equal[/code] verwenden."
+"Zusammengefasst, immer wenn möglicherweise ein [code]Dictionary[/code] "
+"involviert ist und du einen echten Inhaltsvergleich brauchst, verwende "
+"[code]deep_equal[/code]."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -969,7 +968,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 "
@@ -989,17 +987,24 @@ msgid ""
"To perform eased interpolation with [method lerp], combine it with [method "
"ease] or [method smoothstep]."
msgstr ""
-"Interpoliert einen normalisierten Wert linear zwischen zwei Grenzwerten. "
-"Dies entspricht der Umkehrfunktion von [method inverse_lerp].\n"
-"Wenn die [code]from[/code] und [code]to[/code] Argumente vom Typ [int] oder "
-"[float] sind, dann ist der Rückgabewert ein [float].\n"
-"Sind beide Argumente vom gleichen Typ ([Vector2], [Vector3] oder [Color]), "
-"dann ist der Rückgabewert auch von diesem Typ ([code]lerp[/code] ruft dann "
-"die Methode [code]lerp[/code] dieses Vektortyps auf).\n"
+"Interpoliert linear zwischen zwei Werten mit dem in [code]weight[/code] "
+"definierten Faktor. Um eine Interpolation durchzuführen, sollte "
+"[code]Gewicht[/code] zwischen [code]0.0[/code] und [code]1.0[/code] "
+"(einschließlich) liegen. Werte außerhalb dieses Bereichs sind jedoch "
+"zulässig und können verwendet werden, um [i]Extrapolation[/i] "
+"durchzuführen.\n"
+"Wenn die Argumente [code]von[/code] und [code]bis[/code] vom Typ [int] oder "
+"[float] sind, ist der Rückgabewert ein [float].\n"
+"Wenn beide vom gleichen Vektortyp sind ([Vector2], [Vector3] oder [Color]), "
+"ist der Rückgabewert vom gleichen Typ ([code]lerp[/code] ruft dann die "
+"Methode [code]linear_interpolate[/code] des Vektortyps auf).\n"
"[codeblock]\n"
-"lerp(0, 4, 0.75) # Returns 3.0\n"
-"lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Returns Vector2(2, 3.5)\n"
-"[/codeblock]"
+"lerp(0, 4, 0.75) # Gibt 3.0 zurück\n"
+"lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Liefert Vector2(2, 3.5)\n"
+"[/codeblock]\n"
+"Siehe auch [method inverse_lerp], die die Umkehrung dieser Operation "
+"durchführt. Um eine Interpolation mit [method lerp] durchzuführen, "
+"kombiniere sie mit [method ease] oder [method smoothstep]."
#: modules/gdscript/doc_classes/@GDScript.xml
#, fuzzy
@@ -1398,9 +1403,22 @@ msgstr ""
"Trace aus."
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+#, fuzzy
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
-"Funktioniert wie [method print], gibt jedoch nur im Debug Modues Text aus."
+"Gibt einen Stacktrace zum Quelltextort aus, funktioniert nur wenn das "
+"\"Ausführen mit Debugger\" aktiviert ist.\n"
+"Die Ausgabe in der Konsole würde ungefähr so aussehen:\n"
+"[codeblock]\n"
+"Frame 0 - res://test.gd:16 in function '_process'\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1660,6 +1678,45 @@ msgid ""
"3\n"
"[/codeblock]"
msgstr ""
+"Gibt ein Array mit dem angegebenen Bereich zurück. Die [Methode range] kann "
+"auf drei Arten aufgerufen werden:\n"
+"[code]range(n: int)[/code]: Beginnt bei 0, erhöht sich in Schritten von 1 "
+"und endet [i]vor[/i] [code]n[/code]. Das Argument [code]n[/code] ist "
+"[b]exklusiv[/b].\n"
+"[code]range(b: int, n: int)[/code]: Beginnt bei [code]b[/code], erhöht sich "
+"in Schritten von 1 und endet [i]vor[/i] [code]n[/code]. Die Argumente "
+"[code]b[/code] und [code]n[/code] sind [b]inklusive[/b] bzw. [b]exklusive[/"
+"b].\n"
+"[code]bereich(b: int, n: int, s: int)[/code]: Beginnt bei [code]b[/code], "
+"erhöht/verringert sich um Schritte von [code]s[/code] und endet [i]vor[/i] "
+"[code]n[/code]. Die Argumente [code]b[/code] und [code]n[/code] sind "
+"[b]inklusive[/b] bzw. [b]exklusive[/b]. Das Argument [code]s[/code] [b]kann[/"
+"b] negativ sein, aber nicht [code]0[/code]. Wenn [code]s[/code] [code]0[/"
+"code] ist, wird eine Fehlermeldung ausgegeben.\n"
+"Der [Methodenbereich] wandelt alle Argumente vor der Verarbeitung in [int] "
+"um.\n"
+"[b]Hinweis:[/b] Gibt ein leeres Array zurück, wenn kein Wert die "
+"Werteinschränkung erfüllt (z. B. [code]range(2, 5, -1)[/code] oder "
+"[code]range(5, 5, 1)[/code]).\n"
+"Beispiele:\n"
+"[codeblock]\n"
+"print(bereich(4)) # Gibt [0, 1, 2, 3] aus\n"
+"print(bereich(2, 5)) # Gibt [2, 3, 4] aus\n"
+"print(range(0, 6, 2)) # Gibt [0, 2, 4] aus\n"
+"print(range(4, 1, -1)) # Gibt [4, 3, 2] aus\n"
+"[/codeblock]\n"
+"Um rückwärts über ein [Array] zu iterieren, benutze:\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"
+"Ausgabe:\n"
+"[codeblock]\n"
+"9\n"
+"6\n"
+"3\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -2194,6 +2251,50 @@ msgid ""
"[code]GDScriptFunctionState[/code]. Notice [code]yield(get_tree(), "
"\"idle_frame\")[/code] from the above example."
msgstr ""
+"Stoppt die Ausführung der Funktion und gibt den aktuellen angehaltenen "
+"Zustand an die aufrufende Funktion zurück.\n"
+"Rufe vom Aufrufer [Methode GDScriptFunctionState.resume] von dem Zustand "
+"auf, um die Ausführung wieder aufzunehmen. Dadurch wird der Zustand "
+"ungültig. Innerhalb der wiederaufgenommenen Funktion gibt [code]yield()[/"
+"code] das zurück, was an den Funktionsaufruf [code]resume()[/code] übergeben "
+"wurde.\n"
+"Wenn ein Objekt und ein Signal übergeben werden, wird die Ausführung "
+"fortgesetzt, wenn das Objekt das angegebene Signal aussendet. In diesem Fall "
+"gibt [code]yield()[/code] das an [code]emit_signal()[/code] übergebene "
+"Argument zurück, wenn das Signal nur ein Argument benötigt, oder ein Array "
+"mit allen an [code]emit_signal()[/code] übergebenen Argumenten, wenn das "
+"Signal mehrere Argumente benötigt.\n"
+"[code]yield[/code] kann auch verwendet werden um auf das Ende einer Funktion "
+"zu warten:\n"
+"[codeblock]\n"
+"func _ready():\n"
+" yield(countdown(), \"completed\") # Warten auf die Beendigung der "
+"Funktion countdown()\n"
+" print('Fertig')\n"
+"\n"
+"func countdown():\n"
+" yield(get_tree(), \"idle_frame\") # gibt ein GDScriptFunctionState "
+"Objekt an _ready() zurück\n"
+" print(3)\n"
+" yield(get_tree().create_timer(1.0), \"timeout\")\n"
+" print(2)\n"
+" yield(get_tree().create_timer(1.0), \"timeout\")\n"
+" print(1)\n"
+" yield(get_tree().create_timer(1.0), \"timeout\")\n"
+"\n"
+"# gibt aus:\n"
+"# 3\n"
+"# 2\n"
+"# 1\n"
+"# bereit\n"
+"[/codeblock]\n"
+"Beim Yielding einer Funktion wird das Signal [code]completed[/code] "
+"automatisch ausgegeben, wenn die Funktion zurückkehrt. Es kann daher als "
+"[code]signal[/code] Parameter der [code]yield[/code] Methode verwendet "
+"werden, um fortzufahren.\n"
+"Um eine Funktion zu beenden, sollte die resultierende Funktion auch einen "
+"[code]GDScriptFunctionState[/code] zurückgeben. Beachte "
+"[code]yield(get_tree(), \"idle_frame\")[/code] aus dem obigen Beispiel."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -3946,6 +4047,8 @@ msgid ""
"MIDI aftertouch message. This message is most often sent by pressing down on "
"the key after it \"bottoms out\"."
msgstr ""
+"MIDI-Aftertouch-Meldung. Diese Meldung wird meistens durch Drücken der Taste "
+"nachdem sie den Tiefpunkt erreicht hat gesendet."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -3961,6 +4064,8 @@ msgid ""
"MIDI program change message. This message sent when the program patch number "
"changes."
msgstr ""
+"MIDI-Programmwechselmeldung. Diese Meldung wird gesendet, wenn sich die "
+"Programm-Patch-Nummer ändert."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -3968,12 +4073,18 @@ 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 ""
+"MIDI-Kanal-Druckmeldung. Diese Meldung wird meistens durch Drücken der Taste "
+"nachdem sie den Tiefpunkt erreicht hat gesendet.Diese Meldung unterscheidet "
+"sich von der polyphonen Aftertouch-Meldung, da sie den höchsten Druck über "
+"alle Tasten hinweg anzeigt."
#: doc/classes/@GlobalScope.xml
msgid ""
"MIDI pitch bend message. This message is sent to indicate a change in the "
"pitch bender (wheel or lever, typically)."
msgstr ""
+"MIDI-Pitch-Bend-Meldung. Diese Meldung wird gesendet, um eine Änderung des "
+"Pitch-Benders (typischerweise Rad oder Hebel) anzuzeigen."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -9731,8 +9842,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -12026,7 +12137,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -12192,7 +12309,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -13821,7 +13944,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -14222,10 +14350,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 +21833,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 +21853,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 +21874,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
@@ -22421,7 +22559,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -25839,7 +25977,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -27681,7 +27819,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -30768,13 +30906,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -31765,7 +31904,7 @@ msgstr ""
#: doc/classes/Input.xml
msgid "A singleton that deals with inputs."
-msgstr ""
+msgstr "Ein Singleton, der sich mit Inputs befasst."
#: doc/classes/Input.xml
msgid ""
@@ -31774,6 +31913,11 @@ msgid ""
"set in the [b]Input Map[/b] tab in the [b]Project > Project Settings[/b], or "
"with the [InputMap] class."
msgstr ""
+"Ein Singleton, das sich mit Inputs befasst. Dazu gehören Tastendrucke, "
+"Maustasten und -bewegungen, Joypads und Eingabeaktionen. Aktionen und ihre "
+"Ereignisse können auf der Registerkarte [b]Eingabe-Zuordnung[/b] unter "
+"[b]Projekt > Projekteinstellungen[/b] oder mit der Klasse [InputMap] "
+"festgelegt werden."
#: doc/classes/Input.xml
msgid "Inputs tutorial index"
@@ -32005,6 +32149,20 @@ msgid ""
"[url=$DOCS_URL/tutorials/inputs/input_examples.html#keyboard-events]Input "
"examples[/url] in the documentation for more information."
msgstr ""
+"Gibt [code]true[/code] aus, wenn Sie das Aktionsereignis drücken. Beachten "
+"Sie, dass, wenn einer Aktion mehrere Tasten zugewiesen sind und mehr als "
+"eine von ihnen gedrückt wird, das Loslassen einer Taste die Aktion auslöst, "
+"selbst wenn eine andere Taste, die dieser Aktion zugewiesen ist, noch "
+"gedrückt ist.\n"
+"Wenn [code]exact[/code] [code] false[/code] ist, werden zusätzliche "
+"Eingabemodifikatoren für die Ereignisse [InputEventKey] und "
+"[InputEventMouseButton] sowie die Richtung für die Ereignisse "
+"[InputEventJoypadMotion] ignoriert.\n"
+"[b]Hinweis:[/b] Aufgrund von Tastatur-Ghosting kann [method "
+"is_action_pressed] [code]false[/code] zurückgeben, auch wenn eine der Tasten "
+"der Aktion gedrückt ist. Siehe [url=$DOCS_URL/tutorials/inputs/"
+"input_examples.html#keyboard-events]Eingabebeispiele[/url] in der "
+"Dokumentation für weitere Informationen."
#: doc/classes/Input.xml
#, fuzzy
@@ -32199,7 +32357,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -32773,10 +32934,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -32787,6 +32952,14 @@ msgid "Mouse and input coordinates"
msgstr ""
#: doc/classes/InputEventMouseMotion.xml
+#, fuzzy
+msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+"Liefert [code]true[/code] wenn die Länge der Zeichenkette [code]0[/code] ist."
+
+#: doc/classes/InputEventMouseMotion.xml
msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
@@ -33104,6 +33277,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 ""
@@ -34868,7 +35046,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -34884,7 +35062,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -34920,7 +35098,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -38619,7 +38797,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 +38912,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 ""
@@ -39089,7 +39275,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -39356,7 +39542,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -39477,6 +39663,53 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+#, fuzzy
+msgid "Set the max packet size that this peer can handle."
+msgstr "Gibt das AnimationNode mit dem gegebenen Namen zurück."
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -42180,7 +42413,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -42192,7 +42431,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -47875,6 +48115,14 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+#, fuzzy
+msgid "Sorts the elements of the array in ascending order."
+msgstr "Entfernt das Element der Arrays dessen Position übergeben wurde."
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -52484,8 +52732,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
@@ -56926,7 +57174,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56966,15 +57215,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -58462,11 +58712,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -60157,7 +60426,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -60981,7 +61250,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 +61875,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
@@ -63091,8 +63386,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -63158,6 +63453,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."
@@ -66784,13 +67084,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -66802,13 +67103,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -68770,11 +69072,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -68854,8 +69156,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -69471,9 +69773,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 +69808,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
@@ -73949,9 +74256,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
-msgstr "Wenn [code]true[/code], wird die Textur zentriert."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -74035,6 +74345,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/el.po b/doc/translations/el.po
index 782205fcfa..87eee32604 100644
--- a/doc/translations/el.po
+++ b/doc/translations/el.po
@@ -855,7 +855,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7694,8 +7701,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9976,7 +9983,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10141,7 +10154,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11754,7 +11773,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12152,10 +12176,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 +19478,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 +19498,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 +19519,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
@@ -20170,7 +20204,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23562,7 +23596,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25399,7 +25433,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28442,13 +28476,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29863,7 +29898,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30437,10 +30475,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30452,6 +30494,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30764,6 +30812,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 ""
@@ -32483,7 +32536,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32499,7 +32552,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32529,7 +32582,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36189,7 +36242,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 +36355,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 ""
@@ -36649,7 +36710,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36912,7 +36973,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37030,6 +37091,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39727,7 +39834,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39739,7 +39852,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45357,6 +45471,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49907,8 +50028,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
@@ -54286,7 +54407,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54326,15 +54448,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55810,11 +55933,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57484,7 +57626,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58281,7 +58423,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 +59044,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
@@ -60359,8 +60527,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60425,6 +60593,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."
@@ -63987,13 +64160,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64005,13 +64179,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65821,11 +65996,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65905,8 +66080,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66513,9 +66688,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 +66720,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
@@ -70915,7 +71095,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71000,6 +71184,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/es.po b/doc/translations/es.po
index 242710fe39..f9d008c41a 100644
--- a/doc/translations/es.po
+++ b/doc/translations/es.po
@@ -1380,9 +1380,22 @@ msgstr ""
"mientras muestra un trazo de cuando un error o advertencia se muestra."
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+#, fuzzy
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
-"Como [method print], pero imprime sólo cuando se usa en modo de depuración."
+"Imprime una registro de la pila en la ubicación del código, sólo funciona "
+"cuando se ejecuta con el depurador activado.\n"
+"La salida en la consola se vería algo así:\n"
+"[codeblock]\n"
+"Frame 0 - res://test.gd:16 in function '_process'\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -10108,8 +10121,8 @@ msgstr ""
#, fuzzy
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -13142,8 +13155,14 @@ msgstr ""
"escena."
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
-msgstr "El bus en el que se está reproduciendo este audio."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
+msgstr ""
#: doc/classes/AudioStreamPlayer.xml
msgid ""
@@ -13329,9 +13348,14 @@ msgstr ""
"escena."
#: doc/classes/AudioStreamPlayer3D.xml
-#, fuzzy
-msgid "The bus on which this audio is playing."
-msgstr "El bus en el que se está reproduciendo este audio."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
+msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
msgid ""
@@ -15364,10 +15388,13 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
-"Si [code]true[/code], el ancestro [Viewport] está actualmente usando esta "
-"cámara."
#: doc/classes/Camera.xml
msgid ""
@@ -15915,10 +15942,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 +25600,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 +25622,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 +25641,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 +25654,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 +25667,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 "
@@ -26596,10 +26634,11 @@ msgstr ""
"save_to_file]."
#: doc/classes/EditorFeatureProfile.xml
+#, fuzzy
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
"Guarda el perfil de características del editor en un archivo en formato "
"JSON. Luego puede ser importado usando el botón [b]Import[/b] del "
@@ -31128,9 +31167,10 @@ msgid "The default exposure used for tonemapping."
msgstr "La exposición predeterminada que se utiliza para el mapeo de tonos."
#: doc/classes/Environment.xml
+#, fuzzy
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
"El modo de mapeo de tonos a utilizar. El \"tonemapping\" es el proceso que "
@@ -33557,9 +33597,10 @@ msgstr ""
"puntos finales."
#: doc/classes/Geometry.xml
+#, fuzzy
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -37667,13 +37708,14 @@ msgstr "Número máximo de redirecciones permitidas."
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -39542,7 +39584,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]enabled[/i] by default. It is "
+"recommended to keep it enabled 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 +40346,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -40327,6 +40376,15 @@ msgid "Mouse and input coordinates"
msgstr "Medio desplazamiento en la coordenada X."
#: doc/classes/InputEventMouseMotion.xml
+#, fuzzy
+msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+"Devuelve el número de disposiciones del teclado.\n"
+"[b]Nota:[/b] Este método está implementado en Linux, macOS y Windows."
+
+#: doc/classes/InputEventMouseMotion.xml
msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
@@ -40745,6 +40803,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."
@@ -43007,7 +43071,7 @@ msgstr "La altura del cilindro."
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -43033,7 +43097,7 @@ msgstr "El tamaño del ancho de un píxel en el sprite para escalarlo en 3D."
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -43080,7 +43144,7 @@ msgstr "Si se ajusta, las luces del entorno afectan al sprite."
#: doc/classes/Label3D.xml
#, fuzzy
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
"Si se fija, la textura puede ser vista desde atrás también, si no, es "
@@ -47706,7 +47770,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 +47885,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 ""
@@ -48200,7 +48272,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -48523,7 +48595,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -48649,6 +48721,54 @@ msgstr ""
msgid "Control activation of this server."
msgstr "Traducción local de este nodo."
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+#, fuzzy
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr "Devuelve el estado actual de la conexión. Ver [enum ConnectionStatus]."
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+#, fuzzy
+msgid "Set the max packet size that this peer can handle."
+msgstr "Establece la piel que se utilizará en esta instancia."
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -52571,8 +52691,14 @@ msgid "See [enum ShadowDetail]."
msgstr "Ver [enum ShadowMode]."
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
-msgstr "Ver [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
+msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
@@ -52583,9 +52709,11 @@ msgstr ""
"que [constant SHADOW_CUBE], pero de menor calidad."
#: doc/classes/OmniLight.xml
+#, fuzzy
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
"Las sombras se representan en un mapa de cubos. Más lento que [constant "
"SHADOW_DUAL_PARABOLOID], pero de mayor calidad."
@@ -60048,6 +60176,14 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr "Cambia el byte en el índice dado."
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+#, fuzzy
+msgid "Sorts the elements of the array in ascending order."
+msgstr "Elimina un elemento del array por indice."
+
#: doc/classes/PoolByteArray.xml
#, fuzzy
msgid ""
@@ -65718,12 +65854,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 ""
@@ -71412,7 +71549,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -71452,15 +71590,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -73276,11 +73415,41 @@ msgstr ""
#: doc/classes/Spatial.xml
#, fuzzy
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+"Parte de la rotación de la transformación local en radianes, especificada en "
+"términos de ángulos YXZ-Euler en el formato (ángulo X, ángulo Y, ángulo Z).\n"
+"[b]Nota:[/b] En el sentido matemático, la rotación es una matriz y no un "
+"vector. Los tres ángulos de Euler, que son los tres parámetros "
+"independientes de la parametrización del ángulo de Euler de la matriz de "
+"rotación, se almacenan en una estructura de datos [Vector3] no porque la "
+"rotación sea un vector, sino sólo porque el [Vector3] existe como una "
+"estructura de datos conveniente para almacenar 3 números reales. Por lo "
+"tanto, la aplicación de operaciones afines en el \"vector\" de rotación no "
+"es significativa."
+
+#: doc/classes/Spatial.xml
+#, fuzzy
msgid "World space (global) [Transform] of this node."
msgstr "World3D espacio (global) [Transform] de este nodo."
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -75414,7 +75583,7 @@ msgstr "El tamaño del ancho de un píxel en el sprite para escalarlo en 3D."
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -76413,10 +76582,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 +77377,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."
@@ -79096,8 +79286,8 @@ msgstr "Establece el texto para una línea específica."
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -79173,6 +79363,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."
@@ -83714,15 +83909,18 @@ msgstr ""
"elementos pueden establecerse utilizando [method set_item_metadata]."
#: doc/classes/TreeItem.xml
+#, fuzzy
msgid ""
-"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."
msgstr ""
"Devuelve el siguiente TreeItem del árbol o un objeto nulo si no hay ninguno."
#: doc/classes/TreeItem.xml
+#, fuzzy
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -83738,15 +83936,18 @@ msgid "Returns the parent TreeItem or a null object if there is none."
msgstr "Devuelve el TreeItem padre o un objeto nulo si no hay ninguno."
#: doc/classes/TreeItem.xml
+#, fuzzy
msgid ""
-"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."
msgstr ""
"Devuelve el TreeItem anterior del árbol o un objeto nulo si no hay ninguno."
#: doc/classes/TreeItem.xml
+#, fuzzy
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -86246,11 +86447,11 @@ msgstr ""
#, fuzzy
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -86374,8 +86575,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
#, fuzzy
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -87155,12 +87356,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 +87400,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 ""
@@ -92915,9 +93121,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr "Establece la matriz de transformación global del Viewport."
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
-msgstr "Si [code]true[/code], el canvas del viewport no se renderiza."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -93025,6 +93234,15 @@ msgstr ""
"ViewportUpdateMode] para las opciones."
#: doc/classes/VisualServer.xml
+msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
#, fuzzy
msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
diff --git a/doc/translations/fa.po b/doc/translations/fa.po
index a8972b49a5..7416d80072 100644
--- a/doc/translations/fa.po
+++ b/doc/translations/fa.po
@@ -1269,8 +1269,15 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
-msgstr "شبیه متد چاپ، اما چاپ کردن تنها در حالت اشکال زدایی Ø§Ø³ØªÙØ§Ø¯Ù‡ میشود."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
+msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -8118,8 +8125,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10399,7 +10406,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10564,7 +10577,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -12175,7 +12194,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12573,10 +12597,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 +19884,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 +19904,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 +19925,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
@@ -20576,7 +20610,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23965,7 +23999,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25796,7 +25830,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28837,13 +28871,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30256,7 +30291,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30830,10 +30868,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30845,6 +30887,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -31156,6 +31204,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 ""
@@ -32873,7 +32926,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32889,7 +32942,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32919,7 +32972,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36562,7 +36615,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 +36726,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 ""
@@ -37017,7 +37078,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37278,7 +37339,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37392,6 +37453,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -40089,7 +40196,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40101,7 +40214,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45717,6 +45831,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50264,8 +50385,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
@@ -54645,7 +54766,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54685,15 +54807,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56169,11 +56292,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57843,7 +57985,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58638,7 +58780,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 +59401,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
@@ -60708,8 +60876,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60774,6 +60942,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."
@@ -64328,13 +64500,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64346,13 +64519,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -66160,11 +66334,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66244,8 +66418,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66848,9 +67022,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 +67054,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
@@ -71233,7 +71412,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71318,6 +71501,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/fi.po b/doc/translations/fi.po
index 9c41935f5e..b1d940aa14 100644
--- a/doc/translations/fi.po
+++ b/doc/translations/fi.po
@@ -922,7 +922,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7767,8 +7774,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10049,7 +10056,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10214,7 +10227,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11828,7 +11847,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12226,10 +12250,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 +19554,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 +19574,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 +19595,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
@@ -20246,7 +20280,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23638,7 +23672,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25475,7 +25509,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28525,13 +28559,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29946,7 +29981,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30520,10 +30558,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30535,6 +30577,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30847,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 ""
@@ -32566,7 +32619,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32582,7 +32635,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32612,7 +32665,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36274,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 "
@@ -36387,6 +36440,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 ""
@@ -36734,7 +36795,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36997,7 +37058,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37115,6 +37176,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39812,7 +39919,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39824,7 +39937,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45442,6 +45556,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49992,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
@@ -54371,7 +54492,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54411,15 +54533,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55896,11 +56019,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57571,7 +57713,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58368,7 +58510,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 +59131,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
@@ -60447,8 +60615,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60513,6 +60681,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."
@@ -64077,13 +64250,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64095,13 +64269,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65914,11 +66089,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65998,8 +66173,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66606,9 +66781,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 +66813,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
@@ -71010,7 +71190,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71095,6 +71279,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/fil.po b/doc/translations/fil.po
index 1ae1d0b02b..42ab5537f4 100644
--- a/doc/translations/fil.po
+++ b/doc/translations/fil.po
@@ -856,7 +856,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7693,8 +7700,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9974,7 +9981,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10139,7 +10152,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11750,7 +11769,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12148,10 +12172,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 +19459,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 +19479,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 +19500,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
@@ -20151,7 +20185,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23540,7 +23574,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25371,7 +25405,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28412,13 +28446,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29831,7 +29866,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30405,10 +30443,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30420,6 +30462,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30731,6 +30779,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 ""
@@ -32448,7 +32501,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32464,7 +32517,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32494,7 +32547,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36131,7 +36184,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 +36295,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 ""
@@ -36586,7 +36647,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36847,7 +36908,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36961,6 +37022,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39658,7 +39765,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39670,7 +39783,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45274,6 +45388,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49821,8 +49942,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
@@ -54198,7 +54319,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54238,15 +54360,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55722,11 +55845,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57396,7 +57538,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58191,7 +58333,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 +58954,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
@@ -60261,8 +60429,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60327,6 +60495,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."
@@ -63881,13 +64053,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63899,13 +64072,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65713,11 +65887,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65797,8 +65971,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66401,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
@@ -66432,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
@@ -70786,7 +70965,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70871,6 +71054,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/fr.po b/doc/translations/fr.po
index 2dcac4940b..44d40e1bd5 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-08-04 05:23+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"
@@ -70,7 +70,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -548,7 +548,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"
@@ -574,15 +573,15 @@ msgstr ""
"- Pour [code]null[/code], [code]int[/code], [code]float[/code], "
"[code]String[/code], [code]Object[/code] et [code]RID[/code], les résultats "
"de [code]deep_equal[/code] et [code]==[/code] sont les mêmes.\n"
-"- Pour [code]Dictionary[/code], [code]==[/code] considère que l'égalité est "
-"respéctée si et seulement si les deux variables pointent vers le même "
-"[code]Dictionary[/code], sans recursion ou connaissance du contenu des "
+"- Pour les [code]Dictionary[/code], [code]==[/code] considère que l'égalité "
+"est respectée si et seulement si les deux variables pointent vers le même "
+"[code]Dictionary[/code], sans récursion ou comparaison du contenu des "
"variables.\n"
-"- For [code]Array[/code], [code]==[/code] considère que l'égalité est "
-"respéctée si et seulement si chaque élement du premier [code]Tableau[/code] "
+"- Pour les [code]Array[/code], [code]==[/code] considère que l'égalité est "
+"respectée si et seulement si chaque élément du premier [code]Array[/code] "
"est égal à l'élément au même index du second [code]Array[/code], évalué par "
-"[code]==[/code] lui même. Cela implique que [code]==[/code] recurses dans un "
-"[code]Array[/code], mais pas dans un [code]Dictionary[/code].\n"
+"[code]==[/code] lui-même. Cela implique un récursion avec [code]==[/code] "
+"pour les [code]Array[/code], mais pas les [code]Dictionary[/code].\n"
"Rapidement, dès qu'un [code]Dictionary[/code] est potentiellement impliqué, "
"si une vraie comparaison du contenu est souhaité, il faut utiliser "
"[code]deep_equal[/code]."
@@ -608,7 +607,6 @@ msgstr ""
"nouveau en une instance. Utile pour la désérialisation."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns an \"eased\" value of [code]x[/code] based on an easing function "
"defined with [code]curve[/code]. This easing function is based on an "
@@ -634,13 +632,15 @@ msgstr ""
"nombre à virgule flottante, avec des valeurs spécifiques conduisant aux "
"comportements suivants:\n"
"[codeblock]\n"
-"- Inférieur à -1.0 (exclusif): Ease in-out\n"
-"- 1.0: Linéaire\n"
-"- Entre -1.0 et 0.0 (exclusif): Ease out-in\n"
-"- 0.0: Constante\n"
-"- Entre 0.0 et 1.0 (exclusif): Ease in\n"
-"- 1.0: Linéaire\n"
-"- Supérieur à 1.0 (exclusif): Ease out\n"
+"- Inférieur à -1.0 (exclus) : Plus lent au début et à la fin (\"ease in-out\""
+")\n"
+"- 1.0 : Linéaire\n"
+"- Entre -1.0 et 0.0 (exclus) : Plus rapide au début et à la fin (\"ease out-"
+"in\")\n"
+"- 0.0 : Constante\n"
+"- Entre 0.0 et 1.0 (exclus) : Plus lent au début (\"ease in\")\n"
+"- 1.0 : Linéaire\n"
+"- Supérieur à 1.0 (exclus) : Plus lent à la fin (\"ease out\")\n"
"[/codeblock]\n"
"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/"
"ease_cheatsheet.png]ease() curve values cheatsheet[/url]\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"
@@ -1421,9 +1423,22 @@ msgstr ""
"ou un avertissement est affiché."
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
-"Comme [method print], mais ne s'affiche que lorsqu'utilisé en mode débogage."
+"Comme [method prunt], mais inclus la frame de la pile actuelle quand le "
+"débogueur est activé.\n"
+"La sortie dans la console ressemblerait à ceci :\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1809,7 +1824,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns the result of smoothly interpolating the value of [code]s[/code] "
"between [code]0[/code] and [code]1[/code], based on the where [code]s[/code] "
@@ -1835,25 +1849,26 @@ msgid ""
"-1.6521) return values[/url]"
msgstr ""
"Retourne le résultat de l'interpolation douce de la valeur [code]s[/code] "
-"entre [code]0[/code] et [code]1[/code], basée sur la position de [code]s[/"
-"code] entre [code]from[/code] et [code]to[/code].\n"
-"La valeur de retour est [code]0[/code] si [code]s <= from[/code], et "
+"entre [code]0[/code] et [code]1[/code], basée sur la position de "
+"[code]s[/code] entre [code]from[/code] et [code]to[/code].\n"
+"La valeur retournée est [code]0[/code] si [code]s <= from[/code], et "
"[code]1[/code] si [code]s >= to[/code]. Si [code]s[/code] se trouve entre "
"[code]from[/code] et [code]to[/code], la valeur retournée suit une courbe en "
-"S qui représente les positions de [code]s[/code] entre[code]0[/code] and "
+"S qui représente les positions de [code]s[/code] entre[code]0[/code] et "
"[code]1[/code].\n"
-"Cette courbe en S est l'interpolateur cubique d'Hermite, obtenu par "
-"[code]f(y) = 3*y^2 - 2*y^3[/code] où [code]y = (x-from) / (to-from)[/code].\n"
-"[codeblock]\n"
-"smoothstep(0, 2, -5.0) # Renvoie 0.0\n"
-"smoothstep(0, 2, 0.5) # Renvoie 0.15625\n"
-"smoothstep(0, 2, 1.0) # Renvoie 0.5\n"
-"smoothstep(0, 2, 2.0) # Renvoie 1.0\n"
+"Cette courbe en S est l'interpolation cubique d'Hermite, obtenu par la "
+"fonction mathématique [code]f(y) = 3*y^2 - 2*y^3[/code] où [code]y = (x-from)"
+" / (to-from)[/code].\n"
+"[codeblock]\n"
+"smoothstep(0, 2, -5.0) # Retourne 0.0\n"
+"smoothstep(0, 2, 0.5) # Retourne 0.15625\n"
+"smoothstep(0, 2, 1.0) # Retourne 0.5\n"
+"smoothstep(0, 2, 2.0) # Retourne 1.0\n"
"[/codeblock]\n"
-"Comparé à [method ease] avec une valeur de courbe de [code]-1.6521[/code], "
-"[method smoothstep] retourne la courbe la plus douce possible sans change "
-"brusque dans la dérivée. Si vous avez besoin d'effectuer des transitions "
-"plus avancées, utilisez [Tween] ou [AnimationPlayer].\n"
+"Comparé à l'utilisateur [method ease] avec une valeur de courbe de [code]-1."
+"6521[/code], [method smoothstep] retourne la courbe la plus douce possible, "
+"sans changement brusque de dérivée. Si vous avez besoin d'effectuer des "
+"transitions plus avancées, utilisez [Tween] ou [AnimationPlayer].\n"
"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/"
"smoothstep_ease_comparison.png]Comparaison entre les valeurs retournées par "
"smoothstep() et ease(x, -1.6521)[/url]"
@@ -4060,6 +4075,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 +4093,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 +4108,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."
@@ -4475,13 +4510,12 @@ msgstr ""
"les couches de physique 2D optionnellement nommées."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid ""
"Hints that an integer property is a bitmask using the optionally named 2D "
"navigation layers."
msgstr ""
-"Indique qu'une propriété nombre entier est un masque de bits utilisant les "
-"couches de rendu 2D optionnellement nommées."
+"Indique qu'une propriété de nombre entier est un masque de bits indiquant "
+"des calques de navigation 2D, qui peuvent être nommées."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4500,13 +4534,12 @@ msgstr ""
"couches de physique 3D optionnellement nommées."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid ""
"Hints that an integer property is a bitmask using the optionally named 3D "
"navigation layers."
msgstr ""
-"Indique qu'une propriété nombre entier est un masque de bits utilisant les "
-"couches de rendu 2D optionnellement nommées."
+"Indique qu'une propriété de nombre entier est un masque de bits indiquant "
+"des calques de navigation 3D, qui peuvent être nommées."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4625,9 +4658,10 @@ msgid "The property is a translatable string."
msgstr "La propriété est une chaîne de caractères traduisible."
#: doc/classes/@GlobalScope.xml
-#, fuzzy
msgid "Used to group properties together in the editor. See [EditorInspector]."
-msgstr "Utilisé pour rassembler des propriétés ensemble dans l'éditeur."
+msgstr ""
+"Utilisé pour rassembler des propriétés ensemble dans l'éditeur. Voir "
+"[EditorInspector]."
#: doc/classes/@GlobalScope.xml
msgid "Used to categorize properties together in the editor."
@@ -5206,7 +5240,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 +5247,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."
@@ -5407,10 +5442,11 @@ msgid "Maximum value for the mode enum."
msgstr "Valeur maximale pour le mode énumeration."
#: doc/classes/AnimatedSprite.xml
-#, fuzzy
msgid ""
"Sprite node that contains multiple textures as frames to play for animation."
-msgstr "Nœud de sprite qui peut utiliser plusieurs textures pour l'animation."
+msgstr ""
+"Le nœud de sprite qui peut utiliser plusieurs textures pour jouer une "
+"animation."
#: doc/classes/AnimatedSprite.xml
msgid ""
@@ -7336,7 +7372,7 @@ msgstr "Le type de transition."
#: doc/classes/AnimationNodeStateMachineTransition.xml
msgid "The time to cross-fade between this state and the next."
-msgstr ""
+msgstr "La durée du fondu entre cet état et le suivant."
#: doc/classes/AnimationNodeStateMachineTransition.xml
msgid "Emitted when [member advance_condition] is changed."
@@ -7479,9 +7515,8 @@ msgstr ""
"processus."
#: doc/classes/AnimationPlayer.xml
-#, fuzzy
msgid "Animation tutorial index"
-msgstr "Nœud d'animation."
+msgstr ""
#: doc/classes/AnimationPlayer.xml
msgid ""
@@ -8063,9 +8098,8 @@ msgstr ""
"connectés à l'emplacement spécifié.."
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid "Returns the blend amount of a Blend2 node given its name."
-msgstr "Retourne le nombre de clés d'une piste donnée."
+msgstr ""
#: doc/classes/AnimationTreePlayer.xml
msgid ""
@@ -8093,9 +8127,8 @@ msgstr ""
"code]. Les enfants modifiés du node's continuent d'être animés."
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid "Returns the blend amount of a Blend3 node given its name."
-msgstr "Retourne le nombre de clés d'une piste donnée."
+msgstr ""
#: doc/classes/AnimationTreePlayer.xml
msgid ""
@@ -8116,9 +8149,8 @@ msgstr ""
"de B+ est à 0. À 1, la sortie est l'entrée B+."
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid "Returns the blend amount of a Blend4 node given its name."
-msgstr "Retourne le nombre de clés d'une piste donnée."
+msgstr ""
#: doc/classes/AnimationTreePlayer.xml
msgid ""
@@ -8150,9 +8182,8 @@ msgid "Returns a [PoolStringArray] containing the name of all nodes."
msgstr "Retourne un [PoolStringArray] contenant le nom de tous les nœuds."
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid "Returns the mix amount of a Mix node given its name."
-msgstr "Retourne le nombre de clés d'une piste donnée."
+msgstr ""
#: doc/classes/AnimationTreePlayer.xml
msgid ""
@@ -8198,23 +8229,20 @@ msgstr ""
"position."
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid "Returns the autostart delay of a OneShot node given its name."
-msgstr "Retourne la valeur d'une clé donnée dans une piste donnée."
+msgstr ""
#: doc/classes/AnimationTreePlayer.xml
msgid "Returns the autostart random delay of a OneShot node given its name."
msgstr ""
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid "Returns the fade in time of a OneShot node given its name."
-msgstr "Retourne le nom du nœud d'animation donné."
+msgstr ""
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid "Returns the fade out time of a OneShot node given its name."
-msgstr "Retourne la valeur d'une clé donnée dans une piste donnée."
+msgstr ""
#: doc/classes/AnimationTreePlayer.xml
msgid "Returns whether a OneShot node will auto restart given its name."
@@ -8328,26 +8356,25 @@ msgstr ""
"transition nommé [code]id[/code]."
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid ""
"Returns the index of the currently evaluated input for the transition node "
"with name [code]id[/code]."
msgstr ""
-"Retourne la distance la plus courte de l'avion à la position [code]point [/"
-"code]."
#: doc/classes/AnimationTreePlayer.xml
msgid ""
"Returns the number of inputs for the transition node with name [code]id[/"
"code]. You can add inputs by right-clicking on the transition node."
msgstr ""
+"Retourne le nombre d'entrées pour le nœud de transition nommé [code]id[/"
+"code]. Vous pouvez ajouter des entrées en faisant un clic droit sur le nœud "
+"de transition."
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid ""
"Returns the cross fade time for the transition node with name [code]id[/"
"code]."
-msgstr "Retourne le nom du nœud à [code]idx[/code]."
+msgstr ""
#: doc/classes/AnimationTreePlayer.xml
msgid ""
@@ -8355,21 +8382,23 @@ msgid ""
"transition node with name [code]id[/code] is set to automatically advance to "
"the next input upon completion."
msgstr ""
+"Retourne [code]true[/code] si l'entrée [code]input_idx[/code] du nœud de "
+"transition nommé [code]id[/code] est définie pour avancer automatiquement "
+"vers la prochaine entrée dès que la transition se termine."
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid ""
"The transition node with name [code]id[/code] sets its current input at "
"[code]input_idx[/code]."
msgstr ""
-"Change la position de l'index de la piste [code]idx[/code] à celui définie "
-"par [code]to_idx[/code]."
#: doc/classes/AnimationTreePlayer.xml
msgid ""
"The transition node with name [code]id[/code] advances to its next input "
"automatically when the input at [code]input_idx[/code] completes."
msgstr ""
+"Le nœud de transition nommé [code]id[/code] avance à sa prochaine entrée "
+"automatiquement lorsque l'entrée [code]input_idx[/code] se termine."
#: doc/classes/AnimationTreePlayer.xml
msgid ""
@@ -8380,13 +8409,10 @@ msgstr ""
"nommé [code]id[/code]."
#: doc/classes/AnimationTreePlayer.xml
-#, fuzzy
msgid ""
"The transition node with name [code]id[/code] sets its cross fade time to "
"[code]time_sec[/code]."
msgstr ""
-"Change la position de l'index de la piste [code]idx[/code] à celui définie "
-"par [code]to_idx[/code]."
#: doc/classes/AnimationTreePlayer.xml
msgid ""
@@ -8408,6 +8434,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."
@@ -8463,6 +8493,10 @@ msgid ""
"exiting. Can also alter or override local physics parameters (gravity, "
"damping) and route audio to custom audio buses."
msgstr ""
+"La zone 3D qui détecte nœuds [CollisionObject] qui se chevauchent, entrent "
+"ou sortent. Peut également modifier ou surcharger les paramètres de physique "
+"locale (gravité, amortissement) et passer l'audio à des bus audio "
+"personnalisés."
#: doc/classes/Area.xml doc/classes/QuadMesh.xml doc/classes/Viewport.xml
#: doc/classes/ViewportTexture.xml
@@ -8543,6 +8577,10 @@ msgid ""
"See [member ProjectSettings.physics/3d/default_angular_damp] for more "
"details about damping."
msgstr ""
+"La vitesse à laquelle les objets s'arrêtent de tourner dans cette zone. "
+"Représente la vitesse angulaire perdue par seconde.\n"
+"Voir [member ProjectSettings.physics/3d/default_angular_damp] pour plus de "
+"détails sur l'amortissement."
#: doc/classes/Area.xml doc/classes/Area2D.xml
msgid "The name of the area's audio bus."
@@ -8592,6 +8630,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."
@@ -8650,6 +8692,9 @@ msgid ""
"be set to [code]true[/code].\n"
"[code]area[/code] the other Area."
msgstr ""
+"Émis quand une autre Area entre dans cette zone. Nécessite [member "
+"monitoring] d'être défini à [code]true[/code].\n"
+"[code]area[/code] l'autre Area."
#: doc/classes/Area.xml
msgid ""
@@ -8657,6 +8702,9 @@ msgid ""
"be set to [code]true[/code].\n"
"[code]area[/code] the other Area."
msgstr ""
+"Émis quand une autre Area quitte cette Area. Nécessite [member monitoring] "
+"d'être défini à [code]true[/code].\n"
+"[code]area[/code] l'autre Area."
#: doc/classes/Area.xml
msgid ""
@@ -8824,6 +8872,14 @@ msgid ""
"list is modified once during the physics step, not immediately after objects "
"are moved. Consider using signals instead."
msgstr ""
+"Retourne la liste des intersections entre les [PhysiqueBody2D]. Le calque "
+"[member CollisionObject2D.collision_layer] du corps entrant en intersection "
+"doit être dans le masque [member CollisionObject2D.collision_mask] de ce "
+"corps pour être détecté.\n"
+"Pour des raisons de performance (les collisions sont toutes traitées en même "
+"temps) cette liste est modifiée une fois pendant l'étape physique, pas "
+"immédiatement après le déplacement des objets. Considérez plutôt "
+"l'utilisation des signaux."
#: doc/classes/Area2D.xml
msgid ""
@@ -8832,6 +8888,11 @@ msgid ""
"For performance, the list of overlaps is updated once per frame and before "
"the physics step. Consider using signals instead."
msgstr ""
+"Si [code]true[/code], la zone donnée recouvre la Area2D.\n"
+"[b]Note :[/b] Le résultat de ce test n'est pas immédiat après le déplacement "
+"des objets. Pour des raisons de performance, la liste des collisions est "
+"mise à jour une fois par trame et avant l'étape physique. Considérez plutôt "
+"l'utilisation des signaux."
#: doc/classes/Area2D.xml
msgid ""
@@ -8882,6 +8943,10 @@ msgid ""
"See [member ProjectSettings.physics/2d/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/2d/default_linear_damp] pour plus de "
+"détails sur l'amortissement."
#: doc/classes/Area2D.xml
msgid ""
@@ -8889,6 +8954,9 @@ msgid ""
"to be set to [code]true[/code].\n"
"[code]area[/code] the other Area2D."
msgstr ""
+"Émis quand une autre Area2D entre dans cette Area2D. Nécessite [member "
+"monitoring] d'être défini à [code]true[/code].\n"
+"[code]area[/code] l'autre Area2D."
#: doc/classes/Area2D.xml
msgid ""
@@ -8896,6 +8964,9 @@ msgid ""
"to be set to [code]true[/code].\n"
"[code]area[/code] the other Area2D."
msgstr ""
+"Émis quand une autre Area2D quitte cette Area2D. Nécessite [member "
+"monitoring] d'être défini à [code]true[/code].\n"
+"[code]area[/code] l'autre Area2D."
#: doc/classes/Area2D.xml
msgid ""
@@ -9501,7 +9572,7 @@ msgid ""
"element, the slower [method pop_at] will be."
msgstr ""
"Retire et retourne l'élément du tableau à la [code]position[/code]. Si "
-"négatif, [code]position[/code] part de la la fin du tableau vers le début. "
+"négatif, [code]position[/code] part de la fin du tableau vers le début. "
"Laisse le tableau intact et retourne [code]null[/code] si le tableau est "
"vide ou s'il la position est en dehors des limites du tableau. Un message "
"d'erreur est affiché lorsque la position est en dehors des limites du "
@@ -9827,7 +9898,7 @@ msgstr ""
#: doc/classes/ArrayMesh.xml
msgid "Will regenerate normal maps for the [ArrayMesh]."
-msgstr ""
+msgstr "Régénérera les cartes normales pour le [ArrayMesh]."
#: doc/classes/ArrayMesh.xml
msgid ""
@@ -9842,12 +9913,16 @@ msgid ""
"Returns the length in indices of the index array in the requested surface "
"(see [method add_surface_from_arrays])."
msgstr ""
+"Retourne la longueur des indices du tableau d'indices pour la surface "
+"spécifiée (voir [method add_surface_from_arrays])."
#: doc/classes/ArrayMesh.xml
msgid ""
"Returns the length in vertices of the vertex array in the requested surface "
"(see [method add_surface_from_arrays])."
msgstr ""
+"Retourne la longueur des sommets du tableau des sommets dans la surface "
+"spécifiée (voir [method add_surface_from_arrays])."
#: doc/classes/ArrayMesh.xml
msgid ""
@@ -9895,7 +9970,7 @@ msgstr ""
#: doc/classes/ArrayMesh.xml
msgid "Sets the blend shape mode to one of [enum Mesh.BlendShapeMode]."
-msgstr ""
+msgstr "Définit le mode de forme de mélange avec [enum Mesh.BlendShapeMode]."
#: doc/classes/ArrayMesh.xml doc/classes/PrimitiveMesh.xml
msgid ""
@@ -9908,10 +9983,8 @@ msgstr ""
"lors de l'utilisation d'un shader qui décale les sommets."
#: doc/classes/ArrayMesh.xml
-#, fuzzy
msgid "Value used internally when no indices are present."
-msgstr ""
-"La valeur par défaut utilisée pour index_array_len quand il n'y pas d'indice."
+msgstr "La valeur par défaut utilisée en interne quand il n'y pas d'indice."
#: doc/classes/ArrayMesh.xml
msgid "Amount of weights/bone indices per vertex (always 4)."
@@ -10134,7 +10207,6 @@ msgstr ""
"constamment mise à jour [code]mesh_updated[/code]."
#: doc/classes/ARVRCamera.xml
-#, fuzzy
msgid ""
"A camera node with a few overrules for AR/VR applied, such as location "
"tracking."
@@ -10293,14 +10365,14 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
"L'intensité de vibration du contrôleur. L'intervalle va de [code]0.0[/code] "
-"à [code]1.0[/code] avec une précision de [code]0.01[/code]. Si changé, met à "
-"jour [membrez ARVRPositionalTracker.rumble] en conséquence.\n"
+"à [code]1.0[/code]. Si changé, [member ARVRPositionalTracker.rumble] sera "
+"mis à jour en conséquence.\n"
"C'est une propriété utile à animer si vous souhaitez que le contrôleur vibre "
"pendant une durée limitée."
@@ -10470,6 +10542,7 @@ msgstr "Cette interface est compatible avec le rendu stéréoscopique."
#: doc/classes/ARVRInterface.xml
msgid "This interface supports AR (video background and real world tracking)."
msgstr ""
+"Cette interface supporte la AR (arrière-plan vidéo et suivi du monde réel)."
#: doc/classes/ARVRInterface.xml
msgid ""
@@ -10546,9 +10619,8 @@ msgstr ""
"lumières sont éteintes, etc.)."
#: modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
-#, fuzzy
msgid "GDNative wrapper for an ARVR interface."
-msgstr "Classe de base pour une implémentation d’interface AR / VR."
+msgstr "L'encapsulation GDNative pour les interfaces ARVR."
#: modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
msgid ""
@@ -10832,6 +10904,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 +10914,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 +10924,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 ""
@@ -10971,7 +11052,6 @@ msgstr ""
"position du joueur."
#: doc/classes/AspectRatioContainer.xml
-#, fuzzy
msgid "Container that preserves its child controls' aspect ratio."
msgstr "Un conteneur qui préserve le ratio d'aspect des contrôles enfants."
@@ -10994,19 +11074,16 @@ msgstr ""
#: doc/classes/PanelContainer.xml doc/classes/ScrollContainer.xml
#: doc/classes/SplitContainer.xml doc/classes/TabContainer.xml
#: doc/classes/VBoxContainer.xml doc/classes/VSplitContainer.xml
-#, fuzzy
msgid "GUI containers"
-msgstr "Conteneur à onglets."
+msgstr "Conteneurs d'interface"
#: doc/classes/AspectRatioContainer.xml
-#, fuzzy
msgid "Specifies the horizontal relative position of child controls."
-msgstr "La séparation horizontale des nœuds enfants."
+msgstr "Définit la position horizontale relative des nœuds enfants."
#: doc/classes/AspectRatioContainer.xml
-#, fuzzy
msgid "Specifies the vertical relative position of child controls."
-msgstr "La séparation verticale des nœuds enfants."
+msgstr "Définit la position verticale relative des nœuds enfants."
#: doc/classes/AspectRatioContainer.xml
msgid ""
@@ -11057,19 +11134,17 @@ msgstr ""
"de limiter la visibilité à seulement la taille du conteneur."
#: doc/classes/AspectRatioContainer.xml
-#, fuzzy
msgid ""
"Aligns child controls with the beginning (left or top) of the container."
-msgstr "Aligne les enfants avec le début du conteneur."
+msgstr "Aligne les enfants au début (à gauche ou en haut) du conteneur."
#: doc/classes/AspectRatioContainer.xml
msgid "Aligns child controls with the center of the container."
msgstr "Aligne les contrôles enfants au centre du conteneur."
#: doc/classes/AspectRatioContainer.xml
-#, fuzzy
msgid "Aligns child controls with the end (right or bottom) of the container."
-msgstr "Aligne les enfants avec le centre du conteneur."
+msgstr "Aligne les enfants à la fin (à droite ou en-bas) du conteneur."
#: doc/classes/AStar.xml
msgid ""
@@ -11366,6 +11441,8 @@ msgid ""
"Returns the capacity of the structure backing the points, useful in "
"conjunction with [code]reserve_space[/code]."
msgstr ""
+"Retourne la capacité de la structure qui garde les points en cache, utile "
+"avec [code]reserve_space[/code]."
#: doc/classes/AStar.xml
msgid ""
@@ -11428,6 +11505,8 @@ msgid ""
"Returns the weight scale of the point associated with the given [code]id[/"
"code]."
msgstr ""
+"Retourne l'échelle de poids du point associé pour le [code]id[/code] "
+"spécifié."
#: doc/classes/AStar.xml doc/classes/AStar2D.xml
msgid "Returns an array of all points."
@@ -11444,6 +11523,8 @@ msgid ""
"Returns whether a point is disabled or not for pathfinding. By default, all "
"points are enabled."
msgstr ""
+"Retourne si un point est désactivé ou non pour le calcul du chemin. Par "
+"défaut, tous les points sont activés."
#: doc/classes/AStar.xml doc/classes/AStar2D.xml
msgid ""
@@ -11459,6 +11540,9 @@ msgid ""
"you're adding a known large number of points at once, for a grid for "
"instance. New capacity must be greater or equals to old capacity."
msgstr ""
+"Réserve l'espace interne pour [code]num_nodes[/code] points, utile si vous "
+"voulez ajouter un grand nombre de points à la fois, pour une grille par "
+"exemple. La nouvelle capacité doit être supérieure ou égale à l'ancienne."
#: doc/classes/AStar.xml doc/classes/AStar2D.xml
msgid ""
@@ -11545,14 +11629,13 @@ msgstr ""
"position et sont facteur de poids seront mis à jour avec la valeur donnée."
#: doc/classes/AStar2D.xml
-#, fuzzy
msgid ""
"Returns whether there is a connection/segment between the given points. If "
"[code]bidirectional[/code] is [code]false[/code], returns whether movement "
"from [code]id[/code] to [code]to_id[/code] is possible through this segment."
msgstr ""
"Retourne si les deux points donnés sont directement reliés par un segment. "
-"Si [code]bidirectionnel[/code] est [code]false[/code], retourne si le "
+"Si [code]bidirectional[/code] est [code]false[/code], retourne si le "
"mouvement d'identifiant [code]id[/code] vers l'autre identifiant "
"[code]to_id[/code] est possible par ce segment."
@@ -11740,11 +11823,10 @@ msgstr ""
"sont ignorés pour les AtlasTexture."
#: doc/classes/AtlasTexture.xml
-#, fuzzy
msgid "The texture that contains the atlas. Can be any [Texture] subtype."
msgstr ""
-"La texture qui contient l'atlas. Peut être de n'importe quel sous-type "
-"[Texture2D]."
+"La texture qui contient l'atlas. Peut être de n'importe quel sous-type de "
+"[Texture]."
#: doc/classes/AtlasTexture.xml
msgid ""
@@ -11819,6 +11901,9 @@ msgid ""
"Limits the frequencies in a range around the [member AudioEffectFilter."
"cutoff_hz] and allows frequencies outside of this range to pass."
msgstr ""
+"Limite l'intensité des fréquences dans la gamme autour de [member "
+"AudioEffectFilter.cutoff_hz], et permet aux fréquences en dehors de cette "
+"gamme de passer."
#: doc/classes/AudioEffectBandPassFilter.xml
msgid "Adds a band pass filter to the audio bus."
@@ -11829,6 +11914,9 @@ msgid ""
"Attenuates the frequencies inside of a range around the [member "
"AudioEffectFilter.cutoff_hz] and cuts frequencies outside of this band."
msgstr ""
+"Atténue les fréquences à l'intérieur de la gamme autour de [member "
+"AudioEffectFilter.cutoff_hz] et coupe les fréquences en dehors de cette "
+"gamme."
#: doc/classes/AudioEffectCapture.xml
msgid "Captures audio from an audio bus in real-time."
@@ -11873,9 +11961,8 @@ msgstr ""
"pas assez de données disponibles."
#: doc/classes/AudioEffectCapture.xml
-#, fuzzy
msgid "Returns the total size of the internal ring buffer in frames."
-msgstr "Renvoie le reste de deux vecteurs."
+msgstr ""
#: doc/classes/AudioEffectCapture.xml
msgid ""
@@ -11886,15 +11973,13 @@ msgstr ""
"mémoire est pleine."
#: doc/classes/AudioEffectCapture.xml
-#, fuzzy
msgid ""
"Returns the number of frames available to read using [method get_buffer]."
-msgstr "Retourne le nombre de formes assignées à une zone."
+msgstr ""
#: doc/classes/AudioEffectCapture.xml
-#, fuzzy
msgid "Returns the number of audio frames inserted from the audio bus."
-msgstr "Renvoie le nombre de points sur l'axe de mélange."
+msgstr ""
#: doc/classes/AudioEffectCapture.xml
msgid ""
@@ -12018,6 +12103,9 @@ msgid ""
"Compressor's delay time to stop reducing the signal after the signal level "
"falls below the threshold, in milliseconds. Value can range from 20 to 2000."
msgstr ""
+"Le retard du compresseur avant d'arrêter de réduire le signal après que le "
+"niveau de signal sous le seuil, en millisecondes. La valeur peut aller de 20 "
+"à 2000."
#: doc/classes/AudioEffectCompressor.xml
msgid "Reduce the sound level using another audio bus for threshold detection."
@@ -12050,6 +12138,10 @@ msgid ""
"echo. Delay effects range from a subtle echo effect to a pronounced blending "
"of previous sounds with new sounds."
msgstr ""
+"Joue le signal d'entrée après une période de temps. Le signal retardé peut "
+"être joué plusieurs fois pour créer un écho qui s'amortit dans le temps. Les "
+"effets de retard vont d'un subtil écho à un mélange prononcé de sons "
+"précédents avec les nouveaux sons."
#: doc/classes/AudioEffectDelay.xml
msgid ""
@@ -12088,6 +12180,8 @@ msgid ""
"Pan position for [code]tap1[/code]. Value can range from -1 (fully left) to "
"1 (fully right)."
msgstr ""
+"La position gauche-droite pour [code]tap1[/code]. La valeur peut aller de -1 "
+"(complètement à gauche) à 1 (complètement à droite)."
#: doc/classes/AudioEffectDelay.xml
msgid "If [code]true[/code], [code]tap2[/code] will be enabled."
@@ -12106,6 +12200,8 @@ msgid ""
"Pan position for [code]tap2[/code]. Value can range from -1 (fully left) to "
"1 (fully right)."
msgstr ""
+"La position gauche-droite pour [code]tap2[/code]. La valeur peut aller de -1 "
+"(complètement à gauche) à 1 (complètement à droite)."
#: doc/classes/AudioEffectDistortion.xml
msgid ""
@@ -12137,6 +12233,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 +12245,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 +12267,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 ""
@@ -12440,15 +12544,22 @@ msgid ""
"Attenuates frequencies in a narrow band around the [member AudioEffectFilter."
"cutoff_hz] and cuts frequencies outside of this range."
msgstr ""
+"Atténue les fréquences dans une bande étroite autour du [member "
+"AudioEffectFilter.cutoff_hz] et coupe les fréquences en dehors de cette "
+"gamme."
#: doc/classes/AudioEffectPanner.xml
msgid "Adds a panner audio effect to an Audio bus. Pans sound left or right."
msgstr ""
+"Ajoute un effet audio de balance à un bus audio. Balance les sons à gauche "
+"ou à droite."
#: doc/classes/AudioEffectPanner.xml
msgid ""
"Determines how much of an audio signal is sent to the left and right buses."
msgstr ""
+"Détermine quelle quantité d'un signal audio est envoyé aux bus de gauche et "
+"de droite."
#: doc/classes/AudioEffectPanner.xml
msgid "Pan position. Value can range from -1 (fully left) to 1 (fully right)."
@@ -12462,6 +12573,9 @@ msgid ""
"Combines the original signal with a copy that is slightly out of phase with "
"the original."
msgstr ""
+"Ajoute un effet audio de phaseur à un bus audio.\n"
+"Combine le signal original avec une copie de l'original légèrement hors "
+"phase."
#: doc/classes/AudioEffectPhaser.xml
msgid ""
@@ -12530,6 +12644,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 +12936,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,29 +12952,34 @@ 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
msgid "Returns the sample rate at the output of the [AudioServer]."
msgstr "Retourne le débit de sortie du [AudioServer]."
@@ -12887,6 +13012,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 +13024,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 +13060,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 +13075,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 +13087,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 +13133,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 +13166,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 +13200,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 +13217,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 ""
@@ -13110,14 +13264,11 @@ msgstr ""
"pour lire l'audio généré en temps réel."
#: doc/classes/AudioStreamGeneratorPlayback.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if a buffer of the size [code]amount[/code] can be "
"pushed to the audio sample data buffer without overflowing it, [code]false[/"
"code] otherwise."
msgstr ""
-"Retourne [code]true[/code] si le paramètre spécifié par [code]name[/code] "
-"existe, [code]false[/code] autrement."
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid "Clears the audio sample data buffer."
@@ -13130,6 +13281,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 +13293,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,11 +13304,14 @@ 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
msgid "MP3 audio stream driver."
-msgstr "Pilote de flux audio OGG Vorbis."
+msgstr "Le pilote de flux audio MP3."
#: modules/minimp3/doc_classes/AudioStreamMP3.xml
#: modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
@@ -13167,7 +13330,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 +13345,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 +13358,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."
@@ -13227,8 +13395,14 @@ msgstr ""
"scènes."
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
-msgstr "Bus sur lequel cet audio joue."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
+msgstr ""
#: doc/classes/AudioStreamPlayer.xml
msgid ""
@@ -13281,6 +13455,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 +13470,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 +13506,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 +13587,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."
@@ -13423,8 +13615,14 @@ msgstr ""
"ajouté à la scène."
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
-msgstr "Le bus sur lequel cet audio est joué."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
+msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
msgid ""
@@ -13460,7 +13658,7 @@ msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
msgid "Sets the absolute maximum of the soundlevel, in decibels."
-msgstr ""
+msgstr "Définit le maximum absolu du niveau sonore, en décibels."
#: doc/classes/AudioStreamPlayer3D.xml
msgid ""
@@ -13492,13 +13690,15 @@ msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
msgid "The base sound level unaffected by dampening, in decibels."
-msgstr ""
+msgstr "Le niveau sonore de base non affecté par l'amortissement, en décibels."
#: doc/classes/AudioStreamPlayer3D.xml
msgid ""
"The factor for the attenuation effect. Higher values make the sound audible "
"over a larger distance."
msgstr ""
+"Le facteur pour l'effet d'atténuation. Des valeurs plus élevées rendent le "
+"son audible sur une distance plus grande."
#: doc/classes/AudioStreamPlayer3D.xml
msgid "Linear dampening of loudness according to distance."
@@ -13529,6 +13729,10 @@ msgid ""
"but keeps the sound playing at the correct position if the camera leaves and "
"enters the [AudioStreamPlayer3D]'s [member max_distance] radius."
msgstr ""
+"Mélanger ce son, même lorsqu'il est hors de portée. Cela augmente "
+"l'utilisation de CPU, mais garde le son à la bonne position de lecture si la "
+"caméra quitte puis entre à nouveau dans le rayon [member max_distance] du "
+"[AudioStreamPlayer3D]."
#: doc/classes/AudioStreamPlayer3D.xml
msgid ""
@@ -13536,6 +13740,9 @@ msgid ""
"will cause the sound to restart if the camera leaves and enters the "
"[AudioStreamPlayer3D]'s [member max_distance] radius."
msgstr ""
+"Pause ce son quand il hors de portée. Cela diminue l'utilisation du CPU, "
+"mais cela fera redémarrer le son si la caméra quitte puis entre dans le "
+"rayon [member max_distance] du [AudioStreamPlayer3D]."
#: doc/classes/AudioStreamPlayer3D.xml
msgid "Disables doppler tracking."
@@ -13579,6 +13786,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 +13801,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 +13813,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 +13830,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 +13840,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 +13915,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 +13932,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 +14038,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 +14098,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 ""
@@ -13860,9 +14111,8 @@ msgstr ""
"[constant ENVIRONMENT_MODE_CUSTOM_SKY]."
#: doc/classes/BakedLightmap.xml
-#, fuzzy
msgid "The rotation of the baked custom sky."
-msgstr "La racine de la scène éditée."
+msgstr ""
#: doc/classes/BakedLightmap.xml
msgid ""
@@ -13888,6 +14138,8 @@ msgid ""
"Deprecated, in previous versions it determined the location where lightmaps "
"were be saved."
msgstr ""
+"Obsolète, dans les versions précédentes ça déterminait l'emplacement où les "
+"textures de lumière étaient enregistrées."
#: doc/classes/BakedLightmap.xml
msgid "The calculated light data."
@@ -13925,6 +14177,15 @@ msgid ""
"lightmap banding even when using the GLES2 backend or if [member "
"ProjectSettings.rendering/quality/depth/hdr] is [code]false[/code]."
msgstr ""
+"Si [code]true[/code], enregistre les textures de lumière dans un format de "
+"plage dynamique élevée (type EXR). Si [code]false[/code], enregistre les "
+"textures de lumière dans une image PNG de plage dynamique faible. Ceci peut "
+"être défini à [code]false[/code] pour réduire l'usage du disque, mais les "
+"valeurs lumineuses supérieures à 1.0 seront limitées et vous pouvez voir un "
+"effet de bandes qui apparaissent à cause de cette précision réduite.\n"
+"[b]Note :[/b] Définir [member use_hdr] à [code]true[/code] réduira l'effet "
+"de bandes même sous GLES2 ou quand [member ProjectSettings.rendering/quality/"
+"depth/hdr] est [code]false[/code]."
#: doc/classes/BakedLightmap.xml
msgid "The lowest bake quality mode. Fastest to calculate."
@@ -13951,15 +14212,17 @@ msgid ""
"Returns if no viable save path is found. This can happen where an [member "
"image_path] is not specified or when the save location is invalid."
msgstr ""
+"Retourne si aucun chemin d'enregistrement invalid n'est trouvé. Cela peut se "
+"produire lorsqu'un [member image_path] n'est pas spécifié ou lorsque "
+"l'emplacement de sauvegarde est invalide."
#: doc/classes/BakedLightmap.xml doc/classes/SpatialMaterial.xml
msgid "Currently unused."
msgstr "Actuellement inutilisé."
#: doc/classes/BakedLightmap.xml
-#, fuzzy
msgid "Returns when the baker cannot save per-mesh textures to file."
-msgstr "Renvoie l'arc tangente des paramètres."
+msgstr ""
#: doc/classes/BakedLightmap.xml
msgid "The size of the generated lightmaps is too large."
@@ -14027,17 +14290,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,9 +14317,12 @@ 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
msgid ""
"Returns [code]true[/code] if the mouse has entered the button and has not "
"left it yet."
@@ -14065,6 +14339,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 +14361,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 +14380,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 +14396,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 +14411,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."
@@ -14134,6 +14435,8 @@ msgid ""
"If [code]true[/code], the button is in toggle mode. Makes the button flip "
"state between pressed and unpressed each time its area is clicked."
msgstr ""
+"Si [code]true[/code], le bouton est en mode basculement. Fait basculer le "
+"bouton entre les états pressé et non-pressé chaque fois qu'il est cliqué."
#: doc/classes/BaseButton.xml
msgid "Emitted when the button starts being held down."
@@ -14151,6 +14454,11 @@ msgid ""
"If you need to know the button's pressed state (and [member toggle_mode] is "
"active), use [signal toggled] instead."
msgstr ""
+"Émis quand le bouton est basculé ou pressé. Émis lors de [signal "
+"button_down] si [member action_mode] est [constant ACTION_MODE_BUTTON_PRESS] "
+"et lors de [signal button_up] sinon.\n"
+"Si vous avez besoin de connaître l'état du bouton (et que [member "
+"toggle_mode] est actif), utilisez plutôt [signal toggled]."
#: doc/classes/BaseButton.xml
msgid ""
@@ -14158,12 +14466,17 @@ msgid ""
"(only if [member toggle_mode] is active). The new state is contained in the "
"[code]button_pressed[/code] argument."
msgstr ""
+"Émis lorsque le bouton a été juste basculé entre les états pressé et normal "
+"(seulement si [member toggle_mode] est actif). Le nouvel état est passé dans "
+"l'argument [code]button_pressed[/code]."
#: doc/classes/BaseButton.xml
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 +14523,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 +14545,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 +14579,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)."
@@ -14381,24 +14709,34 @@ msgid ""
"[b]Note:[/b] This results in a multiplication by the inverse of the matrix "
"only if it represents a rotation-reflection."
msgstr ""
+"Retourne un vecteur transformé (multiplié) par la matrice de base "
+"transposée.\n"
+"[b]Note :[/b] Cela entraîne une multiplication par l'inverse de la matrice "
+"seulement si elle représente une rotation-réflexion."
#: doc/classes/Basis.xml doc/classes/Transform2D.xml
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 +14745,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 +14784,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 +14796,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 +14815,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 +14841,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]."
@@ -14513,6 +14879,10 @@ msgid ""
"Supports distance fields. For using vector font files like TTF directly, see "
"[DynamicFont]."
msgstr ""
+"Rend le texte en utilisant les atlas des texture contenues dans le fichier "
+"[code]*.fnt[/code]. Supporte les champs de distance. Pour utiliser "
+"directement des fichiers de police vectorielles, comme le TTF, voir "
+"[DynamicFont]."
#: doc/classes/BitmapFont.xml
msgid ""
@@ -14522,6 +14892,11 @@ msgid ""
"alignment for the character and [code]advance[/code] is the (optional) "
"advance."
msgstr ""
+"Ajoute un caractère à la police, où [code]character[/code] est la valeur "
+"Unicode, [code]texture[/code] est l'index de la texture, [code]rect[/code] "
+"est la région de la texture (en pixels !), [code]align[/code] est "
+"l'alignement (optionnel) du caractère et [code]advance[/code] est "
+"l'avancement (optionnel)."
#: doc/classes/BitmapFont.xml
msgid ""
@@ -14592,6 +14967,17 @@ msgid ""
"menu option, from the code, you need to iterate over the bones to set their "
"individual rest poses."
msgstr ""
+"Utilise une hiérarchie [code]Bone2D[/code] liée à un [Skeleton2D] pour "
+"contrôler et animer d'autres nœuds [Node2D].\n"
+"Vous pouvez utiliser les nœuds [code]Bone2D[/code] et [code]Skeleton2D[/"
+"code] pour animer les maillages 2D créées avec l'éditeur d'UV de Polygon "
+"2D.\n"
+"Chaque os a une transformation de repos [member rest] que vous pouvez "
+"réinitialiser avec [method apply_rest]. Ces poses de repos sont par rapport "
+"au parent de l'os.\n"
+"Si dans l'éditeur vous pouvez définir la pose de repos d'un squelette entier "
+"en utilisant une option de menu, à partir du code, vous devez itérer sur les "
+"os pour définir leurs poses de repos individuelles."
#: doc/classes/Bone2D.xml
msgid "Stores the node's current transforms in [member rest]."
@@ -14607,6 +14993,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 +15022,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 +15159,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 +15174,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 +15220,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 +15296,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 +15312,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 +15335,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 +15347,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 +15382,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 +15412,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 +15438,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 ""
@@ -15029,14 +15456,12 @@ msgid "Returns the current pressed button."
msgstr "Renvoie le bouton actuellement enfoncé."
#: doc/classes/ButtonGroup.xml
-#, fuzzy
msgid "Emitted when one of the buttons of the group is pressed."
-msgstr "Émis lorsqu’un bouton de ce contrôleur est appuyé."
+msgstr "Émis lorsqu’un des boutons de ce groupe est appuyé."
#: doc/classes/CallbackTweener.xml
-#, fuzzy
msgid "Calls the specified method after optional delay."
-msgstr "Verrouille l'axe linéaire et de rotation spécifié."
+msgstr "Appelle la méthode spécifiée après un délai optionnel."
#: doc/classes/CallbackTweener.xml
msgid ""
@@ -15098,6 +15523,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 +15538,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 ""
@@ -15132,6 +15564,9 @@ msgid ""
"[b]Note:[/b] A position which returns [code]false[/code] may still be "
"outside the camera's field of view."
msgstr ""
+"Retourne [code]true[/code] si la position donnée est derrière la caméra.\n"
+"[b]Note :[/b] Une position qui retourne [code]false[/code] peut quand même "
+"être en dehors du champ de vision de la caméra."
#: doc/classes/Camera.xml
msgid ""
@@ -15139,6 +15574,10 @@ msgid ""
"description). If the camera node is outside the scene tree, it will attempt "
"to become current once it's added."
msgstr ""
+"Fait que cette caméra devient l'actuelle pour le [Viewport] (voir la "
+"description de la classe). Si le nœud de la caméra est en dehors de "
+"l'arborescence de la scène, il tentera de devenir l'actuel dès qu'il sera "
+"ajouté."
#: doc/classes/Camera.xml
msgid ""
@@ -15153,6 +15592,9 @@ msgid ""
"the [Viewport] rectangle on a plane that is the given [code]z_depth[/code] "
"distance into the scene away from the camera."
msgstr ""
+"Retourne le point 3D dans l'espace global qui correspond à la coordonnées 2D "
+"donnée dans le rectangle du [Viewport] sur un plan qui est à la distance "
+"[code]z_depth[/code] donnée dans la scène par rapport à la caméra."
#: doc/classes/Camera.xml
msgid ""
@@ -15161,6 +15603,10 @@ msgid ""
"useful for casting rays in the form of (origin, normal) for object "
"intersection or picking."
msgstr ""
+"Retourne la normale dans l'espace global, qui est le résultat de la "
+"projection d'un point sur le rectangle [Viewport] par la projection inverse "
+"de la caméra. Ceci est utile pour lancer des rayons sous la forme (origine, "
+"normale) pour l'intersection ou la sélection d'objets."
#: doc/classes/Camera.xml
msgid ""
@@ -15169,6 +15615,10 @@ msgid ""
"useful for casting rays in the form of (origin, normal) for object "
"intersection or picking."
msgstr ""
+"Retourne la position 3D dans l'espace global, qui est le résultat de "
+"projeter un point sur le rectangle [Viewport] par la projection inverse de "
+"la caméra. Ceci est utile pour lancer des rayons sous la forme (origine, "
+"normale) pour l'intersection ou la sélection d'objets."
#: doc/classes/Camera.xml
msgid ""
@@ -15239,9 +15689,13 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
-"Si [code]true[/code], l’ancêtre [Viewport] utilise actuellement cette caméra."
#: doc/classes/Camera.xml
msgid ""
@@ -15313,6 +15767,8 @@ msgid ""
"The axis to lock during [member fov]/[member size] adjustments. Can be "
"either [constant KEEP_WIDTH] or [constant KEEP_HEIGHT]."
msgstr ""
+"L'axe à verrouiller pendant les réglages [member fov] ou [member size]. Peut "
+"être soit [constant KEEP_WIDTH] ou [constant KEEP_HEIGHT]."
#: doc/classes/Camera.xml
msgid ""
@@ -15326,6 +15782,9 @@ msgid ""
"objects' Z distance from the camera's local space scales their perceived "
"size."
msgstr ""
+"Le mode de projection de la caméra. Dans le mode [constant "
+"PROJECTION_PERSPECTIVE], la distance des objets dans l'espace local de la "
+"caméra détermine la taille apparante de ces objets."
#: doc/classes/Camera.xml
msgid ""
@@ -15333,6 +15792,10 @@ msgid ""
"orthogonal and frustum modes. Since [member keep_aspect] locks on axis, "
"[code]size[/code] sets the other axis' size length."
msgstr ""
+"La taille de la caméra mesurée comme la moitié de la largeur ou de la "
+"hauteur. N'est applicable qu'en modes orthogonal et frustum. Comme [member "
+"keep_aspect] verrouille l'axe, [code]size[/code] fixe la longueur de la "
+"taille sur l'autre axe."
#: doc/classes/Camera.xml
msgid "The vertical (Y) offset of the camera viewport."
@@ -15351,6 +15814,9 @@ msgid ""
"Orthogonal projection, also known as orthographic projection. Objects remain "
"the same size on the screen no matter how far away they are."
msgstr ""
+"La projection orthogonale, également connue sous le nom de projection "
+"orthographique. Les objets gardent la même taille à l'écran, indépendamment "
+"de leur distance."
#: doc/classes/Camera.xml
msgid ""
@@ -15371,6 +15837,10 @@ msgid ""
"usually the best option for projects running in landscape mode, as wider "
"aspect ratios will automatically benefit from a wider horizontal FOV."
msgstr ""
+"Préserve le rapport d'aspect vertical ; également connu sous le nom "
+"d'échelle Hor+. C'est généralement la meilleure option pour les projets en "
+"mode paysage, car les ratios d'aspect plus larges bénéficieront "
+"automatiquement d'un champ de vision horizontal plus large."
#: doc/classes/Camera.xml
msgid ""
@@ -15471,6 +15941,11 @@ msgid ""
"or [member Node2D.global_position], as it is affected by the [code]drag[/"
"code] properties."
msgstr ""
+"Retourne la [code]position[/code] de la caméra (le point suivi que la caméra "
+"essaye de suivre), par rapport à l'origine.\n"
+"[b]Note :[/b] La valeur retournée n'est pas la même que [member Node2D."
+"position] ou [member Node2D.global_position], car elle est aussi affectée "
+"par les propriétés [code]drag[/code]."
#: doc/classes/Camera2D.xml
msgid ""
@@ -15479,12 +15954,18 @@ msgid ""
"[b]Note:[/b] The real [code]position[/code] of the camera may be different, "
"see [method get_camera_position]."
msgstr ""
+"Retourne l'emplacement du centre de l'écran de la [Camera2D], par rapport à "
+"l'origine.\n"
+"[b]Note :[/b] La véritable [code]position[/code] de la caméra peut être "
+"différente, voir [method get_camera_position]."
#: doc/classes/Camera2D.xml
msgid ""
"Returns the specified margin. See also [member drag_margin_bottom], [member "
"drag_margin_top], [member drag_margin_left], and [member drag_margin_right]."
msgstr ""
+"Retourne la marge spécifiée. Voir aussi [member drag_margin_bottom], [member "
+"drag_margin_top], [member drag_margin_left], et [member drag_margin_right]."
#: doc/classes/Camera2D.xml
msgid ""
@@ -15539,6 +16020,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 ""
@@ -15552,24 +16036,36 @@ msgid ""
"drag margins. If [code]false[/code], the camera moves horizontally "
"regardless of margins."
msgstr ""
+"Si [code]true[/code], la caméra ne bouge que lorsqu'elle atteint les marges "
+"horizontales de glissage. Si [code]false[/code], la caméra se déplace "
+"horizontalement indépendamment des marges."
#: doc/classes/Camera2D.xml
msgid ""
"Left margin needed to drag the camera. A value of [code]1[/code] makes the "
"camera move only when reaching the edge of the screen."
msgstr ""
+"La marge gauche nécessaire pour glisser la caméra. Une valeur de "
+"[code]1[/code] ne déplace la caméra que lorsqu'elle atteint le bord de "
+"l'écran."
#: doc/classes/Camera2D.xml
msgid ""
"Right margin needed to drag the camera. A value of [code]1[/code] makes the "
"camera move only when reaching the edge of the screen."
msgstr ""
+"La marge droite nécessaire pour glisser la caméra. Une valeur de "
+"[code]1[/code] ne déplace la caméra que lorsqu'elle atteint le bord de "
+"l'écran."
#: doc/classes/Camera2D.xml
msgid ""
"Top margin needed to drag the camera. A value of [code]1[/code] makes the "
"camera move only when reaching the edge of the screen."
msgstr ""
+"La marge supérieure nécessaire pour glisser la caméra. Une valeur de "
+"[code]1[/code] ne déplacer la caméra que lorsqu'elle atteint le bord de "
+"l'écran."
#: doc/classes/Camera2D.xml
msgid ""
@@ -15577,16 +16073,23 @@ msgid ""
"margins. If [code]false[/code], the camera moves vertically regardless of "
"margins."
msgstr ""
+"Si [code]true[/code], la caméra ne bouge que lorsqu'elle atteint les marges "
+"verticales de glissage. Si [code]false[/code], la caméra se déplace "
+"verticalement indépendamment des marges."
#: doc/classes/Camera2D.xml
msgid ""
"If [code]true[/code], draws the camera's drag margin rectangle in the editor."
msgstr ""
+"Si [code]true[/code], dessine le rectangle de la marge de glissage de la "
+"caméra activée dans l'éditeur."
#: doc/classes/Camera2D.xml
msgid ""
"If [code]true[/code], draws the camera's limits rectangle in the editor."
msgstr ""
+"Si [code]true[/code], dessine le rectangle des limites de la caméra activée "
+"dans l'éditeur."
#: doc/classes/Camera2D.xml
msgid ""
@@ -15627,6 +16130,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 ""
@@ -15649,12 +16159,19 @@ msgid ""
"not updated in any way if drag margins are enabled and can be used to set "
"initial offset."
msgstr ""
+"Le décalage horizontal de la caméra, par rapport aux marges de glissage.\n"
+"[b]Note :[/b] Le décalage H est utilisé uniquement pour forcer le décalage "
+"par rapport aux marges. Elle n'est pas mise à jour même si les marges de "
+"glissage sont activées et peuvent être utilisées pour régler le décalage "
+"initial."
#: doc/classes/Camera2D.xml
msgid ""
"The vertical offset of the camera, relative to the drag margins.\n"
"[b]Note:[/b] Used the same as [member offset_h]."
msgstr ""
+"Le décalage vertical de la caméra, par rapport aux marges de glissage.\n"
+"[b]Note :[/b] Utilisé de la même manière que [member offset_h]."
#: doc/classes/Camera2D.xml
msgid "The camera's process callback. See [enum Camera2DProcessMode]."
@@ -15662,9 +16179,8 @@ msgstr ""
"La méthode de mise à jour de la camera. Voir [enum Camera2DProcessMode]."
#: doc/classes/Camera2D.xml
-#, fuzzy
msgid "If [code]true[/code], the camera view rotates with the target."
-msgstr "Si [code]true[/code], le bouton \"add preset\" est activé."
+msgstr ""
#: doc/classes/Camera2D.xml
msgid ""
@@ -15679,6 +16195,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 +16205,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 +16227,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]."
@@ -15744,9 +16268,8 @@ msgid "Returns the unique ID for this feed."
msgstr "Retourne l'identifiant unique de ce flux."
#: doc/classes/CameraFeed.xml
-#, fuzzy
msgid "Returns the camera's name."
-msgstr "Renvoie le nom de l'élément."
+msgstr "Retourne le nom de la caméra."
#: doc/classes/CameraFeed.xml
msgid "Returns the position of camera on the device."
@@ -15816,20 +16339,18 @@ msgstr ""
"iOS. Sur les autres plates-formes, aucun [CameraFeed] ne sera disponible."
#: doc/classes/CameraServer.xml
-#, fuzzy
msgid "Adds the camera [code]feed[/code] to the camera server."
-msgstr "Ajoute un [Shape2D] au propriétaire de la forme."
+msgstr ""
#: doc/classes/CameraServer.xml
msgid "Returns an array of [CameraFeed]s."
msgstr "Retourne un tableau de [CameraFeed]s."
#: doc/classes/CameraServer.xml
-#, fuzzy
msgid ""
"Returns the [CameraFeed] corresponding to the camera with the given "
"[code]index[/code]."
-msgstr "Retourne la position du point à l'index [code]point[/code]."
+msgstr ""
#: doc/classes/CameraServer.xml
msgid "Returns the number of [CameraFeed]s registered."
@@ -15840,14 +16361,12 @@ msgid "Removes the specified camera [code]feed[/code]."
msgstr "Supprime le flux de caméra [code]feed[/code] spécifié."
#: doc/classes/CameraServer.xml
-#, fuzzy
msgid "Emitted when a [CameraFeed] is added (e.g. a webcam is plugged in)."
-msgstr "Émis lorsqu'une interface est supprimée."
+msgstr ""
#: doc/classes/CameraServer.xml
-#, fuzzy
msgid "Emitted when a [CameraFeed] is removed (e.g. a webcam is unplugged)."
-msgstr "Émis lorsqu'une interface est supprimée."
+msgstr ""
#: doc/classes/CameraServer.xml
msgid "The RGBA camera image."
@@ -15877,6 +16396,10 @@ msgid ""
"[b]Note:[/b] Many cameras supply YCbCr images which need to be converted in "
"a shader."
msgstr ""
+"Cette texture donne accès à la texture de la caméra fournie par "
+"[CameraFeed].\n"
+"[b]Note :[/b] Beaucoup de caméras fournissent des images au format YCbCr qui "
+"doivent être converties dans un shader."
#: doc/classes/CameraTexture.xml
msgid "The ID of the [CameraFeed] for which we want to display the image."
@@ -15887,13 +16410,15 @@ msgstr ""
msgid ""
"Convenience property that gives access to the active property of the "
"[CameraFeed]."
-msgstr ""
+msgstr "Propriété utile qui donne accès à la propriété active du [CameraFeed]."
#: doc/classes/CameraTexture.xml
msgid ""
"Which image within the [CameraFeed] we want access to, important if the "
"camera image is split in a Y and CbCr component."
msgstr ""
+"L'image du [CameraFeed] pour laquelle nous voulons accéder, important si "
+"l'image de la caméra est divisée en composants Y et CbCr."
#: doc/classes/CanvasItem.xml
msgid "Base class of anything 2D."
@@ -16082,6 +16607,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 +16670,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 +16910,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 +16929,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 +16955,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 +16971,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 +16989,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 +17048,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 ""
@@ -16529,6 +17080,8 @@ msgid ""
"The color applied to textures on this [CanvasItem]. This is not inherited by "
"children [CanvasItem]s."
msgstr ""
+"La couleur appliquée aux textures sur ce [CanvasItem]. Cela n'est pas hérité "
+"pour les [CanvasItem] enfants."
#: doc/classes/CanvasItem.xml
msgid "If [code]true[/code], the object draws behind its parent."
@@ -16543,6 +17096,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 +17108,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 +17134,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."
@@ -16580,6 +17147,8 @@ msgid ""
"Mix blending mode. Colors are assumed to be independent of the alpha "
"(opacity) value."
msgstr ""
+"Le mode de mélange. Les couleurs sont supposées être indépendantes de "
+"l'opacité."
#: doc/classes/CanvasItem.xml doc/classes/CanvasItemMaterial.xml
msgid "Additive blending mode."
@@ -16598,6 +17167,8 @@ msgid ""
"Mix blending mode. Colors are assumed to be premultiplied by the alpha "
"(opacity) value."
msgstr ""
+"Le mode de mélange. Les couleurs sont supposées être prémultipliées par leur "
+"opacité."
#: doc/classes/CanvasItem.xml
msgid ""
@@ -16611,12 +17182,16 @@ msgid ""
"The [CanvasItem]'s global transform has changed. This notification is only "
"received if enabled by [method set_notify_transform]."
msgstr ""
+"La transformation globale du [CanvasItem] a changé. Cette notification n'est "
+"reçue que si elle est activée par [method set_notify_transform]."
#: doc/classes/CanvasItem.xml
msgid ""
"The [CanvasItem]'s local transform has changed. This notification is only "
"received if enabled by [method set_notify_local_transform]."
msgstr ""
+"La transformation locale [CanvasItem] a changé. Cette notification n'est "
+"reçue que si elle est activée par [method set_notify_local_transform]."
#: doc/classes/CanvasItem.xml
msgid "The [CanvasItem] is requested to draw."
@@ -16708,6 +17283,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 +17327,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 +17358,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,11 +17396,14 @@ 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
msgid "Emitted when visibility of the layer is changed. See [member visible]."
-msgstr "Émis lorsque le VisibilityNotifier3D quitte la vue d'un [Camera3D]."
+msgstr ""
#: doc/classes/CanvasModulate.xml
msgid "Tint the entire canvas."
@@ -16842,6 +17431,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 +17473,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 ""
@@ -16901,13 +17498,12 @@ msgstr ""
"contrôler le rendu de caractères individuels dans un [RichTextEffect]."
#: doc/classes/CharFXTransform.xml
-#, fuzzy
msgid ""
"The index of the current character (starting from 0) for the "
"[RichTextLabel]'s BBCode text. Setting this property won't affect drawing."
msgstr ""
-"L'index du caractère actuel (commence à 0). Régler cette propriété n'affecte "
-"pas l'affichage."
+"L'index du caractère actuel (commence à 0) pour le texte BBCode du "
+"[RichTextLabel]. Régler cette propriété n'affecte pas l'affichage."
#: doc/classes/CharFXTransform.xml
msgid ""
@@ -16986,13 +17582,12 @@ msgstr ""
"pixels)."
#: doc/classes/CharFXTransform.xml
-#, fuzzy
msgid ""
"The index of the current character (starting from 0) for this "
"[RichTextEffect] custom block. Setting this property won't affect drawing."
msgstr ""
-"L'index du caractère actuel (commence à 0). Régler cette propriété n'affecte "
-"pas l'affichage."
+"L'index du caractère actuel (commence à 0) pour le bloc personnalisé du "
+"[RichTextEffect]. Régler cette propriété n'affecte pas l'affichage."
#: doc/classes/CharFXTransform.xml
msgid ""
@@ -17110,10 +17705,9 @@ msgid "The check icon to display when the [CheckBox] is unchecked."
msgstr "L'icône de la coche à afficher quand la [CheckBox] est décochée."
#: doc/classes/CheckBox.xml
-#, fuzzy
msgid ""
"The check icon to display when the [CheckBox] is unchecked and disabled."
-msgstr "Icône à afficher lorsque le [CheckButton] est coché et désactivé."
+msgstr "L'icône à afficher lorsque le [CheckBox] est décoché et désactivé."
#: doc/classes/CheckBox.xml
msgid ""
@@ -17190,6 +17784,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 +17806,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 +17857,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 +17877,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 +17899,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,36 +17911,47 @@ 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
msgid ""
"Returns an array with all the enums of [code]class[/code] or its ancestry."
-msgstr "Retourne si la [code]class[/code] spécifiée est disponible ou non."
+msgstr ""
#: doc/classes/ClassDB.xml
msgid ""
"Returns the value of the integer constant [code]name[/code] of [code]class[/"
"code] or its ancestry. Always returns 0 when the constant could not be found."
msgstr ""
+"Retourne la valeur de la constante entière nommée [code]name[/code] dans "
+"[code]class[/code] ou un de ses parents. Retourne toujours 0 si la constante "
+"n'a pas été trouvée."
#: doc/classes/ClassDB.xml
msgid ""
"Returns which enum the integer constant [code]name[/code] of [code]class[/"
"code] or its ancestry belongs to."
msgstr ""
+"Retourne à quelle énumération la constante entière nommée [code]name[/code] "
+"dans [code]class[/code] ou un de ses parents."
#: doc/classes/ClassDB.xml
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 +17964,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 +17987,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 +17998,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 +18010,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,12 +18027,17 @@ 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 ""
"Returns whether [code]class[/code] (or its ancestry if [code]no_inheritance[/"
"code] is [code]false[/code]) has a method called [code]method[/code] or not."
msgstr ""
+"Retourne si [code]class[/code] (ou un de ses parents si "
+"[code]no_inheritance[/code] est [code]false[/code]) a une méthode nommée "
+"[code]method[/code] ou non."
#: doc/classes/ClassDB.xml
msgid ""
@@ -17422,6 +18063,8 @@ msgid ""
"Returns the names of all the classes that directly or indirectly inherit "
"from [code]class[/code]."
msgstr ""
+"Retourne le nom de toutes les classes qui héritent directement ou "
+"indirectement de [code]class[/code]."
#: doc/classes/ClassDB.xml
msgid "Returns the parent class of [code]class[/code]."
@@ -17452,6 +18095,9 @@ msgid ""
"This node extends [Camera] to add collisions with [Area] and/or "
"[PhysicsBody] nodes. The camera cannot move through colliding objects."
msgstr ""
+"Ce nœud étend [Camera] pour ajouter des collisions avec des nœuds [Area] et/"
+"ou [PhysicsBody]. La caméra ne peut pas passer à travers les objets avec "
+"lesquels elle rentre en collision."
#: doc/classes/ClippedCamera.xml
msgid ""
@@ -17483,6 +18129,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 +18145,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 +18166,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 +18196,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 +18212,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 ""
@@ -17640,20 +18307,18 @@ msgid "Returns the parent object of the given shape owner."
msgstr "Retourne l'objet parent du propriétaire de la forme spécifié."
#: doc/classes/CollisionObject.xml
-#, fuzzy
msgid "Returns the [Shape] with the given id from the given shape owner."
-msgstr "Retourne le [RID] de la énième forme d'une zone."
+msgstr ""
#: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml
msgid "Returns the number of shapes the given shape owner contains."
msgstr "Retourne le nombre de formes que le propriétaire de forme contient."
#: doc/classes/CollisionObject.xml
-#, fuzzy
msgid ""
"Returns the child index of the [Shape] with the given id from the given "
"shape owner."
-msgstr "Retourne la liste de tous les nœuds du shader avec le type spécifié."
+msgstr ""
#: doc/classes/CollisionObject.xml
msgid "Returns the shape owner's [Transform]."
@@ -17723,6 +18388,10 @@ msgid ""
"the mouse pointer entering/leaving, and if the mouse is inside it, report "
"input events. Requires at least one [member collision_layer] bit to be set."
msgstr ""
+"Si [code]true[/code], cet objet peut être sélectionné. Ces objets peuvent "
+"détecter l'entrée/la sortie du pointeur de la souris sur eux, et si la "
+"souris pointe sur l'objet, signaler par des événements d'entrée. Nécessite "
+"au moins un bit de [member collision_layer] d'être réglé."
#: doc/classes/CollisionObject.xml
msgid ""
@@ -17778,6 +18447,10 @@ msgid ""
"[Shape2D]. Connect to the [code]input_event[/code] signal to easily pick up "
"these events."
msgstr ""
+"Accepte les [InputEvent] non traités. Nécessite [member input_pickable] "
+"d'être à [code]true[/code]. [code]shape_idx[/code] est l'index de la "
+"[Shape2D] enfant. Connectez-vous au signal [code]input_event[/code] pour "
+"récupérer facilement ces événements."
#: doc/classes/CollisionObject2D.xml
msgid ""
@@ -17793,6 +18466,9 @@ msgid ""
"this [CollisionObject2D] will not be reported to collided with "
"[CollisionObject2D]s."
msgstr ""
+"Retourne [code]true[/code] si les collisions pour le propriétaire de forme "
+"venant de ce [CollisionObject2D] ne seront pas signalées aux "
+"[CollisionObject2D] entrants en collision."
#: doc/classes/CollisionObject2D.xml
msgid "Adds a [Shape2D] to the shape owner."
@@ -17801,12 +18477,16 @@ msgstr "Ajoute un [Shape2D] au propriétaire de la forme."
#: doc/classes/CollisionObject2D.xml
msgid "Returns the [Shape2D] with the given id from the given shape owner."
msgstr ""
+"Retourne la [Shape2D] avec l'identifiant donné du propriétaire donné de la "
+"forme."
#: doc/classes/CollisionObject2D.xml
msgid ""
"Returns the child index of the [Shape2D] with the given id from the given "
"shape owner."
msgstr ""
+"Retourne l'indice de enfant du [Shape2D] avec l'identifiant donné du "
+"propriétaire donné de forme."
#: doc/classes/CollisionObject2D.xml
msgid "Returns the shape owner's [Transform2D]."
@@ -17818,12 +18498,17 @@ msgid ""
"originating from this [CollisionObject2D] will not be reported to collided "
"with [CollisionObject2D]s."
msgstr ""
+"Si [code]enable[/code] est [code]true[/code], les collisions pour le "
+"propriétaire de forme original de ce [CollisionObject2D] ne seront pas "
+"rapportées aux [CollisionObject2D] entrant en collision."
#: doc/classes/CollisionObject2D.xml
msgid ""
"Sets the [code]one_way_collision_margin[/code] of the shape owner identified "
"by given [code]owner_id[/code] to [code]margin[/code] pixels."
msgstr ""
+"Définit la marge [code]one_way_collision_margin[/code] du propriétaire de la "
+"forme identifié par [code]owner_id[/code] à [code]margin[/code] pixels."
#: doc/classes/CollisionObject2D.xml
msgid "Sets the [Transform2D] of the given shape owner."
@@ -17910,12 +18595,20 @@ msgid ""
"editor. It will not appear in the scene tree at run-time. Creates a [Shape] "
"for gameplay. Properties modified during gameplay will have no effect."
msgstr ""
+"Permet d'éditer des sommets de collision sur un plan sélectionné. Peut "
+"également définir une profondeur perpendiculaire à ce plan. Cette classe "
+"n'est disponible que dans l'éditeur. Elle n'apparaîtra pas dans "
+"l'arborescence de la scène quand le jeu est lancé. Crée une [Shape] pour les "
+"mécaniques de jeu. Les propriétés modifiées une fois le jeu lancé n'auront "
+"aucun effet."
#: doc/classes/CollisionPolygon.xml
msgid ""
"Length that the resulting collision extends in either direction "
"perpendicular to its polygon."
msgstr ""
+"La longueur que la collision résultante s'étend dans la direction "
+"perpendiculaire à son polygone."
#: doc/classes/CollisionPolygon.xml
msgid "If [code]true[/code], no collision will be produced."
@@ -17926,6 +18619,8 @@ msgid ""
"The collision margin for the generated [Shape]. See [member Shape.margin] "
"for more details."
msgstr ""
+"La marge de collision pour la [Shape] générée. Voir [member Shape.margin] "
+"pour plus d'informations."
#: doc/classes/CollisionPolygon.xml
msgid ""
@@ -17936,6 +18631,12 @@ msgid ""
"temporary variable and make changes before reassigning the [code]polygon[/"
"code] member."
msgstr ""
+"Un tableau de sommets qui définissent le polygone.\n"
+"[b]Note :[/b] La valeur retournée est une copie de l'original. Les méthodes "
+"qui modifie la taille ou les propriétés de la valeur de retour n'affecteront "
+"pas le polygone d'origine. Pour modifier les propriétés du polygone, "
+"assignez-le à une variable temporaire et faites des changements avant de le "
+"réassigner au membre [code]polygon[/code]."
#: doc/classes/CollisionPolygon2D.xml
msgid "Defines a 2D collision polygon."
@@ -17946,10 +18647,14 @@ msgid ""
"Provides a 2D collision polygon to a [CollisionObject2D] parent. Polygons "
"can be drawn in the editor or specified by a list of vertices."
msgstr ""
+"Fournit un polygone de collision 2D à un parent [CollisionObject2D]. Les "
+"polygones peuvent être dessinés manuellement dans l'éditeur ou spécifiés par "
+"une liste de sommets."
#: doc/classes/CollisionPolygon2D.xml
msgid "Collision build mode. Use one of the [enum BuildMode] constants."
msgstr ""
+"Le mode d'assemblage. Utilisez l'une des constantes de [enum BuildMode]."
#: doc/classes/CollisionPolygon2D.xml
msgid "If [code]true[/code], no collisions will be detected."
@@ -17962,6 +18667,11 @@ msgid ""
"[b]Note:[/b] This property has no effect if this [CollisionPolygon2D] is a "
"child of an [Area2D] node."
msgstr ""
+"Si [code]true[/code], seuls les bords qui font face, par rapport à la "
+"rotation du [CollisionPolygon2D], entreront en collision avec d'autres "
+"objets.\n"
+"[b]Note :[/b] Cette propriété n'a aucun effet si cette [CollisionPolygon2D] "
+"est un enfant d'un nœud [Area2D]."
#: doc/classes/CollisionPolygon2D.xml
msgid ""
@@ -17969,6 +18679,9 @@ msgid ""
"the shape thicker, and work better for colliders that enter the polygon at a "
"high velocity."
msgstr ""
+"La marge (en pixels) utilisée pour une collision à sens unique. Des valeurs "
+"plus élevées rendront la forme plus épaisse, et fonctionneront mieux pour "
+"les objets entrant en collision quand ils vont à une vitesse élevée."
#: doc/classes/CollisionPolygon2D.xml
msgid ""
@@ -18001,6 +18714,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 +18768,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
@@ -18056,11 +18783,12 @@ msgid "2D Kinematic Character Demo"
msgstr "Démo de caractère cinétique 2D"
#: doc/classes/CollisionShape2D.xml
-#, fuzzy
msgid ""
"A disabled collision shape has no effect in the world. This property should "
"be changed with [method Object.set_deferred]."
-msgstr "Une forme de collision désactivée n’a aucun effet dans le monde."
+msgstr ""
+"Une forme de collision désactivée n’a aucun effet dans le monde. Cette "
+"propriété devrait être modifiée avec [method Object.set_deferred]."
#: doc/classes/CollisionShape2D.xml
msgid ""
@@ -18245,6 +18973,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 +19002,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 +19167,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 +19601,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 +19828,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."
@@ -19152,11 +19887,18 @@ msgid ""
"in the color picker and the user will be able to select them.\n"
"[b]Note:[/b] The presets list is only for [i]this[/i] color picker."
msgstr ""
+"Ajoute la couleur donnée à une liste de pré-réglages de couleur. Les pré-"
+"réglages sont affichés dans le sélectionneur de couleurs que l'utilisateur "
+"pourra sélectionner.\n"
+"[b]Note :[/b] La liste des pré-réglages est seulement pour [i]ce[/i] "
+"sélectionneur de couleur."
#: doc/classes/ColorPicker.xml
msgid ""
"Removes the given color from the list of color presets of this color picker."
msgstr ""
+"Retire la couleur donnée de la liste des pré-réglages de couleur de ce "
+"sélectionneur de couleur."
#: doc/classes/ColorPicker.xml
msgid "Returns the list of colors in the presets of the color picker."
@@ -19173,11 +19915,14 @@ msgid ""
"mouse button, otherwise it will apply immediately even in mouse motion event "
"(which can cause performance issues)."
msgstr ""
+"Si [code]true[/code], la couleur ne s'appliquera que quand l'utilisateur "
+"relâche le bouton de la souris, sinon elle s'appliquera immédiatement en "
+"suivant le déplacement de la souris (ce qui peut causer des problèmes de "
+"performance)."
#: doc/classes/ColorPicker.xml
-#, fuzzy
msgid "If [code]true[/code], shows an alpha channel slider (opacity)."
-msgstr "Si [code]true[/code], le GraphNode est sélectionné."
+msgstr ""
#: doc/classes/ColorPicker.xml
msgid ""
@@ -19185,6 +19930,9 @@ msgid ""
"sliders.\n"
"[b]Note:[/b] Cannot be enabled if raw mode is on."
msgstr ""
+"Si [code]true[/code], permet de modifier la couleur avec des curseurs teinte/"
+"saturation/valeur.\n"
+"[b]Note :[/b] Ne peut être activé si le mode brut est activé."
#: doc/classes/ColorPicker.xml
msgid "If [code]true[/code], the \"add preset\" button is enabled."
@@ -19252,10 +20000,12 @@ msgid ""
"The indicator used to signalize that the color value is outside the 0-1 "
"range."
msgstr ""
+"L'indicateur utilisé pour signaler que la valeur de couleur est en dehors de "
+"l'intervalle 0-1."
#: doc/classes/ColorPicker.xml
msgid "The icon for the screen color picker button."
-msgstr ""
+msgstr "L'icône pour le bouton de sélecteur de couleurs."
#: doc/classes/ColorPickerButton.xml
msgid "Button that pops out a [ColorPicker]."
@@ -19271,6 +20021,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 +20036,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 +20050,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 +20073,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 +20095,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 +20130,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 +20155,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 +20183,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 +20216,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 ""
@@ -19645,18 +20441,25 @@ msgid ""
"Deletes the specified section along with all the key-value pairs inside. "
"Raises an error if the section does not exist."
msgstr ""
+"Supprime la section spécifiée ainsi que toutes ses paires valeur-clé avec. "
+"Affiche une erreur si la section n'existe pas."
#: doc/classes/ConfigFile.xml
msgid ""
"Deletes the specified key in a section. Raises an error if either the "
"section or the key do not exist."
msgstr ""
+"Supprime la clé spécifiée dans une section. Affiche une erreur si la section "
+"ou la clé n'existe pas."
#: doc/classes/ConfigFile.xml
msgid ""
"Returns an array of all defined key identifiers in the specified section. "
"Raises an error and returns an empty array if the section does not exist."
msgstr ""
+"Retourne un tableau de tous les identifiants des clés définis dans la "
+"section spécifiée. Affiche une erreur et retourne un tableau vide si la "
+"section n'existe pas."
#: doc/classes/ConfigFile.xml
msgid "Returns an array of all defined section identifiers."
@@ -19669,6 +20472,10 @@ msgid ""
"[code]default[/code] value. If [code]default[/code] is not specified or set "
"to [code]null[/code], an error is also raised."
msgstr ""
+"Retourne l'actuelle valeur pour la section et la clé spécifiées. Si la "
+"section ou la clé n'existent pas, la méthode retourne la valeur du paramètre "
+"[code]default[/code]. Si [code]default[/code] n'est pas spécifié ou défini à "
+"[code]null[/code], une erreur est affichée."
#: doc/classes/ConfigFile.xml
msgid "Returns [code]true[/code] if the specified section exists."
@@ -19686,6 +20493,10 @@ msgid ""
"on.\n"
"Returns one of the [enum Error] code constants ([code]OK[/code] on success)."
msgstr ""
+"Charge le fichier de configuration spécifié en paramètre. Le contenu du "
+"fichier est interprété et chargé dans l'objet [ConfigFile] sur lequel la "
+"méthode a été appelée.\n"
+"Retourne un des codes [enum Error] ([code]OK[/code] en cas de succès)."
#: doc/classes/ConfigFile.xml
msgid ""
@@ -19694,6 +20505,11 @@ msgid ""
"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é en paramètre, en "
+"utilisant la clé [code]key[/code] fournie pour le décrypter. Le contenu du "
+"fichier est interprété et chargé dans l'objet [ConfigFile] sur lequel la "
+"méthode a été appelée.\n"
+"Retourne un des codes [enum Error] ([code]OK[/code] en cas de succès)."
#: doc/classes/ConfigFile.xml
msgid ""
@@ -19702,6 +20518,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 +20530,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 +20541,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 ""
@@ -19751,6 +20579,10 @@ msgid ""
"code] value deletes the specified key if it exists, and deletes the section "
"if it ends up empty once the key has been removed."
msgstr ""
+"Attribue une valeur à la clé spécifiée de la section spécifiée. Si la "
+"section ou la clé n'existe pas, elles sont créées. Passer une valeur "
+"[code]null[/code] supprime la clé spécifiée si elle existe, et supprime la "
+"section si elle est vide une fois que la clé a été supprimée."
#: doc/classes/ConfirmationDialog.xml
msgid "Dialog for confirmation of actions."
@@ -19781,6 +20613,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 bouton annuler.\n"
+"[b]Avertissement :[/b] Il s'agit d'un nœud interne requis, le retirer et le "
+"libérer peut causer un plantage. Si vous voulez le cacher lui ou un de ses "
+"enfants, utilisez la propriété [member CanvasItem.visible]."
#: doc/classes/Container.xml
msgid "Base node for containers."
@@ -19792,18 +20628,26 @@ msgid ""
"automatically arranges them in a certain way.\n"
"A Control can inherit this to create custom container classes."
msgstr ""
+"Le nœud de base pour les conteneurs. Un [Container] contient d'autres "
+"contrôles et les arrange automatiquement d'une certaine manière.\n"
+"Un Control peut en hériter pour créer des classes de conteneur qui arrange "
+"les contrôles enfants de manière personnalisée."
#: doc/classes/Container.xml
msgid ""
"Fit a child control in a given rect. This is mainly a helper for creating "
"custom container classes."
msgstr ""
+"Ajuste un contrôle enfant dans un rectangle donné. Il s'agit principalement "
+"d'une aide pour créer des classes de conteneurs personnalisées."
#: doc/classes/Container.xml
msgid ""
"Queue resort of the contained children. This is called automatically anyway, "
"but can be called upon request."
msgstr ""
+"Ajoute un commande de tri pour les contrôles enfants. Ceci est appelé "
+"automatiquement de tous les cas, mais peut être appelé sur demande."
#: doc/classes/Container.xml
msgid "Emitted when sorting the children is needed."
@@ -19813,12 +20657,17 @@ msgstr "Émis quand le tri des enfants est nécessaire."
msgid ""
"Notification for when sorting the children, it must be obeyed immediately."
msgstr ""
+"La notification pour le tri des enfants, à laquelle faut l'obéir "
+"immédiatement."
#: doc/classes/Control.xml
msgid ""
"All user interface nodes inherit from Control. A control's anchors and "
"margins adapt its position and size relative to its parent."
msgstr ""
+"Tous les nœuds d'interface utilisateur héritent de Control. Les ancres et "
+"les marges des contrôles adaptent leur position et leur taille par rapport à "
+"son parent."
#: doc/classes/Control.xml
msgid ""
@@ -19905,7 +20754,7 @@ msgstr "Galerie des nœuds de contrôle"
#: doc/classes/Control.xml
msgid "All GUI Demos"
-msgstr ""
+msgstr "Toutes les démos d'interface"
#: doc/classes/Control.xml
msgid ""
@@ -19915,6 +20764,13 @@ msgid ""
"Similar to [member rect_clip_content], but doesn't affect visibility.\n"
"If not overridden, defaults to [code]false[/code]."
msgstr ""
+"Méthode virtuelle à surcharger par l'utilisateur. Retourne si [méthode "
+"gui_input] ne doit pas être appelé pour les contrôles enfants en dehors du "
+"rectangle englobant du contrôle. L'entrée sera limitée au Rect de ce "
+"[Control]. Similaire à [member rect_clip_content], mais n'affecte pas la "
+"visibilité.\n"
+"Si la méthode n'est pas surchargée, la valeur par défaut retournée est "
+"[code]false[/code]."
#: doc/classes/Control.xml
msgid ""
@@ -20091,15 +20947,12 @@ msgstr ""
"[/codeblock]"
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Creates a local override for a theme constant with the specified [code]name[/"
"code]. Local overrides always take precedence when fetching theme items for "
"the control.\n"
"See also [method get_constant], [method remove_constant_override]."
msgstr ""
-"Retourne [code]true[/code] si le paramètre spécifié par [code]name[/code] "
-"existe, [code]false[/code] autrement."
#: doc/classes/Control.xml
msgid ""
@@ -20276,6 +21129,12 @@ msgid ""
"The methods [method can_drop_data] and [method drop_data] must be "
"implemented on controls that want to receive drop data."
msgstr ""
+"Force le glissage et contourne [method get_drag_data] et [method "
+"set_drag_preview] en passant [code]data[/code] et [code]preview[/code]. Le "
+"glissage va commencer même si la souris n'est ni sur, ni appuyé sur ce "
+"contrôle.\n"
+"Les méthodes [method can_drop_data] et [method drop_data] doivent être "
+"implémentées pour les contrôles qui veulent recevoir ces données de glissage."
#: doc/classes/Control.xml
msgid ""
@@ -20368,6 +21227,8 @@ msgid ""
"Returns the mouse cursor shape the control displays on mouse hover. See "
"[enum CursorShape]."
msgstr ""
+"Retourne le curseur de la souris que le contrôle affiche quand la souris le "
+"survole. Voir [enum CursorShape]."
#: doc/classes/Control.xml
msgid ""
@@ -20413,6 +21274,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 +21292,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 +21312,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 +21323,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]."
@@ -20455,9 +21334,8 @@ msgstr ""
"Retourne la taille minimale de ce contrôle. Voir [member rect_min_size]."
#: doc/classes/Control.xml
-#, fuzzy
msgid "Returns the width/height occupied in the parent control."
-msgstr "Renvoie la largeur / hauteur occupée dans le contrôle du parent."
+msgstr "Retourne la largeur / hauteur occupée dans le contrôle du parent."
#: doc/classes/Control.xml
msgid "Returns the parent control node."
@@ -20468,6 +21346,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 +21360,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 ""
@@ -20487,6 +21371,10 @@ msgid ""
"[Theme] has a valid [member Theme.default_font] value.\n"
"See [method get_color] for details."
msgstr ""
+"Retourne la police par défaut de la première correspondance [Theme] trouvée "
+"dans l'arborescence si ce [Theme] a une valeur valide pour [member Theme."
+"default_font].\n"
+"Voir [method get_color] pour plus de détails."
#: doc/classes/Control.xml
msgid ""
@@ -20506,6 +21394,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 +21417,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 +21439,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 +21515,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 ""
@@ -20630,6 +21539,10 @@ msgid ""
"[code]theme_type[/code].\n"
"See [method get_color] for details."
msgstr ""
+"Retourne [code]true[/code] s'il y a une correspondance [Theme] dans "
+"l'arborescence qui a un élément de la boîte de style avec le code spécifié "
+"[code]name[/code] et [code]theme_type[/code].\n"
+"Voir [method get_color] pour plus de détails."
#: doc/classes/Control.xml
msgid ""
@@ -20658,44 +21571,44 @@ msgid ""
"changed. Setting [member rect_min_size] directly calls this method "
"automatically."
msgstr ""
+"Invalide le cache de taille de ce nœud et des nœuds parents jusqu'à la "
+"racine. Prévu pour être utilisé avec [method get_minimum_size] quand la "
+"valeur de retour est changée. Définir [member rect_min_size] appelle cette "
+"méthode automatiquement."
#: doc/classes/Control.xml
msgid ""
"Give up the focus. No other control will be able to receive keyboard input."
msgstr ""
+"Relâche le focus. Aucun autre contrôle ne pourra recevoir les entrées du "
+"clavier."
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Removes a theme override for a [Color] with the given [code]name[/code]."
-msgstr "Supprime l’animation avec la touche [code]name[/code]."
+msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Removes a theme override for a constant with the given [code]name[/code]."
-msgstr "Supprime l’animation avec la touche [code]name[/code]."
+msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid "Removes a theme override for a [Font] with the given [code]name[/code]."
-msgstr "Supprime l’animation avec la touche [code]name[/code]."
+msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid "Removes a theme override for an icon with the given [code]name[/code]."
-msgstr "Supprime l’animation avec la touche [code]name[/code]."
+msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid "Removes a theme override for a shader with the given [code]name[/code]."
-msgstr "Retourne la position du point à l'index [code]point[/code]."
+msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Removes a theme override for a [StyleBox] with the given [code]name[/code]."
-msgstr "Supprime l’animation avec la touche [code]name[/code]."
+msgstr ""
#: doc/classes/Control.xml
msgid ""
@@ -20731,12 +21644,18 @@ msgid ""
"code] argument and automatic update of margin, it allows to set the margin "
"offset yourself (see [method set_margin])."
msgstr ""
+"Fonctionne comme [method set_anchor], mais au lieu de l'argument "
+"[code]keep_margin[/code] et de la mise à jour automatique de la marge, ça "
+"permet de définir la marge de décalage par vous-même (voir [method "
+"set_margin])."
#: doc/classes/Control.xml
msgid ""
"Sets both anchor preset and margin preset. See [method set_anchors_preset] "
"and [method set_margins_preset]."
msgstr ""
+"Définit à la fois le préréglage de l'ancre et de la marge. Voir [method "
+"set_anchors_preset] et [method set_margins_preset]."
#: doc/classes/Control.xml
msgid ""
@@ -20746,6 +21665,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 +21807,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 +21824,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 +21841,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 +21855,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 ""
@@ -20925,6 +21869,15 @@ msgid ""
"If [code]exclusive[/code] is [code]true[/code], other controls will not "
"receive input and clicking outside this control will not close it."
msgstr ""
+"Affiche un contrôle en tant que modal. Le contrôle doit être une sous-"
+"fenêtre. Les contrôles de modal capturent les signaux d'entrée jusqu'à ce "
+"que la zone située à l'extérieur soit accessible. Lorsqu'un contrôle modal "
+"perd le focus, ou que la touche échap est pressée, il disparait "
+"automatiquement. Les contrôles de modal sont largement utilisés pour les "
+"dialogues surgissants (popup) et les menus.\n"
+"Si [code]exclusif[/code] est [code]true[/code], les autres contrôles ne "
+"recevront pas les entrées, et cliquer à l'extérieur de ce contrôle ne le "
+"fermera pas."
#: doc/classes/Control.xml
msgid ""
@@ -20941,6 +21894,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 +21906,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 +21918,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,12 +21929,19 @@ 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 ""
"The focus access mode for the control (None, Click or All). Only one Control "
"can be focused at the same time, and it will receive keyboard signals."
msgstr ""
+"Le mode de focus du contrôle (aucun, clic ou tous). Un seul contrôle peut "
+"avoir le focus à un moment donné, et il recevra des signaux des touches du "
+"clavier appuyées."
#: doc/classes/Control.xml
msgid ""
@@ -21065,6 +22037,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 +22048,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 +22104,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 +22202,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 +22222,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 +22235,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 +22246,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 +22296,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 +22305,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 +22317,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 +22329,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 +22408,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 +22454,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 +22474,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 +22507,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 ""
@@ -21503,6 +22546,9 @@ msgid ""
"beam pointer has a shape similar to \"I\". It tells the user they can "
"highlight or insert text."
msgstr ""
+"Affiche le curseur de la souris en forme de I lorsque l'utilisateur survole "
+"le nœud. Le pointeur en I a une forme semblable à un \"I\". Il signale à "
+"l'utilisateur qu'il peut insérer ou surligner du texte."
#: doc/classes/Control.xml
msgid ""
@@ -21515,20 +22561,20 @@ msgstr ""
"Affiche le curseur en croix du système quand l'utilisateur survole ce nœud."
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Show the system's wait mouse cursor when the user hovers the node. Often an "
"hourglass."
msgstr ""
-"Affiche le curseur en croix du système quand l'utilisateur survole ce nœud."
+"Affiche le curseur d'attente du système quand l'utilisateur survole ce nœud. "
+"Souvent un sablier."
#: doc/classes/Control.xml
-#, fuzzy
msgid ""
"Show the system's busy mouse cursor when the user hovers the node. Often an "
"arrow with a small hourglass."
msgstr ""
-"Affiche le curseur en croix du système quand l'utilisateur survole ce nœud."
+"Affiche le curseur d'occupation du système quand l'utilisateur survole ce "
+"nœud. Souvent une flèche avec un petit sablier."
#: doc/classes/Control.xml
msgid ""
@@ -21623,72 +22669,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 +22768,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 +22780,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 +22792,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 +22804,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 +22832,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 +22860,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 +22872,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 +22990,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,16 +23002,21 @@ 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."
msgstr "Forme de polygone convexe pour la physique 3D."
#: doc/classes/ConvexPolygonShape.xml
-#, fuzzy
msgid ""
"Convex polygon shape resource, which can be added to a [PhysicsBody] or area."
-msgstr "Ressource de forme de polygone concave 2D pour la physique."
+msgstr ""
+"Un ressource de forme de polygone convexe, qui peut être ajoutée à un "
+"[PhysicsBody] ou une aire."
#: doc/classes/ConvexPolygonShape.xml
msgid "The list of 3D points forming the convex polygon shape."
@@ -21920,6 +23037,15 @@ 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 ""
+"Forme polygone convexe pour la physique 2D. Un polygone convexe, quelle que "
+"soit sa forme, est décomposé en interne par d'autant de polygones convexes "
+"que nécessaire pour assurer que toutes les collisions sont toujours "
+"effectués sur les polygones convexes (ce qui sont plus rapide à vérifier).\n"
+"La principale différence entre un [ConvexPolygonShape2D] et un "
+"[ConcavePolygonShape2D] est qu'un polygone concave suppose toujours qu'il "
+"est concave et utilise une méthode plus complexe pour la détection des "
+"collisions, alors qu'un polygone convexe suppose toujours qu'il est convexe "
+"pour accélérer la détection des collisions."
#: doc/classes/ConvexPolygonShape2D.xml
msgid ""
@@ -21927,6 +23053,10 @@ msgid ""
"points] property using the convex hull algorithm. Removing all unneeded "
"points. See [method Geometry.convex_hull_2d] for details."
msgstr ""
+"Basé sur l'ensemble des points fournis, cela crée et définit la propriété "
+"[member points] en utilisant l'algorithme de découpage convexe. Ça enlève "
+"aussi tous les points inutiles. Voir [method Geometry.convex_hull_2d] pour "
+"plus de détails."
#: doc/classes/ConvexPolygonShape2D.xml
msgid ""
@@ -21935,6 +23065,10 @@ msgid ""
"[method set_point_cloud] to generate a convex hull shape from concave shape "
"points."
msgstr ""
+"La liste des sommets du polygone. Peut être dans le sens horaire ou dans le "
+"sens anti-horaire. Ne définissez cette propriété qu'avec des points d'une "
+"forme convexe, et utilisez [method set_point_cloud] pour générer une forme "
+"convexe à partir de points d'une forme concave."
#: doc/classes/CPUParticles.xml
msgid "CPU-based 3D particle emitter."
@@ -21949,12 +23083,22 @@ msgid ""
"[b]Note:[/b] Unlike [Particles], the visibility rect is generated on-the-fly "
"and doesn't need to be configured by the user."
msgstr ""
+"Un nœud pour les particules 3D fonctionnant sur le CPU utilisé pour créer "
+"une grande variété d'effets de particules.\n"
+"Voir aussi [Particles], qui fournit la même fonctionnalité mais avec "
+"l'accélération matérielle (via GPU), mais ne peut pas fonctionner sur des "
+"appareils plus anciens.\n"
+"[b]Note :[/b] Contrairement aux [Particles], le rect de visibilité est "
+"généré à lors de émission et n'a pas besoin d'être configuré par "
+"l'utilisateur."
#: doc/classes/CPUParticles.xml
msgid ""
"Sets this node's properties to match a given [Particles] node with an "
"assigned [ParticlesMaterial]."
msgstr ""
+"Génère les propriétés de ce nœud pour correspondre à un nœud [Particules] "
+"avec en plus un nœud assigné [ParticlesMaterial]."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid "Returns the base value of the parameter specified by [enum Parameter]."
@@ -22012,6 +23156,11 @@ msgid ""
"therefore removing all particles that were already emitted before changing "
"[member amount]."
msgstr ""
+"Le nombre de particules émises dans un cycle d'émission (correspondant à la "
+"durée [member lifetime]).\n"
+"[b]Note :[/b] Changer [member amount] réinitialisera l'émission des "
+"particules, supprimant ainsi toutes les particules déjà émises avant de "
+"changer [member amount]."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid "Initial rotation applied to each particle, in degrees."
@@ -22083,6 +23232,9 @@ msgid ""
"[SpatialMaterial] make sure to set [member SpatialMaterial."
"vertex_color_use_as_albedo] to [code]true[/code]."
msgstr ""
+"La couleur initiale de chaque particule. Pour utiliser cette couleur dans un "
+"[SpatialMaterial], assurez-vous de définir [membrer SpatialMaterial."
+"vertex_color_use_as_albedo] à [code]true[/code]."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -22090,6 +23242,8 @@ msgid ""
"Each particle's initial color will vary along this [GradientTexture] "
"(multiplied with [member color])."
msgstr ""
+"La couleur initiale de chaque particule qui varie suivant la "
+"[GradientTexture] (multipliée avec [member color])."
#: doc/classes/CPUParticles.xml doc/classes/ParticlesMaterial.xml
msgid ""
@@ -22110,7 +23264,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 +23292,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 +23308,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 +23330,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 ""
@@ -22217,6 +23377,10 @@ msgid ""
"the value to 2 will make the particles render at 2 frames per second. Note "
"this does not slow down the particle system itself."
msgstr ""
+"Le nombre de trames du système de particules est fixé à une valeur. Par "
+"exemple, changer la valeur à 2 rendra les particules à 2 trames par seconde. "
+"Notez que cela ne ralentit pas le système de particules lui-même juste "
+"l'affichage final."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -22240,6 +23404,8 @@ msgid ""
"Amount of [member spread] in Y/Z plane. A value of [code]1[/code] restricts "
"particles to X/Z plane."
msgstr ""
+"La quantité d'éparpillement [member spread] dans le plan Y/Z. Une valeur de "
+"[code]1[/code] limite les particules au plan X/Z."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/Particles.xml doc/classes/Particles2D.xml
@@ -22247,6 +23413,8 @@ msgid ""
"If [code]true[/code], results in fractional delta calculation which has a "
"smoother particles display effect."
msgstr ""
+"Si [code]true[/code], utilise un calcul d'étape fractionnelle qui permet "
+"affichage plus lisse des particules."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -22273,6 +23441,8 @@ msgid ""
"Initial velocity magnitude for each particle. Direction comes from [member "
"spread] and the node's orientation."
msgstr ""
+"La magnitude de la vitesse initiale de chaque particule. L'orientation "
+"dépend de [member spread] et de l'orientation du nœud."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -22294,6 +23464,8 @@ msgstr "Facteur d'aléatoire de la durée de vie d'une particule."
msgid ""
"Linear acceleration applied to each particle in the direction of motion."
msgstr ""
+"L'accélération linéaire appliquée à chaque particule dans la direction du "
+"mouvement."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid "Each particle's linear acceleration will vary along this [Curve]."
@@ -22312,6 +23484,9 @@ msgid ""
"If [code]true[/code], particles use the parent node's coordinate space. If "
"[code]false[/code], they use global coordinates."
msgstr ""
+"Si [code]true[/code], les particules utilisent l'espace de coordonnées du "
+"parent du nœud. Si [code]false[/code], ils utilisent des coordonnées "
+"globales."
#: doc/classes/CPUParticles.xml
msgid ""
@@ -22327,6 +23502,9 @@ msgid ""
"If [code]true[/code], only one emission cycle occurs. If set [code]true[/"
"code] during a cycle, emission will stop at the cycle's end."
msgstr ""
+"Si [code]true[/code], un seul cycle d'émission se produit. Si définit à "
+"[code]true[/code] pendant un cycle, l'émission s'arrêtera à la fin de ce "
+"cycle."
#: doc/classes/CPUParticles.xml
msgid ""
@@ -22336,6 +23514,11 @@ msgid ""
"This property is only available when [member flag_disable_z] is [code]true[/"
"code]."
msgstr ""
+"La vitesse orbitale appliquée à chaque particule. Fait tourner les "
+"particules autour d'origine sur le plan XY local. Spécifié en nombre de "
+"rotations complètes autour de l'origine par seconde.\n"
+"Cette propriété est uniquement disponible lorsque [member flag_disable_z] "
+"est [code]true[/code]."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid "Each particle's orbital velocity will vary along this [Curve]."
@@ -22352,6 +23535,8 @@ msgstr "Facteur d'aléatoire de la vélocité orbitale."
#: doc/classes/Particles2D.xml
msgid "Particle system starts as if it had already run for this many seconds."
msgstr ""
+"Le système de particules démarre comme s'il avait déjà commencé depuis "
+"plusieurs secondes."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -22398,12 +23583,17 @@ msgid ""
"Particle system's running speed scaling ratio. A value of [code]0[/code] can "
"be used to pause the particles."
msgstr ""
+"Le facteur de vitesse du système de particules. Une valeur de [code]0[/code] "
+"peut être utilisée pour arrêter les particules."
#: 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 ""
+"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
@@ -22412,6 +23602,9 @@ msgid ""
"perpendicular to the particle's velocity giving the particles a swirling "
"motion."
msgstr ""
+"L'accélération tangentielle appliquée à chaque particule. Elle est "
+"perpendiculaire à la vitesse de la particule, ce qui donne aux particules un "
+"mouvement de glissement."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid "Each particle's tangential acceleration will vary along this [Curve]."
@@ -22445,30 +23638,40 @@ msgid ""
"Use with [method set_param], [method set_param_randomness], and [method "
"set_param_curve] to set initial velocity properties."
msgstr ""
+"À utiliser avec [method set_param], [method set_param_randomness], et "
+"[method set_param_curve] pour définir les propriétés de vitesse initiale."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid ""
"Use with [method set_param], [method set_param_randomness], and [method "
"set_param_curve] to set angular velocity properties."
msgstr ""
+"À utiliser avec [method set_param], [method set_param_randomness], et "
+"[method set_param_curve] pour définir les propriétés de vitesse angulaire."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid ""
"Use with [method set_param], [method set_param_randomness], and [method "
"set_param_curve] to set orbital velocity properties."
msgstr ""
+"À utiliser avec [method set_param], [method set_param_randomness], et "
+"[method set_param_curve] pour définir les propriétés de vitesse orbitale."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid ""
"Use with [method set_param], [method set_param_randomness], and [method "
"set_param_curve] to set linear acceleration properties."
msgstr ""
+"À utiliser avec [method set_param], [method set_param_randomness], et "
+"[method set_param_curve] pour définir les propriétés d'accélération linéaire."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid ""
"Use with [method set_param], [method set_param_randomness], and [method "
"set_param_curve] to set radial acceleration properties."
msgstr ""
+"À utiliser avec [method set_param], [method set_param_randomness], et "
+"[method set_param_curve] pour définir les propriétés d'accélération radiale."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid ""
@@ -22572,6 +23775,9 @@ msgid ""
"emission_points]. Particle color will be modulated by [member "
"emission_colors]."
msgstr ""
+"Les particules seront émises à une position choisie au hasard parmi les "
+"points [member emission_points]. La couleur des particules sera modulée par "
+"[member emission_colors]."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid ""
@@ -22580,6 +23786,10 @@ msgid ""
"[member emission_normals]. Particle color will be modulated by [member "
"emission_colors]."
msgstr ""
+"Les particules seront émises à une position choisie au hasard parmi [member "
+"emission_points]. La vitesse et la rotation des particules seront "
+"déterminées en fonction de [member emission_normals]. La couleur des "
+"particules sera modulée par [member emission_colors]."
#: doc/classes/CPUParticles.xml doc/classes/ParticlesMaterial.xml
msgid "Particles will be emitted in a ring or cylinder."
@@ -22603,36 +23813,53 @@ msgid ""
"[b]Note:[/b] Unlike [Particles2D], the visibility rect is generated on-the-"
"fly and doesn't need to be configured by the user."
msgstr ""
+"Nœud de particules 2D calculées par le CPU pour créer une variété de "
+"systèmes et d'effets de particules.\n"
+"Voir aussi [Particles2D], qui fournit la même fonctionnalité mais en "
+"utilisant l'accélération matérielle, mais ne peut pas fonctionner sur des "
+"appareils plus anciens.\n"
+"[b]Note :[/b] Contrairement [Particles2D], le rectangle de visibilité est "
+"généré à l'émission et n'a donc pas besoin d'être définit par l'utilisateur."
#: doc/classes/CPUParticles2D.xml
msgid ""
"Sets this node's properties to match a given [Particles2D] node with an "
"assigned [ParticlesMaterial]."
msgstr ""
+"Définit les propriétés de ce nœud pour correspondre à au nœud [Particles2D] "
+"spécifié, en incluant un nœud [ParticlesMaterial]."
#: doc/classes/CPUParticles2D.xml
msgid ""
"Each particle's initial color. If [member texture] is defined, it will be "
"multiplied by this color."
msgstr ""
+"La couleur initiale de chaque particule. Si [member texture] est défini, les "
+"particules sont multipliées par cette couleur."
#: doc/classes/CPUParticles2D.xml
msgid ""
"Each particle's color will vary along this [Gradient] (multiplied with "
"[member color])."
msgstr ""
+"Chaque couleur de particle varie selon ce [Gradient] (multiplié avec [member "
+"color])."
#: doc/classes/CPUParticles2D.xml
msgid ""
"The rectangle's extents if [member emission_shape] is set to [constant "
"EMISSION_SHAPE_RECTANGLE]."
msgstr ""
+"Le rectangle d'émission si [member emission_shape] est [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 ""
+"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
@@ -22641,6 +23868,10 @@ msgid ""
"the value to 2 will make the particles render at 2 frames per second. Note "
"this does not slow down the simulation of the particle system itself."
msgstr ""
+"Le nombre de trames du système de particules est fixé à une valeur. Par "
+"exemple, changer la valeur à 2 rendra les particules à 2 trames par seconde. "
+"Notez que cela ne ralentit pas le système de particules lui-même juste "
+"l'affichage final."
#: doc/classes/CPUParticles2D.xml doc/classes/Particles2D.xml
msgid ""
@@ -22650,12 +23881,21 @@ msgid ""
"Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for "
"a comparison of normal map coordinates expected by popular engines."
msgstr ""
+"La texture de normale à utiliser pour la propriété [member texture].\n"
+"[b]Note :[/b] Godot s'attend à ce que la texture de normale utilise les "
+"coordonnées +X, -Y, et +Z. Voir [url=http://wiki.polycount.com/wiki/"
+"Normal_Map_Technical_Details#Common_Swizzle_Coordinates]cette page[/url] "
+"pour une comparaison des coordonnées des textures de normales attendues par "
+"les principaux moteurs de jeu."
#: doc/classes/CPUParticles2D.xml
msgid ""
"Orbital velocity applied to each particle. Makes the particles circle around "
"origin. Specified in number of full rotations around origin per second."
msgstr ""
+"La vitesse orbitale appliquée à chaque particule. Fait tourner les "
+"particules autour de l'origine. Spécifié en nombre de rotations complètes "
+"autour de l'origine par seconde."
#: doc/classes/CPUParticles2D.xml doc/classes/ParticlesMaterial.xml
msgid ""
@@ -22682,6 +23922,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 +24020,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 +24063,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 ""
@@ -22864,6 +24113,12 @@ msgid ""
"Currently, only [constant HashingContext.HASH_SHA256] and [constant "
"HashingContext.HASH_SHA1] are supported."
msgstr ""
+"Génère un résumé [url=https://en.wikipedia.org/wiki/HMAC]HMAC[/url] de "
+"[code]msg[/code] à partir de la clé [code]key[/code]. Le paramètre "
+"[code]hash_type[/code] est l'algorithme de hachage utilisé pour les hachages "
+"intérieurs et extérieurs.\n"
+"Actuellement, seuls les algorithmes [constant HashingContext.HASH_SHA256] et "
+"[constant HashingContext.HASH_SHA1] sont supportés."
#: doc/classes/Crypto.xml
msgid ""
@@ -22893,6 +24148,12 @@ msgid ""
"Crypto.generate_self_signed_certificate] and as private key in [method "
"StreamPeerSSL.accept_stream] along with the appropriate certificate."
msgstr ""
+"La classe CryptoKey représente une clé cryptographique. Les clés peuvent "
+"être chargées et sauvegardées comme toute autre [Resource].\n"
+"Elles peuvent être utilisées pour générer un certicat [X509Certificate] "
+"autosigné avec [method Crypto.generate_self_signed_certificate] et comme clé "
+"privée dans [method StreamPeerSSL.accept_stream] avec le certificat "
+"approprié."
#: doc/classes/CryptoKey.xml
msgid ""
@@ -22909,12 +24170,19 @@ msgid ""
"[b]Note:[/b] [code]path[/code] should be a \"*.pub\" file if "
"[code]public_only[/code] is [code]true[/code], a \"*.key\" file otherwise."
msgstr ""
+"Charge la clé à [code]path[/code]. Si [code]public_only[/code] est "
+"[code]true[/code], seule la clé publique sera chargée.\n"
+"[b]Note :[/b] [code]path[/code] doit être un fichier \"*.pub\" si "
+"[code]public_only[/code] est [code]true[/code], et un fichier \"*.key\" "
+"sinon."
#: doc/classes/CryptoKey.xml
msgid ""
"Loads a key from the given [code]string[/code]. If [code]public_only[/code] "
"is [code]true[/code], only the public key will be loaded."
msgstr ""
+"Charge une clé depuis la [code]string[/code] donnée. Si [code]public_only[/"
+"code] est [code]true[/code], seule la clé publique sera chargée."
#: doc/classes/CryptoKey.xml
msgid ""
@@ -22923,12 +24191,21 @@ msgid ""
"[b]Note:[/b] [code]path[/code] should be a \"*.pub\" file if "
"[code]public_only[/code] is [code]true[/code], a \"*.key\" file otherwise."
msgstr ""
+"Enregistre une clé au chemin [code]path[/code] spécifié. Si "
+"[code]public_only[/code] est [code]true[/code], seule la clé publique sera "
+"enregistrée.\n"
+"[b]Note :[/b] [code]path[/code] doit être un fichier avec l'extension \"."
+"pub\" si [code]public_only[/code] est [code]true[/code], et avec l'extension "
+"\".key\" sinon."
#: doc/classes/CryptoKey.xml
msgid ""
"Returns a string containing the key in PEM format. If [code]public_only[/"
"code] is [code]true[/code], only the public key will be included."
msgstr ""
+"Retourne une chaîne de caractères contenant la clé en format PEM. Si "
+"[code]public_only[/code] est [code]true[/code], seule la clé publique sera "
+"incluse."
#: modules/csg/doc_classes/CSGBox.xml
msgid "A CSG Box shape."
@@ -22991,7 +24268,6 @@ msgid ""
msgstr ""
#: modules/csg/doc_classes/CSGCylinder.xml
-#, fuzzy
msgid "A CSG Cylinder shape."
msgstr "Une forme de cylindre CSG."
@@ -23007,7 +24283,6 @@ msgid ""
msgstr ""
#: modules/csg/doc_classes/CSGCylinder.xml
-#, fuzzy
msgid ""
"If [code]true[/code] a cone is created, the [member radius] will only apply "
"to one side."
@@ -23113,12 +24388,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 +24407,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 +24418,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 +24428,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 +24463,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,11 +24477,16 @@ 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
msgid "If [code]true[/code], applies smooth shading to the extrusions."
-msgstr "Si [code]true[/code], l’audio est stéréo."
+msgstr ""
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23195,7 +24502,7 @@ msgstr ""
#: modules/csg/doc_classes/CSGPolygon.xml
msgid "The [member polygon] shape is extruded along the negative Z axis."
-msgstr ""
+msgstr "La forme [member polygone] est extrudée le long de l'axe Z négatif."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23209,6 +24516,8 @@ msgid ""
"The [member polygon] shape is extruded along the [Path] specified in [member "
"path_node]."
msgstr ""
+"La forme [member polygone] est extrudée le long du [Path] spécifié par "
+"[member path_node]."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23216,6 +24525,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 +24536,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 +24554,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."
@@ -23290,6 +24612,9 @@ msgid ""
"node and the second is the root [Mesh] of this node. Only works when this "
"node is the root shape."
msgstr ""
+"Retourne un [Array] avec deux éléments, le premier est la [Transform] de ce "
+"nœud et le second est le [Mesh] racine de ce nœud. Ne fonctionne que lorsque "
+"ce nœud est la forme racine."
#: modules/csg/doc_classes/CSGShape.xml
msgid ""
@@ -23304,12 +24629,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 ""
@@ -23356,6 +24685,9 @@ msgid ""
"CSG child node as the operation is between this node and the previous child "
"of this nodes parent."
msgstr ""
+"L'opération effectuée sur cette forme. Ceci est ignoré pour le premier nœud "
+"enfant CSG puisque l'opération est entre ce nœud et l'enfant précédent de ce "
+"nœud parent."
#: modules/csg/doc_classes/CSGShape.xml
msgid ""
@@ -23370,6 +24702,9 @@ msgid ""
"always act like a static body. Note that the collision shape is still active "
"even if the CSG shape itself is hidden."
msgstr ""
+"Ajoute une forme de collision au moteur de physique pour cette forme CSG. "
+"Cela agira toujours comme un corps statique. Notez que la forme de collision "
+"est toujours active même si cette forme CSG est cachée."
#: modules/csg/doc_classes/CSGShape.xml
msgid ""
@@ -23383,7 +24718,6 @@ msgid "Only intersecting geometry remains, the rest is removed."
msgstr "Il ne reste que la géométrie d'intersection, le reste est supprimé."
#: modules/csg/doc_classes/CSGShape.xml
-#, fuzzy
msgid ""
"The second shape is subtracted from the first, leaving a dent with its shape."
msgstr ""
@@ -23467,15 +24801,17 @@ msgid ""
"effect making the torus seem rounded. If [code]false[/code] the torus will "
"have a flat shaded look."
msgstr ""
+"Si [code]true[/code] les normales du tore sont définies pour donner un effet "
+"lisse donnant l'impression que le tore est arrondis. Si [code]false[/code] "
+"le tore aura un aspect de rendu plat."
#: modules/mono/doc_classes/CSharpScript.xml
-#, fuzzy
msgid ""
"A script implemented in the C# programming language (Mono-enabled builds "
"only)."
msgstr ""
-"Un script implémenté dans le langage de programmation C# (uniquement des "
-"compilations Mono-activé)."
+"Un script implémenté en langage C# (uniquement pour les versions où Mono est "
+"activé)."
#: modules/mono/doc_classes/CSharpScript.xml
msgid ""
@@ -23483,6 +24819,9 @@ msgid ""
"class and is only available in Mono-enabled Godot builds.\n"
"See also [GodotSharp]."
msgstr ""
+"Cette classe représente un script C#. C'est l'équivalent C# de la classe "
+"[GDScript] et n'est disponible que dans les versions de Godot avec Mono.\n"
+"Voir aussi [GodotSharp]."
#: modules/mono/doc_classes/CSharpScript.xml
#: modules/gdnative/doc_classes/PluginScript.xml
@@ -23501,9 +24840,8 @@ msgid ""
msgstr ""
#: doc/classes/CubeMap.xml
-#, fuzzy
msgid "Returns the [CubeMap]'s height."
-msgstr "Retourne la hauteur de texture."
+msgstr "Retourne la hauteur du [CubeMap]."
#: doc/classes/CubeMap.xml
msgid ""
@@ -23514,9 +24852,8 @@ msgstr ""
"constantes [enum Side]."
#: doc/classes/CubeMap.xml
-#, fuzzy
msgid "Returns the [CubeMap]'s width."
-msgstr "Renvoie la largeur de texture."
+msgstr "Renvoie la largeur du [CubeMap]."
#: doc/classes/CubeMap.xml
msgid ""
@@ -23543,9 +24880,8 @@ msgstr ""
"défini à [constant STORAGE_COMPRESS_LOSSY]."
#: doc/classes/CubeMap.xml
-#, fuzzy
msgid "The [CubeMap]'s storage mode. See [enum Storage] constants."
-msgstr "Convertit le format de l’image. Voir les constantes [enum Format]."
+msgstr ""
#: doc/classes/CubeMap.xml
msgid "Store the [CubeMap] without any compression."
@@ -23624,6 +24960,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 +24978,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 +25102,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 +25114,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 +25130,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 +25176,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 +25185,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 +25262,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."
@@ -23930,12 +25297,24 @@ msgid ""
"get_point_count][/code]), the point will be appended at the end of the point "
"list."
msgstr ""
+"Ajoute un point à une courbe à la [code]position[/code] par rapport à la "
+"position de la [Curve2D], avec des points de contrôle d'entrée "
+"[code]in[/code] et de sortie [code]out[/code].\n"
+"Si [code]at_position[/code] est spécifié, le point est inséré juste avant ce "
+"numéro de point [code]at_position[/code], en déplaçant ce point (et tous les "
+"autres points qui suivent) après le point inséré. Si [code]at_position[/code]"
+" n'est pas donné, ou est une valeur invalide ([code]at_position < 0[/code] "
+"ou [code]at_position >= [method get_point_count][/code]), le point sera "
+"ajouté en dernier."
#: doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid ""
"Returns the total length of the curve, based on the cached points. Given "
"enough density (see [member bake_interval]), it should be approximate enough."
msgstr ""
+"Retourne la longueur totale de la courbe, à partir de la distance entre les "
+"points mis en cache. Si la densité est suffisante (voir [member "
+"bake_interval]), cette longeur devrait être une approximation suffisante."
#: doc/classes/Curve2D.xml
msgid "Returns the cache of points as a [PoolVector2Array]."
@@ -23947,6 +25326,9 @@ msgid ""
"be used in [method interpolate_baked].\n"
"[code]to_point[/code] must be in this curve's local space."
msgstr ""
+"Retourne le décalage le plus proche de [code]to_point[/code]. Ce décalage "
+"est destiné à être utilisé dans [méthode interpolate_baked].\n"
+"[code]to_point[/code] doit être dans l'espace local de la courbe."
#: doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid ""
@@ -23954,6 +25336,9 @@ msgid ""
"code].\n"
"[code]to_point[/code] must be in this curve's local space."
msgstr ""
+"Retourne le point en cache le plus proche (dans l'espace local de la courbe) "
+"de [code]to_point[/code].\n"
+"[code]to_point[/code] doit être dans l'espace local de la courbe."
#: doc/classes/Curve2D.xml
msgid ""
@@ -23962,6 +25347,10 @@ msgid ""
"the index is out of bounds, the function sends an error to the console, and "
"returns [code](0, 0)[/code]."
msgstr ""
+"Retourne la position du point de contrôle menant vers le sommet [code]idx[/"
+"code]. La position retournée est relative au sommet [code]idx[/code]. Si "
+"l'index est hors limites, la fonction affiche une erreur, et retourne [code]"
+"(0, 0)[/code]."
#: doc/classes/Curve2D.xml
msgid ""
@@ -23970,6 +25359,10 @@ msgid ""
"code]. If the index is out of bounds, the function sends an error to the "
"console, and returns [code](0, 0)[/code]."
msgstr ""
+"Retourne la position du point de contrôle en partant du sommet [code]idx[/"
+"code]. La position retournée est relative au sommet [code]idx[/code]. Si "
+"l'index est hors limites, la fonction affiche une erreur, et retourne [code]"
+"(0, 0)[/code]."
#: doc/classes/Curve2D.xml
msgid ""
@@ -23977,6 +25370,8 @@ msgid ""
"bounds, the function sends an error to the console, and returns [code](0, 0)"
"[/code]."
msgstr ""
+"Retourne la position du sommet [code]idx[/code]. Si l'index est hors "
+"limites, la fonction affiche une erreur, et retourne [code](0, 0)[/code]."
#: doc/classes/Curve2D.xml
msgid ""
@@ -23989,6 +25384,14 @@ msgid ""
"vertex, and [code]t[/code] is ignored. If the curve has no points, the "
"function sends an error to the console, and returns [code](0, 0)[/code]."
msgstr ""
+"Retourne la position entre le sommet [code]idx[/code] et le sommet [code]idx "
+"+ 1[/code], où [code]t[/code] contrôle si le point est le premier sommet "
+"([code]t = 0,0[/code]), le dernier sommet ([code]t = 1.0[/code]), ou entre "
+"les deux. Les valeurs de [code]t[/code] en dehors de l'intervalle ([code]0.0 "
+">= t <=1[/code]) donnent des résultats inattendus, mais prévisibles.\n"
+"Si [code]idx[/code] est hors limites il est tronqué au premier ou au dernier "
+"sommet, et [code]t[/code] est ignoré. Si la courbe n'a pas de points, la "
+"fonction affiche une erreur, et retourne [code](0, 0)[/code]."
#: doc/classes/Curve2D.xml
msgid ""
@@ -24001,6 +25404,14 @@ msgid ""
"Cubic interpolation tends to follow the curves better, but linear is faster "
"(and often, precise enough)."
msgstr ""
+"Retourne un point dans la courbe à la position [code]offset[/code], où "
+"[code]offset[/code] est mesuré en pixels le long de la courbe.\n"
+"Pour cela, il trouve les deux points dans le cache où le [code]offset[/code] "
+"se situe entre, puis interpole les valeurs. Cette interpolation est cubique "
+"si [code]cubic[/code] est [code]true[/code], ou linéaire si est [code]false[/"
+"code].\n"
+"L'interpolation cubique tend à mieux suivre les courbes, mais "
+"l'interpolation linéaire est plus rapide (et souvent bien assez précise)."
#: doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid ""
@@ -24008,12 +25419,17 @@ msgid ""
"interpolate] using the integer part of [code]fofs[/code] as [code]idx[/"
"code], and its fractional part as [code]t[/code]."
msgstr ""
+"Retourne la position au sommet [code]fofs[/code]. Ça appelle [method "
+"interpolate] en utilisant la partie entière de [code]fofs[/code] pour "
+"[code]idx[/code], et sa partie décimale pour [code]t[/code]."
#: doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid ""
"Deletes the point [code]idx[/code] from the curve. Sends an error to the "
"console if [code]idx[/code] is out of bounds."
msgstr ""
+"Supprime le point [code]idx[/code] de la courbe. Affiche une erreur si "
+"[code]idx[/code] est hors limites."
#: doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid ""
@@ -24021,6 +25437,9 @@ msgid ""
"code]. If the index is out of bounds, the function sends an error to the "
"console. The position is relative to the vertex."
msgstr ""
+"Régle la position du point de contrôle menant au sommet [code]idx[/code]. Si "
+"l'index est hors limites, la fonction affiche une erreur. La position est "
+"relative au sommet."
#: doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid ""
@@ -24028,12 +25447,17 @@ msgid ""
"code]. If the index is out of bounds, the function sends an error to the "
"console. The position is relative to the vertex."
msgstr ""
+"Régle la position du point de contrôle partant du sommet [code]idx[/code]. "
+"Si l'index est hors limites, la fonction affiche une erreur. La position est "
+"relative au sommet."
#: doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid ""
"Sets the position for the vertex [code]idx[/code]. If the index is out of "
"bounds, the function sends an error to the console."
msgstr ""
+"Définit la position pour le vertex [code]idx[/code]. Si l'index est hors "
+"limites, la fonction affiche une erreur."
#: doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid ""
@@ -24089,6 +25513,11 @@ msgid ""
"It keeps a cache of precalculated points along the curve, to speed up "
"further calculations."
msgstr ""
+"Cette classe décrit une courbe de Bézier dans l'espace 3D. Elle est "
+"principalement utilisée pour donner une forme à un [Path], mais peut être "
+"échantillonné manuellement à d'autres fins.\n"
+"Elle conserve un cache de points précalculés le long de la courbe, pour "
+"accélérer de nouveaux calculs."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24101,6 +25530,15 @@ msgid ""
"get_point_count][/code]), the point will be appended at the end of the point "
"list."
msgstr ""
+"Ajoute un point à la courbe à [code]position[/code] par rapport à la "
+"position [Curve3D], avec des points de contrôle [code]in[/code] et "
+"[code]out[/code].\n"
+"Si [code]at_position[/code] est spécifiée, le point est inséré avant le "
+"numéro de point [code]at_position[/code], deplaçant ce point (et tous les "
+"suivants) après le point inséré. Si [code]at_position[/code] n'est pas "
+"spécifiée, ou est une valeur invalide ([code]at_position <0[/code] ou "
+"[code]at_position >= [method get_point_count][/code]), le point sera ajouté "
+"à la fin de la liste des points."
#: doc/classes/Curve3D.xml
msgid "Returns the cache of points as a [PoolVector3Array]."
@@ -24115,6 +25553,8 @@ msgid ""
"Returns the cache of up vectors as a [PoolVector3Array].\n"
"If [member up_vector_enabled] is [code]false[/code], the cache will be empty."
msgstr ""
+"Retourne le cache des vecteurs du haut dans un [PoolVector3Array].\n"
+"Si [member up_vector_enabled] est [code]false[/code], le cache sera vide."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24123,6 +25563,10 @@ msgid ""
"interpolate_baked_up_vector].\n"
"[code]to_point[/code] must be in this curve's local space."
msgstr ""
+"Retourne le décalage le plus proche de [code]to_point[/code]. Ce décalage "
+"est destiné à être utilisé dans [method interpolate_baked] ou [method "
+"interpolate_baked_up_vector].\n"
+"[code]to_point[/code] doit être dans l'espace local de cette courbe."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24131,6 +25575,10 @@ msgid ""
"the index is out of bounds, the function sends an error to the console, and "
"returns [code](0, 0, 0)[/code]."
msgstr ""
+"Retourne la position du point de contrôle menant au sommet [code]idx[/code]. "
+"La position retournée est relative au sommet [code]idx[/code]. Si l'index "
+"est hors limites, la fonction affiche une erreur, et retourne [code](0, 0, 0)"
+"[/code]."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24139,6 +25587,10 @@ msgid ""
"code]. If the index is out of bounds, the function sends an error to the "
"console, and returns [code](0, 0, 0)[/code]."
msgstr ""
+"Retourne la position du point de contrôle partant du sommet [code]idx[/"
+"code]. La position retournée est relative au sommet [code]idx[/code]. Si "
+"l'index est hors limites, la fonction affiche une erreur, et retourne [code]"
+"(0, 0, 0)[/code]."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24146,6 +25598,8 @@ msgid ""
"bounds, the function sends an error to the console, and returns [code](0, 0, "
"0)[/code]."
msgstr ""
+"Retourne la position du sommet [code]idx[/code]. Si l'index est hors "
+"limites, la fonction affiche une erreur, et retourne [code](0, 0, 0)[/code]."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24168,6 +25622,15 @@ msgid ""
"vertex, and [code]t[/code] is ignored. If the curve has no points, the "
"function sends an error to the console, and returns [code](0, 0, 0)[/code]."
msgstr ""
+"Retourne la position entre le sommet [code]idx[/code] et le sommet [code]idx "
+"+ 1[/code], où [code]t[/code] contrôle si le point est le premier sommet "
+"([code]t = 0,0[/code]), le dernier sommet ([code]t = 1.0[/code]), ou entre "
+"ces deux valeurs. Les valeurs de [code]t[/code] en dehors de l'intervalle "
+"([code]0.0 >= t <=1[/code]) donnent des résultats inattendus, mais "
+"prévisibles.\n"
+"Si [code]idx[/code] est hors limites il est tronqué au premier ou au dernier "
+"sommet, et [code]t[/code] est ignoré. Si la courbe n'a pas de points, la "
+"fonction affiche une erreur, et retourne [code](0, 0, 0)[/code]."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24180,6 +25643,14 @@ msgid ""
"Cubic interpolation tends to follow the curves better, but linear is faster "
"(and often, precise enough)."
msgstr ""
+"Retourne un point dans la courbe à la position [code]offset[/code], où "
+"[code]offset[/code] est mesuré en unités 3D le long de la courbe.\n"
+"Pour cela, il trouve les deux points dans le cache où le [code]offset[/code] "
+"se situe entre, puis interpole les valeurs. Cette interpolation est cubique "
+"si [code]cubic[/code] est [code]true[/code], ou linéaire si est [code]false[/"
+"code].\n"
+"L'interpolation cubique tend à mieux suivre les courbes, mais "
+"l'interpolation linéaire est plus rapide (et souvent bien assez précise)."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24192,6 +25663,14 @@ msgid ""
"If the curve has no up vectors, the function sends an error to the console, "
"and returns [code](0, 1, 0)[/code]."
msgstr ""
+"Retourne un vecteur haut dans la courbe à la position [code]offset[/code], "
+"où [code]offset[/code] est mesuré en unités 3D le long de la courbe.\n"
+"Pour cela, il trouve les deux vecteurs dans le cache où le [code]offset[/"
+"code] se situe entre, puis interpole les valeurs. Si [code]apply_tilt[/code] "
+"est [code]true[/code], une inclinaison interpolée est aussi appliquée au "
+"vecteur interpolé.\n"
+"Si la courbe n'a pas de vecteurs, la fonction affiche une erreur, et "
+"retourne [code](0, 1, 0)[/code]."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24201,6 +25680,11 @@ msgid ""
"the path would have. In the case of a curve controlling a [PathFollow], this "
"tilt is an offset over the natural tilt the [PathFollow] calculates."
msgstr ""
+"Définit l'angle d'inclinaison en radians pour le point [code]idx[/code]. Si "
+"l'index est hors limites, la fonction affiche une erreur.\n"
+"L'inclinaison contrôle la rotation qu'un objet parcourant la courbe aurait. "
+"Dans le cas d'une courbe contrôlant un [PathFollow], cette inclinaison est "
+"un décalage sur l'inclinaison naturelle que calcule le [PathFollow]."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24210,6 +25694,11 @@ msgid ""
"smaller the distance, the more points in the cache and the more memory it "
"will consume, so use with care."
msgstr ""
+"La distance en unités entre deux points de cache adjacents. Le changement "
+"force le cache à être recalculé la prochaine fois que la fonction [method "
+"get_baked_points] ou [method get_baked_length] sera appelée. Plus la "
+"distance est petite, plus il y aura de points dans le cache, et plus ça "
+"utilisera de mémoire, à utiliser donc avec soin."
#: doc/classes/Curve3D.xml
msgid ""
@@ -24217,6 +25706,10 @@ msgid ""
"This is used when [member PathFollow.rotation_mode] is set to [constant "
"PathFollow.ROTATION_ORIENTED]. Changing it forces the cache to be recomputed."
msgstr ""
+"Si [code]true[/code], la courbe pré-calcule des vecteurs utilisés pour "
+"l'orientation. Ceci est utilisé lorsque [member PathFollow.rotation_mode] "
+"est défini à [constant PathFollow.ROTATION_ORIENTED]. Le changer force le "
+"cache à être recalculé."
#: doc/classes/CurveTexture.xml
msgid "A texture that shows a curve."
@@ -24227,11 +25720,12 @@ msgid ""
"Renders a given [Curve] provided to it. Simplifies the task of drawing "
"curves and/or saving them as image files."
msgstr ""
+"Fait le rendu d'une [Curve] donnée. Simplifie la tâche de dessiner les "
+"courbes et/ou de les enregistrer dans des fichiers d'image."
#: doc/classes/CurveTexture.xml
-#, fuzzy
msgid "The [Curve] that is rendered onto the texture."
-msgstr "La [code]curve[/code] rendue sur la texture."
+msgstr "La [Curve] qui est rendue dans la texture."
#: doc/classes/CurveTexture.xml
msgid ""
@@ -24239,6 +25733,10 @@ msgid ""
"represent high-frequency data better (such as sudden direction changes), at "
"the cost of increased generation time and memory usage."
msgstr ""
+"La largeur de la texture (en pixels). Des valeurs plus élevées permettent de "
+"mieux représenter les données à haute fréquence (comme les changements "
+"soudains de direction) au coût de l'utilisation accrue du temps de "
+"génération et de la mémoire."
#: doc/classes/CylinderMesh.xml
msgid "Class representing a cylindrical [PrimitiveMesh]."
@@ -24250,12 +25748,17 @@ msgid ""
"create cones by setting either the [member top_radius] or [member "
"bottom_radius] properties to [code]0.0[/code]."
msgstr ""
+"La classe représentant un [PrimitiveMesh] cylindrique. Cette classe peut "
+"être utilisée pour créer des cônes en définissant la propriété [member "
+"top_radius] ou [member bottom_radius] à [code]0.0[/code]."
#: doc/classes/CylinderMesh.xml
msgid ""
"Bottom radius of the cylinder. If set to [code]0.0[/code], the bottom faces "
"will not be generated, resulting in a conic shape."
msgstr ""
+"Le rayon inférieur du cylindre. Si [code]0.0[/code], les faces inférieures "
+"ne seront pas générées, ce qui donne une forme conique."
#: doc/classes/CylinderMesh.xml
msgid "Full height of the cylinder."
@@ -24266,6 +25769,9 @@ msgid ""
"Number of radial segments on the cylinder. Higher values result in a more "
"detailed cylinder/cone at the cost of performance."
msgstr ""
+"Le nombre de segments radiaux sur le cylindre. Des valeurs plus élevées "
+"génèrent des cylindres/cônes plus détaillés mais peuvent réduire les "
+"performances."
#: doc/classes/CylinderMesh.xml
msgid ""
@@ -24283,6 +25789,8 @@ msgid ""
"Top radius of the cylinder. If set to [code]0.0[/code], the top faces will "
"not be generated, resulting in a conic shape."
msgstr ""
+"Le rayon supérieur du cylindre. Si [code]0.0[/code], les faces supérieures "
+"ne seront pas générées, ce qui donne une forme conique."
#: doc/classes/CylinderShape.xml
msgid "Cylinder shape for collisions."
@@ -24297,9 +25805,8 @@ msgid "The cylinder's radius."
msgstr "Le rayon du cylindre."
#: doc/classes/DampedSpringJoint2D.xml
-#, fuzzy
msgid "Damped spring constraint for 2D physics."
-msgstr "Contrainte de ressort amortie pour la physique 2D."
+msgstr "Une contrainte de ressort avec amortissement pour la physique 2D."
#: doc/classes/DampedSpringJoint2D.xml
msgid ""
@@ -24583,6 +26090,12 @@ msgid ""
"[b]Note:[/b] Don't erase elements while iterating over the dictionary. You "
"can iterate over the [method keys] array instead."
msgstr ""
+"Efface une paire de clé/valeur du dictionnaire spécifiée par sa clé. "
+"Retourne [code]true[/code] si la clé donnée était présente dans le "
+"dictionnaire, [code]false[/code] sinon.\n"
+"[b]Note :[/b] Ne supprimez pas les éléments pendant l'énumération du "
+"dictionnaire. Vous pouvez à la place énumérer le dictionnaire avec [method "
+"keys] qui retourne un tableau immuable."
#: doc/classes/Dictionary.xml
msgid ""
@@ -24590,6 +26103,9 @@ msgid ""
"key does not exist, the method returns the value of the optional default "
"argument, or [code]null[/code] if it is omitted."
msgstr ""
+"Retourne la valeur actuelle de la clé spécifiée dans le [Dictionnaire]. Si "
+"la clé n'existe pas, la méthode retourne la valeur de l'argument optionnel "
+"\"default\", ou [code]null[/code] si elle n'est pas spécifiée."
#: doc/classes/Dictionary.xml
msgid ""
@@ -24670,6 +26186,9 @@ msgid ""
"duplicate keys will not be copied over, unless [code]overwrite[/code] is "
"[code]true[/code]."
msgstr ""
+"Ajoute tous les éléments de [code]dictionary[/code] à ce [Dictionnaire]. Par "
+"défaut, les clés en double ne seront pas remplaçées, sauf si "
+"[code]overwrite[/code] est [code]true[/code]."
#: doc/classes/Dictionary.xml
msgid "Returns the number of keys in the dictionary."
@@ -24692,18 +26211,32 @@ msgid ""
"or moonlight. The worldspace location of the DirectionalLight transform "
"(origin) is ignored. Only the basis is used to determine light direction."
msgstr ""
+"Une lumière directionnelle est un type de nœud [Light] qui fait un rendu "
+"d'un nombre infini de rayons parallèles couvrant toute la scène. Il est "
+"utilisé pour les lumières à forte intensité qui sont situées loin de la "
+"scène pour modéliser la lumière du soleil ou du clair de lune. L'emplacement "
+"global de la DirectionalLight (son origine) est ignoré. Seule sa rotation "
+"est utilisée pour déterminer la direction de la lumière."
#: 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], le détail des ombres est sacrifié pour obtenir des "
+"transitions plus lisses entre les fractions. Activer cette option a "
+"également un coût modéré sur les performances. Ceci est ignoré lorsque "
+"[member directional_shadow_mode] est [constant SHADOW_ORTHOGONAL]."
#: doc/classes/DirectionalLight.xml
msgid ""
@@ -24714,8 +26247,16 @@ 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 ""
+"La distance maximale pour les fractions des ombres. Augmenter cette valeur "
+"rendra visibles les ombres directionnelles de plus loin, mais affichera "
+"moins de détails des ombres et de moins bonnes performances (puisque plus "
+"d'objets doivent être inclus dans le rendu d'ombre directionnel)."
#: doc/classes/DirectionalLight.xml
msgid "The light's shadow rendering algorithm. See [enum ShadowMode]."
@@ -24727,29 +26268,42 @@ msgid ""
"Can be used to fix special cases of self shadowing when objects are "
"perpendicular to the light."
msgstr ""
+"Peut être utilisé pour corriger des cas spéciaux pour les ombres des objets "
+"qui sont perpendiculaires à la source de lumière."
#: doc/classes/DirectionalLight.xml
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 distance de la caméra à la division 1 de l'ombre. Relative à [member "
+"directional_shadow_max_distance]. Seulement utilisé lorsque [member "
+"directional_shadow_mode] est [constant SHADOW_PARALLEL_2_SPLITS] ou "
+"[constant SHADOW_PARALLEL_4_SPLITS]."
#: 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 ""
+"La distance de la division 1 à la divion 2 de l'ombre. Relative à [member "
+"directional_shadow_max_distance]. Seulement utilisé lorsque [member "
+"directional_shadow_mode] est [constant SHADOW_PARALLEL_2_SPLITS] ou "
+"[constant SHADOW_PARALLEL_4_SPLITS]."
#: 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 ""
+"La distance de la division 2 à la divion 3 de l'ombre. Relative à [member "
+"directional_shadow_max_distance]. Seulement utilisé lorsque [member "
+"directional_shadow_mode] est [constant SHADOW_PARALLEL_4_SPLITS]."
#: doc/classes/DirectionalLight.xml
msgid ""
@@ -24779,6 +26333,8 @@ msgid ""
"Keeps the shadow stable when the camera moves, at the cost of lower "
"effective shadow resolution."
msgstr ""
+"Garde l'ombre stable lorsque la caméra se déplace, mais la résolution de "
+"l'ombre se trouve réduite."
#: doc/classes/DirectionalLight.xml
msgid ""
@@ -24786,6 +26342,10 @@ msgid ""
"shadow edges. This mode typically works best in games where the camera will "
"often move at high speeds, such as most racing games."
msgstr ""
+"Essaye d'atteindre une résolution maximale pour l'ombre. Peut faire "
+"apparaitre un effet de scie sur les bords de l'ombre. Ce mode fonctionne "
+"généralement mieux dans les jeux où la caméra se déplace souvent à des "
+"vitesses élevées, comme la plupart des jeux de course."
#: doc/classes/Directory.xml
msgid "Type used to handle the filesystem."
@@ -24857,9 +26417,9 @@ msgid ""
msgstr ""
"Change le dossier actuellement ouvert par celui donné en argument. "
"L'argument peut être relatif au répertoire actuel (par exemple "
-"[code]nouveau_dossier[/code] ou [code]./dossier[ /code,)] ou être un chemin "
+"[code]nouveau_dossier[/code] ou [code]./dossier[/code]), ou être un chemin "
"absolu (par exemple [code]/tmp/dossier[/code] ou [code]res://parent/"
-"dossier[ /code)].\n"
+"dossier[/code]).\n"
"Retourne une des constantes de code [enum Error] (et [code]OK[/code] en cas "
"de succès)."
@@ -25314,6 +26874,10 @@ msgid ""
"If a given character is included in more than one font, it appears only once "
"in the returned string."
msgstr ""
+"Retourne une chaîne contenant tous les caractères disponibles dans la police "
+"principale et celles de repli.\n"
+"Si un caractère donné est inclus dans plus d'une police, il apparaît "
+"seulement une fois dans la chaîne retournée."
#: doc/classes/DynamicFont.xml
msgid "Returns the fallback font at index [code]idx[/code]."
@@ -25343,6 +26907,8 @@ msgid ""
"Sets the spacing for [code]type[/code] (see [enum SpacingType]) to "
"[code]value[/code] in pixels (not relative to the font size)."
msgstr ""
+"Définit l'espacement pour [code]type[/code] (voir [enum SpacingType]) à "
+"[code]value[/code] en pixels (et en fonction de la taille de la police)."
#: doc/classes/DynamicFont.xml
msgid "Extra spacing at the bottom in pixels."
@@ -25354,6 +26920,8 @@ msgid ""
"This can be a negative number to make the distance between characters "
"smaller."
msgstr ""
+"L'espacement additionnel entre chaque caratère, en pixels.\n"
+"Ceci peut être un nombre négatif pour rapprocher les caractères."
#: doc/classes/DynamicFont.xml
msgid ""
@@ -25361,6 +26929,9 @@ msgid ""
"extra_spacing_char]) in pixels.\n"
"This can be a negative number to make the distance between words smaller."
msgstr ""
+"L'espacement additionnel entre les caractères d'espace (en plus de [member "
+"extra_spacing_char]), en pixels.\n"
+"Cela peut être un nombre négatif pour rapprocher les mots."
#: doc/classes/DynamicFont.xml
msgid "Extra spacing at the top in pixels."
@@ -25378,10 +26949,17 @@ msgid ""
"black here, it won't be possible to change its color using a Label's font "
"outline modulate theme item."
msgstr ""
+"La couleur du contour de la police.\n"
+"[b]Note :[/b] Il est recommandé de laisser ceci à la valeur par défaut afin "
+"que vous puissiez l'ajuster dans les contrôles individuels. Par exemple, si "
+"le contour est déclaré ici en noir, il ne sera pas possible de modifier sa "
+"couleur même en utilisant un thème pour le Label."
#: doc/classes/DynamicFont.xml
msgid "The font outline's thickness in pixels (not relative to the font size)."
msgstr ""
+"L'épaisseur du contour de la police, en pixels (et non en fonction à la "
+"taille de la police)."
#: doc/classes/DynamicFont.xml
msgid "The font size in pixels."
@@ -25402,6 +26980,9 @@ msgid ""
"appearance when downscaling it if font oversampling is disabled or "
"ineffective."
msgstr ""
+"Si [code]true[/code], les mipmaps sont utilisées. Cela améliore l'apparence "
+"de la police lorsqu'elle est désactivée si le sur-échantillonnage de la "
+"police est désactivé ou non utilisé."
#: doc/classes/DynamicFont.xml
msgid "Spacing at the top."
@@ -25429,6 +27010,8 @@ msgid ""
"Used with [DynamicFont] to describe the location of a vector font file for "
"dynamic rendering at runtime."
msgstr ""
+"Utilisé avec [DynamicFont] pour décrire l'emplacement d'un fichier de police "
+"vectoriel pour un rendu dynamique au lancement du projet."
#: doc/classes/DynamicFontData.xml
msgid ""
@@ -25459,9 +27042,8 @@ msgid "Disables font hinting (smoother but less crisp)."
msgstr ""
#: doc/classes/DynamicFontData.xml
-#, fuzzy
msgid "Use the light font hinting mode."
-msgstr "Utilisez le mode d’allusion de police de lumière."
+msgstr "Utilise le mode d'indice de police légère."
#: doc/classes/DynamicFontData.xml
msgid "Use the default font hinting mode (crisper but less smooth)."
@@ -25570,6 +27152,12 @@ msgid ""
"This method should not be used for System libraries as they are already "
"present on the device."
msgstr ""
+"Ajoute une bibliothèque dynamique (*.dylib, *.framework) au \"Linking "
+"Phase\" dans le projet Xcode d'iOS et l'intègre en binaire final.\n"
+"[b]Note :[/b] Pour les bibliothèques statiques (*.a), ça fonctionne de la "
+"même manière que [méthode add_ios_framework].\n"
+"Cette méthode ne devrait pas être utilisée pour les bibliothèques système "
+"car elles sont déjà présentes sur l'appareil."
#: doc/classes/EditorExportPlugin.xml
msgid ""
@@ -25588,6 +27176,8 @@ msgstr ""
#: doc/classes/EditorExportPlugin.xml
msgid "Adds a static lib from the given [code]path[/code] to the iOS project."
msgstr ""
+"Ajoute la bibliothèque statique à l'emplacement [code]path[/code] spécifié "
+"au projet iOS."
#: doc/classes/EditorExportPlugin.xml
msgid ""
@@ -25595,6 +27185,9 @@ msgid ""
"directory of macOS app bundle.\n"
"[b]Note:[/b] This is useful only for macOS exports."
msgstr ""
+"Ajoute le fichier ou le dossier correspondant à l'emplacement [code]path[/"
+"code] au dossier [code]PlugIns[/code] de l'applications macOS.\n"
+"[b]Note :[/b] Cela n'est utile que pour les exports pour macOS."
#: doc/classes/EditorExportPlugin.xml
msgid ""
@@ -25714,11 +27307,12 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
"Enregistre le profil de fonctionnalité de l'éditeur dans un fichier au "
-"format JSON. Il peut ensuite être importé en utilisant le bouton [b]Import[/"
-"b] ou la méthode [method load_from_file]."
+"format JSON. Il peut ensuite être importé en utilisant le bouton "
+"[b]Importer[/b] du gestionnaire de profils ou via la méthode [method "
+"load_from_file]."
#: doc/classes/EditorFeatureProfile.xml
msgid ""
@@ -25750,6 +27344,11 @@ msgid ""
"When a property is disabled, it won't appear in the inspector when selecting "
"a node that extends the class specified by [code]class_name[/code]."
msgstr ""
+"Si [code]disable[/code] est [code]true[/code], désactive l'édition de la "
+"[code]property[/code] dans la classe nommée [code]class_name[/code]. "
+"Lorsqu'une propriété est désactivée, elle n'apparaît plus dans l'inspecteur "
+"lors du choix d'un nœud qui étend la classe spécifiée par [code]class_name[/"
+"code]."
#: doc/classes/EditorFeatureProfile.xml
msgid ""
@@ -25863,12 +27462,17 @@ msgid ""
"Notify the [EditorFileDialog] that its view of the data is no longer "
"accurate. Updates the view contents on next view update."
msgstr ""
+"Notifie le [EditorFileDialog] que sa vue que son contenu n'est plus à jour. "
+"Mettre à jour le contenu de la vue sur la prochaine mise à jour de la vue."
#: doc/classes/EditorFileDialog.xml
msgid ""
"The location from which the user may select a file, including [code]res://[/"
"code], [code]user://[/code], and the local file system."
msgstr ""
+"L'emplacement à partir duquel l'utilisateur peut sélectionner un fichier, y "
+"compris [code]res://[/code], [code]user://[/code], et le système de fichiers "
+"local."
#: doc/classes/EditorFileDialog.xml
msgid "The currently occupied directory."
@@ -25895,11 +27499,13 @@ msgid ""
"The view format in which the [EditorFileDialog] displays resources to the "
"user."
msgstr ""
+"Le format de vue dans lequel le [EditorFileDialog] affiche les ressources à "
+"l'utilisateur."
#: doc/classes/EditorFileDialog.xml
msgid ""
"The purpose of the [EditorFileDialog], which defines the allowed behaviors."
-msgstr ""
+msgstr "Le but du [EditorFileDialog], qui définit les comportements autorisés."
#: doc/classes/EditorFileDialog.xml
msgid ""
@@ -25926,6 +27532,8 @@ msgid ""
"The [EditorFileDialog] can select only one file. Accepting the window will "
"open the file."
msgstr ""
+"Le [EditorFileDialog] ne peut sélectionner qu'un seul fichier. Accepter "
+"cette fenêtre ouvrira le fichier sélectionné."
#: doc/classes/EditorFileDialog.xml
msgid ""
@@ -25940,6 +27548,8 @@ msgid ""
"The [EditorFileDialog] can select only one directory. Accepting the window "
"will open the directory."
msgstr ""
+"Le [EditorFileDialog] ne peut sélectionner qu'un seul dossier. Accepter la "
+"fenêtre ouvrira le dossier sélectionné."
#: doc/classes/EditorFileDialog.xml
msgid ""
@@ -25997,6 +27607,11 @@ msgid ""
"[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access "
"the singleton using [method EditorInterface.get_resource_filesystem]."
msgstr ""
+"Cet objet contient des informations sur toutes les ressources du système de "
+"fichiers, leurs types, etc.\n"
+"[b]Note :[/b] Cette classe ne devrait pas être instanciée directement. "
+"Accédez plutôt à l'instance unique avec [method EditorInterface."
+"get_resource_filesystem]."
#: doc/classes/EditorFileSystem.xml
msgid ""
@@ -26004,6 +27619,10 @@ msgid ""
"string such as [code]\"Resource\"[/code] or [code]\"GDScript\"[/code], "
"[i]not[/i] a file extension such as [code]\".gd\"[/code]."
msgstr ""
+"Retourne le type de ressource du fichier, spécifié par le chemin complet. "
+"Ceci retourne une chaîne comme [code]\"Resource\"[/code] or "
+"[code]\"GDScript\"[/code], mais [i]pas[/i] l'extension du fichier comme "
+"[code]\".gd\"[/code]."
#: doc/classes/EditorFileSystem.xml
msgid "Gets the root directory object."
@@ -26018,9 +27637,10 @@ msgstr ""
#: doc/classes/EditorFileSystem.xml
msgid "Returns the scan progress for 0 to 1 if the FS is being scanned."
msgstr ""
+"Retourne la progression de l'analyse de 0 à 1 si le système de fichiers est "
+"en train d'être scanné."
#: doc/classes/EditorFileSystem.xml
-#, fuzzy
msgid "Returns [code]true[/code] if the filesystem is being scanned."
msgstr "Retourne [code]true[/code] si le système de fichier a été scanné."
@@ -26037,10 +27657,14 @@ msgid ""
"Update a file information. Call this if an external program (not Godot) "
"modified the file."
msgstr ""
+"Met à jour les informations du fichier. Appelez cette méthode si un "
+"programme externe (hors Godot) a modifié le fichier."
#: doc/classes/EditorFileSystem.xml
msgid "Scans the script files and updates the list of custom class names."
msgstr ""
+"Scanne les fichiers de script et met à jour la liste des noms de classe "
+"personnalisés."
#: doc/classes/EditorFileSystem.xml
msgid "Emitted if the filesystem changed."
@@ -26111,6 +27735,9 @@ msgid ""
"[code]idx[/code]. If the file doesn't define a script class using the "
"[code]class_name[/code] syntax, this will return an empty string."
msgstr ""
+"Retourne la classe de base de la classe de script définie dans le fichier à "
+"index [code]idx[/code]. Si le fichier ne définit pas une classe de script en "
+"utilisant la syntaxe [code]class_name[/code], une chaîne vide est retournée."
#: doc/classes/EditorFileSystemDirectory.xml
msgid ""
@@ -26118,6 +27745,9 @@ msgid ""
"code]. If the file doesn't define a script class using the [code]class_name[/"
"code] syntax, this will return an empty string."
msgstr ""
+"Retourne le nom de la classe script définie dans le fichier à index "
+"[code]idx[/code]. Si le fichier ne définit pas une classe de script en "
+"utilisant la syntaxe [code]class_name[/code], une chaîne vide est retournée."
#: doc/classes/EditorFileSystemDirectory.xml
msgid ""
@@ -26125,6 +27755,9 @@ msgid ""
"returns a string such as [code]\"Resource\"[/code] or [code]\"GDScript\"[/"
"code], [i]not[/i] a file extension such as [code]\".gd\"[/code]."
msgstr ""
+"Retourne le type de ressource du fichier à l'index [code]idx[/code]. Ceci "
+"retourne une chaîne comme [code]\"Resource\"[/code] or [code]\"GDScript\"[/"
+"code], mais [i]pas[/i] l'extension du fichier comme [code]\".gd\"[/code]."
#: doc/classes/EditorFileSystemDirectory.xml
msgid "Returns the name of this directory."
@@ -26155,6 +27788,9 @@ msgid ""
"Registers a custom resource importer in the editor. Use the class to parse "
"any file and import it as a new resource type."
msgstr ""
+"Enregistre un importateur de ressources personnalisée dans l'éditeur. "
+"Utilisez cette classe pour interpréter n'importe quel fichier pour "
+"l'importer comme nouveau type de ressource."
#: doc/classes/EditorImportPlugin.xml
msgid ""
@@ -26215,8 +27851,8 @@ msgid ""
msgstr ""
"Les [EditorImportPlugin] fournissent un moyen d'étendre la fonctionnalité "
"d'importation des ressources dans l'éditeur. Utilisez-les pour importer des "
-"ressources depuis des formats de de fichier personnalisés ou pour proposer "
-"une alternative aux importateurs existants de l'éditeur.\n"
+"ressources depuis des formats de fichier personnalisés ou pour proposer une "
+"alternative aux importateurs existants de l'éditeur.\n"
"Les EditorImportPlugins fonctionnent pas associés certaines extensions de "
"fichiers avec un type de ressource. Voir [method get_recognized_extensions] "
"et [method get_resource_type]. Ils peuvent aussi spécifier des préréglages "
@@ -26276,6 +27912,11 @@ msgid ""
"[code]default_value[/code], [code]property_hint[/code] (optional), "
"[code]hint_string[/code] (optional), [code]usage[/code] (optional)."
msgstr ""
+"Retourne les options et les valeurs par défaut pour le préréglage à cet "
+"index. Retourne un Array de Dictionnary avec les clés suivantes : "
+"[code]name[/code], [code]default_value[/code], [code]property_hint[/code] "
+"(optionnel), [code]hint_string[/code] (optionnel) et [code]usage[/code] "
+"(optionnel)."
#: doc/classes/EditorImportPlugin.xml
msgid ""
@@ -26405,10 +28046,8 @@ msgstr ""
"surcharge de cette méthode."
#: doc/classes/EditorInspector.xml
-#, fuzzy
msgid "A control used to edit properties of an object."
-msgstr ""
-"Contrôle personnalisé pour modifier les propriétés à ajouter à l’inspecteur."
+msgstr "Un contrôle pour modifier les propriétés d'un objet."
#: doc/classes/EditorInspector.xml
msgid ""
@@ -26497,10 +28136,13 @@ msgid ""
"by clicking the \"key\" icon next to a property when the Animation panel is "
"toggled."
msgstr ""
+"Émis lorsqu'une propriété est utilisée comme clé dans l'inspecteur. Les "
+"propriétés peuvent être utilisées comme clé en cliquant sur l'icône \"clé\" "
+"à côté d'une propriété lorsque le panneau \"Animation\" est ouvert."
#: doc/classes/EditorInspector.xml
msgid "Emitted when a property is selected in the inspector."
-msgstr ""
+msgstr "Émis lorsqu'une propriété est sélectionnée dans l'inspecteur."
#: doc/classes/EditorInspector.xml
msgid ""
@@ -26509,6 +28151,11 @@ msgid ""
"code] property enabled. Since this property is always enabled in the editor "
"inspector, this signal is never emitted by the editor itself."
msgstr ""
+"Émis lorsqu'une propriété booléenne est basculée dans l'inspecteur.\n"
+"[b]Note :[/b] Ce signal n'est jamais émis si la propriété interne "
+"[code]autoclear[/code] est activée. Comme cette propriété est toujours "
+"activée dans l'inspecteur de l'éditeur, ce signal n'est jamais émis par "
+"l'éditeur lui-même."
#: doc/classes/EditorInspector.xml
msgid "Emitted when a resource is selected in the inspector."
@@ -26563,18 +28210,24 @@ msgstr "Les greffons de l'inspecteur"
#: doc/classes/EditorInspectorPlugin.xml
msgid "Adds a custom control, which is not necessarily a property editor."
msgstr ""
+"Ajoute un contrôle personnalisé, qui n'est pas nécessairement un éditeur de "
+"propriété."
#: doc/classes/EditorInspectorPlugin.xml
msgid ""
"Adds a property editor for an individual property. The [code]editor[/code] "
"control must extend [EditorProperty]."
msgstr ""
+"Ajoute un éditeur de propriétés pour une seule propriété. Le contrôle "
+"[code]editor[/code] doit être une sous-classe de [EditorProperty]."
#: doc/classes/EditorInspectorPlugin.xml
msgid ""
"Adds an editor that allows modifying multiple properties. The [code]editor[/"
"code] control must extend [EditorProperty]."
msgstr ""
+"Ajoute un éditeur qui permet de modifier plusieurs propriétés. Le contrôle "
+"[code]editor[/code] doit être une sous-classe de [EditorProperty]."
#: doc/classes/EditorInspectorPlugin.xml
msgid "Returns [code]true[/code] if this object can be handled by this plugin."
@@ -26599,6 +28252,10 @@ msgid ""
"built-in editor for this property, otherwise allows to insert a custom "
"editor before the built-in one."
msgstr ""
+"Appelé pour autoriser l'ajout d'éditeurs spécifiques à la propriété dans "
+"l'inspecteur. Habituellement, ils héritent de [EditorProperty]. Retourner "
+"[code]true[/code] supprimera l'éditeur intégré pour cette propriété, c'est-à-"
+"dire que ça permet d'insérer un éditeur personnalisé avant l'éditeur intégré."
#: doc/classes/EditorInterface.xml
msgid "Godot editor's interface."
@@ -26636,6 +28293,9 @@ msgid ""
"Edits the given [Resource]. If the resource is a [Script] you can also edit "
"it with [method edit_script] to specify the line and column position."
msgstr ""
+"Modifie la [Resource] donnée. Si la ressource est un [Script], vous pouvez "
+"également la modifier avec [method edit_script] en spécifiant la position de "
+"la ligne et de la colonne."
#: doc/classes/EditorInterface.xml
msgid ""
@@ -26643,6 +28303,10 @@ msgid ""
"can also be specified. The script will be open with the user-configured "
"editor for the script's language which may be an external editor."
msgstr ""
+"Modifie le [Script]. La ligne et la colonne à laquelle ce script s'ouvre "
+"peut également être spécifiées. Le script sera ouvert avec l'éditeur "
+"configuré par l'utilisateur pour ce type de langage, où un éditeur externe "
+"peut être spécifié."
#: doc/classes/EditorInterface.xml
msgid ""
@@ -26652,10 +28316,15 @@ msgid ""
"[b]Warning:[/b] Removing and freeing this node will render the editor "
"useless and may cause a crash."
msgstr ""
+"Retourne le conteneur principal de la fenêtre de l'éditeur de Godot. Par "
+"exemple, vous pouvez l'utiliser pour récupérer la taille du conteneur et "
+"placer vos contrôles en conséquence.\n"
+"[b]Avertissement :[/b] Enlever et libérer ce nœud rend l'éditeur inutile et "
+"peut causer un plantage."
#: doc/classes/EditorInterface.xml
msgid "Returns the current path being viewed in the [FileSystemDock]."
-msgstr ""
+msgstr "Retourne l'actuel chemin en train d'être vu dans le [FileSystemDock]."
#: doc/classes/EditorInterface.xml
msgid "Returns the edited (current) scene's root [Node]."
@@ -26670,6 +28339,13 @@ msgid ""
"code] and [code]interface/editor/custom_display_scale[/code] editor "
"settings. Editor must be restarted for changes to be properly applied."
msgstr ""
+"Retourne l'échelle actuelle de l'interface de l'éditeur ([code]1.0[/code] "
+"étant une échelle à 100%). Cela peut être utilisé pour régler la position et "
+"les dimensions des interfaces utilisateurs ajoutées par les greffons.\n"
+"[b]Note :[/b] Cette valeur est définie par [code]interface/editor/"
+"display_scale[/code] et [code]interface/editor/custom_display_scale[/code]. "
+"L'éditeur doit être redémarré pour que les changements soient complètement "
+"appliqués."
#: doc/classes/EditorInterface.xml
msgid "Returns the editor's [EditorSettings] instance."
@@ -26746,6 +28422,9 @@ msgid ""
"[FileSystemDock]. If a file is selected, its base directory will be returned "
"using [method String.get_base_dir] instead."
msgstr ""
+"Retourne le chemin du dossier actuellement sélectionné dans le "
+"[FileSystemDock]. Si un fichier est sélectionné, son dossier de base sera "
+"retourné en utilisant [method String.get_base_dir]."
#: doc/classes/EditorInterface.xml
msgid "Returns the editor's [EditorSelection] instance."
@@ -26757,24 +28436,22 @@ msgid ""
"Inspector dock. If [code]inspector_only[/code] is [code]true[/code], plugins "
"will not attempt to edit [code]object[/code]."
msgstr ""
+"Affiche la propriété donnée sur le [code]object[/code] donné dans la barre "
+"d'outils de l'inspecteur de l'éditeur. Si [code]inspector_only[/code] est "
+"[code]true[/code], les greffons ne tenteront pas de modifier cet "
+"[code]object[/code]."
#: doc/classes/EditorInterface.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if a scene is currently being played, [code]false[/"
"code] otherwise. Paused scenes are considered as being played."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères commence par la chaîne "
-"de caractères donnée, ou [code]false[/code] le cas échéant."
#: doc/classes/EditorInterface.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the specified [code]plugin[/code] is enabled. "
"The plugin name is the same as its directory name."
msgstr ""
-"Renvoie [code]true[/code] (vrai) si [code]s[/code] vaut zéro ou quasiment "
-"zéro."
#: doc/classes/EditorInterface.xml
msgid ""
@@ -26830,6 +28507,10 @@ msgid ""
"([code]2D[/code], [code]3D[/code], [code]Script[/code], [code]AssetLib[/"
"code])."
msgstr ""
+"Spécifie l'écran principal courant de l'éditeur activé avec celui nommé "
+"[code]name[/code]. [code]name[/code] doit correspondre exactement au texte "
+"de l'onglet en question (soit [code]2D[/code], [code]3D[/code], "
+"[code]Script[/code], ou [code]AssetLib[/code])."
#: doc/classes/EditorInterface.xml
msgid ""
@@ -26848,6 +28529,8 @@ msgid ""
"If [code]true[/code], enables distraction-free mode which hides side docks "
"to increase the space available for the main view."
msgstr ""
+"Si [code]true[/code], active le mode sans distraction qui cache les barres "
+"d'outils latérales pour augmenter l'espace disponible pour la vue principale."
#: doc/classes/EditorPlugin.xml
msgid "Used by the editor to extend its functionality."
@@ -26860,6 +28543,10 @@ msgid ""
"plugins and export plugins. See also [EditorScript] to add functions to the "
"editor."
msgstr ""
+"Les greffons sont utilisés par l'éditeur pour étendre les fonctionnalités. "
+"Les types les plus courants de greffons sont ceux qui modifient un nœud "
+"donné ou un type de ressource, les greffons d'importation et d'exportation. "
+"Voir aussi [EditorScript] pour ajouter des fonctions à l'éditeur."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27016,6 +28703,9 @@ msgid ""
"Registers a new [EditorSceneImporter]. Scene importers are used to import "
"custom 3D asset formats as scenes."
msgstr ""
+"Enregistre un nouveau [EditorSceneImporter]. Les importateurs de scène sont "
+"utilisés pour importer des formats d'éléments 3D personnalisés comme des "
+"scènes."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27023,6 +28713,11 @@ msgid ""
"custom gizmos to the 3D preview viewport for a [Spatial].\n"
"See [method add_inspector_plugin] for an example of how to register a plugin."
msgstr ""
+"Enregistre un nouveau [EditorSpatialGizmoPlugin]. Les greffons du "
+"manipulateur sont utilisés pour ajouter des manipulateurs personnalisés dans "
+"la fenêtre d'affichage 3D pour transformer un [Spatial].\n"
+"Voir [method add_inspector_greffon] pour un exemple sur comment enregistrer "
+"un greffon."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27046,6 +28741,13 @@ msgid ""
"This is used, for example, in shader editors to let the plugin know that it "
"must apply the shader code being written by the user to the object."
msgstr ""
+"Cette méthode est appelée lorsque l'éditeur est sur le point d'enregistrer "
+"le projet, passer à un autre onglet, etc. Il demande au greffon d'appliquer "
+"tout changement d'état qui serait en attente pour garder une certaine "
+"cohérence.\n"
+"Ceci est utilisé, par exemple, dans les éditeurs d'ombres pour signaler au "
+"greffon qu'il doit appliquer le shader d'ombre écrit par l'utilisateur à "
+"l'objet."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27055,6 +28757,13 @@ msgid ""
"code], the project will not run. The run is aborted immediately, so this "
"also prevents all other plugins' [method build] methods from running."
msgstr ""
+"Cette méthode est appelée lorsque l'éditeur est sur le point de lancer le "
+"projet. Le greffon peut ensuite effectuer les opérations requises avant le "
+"lancement du projet.\n"
+"Cette méthode doit retourner un booléen. Si cette méthode retourne "
+"[code]false[/code], le projet ne sera pas lancé. Le lancement sera "
+"immédiatement annulé, ce qui empêche également toutes les autres méthodes de "
+"fonctionnement des greffons."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27062,24 +28771,34 @@ msgid ""
"your plugin does not keep editing a currently existing node, or a node from "
"the wrong scene."
msgstr ""
+"Efface tout l'état et réinitialise à zéro l'objet modifié. Cela garantit que "
+"votre greffon ne maintient pas l'édition d'un nœud existant ou d'une autre "
+"scène."
#: doc/classes/EditorPlugin.xml
msgid ""
"Called by the engine when the user disables the [EditorPlugin] in the Plugin "
"tab of the project settings window."
msgstr ""
+"Appelé par le moteur lorsque l'utilisateur désactive le [EditorPlugin] dans "
+"l'onglet Greffon de la fenêtre des paramètres du projet."
#: doc/classes/EditorPlugin.xml
msgid ""
"This function is used for plugins that edit specific object types (nodes or "
"resources). It requests the editor to edit the given object."
msgstr ""
+"Cette fonction est utilisée pour les greffons qui modifient des types "
+"d'objets spécifiques (nœuds ou ressources). Il demande à l'éditeur de "
+"modifier l'objet spécifié."
#: doc/classes/EditorPlugin.xml
msgid ""
"Called by the engine when the user enables the [EditorPlugin] in the Plugin "
"tab of the project settings window."
msgstr ""
+"Appelé par le moteur lorsque l'utilisateur active le [EditorPlugin] dans "
+"l'onglet Greffon de la fenêtre des paramètres du projet."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27126,6 +28845,11 @@ msgid ""
"You need to enable calling of this method by using [method "
"set_force_draw_over_forwarding_enabled]."
msgstr ""
+"Cette méthode est la même que [method forward_canvas_draw_over_viewport], "
+"sauf qu'elle est dessinée au-dessus de tout le reste. Utile quand vous avez "
+"besoin d'une calque supplémentaire qui s'affiche par dessus les autres.\n"
+"Vous devez activer l'appel de cette méthode en utilisant [method "
+"set_force_draw_over_forwarding_enabled]."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27216,6 +28940,11 @@ msgid ""
"You need to enable calling of this method by using [method "
"set_force_draw_over_forwarding_enabled]."
msgstr ""
+"Cette méthode est la même que [method forward_spatial_draw_over_viewport], "
+"sauf qu'elle est dessinée au-dessus de tout le reste. Utile quand vous avez "
+"besoin d'une calque supplémentaire qui s'affiche par dessus les autres.\n"
+"Vous devez activer l'appel de cette méthode en utilisant [method "
+"set_force_draw_over_forwarding_enabled]."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27269,6 +28998,9 @@ msgid ""
"breakpoints in the format ([code]script:line[/code]), for example: "
"[code]res://path_to_script.gd:25[/code]."
msgstr ""
+"C'est pour les éditeurs qui modifient des objets basés sur des scripts. Vous "
+"pouvez retourner une liste de points d'arrêt avec le format ([code]script:"
+"line[/code]), par exemple : [code]res://path_to_script.gd:25[/code]."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27455,6 +29187,11 @@ msgid ""
"Remember that you have to manage the visibility of all your editor controls "
"manually."
msgstr ""
+"Cette fonction sera appelée lorsqu'il est demandé à l'éditeur de devenir "
+"visible. Il est utilisé pour les greffons qui modifient un type d'objet "
+"spécifique.\n"
+"Rappelez-vous que vous devez gérer manuellement la visibilité de tous les "
+"contrôles de votre éditeur."
#: doc/classes/EditorPlugin.xml
msgid "Queue save the project's editor layout."
@@ -27494,29 +29231,25 @@ msgid "Removes a custom type added by [method add_custom_type]."
msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]."
#: doc/classes/EditorPlugin.xml
-#, fuzzy
msgid "Removes an export plugin registered by [method add_export_plugin]."
-msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]."
+msgstr ""
#: doc/classes/EditorPlugin.xml
-#, fuzzy
msgid "Removes an import plugin registered by [method add_import_plugin]."
-msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]."
+msgstr ""
#: doc/classes/EditorPlugin.xml
msgid "Removes an inspector plugin registered by [method add_import_plugin]"
msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]"
#: doc/classes/EditorPlugin.xml
-#, fuzzy
msgid ""
"Removes a scene importer registered by [method add_scene_import_plugin]."
-msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]."
+msgstr ""
#: doc/classes/EditorPlugin.xml
-#, fuzzy
msgid "Removes a gizmo plugin registered by [method add_spatial_gizmo_plugin]."
-msgstr "Supprime un type personnalisé ajouté par [method add_custom_type]."
+msgstr ""
#: doc/classes/EditorPlugin.xml
msgid "Removes a menu [code]name[/code] from [b]Project > Tools[/b]."
@@ -27527,6 +29260,9 @@ msgid ""
"This method is called after the editor saves the project or when it's "
"closed. It asks the plugin to save edited external scenes/resources."
msgstr ""
+"Cette méthode est appelée après que l'éditeur enregistre le projet ou "
+"lorsqu'il est fermé. Il demande au greffon d'enregistrer les scènes et "
+"ressources externes modifiées."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27535,6 +29271,11 @@ msgid ""
"editor when their viewports are updated. You need to call this method only "
"once and it will work permanently for this plugin."
msgstr ""
+"Permet d'appeler [method forward_canvas_force_draw_over_viewport] pour "
+"l'éditeur 2D et [method forward_spatial_force_draw_over_viewport] pour "
+"l'éditeur 3D lorsque leurs fenêtres d'affichage sont mises à jour. Vous "
+"devez appeler cette méthode qu'une seule fois, et ça fonctionnera en "
+"permanence pour ce greffon."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27542,6 +29283,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 ""
+"Utilisez cette méthode si vous voulez toujours recevoir les entrées dans "
+"l'écran d'aperçu 3D dans [method forward_spatial_gui_input]. Ça peut être "
+"utile si votre greffon veut utiliser un Raycast dans la scène."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27598,6 +29342,11 @@ msgid ""
"forward_spatial_draw_over_viewport] and [method "
"forward_spatial_force_draw_over_viewport] to be called."
msgstr ""
+"Met à jour des sur-couches de l'éditeur 2D et 3D. Fait que les méthodes "
+"[method forward_canvas_draw_over_viewport], [method "
+"forward_canvas_force_draw_over_viewport], [method "
+"forward_spatial_draw_over_viewport] et [method "
+"forward_spatial_force_draw_over_port] seront appelées."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27614,6 +29363,9 @@ msgid ""
"the root node of the scene that has just become active. If this scene is new "
"and empty, the argument will be [code]null[/code]."
msgstr ""
+"Émis lorsque la scène est changée dans l'éditeur. L'argument retournera le "
+"nœud racine de la scène qui vient de devenir active. Si cette scène est "
+"nouvelle et vide, l'argument sera [code]null[/code]."
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -27645,6 +29397,8 @@ msgid ""
"If any of the controls added can gain keyboard focus, add it here. This "
"ensures that focus will be restored if the inspector is refreshed."
msgstr ""
+"Si l'un des contrôles ajoutés peut récupérer le focus du clavier, ajoutez-le "
+"ici. Cela permettra de rétablir le focus si l'inspecteur est mis à jour."
#: doc/classes/EditorProperty.xml
msgid ""
@@ -27654,6 +29408,11 @@ msgid ""
"requesting this property to be refreshed (leave as [code]false[/code] if "
"unsure)."
msgstr ""
+"Si une ou plusieurs propriétés ont changé, cela doit être appelé. "
+"[code]field[/code] est utilisé au cas où votre éditeur peut modifier les "
+"champs séparément (par exemple : Vector3.x) L'argument [code]changing[/code] "
+"évite à l'éditeur de demander que cette propriété soit rafraîchie (laissez-"
+"le à [code]false[/code] en cas de doute)."
#: doc/classes/EditorProperty.xml
msgid "Gets the edited object."
@@ -27665,16 +29424,23 @@ msgid ""
"[method EditorInspectorPlugin.parse_property]), then this will return the "
"property."
msgstr ""
+"Retourne la propriété modifiée. Si votre éditeur n'est que pour une seule "
+"propriété (ajouté par [method EditorInspectorPlugin.parse_property]), cela "
+"retournera la propriété."
#: doc/classes/EditorProperty.xml
msgid "Must be implemented to provide a custom tooltip to the property editor."
msgstr ""
+"Doit être implémenté pour fournir un outil personnalisé dans l'éditeur de "
+"propriété."
#: doc/classes/EditorProperty.xml
msgid ""
"Puts the [code]editor[/code] control below the property label. The control "
"must be previously added using [method Node.add_child]."
msgstr ""
+"Place le contrôle [code]editor[/code] sous le label de la propriété. Le "
+"contrôle doit d'abord être ajouté avec [method Node.add_child]."
#: doc/classes/EditorProperty.xml
msgid "When this virtual function is called, you must update your editor."
@@ -27687,11 +29453,15 @@ msgid ""
"Used by the inspector, set to [code]true[/code] when the property is "
"checkable."
msgstr ""
+"Utilisé par l'inspecteur, défini à [code]true[/code] lorsque la propriété "
+"peut être cochée."
#: doc/classes/EditorProperty.xml
msgid ""
"Used by the inspector, set to [code]true[/code] when the property is checked."
msgstr ""
+"Utilisé par l'inspecteur, défini à [code]true[/code] quand la propriété est "
+"cochée."
#: doc/classes/EditorProperty.xml
msgid ""
@@ -27699,6 +29469,9 @@ msgid ""
"with the editor theme's warning color. This is used for editable children's "
"properties."
msgstr ""
+"Utilisé par l'inspecteur, définit à [code]true[/code] quand la propriété est "
+"affiché avec la couleur d'avertissement de l'éditeur. Ceci est utilisé pour "
+"les propriétés modifiables pour les nœuds enfants."
#: doc/classes/EditorProperty.xml
msgid ""
@@ -27719,16 +29492,23 @@ msgid ""
"Used by the inspector, set to [code]true[/code] when the property is read-"
"only."
msgstr ""
+"Utilisé par l'inspecteur, défini à [code]true[/code] quand la propriété est "
+"en lecture-seule."
#: doc/classes/EditorProperty.xml
msgid ""
"Emit it if you want multiple properties modified at the same time. Do not "
"use if added via [method EditorInspectorPlugin.parse_property]."
msgstr ""
+"Émettez-le si vous voulez plusieurs propriétés modifiées en même temps. Ne "
+"pas utiliser s'il a été ajouté avec [method EditorInspectorPlugin."
+"parse_property]."
#: doc/classes/EditorProperty.xml
msgid "Used by sub-inspectors. Emit it if what was selected was an Object ID."
msgstr ""
+"Utilisé par des sous-inspecteurs. Émettez-le si l'identifiant d'un Object a "
+"été sélectionné."
#: doc/classes/EditorProperty.xml
msgid ""
@@ -27746,10 +29526,14 @@ msgid ""
"Emit it if you want to add this value as an animation key (check for keying "
"being enabled first)."
msgstr ""
+"Émettez-le si vous voulez ajouter cette valeur comme clé d'animation "
+"(vérifiez que la clé est d'abord activée)."
#: doc/classes/EditorProperty.xml
msgid "Emit it if you want to key a property with a single value."
msgstr ""
+"Emettez-le si vous voulez définir une clé pour cette propriété avec une "
+"valeur unique."
#: doc/classes/EditorProperty.xml
msgid ""
@@ -27759,6 +29543,11 @@ msgid ""
"instantiated and can come from an ancestor scene in the inheritance/"
"instancing chain, a script or a builtin class."
msgstr ""
+"Émettez-le si vous voulez marquer (ou dé-marquer) la valeur d'une propriété "
+"pour être sauvegardée peu importe si elle est égale à la valeur par défaut.\n"
+"La valeur par défaut est celle que la propriété obtiendra lorsque le nœud "
+"est juste instancié et peut venir d'une scène instanciée ou héritée, d'un "
+"script ou d'une classe intégrée."
#: doc/classes/EditorProperty.xml
msgid ""
@@ -27786,6 +29575,13 @@ msgid ""
"[b]Note:[/b] This [Control] does not include any editor for the resource, as "
"editing is controlled by the Inspector dock itself or sub-Inspectors."
msgstr ""
+"Ce nœud [Control] est utilisé dans la barre d'outils de l'inspecteur de "
+"l'éditeur pour permettre l'édition des propriétés de type [Resource]. Il "
+"offre des options pour créer, charger, enregistrer et convertir des "
+"ressources. Peut être utilisé avec [EditorInspectorPlugin] pour recréer le "
+"même comportement.\n"
+"[b]Note :[/b] Ce [Control] n'inclut aucun éditeur de la ressource, car "
+"l'édition est contrôlée par l'inspecteur lui-même ou les sous-inspecteurs."
#: doc/classes/EditorResourcePicker.xml
msgid ""
@@ -27793,12 +29589,17 @@ msgid ""
"[member base_type]. If the [member base_type] is empty, an empty list is "
"returned."
msgstr ""
+"Retourne une liste de tous les types et sous-types autorisés correspondant "
+"au [member base_type]. Si le [member base_type] est vide, une liste vide est "
+"retournée."
#: doc/classes/EditorResourcePicker.xml
msgid ""
"This virtual method can be implemented to handle context menu items not "
"handled by default. See [method set_create_options]."
msgstr ""
+"Cette méthode virtuelle peut être implémentée pour gérer les éléments du "
+"menu contextuel non gérés par défaut. Voir [method set_create_options]."
#: doc/classes/EditorResourcePicker.xml
msgid ""
@@ -27809,12 +29610,20 @@ msgid ""
"[b]Note:[/b] Implement [method handle_menu_selected] to handle these custom "
"items."
msgstr ""
+"Cette méthode virtuelle est appelée lors de la mise à jour du menu "
+"contextuel de [EditorResourcePicker]. Implémenter cette méthode pour "
+"remplacer les éléments dans « Nouveau... » par vos propres options. "
+"[code]menu_nœud[/code] est une référence au nœud [PopupMenu].\n"
+"[b]Note :[/b] Implémentez [method handle_menu_sélection] pour traiter ces "
+"éléments personnalisés."
#: doc/classes/EditorResourcePicker.xml
msgid ""
"Sets the toggle mode state for the main button. Works only if [member "
"toggle_mode] is set to [code]true[/code]."
msgstr ""
+"Définit l'état du mode de basculement pour le bouton principal. Fonctionne "
+"uniquement si [member toggle_mode] est défini à [code]true[/code]."
#: doc/classes/EditorResourcePicker.xml
msgid ""
@@ -27837,11 +29646,13 @@ msgid ""
"If [code]true[/code], the main button with the resource preview works in the "
"toggle mode. Use [method set_toggle_pressed] to manually set the state."
msgstr ""
+"Si [code]true[/code], le bouton principal avec la prévisualisation des "
+"ressources fonctionne avec le mode de basculement. Utilisez [method "
+"set_toggle_pressed] pour définir manuellement cet état."
#: doc/classes/EditorResourcePicker.xml
-#, fuzzy
msgid "Emitted when the value of the edited resource was changed."
-msgstr "Émis à chaque fois que la ressource change."
+msgstr "Émis quand le valeur d'une ressource modifiée a été changée."
#: doc/classes/EditorResourcePicker.xml
msgid ""
@@ -27849,6 +29660,9 @@ msgid ""
"[code]edit[/code] is [code]true[/code], the signal was caused by the context "
"menu \"Edit\" option."
msgstr ""
+"Émis lorsque la valeur de ressource a été définie et que l'utilisateur a "
+"cliqué pour la modifier. Lorsque [code]edit[/code] est [code]true[/code], le "
+"signal a été causé par le menu contextuel \"Édition\"."
#: doc/classes/EditorResourcePreview.xml
msgid "Helper to generate previews of resources or files."
@@ -27860,6 +29674,11 @@ msgid ""
"[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access "
"the singleton using [method EditorInterface.get_resource_previewer]."
msgstr ""
+"Cet objet est utilisé pour générer des aperçus pour les ressources de "
+"fichiers.\n"
+"[b]Note :[/b] Cette classe ne devrait pas être instanciée directement. "
+"Accédez plutôt à l'instance unique en utilisant [method EditorInterface."
+"get_resource_previewer]."
#: doc/classes/EditorResourcePreview.xml
msgid "Create an own, custom preview generator."
@@ -27870,6 +29689,8 @@ msgid ""
"Check if the resource changed, if so, it will be invalidated and the "
"corresponding signal emitted."
msgstr ""
+"Vérifiez si la ressource a changé, si oui, elle sera invalidée et le signal "
+"correspondant émis."
#: doc/classes/EditorResourcePreview.xml
msgid ""
@@ -27929,6 +29750,8 @@ msgid ""
"Emitted if a preview was invalidated (changed). [code]path[/code] "
"corresponds to the path of the preview."
msgstr ""
+"Émis si un aperçu a été invalidé (c'est-à-dire changé). [code]path[/code] "
+"correspond au chemin de l'aperçu."
#: doc/classes/EditorResourcePreviewGenerator.xml
msgid "Custom generator of previews."
@@ -27940,6 +29763,9 @@ msgid ""
"thumbnail_size[/code] in [EditorSettings] to find out the right size to do "
"previews at."
msgstr ""
+"Le Code personnalisé pour générer des aperçus. Veuillez cocher "
+"[code]file_dialog/thumbnail_size[/code] dans [EditorSettings] pour connaître "
+"la taille correcte des prévisualisations."
#: doc/classes/EditorResourcePreviewGenerator.xml
msgid ""
@@ -28062,6 +29888,10 @@ msgid ""
"to [EditorSceneImporterGLTF] within a script will cause an error in an "
"exported project."
msgstr ""
+"[b]Note :[/b] Cette classe n'est compilée que pour les éditeurs. Le "
+"chargement et l'enregistrement au format glTF [i]n'est pas[/i] disponible "
+"dans les projets exportés. Les références à [EditorSceneImporterGLTF] dans "
+"un script provoquent une erreur dans un projet exporté."
#: doc/classes/EditorScenePostImport.xml
msgid "Post-processes scenes after import."
@@ -28138,6 +29968,8 @@ msgid ""
"Called after the scene was imported. This method must return the modified "
"version of the scene."
msgstr ""
+"Appelé après l'importation de la scène. Cette méthode doit retourner la "
+"version modifiée de la scène."
#: doc/classes/EditorScript.xml
msgid "Base script that can be used to add extension functions to the editor."
@@ -28194,6 +30026,10 @@ msgid ""
"Adds [code]node[/code] as a child of the root node in the editor context.\n"
"[b]Warning:[/b] The implementation of this method is currently disabled."
msgstr ""
+"Ajoute [code]node[/code] comme enfant du nœud racine dans le contexte de "
+"l'éditeur.\n"
+"[b]Avertissement :[/b] L'implémentation de cette méthode est actuellement "
+"désactivée."
#: doc/classes/EditorScript.xml
msgid "Returns the [EditorInterface] singleton instance."
@@ -28208,6 +30044,8 @@ msgid ""
"Godot editor's control for selecting the [code]script[/code] property of a "
"[Node]."
msgstr ""
+"Le contrôle de l'éditeur Godot pour sélectionner la propriété [code]script[/"
+"code] d'un [Node]."
#: doc/classes/EditorScriptPicker.xml
msgid ""
@@ -28244,6 +30082,10 @@ msgid ""
"[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access "
"the singleton using [method EditorInterface.get_selection]."
msgstr ""
+"Cet objet gère la sélection dans le SceneTree dans l'éditeur.\n"
+"[b]Note :[/b] Cette classe ne devrait pas être instanciée directement. "
+"Accédez plutôt à l'instance unique en utilisant [method EditorInterface."
+"get_selection]."
#: doc/classes/EditorSelection.xml
msgid ""
@@ -28252,6 +30094,10 @@ msgid ""
"inspector. If you want to edit a node, use [method EditorInterface."
"edit_node]."
msgstr ""
+"Ajoute un nœud à la sélection.\n"
+"[b]Note :[/b] Le nouveau nœud sélectionné ne sera pas automatiquement "
+"modifié dans l'inspecteur. Si vous souhaitez modifier un nœud, utilisez "
+"[method EditorInterface.edit_nœud]."
#: doc/classes/EditorSelection.xml
msgid "Clear the selection."
@@ -28267,6 +30113,10 @@ msgid ""
"moving them, rotating, etc). This list avoids situations where a node is "
"selected and also child/grandchild."
msgstr ""
+"Retourne la liste des nœuds sélectionnés, optimisés pour les opérations de "
+"transformation (c'est-à-dire le fait de les déplacer, les faire pivoter, "
+"etc.). Cette liste évite les situations où un nœud est sélectionné et mais "
+"aussi ses descendants."
#: doc/classes/EditorSelection.xml
msgid "Removes a node from the selection."
@@ -28381,6 +30231,10 @@ msgid ""
"[code]key[/code] specified. If the metadata doesn't exist, [code]default[/"
"code] will be returned instead. See also [method set_project_metadata]."
msgstr ""
+"Retourne les métadonnées spécifiques au projet pour la [code]section[/code] "
+"et [code]key[/code] spécifiées. Si les métadonnées n'existent pas, "
+"[code]default[/code] sera retourné à la place. Voir aussi [method "
+"set_project_metadata]."
#: doc/classes/EditorSettings.xml
msgid ""
@@ -28405,6 +30259,8 @@ msgid ""
"Returns the value of the setting specified by [code]name[/code]. This is "
"equivalent to using [method Object.get] on the EditorSettings instance."
msgstr ""
+"Retourne la valeur du paramètre spécifié par [code]name[/code]. Ceci est "
+"équivalent à l'utiliser [method Object.get] sur l'instance EditorSettings."
#: doc/classes/EditorSettings.xml
msgid ""
@@ -28434,6 +30290,10 @@ msgid ""
"When this method returns [code]true[/code], a Revert button will display "
"next to the setting in the Editor Settings."
msgstr ""
+"Retourne [code]true[/code] si le paramètre spécifié par [code]name[/code] "
+"peut avoir sa valeur rétablie à cette par défaut, ou [code]false[/code] "
+"sinon. Lorsque cette méthode retourne [code]true[/code], un bouton Rétablir "
+"s'affichera à côté du réglage dans les paramètres de l'éditeur."
#: doc/classes/EditorSettings.xml
msgid ""
@@ -28441,6 +30301,9 @@ msgid ""
"This is the value that would be applied when clicking the Revert button in "
"the Editor Settings."
msgstr ""
+"Retourne la valeur par défaut du paramètre spécifié par [code]name[/code]. "
+"C'est la valeur qui sera appliquée en cliquant sur le bouton Rétablir dans "
+"les paramètres de l'éditeur."
#: doc/classes/EditorSettings.xml
msgid "Sets the list of favorite files and directories for this project."
@@ -28466,6 +30329,11 @@ msgid ""
"project folder and therefore won't be checked into version control. See also "
"[method get_project_metadata]."
msgstr ""
+"Définit des métadonnées spécifiques au projet dans la [code]section[/code], "
+"la [code]key[/code] et les [code]data[/code] spécifiées. Ces métadonnées "
+"sont enregistrées à l'extérieur du dossier du projet, et donc pas dans le "
+"système de contrôle de version (Git, etc.). Voir aussi [method "
+"get_project_metadata]."
#: doc/classes/EditorSettings.xml
msgid ""
@@ -28481,6 +30349,9 @@ msgid ""
"This is equivalent to using [method Object.set] on the EditorSettings "
"instance."
msgstr ""
+"Définit la [code]value[/code] du paramètre nommé [code]name[/code]. Cela "
+"équivaut à l'utilisation de [method Object.set] sur l'instance "
+"EditorSettings."
#: doc/classes/EditorSettings.xml
msgid "Emitted after any editor setting has changed."
@@ -28492,6 +30363,9 @@ msgid ""
"plugins to update their visuals on theme changes or logic on configuration "
"changes."
msgstr ""
+"Émis après que n'importe quel réglage de l'édiateur a changé. Il est utilisé "
+"par divers greffons de l'éditeurs pour mettre à jour leur affichage lors de "
+"changements de thème ou de configuration."
#: doc/classes/EditorSpatialGizmo.xml
msgid "Custom gizmo for editing Spatial objects."
@@ -28503,12 +30377,18 @@ msgid ""
"(handles) for 3D Spatial objects. See [EditorSpatialGizmoPlugin] for more "
"information."
msgstr ""
+"Un manipulateur personnalisé qui est utilisé pour la visualisation et "
+"l'édition personnalisées (poignets) pour les objets 3D de type Spatial. Voir "
+"[EditorSpatialGizmoPlugin] pour plus d'informations."
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
"Adds the specified [code]segments[/code] to the gizmo's collision shape for "
"picking. Call this function during [method redraw]."
msgstr ""
+"Ajoute le [code]segments[/code] spécifié à la forme de collision du "
+"manipulateur pour la sélection. Appelez cette fonction durant [method "
+"redraw]."
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28516,6 +30396,9 @@ msgid ""
"generated from a regular [Mesh] too. Call this function during [method "
"redraw]."
msgstr ""
+"Ajoute des triangles de collision au manipulateur pour la sélection. Un "
+"[TriangleMesh] peut être généré à partir d'un [Mesh] régulier. Appelez cette "
+"fonction durant [method redraw]."
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28524,6 +30407,10 @@ msgid ""
"There are virtual functions which will be called upon editing of these "
"handles. Call this function during [method redraw]."
msgstr ""
+"Ajoute une liste de poignées (points) qui peuvent être utilisées pour "
+"déformer l'objet en cours d'édition.\n"
+"Il y a des fonctions virtuelles qui seront appelés à l'édition de ces "
+"poignées. Appelez cette fonction durant [method redraw]."
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28531,6 +30418,9 @@ msgid ""
"lines are used for visualizing the gizmo. Call this function during [method "
"redraw]."
msgstr ""
+"Ajoute des lignes au gizmo (une liste de paires de points), avec un matériau "
+"donné. Les lignes sont utilisées pour visualiser le manipulateur. Appelez "
+"cette fonction durant [method redraw]."
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28539,6 +30429,11 @@ msgid ""
"is [code]true[/code], the mesh will rotate to always face the camera. Call "
"this function during [method redraw]."
msgstr ""
+"Ajoute un maillage au manipulateur avec l'état [code]billboard[/code] "
+"spécifié, [code]skeleton[/code] et [code]material[/code]. Si "
+"[code]billboard[/code] est [code]true[/code], le maillage tourne pour "
+"toujours faire toujours face à la caméra. Appelez cette fonction durant "
+"[method redraw]."
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28567,23 +30462,32 @@ msgid ""
"by [method add_handles]).\n"
"Handles can be named for reference to the user when editing."
msgstr ""
+"Retourne le nom d'une poignée modifiée (ces poignées doivent d'abord être "
+"ajoutées avec [méthode add_handles]).\n"
+"Les poignées peuvent être nommées pour référence à l'utilisateur lors de "
+"l'édition."
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
"Gets actual value of a handle. This value can be anything and used for "
"eventually undoing the motion when calling [method commit_handle]."
msgstr ""
+"Retourne la valeur réelle d'une poignée. Cette valeur peut être n'importe "
+"quoi et utilisée pour finalement annuler le mouvement en appelant [method "
+"commit_handle]."
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
"Returns the [EditorSpatialGizmoPlugin] that owns this gizmo. It's useful to "
"retrieve materials using [method EditorSpatialGizmoPlugin.get_material]."
msgstr ""
+"Retourne le [EditorSpatialGizmoPlugin] qui possède ce manipulateur. Il est "
+"utile de récupérer les matériaux en utilisant [method "
+"EditorSpatialGizmoPlugin.get_material]."
#: doc/classes/EditorSpatialGizmo.xml
-#, fuzzy
msgid "Returns the Spatial node associated with this gizmo."
-msgstr "Retourne le chemin d’accès au nœud associé à l’os spécifié."
+msgstr ""
#: doc/classes/EditorSpatialGizmo.xml
msgid ""
@@ -28661,6 +30565,9 @@ msgid ""
"nodes of your choice, return [code]null[/code] for the rest of nodes. See "
"also [method has_gizmo]."
msgstr ""
+"Surchargez cette méthode pour retourner un [EditorSpatialGizmo] personnalisé "
+"pour les nœuds spatiaux de votre choix, retourner [code]null[/code] pour le "
+"reste des nœuds. Voir aussi [method has_gizmo]."
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
@@ -28670,6 +30577,12 @@ msgid ""
"Should not be overridden.\n"
"You can optionally provide a texture to use instead of the default icon."
msgstr ""
+"Crée un matériau de poignée avec ses variantes (sélectionnées et/ou "
+"modifiables) et les ajoute à la liste interne des matériaux. Ils peuvent "
+"ensuite être consultés avec [method get_material] et utilisés dans [method "
+"EditorSpatialGizmo.add_handles] Ne devrait pas être surchargé.\n"
+"Vous pouvez en option fournir une texture à utiliser à la place de l'icône "
+"par défaut."
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
@@ -28678,6 +30591,10 @@ msgid ""
"[method get_material] and used in [method EditorSpatialGizmo."
"add_unscaled_billboard]. Should not be overridden."
msgstr ""
+"Crée un matériau d'icône avec ses variantes (sélectionnées et/ou "
+"modifiables) et les ajoute à la liste interne des matériaux. Ils peuvent "
+"ensuite être consultés avec [method get_material] et utilisés dans [method "
+"EditorSpatialGizmo.add_unscaled_billboard]. Ne devrait pas être surchargé."
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
@@ -28686,6 +30603,11 @@ msgid ""
"[method get_material] and used in [method EditorSpatialGizmo.add_mesh] and "
"[method EditorSpatialGizmo.add_lines]. Should not be overridden."
msgstr ""
+"Crée un matériau non éclairé avec ses variantes (sélectionnées et/ou "
+"modifiables) et les ajoute à la liste interne des matériaux. Ils peuvent "
+"ensuite être consultés avec [method get_material] et utilisés dans [method "
+"EditorSpatialGizmo.add_mesh] et [method EditorSpatialGizmo.add_lines]. Ne "
+"devrait pas être dépassé."
#: doc/classes/EditorSpatialGizmoPlugin.xml
msgid ""
@@ -28766,9 +30688,8 @@ msgid ""
msgstr ""
#: doc/classes/EditorSpinSlider.xml
-#, fuzzy
msgid "If [code]true[/code], the slider is hidden."
-msgstr "Si [code]true[/code], la flèche de réduction est masquée."
+msgstr "Si [code]true[/code], le glisseur est masqué."
#: doc/classes/EditorVCSInterface.xml
msgid ""
@@ -28797,10 +30718,8 @@ msgstr ""
"hériter de [EditorVCSInterface] et surcharger ces fonctions virtuelles."
#: doc/classes/EditorVCSInterface.xml
-#, fuzzy
msgid "Checks out a [code]branch_name[/code] in the VCS."
msgstr ""
-"Supprime un [code]name[/code] de chargement automatique à partir de la liste."
#: doc/classes/EditorVCSInterface.xml
msgid ""
@@ -28809,9 +30728,8 @@ msgid ""
msgstr ""
#: doc/classes/EditorVCSInterface.xml
-#, fuzzy
msgid "Creates a new branch named [code]branch_name[/code] in the VCS."
-msgstr "Crée une instance de [code]class[/code]."
+msgstr ""
#: doc/classes/EditorVCSInterface.xml
msgid ""
@@ -28842,9 +30760,8 @@ msgid ""
msgstr ""
#: doc/classes/EditorVCSInterface.xml
-#, fuzzy
msgid "Gets the current branch name defined in the VCS."
-msgstr "Définit le trame présentement visible de l'animation."
+msgstr ""
#: doc/classes/EditorVCSInterface.xml
msgid ""
@@ -28908,9 +30825,8 @@ msgid ""
msgstr ""
#: doc/classes/EditorVCSInterface.xml
-#, fuzzy
msgid "Remove a branch from the local VCS."
-msgstr "Supprime un nœud de la sélection."
+msgstr ""
#: doc/classes/EditorVCSInterface.xml
msgid "Remove a remote from the local VCS."
@@ -28932,9 +30848,8 @@ msgid ""
msgstr ""
#: doc/classes/EditorVCSInterface.xml
-#, fuzzy
msgid "Stages the file present at [code]file_path[/code] to the staged area."
-msgstr "Ajoute un [Shape2D] au propriétaire de la forme."
+msgstr ""
#: doc/classes/EditorVCSInterface.xml
msgid ""
@@ -29044,9 +30959,8 @@ msgid "A commit is encountered from the commit area."
msgstr ""
#: doc/classes/EditorVCSInterface.xml
-#, fuzzy
msgid "A file is encountered from the staged area."
-msgstr "Statut : Déconnecté du serveur."
+msgstr ""
#: doc/classes/EditorVCSInterface.xml
msgid "A file is encountered from the unstaged area."
@@ -29566,14 +31480,12 @@ msgid "The [Sky] resource's rotation expressed as a [Basis]."
msgstr "La rotation du [Sky] exprimée par un [Basis]."
#: doc/classes/Environment.xml
-#, fuzzy
msgid "The [Sky] resource's rotation expressed as Euler angles in radians."
-msgstr "La rotation de la texture en radians."
+msgstr ""
#: doc/classes/Environment.xml
-#, fuzzy
msgid "The [Sky] resource's rotation expressed as Euler angles in degrees."
-msgstr "La rotation de la texture en degrés."
+msgstr ""
#: doc/classes/Environment.xml
msgid "The amount of far blur for the depth-of-field effect."
@@ -29587,9 +31499,8 @@ msgstr ""
"rendu."
#: doc/classes/Environment.xml
-#, fuzzy
msgid "If [code]true[/code], enables the depth-of-field far blur effect."
-msgstr "Si [code]true[/code], active le drapeau spécifié."
+msgstr "Si [code]true[/code], active l'effet de flou de profondeur lointain."
#: doc/classes/Environment.xml
msgid ""
@@ -29909,11 +31820,10 @@ msgid ""
msgstr ""
#: doc/classes/Environment.xml
-#, fuzzy
msgid ""
"The secondary screen-space ambient occlusion intensity. See also [member "
"ssao_radius2]."
-msgstr "Le rayon d'occlusion ambiante de l'espace de l'écran primaire."
+msgstr ""
#: doc/classes/Environment.xml
msgid ""
@@ -29949,7 +31859,7 @@ msgstr "L’exposition par défaut utilisée pour tonifier."
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -31051,7 +32961,7 @@ msgstr ""
#: doc/classes/FlowContainer.xml
#, fuzzy
msgid "Base class for flow containers."
-msgstr "Classe de base pour les conteneurs de boîtes."
+msgstr "La classe de base pour les conteneurs de flux."
#: doc/classes/FlowContainer.xml
msgid ""
@@ -31062,7 +32972,6 @@ msgid ""
msgstr ""
#: doc/classes/FlowContainer.xml
-#, fuzzy
msgid "Returns the current line count."
msgstr "Retourne le numéro de la ligne actuelle."
@@ -31132,30 +33041,24 @@ msgid ""
msgstr ""
#: doc/classes/Font.xml
-#, fuzzy
msgid "Returns resource id of the cache texture containing the char."
-msgstr "Retourne l'identifiant OpenGL de l'image de cette texture."
+msgstr ""
#: doc/classes/Font.xml
-#, fuzzy
msgid "Returns size of the cache texture containing the char."
-msgstr "Retourne la position du contact sur le collisionneur."
+msgstr ""
#: doc/classes/Font.xml
-#, fuzzy
msgid "Returns char offset from the baseline."
-msgstr "Retourne le décalage de la texture de la tuile."
+msgstr ""
#: doc/classes/Font.xml
-#, fuzzy
msgid "Returns size of the char."
-msgstr "Renvoie le sinus du paramètre."
+msgstr "Retourne la taille du caractère."
#: doc/classes/Font.xml
-#, fuzzy
msgid "Returns rectangle in the cache texture containing the char."
msgstr ""
-"Retourne un rectangle englobant les tuiles utilisées (non vides) de la carte."
#: doc/classes/Font.xml
msgid "Returns the font descent (number of pixels below the baseline)."
@@ -31191,9 +33094,8 @@ msgid ""
msgstr ""
#: doc/classes/Font.xml
-#, fuzzy
msgid "Contour point is on the curve."
-msgstr "Supprime tous les points de la courbe."
+msgstr ""
#: doc/classes/Font.xml
msgid ""
@@ -32029,15 +33931,15 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
-"À partir d'un tableau de [Vector2] représentant des tuiles, construit un "
+"À partir d'un tableau de [Vector2] représentant des tuiles, ça construit un "
"atlas. Le dictionnaire retourné a deux clés : [code]points[/code] est un "
"tableau de [Vector2] qui précise les positions de chaque tuile, et "
-"[code]size[/code] contient la taille globale de l'atlas entier sous forme de "
-"[Vector2]."
+"[code]size[/code] contient la taille globale de l'atlas en entier sous forme "
+"d'un [Vector2]."
#: doc/classes/Geometry.xml
msgid ""
@@ -32082,19 +33984,20 @@ msgid ""
msgstr ""
"Gonfle ou dégonfle [code]polygon[/code] par la quantité [code]delta[/code] "
"unités (pixels) dans toutes les directions. Si [code]delta[/code] est "
-"positif, le polygone décale chaque sommet vers l'extérieur. Si [code]delta[/"
-"code] est négatif, décale chaque sommet vers l'intérieur. Retourne une liste "
-"des polygones parce que gonflage/dégonflage peut produire plusieurs "
-"polygones distinctes. Retourne un tableau vide si [code]delta[/code] est "
-"négatif et la valeur absolue de celui-ci dépasse approximativement les "
-"dimensions du rectangle minimal englobant du polygone.\n"
+"positif, le polygone décale chaque sommet vers l'extérieur. Si "
+"[code]delta[/code] est négatif, décale chaque sommet vers l'intérieur. "
+"Retourne une liste des polygones parce que gonflage/dégonflage peut produire "
+"plusieurs polygones distinctes. Retourne un tableau vide si "
+"[code]delta[/code] est négatif et la valeur absolue de celui-ci dépasse "
+"approximativement les dimensions du rectangle minimal englobant du polygone."
+"\n"
"Les sommets de chaque polygone sont arrondis suivant [code]join_type[/code], "
"voir [enum PolyJoinType].\n"
"L'opération peut fournir un polygone extérieur (la limite extérieure) et "
"plusieurs polygones à intérieur (représentant les trous) qui pourraient être "
-"distingués en appelant [méthode is_polygon_clockwise].\n"
-"[b]Note :[/b] Pour transformer les sommets en polygone, utilisez la méthode "
-"[méthode Transform2D.xform]:\n"
+"distingués en appelant [method is_polygon_clockwise].\n"
+"[b]Note :[/b] Pour transformer les sommets en polygone, utilisez la méthode ["
+"method Transform2D.xform]:\n"
"[codeblock]\n"
"var polygon = PoolVector2Array([Vector2(0, 0), Vector2(100, 0), Vector2(100, "
"100), Vector2(0, 100)])\n"
@@ -32119,15 +34022,16 @@ msgid ""
"(hole) produced which could be distinguished by calling [method "
"is_polygon_clockwise]."
msgstr ""
-"par la quantité [code]delta[/code] unités (pixels) dans toutes les "
-"directions. Si [code]delta[/code] est positif, le polygone décale chaque "
-"sommet vers l'extérieur. Retourne une liste des polygones parce que gonflage/"
-"dégonflage peut produire plusieurs polygones distinctes. Si [code]delta[/"
-"code] est négatif, retourne un tableau vide.\n"
+"Gonfle ou dégonfle [code]polyline[/code] par la quantité [code]delta[/code] "
+"d'unités (pixels) dans toutes les directions. Si [code]delta[/code] est "
+"positif, le polygone décale chaque sommet vers l'extérieur. Retourne une "
+"liste des polygones parce que gonflage/dégonflage peut produire plusieurs "
+"polygones distinctes. Si [code]delta[/code] est négatif, retourne un tableau "
+"vide.\n"
"Les sommets de chaque polygone sont arrondis suivant [code]join_type[/code], "
"voir [enum PolyJoinType].\n"
-"Chaque point d'extrémité du polygone sera arrondi suivant [code]end_type[/"
-"code], voir [enum PolyEndType].\n"
+"Chaque point d'extrémité du polygone sera arrondi suivant "
+"[code]end_type[/code], voir [enum PolyEndType].\n"
"L'opération peut fournir un polygone extérieur (la limite extérieur) et "
"plusieurs polygones à intérieur (représentant les trous) qui pourraient être "
"distingués en appelant [method is_polygon_clockwise]."
@@ -32370,39 +34274,35 @@ msgid ""
msgstr ""
#: doc/classes/GeometryInstance.xml
-#, fuzzy
msgid ""
"The GeometryInstance's max LOD distance.\n"
"[b]Note:[/b] This property currently has no effect."
msgstr ""
-"La distance min LOD de GeometryInstance3D.\n"
+"La distance maximale pour ce LOD de la GeometryInstance.\n"
"[b]Remarque :[/b] Cette propriété n’a actuellement aucun effet."
#: doc/classes/GeometryInstance.xml
-#, fuzzy
msgid ""
"The GeometryInstance's max LOD margin.\n"
"[b]Note:[/b] This property currently has no effect."
msgstr ""
-"La distance min LOD de GeometryInstance3D.\n"
+"La marge maximale pour ce LOD de la GeometryInstance.\n"
"[b]Remarque :[/b] Cette propriété n’a actuellement aucun effet."
#: doc/classes/GeometryInstance.xml
-#, fuzzy
msgid ""
"The GeometryInstance's min LOD distance.\n"
"[b]Note:[/b] This property currently has no effect."
msgstr ""
-"La distance min LOD de GeometryInstance3D.\n"
+"La distance minimale pour ce LOD de la GeometryInstance.\n"
"[b]Remarque :[/b] Cette propriété n’a actuellement aucun effet."
#: doc/classes/GeometryInstance.xml
-#, fuzzy
msgid ""
"The GeometryInstance's min LOD margin.\n"
"[b]Note:[/b] This property currently has no effect."
msgstr ""
-"La distance min LOD de GeometryInstance3D.\n"
+"La marge minimale pour ce LOD de la GeometryInstance.\n"
"[b]Remarque :[/b] Cette propriété n’a actuellement aucun effet."
#: doc/classes/GeometryInstance.xml
@@ -32939,13 +34839,10 @@ msgstr ""
"[code]false[/code] sinon."
#: modules/mono/doc_classes/GodotSharp.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the Mono runtime is shutting down, [code]false[/"
"code] otherwise."
msgstr ""
-"Renvoie [code]true[/code] (vrai) si [code]s[/code] vaut zéro ou quasiment "
-"zéro."
#: modules/mono/doc_classes/GodotSharp.xml
msgid ""
@@ -33073,9 +34970,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 ""
@@ -33628,14 +35524,12 @@ msgid "Returns the type of the output connection [code]idx[/code]."
msgstr "Retourne le type de connexion pour la sortie [code]idx[/code]."
#: doc/classes/GraphNode.xml
-#, fuzzy
msgid "Returns the left (input) [Color] of the slot [code]idx[/code]."
-msgstr "Retourne le type du nœud à [code]idx[/code]."
+msgstr ""
#: doc/classes/GraphNode.xml
-#, fuzzy
msgid "Returns the right (output) [Color] of the slot [code]idx[/code]."
-msgstr "Retourne le type du nœud à [code]idx[/code]."
+msgstr ""
#: doc/classes/GraphNode.xml
msgid "Returns the left (input) type of the slot [code]idx[/code]."
@@ -33678,17 +35572,17 @@ msgid ""
"methods. You must enable at least one side of the slot to do so."
msgstr ""
"Définit les propriétés de l'emplacement avec identifiant [code]idx[/code].\n"
-"Si [code]enable_left[code]/[code]right[/code], un port apparaîtra et "
+"Si [code]enable_left[/code]/[code]right[/code], un port apparaîtra et "
"l'emplacement pourra être connectée de ce côté.\n"
-"[code]type_left[code]/[code]right[/code] est un type arbitraire du port. "
+"[code]type_left[/code]/[code]right[/code] est un type arbitraire du port. "
"Seuls les ports avec le même type peuvent être connectés.\n"
-"[code]color_left[code]/[code]right[/code] est la teinte de l'icône du port "
+"[code]color_left[/code]/[code]right[/code] est la teinte de l'icône du port "
"de ce côté.\n"
-"[code]custom_left[code]/[code]right[/code] est une texture personnalisée "
+"[code]custom_left[/code]/[code]right[/code] est une texture personnalisée "
"pour le port de ce côté.\n"
"[b]Note :[/b] Cette méthode ne définit que les propriétés de l'emplacement. "
-"Pour créer l'emplacement, ajoutez un enfant dérivé de [Control] au "
-"GraphNode.\n"
+"Pour créer l'emplacement, ajoutez un enfant dérivé de [Control] au GraphNode."
+"\n"
"Les propriétés individuelles peuvent être définies en utilisant l'une des "
"méthodes [code]set_slot_*[/code]. Vous devez activer au moins un côté de "
"l'emplacement pour le faire."
@@ -34057,13 +35951,10 @@ msgstr ""
"dans la grille."
#: modules/gridmap/doc_classes/GridMap.xml
-#, fuzzy
msgid ""
"Returns an array of all cells with the given item index specified in "
"[code]item[/code]."
msgstr ""
-"Renvoie la texture de l’atlas de police de caractères à l’index [code]idx[/"
-"code]."
#: modules/gridmap/doc_classes/GridMap.xml
msgid ""
@@ -34100,13 +35991,10 @@ msgid ""
msgstr ""
#: modules/gridmap/doc_classes/GridMap.xml
-#, fuzzy
msgid ""
"If [code]true[/code], this GridMap uses cell navmesh resources to create "
"navigation regions."
msgstr ""
-"Si [code]true[/code], met à jour les animations en réponse aux notifications "
-"liées au processus."
#: modules/gridmap/doc_classes/GridMap.xml
msgid "If [code]true[/code], grid items are centered on the X axis."
@@ -34318,9 +36206,8 @@ msgid "The horizontal space between the [HBoxContainer]'s elements."
msgstr "L'espace horizontal entre les éléments du [HBoxContainer]."
#: doc/classes/HeightMapShape.xml
-#, fuzzy
msgid "Height map shape for 3D physics."
-msgstr "Forme de polygone convexe pour la physique 3D."
+msgstr "La forme de carte de hauteurs pour la physique 3D."
#: doc/classes/HeightMapShape.xml
msgid ""
@@ -34350,9 +36237,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]."
@@ -34594,14 +36480,13 @@ msgid "Displayed when the decrement button is being pressed."
msgstr "Affiché quand le bouton de reduction est appuyé."
#: doc/classes/HScrollBar.xml
-#, fuzzy
msgid ""
"Icon used as a button to scroll the [ScrollBar] right. Supports custom step "
"using the [member ScrollBar.custom_step] property."
msgstr ""
-"Icône utilisée comme bouton pour faire défiler la [ScrollBar] correctement. "
-"Supporte l'étape personnalisée en utilisant la propriété [member ScrollBar."
-"custom_step]."
+"L'icône utilisée comme bouton pour faire défiler la [ScrollBar] vers la "
+"droite. Supporte une étape personnalisée en utilisant la propriété [member "
+"ScrollBar.custom_step]."
#: doc/classes/HScrollBar.xml doc/classes/VScrollBar.xml
msgid "Displayed when the mouse cursor hovers over the increment button."
@@ -34620,7 +36505,7 @@ msgstr ""
#: doc/classes/HScrollBar.xml doc/classes/VScrollBar.xml
#, fuzzy
msgid "Used when the mouse hovers over the grabber."
-msgstr "Utilisé lorsque la souris survole le grappin."
+msgstr "Utilisé lorsque la souris survole le glisseur."
#: doc/classes/HScrollBar.xml doc/classes/VScrollBar.xml
msgid "Used when the grabber is being dragged."
@@ -35711,7 +37596,6 @@ msgid "A node with the ability to send HTTP(S) requests."
msgstr "Un nœud qui permet d'envoyer des requêtes HTTP(S)."
#: doc/classes/HTTPRequest.xml
-#, fuzzy
msgid ""
"A node with the ability to send HTTP requests. Uses [HTTPClient] "
"internally.\n"
@@ -35791,28 +37675,28 @@ msgstr ""
"des fichiers ou du contenu web via HTTP.\n"
"[b]Avertissement :[/b] Voir les notes et avertissements du [HTTPClient] pour "
"les limites, notamment concernant la sécurité SSL.\n"
-"[b]Exemple pour contacter une API REST et afficher les champs retournés :[/"
-"b]\n"
+"[b]Exemple pour contacter une API REST et afficher les champs retournés :[/b]"
+"\n"
"[codeblock]\n"
"func _ready():\n"
-" # Créer un nœud de requête HTTP et le connecter au signal de "
-"complétion.\n"
+" # Créer un nœud de requête HTTP et le connecter au signal de complétion."
+"\n"
" var http_request = HTTPRequest.new()\n"
" add_child(http_request)\n"
" http_request.connect(\"request_completed\", self, "
"\"_http_request_completed\")\n"
"\n"
-" # Lancer une requête GET. L'URL en-dessous retourne un JSON au moment de "
+" # Lancer une requête GET. L'URL en dessous retourne un JSON au moment de "
"l'écriture de ce tutoriel.\n"
" var error = http_request.request(\"https://httpbin.org/get\")\n"
" if error != OK:\n"
" push_error(\"Une erreur est survenue dans la requête HTTP.\")\n"
"\n"
-" # Lancer une requête POST. L'URL en-dessous retourne un JSON au moment "
+" # Lancer une requête POST. L'URL en dessous retourne un JSON au moment "
"de l'écriture de ce tutoriel.\n"
" # Note : Don't make simultaneous requests using a single HTTPRequest "
"node.\n"
-" # Le code en-dessous est uniquement donné comme exemple.\n"
+" # Le code en dessous est uniquement donné comme exemple.\n"
" var body = {\"nom\": \"Godette\"}\n"
" error = http_request.request(\"https://httpbin.org/post\", [], true, "
"HTTPClient.METHOD_POST, body)\n"
@@ -35832,14 +37716,14 @@ msgstr ""
"HTTPRequest:[/b]\n"
"[codeblock]\n"
"func _ready():\n"
-" # Créer un nœud de requête HTTP et le connecter au signal de "
-"complétion.\n"
+" # Créer un nœud de requête HTTP et le connecter au signal de complétion."
+"\n"
" var http_request = HTTPRequest.new()\n"
" add_child(http_request)\n"
" http_request.connect(\"request_completed\", self, "
"\"_http_request_completed\")\n"
"\n"
-" # Lancer une requête HTTP. L'URL en-dessous retourne une image PNG au "
+" # Lancer une requête HTTP. L'URL en dessous retourne une image PNG au "
"moment de l'écriture de ce tutoriel.\n"
" var error = http_request.request(\"https://via.placeholder.com/512\")\n"
" if error != OK:\n"
@@ -35946,21 +37830,23 @@ msgid ""
msgstr ""
#: doc/classes/HTTPRequest.xml
-#, fuzzy
msgid ""
"Maximum number of allowed redirects. This is used to prevent endless "
"redirect loops."
-msgstr "Nombre maximal de redirections autorisées."
+msgstr ""
+"Le nombre maximal de redirections autorisées. C'est utilisé pour éviter les "
+"redirections infinies."
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -36022,7 +37908,6 @@ msgstr ""
"max_redirects]."
#: doc/classes/Image.xml
-#, fuzzy
msgid "Image datatype."
msgstr "Type de données d’image."
@@ -36164,9 +38049,8 @@ msgid "Fills [code]rect[/code] with [code]color[/code]."
msgstr "Remplis le [code]rect[/code] avec la [code]color[/code]."
#: doc/classes/Image.xml
-#, fuzzy
msgid "Blends low-alpha pixels with nearby pixels."
-msgstr "Mélange les pixels à faible alpha avec les pixels à proximité."
+msgstr "Mélange les pixels à faible opacité avec ceux proches."
#: doc/classes/Image.xml
msgid "Flips the image horizontally."
@@ -36948,9 +38832,8 @@ msgid ""
msgstr ""
#: doc/classes/ImageTexture.xml
-#, fuzzy
msgid "Returns the format of the texture, one of [enum Image.Format]."
-msgstr "Renvoie l'inverse de la racine carrée du paramètre."
+msgstr ""
#: doc/classes/ImageTexture.xml
msgid ""
@@ -37195,11 +39078,10 @@ msgid ""
msgstr ""
#: doc/classes/Input.xml
-#, fuzzy
msgid ""
"Returns the current value of the joypad axis at given index (see [enum "
"JoystickList])."
-msgstr "Retourne l'état actuel de ce canal, voir [enum ChannelState]."
+msgstr ""
#: doc/classes/Input.xml
msgid "Returns the index of the provided axis name."
@@ -37499,10 +39381,9 @@ msgid ""
msgstr ""
#: doc/classes/Input.xml
-#, fuzzy
msgid "Controls the mouse mode. See [enum MouseMode] for more information."
msgstr ""
-"Définit le mode de la souris. Voir les constantes pour plus d'informations."
+"Définit le mode de la souris. Voir [enum MouseMode] pour plus d'informations."
#: doc/classes/Input.xml
msgid ""
@@ -37515,7 +39396,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -37816,9 +39700,8 @@ msgid ""
msgstr ""
#: doc/classes/InputEventAction.xml
-#, fuzzy
msgid "InputEvent: Actions"
-msgstr "Type d’évènement d’entrée pour les actions."
+msgstr "Évènements d’entrée : les actions"
#: doc/classes/InputEventAction.xml
msgid "The action's name. Actions are accessed via this [String]."
@@ -37997,9 +39880,8 @@ msgid "Wikipedia General MIDI Instrument List"
msgstr ""
#: doc/classes/InputEventMIDI.xml
-#, fuzzy
msgid "Wikipedia Piano Key Frequencies List"
-msgstr "https://en.wikipedia.org/wiki/Piano_key_frequencies#List"
+msgstr "La liste des fréquences des touches de piano sur Wikipédia"
#: doc/classes/InputEventMIDI.xml
msgid ""
@@ -38155,10 +40037,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -38170,6 +40056,15 @@ msgstr "Les coordonnées de la souris"
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+"Retourne [code]true[/code] lors de l'utilisation de la gomme (l'autre "
+"extrémité) d'un stylet.\n"
+"[b]Note :[/b] Cette méthode est implémentée sous Linux, macOS et Windows."
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -38528,6 +40423,13 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+"La méthode de mise à jour de la camera. Voir [enum "
+"InterpolatedCameraProcessMode]."
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -39790,14 +41692,14 @@ msgid ""
msgstr ""
#: doc/classes/KinematicBody.xml doc/classes/KinematicBody2D.xml
-#, fuzzy
msgid ""
"Returns the number of times the body collided and changed direction during "
"the last call to [method move_and_slide] or [method "
"move_and_slide_with_snap]."
msgstr ""
-"Renvoie le nombre de fois où le corps est entré en collision et a changé de "
-"direction au cours du dernier appel vers [method move_and_slide]."
+"Retourne le nombre de fois où le corps est entré en collision et a changé de "
+"direction au cours du dernier appel vers [method move_and_slide] ou [method "
+"move_and_slide_with_snap]."
#: doc/classes/KinematicBody.xml doc/classes/KinematicBody2D.xml
msgid ""
@@ -40399,9 +42301,8 @@ msgid "Background [StyleBox] for the [Label]."
msgstr "Le [StyleBox] d'arrière-plan pour le [Label]."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid "Displays plain text in a 3D world."
-msgstr "Nœud de sprite en 2D dans un monde en 3D."
+msgstr "Affiche du texte dans un monde en 3D."
#: doc/classes/Label3D.xml
msgid ""
@@ -40416,78 +42317,67 @@ msgid ""
msgstr ""
#: doc/classes/Label3D.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the specified flag will be enabled. See [enum Label3D."
"DrawFlags] for a list of flags."
msgstr ""
-"Si [code]true[/code], active l'option donné. Voir [enum Flags] pour ces "
-"options."
+"Si [code]true[/code], active le drapeau spécifié. Voir [enum Label3D."
+"DrawFlags] pour la liste des drapeaux."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid ""
"The alpha cutting mode to use for the sprite. See [enum AlphaCutMode] for "
"possible values."
msgstr ""
-"Le mode d'orientation de la TileMap. Voir [enum Mode] pour les valeurs "
-"possibles."
#: doc/classes/Label3D.xml doc/classes/SpatialMaterial.xml
msgid "Threshold at which the alpha scissor will discard values."
msgstr "Le seuil à partir duquel le ciseau alpha ignorera les valeurs."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid "If [code]true[/code], wraps the text to the [member width]."
-msgstr "Si [code]true[/code], cache la ligne à l'index spécifié."
+msgstr ""
#: doc/classes/Label3D.xml
-#, fuzzy
msgid ""
"The billboard mode to use for the label. See [enum SpatialMaterial."
"BillboardMode] for possible values."
msgstr ""
-"La direction de remplissage. Voir [enum FillMode] pour les valeurs possibles."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid ""
"If [code]true[/code], text can be seen from the back as well, if "
"[code]false[/code], it is invisible when looking at it from behind."
msgstr ""
-"Si [code]true[/code], la ligne sera verticale. Si [code]false[/code], elle "
-"sera horizontale."
#: doc/classes/Label3D.xml doc/classes/SpriteBase3D.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the label is rendered at the same size regardless of "
"distance."
msgstr ""
-"Si [code]true[/code], l'objet est affiché à la même taille indépendamment de "
-"sa distance à la caméra."
+"Si [code]true[/code], le label est affiché à la même taille indépendamment "
+"de sa distance à la caméra."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid "[Font] used for the [Label3D]'s text."
-msgstr "[Font] utilisée pour le texte du [Label]."
+msgstr "La [Font] utilisée pour le texte du [Label3D]."
#: doc/classes/Label3D.xml
msgid ""
"Controls the text's horizontal alignment. Supports left, center, right. Set "
"it to one of the [enum Align] constants."
msgstr ""
+"Control l'alignement horizontal du texte. Supporte à gauche, au centre, ou à "
+"droite. Réglez-le à l'une des constantes de [enum Align]."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid "Vertical space between lines in multiline [Label3D]."
-msgstr "L'espace vertical entre les lignes en multiligne [Label]."
+msgstr ""
+"L'espacement vertical entre les lignes en mode multi-ligne d'un [Label3D]."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid "Text [Color] of the [Label3D]."
-msgstr "La [Color] par défaut du texte du [Label]."
+msgstr "La [Color] du texte du [Label3D]."
#: doc/classes/Label3D.xml doc/classes/SpatialMaterial.xml
#: doc/classes/SpriteBase3D.xml
@@ -40495,73 +42385,94 @@ msgid ""
"If [code]true[/code], depth testing is disabled and the object will be drawn "
"in render order."
msgstr ""
+"Si [code]true[/code], les tests de profondeur sont désactivés et l'objet "
+"sera dessiné suivant son ordre de rendu et non suivant sa distance."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid "The text drawing offset (in pixels)."
-msgstr "Le décalage du dessin de la texture."
+msgstr ""
#: doc/classes/Label3D.xml
-#, fuzzy
msgid "The tint of [Font]'s outline."
-msgstr "La hauteur du cylindre."
+msgstr "Le teinte du contour de la [Font]."
#: doc/classes/Label3D.xml
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
"This is because opaque objects are not sorted, while transparent objects are "
"sorted from back to front (subject to priority)."
msgstr ""
+"Définit la priorité de rendu pour la bordure du texte. Les objets les plus "
+"prioritaires seront affichés par-dessus des objets les moins prioritaires.\n"
+"[b]Note :[/b] Cela ne s'applique que si [member alpha_cut] est défini à ["
+"constant ALPHA_CUT_DISABLED] (c'est la valeur par défaut).\n"
+"[b]Note :[/b] Cela ne s'applique qu'au tri des objets transparents. Cela "
+"n'affectera pas la façon dont les objets transparents sont triés par rapport "
+"aux objets opaques. C'est parce que les objets opaques ne sont pas triés, "
+"alors que les objets transparents sont triés de l'arrière vers l'avant (et "
+"suivant leur priorité)."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid "The size of one pixel's width on the label to scale it in 3D."
-msgstr "La taille d'un des pixels de la sprite pour définir sa taille en 3D."
+msgstr "La taille d'un des pixels du label pour définir sa taille en 3D."
#: doc/classes/Label3D.xml
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
"This is because opaque objects are not sorted, while transparent objects are "
"sorted from back to front (subject to priority)."
msgstr ""
+"Définit la priorité de rendu pour le texte. Les objets les plus prioritaires "
+"seront affichés par-dessus des objets les moins prioritaires.\n"
+"[b]Note :[/b] Cela ne s'applique que si [member alpha_cut] est défini à ["
+"constant ALPHA_CUT_DISABLED] (c'est la valeur par défaut).\n"
+"[b]Note :[/b] Cela ne s'applique qu'au tri des objets transparents. Cela "
+"n'affectera pas la façon dont les objets transparents sont triés par rapport "
+"aux objets opaques. C'est parce que les objets opaques ne sont pas triés, "
+"alors que les objets transparents sont triés de l'arrière vers l'avant (et "
+"suivant leur priorité)."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the [Light] in the [Environment] has effects on the "
"label."
-msgstr "Si [code]true[/code], ce [HTTPClient] a une réponse disponible."
+msgstr ""
#: doc/classes/Label3D.xml
msgid ""
"Controls the text's vertical alignment. Supports top, center, bottom. Set it "
"to one of the [enum VAlign] constants."
msgstr ""
+"Control l'alignement vertical du texte. Supports en haut, au centre, et en "
+"bas. Réglez-le à l'une des constantes de [enum VAlign]."
#: doc/classes/Label3D.xml
msgid "Text width (in pixels), used for autowrap and fill alignment."
msgstr ""
+"La largeur de texte (en pixels), utilisée pour les retours à la ligne et "
+"l'alignement de remplissage."
#: doc/classes/Label3D.xml
-#, fuzzy
msgid "If set, lights in the environment affect the label."
-msgstr "Si [code]true[/code], ce [HTTPClient] a une réponse disponible."
+msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
+"Si défini, le texte sera aussi visible de derrière. Sinon, la texture ne "
+"sera visible que de face."
#: doc/classes/Label3D.xml doc/classes/SpatialMaterial.xml
#: doc/classes/SpriteBase3D.xml
@@ -40569,11 +42480,16 @@ msgid ""
"Disables the depth test, so this object is drawn on top of all others. "
"However, objects drawn after it in the draw order may cover it."
msgstr ""
+"Désactive le test de profondeur, de sorte que cet objet sera dessiné devant "
+"tous les autres. Cependant, les objets dessinés après lui dans l'ordre "
+"d'affichage peuvent être devant."
#: doc/classes/Label3D.xml
msgid ""
"Label is scaled by depth so that it always appears the same size on screen."
msgstr ""
+"L'étiquette est mise à l'échelle suivant la distance pour qu'elle apparaisse "
+"toujours à la même taille à l'écran."
#: doc/classes/Label3D.xml doc/classes/SpriteBase3D.xml
msgid "Represents the size of the [enum DrawFlags] enum."
@@ -40585,6 +42501,9 @@ msgid ""
"areas, but transparency sorting issues may be visible when multiple "
"transparent materials are overlapping."
msgstr ""
+"Ce mode réalise un mélange l'opacité standard. Il peut afficher des zones "
+"translucides, mais des problèmes de tri selon la transparence peuvent être "
+"visibles lorsque plusieurs matériaux transparents se chevauchent."
#: doc/classes/Label3D.xml
msgid ""
@@ -40596,6 +42515,15 @@ msgid ""
"scripts), this mode might have transparency sorting issues between the main "
"text and the outline."
msgstr ""
+"Ce mode ne permet que les pixels transparents ou alors entièrement opaques. "
+"Ce mode est également connu sous le nom de [i]alpha testing[/i] ou "
+"[i]transparence 1 bit[/i].\n"
+"[b]Note :[/b] Ce mode peut avoir des problèmes avec des polices avec "
+"anticrénelage et des contours, essayez d'ajuster [member "
+"alpha_scisor_threshold] ou en utilisant la police avec SDF.\n"
+"[b]Note :[/b] Lors de l'utilisation de texte avec des caractères superposés "
+"(par exemple des cursives), ce mode pourrait avoir des problèmes de tri de "
+"la transparence entre le texte principal et le contour."
#: doc/classes/Label3D.xml
msgid ""
@@ -40607,6 +42535,13 @@ msgid ""
"scripts), this mode might have transparency sorting issues between the main "
"text and the outline."
msgstr ""
+"Ce mode dessine des pixels entièrement opaques lors de la pré-passe de "
+"profondeur. Ceci est plus lent que [constant ALPHA_CUT_DISABLED] ou "
+"[constant ALPHA_CUT_DISCARD], mais ça permet d'afficher des zones "
+"translucides et des bords lisses tout en utilisant le tri approprié.\n"
+"[b]Note :[/b] Lors de l'utilisation de texte avec des caractères superposés "
+"(par exemple des cursives), ce mode pourrait avoir des problèmes de tri de "
+"la transparence entre le texte principal et le contour."
#: doc/classes/LargeTexture.xml
msgid ""
@@ -40623,6 +42558,10 @@ msgid ""
"You can dynamically add pieces ([Texture]s) to this [LargeTexture] using "
"different offsets."
msgstr ""
+"[i]Obsolète (elle sera retiré dans Godot 4.0).[/i] Une [Texture] capable de "
+"stocker de nombreuses textures plus petites avec des décalages.\n"
+"Vous pouvez ajouter dynamiquement des [Texture] à ce [LargeTexture] en "
+"utilisant différents décalages."
#: doc/classes/LargeTexture.xml
msgid ""
@@ -40645,9 +42584,8 @@ msgid "Returns the offset of the piece with the index [code]idx[/code]."
msgstr "Retourne le décalage de la pièce à l'index [code]idx[/code]."
#: doc/classes/LargeTexture.xml
-#, fuzzy
msgid "Returns the [Texture] of the piece with the index [code]idx[/code]."
-msgstr "Retourne la position du point à l'index [code]point[/code]."
+msgstr ""
#: doc/classes/LargeTexture.xml
msgid ""
@@ -40658,12 +42596,10 @@ msgstr ""
"code]."
#: doc/classes/LargeTexture.xml
-#, fuzzy
msgid ""
"Sets the [Texture] of the piece with index [code]idx[/code] to "
"[code]texture[/code]."
msgstr ""
-"Déplace l’élément de l’index [code]from_idx[/code] à [code]to_idx[/code]."
#: doc/classes/LargeTexture.xml
msgid "Sets the size of this [LargeTexture]."
@@ -40680,6 +42616,11 @@ msgid ""
"from it. Light contains the common variables and parameters used for "
"lighting."
msgstr ""
+"Light est la classe de base [i]abstraite[/i] pour les lumières. Puisque ça "
+"ne peut être instancié, ça ne devrait pas être utilisé directement. D'autres "
+"types de nœuds de lumière héritent de cette classe, qui contient les "
+"variables communes aux sous-classes, et les paramètres utilisés pour "
+"l'éclairage."
#: doc/classes/Light.xml doc/classes/SpotLight.xml
msgid "3D lights and shadows"
@@ -40698,6 +42639,8 @@ msgid ""
"If [code]true[/code], the light only appears in the editor and will not be "
"visible at runtime."
msgstr ""
+"Si [code]true[/code], la lumière n'apparaît que dans l'éditeur et ne sera "
+"pas visible au lancement du jeu."
#: doc/classes/Light.xml
msgid "The light's bake mode. See [enum BakeMode]."
@@ -40708,6 +42651,9 @@ msgid ""
"The light's color. An [i]overbright[/i] color can be used to achieve a "
"result equivalent to increasing the light's [member light_energy]."
msgstr ""
+"La couleur de la lumière. Une couleur [i]sur-brillante[/i] peut être "
+"utilisée pour un résultant équivalent à augmenter l'énergie [member "
+"light_energy] de la lumière."
#: doc/classes/Light.xml
msgid "The light will affect objects in the selected layers."
@@ -40719,18 +42665,26 @@ msgid ""
"[OmniLight] and [SpotLight], changing this value will only change the light "
"color's intensity, not the light's radius."
msgstr ""
+"Le multiplicateur de force de la lumière (ça n'a aucune unité physique). "
+"Pour [OmniLight] et [SpotLight], changer cette valeur ne changera que "
+"l'intensité de la constante de couleur de la lumière, et non le rayon de la "
+"lumière."
#: doc/classes/Light.xml
msgid ""
"Secondary multiplier used with indirect light (light bounces). This works on "
"both [BakedLightmap] and [GIProbe]."
msgstr ""
+"Le multiplicateur secondaire utilisé pour la lumière indirecte (les rebonds "
+"de lumière). Cela fonctionne avec [BakedLightmap] et aussi [GIProbe]."
#: doc/classes/Light.xml
msgid ""
"If [code]true[/code], the light's effect is reversed, darkening areas and "
"casting bright shadows."
msgstr ""
+"Si [code]true[/code], l'effet de la lumière est inversé, assombrissant les "
+"zones et lançant des ombres lumineuses."
#: doc/classes/Light.xml
msgid ""
@@ -40747,6 +42701,11 @@ msgid ""
"emission, this can be used to avoid unrealistic reflections when placing "
"lights above an emissive surface."
msgstr ""
+"L'intensité du reflet spéculaire dans les objets touchés par la lumière. "
+"Avec [code]0[/code], la lumière devient une lumière purement diffuse. Si ça "
+"n'est pas une émission pré-calculée, cela peut être utilisé pour éviter des "
+"reflets irréalistes lorsqu'on place des lumières au-dessus d'une surface "
+"émise."
#: doc/classes/Light.xml
msgid ""
@@ -40754,6 +42713,10 @@ msgid ""
"shadowing (\"shadow acne\"), while too large a value causes shadows to "
"separate from casters (\"peter-panning\"). Adjust as needed."
msgstr ""
+"Utilisé pour ajuster l'apparence de l'ombre. Une valeur trop petite résulte "
+"au auto-ombrage (« shadow acne »), et quqand trop grande, ça provoque des "
+"ombres séparées de l'objet qui crée l'ombre (« peter-panning »). Réglez "
+"selon les besoins."
#: doc/classes/Light.xml
msgid "The color of shadows cast by this light."
@@ -40767,6 +42730,11 @@ msgid ""
"[b]Note:[/b] Contact shadows can look broken, so leaving this property to "
"[code]0.0[/code] is recommended."
msgstr ""
+"Tente de réduire l'écart [member shadow_bias] en rendant les ombres de "
+"contact en fonction de l'espace-écran. Cela a un impact sur les "
+"performances, surtout avec des valeurs élevées.\n"
+"[b]Note :[/b] Les ombres de contact peuvent sembler brisées, donc laisser "
+"cette propriété à [code]0.0[/code] est plutôt recommandé."
#: doc/classes/Light.xml
msgid "If [code]true[/code], the light will cast shadows."
@@ -40779,6 +42747,11 @@ msgid ""
"cast a shadow on both sides of the mesh, set the mesh to use double-sided "
"shadows with [constant GeometryInstance.SHADOW_CASTING_SETTING_DOUBLE_SIDED]."
msgstr ""
+"Si [code]true[/code], inverse la face arrière du maillage. Cela peut être "
+"utile lorsque vous avez un maillage plat qui a une lumière derrière elle. Si "
+"vous avez besoin de lancer une ombre sur les deux côtés du maillage, "
+"définissez le maillage pour utiliser les deux faces avec [constant "
+"GeometryInstance.SHADOW_CASTING_SETTING_DOUBLE_SIDED]."
#: doc/classes/Light.xml
msgid "Constant for accessing [member light_energy]."
@@ -40878,10 +42851,13 @@ msgid ""
"Light is ignored when baking.\n"
"[b]Note:[/b] Hiding a light does [i]not[/i] affect baking."
msgstr ""
+"La lumière est ignorée lors du pré-calcul.\n"
+"[b]Note :[/b] L'enregistrement d'une lumière ne [i]n'affecte pas[/i] le pré-"
+"calcul."
#: doc/classes/Light.xml
msgid "Only indirect lighting will be baked (default)."
-msgstr ""
+msgstr "Seul l'éclairage indirect sera pré-calculé (choix par défaut)."
#: doc/classes/Light.xml
msgid ""
@@ -40889,6 +42865,9 @@ msgid ""
"[b]Note:[/b] You should hide the light if you don't want it to appear twice "
"(dynamic and baked)."
msgstr ""
+"La lumière directe et indirecte sera pré-calculée.\n"
+"[b]Note :[/b] Vous devriez cacher la lumière si vous ne voulez pas qu'elle "
+"apparaisse deux fois (une fois dynamique et une autre pour le pré-calcul)."
#: doc/classes/Light2D.xml
msgid "Casts light in a 2D environment."
@@ -40901,6 +42880,11 @@ msgid ""
"parameters (range and shadows-related).\n"
"[b]Note:[/b] Light2D can also be used as a mask."
msgstr ""
+"Montre la lumière dans un environnement 2D. La lumière est définie par une "
+"texture (généralement grise), une couleur, une valeur énergétique, un mode "
+"(voir les constantes), et divers autres paramètres (relatifs à la portée et "
+"aux ombres).\n"
+"[b]Note :[/b] Light2D peut aussi être utilisée comme masque."
#: doc/classes/Light2D.xml
msgid "The Light2D's [Color]."
@@ -40925,20 +42909,23 @@ msgstr ""
#: doc/classes/Light2D.xml
msgid "The Light2D's mode. See [enum Mode] constants for values."
msgstr ""
+"Le mode de la Light2D. Voir les constantes [enum Mode] pour les valeurs."
#: doc/classes/Light2D.xml
msgid "The offset of the Light2D's [code]texture[/code]."
-msgstr ""
+msgstr "Le décalage de la [code]texture[/code] de la Light2D."
#: doc/classes/Light2D.xml
msgid "The height of the Light2D. Used with 2D normal mapping."
-msgstr ""
+msgstr "La hauteur du Light2D. Utilisé avec une mapping de normale 2D."
#: doc/classes/Light2D.xml
msgid ""
"The layer mask. Only objects with a matching mask will be affected by the "
"Light2D."
msgstr ""
+"Le masque de calque. Seuls les objets avec un masque correspondant seront "
+"sous l'influence de ce Light2D."
#: doc/classes/Light2D.xml
msgid "Maximum layer value of objects that are affected by the Light2D."
@@ -40965,7 +42952,6 @@ msgstr ""
"les Light2D."
#: doc/classes/Light2D.xml
-#, fuzzy
msgid "Shadow buffer size."
msgstr "Taille du tampon d'ombre."
@@ -40989,13 +42975,16 @@ msgstr "Valeur de lissage pour les ombres."
#: doc/classes/Light2D.xml
msgid "Smooth shadow gradient length."
-msgstr ""
+msgstr "Longeur de lissage du dégradé d'ombre."
#: doc/classes/Light2D.xml
msgid ""
"The shadow mask. Used with [LightOccluder2D] to cast shadows. Only occluders "
"with a matching light mask will cast shadows."
msgstr ""
+"Le masque d'ombre. Utilisé avec [LightOccluder2D] pour lancer des ombres. "
+"Seuls les occulteurs avec un masque de lumière correspondant lanceront des "
+"ombres."
#: doc/classes/Light2D.xml
msgid "[Texture] used for the Light2D's appearance."
@@ -41010,18 +42999,24 @@ msgid ""
"Adds the value of pixels corresponding to the Light2D to the values of "
"pixels under it. This is the common behavior of a light."
msgstr ""
+"Ajoute la valeur des pixels correspondant à la Light2D aux valeurs des "
+"pixels sous elle. C'est le comportement classique des lumières."
#: doc/classes/Light2D.xml
msgid ""
"Subtracts the value of pixels corresponding to the Light2D to the values of "
"pixels under it, resulting in inversed light effect."
msgstr ""
+"Soustrait la valeur des pixels correspondant à la Light2D aux valeurs des "
+"pixels sous elle, ce qui entraîne un effet de lumière inversé."
#: doc/classes/Light2D.xml
msgid ""
"Mix the value of pixels corresponding to the Light2D to the values of pixels "
"under it by linear interpolation."
msgstr ""
+"Mélange la valeur des pixels correspondant à la Light2D aux valeurs des "
+"pixels sous elle, via une interpolation linéaire."
#: doc/classes/Light2D.xml
msgid ""
@@ -41029,40 +43024,54 @@ msgid ""
"parts of the screen underneath depending on the value of each pixel of the "
"light (mask) texture."
msgstr ""
+"La texture de lumière de la Light2D est utilisée comme masque, cache ou "
+"révèle des parties de l'écran sous la valeur de chaque pixel de la texture "
+"de la lumière (masque)."
#: doc/classes/Light2D.xml
msgid "No filter applies to the shadow map. See [member shadow_filter]."
msgstr ""
+"Aucun filtre ne s'applique à la carte d'ombre. Voir [member Shadow_filter]."
#: doc/classes/Light2D.xml
msgid ""
"Percentage closer filtering (3 samples) applies to the shadow map. See "
"[member shadow_filter]."
msgstr ""
+"Le pourcentage de filtrage proche (3 échantillons) s'applique à la carte de "
+"l'ombre. Voir [member Shadow_filter]."
#: doc/classes/Light2D.xml
msgid ""
"Percentage closer filtering (5 samples) applies to the shadow map. See "
"[member shadow_filter]."
msgstr ""
+"Le pourcentage de filtrage proche (5 échantillons) s'applique à la carte de "
+"l'ombre. Voir [member Shadow_filter]."
#: doc/classes/Light2D.xml
msgid ""
"Percentage closer filtering (7 samples) applies to the shadow map. See "
"[member shadow_filter]."
msgstr ""
+"Le pourcentage de filtrage proche (7 échantillons) s'applique à la carte de "
+"l'ombre. Voir [member Shadow_filter]."
#: doc/classes/Light2D.xml
msgid ""
"Percentage closer filtering (9 samples) applies to the shadow map. See "
"[member shadow_filter]."
msgstr ""
+"Le pourcentage de filtrage proche (9 échantillons) s'applique à la carte de "
+"l'ombre. Voir [member Shadow_filter]."
#: doc/classes/Light2D.xml
msgid ""
"Percentage closer filtering (13 samples) applies to the shadow map. See "
"[member shadow_filter]."
msgstr ""
+"Le pourcentage de filtrage proche (13 échantillons) s'applique à la carte de "
+"l'ombre. Voir [member Shadow_filter]."
#: doc/classes/LightOccluder2D.xml
msgid "Occludes light cast by a Light2D, casting shadows."
@@ -41080,10 +43089,12 @@ msgid ""
"The LightOccluder2D's light mask. The LightOccluder2D will cast shadows only "
"from Light2D(s) that have the same light mask(s)."
msgstr ""
+"Le masque de lumière du LightOccluder2D. Le LightOccluder2D ne lancera que "
+"des ombres que sur les Light2D qui ont le même masque de lumière."
#: doc/classes/LightOccluder2D.xml
msgid "The [OccluderPolygon2D] used to compute the shadow."
-msgstr ""
+msgstr "Le [OccluderPolygon2D] utilisé pour calculer l'ombre."
#: doc/classes/Line2D.xml
msgid "A 2D line."
@@ -41099,6 +43110,14 @@ msgid ""
"[member ProjectSettings.rendering/limits/buffers/"
"canvas_polygon_index_buffer_size_kb]."
msgstr ""
+"Une ligne à travers plusieurs points dans l'espace 2D. Supporte une largeur "
+"et une couleur différentes sur la longueur, la texture et plusieurs types "
+"d'embout et de jointure.\n"
+"[b]Note :[/b] Par défaut, Godot ne peut dessiner que 4 096 points de "
+"polygone à la fois. Pour augmenter cette limite, ouvrez les paramètres du "
+"projet et augmentez [member ProjectSettings.rendering/limits/buffers/"
+"canvas_polygon_buffer_size_kb] et [member ProjectSettings.rendering/limits/"
+"buffers/canvas_polygon_index_buffer_size_kb]."
#: doc/classes/Line2D.xml
msgid ""
@@ -41111,10 +43130,18 @@ msgid ""
"get_point_count][/code]), the point will be appended at the end of the point "
"list."
msgstr ""
+"Ajoute un point au [code]position[/code]. Ajoute le point à la fin de la "
+"ligne.\n"
+"Si [code]at_position[/code] est donné, le point est inséré avant l'indice "
+"[code]at_position[/code], en déplaçant ce point (et chaque point après) "
+"après le point inséré. Si [code]at_position[/code] n'est pas donné, ou est "
+"une valeur invalide ([code]at_position < 0[/code] ou [code]at_position >= "
+"[method get_point_count][/code]), le point sera ajouté à la fin de la liste "
+"des points."
#: doc/classes/Line2D.xml
msgid "Removes all points from the line."
-msgstr ""
+msgstr "Retire tous les points de la ligne."
#: doc/classes/Line2D.xml
msgid "Returns the Line2D's amount of points."
@@ -41150,6 +43177,19 @@ msgid ""
"perform antialiasing. 2D batching is also still supported with those "
"antialiased lines."
msgstr ""
+"Si [code]true[/code], la bordure de la ligne essayera d'activer "
+"anticrénelage en dessinant de fines lignes en OpenGL sur les bords de la "
+"ligne.\n"
+"[b]Note :[/b] Line2D n'est pas accéléré par lots si [code]antialiased[/code] "
+"est [code]true[/code].\n"
+"[b]Note :[/b] En raison de son fonctionnement, l'anticrénelage calculé en "
+"interne n'est pas correct pour les lignes semi-transparents voire peut ne "
+"pas fonctionner sur certaines plateformes. Vous pouvez corriger ce problème "
+"en installant le greffon [url=https://github.com/godot-extended-libraries/"
+"godot-antialiased-line2d]Antialiased Line2D[/url] puis créez un nœud "
+"\"AntialiasedPolygon2D\". Ce nœud utilise des texture avec des mipmaps "
+"personnalisés pour afficher l'anticrénelage. L'accélération par lot est "
+"toujours supporté même avec les lignes avec anticrénelage."
#: doc/classes/Line2D.xml
msgid ""
@@ -41176,6 +43216,8 @@ msgid ""
"The gradient is drawn through the whole line from start to finish. The "
"default color will not be used if a gradient is set."
msgstr ""
+"Le dégradé est dessiné par toute la ligne du début à la fin. La couleur par "
+"défaut ne sera pas utilisée si un dégradé est défini."
#: doc/classes/Line2D.xml
msgid "The style for the points between the start and the end."
@@ -41186,6 +43228,9 @@ msgid ""
"The points that form the lines. The line is drawn between every point set in "
"this array. Points are interpreted as local vectors."
msgstr ""
+"Les points qui forment les lignes. La ligne est tracée entre chaque point "
+"défini dans ce tableau. Les points sont interprétés comme des vecteurs "
+"locaux."
#: doc/classes/Line2D.xml
msgid ""
@@ -41196,24 +43241,37 @@ msgid ""
"width]. For thin lines, this value should be reduced to a number between "
"[code]2[/code] and [code]4[/code] to improve performance."
msgstr ""
+"Le lissage des coins et des bouts. Les valeurs plus élevées affichent des "
+"coins plus lisses, mais demandent plus de ressources pour le rendu. Ceci "
+"n'est utilisé que si un coin ou un bout est défini comme arrondi.\n"
+"[b]Note :[/b] La valeur par défaut est réglée pour les lignes avec la "
+"largeur [member width] par défaut. Pour les lignes fines, cette valeur "
+"devrait être réduite à entre [code]2[/code] et [code]4[/code] pour améliorer "
+"les performances."
#: doc/classes/Line2D.xml
msgid ""
"The direction difference in radians between vector points. This value is "
"only used if [member joint_mode] is set to [constant LINE_JOINT_SHARP]."
msgstr ""
+"La différence de direction entre les points vectoriels. Cette valeur n'est "
+"utilisée que si [member joint_mode] est [constant LINE_JOINT_SHARP]."
#: doc/classes/Line2D.xml
msgid ""
"The texture used for the line's texture. Uses [code]texture_mode[/code] for "
"drawing style."
msgstr ""
+"La texture utilisée pour la texture de la ligne. Utilise "
+"[code]texture_mode[/code] pour le style de dessin."
#: doc/classes/Line2D.xml
msgid ""
"The style to render the [code]texture[/code] on the line. Use [enum "
"LineTextureMode] constants."
msgstr ""
+"Le style de rendu de la [code]texture[/code] sur la ligne. Utilisez une des "
+"constantes [enum LineTextureMode]."
#: doc/classes/Line2D.xml
msgid "The line's width."
@@ -41224,12 +43282,16 @@ msgid ""
"The line's width varies with the curve. The original width is simply "
"multiply by the value of the Curve."
msgstr ""
+"La largeur de la ligne dépend selon la courbe. La largeur originale est "
+"simplement multipliée par la valeur de la Curve."
#: doc/classes/Line2D.xml
msgid ""
"The line's joints will be pointy. If [code]sharp_limit[/code] is greater "
"than the rotation of a joint, it becomes a bevel joint instead."
msgstr ""
+"Les coins de la ligne sont pointus. Si [code]sharp_limit[/code] est plus "
+"grand que l'angle d'un coin, ça devient un biseau."
#: doc/classes/Line2D.xml
msgid "The line's joints will be bevelled/chamfered."
@@ -41237,7 +43299,7 @@ msgstr ""
#: doc/classes/Line2D.xml
msgid "The line's joints will be rounded."
-msgstr ""
+msgstr "Les coins de la ligne seront arrondis."
#: doc/classes/Line2D.xml
msgid "Don't draw a line cap."
@@ -41255,6 +43317,7 @@ msgstr "Dessine le bout de la ligne avec un arrondi."
msgid ""
"Takes the left pixels of the texture and renders it over the whole line."
msgstr ""
+"Utilise les pixels de gauche de la texture pour le rendu de toute la ligne."
#: doc/classes/Line2D.xml
msgid ""
@@ -41267,10 +43330,12 @@ msgid ""
"Stretches the texture across the line. Import the texture with [b]Repeat[/b] "
"disabled for best results."
msgstr ""
+"Étire la texture à travers la ligne. Importez la texture avec la "
+"[b]répétition[/b] désactivée pour de meilleurs résultats."
#: doc/classes/LineEdit.xml
msgid "Control that provides single-line string editing."
-msgstr ""
+msgstr "Le Control qui fournit l'édition d'un texte d'une seule ligne."
#: doc/classes/LineEdit.xml
msgid ""
@@ -41358,6 +43423,9 @@ msgid ""
"[code]from_column[/code] to [code]to_column[/code]. Both parameters should "
"be within the text's length."
msgstr ""
+"Supprime une section du [member text] allant de la position "
+"[code]from_column[/code] à [code]to_column[/code]. Les deux paramètres "
+"doivent être de la longueur du texte."
#: doc/classes/LineEdit.xml doc/classes/RichTextLabel.xml
msgid "Clears the current selection."
@@ -41371,12 +43439,19 @@ 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 [PopupMenu] de ce [LineEdit]. Par défaut, ce menu s'affiche "
+"lorsque le clic-droit sur le [LineEdit].\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, lui ou un de "
+"ses enfants, utilisez la propriété [member CanvasItem.visible]."
#: doc/classes/LineEdit.xml
msgid ""
"Returns the scroll offset due to [member caret_position], as a number of "
"characters."
msgstr ""
+"Retourne le décalage du défilement suivant [member caret_position], en tant "
+"que nombre de caractères."
#: doc/classes/LineEdit.xml doc/classes/TextEdit.xml
msgid "Returns the selection begin column."
@@ -41387,9 +43462,8 @@ msgid "Returns the selection end column."
msgstr "Retourne la colonne de fin de sélection."
#: doc/classes/LineEdit.xml
-#, fuzzy
msgid "Returns [code]true[/code] if the user has selected text."
-msgstr "Retourne [code]true[/code] si le minuteur est arrêté."
+msgstr "Retourne [code]true[/code] si l'utilisateur a sélectionné du texte."
#: doc/classes/LineEdit.xml
msgid "Executes a given action as defined in the [enum MenuItems] enum."
@@ -41408,6 +43482,15 @@ msgid ""
"select(2, 5) # Will select \"lco\".\n"
"[/codeblock]"
msgstr ""
+"Sélectionne les caractères à l'intérieur du [LineEdit] entre [code]from[/"
+"code] et [code]to[/code]. Par défaut, [code]from[/code] est au début et "
+"[code]to[/code] à la fin.\n"
+"[codeblock]\n"
+"text = \"Bienvenue\"\n"
+"select() # Will select \"Bienvenue\".\n"
+"select(5) # Will select \"venue\".\n"
+"select(2, 7) # Will select \"enven\".\n"
+"[/codeblock]"
#: doc/classes/LineEdit.xml
msgid "Selects the whole [String]."
@@ -41430,6 +43513,8 @@ msgid ""
"The cursor's position inside the [LineEdit]. When set, the text may scroll "
"to accommodate it."
msgstr ""
+"La position du curseur dans le [LineEdit]. Lorsqu'il est défini, le texte "
+"peut défiler pour l'afficher."
#: doc/classes/LineEdit.xml
msgid ""
@@ -41446,13 +43531,12 @@ msgstr "Si [code]true[/code], le menu contextuel apparaitra au clic-droit."
#: doc/classes/LineEdit.xml doc/classes/RichTextLabel.xml
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the selected text will be deselected when focus is "
"lost."
msgstr ""
-"Si [code]true[/code], la cellule actuellement sélectionnée peut être "
-"sélectionnée à nouveau."
+"Si [code]true[/code], le texte actuellement sélectionné sera désélectionné "
+"quand le focus sera perdu."
#: doc/classes/LineEdit.xml
msgid ""
@@ -42170,35 +44254,58 @@ msgid ""
"add_constant_override(\"margin_right\", margin_value)\n"
"[/codeblock]"
msgstr ""
+"Ajoute une marge supérieure, gauche, inférieure et droite à tous les nœuds "
+"[Control] qui sont des enfants directs du conteneur. Pour contrôler la marge "
+"du [MarginContainer], utilisez les propriétés [code]margin_*[/code] du "
+"thèmes listées ci-dessous.\n"
+"[b]Note :[/b] Soyez prudent, les valeurs des marges de [Control] sont "
+"différentes des valeurs de marge constante. Si vous souhaitez modifier les "
+"valeurs de marge personnalisées du [MarginContainer] par code, vous devez "
+"utiliser les exemples suivants :\n"
+"[codeblock]\n"
+"# Cet exemple suppose que ce script hérite de MarginContainer.\n"
+"var margin_value = 100\n"
+"add_constant_override(\"margin_top\", margin_value)\n"
+"add_constant_override(\"margin_left\", margin_value)\n"
+"add_constant_override(\"margin_bottom\", margin_value)\n"
+"add_constant_override(\"margin_right\", margin_value)\n"
+"[/codeblock]"
#: doc/classes/MarginContainer.xml
msgid ""
"All direct children of [MarginContainer] will have a bottom margin of "
"[code]margin_bottom[/code] pixels."
msgstr ""
+"Tous les enfants directs de [MarginContainer] auront la marge du bas de "
+"[code]margin_bottom[/code] pixels."
#: doc/classes/MarginContainer.xml
msgid ""
"All direct children of [MarginContainer] will have a left margin of "
"[code]margin_left[/code] pixels."
msgstr ""
+"Tous les enfants directs de [MarginContainer] auront la marge gauche de "
+"[code]margin_left[/code] pixels."
#: doc/classes/MarginContainer.xml
msgid ""
"All direct children of [MarginContainer] will have a right margin of "
"[code]margin_right[/code] pixels."
msgstr ""
+"Tous les enfants directs de [MarginContainer] auront la marge droite de "
+"[code]margin_right[/code] pixels."
#: doc/classes/MarginContainer.xml
msgid ""
"All direct children of [MarginContainer] will have a top margin of "
"[code]margin_top[/code] pixels."
msgstr ""
+"Tous les enfants directs de [MarginContainer] auront la marge du haut de "
+"[code]margin_top[/code] pixels."
#: doc/classes/Marshalls.xml
-#, fuzzy
msgid "Data transformation (marshalling) and encoding helpers."
-msgstr "Transformation de données (marshalling) et assistants d'encodage."
+msgstr "Transformation de données (\"marshalling\") et assistants d'encodage."
#: doc/classes/Marshalls.xml
msgid "Provides data transformation and encoding utility functions."
@@ -42207,13 +44314,12 @@ msgstr ""
"données."
#: doc/classes/Marshalls.xml
-#, fuzzy
msgid ""
"Returns a decoded [PoolByteArray] corresponding to the Base64-encoded string "
"[code]base64_str[/code]."
msgstr ""
-"Renvoie un [PoolByteArray] décodé correspondant à la chaîne de caractères "
-"encodée en Base64 [code]base64_str[/code]."
+"Retourne un [PoolByteArray] décodé correspondant à la chaîne de caractères "
+"[code]base64_str[/code] encodée en Base64."
#: doc/classes/Marshalls.xml
msgid ""
@@ -42347,6 +44453,9 @@ msgid ""
"text color of the button. Disabled, hovered, and pressed states take "
"precedence over this color."
msgstr ""
+"Le texte [Color] utilisé quand le [MenuButton] a le focus. Il suffit de "
+"remplacer la couleur de texte normale du bouton. Les états désactivés, "
+"survolés et pressés sont prioritaires sur cette couleur."
#: doc/classes/MenuButton.xml
msgid "Text [Color] used when the [MenuButton] is being hovered."
@@ -42374,6 +44483,9 @@ msgid ""
"current [StyleBox], so using [StyleBoxEmpty] will just disable the focus "
"visual effect."
msgstr ""
+"La [StyleBox] utilisée quand le [MenuButton] a le focus. Elle est affichée "
+"par dessus l'actuelle [StyleBox], donc utiliser [StyleBoxEmpty] va tout "
+"simplement désactiver l'effet visuel du focus."
#: doc/classes/MenuButton.xml
msgid "[StyleBox] used when the [MenuButton] is being hovered."
@@ -42400,6 +44512,12 @@ msgid ""
"surfaces is preferred to a single surface, because objects created in 3D "
"editing software commonly contain multiple materials."
msgstr ""
+"Mesh est un type de [Resource] qui contient la géométrie à base de tableaux "
+"de sommets, divisé en [i]surfaces[/i]. Chaque surface contient un tableau "
+"complètement séparé et un matériau utilisé pour le dessiner. Au niveau du "
+"design, un maillage avec plusieurs surfaces est préféré à une seule surface, "
+"car les objets créés dans le logiciel d'édition 3D contiennent généralement "
+"plusieurs matériaux."
#: doc/classes/Mesh.xml
msgid ""
@@ -42410,6 +44528,13 @@ msgid ""
"If [code]simplify[/code] is [code]true[/code], the geometry can be further "
"simplified to reduce the amount of vertices. Disabled by default."
msgstr ""
+"Calcule la [ConvexPolygonShape] du maillage.\n"
+"Si [code]clean[/code] est [code]true[/code] (par défaut), les sommets "
+"intérieurs et en double sont automatiquement supprimés. Vous pouvez le "
+"définir à [code]false[/code] pour rendre le processus plus rapide si "
+"nécessaire.\n"
+"Si [code]simplify[/code] est [code]true[/code], la géométrie peut être plus "
+"simplifiée pour réduire la quantité de sommets. Désactivé par défaut."
#: doc/classes/Mesh.xml
msgid ""
@@ -42418,6 +44543,10 @@ msgid ""
"[b]Note:[/b] This method typically returns the vertices in reverse order (e."
"g. clockwise to counterclockwise)."
msgstr ""
+"Calcule un maillage de contour avec un décalage défini (marge) du maillage "
+"d'origine.\n"
+"[b]Note :[/b] Cette méthode renvoie généralement les sommets en ordre "
+"inverse (par ex., du sens horaire au sens anti-horaire)."
#: doc/classes/Mesh.xml
msgid "Calculate a [ConcavePolygonShape] from the mesh."
@@ -42434,6 +44563,10 @@ msgid ""
"get_transformed_aabb].\n"
"[b]Note:[/b] This is only implemented for [ArrayMesh] and [PrimitiveMesh]."
msgstr ""
+"Retourne le plus petit [AABB] englobant ce maillage dans l'espace local. Non "
+"affecté par [code]custom_aabb[/code]. Voir aussi [method VisualInstance."
+"get_transformed_aabb]\n"
+"[b]Note :[/b] Ceci n'est implémenté que pour [ArrayMesh] et [PrimitiveMesh]."
#: doc/classes/Mesh.xml
msgid ""
@@ -42519,37 +44652,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."
@@ -42763,6 +44891,9 @@ msgid ""
"Uses specified surface of given [Mesh] to populate data for MeshDataTool.\n"
"Requires [Mesh] with primitive type [constant Mesh.PRIMITIVE_TRIANGLES]."
msgstr ""
+"Utiliser la surface spécifiée de [Mesh] pour construire les données pour le "
+"MeshDataTool.\n"
+"Nécessite un [Mesh] de type primitif [constant Mesh.PRIMITIVE_TRIANGES]."
#: doc/classes/MeshDataTool.xml
msgid "Returns the number of edges in this [Mesh]."
@@ -42782,6 +44913,9 @@ msgid ""
"Vertex argument can only be 0 or 1 because edges are comprised of two "
"vertices."
msgstr ""
+"Retourne l'index des sommet spécifiés reliés au bord donné.\n"
+"L'argument du sommet ne peut être que 0 ou 1 car les bords ne sont composés "
+"que de deux sommets."
#: doc/classes/MeshDataTool.xml
msgid "Returns the number of faces in this [Mesh]."
@@ -42792,6 +44926,9 @@ msgid ""
"Returns specified edge associated with given face.\n"
"Edge argument must be either 0, 1, or 2 because a face only has three edges."
msgstr ""
+"Retourne le bord spécifié associé au face donné.\n"
+"L'argument du bord doit être soit 0, 1 ou 2 parce qu'une face n'a que trois "
+"bords."
#: doc/classes/MeshDataTool.xml
msgid "Returns the metadata associated with the given face."
@@ -42807,6 +44944,9 @@ msgid ""
"Vertex argument must be either 0, 1, or 2 because faces contain three "
"vertices."
msgstr ""
+"Retourne le vertx spécifié du face donné.\n"
+"L'argument du sommet doit être soit 0, 1 ou 2 parce que les faces ne "
+"contiennent que trois sommets."
#: doc/classes/MeshDataTool.xml
msgid ""
@@ -42817,6 +44957,12 @@ msgid ""
"ARRAY_FORMAT_NORMAL] is [code]2[/code].\n"
"See [enum ArrayMesh.ArrayFormat] for a list of format flags."
msgstr ""
+"Retourne le format du [Mesh]. Le format est un entier composé des drapeaux "
+"de format du [Mesh]. Par exemple, un maillage contenant à la fois des "
+"sommets et des normales retournerait un format de [code]3[/code] parce que ["
+"constant ArrayMesh.ARRAY_FORMAT_VERTEX] est [code]1[/code] et [constant "
+"ArrayMesh.ARRAY_FORMAT_NORMAL] est [code]2[/code].\n"
+"Voir [enum ArrayMesh.ArrayFormat] pour une liste de drapeaux de format."
#: doc/classes/MeshDataTool.xml
msgid "Returns the material assigned to the [Mesh]."
@@ -42931,6 +45077,13 @@ msgid ""
"[Mesh] has to be instanced more than thousands of times at close proximity, "
"consider using a [MultiMesh] in a [MultiMeshInstance] instead."
msgstr ""
+"MeshInstance est un nœud qui prend une ressource [Mesh] et l'ajoute au "
+"scénario actuel en créant une instance. C'est la classe la plus souvent "
+"utilisée pour obtenir la géométrie 3D pour le rendu et peut être utilisé "
+"pour l'instance d'un seul [Mesh] dans de nombreux endroits. Cela permet de "
+"réutiliser la géométrie et d'économiser des ressources. Lorsqu'un [Mesh] "
+"doit être instancié plusieurs milliers de fois les uns proches des autres, "
+"préférez plutôt un [MultiMesh] dans un [MultiMeshInstance]."
#: doc/classes/MeshInstance.xml
msgid ""
@@ -42943,6 +45096,16 @@ msgid ""
"If [code]simplify[/code] is [code]true[/code], the geometry can be further "
"simplified to reduce the amount of vertices. Disabled by default."
msgstr ""
+"Cette aide crée un nœud [StaticBody] enfant avec une forme de collision "
+"[ConvexPolygonShape] calculée à partir de la géométrie du maillage. Elle est "
+"principalement utilisée pour les essais.\n"
+"Si [code]clean[/code] est [code]true[/code] (par défaut), les doublons et "
+"les sommets intérieurs sont automatiquement supprimés. Vous pouvez le "
+"définir à [code]false[/code] pour rendre le processus de création plus "
+"rapide.\n"
+"Si [code]simplify[/code] est [code]true[/code], la géométrie pourra être "
+"simplifiée pour réduire la quantité de sommets, ce qui est désactivé par "
+"défaut."
#: doc/classes/MeshInstance.xml
msgid ""
@@ -42981,11 +45144,15 @@ msgid ""
"[method Mesh.surface_get_material] to get materials associated with the "
"[Mesh] resource."
msgstr ""
+"Retourne la surcharge [Material] pour une surface de la ressource [Mesh].\n"
+"[b]Note :[/b] Cette fonction ne retourne que les matériaux associés à la "
+"[i]surchage[/i] de la [MeshInstance]. Préférez [method get_active_material] "
+"ou [method Mesh.surface_get_material] pour obtenir des matériaux associés à "
+"la ressource [Mesh]."
#: doc/classes/MeshInstance.xml
-#, fuzzy
msgid "Returns the number of surface override materials."
-msgstr "Retourne le nombre de surfaces du matériau."
+msgstr "Retourne le nombre de surcharges des surfaces du matériau."
#: doc/classes/MeshInstance.xml
msgid ""
@@ -42995,6 +45162,12 @@ msgid ""
"In order to be mergeable, properties of the [MeshInstance] must match, and "
"each surface must match, in terms of material, attributes and vertex format."
msgstr ""
+"Retourne [code]true[/code] si cette [MeshInstance] peut être fusionnée avec "
+"l'autre instance [code]other_mesh_instance[/code], en utilisant la fonction ["
+"method MeshInstance.merge_meshes].\n"
+"Pour pouvoir être fusionnées, les propriétés des [MeshInstance] doivent "
+"correspondre, et chaque surface doit correspondre, en termes de matériau, "
+"d'attributs et de format des sommets."
#: doc/classes/MeshInstance.xml
msgid ""
@@ -43019,6 +45192,26 @@ msgid ""
"Also note that any initial data in the destination [MeshInstance] data will "
"be discarded."
msgstr ""
+"Cette fonction peut fusionner les données de plusieurs [MeshInstance] "
+"sources en une seule [MeshInstance] finale (le MeshInstance sur laquel la "
+"fonction est appelée). Ceci est principalement utile pour améliorer les "
+"performances en réduisant le nombre de appels de dessin et de [Node].\n"
+"Le fusions ne doivent être faites que sur des maillages simples et ne "
+"contenant pas d'animation.\n"
+"Les sommets finaux peuvent soit être retournés dans l'espace global, soit "
+"dans l'espace local par rapport à la transformation globale de la "
+"[MeshInstance] finale (ce nœud doit être à l'intérieur du [SceneTree] pour "
+"l'espace local pour fonctionner).\n"
+"La fonction effectuera un contrôle final de compatibilité entre les "
+"[MeshInstance] par défaut, cela devrait toujours être utilisé à moins que "
+"vous n'ayez préalablement vérifié la compatibilité avec [method MeshInstance."
+"is_mergeable_with]. Si la vérification est ignorée et que les maillages sont "
+"fusionnés, vous pouvez voir des erreurs de rendu.\n"
+"[b]Note :[/b] Les exigences de similitude entre les maillages sont assez "
+"strictes. Elles peuvent être vérifiés avec [method MeshInstance."
+"is_mergeable_with], avant d'appeler [method MeshInstance.merge_meshes]\n"
+"Notez également que toutes les données initiales dans la [MeshInstance] "
+"finale seront supprimées."
#: doc/classes/MeshInstance.xml
msgid ""
@@ -43026,6 +45219,9 @@ msgid ""
"resource. This material is associated with this [MeshInstance] rather than "
"with the [Mesh] resource."
msgstr ""
+"Définit la surcharge [Material] pour la surface spécifiée de la ressource "
+"[Mesh]. Ce matériel est associé à cette ressource [MeshInstance] plutôt qu'à "
+"la ressource [Mesh]."
#: doc/classes/MeshInstance.xml
msgid "The [Mesh] resource for the instance."
@@ -43118,9 +45314,8 @@ msgid "Returns the item's mesh."
msgstr "Retourne le maillage de l'élément."
#: doc/classes/MeshLibrary.xml
-#, fuzzy
msgid "Returns the transform applied to the item's mesh."
-msgstr "Retourne la matrice de transformation de la toile de cet objet."
+msgstr ""
#: doc/classes/MeshLibrary.xml
msgid "Returns the item's name."
@@ -43163,9 +45358,8 @@ msgid "Sets the item's mesh."
msgstr "Définit le maillage de l'élément."
#: doc/classes/MeshLibrary.xml
-#, fuzzy
msgid "Sets the transform to apply to the item's mesh."
-msgstr "Retourne la matrice de transformation de la toile de cet objet."
+msgstr ""
#: doc/classes/MeshLibrary.xml
msgid ""
@@ -43294,12 +45488,16 @@ msgid ""
"The height at which the camera is placed in relation to the ground (i.e. "
"[ARVROrigin] node)."
msgstr ""
+"La hauteur à laquelle la caméra est placée par rapport au sol (c'est-à-dire "
+"au nœud [ARVROrigin])."
#: modules/mobile_vr/doc_classes/MobileVRInterface.xml
msgid ""
"The interocular distance, also known as the interpupillary distance. The "
"distance between the pupils of the left and right eye."
msgstr ""
+"La distance interoculaire, aussi appelée la distance interpupillaire. La "
+"distance entre la pupille de l'œil gauche et celle du l'œil droit."
#: modules/mobile_vr/doc_classes/MobileVRInterface.xml
msgid ""
@@ -43312,7 +45510,7 @@ msgstr ""
#: modules/mobile_vr/doc_classes/MobileVRInterface.xml
msgid "The k2 lens factor, see k1."
-msgstr ""
+msgstr "Le facteur k2 de lentille, voir k1."
#: modules/mobile_vr/doc_classes/MobileVRInterface.xml
msgid ""
@@ -43385,6 +45583,18 @@ msgid ""
"(4 bytes as is) and [code]COLOR_FLOAT[/code] / [code]CUSTOM_DATA_FLOAT[/"
"code] is stored as 4 floats."
msgstr ""
+"Définit toutes les données relatives aux instances en une seule fois. Ceci "
+"est particulièrement utile lors du chargement des données du disque ou de la "
+"préparation des données de GDNative.\n"
+"Toutes les données sont empaquetées dans un grand tableau flottant. Un "
+"tableau peut ressembler à ceci : la Transform pour l'instance 1, les données "
+"de couleur pour l'instance 1, des données personnalisées pour l'instance 1, "
+"la Transform pour l'instance 2, les données de couleur pour l'instance 2, "
+"etc.\n"
+"[Transform] est enregistré avec 12 flottants, [Transform2D] avec 8 "
+"flottants, [code]COLOR_8BIT[/code] / [code]CUSTOM_DATA_8BIT[/code] avec 1 "
+"flottant (4 octets en général) et [code]COLOR_FLOAT[/code] / "
+"[code]CUSTOM_DATA_FLOAT[/code] avec 4 flottants."
#: doc/classes/MultiMesh.xml
msgid ""
@@ -43397,6 +45607,16 @@ msgid ""
"When the order of instances is coherent, the simpler [method MultiMesh."
"set_as_bulk_array] can still be used with interpolation."
msgstr ""
+"Une version alternative de [method MultiMesh.set_as_bulk_array] qui peut "
+"être utilisée avec [i]l'interpolation physique[/i]. Cette méthode prend deux "
+"tableaux, et peut définir les données pour la trame actuelle et précédente "
+"en une seule fois. Le rendu interpolera automatiquement les données entre "
+"ces deux trames.\n"
+"Ceci est utile pour les situations où l'ordre des instances peut changer "
+"d'une trame physique à l'autre, comme les systèmes de particules.\n"
+"Lorsque l'ordre des instances est cohérent, la méthode [method MultiMesh."
+"set_as_bulk_array] plus simple peut encore être utilisée avec "
+"l'interpolation."
#: doc/classes/MultiMesh.xml
msgid ""
@@ -43406,6 +45626,11 @@ msgid ""
"[code]null[/code] on the [MultiMesh] and [member SpatialMaterial."
"vertex_color_use_as_albedo] is [code]true[/code] on the material."
msgstr ""
+"Définit la couleur d'une instance spécifique en [i]multipliant[/i] les "
+"couleurs des sommets existants du maillage.\n"
+"Pour que la couleur soit modifiée, assurez-vous que [member color_format] "
+"n'est pas [code]null[/code] pour le [MultiMesh] et [member SpatialMaterial."
+"vertex_color_use_as_albedo] est [code]true[/code] dans le matériau."
#: doc/classes/MultiMesh.xml
msgid ""
@@ -43413,6 +45638,10 @@ msgid ""
"just a container for 4 floating point numbers. The format of the number can "
"change depending on the [enum CustomDataFormat] used."
msgstr ""
+"Définit des données personnalisées pour une instance spécifique. Bien que "
+"[Color] soit utilisée, ce n'est qu'un conteneur pour 4 flottants qui peut "
+"servir à autre chose. Le format du nombre peut changer en fonction du [enum "
+"CustomDataFormat] utilisé."
#: doc/classes/MultiMesh.xml
msgid "Sets the [Transform] for a specific instance."
@@ -43424,11 +45653,11 @@ msgstr "Définit la [Transform2D] pour l'instance spécifiée."
#: doc/classes/MultiMesh.xml
msgid "Format of colors in color array that gets passed to shader."
-msgstr ""
+msgstr "Le format des couleurs dans le tableau de couleurs passé au shader."
#: doc/classes/MultiMesh.xml
msgid "Format of custom data in custom data array that gets passed to shader."
-msgstr ""
+msgstr "Le format des données personnalisées dans ce tableau passé au shader."
#: doc/classes/MultiMesh.xml
msgid ""
@@ -43436,6 +45665,9 @@ msgid ""
"buffers. By default, all instances are drawn but you can limit this with "
"[member visible_instance_count]."
msgstr ""
+"Le nombre de cas qui seront affichés. Cela effacera et re-dimensionnera les "
+"mémoires tampons. Par défaut, toutes les instantes sont dessinées mais vous "
+"pouvez les limiter avec [member visible_instance_count]."
#: doc/classes/MultiMesh.xml
msgid "Mesh to be drawn."
@@ -43450,6 +45682,14 @@ msgid ""
"special cases mentioned above, the quality should be comparable to high "
"quality."
msgstr ""
+"Choisis si vous utilisez une méthode d'interpolation qui favorise la vitesse "
+"ou la qualité.\n"
+"Lors de l'utilisation de faibles taux de trames physiques (généralement "
+"inférieur à 20) ou de taux élevés de rotation d'objets, vous pouvez obtenir "
+"de meilleurs résultats à partir du réglage de haute qualité.\n"
+"[b]Note :[/b] La qualité rapide ne correspond pas à la qualité basse. Sauf "
+"dans les cas particuliers mentionnés ci-dessus, la qualité devrait être "
+"comparable à la qualité."
#: doc/classes/MultiMesh.xml
msgid "Format of transform used to transform mesh, either 2D or 3D."
@@ -43462,6 +45702,8 @@ msgid ""
"Limits the number of instances drawn, -1 draws all instances. Changing this "
"does not change the sizes of the buffers."
msgstr ""
+"Limite le nombre d'instances affichées, et -1 les dessine toutes. Changer "
+"cela ne change pas la taille des mémoires tampons."
#: doc/classes/MultiMesh.xml
msgid "Use this when using 2D transforms."
@@ -43480,12 +45722,17 @@ msgid ""
"Compress [Color] data into 8 bits when passing to shader. This uses less "
"memory and can be faster, but the [Color] loses precision."
msgstr ""
+"Compresse les données [Color] en 8 bits quand elles seront passées au "
+"shader. Cela utilise moins de mémoire et peut être plus rapide, mais les "
+"[Color] perdent en précision."
#: doc/classes/MultiMesh.xml
msgid ""
"The [Color] passed into [method set_instance_color] will use 4 floats. Use "
"this for highest precision [Color]."
msgstr ""
+"La [Color] passée dans [method set_instance_color] utilisera 4 flottants. "
+"Utilisez ceci pour la plus haute précision [Color]."
#: doc/classes/MultiMesh.xml
msgid "Use when you are not using per-instance custom data."
@@ -43677,12 +45924,16 @@ msgid ""
"Emitted when this MultiplayerAPI's [member network_peer] successfully "
"connected to a server. Only emitted on clients."
msgstr ""
+"Émis lorsque le [member network_peer] de ce MultijoueurAPI est connecté avec "
+"succès à un serveur. Seulement émis aux clients."
#: doc/classes/MultiplayerAPI.xml
msgid ""
"Emitted when this MultiplayerAPI's [member network_peer] fails to establish "
"a connection to a server. Only emitted on clients."
msgstr ""
+"Émis lorsque le [member network_peer] de ce MultijoueurAPI ne parvient pas à "
+"établir une connexion à un serveur. Seulement émis aux clients."
#: doc/classes/MultiplayerAPI.xml
msgid ""
@@ -43691,6 +45942,11 @@ msgid ""
"clients connect to the same server. Upon connecting to a server, a client "
"also receives this signal for the server (with ID being 1)."
msgstr ""
+"Émis lorsque le [member network_peer] de ce MultiplayerAPI se connecte à un "
+"nouveau pair. L'identifiant est celui du nouveau pair. Les clients sont "
+"informés lorsque d'autres clients se connectent au même serveur. En se "
+"connectant à un serveur, un client reçoit également ce signal pour le "
+"serveur (avec identifiant étant à 1)."
#: doc/classes/MultiplayerAPI.xml
msgid ""
@@ -43698,6 +45954,9 @@ msgid ""
"peer. Clients get notified when other clients disconnect from the same "
"server."
msgstr ""
+"Émis lorsque le [member network_peer] de ce MultiplayerAPI se déconnecte "
+"d'un pair. Les clients sont informés lorsque d'autres clients se "
+"déconnectent du même serveur."
#: doc/classes/MultiplayerAPI.xml
msgid ""
@@ -43705,12 +45964,18 @@ msgid ""
"[code]packet[/code] with custom data (see [method send_bytes]). ID is the "
"peer ID of the peer that sent the packet."
msgstr ""
+"Émis lorsque le [member network_peer] de ce MultijoueurAPI reçoit un "
+"[code]packet[/code] avec des données personnalisées (voir [method "
+"send_bytes)]. L'identifiant est l'identifiant par les pairs de l'équipe qui "
+"a envoyé le paquet."
#: doc/classes/MultiplayerAPI.xml
msgid ""
"Emitted when this MultiplayerAPI's [member network_peer] disconnects from "
"server. Only emitted on clients."
msgstr ""
+"Émis lorsque le [member network_peer] de ce MultijoueurAPI se déconnecte du "
+"serveur. Seulement émis sur les clients."
#: doc/classes/MultiplayerAPI.xml
msgid ""
@@ -43751,34 +46016,47 @@ msgid ""
"[i]Deprecated.[/i] Use [constant RPC_MODE_PUPPET] instead. Analogous to the "
"[code]slave[/code] keyword."
msgstr ""
+"[i]Obsolète.[/i] Utilisez plutôt [constant RPC_MODE_PUPPET]. Similaire au "
+"mot-clé [code]slave[/code]."
#: doc/classes/MultiplayerAPI.xml
msgid ""
"Behave like [constant RPC_MODE_REMOTE] but also make the call or property "
"change locally. Analogous to the [code]remotesync[/code] keyword."
msgstr ""
+"Se comporte comme [constant RPC_MODE_REMOTE] mais fait aussi l'appel ou le "
+"changement d'un propriété en local. Similaire au mot-clé "
+"[code]remotesync[/code]."
#: doc/classes/MultiplayerAPI.xml
msgid ""
"[i]Deprecated.[/i] Use [constant RPC_MODE_REMOTESYNC] instead. Analogous to "
"the [code]sync[/code] keyword."
msgstr ""
+"[i]Obsolète.[/i] Utilisez plutôt [constant RPC_MODE_REMOTESYNC]. Similaire "
+"au mot-clé [code]sync[/code]."
#: doc/classes/MultiplayerAPI.xml
msgid ""
"Behave like [constant RPC_MODE_MASTER] but also make the call or property "
"change locally. Analogous to the [code]mastersync[/code] keyword."
msgstr ""
+"Se comporte comme [constant RPC_MODE_MASTER] mais fait aussi l'appel ou le "
+"changement d'une propriété en local. Similaire au mot-clé "
+"[code]mastersync[/code]."
#: doc/classes/MultiplayerAPI.xml
msgid ""
"Behave like [constant RPC_MODE_PUPPET] but also make the call or property "
"change locally. Analogous to the [code]puppetsync[/code] keyword."
msgstr ""
+"Se comporte comme [constant RPC_MODE_PUPPET] mais fait aussi l'appel ou le "
+"changement d'une propriété en local. Similaire au mot-clé "
+"[code]puppetsync[/code]."
#: doc/classes/Mutex.xml
msgid "A synchronization mutex (mutual exclusion)."
-msgstr ""
+msgstr "Un mutex de synchronisation (exclusion mutuelle)."
#: doc/classes/Mutex.xml
msgid ""
@@ -43895,6 +46173,9 @@ msgid ""
"Returns the owner of the [NavigationMesh] which contains the navigation "
"point closest to the point given. This is usually a [NavigationMeshInstance]."
msgstr ""
+"Retourne le propriétaire du [NavigationMesh] qui contient le point de "
+"navigation le plus proche du point donné. C'est généralement une "
+"[NavigationMeshInstance]."
#: doc/classes/Navigation.xml
msgid ""
@@ -43905,9 +46186,8 @@ msgid ""
msgstr ""
#: doc/classes/Navigation.xml
-#, fuzzy
msgid "Returns the [RID] of the navigation map on the [NavigationServer]."
-msgstr "Retourne le [RID] de la énième forme d'une zone."
+msgstr ""
#: doc/classes/Navigation.xml
msgid ""
@@ -43919,6 +46199,13 @@ msgid ""
"agent properties associated with each [NavigationMesh] (radius, height, "
"etc.) are considered in the path calculation, otherwise they are ignored."
msgstr ""
+"[i]Obsolète.[/i] Le nœud [Navigation] la méthode [method get_simple_path] "
+"sont obsolètes se seront retiré dans une prochaine version. Utilisez plutôt ["
+"method NavigationServer.map_get_path].\n"
+"Retourne le chemin entre deux points donnés. Les points sont des coordonées "
+"locales. Si [code]optimize[/code] est [code]true[/code] (par défaut), les "
+"propriétés de l'agent associées à chaque [NavigationMesh] (rayon, hauteur, "
+"etc.) sont considérés dans le calcul du chemin, sinon ils sont ignorés."
#: doc/classes/Navigation.xml
msgid "The cell height to use for fields."
@@ -43944,12 +46231,16 @@ msgid ""
"Defines which direction is up. By default, this is [code](0, 1, 0)[/code], "
"which is the world's \"up\" direction."
msgstr ""
+"Définit la direction. Par défaut, il s'agit de [code](0, 1, 0)[/code], qui "
+"est la direction du haut (\"up\")."
#: doc/classes/Navigation.xml doc/classes/Navigation2DServer.xml
#: doc/classes/NavigationServer.xml
msgid ""
"Emitted when a navigation map is updated, when a region moves or is modified."
msgstr ""
+"Émis quand une carte de navigation est mise à jour, ou quand une région se "
+"déplace ou est modifiée."
#: doc/classes/Navigation2D.xml
msgid "2D navigation and pathfinding node."
@@ -43998,9 +46289,8 @@ msgid ""
msgstr ""
#: doc/classes/Navigation2DServer.xml
-#, fuzzy
msgid "Server interface for low-level 2D navigation access."
-msgstr "Interface de serveur pour l'accès audio de bas niveau."
+msgstr ""
#: doc/classes/Navigation2DServer.xml
#, fuzzy
@@ -44038,16 +46328,16 @@ msgstr ""
"de navigation. Ensemble, ces cartes définissent les aires navigables dans le "
"monde 2D. Pour que deux régions soient connectées entre elles, elles doivent "
"avoir une bordure en commun. Une bordure (\"edge\") est considérée connectée "
-"à une autre si elles ont deux sommets rapprochés de moins de la distance "
-"[member Navigation.edge_connection_margin].\n"
+"à une autre si elles ont deux sommets rapprochés de moins de la distance ["
+"member Navigation.edge_connection_margin].\n"
"Pour utiliser le système d'évitement, vous devez utiliser des agents. Vous "
"pouvez définir la vitesse cible d'un agent, puis le serveur émettra une "
"méthode de rappel avec la vitesse modifiée.\n"
"[b]Note :[/b] Le système d'évitement des collisions ignorent les régions. "
"Utiliser la vitesse modifiée telle quelle peut déplacer un agent hors de la "
-"surface de navigable. C'est une limite du système d'évitement des collision, "
-"et certaines situations plus complexes peuvent nécessiter l'utilisation du "
-"moteur physique.\n"
+"surface de navigable. C'est une limite du système d'évitement des "
+"collisions, et certaines situations plus complexes peuvent nécessiter "
+"l'utilisation du moteur physique.\n"
"Le serveur garde en mémoire tous les appels et les exécutent durant la phase "
"de synchronisation. Cela veut dire que vous pouvez demander n'importe quel "
"changement sur l'ensemble des cartes, via n'importe quel fil d'exécution, "
@@ -44062,11 +46352,12 @@ msgid ""
"Returns the navigation map [RID] the requested [code]agent[/code] is "
"currently assigned to."
msgstr ""
+"Retourne le [RID] de la carte de navigation auquel le [code]agent[/code] "
+"spécifié est actuellement assigné."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Returns [code]true[/code] if the map got changed the previous frame."
-msgstr "Renvoie [code]true[/code] si le chemin donné est filtré."
+msgstr ""
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
@@ -44092,11 +46383,13 @@ msgid ""
"navigation. The larger this number, the longer the running time of the "
"simulation. If the number is too low, the simulation will not be safe."
msgstr ""
+"Définit le nombre maximal d'autres agents que cet agent prend en compte dans "
+"la navigation. Plus ce nombre est grand, plus la durée de la simulation est "
+"longue. Si le nombre est trop bas, la simulation ne sera pas fiable."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Sets the maximum speed of the agent. Must be positive."
-msgstr "Obtient le nom d'un entrée par son index."
+msgstr ""
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
@@ -44104,11 +46397,14 @@ msgid ""
"the navigation. The larger this number, the longer the running time of the "
"simulation. If the number is too low, the simulation will not be safe."
msgstr ""
+"Définit la distance maximale avec d'autres agents que cet agent prend en "
+"compte dans la navigation. Plus ce nombre est grand, plus la durée de la "
+"simulation est longue. Si le nombre est trop bas, la simulation ne sera pas "
+"fiable."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Sets the position of the agent in world space."
-msgstr "Définit la position du nœud spécifié."
+msgstr ""
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid "Sets the radius of the agent."
@@ -44126,11 +46422,14 @@ msgid ""
"agents, but the less freedom this agent has in choosing its velocities. Must "
"be positive."
msgstr ""
+"La quantité minimale de temps pour laquelle les vitesses de l'agent "
+"calculées par la simulation sont fiables pour les autres agents. Plus ce "
+"nombre est grand, plus tôt cet agent répondra à la présence d'autres agents, "
+"mais moins il aura de liberté pour choisir sa vitesse. Ça doit être positif."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Sets the current velocity of the agent."
-msgstr "Définit le trame présentement visible de l'animation."
+msgstr ""
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid "Destroys the given RID."
@@ -44142,6 +46441,9 @@ msgid ""
"returns both 2D and 3D created navigation maps as there is technically no "
"distinction between them."
msgstr ""
+"Retourne tous les [RID] des cartes de navigation créées sur le "
+"NavigationServer. Cela renvoie les cartes de navigation 2D et aussi 3D car "
+"il n'y a techniquement aucune distinction entre eux."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid "Create a new map."
@@ -44175,19 +46477,47 @@ msgid ""
"but it can also introduce bugs if used inappropriately without much "
"foresight."
msgstr ""
+"Cette fonction force immédiatement la synchronisation de la navigation "
+"spécifiée par le [RID] spécifié par [code]map[/code]. Par défaut, les cartes "
+"de navigation ne sont synchronisées qu'à la fin de chaque trame physique. "
+"Cette fonction peut être utilisée pour calculer immédiatement tous les "
+"maillages de navigation et les connexions entre les régions de la carte de "
+"navigation. Cela permet d'interroger un chemin de navigation pour une carte "
+"modifiée immédiatement et dans la même trame (plusieurs fois si nécessaire)."
+"\n"
+"En raison de restrictions techniques, la file de commandes actuelle de "
+"NavigationServer sera exécutée aussitôt. Cela signifie que toutes les "
+"commandes de mise à jour en attente pour cette trame de physique seront "
+"exécutées, même celles destinées à d'autres cartes, régions et agents qui ne "
+"font pas partie de la carte spécifiée. Le calcul coûteux des maillages de "
+"navigation et des connexions de régions d'une carte ne sera fait que pour la "
+"carte spécifiée. D'autres cartes recevront la synchronisation normale à la "
+"fin de la trame physique. Si la carte spécifiée reçoit des changements après "
+"la mise à jour forcée, elle sera à nouveau mise à jour aussi bien lorsque "
+"les autres cartes recevront leur mise à jour.\n"
+"Le traitement d'évitement et l'envoi des signaux [code]safe_velocity[/code] "
+"ne sont pas affectés par cette fonction et continuent de se produire pour "
+"tous les cartes et agents à la fin de la trame physique.\n"
+"[b]Note :[/b] Une grande pouvoir implique une grande responsabilité. Cette "
+"fonction ne devrait être utilisée que par les utilisateurs qui savent "
+"vraiment ce qu'ils font et ont une bonne raison de l'utiliser. Pour "
+"effectuer une mise à jour immédiate d'une carte de navigation, il faut "
+"verrouiller le NavigationServer et exécuter toute la file de commandes du "
+"NavigationServer. Non seulement cela peut affecter sévèrement les "
+"performances du jeu, mais il peut également introduire des bugs si ça n'est "
+"pas fait avec le plus grand soin."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
"Returns all navigation agents [RID]s that are currently assigned to the "
"requested navigation [code]map[/code]."
msgstr ""
+"Retourne tous [RID] des agents de navigation qui sont actuellement affectés "
+"à la navigation [code]map[/code] spécifiée."
#: doc/classes/Navigation2DServer.xml
-#, fuzzy
msgid "Returns the map cell height. [b]Note:[/b] Currently not implemented."
msgstr ""
-"Retourne l'actuelle ligne du fichier interprété (actuellement non "
-"implémenté)."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid "Returns the map cell size."
@@ -44206,12 +46536,16 @@ msgid ""
"Returns the owner region RID for the point returned by [method "
"map_get_closest_point]."
msgstr ""
+"Retourne la région propriétaire du RID pour le point retourné par [method "
+"map_get_closest_point]."
#: doc/classes/Navigation2DServer.xml
msgid ""
"Returns the edge connection margin of the map. The edge connection margin is "
"a distance used to connect two regions."
msgstr ""
+"Retourne la marge de raccordement du bord de la carte. La marge de "
+"raccordement est une distance utilisée pour relier deux régions."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
@@ -44219,38 +46553,42 @@ msgid ""
"[code]navigation_layers[/code] is a bitmask of all region layers that are "
"allowed to be in the path."
msgstr ""
+"Retourne le chemin de navigation pour atteindre la destination de l'origine. "
+"[code]navigation_layers[/code] est un bitmask de toutes les calques de la "
+"région qui sont autorisées à être dans le chemin."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
"Returns all navigation regions [RID]s that are currently assigned to the "
"requested navigation [code]map[/code]."
msgstr ""
+"Retourne toutes les régions de navigation [RID] qui sont actuellement "
+"affectées à la navigation demandée [code]map[/code]."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Returns [code]true[/code] if the map is active."
-msgstr "Retourne [code]true[/code] si l'[AABB] est vide."
+msgstr ""
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid "Sets the map active."
msgstr "Définit la carte comme active."
#: doc/classes/Navigation2DServer.xml
-#, fuzzy
msgid ""
"Set the map cell height used to weld the navigation mesh polygons. [b]Note:[/"
"b] Currently not implemented."
-msgstr "Définit le polygone de navigation de la tuile."
+msgstr ""
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Set the map cell size used to weld the navigation mesh polygons."
-msgstr "Définit le polygone de navigation de la tuile."
+msgstr ""
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
"Set the map edge connection margin used to weld the compatible region edges."
msgstr ""
+"Définit la marge de connexion de bord de la carte utilisée pour fusionner "
+"les bords compatibles de la région."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid "Creates a new region."
@@ -44262,6 +46600,8 @@ msgid ""
"index between 0 and the return value of [method "
"region_get_connections_count]."
msgstr ""
+"Retourne le point de fin d'une porte de connexion. [code]connection[/code] "
+"est un indice entre 0 et la valeur de [method region_get_connections_count]."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
@@ -44269,33 +46609,36 @@ msgid ""
"an index between 0 and the return value of [method "
"region_get_connections_count]."
msgstr ""
+"Retourne le point de départ d'une porte de connexion. [code]connection[/code]"
+" est un indice entre 0 et la valeur de [method region_get_connections_count]."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
"Returns how many connections this [code]region[/code] has with other regions "
"in the map."
msgstr ""
+"Retourne le nombre de connexions ce [code]region[/code] a avec les autres "
+"régions de la carte."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Returns the [code]enter_cost[/code] of this [code]region[/code]."
-msgstr "Retourne [code]true[/code] si le [code]signal[/code] donné existe."
+msgstr ""
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
"Returns the navigation map [RID] the requested [code]region[/code] is "
"currently assigned to."
msgstr ""
+"Retourne le [RID] de la carte de navigation à laquelle la [code]region[/code]"
+" spécifiée est actuellement assignée."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Returns the region's navigation layers."
-msgstr "Retourne le maillage de navigation de l'élément."
+msgstr "Retourne les calques de navigation de la région."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Returns the [code]travel_cost[/code] of this [code]region[/code]."
-msgstr "Retourne [code]true[/code] si le [code]signal[/code] donné existe."
+msgstr ""
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
@@ -44313,41 +46656,49 @@ msgid ""
"(which should be avoided in general) the result might not be what is "
"expected."
msgstr ""
+"Retourne [code]true[/code] si la coordonnée [code]point[/code] global "
+"appartient actuellement à la [code]region[/code] de la navigation. Dans ce "
+"contexte, l'une des faces du polygone de maillages de navigation de la "
+"région a une position possible à la distance la plus proche de ce point par "
+"rapport à tous les autres maillages de navigation provenant d'autres régions "
+"de navigation également enregistrées sur la carte de navigation de la région "
+"donnée.\n"
+"Si plusieurs maillages de navigation ont des positions à égale distance, la "
+"région de navigation dont les polygones sont traités en premier sont "
+"retournés. Les polygones sont traités dans l'ordre d'ajout des régions dans "
+"le serveur de navigation.\n"
+"[b]Note :[/b] Si les maillages de navigation provenant de différentes "
+"régions de navigation se chevauchent (qui doivent être évités en général), "
+"le résultat peut être inattendu."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Sets the [code]enter_cost[/code] for this [code]region[/code]."
msgstr ""
-"Définit la [code]position[/code] du point avec l'identifiant [code]id[/code] "
-"spécifié."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Sets the map for the region."
-msgstr "Retourne la hauteur du contenu."
+msgstr "Définit la carte de la région."
#: doc/classes/Navigation2DServer.xml
msgid ""
"Set the region's navigation layers. This allows selecting regions from a "
"path request (when using [method Navigation2DServer.map_get_path])."
msgstr ""
+"Définit les calques de navigation de la région. Cela permet de sélectionner "
+"les régions à partir d'une requête de chemin (en utilisant [method "
+"Navigation2DServer.map_get_path])."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Sets the navigation mesh for the region."
-msgstr "Définit le polygone de navigation de la tuile."
+msgstr "Définit le polygone de navigation de la région."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Sets the global transformation for the region."
-msgstr "Retourne la matrice de transformation globale de cet élément."
+msgstr "Retourne la transformation globale de cette région."
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Sets the [code]travel_cost[/code] for this [code]region[/code]."
msgstr ""
-"Définit la [code]position[/code] du point avec l'identifiant [code]id[/code] "
-"spécifié."
#: doc/classes/NavigationAgent.xml
msgid "3D agent used in navigation for collision avoidance."
@@ -44369,6 +46720,21 @@ msgid ""
"position from this function should be used as the next movement position for "
"the agent's parent Node."
msgstr ""
+"Agent 3D utilisé dans la navigation pour atteindre un emplacement tout en "
+"évitant les obstacles statiques et dynamiques. Les obstacles dynamiques sont "
+"évités en utilisant la méthode RVO (Reciprocal Velocity Obstacles). L'agent "
+"a besoin de données de navigation pour fonctionner correctement. Par défaut "
+"ce nœud s'enregistrera à la carte de navigation par défaut du [World]. Si ce "
+"nœud est un enfant d'un nœud [Navigation] il s'inscrira à la carte de "
+"navigation du nœud de navigation ou la fonction [method set_navigation] peut "
+"être utilisée pour définir le nœud de navigation directement. "
+"[NavigationAgent] est sûr lors du traitement physique.\n"
+"[b]Note :[/b] Après que [method set_target_location] est utilisé, il est "
+"nécessaire d'utiliser la fonction [method get_next_location] une fois par "
+"trame physique pour mettre à jour la logique de chemin interne du "
+"NavigationAgent. La position vectorielle retournée de cette fonction devrait "
+"être utilisée comme position de mouvement suivante pour le Node parent de "
+"l'agent principal."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44376,6 +46742,9 @@ msgid ""
"position. The user must set the target location with [method "
"set_target_location] in order for this to be accurate."
msgstr ""
+"Retourne la distance jusqu'à l'emplacement cible, en utilisant la position "
+"globale de l'agent observé. L'utilisateur doit définir l'emplacement de la "
+"cible avec [method set_target_location] afin d'être précis."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44383,6 +46752,9 @@ msgid ""
"if the navigation path is altered in any way. Because of this, it would be "
"best to check this each frame."
msgstr ""
+"Retourne l'emplacement final accessible dans les coordonnées globales. Cela "
+"peut changer si le chemin de navigation est modifié de quelque manière que "
+"ce soit. Pour cette raison, il serait préférable de vérifier chaque trame."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44395,6 +46767,15 @@ msgid ""
"for the agents movement as this function also updates the internal path "
"logic."
msgstr ""
+"Retourne le chemin actuel de l'agent du début jusqu'à la fin, dans les "
+"coordonnées globales. Le chemin ne met à jour que lorsque l'emplacement de "
+"la cible est modifié ou que l'agent demande un re-calcul du chemin. Le "
+"réseau de chemin n'est pas destiné à être utilisé dans le mouvement de "
+"chemin direct car l'agent a sa propre logique de chemin interne qui serait "
+"corrompu en changeant le réseau de chemin manuellement. Utilisez la [method "
+"get_next_location] voulue une fois chaque trame de physique pour recevoir le "
+"point de chemin suivant pour le mouvement des agents car cette fonction met "
+"également à jour la logique du chemin interne."
#: doc/classes/NavigationAgent.xml
msgid ""
@@ -44407,6 +46788,8 @@ msgid ""
"Returns the [Navigation] node that the agent is using for its navigation "
"system."
msgstr ""
+"Retourne le nœud [Navigation] que l'agent utilise pour son système de "
+"navigation."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44418,6 +46801,14 @@ msgid ""
"the navigation map for the NavigationAgent and also update the agent on the "
"NavigationServer."
msgstr ""
+"Retourne le [RID] de la carte de navigation pour ce nœud NavigationAgent. "
+"Cette fonction retourne toujours la carte définie sur le nœud "
+"NavigationAgent et non la carte de l'agent abstrait sur le serveur "
+"Navigation. Si la carte de l'agent est changée directement avec l'API de "
+"NavigationServer, le nœud NavigationAgent ne sera pas au courant du "
+"changement de carte. Utilisez [method set_navigation_map] pour changer la "
+"carte de navigation pour le NavigationAgent et mettre à jour l'agent sur le "
+"NavigationServer."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44427,25 +46818,28 @@ msgid ""
"use of this function once every physics frame is required to update the "
"internal path logic of the NavigationAgent."
msgstr ""
+"Retourne l'emplacement suivant dans les coordonnées globales qui peuvent "
+"être déplacées, en s'assurant qu'il n'y a pas d'objets statiques dans le "
+"chemin. Si l'agent n'a pas de chemin de navigation, il retourne la position "
+"du parent de l'agent. L'utilisation de cette fonction une fois chaque trame "
+"physique est nécessaire pour mettre à jour la logique de chemin interne de "
+"la NavigationAgent."
#: doc/classes/NavigationAgent.xml
-#, fuzzy
msgid "Returns the [RID] of this agent on the [NavigationServer]."
-msgstr "Retourne le [RID] de la énième forme d'une zone."
+msgstr "Retourne le [RID] de cet agent dans le [NavigationServer]."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
-#, fuzzy
msgid ""
"Returns the user-defined target location (set with [method "
"set_target_location])."
-msgstr "Renvoie le mode de remplacement de l’espace pour la zone."
+msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the navigation path's final location has been "
"reached."
-msgstr "Renvoie [code]true[/code] si le chemin donné est filtré."
+msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44468,18 +46862,25 @@ msgid ""
"Sets the [Navigation] node used by the agent. Useful when you don't want to "
"make the agent a child of a [Navigation] node."
msgstr ""
+"Définit le nœud [Navigation] utilisé par l'agent. Utile lorsque vous ne "
+"voulez pas faire de l'agent un enfant d'un nœud [Navigation]."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
"Sets the [RID] of the navigation map this NavigationAgent node should use "
"and also updates the [code]agent[/code] on the NavigationServer."
msgstr ""
+"Définit le [RID] de la carte de navigation que ce nœud NavigationAgent "
+"devrait utiliser et met à jour le [code]agent[/code] sur le serveur de "
+"navigation."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
"Sets the user desired final location. This will clear the current navigation "
"path."
msgstr ""
+"Définit l'emplacement final souhaité de l'utilisateur. Cela permettra "
+"d'effacer le chemin de navigation actuel."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44487,6 +46888,9 @@ msgid ""
"adjust the velocity to avoid collisions. Once the adjustment to the velocity "
"is complete, it will emit the [signal velocity_computed] signal."
msgstr ""
+"Envoie la vitesse spécifiée à l'algorithme d'évitement de collision. Celui-"
+"ci ajustera la vitesse pour éviter les collisions. Une fois le réglage de la "
+"vitesse terminée, il émettra le signal [signal velocity_computed]."
#: doc/classes/NavigationAgent.xml
msgid ""
@@ -44497,6 +46901,14 @@ msgid ""
"that the developer baked with appropriate agent radius or height values are "
"required to support different-sized agents."
msgstr ""
+"La hauteur du NavigationAgent est soustraite de la valeur de l'axe Y de "
+"toute position de chemin vectoriel pour ce NavigationAgent. Le décalage de "
+"hauteur du NavigationAgent ne change pas ou n'influence pas le résultat de "
+"la requête du maillage de navigation ou du cheminement. Des cartes de "
+"navigation supplémentaires qui utilisent des régions avec des maillages de "
+"navigation que le développeur a pré-calculé avec un rayon d'agent approprié "
+"ou des valeurs de hauteur sont nécessaires pour supporter des agents de "
+"taille différente."
#: doc/classes/NavigationAgent.xml
msgid ""
@@ -44507,22 +46919,29 @@ msgid ""
"with many registered agents has a significant performance cost and should "
"only be enabled on agents that currently require it."
msgstr ""
+"Si [code]true[/code] l'agent est enregistré pour un rappel d'évitement RVO "
+"sur le [NavigationServer]. Lorsque [method set_velocity] est utilisé et que "
+"le traitement est terminé, un Vector3 [code]safe_velocity[/code] est reçu "
+"avec une connexion du signal [signal velocity_computed]. Le traitement de "
+"l'évitement avec de nombreux agents enregistrés a un coût de performance "
+"important et ne devrait être activé que pour les agents qui en ont "
+"actuellement besoin."
#: doc/classes/NavigationAgent.xml
msgid ""
"Ignores collisions on the Y axis. Must be [code]true[/code] to move on a "
"horizontal plane."
msgstr ""
+"Ignore les collisions sur l'axe Y. Doit être [code]true[/code] pour se "
+"déplacer sur un plan horizontal."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
-#, fuzzy
msgid "The maximum number of neighbors for the agent to consider."
-msgstr "La valeur de luminance maximale pour l'exposition automatique."
+msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
-#, fuzzy
msgid "The maximum speed that an agent can move."
-msgstr "Rotation maximale à travers la charnière."
+msgstr "La vitesse maximale à laquelle un agent peut se déplacer."
#: doc/classes/NavigationAgent.xml
msgid ""
@@ -44530,11 +46949,14 @@ msgid ""
"belongs to. On path requests the agent will ignore navmeshes without at "
"least one matching layer."
msgstr ""
+"Un masque de bit déterminant toutes les calque de carte de navigation "
+"auxquels ce [NavigationAgent] appartient. Lors de requête de chemin, l'agent "
+"va ignorer les maillages de navigation qui n'ont pas au moins un calque "
+"correspondant."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
-#, fuzzy
msgid "The distance to search for other agents."
-msgstr "L’instance n’a pas de type."
+msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44546,6 +46968,14 @@ msgid ""
"it will constantly overshoot or undershoot the distance to the next point on "
"each physics frame update."
msgstr ""
+"Le seuil de distance avant qu'un point de chemin soit considéré comme "
+"atteint. Cela permettra à un agent de ne pas avoir à atteindre un point de "
+"chemin exactement sur le chemin, mais uniquement un zone autour. Si cette "
+"valeur est élevée, la NavigationAgent sautera des points sur le chemin qui "
+"peut conduire à quitter le maillage de navigation. Si cette valeur est trop "
+"faible, le NavigationAgent sera coincé dans une boucle de chemin parce qu'il "
+"va constamment mal estimer la distance jusqu'au point suivant à chaque mise "
+"à jour de la trame physique."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44553,8 +46983,11 @@ msgid ""
"final location. This can happen due to trying to avoid collisions. When the "
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
+"La distance maximale de l'agent est permise loin du chemin idéal jusqu'à "
+"l'emplacement final. Cela peut arriver en essayant d'éviter les collisions. "
+"Lorsque la distance maximale est dépassée, cela recalcule le chemin idéal."
-#: 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 "
@@ -44563,6 +46996,13 @@ msgid ""
"bake [NavigationMesh] resources with a different [member NavigationMesh."
"agent_radius] property and use different navigation maps for each actor size."
msgstr ""
+"Le rayon d'évitement de l'agent. Il s'agit du « corps » de l'agent "
+"d'évitement et non le rayon de la manœuvre d'évitement (qui est contrôlé par "
+"[member neighbor_dist)].\n"
+"N'affecte pas le cheminement normal. Pour changer les ressources "
+"[NavigationMesh] de rayon de pré-calcul de cheminement d'un acteur avec la "
+"propriété [member NavigationMesh.agent_radius] différente et utiliser "
+"différentes cartes de navigation pour chaque acteur."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44573,6 +47013,12 @@ msgid ""
"overshoot or undershoot the distance to the final target point on each "
"physics frame update."
msgstr ""
+"Le seuil de distance avant qu'un point de chemin soit considéré comme "
+"atteint. Cela permettra à un agent de ne pas avoir à atteindre un point de "
+"chemin exactement sur le chemin, mais uniquement un zone autour. Si cette "
+"valeur est trop faible, le NavigationAgent sera coincé dans une boucle de "
+"chemin parce qu'il va constamment mal estimer la distance jusqu'au point "
+"suivant à chaque mise à jour de la trame physique."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44582,29 +47028,39 @@ msgid ""
"other agents, but the less freedom in choosing its velocities. Must be "
"positive."
msgstr ""
+"La quantité minimale de temps pour laquelle les vitesses de cet agent, "
+"calculées avec l'algorithme d'évitement de collision, sont sûres pour les "
+"autres agents. Plus le nombre est élevé, plus tôt l'agent répondra à "
+"d'autres agents, mais moins il aura la liberté de choisir sa vitesse. Ça "
+"doit être positif."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
-#, fuzzy
msgid "Notifies when the final location is reached."
-msgstr "Avertit quand une animation commence à jouer."
+msgstr ""
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
"Notifies when the navigation path changes. This can be triggered by the "
"navigation system or by the user changing the path."
msgstr ""
+"Notifie quand le chemin de navigation change. Cela peut être déclenché par "
+"le système de navigation ou par l'utilisateur qui change le chemin."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
"Notifies when the player-defined target, set with [method "
"set_target_location], is reached."
msgstr ""
+"Notifie quand la cible définie par le joueur, définie avec [method "
+"set_target_location], est atteinte."
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
"Notifies when the collision avoidance velocity is calculated after a call to "
"[method set_velocity]."
msgstr ""
+"Notifie quand la vitesse d'évitement de collision est calculée après un "
+"appel à [method set_velocity]."
#: doc/classes/NavigationAgent2D.xml
msgid "2D agent used in navigation for collision avoidance."
@@ -44626,6 +47082,21 @@ msgid ""
"position from this function should be used as the next movement position for "
"the agent's parent Node."
msgstr ""
+"L'agent 2D utilisé dans la navigation pour atteindre un emplacement tout en "
+"évitant les obstacles statiques et dynamiques. Les obstacles dynamiques sont "
+"évités en utilisant l'évitement de collision RVO (Reciprocal Velocity "
+"Obstacles). L'agent a besoin de données de navigation pour fonctionner "
+"correctement. Par défaut ce nœud s'enregistrera à la carte de navigation par "
+"défaut du [World2D]. Si ce nœud est un enfant d'un nœud [Navigation2D] il "
+"s'inscrira à la carte de navigation du nœud de navigation ou la fonction "
+"[method set_navigation] peut être utilisé pour définir le nœud de navigation "
+"directement. [NavigationAgent2D] est sûr lors des trames physiques.\n"
+"[b]Note :[/b] Après que [method set_target_location] est utilisé, il est "
+"nécessaire d'utiliser la fonction [method get_next_location] une fois chaque "
+"trame physique pour mettre à jour la logique interne de chemin du "
+"NavigationAgent. La position vectorielle retournée de cette fonction devrait "
+"être utilisée comme position de mouvement suivante pour le Node parent de "
+"l'agent principal."
#: doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44638,17 +47109,20 @@ msgid ""
"Returns the [Navigation2D] node that the agent is using for its navigation "
"system."
msgstr ""
+"Retourne le nœud [Navigation2D] que l'agent utilise pour son système de "
+"navigation."
#: doc/classes/NavigationAgent2D.xml
-#, fuzzy
msgid "Returns the [RID] of this agent on the [Navigation2DServer]."
-msgstr "Retourne le [RID] de la énième forme d'une zone."
+msgstr "Retourne le [RID] de cet agent dans le [Navigation2DServer]."
#: doc/classes/NavigationAgent2D.xml
msgid ""
"Sets the [Navigation2D] node used by the agent. Useful when you don't want "
"to make the agent a child of a [Navigation2D] node."
msgstr ""
+"Définit le nœud [Navigation2D] utilisé par l'agent. Utile lorsque vous ne "
+"voulez pas faire de l'agent un enfant d'un nœud [Navigation2D]."
#: doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44659,6 +47133,13 @@ msgid ""
"with many registered agents has a significant performance cost and should "
"only be enabled on agents that currently require it."
msgstr ""
+"Si [code]true[/code] l'agent est enregistré pour un rappel d'évitement RVO "
+"sur le [Navigation2DServer]. Lorsque [method set_velocity] est utilisé et "
+"que le traitement est terminé, un Vector2 [code]safe_velocity[/code] est "
+"reçu avec une connexion au signal [signal velocity_computed]. Le traitement "
+"de l'évitement avec de nombreux agents enregistrés a un coût de performance "
+"important et ne devrait être activé que pour les agents qui en ont "
+"actuellement besoin."
#: doc/classes/NavigationAgent2D.xml
msgid ""
@@ -44666,6 +47147,22 @@ msgid ""
"belongs to. On path requests the agent will ignore navmeshes without at "
"least one matching layer."
msgstr ""
+"Un masque de bit déterminant toutes les calque de carte de navigation "
+"auxquels ce [NavigationAgent2D] appartient. Lors de requête de chemin, "
+"l'agent va ignorer les maillages de navigation qui n'ont pas au moins un "
+"calque correspondant."
+
+#: 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 ""
+"Le rayon d'évitement de l'agent. Il s'agit du « corps » de l'agent "
+"d'évitement et non le rayon de la manœuvre d'évitement (qui est contrôlé par "
+"[member neighbor_dist)].\n"
+"N'affecte pas le cheminement normal."
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
@@ -44697,11 +47194,10 @@ msgid ""
msgstr ""
#: doc/classes/NavigationMesh.xml
-#, fuzzy
msgid ""
"Returns whether the specified [code]bit[/code] of the [member "
"geometry_collision_mask] is set."
-msgstr "Retourne si la [code]class[/code] spécifiée est disponible ou non."
+msgstr ""
#: doc/classes/NavigationMesh.xml doc/classes/NavigationPolygon.xml
msgid ""
@@ -44712,9 +47208,8 @@ msgstr ""
"créé."
#: doc/classes/NavigationMesh.xml
-#, fuzzy
msgid "Returns the number of polygons in the navigation mesh."
-msgstr "Renvoie le nombre de points sur l'axe de mélange."
+msgstr ""
#: doc/classes/NavigationMesh.xml
msgid ""
@@ -44725,17 +47220,16 @@ msgstr ""
"créé."
#: doc/classes/NavigationMesh.xml
-#, fuzzy
msgid ""
"If [code]value[/code] is [code]true[/code], sets the specified [code]bit[/"
"code] in the [member geometry_collision_mask].\n"
"If [code]value[/code] is [code]false[/code], clears the specified [code]bit[/"
"code] in the [member geometry_collision_mask]."
msgstr ""
-"Si [code]value[/code] est [code]true[/code]], définit le [code]bit[/code] "
-"spécifié dans le masque [nom collision_mask].\n"
-"Si [code]value[/code] est [code]false[/code], rétablit le [code]bit[/code] "
-"spécifié dans le masque [nom collision_mask]."
+"Si [code]value[/code] est [code]true[/code], définit le [code]bit[/code] "
+"spécifié dans le masque [member geometry_collision_mask].\n"
+"Si [code]value[/code] est [code]false[/code], efface le [code]bit[/code] "
+"spécifié dans le masque [member geometry_collision_mask]."
#: doc/classes/NavigationMesh.xml doc/classes/NavigationPolygon.xml
msgid ""
@@ -44759,9 +47253,8 @@ msgid ""
msgstr ""
#: doc/classes/NavigationMesh.xml
-#, fuzzy
msgid "The maximum slope that is considered walkable, in degrees."
-msgstr "Rotation maximale à travers la charnière."
+msgstr ""
#: doc/classes/NavigationMesh.xml
msgid ""
@@ -44810,9 +47303,8 @@ msgid "The position offset applied to the [member filter_baking_aabb] [AABB]."
msgstr ""
#: doc/classes/NavigationMesh.xml
-#, fuzzy
msgid "If [code]true[/code], marks spans that are ledges as non-walkable."
-msgstr "Si [code]true[/code], les titres des colonnes sont visibles."
+msgstr ""
#: doc/classes/NavigationMesh.xml
msgid ""
@@ -44821,13 +47313,10 @@ msgid ""
msgstr ""
#: doc/classes/NavigationMesh.xml
-#, fuzzy
msgid ""
"If [code]true[/code], marks walkable spans as not walkable if the clearance "
"above the span is less than [member agent_height]."
msgstr ""
-"Si [code]true[/code], les particules sera émise une seule fois puis "
-"arrêtées. Équivalent à [member Particles.one_shot]."
#: doc/classes/NavigationMesh.xml
msgid ""
@@ -44835,12 +47324,17 @@ msgid ""
"Only used when [member geometry_parsed_geometry_type] is [constant "
"PARSED_GEOMETRY_STATIC_COLLIDERS] or [constant PARSED_GEOMETRY_BOTH]."
msgstr ""
+"Les calques de physique pour scanner les collisions statiques.\n"
+"Seulement utilisé quand [member geometry_parsed_geometry_type] est [constant "
+"PARSED_GEOMETRY_STATIC_COLLIDERS] ou [constant] PARSED_GEOMETRY_BOTH]."
#: doc/classes/NavigationMesh.xml
msgid ""
"Determines which type of nodes will be parsed as geometry. See [enum "
"ParsedGeometryType] for possible values."
msgstr ""
+"Détermine quel type de nœuds seront interprétés comme géométrie. Voir [enum "
+"ParsedGeometryType] pour les valeurs possibles."
#: doc/classes/NavigationMesh.xml
msgid ""
@@ -44855,12 +47349,18 @@ msgid ""
"SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN] or [constant "
"SOURCE_GEOMETRY_GROUPS_EXPLICIT]."
msgstr ""
+"Le nom du groupe pour scanner la géométrie.\n"
+"Seulement utilisé lorsque [member geometry_source_geometry_mode] est "
+"[constant SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN] ou [constant] "
+"SOURCE_GEOMETRY_GROUPS_EXPLICIT]."
#: doc/classes/NavigationMesh.xml
msgid ""
"The maximum number of vertices allowed for polygons generated during the "
"contour to polygon conversion process."
msgstr ""
+"Le nombre maximal de sommets permis pour les polygones générés pendant le "
+"contour du processus de conversion en polygones."
#: doc/classes/NavigationMesh.xml
msgid ""
@@ -44869,6 +47369,10 @@ msgid ""
"[b]Note:[/b] This value will be squared to calculate the number of cells. "
"For example, a value of 20 will set the number of cells to 400."
msgstr ""
+"Toutes les régions ayant une taille inférieure à celle-ci seront fusionnées "
+"avec des régions plus grandes si possible.\n"
+"[b]Note :[/b] Cette valeur sera carrée pour calculer le nombre de cellules. "
+"Par exemple, une valeur de 20 définira le nombre de cellules à 400."
#: doc/classes/NavigationMesh.xml
msgid ""
@@ -44877,12 +47381,18 @@ msgid ""
"cells allowed to form isolated island areas. For example, a value of 8 will "
"set the number of cells to 64."
msgstr ""
+"La taille minimale d'une région pour qu'elle soit créée.\n"
+"[b]Note :[/b] Cette valeur sera fixée pour calculer le nombre minimum de "
+"cellules autorisées à former des zones insulaires isolées. Par exemple, une "
+"valeur de 8 définira le nombre de cellules à 64."
#: doc/classes/NavigationMesh.xml
msgid ""
"Partitioning algorithm for creating the navigation mesh polys. See [enum "
"SamplePartitionType] for possible values."
msgstr ""
+"Algorithme de partitionnement pour la création des polygones de maillage de "
+"navigation. Voir [enum SamplePartitionType] pour les valeurs possibles."
#: doc/classes/NavigationMesh.xml
msgid ""
@@ -44894,12 +47404,16 @@ msgstr ""
msgid ""
"Monotone partitioning. Use this if you want fast navigation mesh generation."
msgstr ""
+"Partage monotone. Utilisez ceci si vous voulez une génération de maillages "
+"de navigation rapide."
#: doc/classes/NavigationMesh.xml
msgid ""
"Layer partitioning. Good choice to use for tiled navigation mesh with medium "
"and small sized tiles."
msgstr ""
+"Le partitionnement du calque. Un bon choix à utiliser pour la maillage de "
+"navigation en carreaux de taille moyenne et petite."
#: doc/classes/NavigationMesh.xml
msgid "Represents the size of the [enum SamplePartitionType] enum."
@@ -44918,6 +47432,9 @@ msgid ""
"Parses [StaticBody] colliders as geometry. The collider should be in any of "
"the layers specified by [member geometry_collision_mask]."
msgstr ""
+"Interprète l'élément de collision [StaticBody] comme géométrie. Cet élément "
+"doit être dans l'un des calques spécifiés par [member "
+"geometry_collision_mask]."
#: doc/classes/NavigationMesh.xml
msgid ""
@@ -44935,18 +47452,24 @@ msgstr "Représente la taille de l’enum [enum ParsedGeometryType]."
msgid ""
"Scans the child nodes of [NavigationMeshInstance] recursively for geometry."
msgstr ""
+"Scanne les nœuds d'enfants de [NavigationMeshInstance] récursivement pour la "
+"géométrie."
#: doc/classes/NavigationMesh.xml
msgid ""
"Scans nodes in a group and their child nodes recursively for geometry. The "
"group is specified by [member geometry_source_group_name]."
msgstr ""
+"Scanne les nœuds dans un groupe et leurs nœuds enfants récursivement pour la "
+"géométrie. Le groupe est spécifié par [member geometry_source_group_name]."
#: doc/classes/NavigationMesh.xml
msgid ""
"Uses nodes in a group for geometry. The group is specified by [member "
"geometry_source_group_name]."
msgstr ""
+"Utilise des nœuds dans un groupe de géométrie. Le groupe est spécifié par "
+"[member geometry_source_group_name]."
#: doc/classes/NavigationMesh.xml
msgid "Represents the size of the [enum SourceGeometryMode] enum."
@@ -44955,6 +47478,7 @@ msgstr "Représente la taille de l'énumération [enum SourceGeometryMode]."
#: doc/classes/NavigationMeshGenerator.xml
msgid "Helper class for creating and clearing navigation meshes."
msgstr ""
+"Classe d'aide pour la création et la suppression des maillages de navigation."
#: doc/classes/NavigationMeshGenerator.xml
msgid ""
@@ -44997,6 +47521,52 @@ msgid ""
"inside, the baking will generate navigation mesh areas that are inside the "
"obstructing source geometry mesh."
msgstr ""
+"Cette classe est responsable de la création et du la suppression des "
+"maillages de navigation 3D utilisés comme [NavigationMesh] ressources à "
+"l'intérieur des [NavigationMeshInstance]. Le [NavigationMeshGenerator] est "
+"très limité voire n'a aucune utilisation pour 2D car le processus de "
+"navigation de pré-calcule de maillages s'attend à des types de nœuds 3D et "
+"la géométrie source en 3D.\n"
+"L'ensemble du pré-calcule de maillages de navigation est préférable dans un "
+"autre fil d'exécution puisque les étapes de voxelisation, de collision et "
+"d'optimisation de maillages impliquées sont des opérations, sont très "
+"couteuses en temps processeur.\n"
+"Le pré-calcule de maillage de navigation se produit en plusieurs étapes et "
+"le résultat dépend de la géométrie source 3D et des propriétés de la "
+"ressource [NavigationMesh]. Dans la première étape, à partir d'un nœud "
+"racine et selon les propriétés [NavigationMesh], tous les nœuds de géométrie "
+"de source 3D valides sont collectés à partir du [SceneTree]. Deuxièmement, "
+"tous les nœuds collectés sont interprétés pour obtenir les données de "
+"géométrie 3D pertinentes et un maillage 3D combiné est construit. En raison "
+"des différents types d'objets à interpréter, des [MeshInstance] normaux aux "
+"[CSGShape] ou divers [CollisionObject], certaines opérations de collecte de "
+"données de géométrie peuvent déclencher des synchronisations du "
+"[VisualServer] et du [PhysicsServer]. La synchronisation du serveur peut "
+"avoir un effet négatif sur le temps de pré-calcule car elle implique souvent "
+"le verrouillage de [Mutex] dans le fil d'exécution. De nombreux objets à "
+"interpréter et de nombreuses synchronisations des serveurs peuvent augmenter "
+"considérablement le temps de pré-calcule. D'un autre côté, seulement "
+"quelques objets, mais très grands et complexes, prendront du temps de "
+"préparation des serveurs ce qui peuvent bloquer le rendu suivant. De règle "
+"générale, la quantité totale d'objets à interpréter, leur taille et leur "
+"complexité individuelles devraient être équilibrées pour éviter les "
+"problèmes de fluidité ou des temps de pré-calcule très longs. Le maillage "
+"combiné est ensuite transmis à l'Object Recast Navigation pour tester la "
+"géométrie source pour le terrain à parcourir adapté aux propriétés des "
+"agents [NavigationMesh] en créant un monde de voxel autour de la zone de "
+"maillage.\n"
+"Le maillage de navigation finalisé est ensuite retourné et enregistré à "
+"l'intérieur du [NavigationMesh] pour être utilisé comme ressource à "
+"l'intérieur des nœuds [NavigationMeshInstance].\n"
+"[b]Note :[/b] L'utilisation de maillages ne définissen pas seulement les "
+"surfaces à parcourir mais peut aussi empêcher le pré-calcul de fonctionner. "
+"La navigation n'a pas de concept de ce qu'est une géométrie \"à "
+"l'intérieur\" quand on traite de la géométrie de source de maillage et c'est "
+"intentionnel. Selon les paramètres de pré-calcule actuels, dès que le "
+"maillage obstructif est assez grande pour s'adapter à une zone de maillage "
+"de navigation à l'intérieur, le pré-calcule générera des zones de maillage "
+"de navigation qui sont à l'intérieur du maillage de géométrie de source "
+"obstructif."
#: doc/classes/NavigationMeshGenerator.xml
msgid ""
@@ -45007,13 +47577,18 @@ msgid ""
"NavigationMesh.geometry_source_geometry_mode] properties on the "
"[NavigationMesh] resource."
msgstr ""
+"Pré-calcule les données de navigation du [code]nav_mesh[/code] donné en "
+"interprétant les nœuds enfants dans le [code]root_node[/code] spécifié ou un "
+"groupe spécifique de nœuds pour la géométrie de source potentielle. Le "
+"comportement d'interprétation peut être contrôlé avec les propriétés [member "
+"NavigationMesh.geometry_parsed_geometry_type] et [member NavigationMesh."
+"geometry_source_geometry_mode] de la ressource [NavigationMesh]."
#: doc/classes/NavigationMeshGenerator.xml
-#, fuzzy
msgid ""
"Removes all polygons and vertices from the provided [code]nav_mesh[/code] "
"resource."
-msgstr "Supprime l’animation avec la touche [code]name[/code]."
+msgstr ""
#: doc/classes/NavigationMeshInstance.xml
msgid "An instance of a [NavigationMesh]."
@@ -45033,11 +47608,29 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
msgstr ""
+"Une instance de [NavigationMesh]. Il signale au nœud [Navigation] ce qui "
+"peut être navigué et ce qui ne peut pas, basé sur la ressource "
+"[NavigationMesh].\n"
+"Par défaut ce nœud s'enregistrera à la carte de navigation du [World] par "
+"défaut. Si ce nœud est un enfant d'un nœud [Navigation], il s'inscrira à la "
+"carte de navigation du nœud de navigation.\n"
+"Deux régions peuvent être reliées l'une à l'autre si elles partagent un même "
+"bord. Vous pouvez définir la distance minimale entre deux sommets "
+"nécessaires pour connecter deux bords en utilisant [method NavigationServer."
+"map_set_edge_connection_margin]\n"
+"[b]Note :[/b] Le chevauchement de deux régions n'est pas suffisant pour "
+"relier deux régions. Ils doivent partager un même bord.\n"
+"Le coût d'entrée dans cette région d'une autre région peut être contrôlé "
+"avec la valeur [member enter_cost].\n"
+"[b]Note :[/b] Cette valeur n'est pas ajoutée au coût du chemin lorsque la "
+"position de départ est déjà dans cette région.\n"
+"Le coût des distances de voyage dans cette région peut être contrôlé avec le "
+"multiplicateur [member travel_cost]."
#: doc/classes/NavigationMeshInstance.xml
msgid ""
@@ -45051,6 +47644,18 @@ msgid ""
"operating systems that cannot use threads (such as HTML5 with threads "
"disabled)."
msgstr ""
+"Pré-calcule le [NavigationMesh]. Si [code]on_thread[/code] est défini à "
+"[code]true[/code] (par défaut), le pré-calcul est fait sur un fil "
+"d'exécution séparé. Le pré-calcul sur un fil d'exécution séparé est utile "
+"parce que la navigation est une opération relativement coûteuse. Lorsqu'il "
+"est terminé, il définit automatiquement ce nouveau [NavigationMesh]. "
+"Veuillez noter que le pré-calcul sur le fil d'exécution séparé peut être "
+"très lent si la géométrie est composée de plein de maillages puisque l'accès "
+"asynchrone à chaque maillage nécessite une lourde synchronisation. De plus, "
+"veuillez noter que le pré-calculs sur un fil d'exécution séparé est "
+"automatiquement désactivée sur les systèmes d'exploitation qui ne peuvent "
+"pas utiliser des fils d'exécution (comme HTML5 si cette fonction est "
+"désactivée)."
#: doc/classes/NavigationMeshInstance.xml
msgid ""
@@ -45059,6 +47664,10 @@ msgid ""
"identify the [NavigationMeshInstance] closest to a point on the merged "
"navigation map."
msgstr ""
+"Retourne le [RID] de cette région sur [NavigationServer]. Combiné avec ["
+"method NavigationServer.map_get_closest_point_owner], peut être utilisé pour "
+"identifier le [NavigationMeshInstance] le plus proche d'un point d'une carte "
+"de navigation fusionnée."
#: doc/classes/NavigationMeshInstance.xml
msgid "Determines if the [NavigationMeshInstance] is enabled or disabled."
@@ -45091,11 +47700,13 @@ msgid ""
"are multiplied with [code]travel_cost[/code] for determining the shortest "
"path."
msgstr ""
+"Lorsque le cheminement se déplace à l'intérieur de cette région, les "
+"distances parcourues sont multipliées par [code]travel_cost[/code] pour "
+"déterminer le chemin le plus court."
#: doc/classes/NavigationMeshInstance.xml
-#, fuzzy
msgid "Notifies when the navigation mesh bake operation is completed."
-msgstr "Avertit quand une animation commence à jouer."
+msgstr ""
#: doc/classes/NavigationMeshInstance.xml
msgid "Notifies when the [NavigationMesh] has changed."
@@ -45114,12 +47725,22 @@ msgid ""
"[b]Note:[/b] Obstacles are intended as a last resort option for constantly "
"moving objects that cannot be (re)baked to a navigation mesh efficiently."
msgstr ""
+"Obstacle 3D utilisé dans la navigation pour éviter les collisions. "
+"L'obstacle a besoin de données de navigation pour fonctionner correctement. "
+"Cela peut être fait avec l'obstacle comme enfant d'un nœud [Navigation], ou "
+"en utilisant [method set_navigation]. [NavigationObstacle] est sûr lors des "
+"trames physiques.\n"
+"[b]Note :[/b] Les obstacles sont conçus comme dernière option pour les "
+"objets constamment mobiles qui ne peuvent pas être pré-calculés efficacement "
+"dans un maillage de navigation."
#: doc/classes/NavigationObstacle.xml
msgid ""
"Returns the [Navigation] node that the obstacle is using for its navigation "
"system."
msgstr ""
+"Retourne le nœud [Navigation] que l'obstacle utilise pour son système de "
+"navigation."
#: doc/classes/NavigationObstacle.xml
msgid "Returns the [RID] of this obstacle on the [NavigationServer]."
@@ -45130,18 +47751,24 @@ msgid ""
"Sets the [Navigation] node used by the obstacle. Useful when you don't want "
"to make the obstacle a child of a [Navigation] node."
msgstr ""
+"Définit le nœud [Navigation] utilisé par l'obstacle. Utile lorsque vous ne "
+"voulez pas faire l'obstacle un enfant d'un nœud [Navigation]."
#: doc/classes/NavigationObstacle.xml doc/classes/NavigationObstacle2D.xml
msgid ""
"Enables radius estimation algorithm which uses parent's collision shapes to "
"determine the obstacle radius."
msgstr ""
+"Active l'algorithme d'estimation de rayon qui utilise les formes de "
+"collision des parents pour déterminer le rayon des obstacles."
#: doc/classes/NavigationObstacle.xml doc/classes/NavigationObstacle2D.xml
msgid ""
"The radius of the agent. Used only if [member estimate_radius] is set to "
"[code]false[/code]."
msgstr ""
+"Le rayon de l'agent. Utilisé uniquement si [member estimate_radius] est "
+"[code]false[/code]."
#: doc/classes/NavigationObstacle2D.xml
msgid "2D obstacle used in navigation for collision avoidance."
@@ -45156,12 +47783,22 @@ msgid ""
"[b]Note:[/b] Obstacles are intended as a last resort option for constantly "
"moving objects that cannot be (re)baked to a navigation mesh efficiently."
msgstr ""
+"L'obstacle 2D utilisé dans la navigation pour éviter les collisions. "
+"L'obstacle a besoin de données de navigation pour fonctionner correctement. "
+"Cela peut être fait avec l'obstacle comme enfant d'un nœud [Navigation2D], "
+"ou en utilisant [method set_navigation]. [NavigationObstacle2D] est sûr lors "
+"des trames physiques.\n"
+"[b]Note :[/b] Les obstacles sont conçus comme dernière option pour les "
+"objets constamment mobiles qui ne peuvent pas être pré-calculés efficacement "
+"dans un maillage de navigation."
#: doc/classes/NavigationObstacle2D.xml
msgid ""
"Returns the [Navigation2D] node that the obstacle is using for its "
"navigation system."
msgstr ""
+"Retourne le nœud [Navigation2D] que l'obstacle utilise pour son système de "
+"navigation."
#: doc/classes/NavigationObstacle2D.xml
msgid "Returns the [RID] of this obstacle on the [Navigation2DServer]."
@@ -45172,12 +47809,16 @@ msgid ""
"Sets the [Navigation2D] node used by the obstacle. Useful when you don't "
"want to make the obstacle a child of a [Navigation2D] node."
msgstr ""
+"Définit le nœud [Navigation2D] utilisé par l'obstacle. Utile lorsque vous ne "
+"voulez pas faire l'obstacle un enfant d'un nœud [Navigation2D]."
#: doc/classes/NavigationPolygon.xml
msgid ""
"A node that has methods to draw outlines or use indices of vertices to "
"create navigation polygons."
msgstr ""
+"Un nœud qui a des méthodes pour dessiner des contours ou utiliser des "
+"indices de sommets pour créer des polygones de navigation."
#: doc/classes/NavigationPolygon.xml
msgid ""
@@ -45203,6 +47844,27 @@ msgid ""
"$NavigationPolygonInstance.navpoly = polygon\n"
"[/codeblock]"
msgstr ""
+"Il y a deux façons de créer des polygones. Soit en utilisant la méthode ["
+"method add_outline], soit en utilisant la méthode [method add_polygon].\n"
+"Avec [method add_outline] :\n"
+"[codeblock]\n"
+"var polygon = NavigationPolygon.new()\n"
+"var outline = PoolVector2Array([Vector2(0, 0), Vector2(0, 50), Vector2(50, "
+"50), Vector2(50, 0)])\n"
+"polygon.add_outline(outline)\n"
+"polygon.make_polygons_from_outlines()\n"
+"$NavigationPolygonInstance.navpoly = polygon\n"
+"[/codeblock]\n"
+"Avec [method add_polygon] et les indices du tableau des sommets :\n"
+"[codeblock]\n"
+"var polygon = NavigationPolygon.new()\n"
+"var vertices = PoolVector2Array([Vector2(0, 0), Vector2(0, 50), Vector2(50, "
+"50), Vector2(50, 0)])\n"
+"polygon.set_vertices(vertices)\n"
+"var indices = PoolIntArray([0, 1, 2, 3])\n"
+"polygon.add_polygon(indices)\n"
+"$NavigationPolygonInstance.navpoly = polygon\n"
+"[/codeblock]"
#: doc/classes/NavigationPolygon.xml
msgid ""
@@ -45211,6 +47873,10 @@ msgid ""
"make_polygons_from_outlines] in order for this array to be converted to "
"polygons that the engine will use."
msgstr ""
+"Ajoute un [PoolVector2Array] qui contient les sommets d'un contour au "
+"tableau interne qui contient tous les contours. Vous devez appeler [method "
+"make_polygons_from_outlines] afin que ce tableau soit converti en polygones "
+"que le moteur pourra utiliser."
#: doc/classes/NavigationPolygon.xml
msgid ""
@@ -45219,18 +47885,26 @@ msgid ""
"to call [method make_polygons_from_outlines] in order for this array to be "
"converted to polygons that the engine will use."
msgstr ""
+"Ajoute un [PoolVector2Array] qui contient les sommets d'un contour au "
+"tableau interne qui contient tous les contours à une position fixe. Vous "
+"devez appeler [method make_polygons_from_outlines] afin que ce tableau soit "
+"converti en polygones que le pourra utiliser."
#: doc/classes/NavigationPolygon.xml
msgid ""
"Clears the array of the outlines, but it doesn't clear the vertices and the "
"polygons that were created by them."
msgstr ""
+"Efface le tableau des contours, mais ça n'efface pas les sommets et les "
+"polygones qui ont été créés par eux."
#: doc/classes/NavigationPolygon.xml
msgid ""
"Clears the array of polygons, but it doesn't clear the array of outlines and "
"vertices."
msgstr ""
+"Efface le tableau des polygones, mais ça n'effacera pas le tableau des "
+"contours et des sommets."
#: doc/classes/NavigationPolygon.xml
msgid ""
@@ -45239,17 +47913,25 @@ msgid ""
"NavigationServer.region_set_navmesh] API directly (as 2D uses the 3D server "
"behind the scene)."
msgstr ""
+"Retourne le [NavigationMesh] résultant de ce polygone de navigation. Ce "
+"navmesh peut être utilisé pour mettre à jour le navmesh d'une région avec "
+"l'API [method NavigationServer.region_set_navmesh] directement (comme la 2D "
+"utilise le serveur 3D en interne)."
#: doc/classes/NavigationPolygon.xml
msgid ""
"Returns a [PoolVector2Array] containing the vertices of an outline that was "
"created in the editor or by script."
msgstr ""
+"Retourne un [PoolVector2Array] contenant les sommets d'un contour qui a été "
+"créé dans l'éditeur ou par un script."
#: doc/classes/NavigationPolygon.xml
msgid ""
"Returns the number of outlines that were created in the editor or by script."
msgstr ""
+"Retourne le nombre de contours qui ont été créés dans l'éditeur ou par un "
+"script."
#: doc/classes/NavigationPolygon.xml
msgid "Returns the count of all polygons."
@@ -45260,27 +47942,33 @@ msgid ""
"Returns a [PoolVector2Array] containing all the vertices being used to "
"create the polygons."
msgstr ""
+"Retourne un [PoolVector2Array] contenant tous les sommets utilisés pour "
+"créer les polygones."
#: doc/classes/NavigationPolygon.xml
msgid "Creates polygons from the outlines added in the editor or by script."
msgstr ""
+"Crée des polygones des contours ajoutés dans l'éditeur ou par un script."
#: doc/classes/NavigationPolygon.xml
msgid ""
"Removes an outline created in the editor or by script. You have to call "
"[method make_polygons_from_outlines] for the polygons to update."
msgstr ""
+"Enlève un aperçu créé dans l'éditeur ou par un script. Vous devez appeler ["
+"method make_polygons_from_outlines] pour mettre à jour les polygones."
#: doc/classes/NavigationPolygon.xml
msgid ""
"Changes an outline created in the editor or by script. You have to call "
"[method make_polygons_from_outlines] for the polygons to update."
msgstr ""
+"Change un aperçu créé dans l'éditeur ou par un script. Vous devez appeler ["
+"method make_polygons_from_outlines] pour mettre à jour les polygones."
#: doc/classes/NavigationPolygonInstance.xml
-#, fuzzy
msgid "A region of the 2D navigation map."
-msgstr "Prépare le maillage de navigation."
+msgstr ""
#: doc/classes/NavigationPolygonInstance.xml
msgid ""
@@ -45296,11 +47984,29 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
msgstr ""
+"Une région de la carte de navigation. Il indique au [Navigation2DServer] ce "
+"qui peut être navigué et ce qui ne peut pas l'être, en fonction de sa "
+"ressource [NavigationPolygon].\n"
+"Par défaut ce nœud s'enregistrera à la carte de navigation du [World2D] par "
+"défaut. Si ce nœud est un enfant d'un nœud [Navigation2D], il s'inscrirea à "
+"la carte de navigation du nœud de navigation.\n"
+"Deux régions peuvent être reliées l'une à l'autre si elles partagent un bord "
+"similaire. Vous pouvez définir la distance minimale entre deux sommets "
+"nécessaires pour connecter deux bords en utilisant [method Navigation2DServer"
+".map_set_edge_connection_margin]\n"
+"[b]Note :[/b] Embiquer deux régions ne suffit pas pour relier ces deux "
+"régions. Elles doivent partager un bord similaire.\n"
+"Le coût de cheminement de cette région vers une autre peut être contrôlé "
+"avec la valeur [member enter_cost].\n"
+"[b]Note :[/b] Cette valeur n'est pas ajoutée au coût du chemin lorsque la "
+"position de départ est déjà dans cette région.\n"
+"Le coût de parcours des distances de cheminement à l'intérieur de cette "
+"région peut être contrôlé avec le multiplicateur [member travel_cost]."
#: doc/classes/NavigationPolygonInstance.xml
msgid ""
@@ -45309,11 +48015,14 @@ msgid ""
"identify the [NavigationPolygonInstance] closest to a point on the merged "
"navigation map."
msgstr ""
+"Retourne le [RID] de cette région sur le [Navigation2DServer]. Combiné avec ["
+"method Navigation2DServer.map_get_closest_point_propriétaire] peut permettre "
+"d'identifier le [NavigationPolygonInstance] le plus proche d'un point sur la "
+"carte de navigation fusionnée."
#: doc/classes/NavigationPolygonInstance.xml
-#, fuzzy
msgid "Determines if the [NavigationPolygonInstance] is enabled or disabled."
-msgstr "Détermine si le [NavigationMeshInstance] est actif ou non."
+msgstr "Détermine si la [NavigationPolygonInstance] est active ou non."
#: doc/classes/NavigationPolygonInstance.xml
msgid ""
@@ -45324,14 +48033,12 @@ msgid ""
msgstr ""
#: doc/classes/NavigationPolygonInstance.xml
-#, fuzzy
msgid "The [NavigationPolygon] resource to use."
-msgstr "La ressource [NavigationMesh] à utiliser."
+msgstr "La ressource [NavigationPolygon] à utiliser."
#: doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Server interface for low-level 3D navigation access."
-msgstr "Interface de serveur pour l'accès audio de bas niveau."
+msgstr ""
#: doc/classes/NavigationServer.xml
#, fuzzy
@@ -45381,15 +48088,13 @@ msgstr ""
"sans soucis."
#: doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Returns the map cell height."
-msgstr "Retourne la taille du tableau."
+msgstr ""
#: doc/classes/NavigationServer.xml
-#, fuzzy
msgid ""
"Returns the normal for the point returned by [method map_get_closest_point]."
-msgstr "Renvoie l'inverse de la racine carrée du paramètre."
+msgstr ""
#: doc/classes/NavigationServer.xml
msgid ""
@@ -45403,15 +48108,16 @@ msgid ""
"Returns the edge connection margin of the map. This distance is the minimum "
"vertex distance needed to connect two edges from different regions."
msgstr ""
+"Retourne la marge de raccordement du bord de la carte. Cette distance est la "
+"distance minimale nécessaire pour relier deux bords de différentes régions."
#: doc/classes/NavigationServer.xml
msgid "Returns the map's up direction."
msgstr "Retourne la direction haut de la carte."
#: doc/classes/NavigationServer.xml
-#, fuzzy
msgid "Set the map cell height used to weld the navigation mesh polygons."
-msgstr "Définit le polygone de navigation de la tuile."
+msgstr ""
#: doc/classes/NavigationServer.xml
msgid "Sets the map up direction."
@@ -45424,6 +48130,10 @@ msgid ""
"called in the main thread.\n"
"[b]Note:[/b] This function is not thread safe."
msgstr ""
+"Traite les agents d'évitement de collision.\n"
+"Le résultat de ce processus est nécessaire par le serveur de physique, de "
+"sorte que cela doit être appelé dans le fil d'exécution principal.\n"
+"[b]Note :[/b] Cette fonction n'est pas sûre entre plusieurs fils d'exécution."
#: doc/classes/NavigationServer.xml
msgid "Bakes the navigation mesh."
@@ -45434,11 +48144,62 @@ msgid ""
"Set the region's navigation layers. This allows selecting regions from a "
"path request (when using [method NavigationServer.map_get_path])."
msgstr ""
+"Définir les calques de navigation de la région. Cela permet de sélectionner "
+"les régions à partir d'une requête de chemin (en utilisant [method "
+"NavigationServer.map_get_path])."
#: doc/classes/NavigationServer.xml
msgid "Control activation of this server."
msgstr "Contrôle l'activation de ce serveur."
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+"Retourne l'état actuel de la connexion. Voir [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -45459,6 +48220,18 @@ msgid ""
"the server port in UDP. You can use the [UPNP] class to try to forward the "
"server port automatically when starting the server."
msgstr ""
+"Une implémentation de PacketPeer qui devrait être passée au [member "
+"SceneTree.network_peer] après avoir été initialisé en tant que client ou "
+"serveur. Les événements peuvent ensuite être gérés en se connectant aux "
+"signaux de [SceneTree].\n"
+"L'intêret de ENet est de fournir un calque de communication à travers le "
+"réseau relativement léger, simple et robuste par dessus UDP (User Datagram "
+"Protocol).\n"
+"[b]Note :[/b] ENet utilise seulement UDP, et non TCP. Lors du branchement du "
+"port serveur pour rendre votre serveur accessible sur internet, vous n'avez "
+"besoin que d'envoyer le port serveur en UDP. Vous pouvez utiliser la classe "
+"[UPNP] pour essayer d'envoyer automatiquement le port serveur dès le "
+"démarrage du serveur."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45467,6 +48240,10 @@ msgid ""
"disconnecting them. If this is a client it simply closes the connection to "
"the server."
msgstr ""
+"Ferme la connexion. Ignoré si aucune connexion n'est actuellement établie. "
+"Si c'est un serveur, il essaie de notifier tous les clients avant de les "
+"déconnecter de force. Si c'est un client, il ferme simplement la connexion "
+"au serveur."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45489,6 +48266,25 @@ msgid ""
"code] is specified, the client will also listen to the given port; this is "
"useful for some NAT traversal techniques."
msgstr ""
+"Créer un client qui se connecte au serveur à [code]address[/code] donnée via "
+"le [code]port[/code]. L'adresse donnée doit être soit un nom de domaine "
+"entièrement qualifié (ex.: [code]\"www.example.com\"[/code]) ou une adresse "
+"IP en format IPv4 ou IPv6 (par exemple [code]\"192.168.1.1\"[/code]). Le "
+"[code]port[/code] est le port que le serveur écoute. Les paramètres "
+"[code]in_bandwidth[/code] et [code]out_bandwidth[/code] peuvent être "
+"utilisés pour limiter la bande passante entrante et sortante, en octets par "
+"seconde. Le défaut de 0 signifie que la bande passante ne sera pas limitée. "
+"Notez que ENet ignorera stratégiquement des paquets d'une connexion entre "
+"pairs pour s'assurer que la bande passante par les pairs n'est pas dépassée. "
+"Les paramètres de bande passante déterminent également la taille de la "
+"fenêtre d'une connexion qui limite la quantité de paquets fiables qui "
+"peuvent être envoyés à tout moment donné. Retourne [constant OK] si un "
+"client a été créé, [constant ERR_ALREADY_IN_USE] si ce "
+"NetworkedMultiplayerENet a déjà une connexion ouverte (dans quel cas vous "
+"devez appeler [method close_connection] d'abord) ou [constant "
+"ERR_CANT_CREATE] si le client ne peut pas être créé. Si "
+"[code]client_port[/code] est spécifié, le client écoutera également le port "
+"donné ; ceci est utile pour certaines techniques NAT transversale."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45507,12 +48303,29 @@ msgid ""
"case you need to call [method close_connection] first) or [constant "
"ERR_CANT_CREATE] if the server could not be created."
msgstr ""
+"Créer un serveur qui écoute les connexions via [code]port[/code]. Le port "
+"doit être un port disponible et inutilisé entre 0 et 65535. Notez que les "
+"ports inférieurs à 1024 sont réservés et peuvent nécessiter des "
+"autorisations élevées en fonction de la plateforme. Pour modifier "
+"l'interface que le serveur écoute, utilisez [method set_bind_ip]. L'IP par "
+"défaut est le joker [code]\"*\"[/code], qui écoute toutes les interfaces "
+"disponibles. [code]max_clients[/code] est le nombre maximum de clients "
+"autorisés en même temps, tout nombre jusqu'à 4095 peut être utilisé, même si "
+"le nombre possible de clients simultanés peut être beaucoup plus faible et "
+"dépend de l'application. Pour plus de détails sur les paramètres de bande "
+"passante, voir [method create_client]. Retourne [constant OK] si un serveur "
+"a été créé, [constant ERR_ALREADY_IN_USE] si ce NetworkedMultiplayerENet a "
+"déjà une connexion ouverte (dans quel cas vous devez appeler [method "
+"close_connection] d'abord) ou [constant ERR_CANT_CREATE] si le serveur ne "
+"peut pas être créé."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"Disconnect the given peer. If \"now\" is set to [code]true[/code], the "
"connection will be closed immediately without flushing queued messages."
msgstr ""
+"Déconnecte le pair donné. Si \"maintenant\" est [code]true[/code], la "
+"connexion sera fermée immédiatement sans envoyer les messages en attente."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45527,6 +48340,8 @@ msgid ""
"Returns the channel of the next packet that will be retrieved via [method "
"PacketPeer.get_packet]."
msgstr ""
+"Retourne le canal du prochain paquet qui sera récupéré via [method PacketPeer"
+".get_packet]."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
#: modules/websocket/doc_classes/WebSocketServer.xml
@@ -45545,6 +48360,10 @@ msgid ""
"needs to be in IPv4 or IPv6 address format, for example: "
"[code]\"192.168.1.1\"[/code]."
msgstr ""
+"L'adresse IP utilisée lors de la création d'un serveur. Ceci est défini le "
+"joker [code]\"*\"[/code] par défaut, qui se connecte à toutes les interfaces "
+"disponibles. L'adresse donnée doit être au format IPv4 ou IPv6, par "
+"exemple : [code]\"192.168.1.1\"[/code]."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45552,6 +48371,9 @@ msgid ""
"code]. For servers, you must also setup the [CryptoKey] via [method "
"set_dtls_key]."
msgstr ""
+"Configure le [X509Certificate] à utiliser lorsque [member use_dtls] est "
+"[code]true[/code]. Pour les serveurs, vous devez également configurer le "
+"[CryptoKey] via [method set_dtls_key]."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45559,6 +48381,9 @@ msgid ""
"code]. Remember to also call [method set_dtls_certificate] to setup your "
"[X509Certificate]."
msgstr ""
+"Configure la [CryptoKey] à utiliser lorsque [member use_dtls] est "
+"[code]true[/code]. N'oubliez pas d'appeler [method set_dtls_certificate] "
+"pour configurer votre [X509Certificate]."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45573,6 +48398,17 @@ msgid ""
"other hand, defines a fixed timeout for which any packet must be "
"acknowledged or the peer will be dropped."
msgstr ""
+"Définit les paramètres de limite de temps pour un pair. Les paramètres de "
+"limite de temps contrôlent comment et quand un pair estimera que le traffic "
+"n'est pas assez fiable. Les valeurs de limite de temps sont exprimées en "
+"millisecondes.\n"
+"La [code]timeout_limit[/code] est un facteur qui, multiplié par une valeur "
+"basée sur le temps d'envoi moyen, déterminera la limite de temps pour un "
+"paquet fiable. Lorsque cette limite est atteinte, la limite de temps sera "
+"doublée, et le pair sera déconnecté si cette limite atteint "
+"[code]timeout_min[/code]. Le paramètre [code]timeout_max[/code], d'autre "
+"part, définit une limite de temps fixe pour lequel tout paquet doit estimé "
+"comme fiable, ou alors le pair sera supprimé."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45581,6 +48417,11 @@ msgid ""
"NetworkedMultiplayerPeer.TRANSFER_MODE_UNRELIABLE_ORDERED]). This is the "
"only way to use ordering with the RPC system."
msgstr ""
+"Force le tri des paquets lors de l'utilisation de [constant "
+"NetworkedMultiplayerPeer.TRANSFER_MODE_UNRELIABLE] (ce qui se comporte de la "
+"même manière [constant NetworkedMultiplayerPeer."
+"TRANSFER_MODE_UNRELIABLE_ORDERED]). C'est le seul moyen d'utiliser le tri "
+"avec un système RPC."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45591,6 +48432,12 @@ msgid ""
"status of a packet in one channel won't stall the delivery of other packets "
"in another channel."
msgstr ""
+"Le nombre de canaux à utiliser par ENet. Les canaux sont utilisés pour "
+"séparer différents types de données. En mode fiable ou ordonné, par exemple, "
+"l'ordre d'envoi des paquets est assuré sur une base par canal. Ceci est fait "
+"pour lutter contre la latence et réduit les restrictions d'ordre sur les "
+"paquets. L'état d'envoi d'un paquet d'un canal a été décalé dans l'envoi "
+"d'autres paquets dans un autre canal."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45607,6 +48454,21 @@ msgid ""
"COMPRESS_NONE]. Nonetheless, mixing engine versions between clients and "
"server is not recommended and not officially supported."
msgstr ""
+"La méthode de compression utilisée pour les paquets réseau. Ceux-ci ont "
+"différents compromis de vitesse de compression par rapport à la bande "
+"passante, vous pouvez avoir besoin quelle méthode fonctionne le mieux pour "
+"votre cas d'utilisation si vous utilisez la compression pour tout.\n"
+"[b]Note :[/b] La conception réseau de la plupart des jeux nécessite l'envoi "
+"de nombreux petits paquets fréquemment (moins de 4 KB chacun). Dans le "
+"doute, il est recommandé de garder l'algorithme de compression par défaut "
+"car il fonctionne le mieux avec ces petits paquets.\n"
+"[b]Note :[/b] [member compression_mode] doit être défini à la même valeur "
+"sur le serveur et sur tous ses clients. Les clients ne se connecteront pas "
+"si le [member compression_mode] d'un client diffère de celui du serveur. "
+"Avant Godot 3.4, la valeur par défaut de [member compression_mode] était "
+"[constant COMPRESS_NONE]. Néanmoins, il n'est pas recommandé, ni "
+"officiellement supporté, d'utiliser différentes versions du moteur entre les "
+"clients et le serveur."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45615,9 +48477,12 @@ msgid ""
"When set to an empty string, the [code]address[/code] parameter passed to "
"[method create_client] is used instead."
msgstr ""
+"Le nom d'hôte utilisé pour la vérification DTLS, à comparer à la valeur « CN "
+"» du certificat fourni par le serveur.\n"
+"Si la chaîne est vide, le paramètre [code]address[/code] passé à [method "
+"create_client] est utilisé à la place."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
-#, fuzzy
msgid ""
"Enable or disable certificate verification when [member use_dtls] is "
"[code]true[/code]."
@@ -45632,6 +48497,11 @@ msgid ""
"is [code]false[/code], clients won't be automatically notified of other "
"peers and won't be able to send them packets through the server."
msgstr ""
+"Activer ou désactiver la fonction serveur qui notifie les clients de la "
+"connexion/déconnection des autres pairs enregistrés, et relaye les messages "
+"entre eux. Lorsque cette option est [code]false[/code], les clients ont "
+"obtenu la notification automatique d'autres pairs et ont obtenu la "
+"possibilité de les envoyer par le serveur."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45643,6 +48513,14 @@ msgid ""
"that channel for sending data. See [member channel_count] for more "
"information about ENet channels."
msgstr ""
+"Définit le canal par défaut à utiliser pour transférer les données. Par "
+"défaut, cette valeur est [code]-1[/code] ce qui signifie que ENet "
+"n'utilisera que 2 canaux : un pour les paquets fiables, et un pour les "
+"paquets non fiables. Le canal [code]0[/code] est réservé et ne peut pas être "
+"utilisé. Définit cette propriété à n'importe quelle valeur entre [code]0[/"
+"code] et [member channel_count] (exclus) forcera ENet à utiliser ce canal "
+"pour envoyer les données. Voir [member channel_count] pour plus "
+"d'informations sur les canaux ENet."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45656,6 +48534,16 @@ msgid ""
"dtls_verify] option, and configure the certificate accordingly via [method "
"set_dtls_certificate]."
msgstr ""
+"Quand activé, le client ou le serveur créé par ce pair utilisera "
+"[PacketPeerDTLS] au lieu des sockets UDP bruts pour communiquer avec le pair "
+"distant. Cela permettra de chiffrer la communication avec DTLS avec une "
+"utilisation plus importante des ressources mais aussi peut-être de la taille "
+"des paquets.\n"
+"[b]Note :[/b] Lors de la création d'un serveur DTLS, assurez-vous de "
+"configurer à la fois la clé et le certificat avec [method set_dtls_key] et "
+"[method set_dtls_certificate]. Pour les clients DTLS, regardez l'option "
+"[member dtls_verify] et configurez le certificat en conséquence avec [method "
+"set_dtls_certificate]."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45663,12 +48551,17 @@ msgid ""
"requiring the fewest CPU resources. This option may also be used to make "
"network debugging using tools like Wireshark easier."
msgstr ""
+"Aucune compression. Cela utilise le plus de bande passante, mais moins de "
+"ressource du CPU. Cette option peut également être utilisée pour faciliter "
+"le débogage du réseau en utilisant des outils comme Wireshark."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"ENet's built-in range encoding. Works well on small packets, but is not the "
"most efficient algorithm on packets larger than 4 KB."
msgstr ""
+"L'encodage intégré d'ENet. Fonctionne bien sur les petits paquets, mais "
+"n'est pas l'algorithme le plus efficace pour les paquets de plus de 4 KB."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45676,6 +48569,9 @@ msgid ""
"resources compared to [constant COMPRESS_ZLIB], at the expense of using more "
"bandwidth."
msgstr ""
+"L'algorithme de compression [url=http://fastlz.org/]FastLZ[/url]. Cette "
+"option utilise moins de ressources CPU par rapport à [constant "
+"COMPRESS_ZLIB] mais utilise plus de bande passante."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
@@ -45685,6 +48581,11 @@ msgid ""
"packets smaller than 4 KB. Therefore, it's recommended to use other "
"compression algorithms in most cases."
msgstr ""
+"L'algorithme de compression [url=https://www.zlib.net/]Zlib[/url]. Cette "
+"option utilise moins de bande passante par rapport à [constant "
+"COMPRESS_FASTLZ] mais utilise plus le CPU. Notez que cet algorithme n'est "
+"pas très efficace pour les paquets de moins de 4 KB. Il est donc souvent "
+"recommandé d'utiliser d'autres algorithmes de compression."
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid "[url=https://facebook.github.io/zstd/]Zstandard[/url] compression."
@@ -45704,6 +48605,11 @@ msgid ""
"detail and isn't meant to be used by non-Godot servers. It may change "
"without notice."
msgstr ""
+"Gère la connexion aux pairs du réseau. Attribue des identifiants uniques à "
+"chaque client connecté au serveur. Voir aussi [MultiplayerAPI].\n"
+"[b]Note :[/b] Le protocole de l'API multijoueur de haut niveau dépend de son "
+"implémentation et n'est pas destiné à être utilisé par des serveurs en "
+"dehors de Godot. Ce protocole peut changer dans une future version."
#: doc/classes/NetworkedMultiplayerPeer.xml
msgid "High-level multiplayer"
@@ -45711,7 +48617,7 @@ msgstr "API multijoueur de haut niveau"
#: doc/classes/NetworkedMultiplayerPeer.xml
msgid "WebRTC Signaling Demo"
-msgstr ""
+msgstr "Démo des signaux WebRTC"
#: doc/classes/NetworkedMultiplayerPeer.xml
msgid ""
@@ -45743,6 +48649,13 @@ msgid ""
"peer ID to send to all peers except that one. By default, the target peer is "
"[constant TARGET_PEER_BROADCAST]."
msgstr ""
+"Définit le pair auquel les paquets seront envoyés.\n"
+"L'identifiant [code]id[/code] peut être : [constant TARGET_PEER_BROADCAST] "
+"pour envoyer à tous les pairs connectés, [constant TARGET_PEER_SERVER] pour "
+"envoyer au pair agissant en tant que serveur, un identifiant de pairs valide "
+"pour envoyer à ce pair spécifique, ou un identifiant négatif pour envoyer à "
+"tous les pairs sauf celui-ci. Par défaut, le pair cible est [constant "
+"TARGET_PEER_BROADCAST]."
#: doc/classes/NetworkedMultiplayerPeer.xml
msgid ""
@@ -45757,6 +48670,8 @@ msgid ""
"The manner in which to send packets to the [code]target_peer[/code]. See "
"[enum TransferMode]."
msgstr ""
+"La manière d'envoyer des paquets au [code]target_peer[/code]. Voir [enum "
+"TransferMode]."
#: doc/classes/NetworkedMultiplayerPeer.xml
msgid "Emitted when a connection attempt fails."
@@ -45785,6 +48700,11 @@ msgid ""
"TRANSFER_MODE_UNRELIABLE_ORDERED]. Use for non-critical data, and always "
"consider whether the order matters."
msgstr ""
+"Les paquets ne sont pas reconnus, aucune tentative de ré-envoi n'est faite "
+"pour les paquets perdus. Les paquets peuvent arriver dans n'importe quelle "
+"commande. Peut être plus rapide que [constant "
+"TRANSFER_MODE_UNRELIABLE_ORDERED]. À utiliser pour des données non "
+"critiques, et toujours à considérer si l'ordre compte."
#: doc/classes/NetworkedMultiplayerPeer.xml
msgid ""
@@ -45794,6 +48714,12 @@ msgid ""
"would be outdated if received late due to resend attempt(s) anyway, for "
"example movement and positional data."
msgstr ""
+"Les paquets ne sont pas reconnus, aucune tentative de ré-envoi n'est faite "
+"pour les paquets perdus. Les paquets sont reçus dans l'ordre où ils ont été "
+"envoyés. Peut être plus rapide que [constant TRANSFER_MODE_RELIABLE]. À "
+"utiliser pour les données non critiques ou qui seraient périmées si elles "
+"étaient reçues tardivement à cause du ré-envoi, par exemple pour les données "
+"de mouvement et de positionnement."
#: doc/classes/NetworkedMultiplayerPeer.xml
msgid ""
@@ -45804,6 +48730,14 @@ msgid ""
"order, for example an ability being triggered or a chat message. Consider "
"carefully if the information really is critical, and use sparingly."
msgstr ""
+"Les paquets doivent être reçus et les tentatives de ré-envoi doivent être "
+"faites jusqu'à ce que les paquets soient reconnus. Les paquets doivent être "
+"reçus dans l'ordre où ils ont été envoyés. C'est le mode de transfert le "
+"plus fiable, mais potentiellement le plus lent en cause de la surcharge. À "
+"utiliser pour les données critiques qui doivent être transmises et arriver "
+"en ordre, par exemple un élément activé ou un message de discussion. À "
+"considérez soigneusement si l'information est vraiment critique, et à "
+"utiliser avec parcimonie."
#: doc/classes/NetworkedMultiplayerPeer.xml
msgid "The ongoing connection disconnected."
@@ -45845,30 +48779,40 @@ msgid ""
"Returns the size of the margin identified by the given [enum Margin] "
"constant."
msgstr ""
+"Retourne la taille de la marge identifiée par la constante [enum Margin] "
+"donnée."
#: doc/classes/NinePatchRect.xml
msgid ""
"Sets the size of the margin identified by the given [enum Margin] constant "
"to [code]value[/code] in pixels."
msgstr ""
+"Définit la taille de la marge identifiée par la constante [enum Margin] "
+"donnée à [code]value[/code] en pixels."
#: doc/classes/NinePatchRect.xml
msgid ""
"The stretch mode to use for horizontal stretching/tiling. See [enum "
"NinePatchRect.AxisStretchMode] for possible values."
msgstr ""
+"Le mode d'étirement à utiliser pour l'étirement horizontal. Voir [enum "
+"NinePatchRect.AxisStretchMode] pour les valeurs possibles."
#: doc/classes/NinePatchRect.xml
msgid ""
"The stretch mode to use for vertical stretching/tiling. See [enum "
"NinePatchRect.AxisStretchMode] for possible values."
msgstr ""
+"Le mode d'étirement à utiliser pour l'étirement vertical. Voir [enum "
+"NinePatchRect.AxisStretchMode] pour les valeurs possibles."
#: doc/classes/NinePatchRect.xml
msgid ""
"If [code]true[/code], draw the panel's center. Else, only draw the 9-slice's "
"borders."
msgstr ""
+"Si [code]true[/code], dessine le centre du panneau. Sinon, ne dessine que "
+"les bordures des 9 parties."
#: doc/classes/NinePatchRect.xml
msgid ""
@@ -45876,6 +48820,10 @@ msgid ""
"bottom corners and side will have a height of 16 pixels. You can set all 4 "
"margin values individually to create panels with non-uniform borders."
msgstr ""
+"La hauteur de la ligne du bas des 9 parties. Une marge de 16 signifie que "
+"les angles du bas des 9 parties et les côtés auront une hauteur de 16 "
+"pixels. Vous pouvez définir les 4 valeurs de marge individuellement pour "
+"créer des panneaux avec des bordures non uniformes."
#: doc/classes/NinePatchRect.xml
msgid ""
@@ -45883,6 +48831,10 @@ msgid ""
"left corners and side will have a width of 16 pixels. You can set all 4 "
"margin values individually to create panels with non-uniform borders."
msgstr ""
+"La largeur de la colonne gauche des 9 parties. Une marge de 16 signifie que "
+"les angles de gauche des 9 parties et les côtés auront une largeur de 16 "
+"pixels. Vous pouvez définir les 4 valeurs de marge individuellement pour "
+"créer des panneaux avec des bordures non uniformes."
#: doc/classes/NinePatchRect.xml
msgid ""
@@ -45890,6 +48842,10 @@ msgid ""
"right corners and side will have a width of 16 pixels. You can set all 4 "
"margin values individually to create panels with non-uniform borders."
msgstr ""
+"La largeur de la colonne droite de 9 parties. Une marge de 16 signifie que "
+"les angles de droite des 9 parties et le côté auront une largeur de 16 "
+"pixels. Vous pouvez définir les 4 valeurs de marge individuellement pour "
+"créer des panneaux avec des bordures non uniformes."
#: doc/classes/NinePatchRect.xml
msgid ""
@@ -45897,6 +48853,10 @@ msgid ""
"corners and side will have a height of 16 pixels. You can set all 4 margin "
"values individually to create panels with non-uniform borders."
msgstr ""
+"La hauteur de la ligne du haut de 9 parties. Une marge de 16 signifie que "
+"les angles du haut des 9 parties et le côté auront une hauteur de 16 pixels. "
+"Vous pouvez définir les 4 valeurs de marge individuellement pour créer des "
+"panneaux avec des bordures non uniformes."
#: doc/classes/NinePatchRect.xml
msgid ""
@@ -45905,6 +48865,10 @@ msgid ""
"other properties are relative to this one. If the rect is empty, "
"NinePatchRect will use the whole texture."
msgstr ""
+"La région rectangulaire de la texture à utiliser. Si vous travaillez avec un "
+"atlas, utilisez cette propriété pour définir la zone à utiliser. Toutes les "
+"autres propriétés sont par rapport à celle-ci. Si le rectangle est vide, le "
+"NinePatchRect utilisera la texture dans son entièreté."
#: doc/classes/NinePatchRect.xml
msgid "The node's texture resource."
@@ -45919,6 +48883,8 @@ msgid ""
"Stretches the center texture across the NinePatchRect. This may cause the "
"texture to be distorted."
msgstr ""
+"Étire la texture du centre sur tout le NinePatchRect. Cela peut entraîner "
+"une distorsion de cette texture."
#: doc/classes/NinePatchRect.xml
msgid ""
@@ -45928,6 +48894,11 @@ msgid ""
"[b]Note:[/b] Only supported when using the GLES3 renderer. When using the "
"GLES2 renderer, this will behave like [constant AXIS_STRETCH_MODE_STRETCH]."
msgstr ""
+"Répète la texture centrale sur tout le NinePatchRect. Cela ne provoque "
+"aucune distorsion visible. La texture doit être transparente pour que cela "
+"fonctionne sans afficher d'artefacts entre les bords.\n"
+"[b]Note :[/b] Seulement pris en charge avec GLES3. Avec GLES2, cela se "
+"comportera comme [constant AXIS_STRETCH_MODE_STRETCH]."
#: doc/classes/NinePatchRect.xml
msgid ""
@@ -45939,6 +48910,13 @@ msgid ""
"[b]Note:[/b] Only supported when using the GLES3 renderer. When using the "
"GLES2 renderer, this will behave like [constant AXIS_STRETCH_MODE_STRETCH]."
msgstr ""
+"Répète la texture centrale sur tout le NinePatchRect, mais étirera également "
+"la texture pour s'assurer que chaque tuile est visible entièrement. Cela "
+"peut causer une distorsion de la texture, mais moins que [constant "
+"AXIS_STRETCH_MODE_STRETCH]. La texture doit être transparente pour que cela "
+"fonctionne sans afficher d'artefacts entre les bords.\n"
+"[b]Note :[/b] Seulement pris en charge avec GLES3. Avec GLES2, cela se "
+"comportera comme [constant AXIS_STRETCH_MODE_STRETCH]."
#: doc/classes/Node.xml
msgid "Base class for all [i]scene[/i] objects."
@@ -46004,6 +48982,69 @@ msgid ""
"(make sure node names are the same on all peers). Also, take a look at the "
"high-level networking tutorial and corresponding demos."
msgstr ""
+"Les nœuds sont les blocs de construction de Godot. Ils peuvent être assignés "
+"comme enfant d'un autre nœud, ce qui entraîne définit l'arborescence. Un "
+"nœud donné peut contenir n'importe quel nombre de nœuds enfants mais tous "
+"ces enfants doivent avoir des noms différents.\n"
+"Une arborescence de nœuds est appelé une [i]scène[/i]. Les scènes peuvent "
+"être sauvegardées sur le disque et ensuite instanciées dans d'autres scènes. "
+"Cela permet une très grande flexibilité dans l'architecture et le modèle de "
+"données des projets Godot.\n"
+"[b]Arbre de scène :[/b] Le [SceneTree] contient l'arborescence des nœuds. "
+"Lorsqu'un nœud est ajouté à l'arborescence de scène, il reçoit la "
+"notification [constant NOTIFICATION_ENTER_TREE] et sa méthode [method "
+"enter_tree] est appelée. Les nœuds d'enfants sont toujours ajoutés [i]après[/"
+"i] leur nœud parent, c'est-à-dire la méthode [method enter_tree] d'un nœud "
+"parent sera appelée avant celle de son enfant.\n"
+"Une fois que tous les nœuds ont été ajoutés dans l'arborescence de la scène, "
+"ils reçoivent la notification [constante NOTIFICATION_READY] et leurs "
+"méthodes respectives [method _ready] sont appelées. Pour les groupes de "
+"nœuds, la méthode [method _ready] est appelée avec un ordre inversé, en "
+"commençant par les enfants et en allant jusqu'aux nœuds parent.\n"
+"Cela signifie qu'en ajoutant un nœud à l'arborescence de la scène, l'ordre "
+"suivant sera utilisé pour les appels des méthodes: [method enter_tree] du "
+"parent, [method enter_tree] des enfants, [method _ready] des enfants et "
+"enfin [method _ready] du parent (recursivement pour l'arborescence complète "
+"de la scène).\n"
+"[b]Processus :[/b] Les nœuds peuvent surcharger l'état du processus, de "
+"sorte qu'ils reçoivent un appel à chaque trame demandant un traitement (de "
+"faire quelque chose). Le traitement normal (la méthode [method _process], "
+"activée avec [method set_process]) se produit aussi vite que possible et "
+"dépend du nombre de trames par seconde, de sorte que le temps de traitement "
+"[i]delta[/i] (en secondes) est passé en argument. Le traitement physique (la "
+"méthode [method physical_process], activée avec [method "
+"set_physics_process]) est appelée un nombre fixe de fois par seconde (60 "
+"fois par défaut) et est utile pour le code lié au moteur physique.\n"
+"Les nœuds peuvent également traiter les événements d'entrée. À l'heure "
+"actuelle, la fonction [method _input] sera appelée pour chaque entrée que le "
+"programme reçoit. Dans de nombreux cas, cela peut faire trop d'informations "
+"(sauf pour des projets simples), et la fonction [method unhandled_input] "
+"peut être préférée ; elle est appelée lorsque l'événement d'entrée n'a été "
+"traité par aucun élément (généralement, des nœuds d'interface [Control]), "
+"pour s'assurer que le nœud ne reçoit que les événements qui lui sont "
+"destinés.\n"
+"Pour garder la trace de l'arborescence de la scène (surtout lorsque vous "
+"instanciez des scènes dans d'autres scènes), un \"propriétaire\" peut être "
+"défini pour le nœud avec la propriété [member owner]. Cela garde une trace "
+"de quel élément a instancié quel autre élément. Cela est surtout utile "
+"lorsque vous écrivez des éditeurs et des outils.\n"
+"Enfin, quand un nœud est libéré avec [method Object.free] ou [method "
+"queue_free], il va également libérer tous ses enfants.\n"
+"[b]Les groupes : [/b] Les nœuds peuvent être ajoutés à autant de groupes que "
+"vous voulez, vous pouvez créer des groupes comme « ennemis » ou « "
+"récupérables » par exemple, selon votre jeu. Voir [method add_to_group], "
+"[method is_in_group] et [method remove_from_group]. Vous pouvez ensuite "
+"récupérer tous les nœuds d'un groupe, lister les groupes et même appeler des "
+"méthodes sur les groupes via des méthodes de [SceneTree].\n"
+"[b]Faire communiquer les nœud via le réseau :[/b] Après s'être connecté à un "
+"serveur (ou en faire un, voir [NetworkedMultiplayerENet]), il est possible "
+"d'utiliser le système RPC intégré (\"Remote Procedure Call\") pour "
+"communiquer sur le réseau. En appelant [method rpc] avec un nom de méthode, "
+"il sera appelé localement et pour tous les pairs connectés (un pair = un "
+"client et le serveur qui accepte les connexions). Pour identifier quel nœud "
+"reçoit l'appel RPC, Godot utilisera son [NodePath] (s'assurant que les noms "
+"de nœuds sont les mêmes sur tous les pairs). Consultez également le tutoriel "
+"pour les réseaux à haut niveau et les démos correspondantes."
#: doc/classes/Node.xml
msgid "Nodes and Scenes"
@@ -46022,6 +49063,12 @@ msgid ""
"Corresponds to the [constant NOTIFICATION_ENTER_TREE] notification in "
"[method Object._notification]."
msgstr ""
+"Appelé lorsque le nœud entre dans la [SceneTree] (par exemple en étant "
+"instancié, au changement de scène, ou après avoir appelé [method add_child] "
+"dans un script). Si le nœud a des enfants, sa méthode [méthod enter_tree] "
+"sera appelée d'abord, puis ensuite celle de ses enfants.\n"
+"Correspond à la notification [constant NOTIFICATION_ENTER_TREE] dans [method "
+"Object._notification]."
#: doc/classes/Node.xml
msgid ""
@@ -46034,6 +49081,15 @@ msgid ""
"the node has already left the active tree, connect to the [signal "
"tree_exited]."
msgstr ""
+"Appelé lorsque le nœud va quitter la [SceneTree] (par exemple sur la "
+"suppression, au changement de scène, ou après avoir appelé [method "
+"remove_child] dans un script). Si le nœud a des enfants, sa méthode [method "
+"exit_tree] sera appelée en dernier, quand tous ses enfants auront quitté "
+"l'arborescence.\n"
+"Correspond à la notification [constant NOTIFICATION_EXIT_TREE] dans [method "
+"Object._notification] et signal [signal tree_exiting]. Pour être notifié "
+"lorsque le nœud a déjà quitté l'arborescence active, connectez-vous à "
+"[signal tree_exited]."
#: doc/classes/Node.xml
msgid ""
@@ -46043,6 +49099,12 @@ msgid ""
"Call [method update_configuration_warning] when the warning needs to be "
"updated for this node."
msgstr ""
+"La chaîne retournée de cette méthode est affichée comme un avertissement "
+"dans la barre d'outil Scène si le script qui la modifie est un script "
+"[code]tool[/code].\n"
+"Retourner une chaîne vide ne produit aucun avertissement.\n"
+"Appelez [method update_configuration_warning] lorsque l'avertissement doit "
+"être mis à jour pour ce nœud."
#: doc/classes/Node.xml
msgid ""
@@ -46141,6 +49203,21 @@ msgid ""
"call with [method request_ready], which may be called anywhere before adding "
"the node again."
msgstr ""
+"Appelé lorsque le nœud est « prêt », c'est-à-dire lorsque le nœud et ses "
+"enfants sont entrés dans l'arborescence de la scène. Si le nœud a des "
+"enfants, leur méthode [method _ready] sera appelée en premier, et le nœud "
+"parent recevra la notification après.\n"
+"Correspond à la notification [constant NOTIFICATION_READY] dans [method "
+"Object._notification]. Voir aussi le mot-clé [code]onready[/code] pour les "
+"variables.\n"
+"Habituellement utilisé pour l'initialisation. Pour encore avant cela, "
+"[method Object._init] peut être utilisé. Voir aussi [méthod enter_tree].\n"
+"[b]Note :[/b] [method _ready] ne peut être appelée qu'une seule fois pour "
+"chaque nœud. Après avoir retiré un nœud de l'arborescence de scène et "
+"l'ajouter à nouveau, [code]_ready[/code] ne sera pas appelé une deuxième "
+"fois. Cela peut être changé en demandant un autre appel avec [method "
+"request_ready], qui peut être appelé n'importe où avant d'ajouter le nœud à "
+"nouveau."
#: doc/classes/Node.xml
msgid ""
@@ -46230,6 +49307,30 @@ msgid ""
"will not be visible in the scene tree, though it will be visible in the "
"2D/3D view."
msgstr ""
+"Ajoute un nœud enfant. Les nœuds peuvent avoir autant d'enfants que voulu, "
+"mais chaque enfant doit avoir un nom unique. Les nœuds d'enfants sont "
+"automatiquement supprimés lorsque le nœud parent est supprimé, de sorte "
+"qu'une scène entière peut être supprimée en supprimant juste son nœud le "
+"plus haut.\n"
+"Si [code]legible_unique_name[/code] est [code]true[/code], le nœud d'enfant "
+"aura un nom clairement lisible basé sur le nom du nœud étant analysé au lieu "
+"de son type.\n"
+"[b]Note :[/b] Si le nœud enfant a déjà un parent, la fonction échouera. "
+"Utilisez [method remove_child] d'abord pour retirer le nœud de son parent "
+"actuel. Par exemple :\n"
+"[codeblock]\n"
+"if child_node.get_parent():\n"
+" child_node.get_parent().remove_child(child_node)\n"
+"add_child(child_node)\n"
+"[/codeblock]\n"
+"[b]Note :[/b] Si vous voulez qu'un enfant soit persiste dans un "
+"[PackedScene], vous devez définir [member owner] après avoir appelé [method "
+"add_child]. Ceci est généralement pertinent pour [url=$DOCS_URL/tutorials/"
+"plugins/running_code_in_the_editor.html]scripts d'outil[/url] et "
+"[url=$DOCS_URL/tutorials/plugins/editor/index.html]greffons d'éditeur[/url]. "
+"Si [method add_child] est appelé sans définir [member owner], le nouveau "
+"[Node] ajouté ne sera pas visible dans l'arborescence de la scène, bien "
+"qu'il sera visible dans la vue 2D/3D."
#: doc/classes/Node.xml
msgid ""
@@ -46239,6 +49340,10 @@ msgid ""
"will have a human-readable name based on the name of the node being "
"instanced instead of its type."
msgstr ""
+"Ajoute [code]child_nœud[/code] en tant qu'enfant. L'enfant est placé sous le "
+"[code]nœud[/code] donné dans la liste des enfants.\n"
+"Si [code]legible_unique_name[/code] est [code]true[/code], le nœud d'enfant "
+"aura un nom lisible humainement basé sur le nom du nœud plutôt que son type."
#: doc/classes/Node.xml
msgid ""
@@ -46261,6 +49366,10 @@ msgid ""
"scene tree is not paused, and [code]false[/code] if the node is not in the "
"tree."
msgstr ""
+"Retourne [code]true[/code] si le nœud peut traiter pendant que "
+"l'arborescence de scène est interrompue (voir [member pause_mode)]. Retourne "
+"toujours [code]true[/code] si l'arborescence de scène n'est pas interrompue, "
+"et [code]false[/code] si le nœud n'est pas dans l'arborescence."
#: doc/classes/Node.xml
msgid ""
@@ -46270,6 +49379,10 @@ msgid ""
"get_tree().create_tween().bind_node(self)\n"
"[/codeblock]"
msgstr ""
+"Crée un nouveau [SceneTreeTween] et le lie à ce nœud. Cela équivaut à :\n"
+"[codeblock]\n"
+"get_tree().create_tween().bind_node(self)\n"
+"[/codeblock]"
#: doc/classes/Node.xml
msgid ""
@@ -46280,6 +49393,13 @@ msgid ""
"constructor arguments (i.e. needs to supply arguments to [method Object."
"_init] method). In that case, the node will be duplicated without a script."
msgstr ""
+"Duplique le nœud, retournant un nouveau nœud.\n"
+"Vous pouvez affiner le comportement en utilisant des drapeaux dans "
+"[code]flags[/code] (voir [enum DuplicateFlags)].\n"
+"[b]Note :[/b] Ça ne fonctionnera pas correctement si le nœud contient un "
+"script avec des arguments de constructeur (c'est-à-dire qu'on doit fournir "
+"des arguments à la méthode [method Object._init]). Dans ce cas, le nœud sera "
+"dupliqué sans script."
#: doc/classes/Node.xml
msgid ""
@@ -46298,6 +49418,23 @@ msgid ""
"consider using [method get_node] instead. To avoid using [method find_node] "
"too often, consider caching the node reference into a variable."
msgstr ""
+"Trouve un descendant de ce nœud dont le nom correspond à [code]mask[/code] "
+"suivant le même fonctionnement que pour [method String.match] (c'est-à-dire "
+"sensible à la casse, que [code]\"*\"[/code] correspond à un zéro au un seul "
+"caractère, et que [code]\"?\"[/code] correspond à n'importe quel unique "
+"caractère sauf [code]\".\"[/code]). Retourne [code]null[/code] si aucun "
+"[Node] correspondant n'est trouvée.\n"
+"[b]Note :[/b] La correspondance ne se fait pas sur le chemin complet mais "
+"juste les noms des nœuds.\n"
+"Si [code]owned[/code] est [code]true[/code], cette méthode ne trouve que des "
+"nœuds dont le propriétaire est ce nœud. Ceci est particulièrement important "
+"pour les scènes instanciée par un script, parce que ces scènes n'ont pas de "
+"propriétaire.\n"
+"[b]Note :[/b] Comme cette méthode liste tous les descendants d'un nœud, "
+"c'est le moyen le plus lent d'obtenir une référence à un autre nœud. Dans la "
+"mesure du possible, essayez plutôt d'utiliser [method get_node]. Pour éviter "
+"d'utiliser [method find_node] trop souvent, essayez de mettre en chache la "
+"référence de ce nœud dans une variable."
#: doc/classes/Node.xml
msgid ""
@@ -46312,6 +49449,18 @@ msgid ""
"[method get_node] instead. To avoid using [method find_parent] too often, "
"consider caching the node reference into a variable."
msgstr ""
+"Trouve le premier parent de ce nœud dont le nom correspond à "
+"[code]mask[/code] suivant le même fonctionnement que pour [method String."
+"match] (c'est-à-dire sensible à la casse, que [code]\"*\"[/code] correspond "
+"à un zéro au un seul caractère, et que [code]\"?\"[/code] correspond à "
+"n'importe quel unique caractère sauf [code]\".\"[/code]).\n"
+"[b]Note :[/b] La correspondance ne se fait pas sur le chemin complet mais "
+"juste les noms des nœuds.\n"
+"[b]Note :[/b] Comme cette méthode liste tous les parents d'un nœud, c'est le "
+"moyen le plus lent d'obtenir une référence à un autre nœud. Dans la mesure "
+"du possible, essayez plutôt d'utiliser [method get_node]. Pour éviter "
+"d'utiliser [method find_node] trop souvent, essayez de mettre en chache la "
+"référence de ce nœud dans une variable."
#: doc/classes/Node.xml
msgid ""
@@ -46319,6 +49468,9 @@ msgid ""
"method is often used for iterating all children of a node.\n"
"To access a child node via its name, use [method get_node]."
msgstr ""
+"Retourne un nœud enfant par son index (voir [method get_child_count)]. Cette "
+"méthode est souvent utilisée pour itérer tous les enfants d'un nœud.\n"
+"Pour accéder à un nœud enfant par son nom, utilisez [method get_node]."
#: doc/classes/Node.xml
msgid "Returns the number of child nodes."
@@ -46346,17 +49498,38 @@ msgid ""
" non_internal_groups.push_back(group)\n"
"[/codeblock]"
msgstr ""
+"Retourne un tableau énumérant les groupes dont ce nœud est membre.\n"
+"[b]Note :[/b] Pour des raisons de performance, l'ordre des groupes de nœuds "
+"n'est [i]pas[/i] garanti. cet ordre des groupes de nœuds ne devrait pas être "
+"utilisé car il peut varier entre les différents projets.\n"
+"[b]Note :[/b] Le moteur utilise des noms de groupe en l'interne (tous "
+"commençent par \"_\"). Pour éviter les conflits avec des groupes internes, "
+"n'ajoutez pas de groupes personnalisés dont le nom commence par \"_\". Pour "
+"exclure les groupes internes en boucle sur [method get_groups], utiliser le "
+"code suivant:\n"
+"[codeblock]\n"
+"# Enregistre tous les nœuds des groupes non internes au moteur (dans un "
+"tableau de String).\n"
+"var non_internal_groups = []\n"
+"for group in get_groups():\n"
+" if not group.begins_with(\"_\"):\n"
+" non_internal_groups.push_back(group)\n"
+"[/codeblock]"
#: doc/classes/Node.xml
msgid ""
"Returns the node's index, i.e. its position among the siblings of its parent."
msgstr ""
+"Retourne l'indice du nœud, c'est-à-dire sa position parmi les enfants de son "
+"parent."
#: doc/classes/Node.xml
msgid ""
"Returns the peer ID of the network master for this node. See [method "
"set_network_master]."
msgstr ""
+"Retourne l'identifiant du pair du maître du réseau pour ce nœud. Voir "
+"[method set_network_master]."
#: doc/classes/Node.xml
msgid ""
@@ -46435,12 +49608,33 @@ msgid ""
"[[CollisionShape2D:1161], [RectangleShape2D:1156], :extents]\n"
"[/codeblock]"
msgstr ""
+"Récupère un nœud et une de ses ressources comme spécifié par le sous-nom de "
+"son [NodePath] (ex.: [code]Area2D/CollisionShape2D:shape[/code]). Si "
+"plusieurs ressources imbriquées sont spécifiées dans le [NodePath], seul le "
+"dernier sera récupéré.\n"
+"La valeur de retour est un tableau de 3 éléments : le premier élément est le "
+"[Node] (ou [code]null[/code] s'il n'est pas trouvé), le deuxième élément est "
+"la [Resource] (ou [code]null[/code] si elle n'est pas trouvée), et le "
+"troisième élément est le reste du [NodePath], le cas échéant.\n"
+"Par exemple, en supposant que [code]Area2D/CollisionShape2D[/code] est un "
+"nœud valide et que sa propriété [code]shape[/code] a été assignée à une "
+"ressource [RectangleShape2D], on pourrait avoir ce type de sortie:\n"
+"[codeblock]\n"
+"print(get_node_and_resource(\"Area2D/CollisionShape2D\")) # "
+"[[CollisionShape2D:1161], Null, ]\n"
+"print(get_node_and_resource(\"Area2D/CollisionShape2D:shape\")) # "
+"[[CollisionShape2D:1161], [RectangleShape2D:1156], ]\n"
+"print(get_node_and_resource(\"Area2D/CollisionShape2D:shape:extents\")) # "
+"[[CollisionShape2D:1161], [RectangleShape2D:1156], :extents]\n"
+"[/codeblock]"
#: doc/classes/Node.xml
msgid ""
"Similar to [method get_node], but does not log an error if [code]path[/code] "
"does not point to a valid [Node]."
msgstr ""
+"Semblable à [method get_node], mais n'affiche pas d'erreur si [code]path[/"
+"code] ne pointe pas vers une valeur valide [Node]."
#: doc/classes/Node.xml
msgid ""
@@ -46455,12 +49649,18 @@ msgid ""
"Returns the absolute path of the current node. This only works if the "
"current node is inside the scene tree (see [method is_inside_tree])."
msgstr ""
+"Retourne le chemin absolu du nœud actuel. Cela ne fonctionne que si le nœud "
+"actuel est à l'intérieur de l'arborescence de la scène (voir [method "
+"is_inside_tree)]."
#: doc/classes/Node.xml
msgid ""
"Returns the relative [NodePath] from this node to the specified [code]node[/"
"code]. Both nodes must be in the same scene or the function will fail."
msgstr ""
+"Retourne le chemin [NodePath] relatif de ce nœud par rapport au nœud "
+"[code]nœud[/code] spécifié. Les deux nœuds doivent être dans la même scène "
+"sinon la fonction échouera."
#: doc/classes/Node.xml
msgid ""
@@ -46469,18 +49669,26 @@ msgid ""
"processing unless the frames per second is changed via [member Engine."
"iterations_per_second]."
msgstr ""
+"Retourne le temps écoulé (en secondes) depuis la dernière trame physique ("
+"voir [method _physics_process]). C'est toujours une valeur constante dans le "
+"traitement de la physique à moins que les trames par seconde ne soient "
+"changés via [member Engine.iterations_per_second]."
#: doc/classes/Node.xml
msgid ""
"Returns the node's order in the scene tree branch. For example, if called on "
"the first child node the position is [code]0[/code]."
msgstr ""
+"Retourne l'ordre du nœud dans la branche de la scène. Par exemple, si on "
+"l'appelle sur le premier nœud enfant, la position est [code]0[/code]."
#: doc/classes/Node.xml
msgid ""
"Returns the time elapsed (in seconds) since the last process callback. This "
"value may vary from frame to frame."
msgstr ""
+"Retourne le temps écoulé (en secondes) depuis le dernier rappel de process. "
+"Cette valeur peut varier d'une trame à l'autre."
#: doc/classes/Node.xml
msgid ""
@@ -46511,12 +49719,19 @@ msgid ""
"shape[/code]. Properties with a non-[Resource] type (e.g. nodes or primitive "
"math types) are not considered resources."
msgstr ""
+"Retourne [code]true[/code] si le [NodePath] désigne un nœud valide et son "
+"sous-nom désigne une ressource valide, par exemple [code]Area2D/"
+"CollisionShape2D:shape[/code]. Les propriétés avec un type qui n'est pas une "
+"[Resource] (par exemple les nœuds ou les types mathématiques primitifs) ne "
+"sont pas considérées comme des ressources."
#: doc/classes/Node.xml
msgid ""
"Returns [code]true[/code] if the given node is a direct or indirect child of "
"the current node."
msgstr ""
+"Retourne [code]true[/code] si le nœud donné est un enfant direct ou indirect "
+"du nœud actuel."
#: doc/classes/Node.xml
msgid ""
@@ -46537,6 +49752,8 @@ msgid ""
"Returns [code]true[/code] if this node is in the specified group. See notes "
"in the description, and the group methods in [SceneTree]."
msgstr ""
+"Retourne [code]true[/code] si ce nœud est dans le groupe spécifié. Voir les "
+"notes dans la description, et les méthodes de groupe dans [SceneTree]."
#: doc/classes/Node.xml
msgid ""
@@ -46548,6 +49765,7 @@ msgstr ""
msgid ""
"Returns [code]true[/code] if the local system is the master of this node."
msgstr ""
+"Retourne [code]true[/code] si le système local est le maître de ce nœud."
#: doc/classes/Node.xml
msgid ""
@@ -46557,6 +49775,11 @@ msgid ""
"[b]and[/b] physics interpolation is enabled within the [SceneTree]. This can "
"be tested using [method is_physics_interpolated_and_enabled]."
msgstr ""
+"Retourne [code]true[/code] si le drapeau interpolé de la physique est défini "
+"pour ce nœud (voir [member physics_interpolation_mode)].\n"
+"[b]Note :[/b] L'interpolation ne sera active que si le drapeau est défini "
+"[b]et[/b] que l'interpolation physique est activée dans [SceneTree]. Ceci "
+"peut être testé en utilisant [method is_physics_interpolated_and_enabled]."
#: doc/classes/Node.xml
msgid ""
@@ -46567,36 +49790,52 @@ msgid ""
"See [member SceneTree.physics_interpolation] and [member ProjectSettings."
"physics/common/physics_interpolation]."
msgstr ""
+"Retourne [code]true[/code] si l'interpolation physique est activée (voir ["
+"member physics_interpolation_mode]) [b]et[/b] activée dans [SceneTree].\n"
+"Il s'agit d'une version pratique de [method is_physics_interpolated] qui "
+"vérifie également si l'interpolation physique est activée globalement.\n"
+"Voir [member SceneTree.physics_interpolation] et [member ProjectSettings."
+"physics/common/physics_interpolation]."
#: doc/classes/Node.xml
msgid ""
"Returns [code]true[/code] if physics processing is enabled (see [method "
"set_physics_process])."
msgstr ""
+"Retourne [code]true[/code] si le traitement physique est activé (voir "
+"[method set_physics_process)]."
#: doc/classes/Node.xml
msgid ""
"Returns [code]true[/code] if internal physics processing is enabled (see "
"[method set_physics_process_internal])."
msgstr ""
+"Retourne [code]true[/code] si le traitement physique interne est activé "
+"(voir [method set_physics_process_internal)]."
#: doc/classes/Node.xml
msgid ""
"Returns [code]true[/code] if processing is enabled (see [method "
"set_process])."
msgstr ""
+"Retourne [code]true[/code] si le traitement est activé (voir [method "
+"set_process)]."
#: doc/classes/Node.xml
msgid ""
"Returns [code]true[/code] if the node is processing input (see [method "
"set_process_input])."
msgstr ""
+"Retourne [code]true[/code] si le nœud gère l'entrée (voir [method "
+"set_process_input)]."
#: doc/classes/Node.xml
msgid ""
"Returns [code]true[/code] if internal processing is enabled (see [method "
"set_process_internal])."
msgstr ""
+"Retourne [code]true[/code] si le traitement interne est activé (voir [method "
+"set_process_internal)]."
#: doc/classes/Node.xml
msgid ""
@@ -46611,6 +49850,8 @@ msgid ""
"Returns [code]true[/code] if the node is processing unhandled key input (see "
"[method set_process_unhandled_key_input])."
msgstr ""
+"Retourne [code]true[/code] si le nœud gère l'entrée de touche non traitée "
+"(voir [method set_process_unhandled_key_input)]."
#: doc/classes/Node.xml
msgid ""
@@ -46618,12 +49859,17 @@ msgid ""
"Since calls, signals, etc are performed by tree order, changing the order of "
"children nodes may be useful."
msgstr ""
+"Déplace un nœud enfant à une position différente (ordre) parmi les autres "
+"enfants. Comme les appels, les signaux, etc. sont effectués par l'ordre des "
+"arborescences, changer l'ordre des nœuds d'enfants peut être utile."
#: doc/classes/Node.xml
msgid ""
"Prints all stray nodes (nodes outside the [SceneTree]). Used for debugging. "
"Works only in debug builds."
msgstr ""
+"Imprime tous les nœuds égarés (sauf le [SceneTree)]. Utilisé pour le "
+"débogage. Fonctionne seulement dans les versions de débogage."
#: doc/classes/Node.xml
msgid ""
@@ -46640,6 +49886,18 @@ msgid ""
"TheGame/SplashScreen/Camera2D\n"
"[/codeblock]"
msgstr ""
+"Imprime l'arborescence dans la console. Utilisé principalement à des fins de "
+"débogage. Cette version affiche le chemin par rapport au nœud actuel, ce qui "
+"est utile pour le copier/coller dans la fonction [method get_node].\n"
+"[b]Exemple de sortie:[/b]\n"
+"[codeblock]\n"
+"TheGame\n"
+"TheGame/Menu\n"
+"TheGame/Menu/Label\n"
+"TheGame/Menu/Camera2D\n"
+"TheGame/SplashScreen\n"
+"TheGame/SplashScreen/Camera2D\n"
+"[/codeblock]"
#: doc/classes/Node.xml
msgid ""
@@ -46656,6 +49914,19 @@ msgid ""
" â”–â•´Camera2D\n"
"[/codeblock]"
msgstr ""
+"Comme [method print_tree], cela imprime l'arborescence dans la console. "
+"Cette version affiche une représentation plus graphique semblable à ce qui "
+"est affiché dans l'inspecteur de scène. C'est utile pour inspecter les "
+"grands arborescences.\n"
+"[b]Exemple de sortie:[/b]\n"
+"[codeblock]\n"
+" â”–â•´TheGame\n"
+" â” â•´Menu\n"
+" ┃ ┠╴Label\n"
+" ┃ ┖╴Camera2D\n"
+" â”–â•´SplashScreen\n"
+" â”–â•´Camera2D\n"
+"[/codeblock]"
#: doc/classes/Node.xml
msgid ""
@@ -46666,12 +49937,20 @@ msgid ""
"[code]parent_first[/code] is [code]false[/code], the children will be called "
"first."
msgstr ""
+"Appelle la méthode donnée (si présente) avec les arguments spécifiés dans "
+"[code]args[/code] sur ce nœud et récursivement sur tous ses enfants. Si "
+"l'argument [code]parent_first[/code] est [code]true[/code], la méthode sera "
+"appelée d'abord sur le nœud courant, puis sur tous ses enfants. Si "
+"[code]parent_first[/code] est [code]false[/code], les enfants seront appelés "
+"en premier."
#: doc/classes/Node.xml
msgid ""
"Notifies the current node and all its children recursively by calling "
"[method Object.notification] on all of them."
msgstr ""
+"Notifie le nœud actuel et tous ses enfants de façon récursive en les "
+"appelant [method Object.notification] sur tous."
#: doc/classes/Node.xml
msgid ""
@@ -46686,6 +49965,17 @@ msgid ""
"[method @GDScript.is_instance_valid] before attempting to call its methods "
"or access its properties."
msgstr ""
+"Place le nœud dans une file d'attente pour la suppression à la fin de la "
+"trame actuel. Lorsque supprimé, tous ses nœuds d'enfants seront supprimés "
+"aussi. Cette méthode s'assure qu'il est sûr de supprimer le nœud, "
+"contrairement [method Object.free]. Utilisez [method Object."
+"is_queued_for_deletion] pour vérifier si un nœud sera supprimé à la fin de "
+"la trame.\n"
+"[b]Important:[/b] Si vous avez une variable pointant vers un nœud, il ne "
+"sera [i]pas[/i] attribué à [code]null[/code] une fois le nœud libéré. Au "
+"lieu de cela, il va pointer vers [i]l'instance précédemment libérée[/i] et "
+"vous devez le valider avec [method @GDScript.is_instance_valid] avant de "
+"risquer d'appeler des méthodes dessus ou d'accéder à ses propriétés."
#: doc/classes/Node.xml
msgid ""
@@ -46696,6 +49986,12 @@ msgid ""
"of it. After using [code]raise[/code], a Control will be drawn on top of its "
"siblings."
msgstr ""
+"Déplace ce nœud vers le bas de la hiérarchie des enfants. Cela est souvent "
+"utile dans les nœuds d'interface ([Control]), parce que leur ordre de dessin "
+"dépend de leur ordre dans l'arborescence. Le Node en haut est dessiné "
+"d'abord, puis les nœuds en dessous dans la hiérarchie qui sont "
+"successivement dessinés. Après avoir utilisé [code]raise[/code], un contrôle "
+"sera affiché par dessus les autres enfants."
#: doc/classes/Node.xml
msgid ""
@@ -46703,6 +49999,9 @@ msgid ""
"it exists). All event subscriptions that pass by the removed node will be "
"unsubscribed."
msgstr ""
+"Retire un nœud et fixe tous ses enfants comme enfants du nœud parent (s'il "
+"existe). Tous les souscriptions d'événement qui passent par le nœud retiré "
+"seront aussi retirées."
#: doc/classes/Node.xml
msgid ""
@@ -46711,12 +50010,19 @@ msgid ""
"(or its descendants) to be [code]null[/code], if that [member owner] is no "
"longer a parent or ancestor."
msgstr ""
+"Retire un nœud d'enfant. Le nœud n'est PAS supprimé et doit être supprimé "
+"manuellement.\n"
+"[b]Note :[/b] Cette fonction peut définir le [member owner] du nœud enlevé "
+"(ou ses descendants) comme [code]null[/code], si ce [member owner] n'est "
+"plus un parent."
#: doc/classes/Node.xml
msgid ""
"Removes a node from a group. See notes in the description, and the group "
"methods in [SceneTree]."
msgstr ""
+"Retire un nœud d'un groupe. Voir les notes dans la description, et les "
+"méthodes de groupe dans [SceneTree]."
#: doc/classes/Node.xml
msgid ""
@@ -46728,6 +50034,13 @@ msgid ""
"need to keep it in a variable for later use or free it using [method Object."
"free]."
msgstr ""
+"Remplace un nœud dans une scène par celui donné. Les souscriptions qui "
+"passent par ce nœud seront perdus.\n"
+"[b]Note :[/b] Le nœud donné deviendra le nouveau parent de tous les nœuds "
+"d'enfants que le nœud remplacé avait.\n"
+"[b]Note :[/b] Le nœud remplacé n'est pas automatiquement libéré, donc vous "
+"devez le garder dans une variable pour une utilisation ultérieure ou le "
+"libérer en utilisant [method Object.free]."
#: doc/classes/Node.xml
msgid ""
@@ -46739,6 +50052,13 @@ msgid ""
"which case, [code]_ready[/code] will be called in the same order as it would "
"normally)."
msgstr ""
+"Demande que [code]_ready[/code] soit de nouveau appelé. Notez que la méthode "
+"va s'appeler immédiatement, mais qu'elle est prévue lorsque le nœud est "
+"ajouté à l'arborescence de scène à nouveau (voir [method _ready)]. "
+"[code]_ready[/code] est appelé seulement pour le nœud qui l'a demandé, ce "
+"qui signifie que vous devez le demander pour chaque enfant si vous voulez "
+"qu'ils appellent [code]_ready[/code] aussi (dans quel cas, [code]_ready[/"
+"code] sera appelé dans le même ordre que normalement)."
#: doc/classes/Node.xml
msgid ""
@@ -46754,6 +50074,17 @@ msgid ""
"[b]Note:[/b] This function should be called [b]after[/b] moving the node, "
"rather than before."
msgstr ""
+"Lorsque l'interpolation de la physique est active, déplacer un nœud vers une "
+"transformation radicalement différente (comme le placement dans un niveau) "
+"peut entraîner un glissement visible car l'objet est rendu lors de son "
+"déplacement lors de la trame physique.\n"
+"Ce glitch peut être évité en appelant [code]reset_physics_interpolation[/"
+"code], qui annule temporairement l'interpolation jusqu'à ce que la trame "
+"physique soit complète.\n"
+"[constant NOTIFICATION_RESET_PHYSICS_INTERPOLATION] sera reçu par le nœud et "
+"tous les enfants de façon récursive.\n"
+"[b]Note :[/b] Cette fonction doit être appelée [b]après[/b] le déplacement "
+"du nœud, plutôt qu'avant."
#: doc/classes/Node.xml
msgid ""
@@ -46771,6 +50102,20 @@ msgid ""
"like [code]server_disconnected[/code] or by checking [code]SceneTree."
"network_peer.get_connection_status() == CONNECTION_CONNECTED[/code]."
msgstr ""
+"Envoie une requête d'appel de procédure à distance pour la [code]method[/"
+"code] donnée aux pairs sur le réseau (et localement), en option en envoyant "
+"tous les arguments supplémentaires comme arguments à la méthode appelée par "
+"le RPC. La requête d'appel ne sera reçue que par des nœuds ayant le même "
+"[NodePath], y compris le même nom de nœud. Le comportement dépend de la "
+"configuration RPC pour la méthode donnée, voir [method rpc_config]. Les "
+"méthodes ne sont pas exposées aux RPC par défaut. Voir aussi [method rset] "
+"et [method rset_config] pour les propriétés. Retourne [code]null[/code].\n"
+"[b]Note :[/b] Vous pouvez seulement utiliser RPC en toute sécurité sur les "
+"clients après avoir reçu le signal [code]connected_to_server[/code] du "
+"[SceneTree]. Vous devez également suivre l'état de connexion, soit par les "
+"signaux [SceneTree] comme [code]server_disconnected[/code] ou en vérifiant "
+"[code]SceneTree.network_peer.get_connection_status() == "
+"CONNECTION_CONNECTED[/code]."
#: doc/classes/Node.xml
msgid ""
@@ -46782,6 +50127,13 @@ msgid ""
"By default, methods are not exposed to networking (and RPCs). See also "
"[method rset] and [method rset_config] for properties."
msgstr ""
+"Change le mode RPC pour la [code]method[/code] donné pour le "
+"[code]mode[/code] spécifié. Voir [enum MultiplayerAPI.RPCMode]. Une "
+"alternative est d'annoter les méthodes et les propriétés avec les mots-clés "
+"correspondants ([code]remote[/code], [code]master[/code], [code]puppet[/code]"
+", [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code])"
+". Par défaut, les méthodes ne sont pas exposées au réseaut (et aux RPC). "
+"Voir aussi [method rset] et [method rset_config] pour les propriétés."
#: doc/classes/Node.xml
msgid ""
@@ -46789,6 +50141,9 @@ msgid ""
"(see [method NetworkedMultiplayerPeer.set_target_peer]). Returns [code]null[/"
"code]."
msgstr ""
+"Envoie un [method rpc] à un pair spécifique identifié par [code]peer_id[/"
+"code] (voir [method NetworkedMultiplayerPeer.set_target_peer]). Retourne "
+"[code]null[/code]."
#: doc/classes/Node.xml
msgid ""
@@ -46803,6 +50158,9 @@ msgid ""
"using an unreliable protocol (see [method NetworkedMultiplayerPeer."
"set_target_peer]). Returns [code]null[/code]."
msgstr ""
+"Envoie un [method rpc] à un pair spécifique identifié par [code]peer_id[/"
+"code] en utilisant un protocole non fiable (voir [method "
+"NetworkedMultiplayerPeer.set_target_peer]). Retourne [code]null[/code]."
#: doc/classes/Node.xml
msgid ""
@@ -46811,6 +50169,10 @@ msgid ""
"rset_config]. See also [method rpc] for RPCs for methods, most information "
"applies to this method as well."
msgstr ""
+"Change une propriété distante sur d'autres pairs (et localement). Le "
+"comportement dépend de la configuration du RPC pour la propriété donnée, "
+"voir [method rset_config]. Voir aussi [method rpc] pour les RPC sur les "
+"méthodes, la plupart des informations s'appliquent aussi à cette méthode."
#: doc/classes/Node.xml
msgid ""
@@ -46822,6 +50184,13 @@ msgid ""
"By default, properties are not exposed to networking (and RPCs). See also "
"[method rpc] and [method rpc_config] for methods."
msgstr ""
+"Change le mode RPC pour la [code]property[/code] donnée au [code]mode[/code] "
+"spécifié. Voir [enum MultiplayerAPI.RPCMode]. Une alternative est "
+"l'annotation des méthodes et des propriétés avec les mots-clés "
+"correspondants ([code]remote[/code], [code]master[/code], [code]puppet[/code]"
+", [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code])"
+". Par défaut, les propriétés ne sont pas exposées au réseau (et au RPC). "
+"Voir aussi [method rpc] et [method rpc_config] pour les méthodes."
#: doc/classes/Node.xml
msgid ""
@@ -47069,11 +50438,13 @@ msgid ""
msgstr ""
#: doc/classes/Node.xml
-#, fuzzy
msgid ""
"Notification received when the node is about to exit a [SceneTree].\n"
"This notification is emitted [i]after[/i] the related [signal tree_exiting]."
-msgstr "La notification reçue quand le nœud va quitter le [SceneTree]."
+msgstr ""
+"La notification reçue quand le nœud va quitter le [SceneTree].\n"
+"Cette notification est émise [i]après[/i] le signal [signal tree_exiting] "
+"correspondant."
#: doc/classes/Node.xml
msgid "Notification received when the node is moved in the parent."
@@ -47349,7 +50720,7 @@ msgstr ""
#: doc/classes/Node2D.xml
msgid "Local [Transform2D]."
-msgstr "[Transform2D] local."
+msgstr "[Transform2D] locale."
#: doc/classes/Node2D.xml
msgid ""
@@ -47367,9 +50738,8 @@ msgid ""
msgstr ""
#: doc/classes/NodePath.xml
-#, fuzzy
msgid "Pre-parsed scene tree path."
-msgstr "Chemin de l'arborescence des scènes pré-analysé."
+msgstr "Le chemin pré-analysé de l'arborescence des scènes."
#: doc/classes/NodePath.xml
msgid ""
@@ -48400,19 +51770,16 @@ msgid "Sets an individual hole point position."
msgstr "Définit la position d'un trou simple."
#: doc/classes/OccluderShapePolygon.xml
-#, fuzzy
msgid "Sets an individual polygon point position."
-msgstr "Définit la position d'un polygone simple."
+msgstr "Définit la position d'un seul point d'un polygone."
#: doc/classes/OccluderShapePolygon.xml
-#, fuzzy
msgid "Allows changing the hole geometry from code."
-msgstr "Dessine une géométrie simple à partir du code."
+msgstr ""
#: doc/classes/OccluderShapePolygon.xml
-#, fuzzy
msgid "Allows changing the polygon geometry from code."
-msgstr "Dessine une géométrie simple à partir du code."
+msgstr ""
#: doc/classes/OccluderShapePolygon.xml
msgid ""
@@ -48486,8 +51853,14 @@ msgid "See [enum ShadowDetail]."
msgstr "Voir [enum ShadowDetail]."
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
-msgstr "Voir [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
+msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
@@ -48498,7 +51871,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -48675,18 +52049,16 @@ msgid "Returns the text of the item at index [code]idx[/code]."
msgstr "Retourne le texte de l'élément à l'index [code]idx[/code]."
#: doc/classes/OptionButton.xml
-#, fuzzy
msgid "Returns the tooltip of the item at index [code]idx[/code]."
-msgstr "Retourne le texte de l'élément à l'index [code]idx[/code]."
+msgstr "Retourne l'infobulle de l'élément à l'index [code]idx[/code]."
#: doc/classes/OptionButton.xml
-#, fuzzy
msgid ""
"Returns the ID of the selected item, or [code]-1[/code] if no item is "
"selected."
msgstr ""
-"Retourne la position de l’élément qui a actuellement le focus. Ou retourne "
-"[code]-1[/code] si aucun n'a le focus."
+"Retourne l'identifiant de l’élément sélectionné, ou [code]-1[/code] si aucun "
+"n'est sélectionné."
#: doc/classes/OptionButton.xml
msgid ""
@@ -48739,9 +52111,8 @@ msgid "Sets the text of the item at index [code]idx[/code]."
msgstr "Définit le texte pour l'élément à l'index [code]idx[/code]."
#: doc/classes/OptionButton.xml
-#, fuzzy
msgid "Sets the tooltip of the item at index [code]idx[/code]."
-msgstr "Définit le texte pour l'élément à l'index [code]idx[/code]."
+msgstr "Définit l'infobulle pour l'élément à l'index [code]idx[/code]."
#: doc/classes/OptionButton.xml
msgid ""
@@ -48864,9 +52235,8 @@ msgstr ""
"fils d'exécutions."
#: doc/classes/OS.xml
-#, fuzzy
msgid "Centers the window on the screen if in windowed mode."
-msgstr "Définit la position du nœud spécifié."
+msgstr ""
#: doc/classes/OS.xml
msgid ""
@@ -49025,18 +52395,16 @@ msgid ""
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid "Returns the scancode of the given string (e.g. \"Escape\")."
-msgstr "Renvoie le reste de deux vecteurs."
+msgstr ""
#: doc/classes/OS.xml
msgid "Returns the total number of available audio drivers."
msgstr "Retourne le nombre total de périphériques audio."
#: doc/classes/OS.xml
-#, fuzzy
msgid "Returns the audio driver name for the given index."
-msgstr "Retourne le sommet à l’index donné."
+msgstr ""
#: doc/classes/OS.xml
msgid ""
@@ -49455,14 +52823,13 @@ msgid ""
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid "Returns the epoch time of the operating system in milliseconds."
-msgstr "Retourne le temps epoch du système d'exploitation en millisecondes."
+msgstr ""
+"Retourne l'heure de l'époque du système d'exploitation en millisecondes."
#: doc/classes/OS.xml
-#, fuzzy
msgid "Returns the epoch time of the operating system in seconds."
-msgstr "Retourne le temps epoch du système d'exploitation en secondes."
+msgstr "Retourne l'heure de l'époque du système d'exploitation en secondes."
#: doc/classes/OS.xml
msgid ""
@@ -49579,9 +52946,8 @@ msgid ""
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid "Returns the number of video drivers supported on the current platform."
-msgstr "Renvoie le nombre de points sur l'axe de mélange."
+msgstr ""
#: doc/classes/OS.xml
msgid ""
@@ -49629,9 +52995,8 @@ msgid ""
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid "Returns [code]true[/code] if there is content on the clipboard."
-msgstr "Retourne [code]true[/code] si l'[AABB] est plate ou vide."
+msgstr "Retourne [code]true[/code] si le presse-papiers n'est pas vide."
#: doc/classes/OS.xml
msgid ""
@@ -49653,19 +53018,19 @@ msgid ""
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the device has a touchscreen or emulates one."
-msgstr "Retourne [code]true[/code] (vrai) si la chaîne de caractères est vide."
+msgstr ""
+"Retourne [code]true[/code] si le périphérique à un écran tactile ou en "
+"simule un."
#: doc/classes/OS.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the platform has a virtual keyboard, "
"[code]false[/code] otherwise."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères est vide, ou "
-"[code]false[/code] le cas échéant."
+"Retourne [code]true[/code] si la plateforme à un clavier virtuel (non "
+"physique), ou [code]false[/code] sinon."
#: doc/classes/OS.xml
msgid "Hides the virtual keyboard if it is shown, does nothing otherwise."
@@ -49700,11 +53065,10 @@ msgid ""
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the input scancode corresponds to a Unicode "
"character."
-msgstr "Retourne [code]true[/code] si l'[AABB] chevauche une autre."
+msgstr ""
#: doc/classes/OS.xml
msgid ""
@@ -50009,7 +53373,6 @@ msgstr ""
"Windows."
#: doc/classes/OS.xml
-#, fuzzy
msgid ""
"Requests the OS to open a resource with the most appropriate program. For "
"example:\n"
@@ -50036,12 +53399,12 @@ msgstr ""
"d'accueil de Godot dans le navigateur web par défaut.\n"
"- [code]OS.shell_open(\"mailto:example@example.com\")[/code] ouvrira le "
"client mail par défaut avec le champs destinataire définit à "
-"[code]example@example.com[/code]. Voir [url=https://blog.escapecreative.com/"
-"customizing-mailto-links/]Personnaliser les liens [code]mailto:[/code][/url] "
-"pour la liste des champs qui peuvent être ajoutés.\n"
+"[code]example@example.com[/code]. Voir [url=https://datatracker.ietf.org/doc/"
+"html/rfc2368]RFC 2368 - The [code]mailto[/code] URL scheme[/url] pour la "
+"liste des champs qui peuvent être ajoutés.\n"
"Utilisez [method ProjectSettings.globalize_path] pour convertir un chemin "
-"[code]res://[/code] ou [code]user://[/code] en chemin système pour utiliser "
-"avec cette méthode.\n"
+"[code]res://[/code] ou [code]user://[/code] en chemin système qui peut être "
+"utilisé avec cette méthode.\n"
"[b]Note :[/b] Cette méthode est implémentée sous Android, iOS, HTML5, Linux, "
"macOS et Windows."
@@ -50085,12 +53448,12 @@ msgid ""
msgstr ""
#: doc/classes/OS.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the engine tries to keep the screen on while the game "
"is running. Useful on mobile."
msgstr ""
-"Si [code]true[/code], le mouvement linéaire à travers l’axe Z est limité."
+"Si [code]true[/code], Le moteur tente de garder l'écran allumé quand le jeu "
+"est lancé. Utile sur les mobiles."
#: doc/classes/OS.xml
msgid ""
@@ -51148,9 +54511,8 @@ msgid ""
msgstr ""
#: doc/classes/Particles.xml
-#, fuzzy
msgid "Maximum number of draw passes supported."
-msgstr "Nombre maximal de passes de tirage prises en charge."
+msgstr "Le nombre maximal de passes de dessin supporté."
#: doc/classes/Particles2D.xml
msgid "GPU-based 2D particle emitter."
@@ -51828,11 +55190,10 @@ msgstr ""
"dans les versions finales."
#: doc/classes/Performance.xml
-#, fuzzy
msgid "Available static memory. Not available in release builds."
msgstr ""
"La mémoire statique disponible. N'est pas utilisable dans les versions "
-"finales."
+"exportés sans le mode débogage."
#: doc/classes/Performance.xml
msgid "Available dynamic memory. Not available in release builds."
@@ -51953,7 +55314,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 ""
@@ -52665,9 +56026,8 @@ msgid ""
msgstr ""
#: doc/classes/Physics2DServer.xml
-#, fuzzy
msgid "Returns the value of a damped spring joint parameter."
-msgstr "Renvoie la valeur opposée du paramètre."
+msgstr ""
#: doc/classes/Physics2DServer.xml
#, fuzzy
@@ -52675,8 +56035,8 @@ msgid ""
"Sets a damped spring joint parameter. See [enum DampedStringParam] for a "
"list of available parameters."
msgstr ""
-"Définit la valeur d’un paramètre de zone. Voir [enum AreaParameter] pour une "
-"liste de paramètres disponibles."
+"Définit la valeur d’un paramètre de zone. Voir [enum DampedStringParam] pour "
+"une liste de paramètres disponibles."
#: doc/classes/Physics2DServer.xml
msgid ""
@@ -53644,18 +57004,16 @@ msgid "Creates a [SliderJoint]."
msgstr "Crée un [SliderJoint]."
#: doc/classes/PhysicsServer.xml
-#, fuzzy
msgid "Gets the priority value of the Joint."
-msgstr "Renvoie la valeur opposée du paramètre."
+msgstr ""
#: doc/classes/PhysicsServer.xml
msgid "Returns the type of the Joint."
msgstr "Retourne le type de Joint."
#: doc/classes/PhysicsServer.xml
-#, fuzzy
msgid "Sets the priority value of the Joint."
-msgstr "Renvoie la valeur opposée du paramètre."
+msgstr "Définit la priorité de la valeur du Joint."
#: doc/classes/PhysicsServer.xml
msgid ""
@@ -53936,20 +57294,17 @@ msgid ""
msgstr ""
#: doc/classes/PhysicsServer.xml
-#, fuzzy
msgid "If set, linear motion is possible within the given limits."
msgstr ""
-"Si [code]set[/code] il y a un mouvement linéaire possible dans les limites "
-"données."
+"Si définit, le mouvement linéaire est possible dans les limites données."
#: doc/classes/PhysicsServer.xml
msgid "If set, rotational motion is possible."
msgstr "Si définit, la rotation est possible."
#: doc/classes/PhysicsServer.xml
-#, fuzzy
msgid "If set, there is a rotational motor across these axes."
-msgstr "La vitesse de toutes les rotations à travers l’axe X."
+msgstr ""
#: doc/classes/PhysicsServer.xml
msgid ""
@@ -54010,14 +57365,12 @@ msgid "Sets the [Shape] that will be used for collision/intersection queries."
msgstr ""
#: doc/classes/PhysicsShapeQueryParameters.xml
-#, fuzzy
msgid "If [code]true[/code], the query will take [Area]s into account."
-msgstr "Si [code]true[/code], la texture sera centrée."
+msgstr "Si [code]true[/code], le requête prendra les [Area] en compte."
#: doc/classes/PhysicsShapeQueryParameters.xml
-#, fuzzy
msgid "If [code]true[/code], the query will take [PhysicsBody]s into account."
-msgstr "Si [code]true[/code], la texture sera centrée."
+msgstr "Si [code]true[/code], le requête prendra les [PhysicsBody] en compte."
#: doc/classes/PinJoint.xml
#, fuzzy
@@ -54043,13 +57396,10 @@ msgid ""
msgstr ""
#: doc/classes/PinJoint.xml
-#, fuzzy
msgid ""
"If above 0, this value is the maximum value for an impulse that this Joint "
"produces."
msgstr ""
-"Retourne quand la mot clé [code]keyword[/code] spécifié a une couleur de "
-"défini ou non."
#: doc/classes/PinJoint2D.xml
#, fuzzy
@@ -54088,11 +57438,8 @@ msgid ""
msgstr ""
#: doc/classes/Plane.xml
-#, fuzzy
msgid "Creates a plane from the three points, given in clockwise order."
-msgstr ""
-"Crée un plan à partir des trois points, donné dans le sens des aiguilles "
-"d’une montre."
+msgstr "Crée un plan à partir de trois points, spécifiés dans le sens horaire."
#: doc/classes/Plane.xml
msgid "Creates a plane from the normal and the plane's distance to the origin."
@@ -54320,9 +57667,8 @@ msgid "Returns the path to the node associated with the specified bone."
msgstr "Retourne le chemin d’accès au nœud associé à l’os spécifié."
#: doc/classes/Polygon2D.xml
-#, fuzzy
msgid "Returns the height values of the specified bone."
-msgstr "Retourne la hauteur de l'os spécifié."
+msgstr "Retourne les valeurs de hauteur de l'os spécifié."
#: doc/classes/Polygon2D.xml
msgid "Sets the path to the node associated with the specified bone."
@@ -54589,6 +57935,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr "Change l'octet à la position donnée."
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr "Tris les éléments du tableau dans l'ordre croissant."
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -54599,7 +57952,6 @@ msgstr ""
"nouveau [PoolByteArray]. Chaque index négatif partira de la fin du tableau."
#: doc/classes/PoolColorArray.xml
-#, fuzzy
msgid "A pooled array of [Color]s."
msgstr "Un tableau compacté de [Color]."
@@ -54764,9 +58116,8 @@ msgid "Changes the int at the given index."
msgstr "Modifie le [int] à l’index donné."
#: doc/classes/PoolRealArray.xml
-#, fuzzy
msgid "A pooled array of real numbers ([float])."
-msgstr "Un tableau compacté de flottants ([float])."
+msgstr "Un tableau compacté de nombres réels (des flottants, [float])."
#: doc/classes/PoolRealArray.xml
msgid ""
@@ -54845,7 +58196,6 @@ msgid "Changes the float at the given index."
msgstr "Change la flottant à la position donnée."
#: doc/classes/PoolStringArray.xml
-#, fuzzy
msgid "A pooled array of [String]s."
msgstr "Un tableau compacté de [String]."
@@ -54924,7 +58274,6 @@ msgid "Changes the [String] at the given index."
msgstr "Change la [String] à la position donnée."
#: doc/classes/PoolVector2Array.xml
-#, fuzzy
msgid "A pooled array of [Vector2]s."
msgstr "Un tableau compacté de [Vector2]."
@@ -55006,7 +58355,6 @@ msgid "A pooled array of [Vector3]."
msgstr "Un tableau compacté de [Vector3]."
#: doc/classes/PoolVector3Array.xml
-#, fuzzy
msgid ""
"An array specifically designed to hold [Vector3]. Optimized for memory "
"usage, does not fragment the memory.\n"
@@ -55169,9 +58517,8 @@ msgstr ""
"[WindowDialog]."
#: doc/classes/PopupDialog.xml
-#, fuzzy
msgid "Sets a custom [StyleBox] for the panel of the [PopupDialog]."
-msgstr "[StyleBox] par défaut pour le [Button]."
+msgstr ""
#: doc/classes/PopupMenu.xml
msgid "PopupMenu displays a list of options."
@@ -55401,7 +58748,6 @@ msgid ""
msgstr ""
#: doc/classes/PopupMenu.xml
-#, fuzzy
msgid ""
"Returns the tooltip associated with the specified index [code]idx[/code]."
msgstr "Retourne l'infobulle associée avec l'index [code]idx[/code] spécifié."
@@ -55464,9 +58810,8 @@ msgid ""
msgstr ""
#: doc/classes/PopupMenu.xml
-#, fuzzy
msgid "Sets the currently focused item as the given [code]index[/code]."
-msgstr "Retourne la position du point à l'index [code]point[/code]."
+msgstr ""
#: doc/classes/PopupMenu.xml
msgid "Hides the [PopupMenu] when the window loses focus."
@@ -55556,11 +58901,10 @@ msgstr ""
"spécifié."
#: doc/classes/PopupMenu.xml
-#, fuzzy
msgid ""
"Toggles the check state of the item of the specified index [code]idx[/code]."
msgstr ""
-"Active l'état de contrôle de l'élément de l'index spécifié [code]idx[/code]."
+"Bascule l'état de contrôle de l'élément de l'index [code]idx[/code] spécifié."
#: doc/classes/PopupMenu.xml
msgid ""
@@ -55974,9 +59318,8 @@ msgid ""
msgstr ""
#: doc/classes/ProceduralSky.xml
-#, fuzzy
msgid "Amount of energy contribution from the sun."
-msgstr "Montant de la contribution énergétique du ciel."
+msgstr "La quantité de contribution énergétique du ciel."
#: doc/classes/ProceduralSky.xml
msgid "The sun's height using polar coordinates."
@@ -56228,6 +59571,16 @@ msgid ""
"specify the offset in bytes to the start of the resource pack. This is only "
"supported for .pck files."
msgstr ""
+"Charge le contenu du fichier .pck ou .zip spécifié par [code]pack[/code] "
+"dans le système de fichiers de ressources ([code]res://[/code]). Retourne "
+"[code]true[/code] en cas de succès.\n"
+"[b]Note :[/b] Si un fichier de [code]pack[/code] partage le même chemin "
+"qu'un fichier déjà dans le système de fichiers de ressources, toute "
+"tentative de charger ce fichier utilisera le fichier de [code]pack[/code] "
+"sauf si [code]replace_files[/code] est défini à [code]false[/code].\n"
+"[b]Note :[/b] Le paramètre optionnel [code]offset[/code] peut être utilisé "
+"pour spécifier le décalage en octets au début du pack de ressources. Ceci "
+"n'est pris en charge que pour les fichiers .pck."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56235,18 +59588,25 @@ msgid ""
"to the absolute, native OS [code]path[/code]. See also [method "
"globalize_path]."
msgstr ""
+"Retourne le chemin localisé (démarrant par [code]res://[/code]) "
+"correspondant au chemin [code]path[/code] absolu et natif du système "
+"d'exploitation. Voir aussi [method globalize_path]."
#: doc/classes/ProjectSettings.xml
msgid ""
"Returns [code]true[/code] if the specified property exists and its initial "
"value differs from the current value."
msgstr ""
+"Retourne [code]true[/code] si la propriété spécifiée existe et sa valeur "
+"initiale diffère de la valeur actuelle."
#: doc/classes/ProjectSettings.xml
msgid ""
"Returns the specified property's initial value. Returns [code]null[/code] if "
"the property does not exist."
msgstr ""
+"Retourne la valeur initiale de la propriété spécifiée. Retourne "
+"[code]null[/code] si la propriété n'existe pas."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56256,6 +59616,12 @@ msgid ""
"want to change project settings in exported projects, use [method "
"save_custom] to save [code]override.cfg[/code] file."
msgstr ""
+"Enregistre la configuration du fichier [code]project.godot[/code].\n"
+"[b]Note :[/b] Cette méthode est destinée à être utilisée par les greffons de "
+"l'éditeur, puisque [ProjectSettings] ne peut pas être modifié puis chargé "
+"directement dans une application lancée. Si vous voulez modifier les "
+"paramètres de projet depuis un projet exporté, utilisez [method save_custom] "
+"pour enregistrer le fichier [code]override.cfg[/code]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56265,18 +59631,28 @@ msgid ""
"code] file, which is also text, but can be used in exported projects unlike "
"other formats."
msgstr ""
+"Enregistre la configuration vers un fichier personnalisé. L'extension de "
+"fichier doit être [code].godot[/code] (pour enregistrer dans le format "
+"[ConfigFile] au format texte) ou [code].binary[/code] (pour enregistrer au "
+"format binaire). Vous pouvez également enregistrer le fichier [code]override."
+"cfg[/code], qui est également au format texte, mais peut être utilisé dans "
+"des projets exportés contrairement aux autres formats."
#: doc/classes/ProjectSettings.xml
msgid ""
"Sets the specified property's initial value. This is the value the property "
"reverts to."
msgstr ""
+"Définit la valeur initiale de la propriété spécifiée. C'est cette valeur qui "
+"sera rétablie pour cette propriété."
#: doc/classes/ProjectSettings.xml
msgid ""
"Sets the order of a configuration value (influences when saved to the config "
"file)."
msgstr ""
+"Définit l'ordre d'une valeur de configuration (qui a une influence quand "
+"sauvegardée dans le fichier de configuration)."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56288,6 +59664,14 @@ msgid ""
"This can also be used to erase custom project settings. To do this change "
"the setting value to [code]null[/code]."
msgstr ""
+"Définit la valeur d'un réglage.\n"
+"[b]Exemple :[/b]\n"
+"[codeblock]\n"
+"ProjectSettings.set_setting(\"application/config/name\", \"Example\")\n"
+"/[codeblock]\n"
+"Cela peut également être utilisé pour effacer les paramètres de projet "
+"personnalisés. Pour ce faire, utilisez la valeur [code]null[/code] pour le "
+"réglage."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56312,6 +59696,9 @@ msgid ""
"(preserving the aspect ratio) when the engine starts. If [code]false[/code], "
"the engine will leave it at the default pixel size."
msgstr ""
+"Si [code]true[/code], étire l'image au lancement du jeu suivant la taille de "
+"la fenêtre (et préserve le ratio). Si [code]false[/code], l'image sera "
+"affichée par défaut suivant sa taille en pixels."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56320,6 +59707,10 @@ msgid ""
"[b]Note:[/b] Only effective if [member application/boot_splash/show_image] "
"is [code]true[/code]."
msgstr ""
+"Le chemin vers une image utilisée au lancement du jeu. Si vide, l'image avec "
+"le logo de Godot sera affichée à la place.\n"
+"[b]Note :[/b] Ne fonctionne que si [member application/boot_splash/"
+"show_image] est [code]true[/code]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56328,6 +59719,10 @@ msgid ""
"displays the plain color specified in [member application/boot_splash/"
"bg_color]."
msgstr ""
+"Si [code]true[/code], affiche l'image spécifiée dans [member application/"
+"boot_splash/image] lorsque le moteur démarre. Si [code]false[/code], affiche "
+"seulement la couleur spécifiée dans [member application/boot_splash/"
+"bg_color]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56335,6 +59730,10 @@ msgid ""
"(recommended for high-resolution artwork). If [code]false[/code], uses "
"nearest-neighbor interpolation (recommended for pixel art)."
msgstr ""
+"Si [code]true[/code], applique le filtrage linéaire pour l'étirement de "
+"l'image (recommandé pour les images à haute résolution.) Si "
+"[code]false[/code], utilise l'interpolation la plus proche (recommandée pour "
+"le pixel-art)."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56348,24 +59747,41 @@ msgid ""
"The [member application/config/use_custom_user_dir] setting must be enabled "
"for this to take effect."
msgstr ""
+"Ce dossier utilisateur est utilisé pour stocker des données persistantes (le "
+"système de fichiers [code]user://[/code]). Si laissé vide, "
+"[code]user://[/code] va pointer vers un dossier spécifique au projet suivant "
+"la configuration de Godot (voir [method OS.get_user_data_dir]). Si un nom de "
+"dossier personnalisé est défini, ce nom sera utilisé à la place, puis ajouté "
+"au dossier de données utilisateur spécifique au système (le même dossier "
+"parent que celui configuration Godot documenté dans [method OS."
+"get_user_data_dir]).\n"
+"Le paramètre [member application/config/use_custom_user_dir] doit être actif "
+"pour que cela fonctionne."
#: doc/classes/ProjectSettings.xml
msgid ""
"The project's description, displayed as a tooltip in the Project Manager "
"when hovering the project."
msgstr ""
+"La description du projet, affichée en tant qu'infobulle dans le Gestionnaire "
+"de projet quand le projet est survolé."
#: doc/classes/ProjectSettings.xml
msgid ""
"Icon used for the project, set when project loads. Exporters will also use "
"this icon when possible."
msgstr ""
+"L'icône utilisée pour le projet, défini au chargement du projet. Les "
+"exportateurs utiliseront également cette icône si possible."
#: doc/classes/ProjectSettings.xml
msgid ""
"Icon set in [code].icns[/code] format used on macOS to set the game's icon. "
"This is done automatically on start by calling [method OS.set_native_icon]."
msgstr ""
+"L'icône définit dans le format [code].icns[/code] utilisé sur macOS pour "
+"définir l'icône du jeu. Ceci est fait automatiquement au lancement en "
+"appelant [method OS.set_native_icon]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56414,12 +59830,28 @@ msgid ""
"default can impact compatibility with some external tools or plugins which "
"expect the default [code].import[/code] folder."
msgstr ""
+"Si [code]true[/code], le projet utilisera un dossier caché ([code]."
+"import[/code]) pour stocker des données spécifiques au projet (métadonnées, "
+"cache des shaders, etc.)\n"
+"Si [code]false[/code], un dossier non caché ([code]import[/code]) sera "
+"utilisé à la place.\n"
+"[b]Note :[/b] Vous devez redémarrer l'application après avoir modifié ce "
+"réglage.\n"
+"[b]Note :[/b] Changer cette valeur peut aider sur les plateformes ou avec "
+"des outils tiers où les modèles de dossier cachés ne sont pas autorisés. Il "
+"suffit de modifier ce paramètre si vous savez que votre environnement "
+"l'exige, car le changer par défaut peut impacter la compatibilité avec "
+"certains outils ou greffons externes qui s'attendent à ce que le dossier par "
+"défaut soit [code].import[/code]."
#: doc/classes/ProjectSettings.xml
msgid ""
"Icon set in [code].ico[/code] format used on Windows to set the game's icon. "
"This is done automatically on start by calling [method OS.set_native_icon]."
msgstr ""
+"L'icône définit dans le format [code].ico[/code] utilisé sur Windows pour "
+"définir l'icône du jeu. Ceci est fait automatiquement au lancement en "
+"appelant [method OS.set_native_icon]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56649,11 +60081,10 @@ msgstr ""
"ne généreront pas d'avertissements."
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"If [code]true[/code], enables warnings when the type of the default value "
"set to an exported variable is different than the specified export type."
-msgstr "Si [code]true[/code], le filtrage est activé."
+msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -56805,17 +60236,14 @@ msgstr ""
"qui n'est pas garantie d'exister dans la classe à la compilation."
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"If [code]true[/code], enables warnings when a function parameter is unused."
msgstr ""
-"Si [code]true[/code], le mouvement linéaire à travers l’axe Z est limité."
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"If [code]true[/code], enables warnings when a member variable is unused."
-msgstr "Si [code]true[/code], le filtrage est activé."
+msgstr ""
#: doc/classes/ProjectSettings.xml
msgid "If [code]true[/code], enables warnings when a signal is unused."
@@ -56905,42 +60333,57 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid "Maximum call stack in visual scripting, to avoid infinite recursion."
msgstr ""
+"Le nombre maximal de la pile d'appels dans le script visuel, pour éviter une "
+"récursion infinie."
#: doc/classes/ProjectSettings.xml
msgid ""
"Color of the contact points between collision shapes, visible when \"Visible "
"Collision Shapes\" is enabled in the Debug menu."
msgstr ""
+"La couleur des points de contact entre les formes de collision, visible "
+"lorsque \"Formes de collision visibles\" est activé dans le menu Débogage."
#: doc/classes/ProjectSettings.xml
msgid ""
"Sets whether 2D physics will display collision outlines in game when "
"\"Visible Collision Shapes\" is enabled in the Debug menu."
msgstr ""
+"Définit si la physique 2D affichera les contours de collision dans le jeu "
+"lorsque \"Formes de collision visibles\" est activé dans le menu Débogage."
#: doc/classes/ProjectSettings.xml
msgid ""
"Maximum number of contact points between collision shapes to display when "
"\"Visible Collision Shapes\" is enabled in the Debug menu."
msgstr ""
+"Le nombre maximal de points de contact entre les formes de collision à "
+"afficher lorsque \"Formes de collision visibles\" est activé dans le menu "
+"Débogage."
#: doc/classes/ProjectSettings.xml
msgid ""
"Color of the collision shapes, visible when \"Visible Collision Shapes\" is "
"enabled in the Debug menu."
msgstr ""
+"La couleur des formes de collision, visible lorsque \"Formes de collision "
+"visibles\" est activé dans le menu Débogage."
#: doc/classes/ProjectSettings.xml
msgid ""
"Color of the disabled navigation geometry, visible when \"Visible "
"Navigation\" is enabled in the Debug menu."
msgstr ""
+"La couleur de la géométrie de navigation désactivée, visible lorsque "
+"\"Navigation visible\" est activée dans le menu Débogage."
#: doc/classes/ProjectSettings.xml
msgid ""
"Color of the navigation geometry, visible when \"Visible Navigation\" is "
"enabled in the Debug menu."
msgstr ""
+"La couleur de la géométrie de navigation, visible lorsque \"Navigation "
+"visible\" est activée dans le menu Débogage."
#: doc/classes/ProjectSettings.xml
msgid "Custom image for the mouse cursor (limited to 256×256)."
@@ -57137,18 +60580,25 @@ msgid ""
"Load the previously opened VCS plugin when the editor starts up. This is set "
"to [code]true[/code] whenever a new VCS plugin is initialized."
msgstr ""
+"Charge le greffon VCS précédemment ouvert dès que l'éditeur démarre. Ceci "
+"est défini à [code]true[/code] chaque fois qu'un nouveau greffon VCS est "
+"initialisé."
#: doc/classes/ProjectSettings.xml
msgid ""
"Last loaded VCS plugin name. Used to autoload the plugin when the editor "
"starts up."
msgstr ""
+"Le dernier nom de greffon VCS chargé. Utilisé pour recharger le greffon dès "
+"que l'éditeur démarre."
#: doc/classes/ProjectSettings.xml
msgid ""
"Default value for [member ScrollContainer.scroll_deadzone], which will be "
"used for all [ScrollContainer]s unless overridden."
msgstr ""
+"La valeur par défaut pour [member ScrollContainer.scroll_deadzone], qui sera "
+"utilisé pour tous les [ScrollContainer] à moins d'être surchargé."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -57168,6 +60618,8 @@ msgid ""
"If [code]true[/code], swaps OK and Cancel buttons in dialogs on Windows and "
"UWP to follow interface conventions."
msgstr ""
+"Si [code]true[/code], échange des boutons OK et Annuler dans les dialogues "
+"sur Windows et UWP pour suivre les conventions d'interface."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -57180,6 +60632,8 @@ msgid ""
"Path to a custom [Font] resource to use as default for all GUI elements of "
"the project."
msgstr ""
+"Le chemin vers une [Font] personnalisée à utiliser par défaut pour tous les "
+"éléments graphiques du projet."
#: doc/classes/ProjectSettings.xml
msgid "If [code]true[/code], makes sure the theme used works with HiDPI."
@@ -57383,208 +60837,278 @@ msgid ""
"If [code]true[/code], sends mouse input events when tapping or swiping on "
"the touchscreen."
msgstr ""
+"Si [code]true[/code], envoie des événements d'entrée de la souris lorsque "
+"vous tapez ou glissez sur l'écran tactile."
#: doc/classes/ProjectSettings.xml
msgid ""
"If [code]true[/code], sends touch input events when clicking or dragging the "
"mouse."
msgstr ""
+"Si [code]true[/code], envoie des événements d'entrée tactile lorsque vous "
+"cliquez ou faites glisser la souris."
#: doc/classes/ProjectSettings.xml
msgid "Default delay for touch events. This only affects iOS devices."
msgstr ""
+"Un retard par défaut pour les événements tactiles. Cela n'affecte que les "
+"appareils iOS."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 1. If left empty, the layer will "
"display as \"Layer 1\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 1. Si vide, le "
+"calque s'affichera comme \"Calque 1\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 10. If left empty, the layer will "
"display as \"Layer 10\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 10. Si vide, la "
+"calque s'affichera comme \"Calque 10\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 11. If left empty, the layer will "
"display as \"Layer 11\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 11. Si vide, la "
+"calque s'affichera comme \"Calque 11\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 12. If left empty, the layer will "
"display as \"Layer 12\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 12. Si vide, la "
+"calque s'affichera comme \"Calque 12\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 13. If left empty, the layer will "
"display as \"Layer 13\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 13. Si vide, la "
+"calque s'affichera comme \"Calque 13\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 14. If left empty, the layer will "
"display as \"Layer 14\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 14. Si vide, la "
+"calque s'affichera comme \"Calque 14\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 15. If left empty, the layer will "
"display as \"Layer 15\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 15. Si vide, la "
+"calque s'affichera comme \"Calque 15\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 16. If left empty, the layer will "
"display as \"Layer 16\"."
msgstr ""
+"Nom facultatif pour la calque de navigation 2D numéro 16. Si vide, la calque "
+"s'affichera comme \"Calque 16\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 17. If left empty, the layer will "
"display as \"Layer 17\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 17. Si vide, la "
+"calque s'affichera comme \"Calque 17\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 18. If left empty, the layer will "
"display as \"Layer 18\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 18. Si vide, la "
+"calque s'affichera comme \"Calque 18\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 19. If left empty, the layer will "
"display as \"Layer 19\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 19. Si vide, la "
+"calque s'affichera comme \"Calque 19\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 2. If left empty, the layer will "
"display as \"Layer 2\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 2. Si vide, la "
+"calque affichera comme « calque 2 »."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 20. If left empty, the layer will "
"display as \"Layer 20\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 20. Si vide, la "
+"calque s'affichera comme \"Calque 20\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 21. If left empty, the layer will "
"display as \"Layer 21\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 21. Si vide, la "
+"calque s'affichera comme \"Calque 21\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 22. If left empty, the layer will "
"display as \"Layer 22\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 22. Si vide, la "
+"calque s'affichera comme \"Calque 22\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 23. If left empty, the layer will "
"display as \"Layer 23\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 23. Si vide, la "
+"calque s'affichera comme \"Calque 23\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 24. If left empty, the layer will "
"display as \"Layer 24\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 24. Si vide, la "
+"calque s'affichera comme \"Calque 24\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 25. If left empty, the layer will "
"display as \"Layer 25\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 25. Si vide, la "
+"calque s'affichera comme \"Calque 25\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 26. If left empty, the layer will "
"display as \"Layer 26\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 26. Si vide, la "
+"calque s'affichera comme \"Calque 26\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 27. If left empty, the layer will "
"display as \"Layer 27\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 27. Si vide, la "
+"calque s'affichera comme \"Calque 27\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 28. If left empty, the layer will "
"display as \"Layer 28\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 28. Si vide, la "
+"calque s'affichera comme \"Calque 28\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 29. If left empty, the layer will "
"display as \"Layer 29\"."
msgstr ""
+"Nom facultatif pour la calque de navigation 2D numéro 29. Si vide, la calque "
+"s'affichera comme \"Calque 29\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 3. If left empty, the layer will "
"display as \"Layer 3\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 3. Si vide, la "
+"calque s'affichera comme « calque 3 »."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 30. If left empty, the layer will "
"display as \"Layer 30\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 30. Si vide, la "
+"calque s'affichera comme \"Calque 30\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 31. If left empty, the layer will "
"display as \"Layer 31\"."
msgstr ""
+"Nom facultatif pour la calque de navigation 2D numéro 31. Si vide, la calque "
+"s'affichera comme \"Calque 31\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 32. If left empty, the layer will "
"display as \"Layer 32\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 32. Si vide, la "
+"calque s'affichera comme \"Calque 32\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 4. If left empty, the layer will "
"display as \"Layer 4\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 4. Si vide, la "
+"calque apparaîtra comme \"Calque 4\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 5. If left empty, the layer will "
"display as \"Layer 5\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 5. Si vide, le "
+"calque affichera comme \"Calque 5\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 6. If left empty, the layer will "
"display as \"Layer 6\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 6. Si vide, la "
+"calque apparaîtra comme \"Calque 6\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 7. If left empty, the layer will "
"display as \"Layer 7\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 7. Si vide, la "
+"calque s'affichera comme « calque 7 »."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 8. If left empty, the layer will "
"display as \"Layer 8\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 8. Si vide, la "
+"calque s'affichera comme \"Calque 8\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 2D navigation layer 9. If left empty, the layer will "
"display as \"Layer 9\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 2D numéro 9. Si vide, la "
+"calque s'affichera comme \"Calque 9\"."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 2D physics layer 1."
@@ -57799,192 +61323,256 @@ msgid ""
"Optional name for the 3D navigation layer 1. If left empty, the layer will "
"display as \"Layer 1\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 1. Si vide, le "
+"calque s'affichera comme \"Calque 1\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 10. If left empty, the layer will "
"display as \"Layer 10\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 10. Si vide, la "
+"calque s'affichera comme \"Calque 10\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 11. If left empty, the layer will "
"display as \"Layer 11\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 11. Si vide, la "
+"calque s'affichera comme \"Calque 11\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 12. If left empty, the layer will "
"display as \"Layer 12\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 12. Si vide, la "
+"calque s'affichera comme \"Calque 12\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 13. If left empty, the layer will "
"display as \"Layer 13\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 13. Si vide, la "
+"calque s'affichera comme \"Calque 13\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 14. If left empty, the layer will "
"display as \"Layer 14\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 14. Si vide, la "
+"calque s'affichera comme \"Calque 14\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 15. If left empty, the layer will "
"display as \"Layer 15\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 15. Si vide, la "
+"calque s'affichera comme \"Calque 15\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 16. If left empty, the layer will "
"display as \"Layer 16\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 16. Si vide, la "
+"calque s'affichera comme \"Calque 16\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 17. If left empty, the layer will "
"display as \"Layer 17\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 17. Si vide, la "
+"calque s'affichera comme \"Calque 17\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 18. If left empty, the layer will "
"display as \"Layer 18\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 18. Si vide, la "
+"calque s'affichera comme \"Calque 18\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 19. If left empty, the layer will "
"display as \"Layer 19\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 19. Si vide, la "
+"calque s'affichera comme \"Calque 19\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 2. If left empty, the layer will "
"display as \"Layer 2\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 2. Si vide, la "
+"calque affichera comme « calque 2 »."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 20. If left empty, the layer will "
"display as \"Layer 20\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 20. Si vide, la "
+"calque s'affichera comme \"Calque 20\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 21. If left empty, the layer will "
"display as \"Layer 21\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 21. Si vide, la "
+"calque s'affichera comme \"Calque 21\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 22. If left empty, the layer will "
"display as \"Layer 22\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 22. Si vide, la "
+"calque s'affichera comme \"Calque 22\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 23. If left empty, the layer will "
"display as \"Layer 23\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 23. Si vide, la "
+"calque s'affichera comme \"Calque 23\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 24. If left empty, the layer will "
"display as \"Layer 24\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 24. Si vide, la "
+"calque s'affichera comme \"Calque 24\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 25. If left empty, the layer will "
"display as \"Layer 25\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 25. Si vide, la "
+"calque s'affichera comme \"Calque 25\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 26. If left empty, the layer will "
"display as \"Layer 26\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 26. Si vide, la "
+"calque s'affichera comme \"Calque 26\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 27. If left empty, the layer will "
"display as \"Layer 27\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 27. Si vide, la "
+"calque s'affichera comme \"Calque 27\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 28. If left empty, the layer will "
"display as \"Layer 28\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 28. Si vide, la "
+"calque s'affichera comme \"Calque 28\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 29. If left empty, the layer will "
"display as \"Layer 29\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 29. Si vide, la "
+"calque s'affichera comme \"Calque 29\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 3. If left empty, the layer will "
"display as \"Layer 3\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 3. Si vide, la "
+"calque s'affichera comme « calque 3 »."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 30. If left empty, the layer will "
"display as \"Layer 30\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 30. Si vide, la "
+"calque s'affichera comme \"Calque 30\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 31. If left empty, the layer will "
"display as \"Layer 31\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 31. Si vide, la "
+"calque s'affichera comme \"Calque 31\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 32. If left empty, the layer will "
"display as \"Layer 32\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 32. Si vide, la "
+"calque s'affichera comme \"Calque 32\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 4. If left empty, the layer will "
"display as \"Layer 4\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 4. Si vide, la "
+"calque apparaîtra comme \"Calque 4\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 5. If left empty, the layer will "
"display as \"Layer 5\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 5. Si vide, le "
+"calque affichera comme \"Calque 5\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 6. If left empty, the layer will "
"display as \"Layer 6\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 6. Si vide, la "
+"calque apparaîtra comme \"Calque 6\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 7. If left empty, the layer will "
"display as \"Layer 7\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 7. Si vide, la "
+"calque s'affichera comme « calque 7 »."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 8. If left empty, the layer will "
"display as \"Layer 8\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 8. Si vide, la "
+"calque s'affichera comme \"Calque 8\"."
#: doc/classes/ProjectSettings.xml
msgid ""
"Optional name for the 3D navigation layer 9. If left empty, the layer will "
"display as \"Layer 9\"."
msgstr ""
+"Le nom optionnel pour la calque de navigation 3D numéro 9. Si vide, la "
+"calque s'affichera comme \"Calque 9\"."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 1."
@@ -58135,9 +61723,8 @@ msgid "Optional name for the 3D render layer 13."
msgstr "Le nom facultatif pour le calque 13 de rendu 3D."
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid "Optional name for the 3D render layer 14."
-msgstr "Le nom facultatif pour le calque 14 de rendu 3D"
+msgstr "Le nom facultatif pour le calque 14 de rendu 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D render layer 15."
@@ -58200,6 +61787,8 @@ 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 ""
+"Le langage de repli si une traduction n'est pas disponible dans une langue "
+"donnée. Si laissé vide, [code]en[/code] (anglais) sera utilisé."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -58218,6 +61807,9 @@ msgid ""
"Desktop override for [member logging/file_logging/enable_file_logging], as "
"log files are not readily accessible on mobile/Web platforms."
msgstr ""
+"Le surcharge du bureau pour [member logging/file_logging/enable_file_logging]"
+", car les fichiers de journaux ne sont pas facilement accessibles sur les "
+"plateformes mobiles et web."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59018,6 +62610,12 @@ msgid ""
"[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/"
"shaders/shader_compilation_mode] is [b]not[/b] [code]Synchronous[/code]."
msgstr ""
+"La valeur par défaut est une surcharge très conservatrice pour [member "
+"rendering/gles3/shaders/max_simultaneous_compiles].\n"
+"Selon les appareils spécifiques que vous ciblez, vous pouvez vouloir "
+"l'augmenter.\n"
+"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/"
+"shader_compilation_mode] n'est [b]pas[/b] à [code]Synchrone[/code]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59028,6 +62626,12 @@ msgid ""
"[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/"
"shaders/shader_compilation_mode] is [b]not[/b] [code]Synchronous[/code]."
msgstr ""
+"La valeur par défaut est une surcharge très conservatrice pour [member "
+"rendering/gles3/shaders/max_simultaneous_compiles].\n"
+"Selon les navigateurs spécifiques que vous ciblez, vous pouvez vouloir "
+"l'augmenter.\n"
+"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/"
+"shader_compilation_mode] n'est [b]pas[/b] à [code]Synchrone[/code]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59037,6 +62641,11 @@ msgid ""
"[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/"
"shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]."
msgstr ""
+"La taille maximale, en mégaoctets, que le cache de ubershader peut "
+"atteindre. Au démarrage, les entrées les moins récemment utilisées seront "
+"supprimées jusqu'à ce que la taille totale soit dans les limites.\n"
+"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/"
+"shader_compilation_mode] est défini à [code]Synchrone + Cache[/code]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59046,6 +62655,11 @@ msgid ""
"[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/"
"shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]."
msgstr ""
+"Une surcharge pour [member rendering/gles3/shaders/shader_cache_size_mb], de "
+"sorte qu'une taille maximale plus petite peut être configurée pour les "
+"plates-formes mobiles, où l'espace de stockage est plus limité.\n"
+"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/"
+"shader_compilation_mode] est défini à [code]Synchrone + Cache[/code]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59057,6 +62671,13 @@ msgid ""
"[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/"
"shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]."
msgstr ""
+"Une surcharge pour [member rendering/gles3/shaders/shader_cache_size_mb], de "
+"sorte qu'une taille maximale plus petite peut être configurée pour les "
+"plateformes web, où l'espace de stockage est plus limité.\n"
+"[b]Note :[/b] Actuellement, le caisson d'ombrage n'est généralement pas "
+"disponible sur les plateformes Web.\n"
+"[b]Note :[/b] Ce paramètre n'est utile que si [nomm rendering/gles3/shaders/"
+"shader_compilation_mode] est défini à [code]Synchrone + Cache[/code]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59106,24 +62727,33 @@ msgid ""
"Max buffer size for blend shapes. Any blend shape bigger than this will not "
"work."
msgstr ""
+"La capacité maximale de la mémoire tampon pour les formes de mélange. Toute "
+"forme de mélange plus grande que cela ne fonctionnera pas."
#: doc/classes/ProjectSettings.xml
msgid ""
"Max buffer size for drawing polygons. Any polygon bigger than this will not "
"work."
msgstr ""
+"La capacity maximale de la mémoire tampon pour dessiner des polygones. Tout "
+"polygone plus grand que cela ne fonctionnera pas."
#: doc/classes/ProjectSettings.xml
msgid ""
"Max index buffer size for drawing polygons. Any polygon bigger than this "
"will not work."
msgstr ""
+"La capacity maximale de la mémoire tampon pour le dessin des polygones. Tout "
+"polygone plus grand que cela ne fonctionnera pas."
#: doc/classes/ProjectSettings.xml
msgid ""
"Max buffer size for drawing immediate objects (ImmediateGeometry nodes). "
"Nodes using more than this size will not work."
msgstr ""
+"La capacity maximale de la mémoire tampon pour le dessin d'objets immédiats ("
+"les nœuds ImmediateGeometry). Les nœuds utilisant plus que cette taille ne "
+"fonctionneront pas."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59169,13 +62799,10 @@ msgid ""
msgstr ""
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the texture importer will import lossless textures "
"using the PNG format. Otherwise, it will default to using WebP."
msgstr ""
-"Si [code]true[/code], la [SpinBox] sera modifiable. Sinon, elle sera en "
-"lecture seule."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59185,6 +62812,12 @@ msgid ""
"Note that compression levels above 6 are very slow and offer very little "
"savings."
msgstr ""
+"Le niveau de compression par défaut pour le format WebP sans perte. Des "
+"niveaux plus élevés entraînent des fichiers plus petits mais une plus lente "
+"vitesse de compression. La vitesse de décompression ne dépend pas du niveau "
+"de compression. Les valeurs supportées vont de 0 à 9. Notez que les niveaux "
+"de compression supérieurs à 6 sont très lents et offrent une très petite "
+"réduction du poids du fichier."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59193,6 +62826,11 @@ msgid ""
"attributes data. Recommended to be enabled if targeting mobile devices. "
"Requires manual reimport of meshes after toggling."
msgstr ""
+"À l'importation, les données des sommets de maillage seront divisées en deux "
+"flux dans une seule mémoire tampon pour les sommets, l'une pour les données "
+"de position et l'autre pour les données d'attributs. Recommandé si vous "
+"ciblez des appareils mobiles. Nécessite de réimporter manuellement toutes "
+"les meshes après l'activation."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59204,6 +62842,14 @@ msgid ""
"A greater number of polygons can potentially cull more objects, however the "
"cost of culling calculations scales with the number of occluders."
msgstr ""
+"Détermine le nombre maximal d'occulteurs de polygones qui seront utilisés à "
+"tout moment.\n"
+"Même si vous pouvez avoir de nombreux occulteurs dans une même scène, à "
+"chaque trame, le système choisira parmi ces plus pertinents basés sur une "
+"métrique de l'espace à l'écran, afin de donner la meilleure performance "
+"globale.\n"
+"Un plus grand nombre de polygones peut potentiellement masquer plus "
+"d'objets, cependant les performances baissent avec le nombre d'occulteurs."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59213,6 +62859,12 @@ msgid ""
"choose from these the most relevant based on a screen space metric, in order "
"to give the best overall performance."
msgstr ""
+"Détermine le nombre maximal d'occulteurs de sphère qui seront utilisés à "
+"tout moment.\n"
+"Même si vous pouvez avoir de nombreux occulteurs dans une même scène, à "
+"chaque trame, le système choisira parmi ces plus pertinents basés sur une "
+"métrique de l'espace à l'écran, afin de donner la meilleure performance "
+"globale."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59223,6 +62875,12 @@ msgid ""
"It will flip named portal meshes (i.e. [code]-portal[/code]) on the initial "
"conversion to [Portal] nodes."
msgstr ""
+"La convention par défaut est de pointer vers l'extérieur (la face vers "
+"l'extérieur) de la salle source.\n"
+"Si vous construisez accidentellement votre niveau avec des portails faisant "
+"face de la mauvaise manière, ce réglage peut corriger le problème.\n"
+"Cela va inverser le maillages nommés de portail (c'est-à-dire finissant par "
+"[code]-portal[/code]) pour les nœuds [Portal]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59233,14 +62891,11 @@ msgstr ""
"[b]Note :[/b] Cela sera automatiquement désactivé dans les exports."
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"If [code]true[/code], gameplay callbacks will be sent as [code]signals[/"
"code]. If [code]false[/code], they will be sent as [code]notifications[/"
"code]."
msgstr ""
-"Si [code]true[/code], l’état de la clé est pressé. Si [code]false[/code], "
-"l’état de la clé est libéré."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59256,6 +62911,8 @@ msgid ""
"Show logs during PVS generation.\n"
"[b]Note:[/b] This will automatically be disabled in exports."
msgstr ""
+"Afficher les journaux pendant la génération du PVS.\n"
+"[b]Note :[/b] Cela sera automatiquement désactivé dans les exportations."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59564,8 +63221,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
@@ -59590,6 +63247,9 @@ msgid ""
"Lower-end override for [member rendering/quality/shadows/filter_mode] on "
"mobile devices, due to performance concerns or driver support."
msgstr ""
+"Surcharge pour les appareils bas de gamme pour [le rendu de membre/qualité/"
+"shadows/filter_mode] sur les appareils mobiles, en raison de performance "
+"plus faibles ou du support des pilotes."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -59750,6 +63410,8 @@ msgid ""
"Objects can use this signal to restrict reading of settings only to "
"situations where a change has been made."
msgstr ""
+"Les objets peuvent utiliser ce signal pour restreindre leur lecture aux "
+"seuls paramètres modifiés."
#: doc/classes/PropertyTweener.xml
msgid "Interpolates an [Object]'s property over time."
@@ -59763,6 +63425,11 @@ msgid ""
"to create [PropertyTweener]. Any [PropertyTweener] created manually will not "
"function correctly."
msgstr ""
+"[PropertyTweener] est utilisé pour interpoler une propriété dans un objet. "
+"Voir [method SceneTreeTween.tween_property] pour plus d'informations.\n"
+"[b]Note :[/b] [method SceneTreeTween.tween_property] est le seul moyen "
+"correct de créer un [PropertyTweener]. Les [PropertyTweener] créés "
+"manuellement ne fonctionneront pas correctement."
#: doc/classes/PropertyTweener.xml
msgid ""
@@ -59774,6 +63441,13 @@ msgid ""
"as_relative() #the node will move by 100 pixels to the right\n"
"[/codeblock]"
msgstr ""
+"Quand appellé, la valeur finale sera utilisée comme valeur relative. Par "
+"exemple :\n"
+"[codeblock]\n"
+"var tween = get_tree().create_tween()\n"
+"tween.tween_property(self, \"position\", Vector2.RIGHT * 100, 1)."
+"as_relative() # Le nœud sera déplacé de 100 pixels sur la droite\n"
+"/[codeblock]"
#: doc/classes/PropertyTweener.xml
msgid ""
@@ -59785,6 +63459,14 @@ msgid ""
"(200, 100)\n"
"[/codeblock]"
msgstr ""
+"Définit une valeur initiale personnalisée pour le [PropertyTweener]. Par "
+"exemple :\n"
+"[codeblock]\n"
+"var tween = get_tree().create_tween()\n"
+"tween.tween_property(self, \"position\", Vector2(200, 100), 1).from(Vector2("
+"100, 100) # Ça déplacera le nœud de la position (100, 100) jusqu'à (200, 100)"
+"\n"
+"/[codeblock]"
#: doc/classes/PropertyTweener.xml
msgid ""
@@ -59799,6 +63481,16 @@ msgid ""
"from_current()\n"
"[/codeblock]"
msgstr ""
+"Fait que ce [PropertyTweener] utilisera la valeur de propriété actuelle "
+"(c'est-à-dire au moment de créer ce [PropertyTweener]) comme point de "
+"départ. Ceci est pareil que [method from] avec la valeur actuelle. Ces deux "
+"appels sont identiques :\n"
+"[codeblock]\n"
+"tween.tween_property(self, \"position\", Vector2(200, 100), 1).from(position)"
+"\n"
+"tween.tween_property(self, \"position\", Vector2(200, 100), 1).from_current()"
+"\n"
+"/[codeblock]"
#: doc/classes/PropertyTweener.xml
msgid ""
@@ -59809,9 +63501,8 @@ msgstr ""
"interpolation. Par défaut, il n'y a pas de délai."
#: doc/classes/ProximityGroup.xml
-#, fuzzy
msgid "General-purpose 3D proximity detection node."
-msgstr "Nœud de détection de proximité pour usage général."
+msgstr "Un nœud de détection de proximité 3D pour un usage général."
#: doc/classes/ProximityGroup.xml
msgid ""
@@ -59883,11 +63574,16 @@ msgid ""
"If the [member dispatch_mode] is set to [constant MODE_PROXY] (the default), "
"all calls are delegated to their respective parent [Node]."
msgstr ""
+"Appelle la méthode et les paramètres donnés à tous les [ProximityGroup] qui "
+"s'intersectent.\n"
+"Si le [member dispatch_mode] est [constant MODE_PROXY] (par défaut), tous "
+"les appels sont délégués à leur parent [Node] respectif."
#: doc/classes/ProximityGroup.xml
msgid ""
"Specifies which node gets contacted on a call of method [method broadcast]."
msgstr ""
+"Spécifie quel nœud est contacté sur un appel de méthode [method broadcast]."
#: doc/classes/ProximityGroup.xml
msgid ""
@@ -59897,6 +63593,11 @@ msgid ""
"proximity checks at the cost of performance, since more groups will be "
"created."
msgstr ""
+"La taille de l'espace en unités 3D. Cela définit également la quantité de "
+"coordonnées requises pour calculer si deux nœuds [ProximityGroup] sont en "
+"intersection ou non. Des valeurs plus petites de [member grid_radius] "
+"peuvent être utilisées pour des vérifications de proximité plus précises "
+"mais avec de moins bonnes performances, car plus de groupes seront créés."
#: doc/classes/ProximityGroup.xml
msgid ""
@@ -59923,13 +63624,15 @@ msgstr ""
#: doc/classes/ProximityGroup.xml
msgid "This [ProximityGroup]'s parent will be target of [method broadcast]."
-msgstr ""
+msgstr "Le parent de ce [ProximityGroup] sera la cible de [method broadcast]."
#: doc/classes/ProximityGroup.xml
msgid ""
"This [ProximityGroup] will emit the [signal broadcast] [i]signal[/i] when "
"calling the [method broadcast] [i]method[/i]."
msgstr ""
+"Ce [ProximityGroup] émettra le [i]signal[/i] [signal broadcast] lors de "
+"l'appel de la [i]méthode[/i] [method broadcast]."
#: doc/classes/QuadMesh.xml
msgid "Class representing a square mesh."
@@ -59992,9 +63695,8 @@ msgstr ""
"spécifié. L'axe doit être un vecteur normalisé."
#: doc/classes/Quat.xml
-#, fuzzy
msgid "Constructs a quaternion defined by the given values."
-msgstr "Construit une nouvelle chaîne de caractères à partir du [Plane] donné."
+msgstr ""
#: doc/classes/Quat.xml
msgid ""
@@ -60012,6 +63714,9 @@ msgid ""
"code], this vector, [code]b[/code], and [code]post_b[/code], by the given "
"amount [code]weight[/code]."
msgstr ""
+"Exécute une interpolation sphérique cubique entre les quaternions "
+"[code]pre_a[/code], ce vecteur, [code]b[/code], et [code]post_b[/code], par "
+"la quantité [code]weight[/code] spécifiée."
#: doc/classes/Quat.xml
msgid "Returns the dot product of two quaternions."
@@ -60024,6 +63729,10 @@ msgid ""
"quaternion. Returned vector contains the rotation angles in the format (X "
"angle, Y angle, Z angle)."
msgstr ""
+"Retourne les angles d'Euler (selon la convention YXZ : lors de la "
+"décomposition, d'abord Z, puis X, et enfin Y) correspondant à la rotation "
+"représentée par un quaternion d'unité. Le vecteur retourné contient les "
+"angles de rotation dans le format (angle X, angle Y, angle Z)."
#: doc/classes/Quat.xml
msgid "Returns the inverse of the quaternion."
@@ -60060,6 +63769,8 @@ msgid ""
"Sets the quaternion to a rotation which rotates around axis by the specified "
"angle, in radians. The axis must be a normalized vector."
msgstr ""
+"Définit le quaternion avec une rotation qui tourne autour de l'axe par "
+"l'angle spécifié, en radians. L'axe doit être un vecteur normalisé."
#: doc/classes/Quat.xml
msgid ""
@@ -60067,6 +63778,9 @@ msgid ""
"convention: when decomposing, first Z, then X, and Y last), given in the "
"vector format as (X angle, Y angle, Z angle)."
msgstr ""
+"Définit le quaternion avec une rotation spécifiée par les angles d'Euler ("
+"selon la convention YXZ : lors de la décomposition, d'abord Z, puis X, et "
+"enfin Y), donnée dans le format vectoriel comme (angle X, angle Y, angle Z)."
#: doc/classes/Quat.xml
msgid ""
@@ -60074,6 +63788,10 @@ msgid ""
"quaternion and [code]to[/code] by amount [code]weight[/code].\n"
"[b]Note:[/b] Both quaternions must be normalized."
msgstr ""
+"Retourne le résultat de l'interpolation linéaire sphérique entre ce "
+"quaternion et [code]to[/code] par la quantité [code]weight[/code] spécifiée."
+"\n"
+"[b]Note :[/b] Les deux quaternions doivent être normalisés."
#: doc/classes/Quat.xml
msgid ""
@@ -60081,6 +63799,9 @@ msgid ""
"quaternion and [code]to[/code] by amount [code]weight[/code], but without "
"checking if the rotation path is not bigger than 90 degrees."
msgstr ""
+"Retourne le résultat de l'interpolation linéaire sphérique entre ce "
+"quaternion et [code]to[/code] par la quantité [code]weight[/code] spécifiée, "
+"mais sans vérifier si la rotation n'est pas supérieure à 90 degrés."
#: doc/classes/Quat.xml
msgid "Returns a vector transformed (multiplied) by this quaternion."
@@ -60124,6 +63845,9 @@ msgid ""
"[Basis] matrix. If a vector is transformed by an identity quaternion, it "
"will not change."
msgstr ""
+"La quaternion d'identité, sans rotation. Équivalent à la matrice [Basis] "
+"d'identité. Si un vecteur est transformé par un quaternion d'identité, il ne "
+"changera pas."
#: doc/classes/RandomNumberGenerator.xml
msgid "A class for generating pseudo-random numbers."
@@ -60289,22 +64013,21 @@ msgstr ""
"avec une valeur personnalisée, utilisez plutôt [member seed]."
#: doc/classes/Range.xml
-#, fuzzy
msgid "Abstract base class for range-based controls."
-msgstr "Classe de base abstraite pour les contrôles basés sur la portée."
+msgstr "Une classe de base abstraite pour les contrôles basés sur la portée."
#: doc/classes/Range.xml
-#, fuzzy
msgid ""
"Range is a base class for [Control] nodes that change a floating-point "
"[member value] between a [member min_value] and [member max_value], using a "
"configured [member step] and [member page] size. See e.g. [ScrollBar] and "
"[Slider] for examples of higher level nodes using Range."
msgstr ""
-"Range est une classe de base des nœuds [Control] qui change une [code]value[/"
-"code] flottante entre le [code]minimum[/code] et le [code]maximum[/code], "
-"par étape [code]step[/code] et par [code]page[/code], par exemple un "
-"[ScrollBar]."
+"Range est une classe de base des nœuds [Control] qui change une "
+"[code]value[/code] flottante entre le [code]minimum[/code] et le "
+"[code]maximum[/code], par étape [code]step[/code] et par [code]page[/code], "
+"par exemple un [ScrollBar]. Voir [ScrollBar] et [Slider] pour des exemples "
+"de nœuds de haut niveau utilisant des Range."
#: doc/classes/Range.xml
msgid ""
@@ -60315,7 +64038,7 @@ msgstr ""
#: doc/classes/Range.xml
msgid "Stops the [Range] from sharing its member variables with any other."
-msgstr ""
+msgstr "Arrête le [Range] de partager ses variables membres avec les autres."
#: doc/classes/Range.xml
msgid ""
@@ -60336,6 +64059,9 @@ msgid ""
"If [code]true[/code], and [code]min_value[/code] is greater than 0, "
"[code]value[/code] will be represented exponentially rather than linearly."
msgstr ""
+"Si [code]true[/code], et [code]min_value[/code] est supérieur à 0, "
+"[code]value[/code] sera représenté de façon exponentielle plutôt que "
+"linéaire."
#: doc/classes/Range.xml
msgid ""
@@ -60359,6 +64085,9 @@ msgid ""
"multiplied by [code]page[/code] over the difference between [code]min_value[/"
"code] and [code]max_value[/code]."
msgstr ""
+"La taille de la page. Utilisé principalement pour [ScrollBar]. La longueur "
+"de la barre de défilement est multipliée par [code]page[/code] divisé par la "
+"différence entre [code]min_value[/code] et [code]max_value[/code]."
#: doc/classes/Range.xml
msgid "The value mapped between 0 and 1."
@@ -60463,12 +64192,17 @@ msgid ""
"[code]0[/code] if no object is intersecting the ray (i.e. [method "
"is_colliding] returns [code]false[/code])."
msgstr ""
+"Retourne l'identifiant de forme du premier objet que le rayon intersecte, ou "
+"[code]0[/code] si aucun objet n'intersecte le rayon (c'est-à-dire [method "
+"is_colliding] renvoie [code]false[/code])."
#: doc/classes/RayCast.xml
msgid ""
"Returns [code]true[/code] if the bit index passed is turned on.\n"
"[b]Note:[/b] Bit indices range from 0-19."
msgstr ""
+"Retourne [code]true[/code] si l'index de bit est activé.\n"
+"[b]Note :[/b] Les indices de bit vont de 0 à 19."
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid ""
@@ -60480,6 +64214,10 @@ msgid ""
"Returns the collision point at which the ray intersects the closest object.\n"
"[b]Note:[/b] This point is in the [b]global[/b] coordinate system."
msgstr ""
+"Retourne le point de collision où le rayon intersecte l'objet le plus proche."
+"\n"
+"[b]Note :[/b] Ce point se trouve dans le système de coordonnées "
+"[b]global[/b]."
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid ""
@@ -60510,21 +64248,24 @@ msgid ""
"Sets the bit index passed to the [code]value[/code] passed.\n"
"[b]Note:[/b] Bit indexes range from 0-19."
msgstr ""
+"Définit l'index de bit transmis à la [code]valeur[/code] passée.\n"
+"[b]Note :[/b] Les index de bit vont de 0-19."
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid ""
"The ray's destination point, relative to the RayCast's [code]position[/code]."
msgstr ""
+"Le point de destination du rayon, par rapport à la [code]position[/code] du "
+"RayCast."
#: doc/classes/RayCast.xml
-#, fuzzy
msgid "If [code]true[/code], collision with [Area]s will be reported."
-msgstr "Si [code]true[/code], les collisions seront signalées."
+msgstr "Si [code]true[/code], les collisions avec les [Area] seront signalées."
#: doc/classes/RayCast.xml
-#, fuzzy
msgid "If [code]true[/code], collision with [PhysicsBody]s will be reported."
-msgstr "Si [code]true[/code], les collisions seront signalées."
+msgstr ""
+"Si [code]true[/code], les collisions avec les [PhysicsBody] seront signalées."
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid ""
@@ -60557,11 +64298,12 @@ msgid "If [code]true[/code], collisions will be reported."
msgstr "Si [code]true[/code], les collisions seront signalées."
#: doc/classes/RayCast.xml
-#, fuzzy
msgid ""
"If [code]true[/code], collisions will be ignored for this RayCast's "
"immediate parent."
-msgstr "Si [code]true[/code], les collisions seront signalées."
+msgstr ""
+"Si [code]true[/code], les collisions seront ignorées avec le parent direct "
+"de ce RayCast."
#: doc/classes/RayCast2D.xml
msgid ""
@@ -60587,6 +64329,8 @@ msgid ""
"Sets or clears individual bits on the collision mask. This makes selecting "
"the areas scanned easier."
msgstr ""
+"Définit ou efface des bits individuels sur le masque de collision. Cela "
+"facilite le choix des aires scannées."
#: doc/classes/RayCast2D.xml
msgid "If [code]true[/code], collision with [Area2D]s will be reported."
@@ -60618,6 +64362,10 @@ msgid ""
"itself from whatever is touching its far endpoint. It's often useful for "
"characters."
msgstr ""
+"Une forme en rayon pour les collisions en 3D, qui peuvt être placée dans un "
+"[PhysicsBody] ou une [Area]. Un rayon n'est pas vraiment un corps de "
+"collision ; il tente plutôt de se séparer de ce qui touche son point "
+"d'extrémité lointain. Il est souvent utile pour les caractères."
#: doc/classes/RayShape.xml doc/classes/RayShape2D.xml
msgid "The ray's length."
@@ -60639,11 +64387,13 @@ msgid ""
"it tries to separate itself from whatever is touching its far endpoint. It's "
"often useful for characters."
msgstr ""
+"Une forme en rayon pour les collisions 2D. Un rayon n'est pas vraiment un "
+"corps de collision ; il tente plutôt de se séparer de ce qui touche son "
+"point d'extrémité lointain. Il est souvent utile pour les caractères."
#: doc/classes/Rect2.xml
-#, fuzzy
msgid "2D axis-aligned bounding box."
-msgstr "Boîte de délimitation alignée sur l'axe."
+msgstr "La boîte de délimitation 2D alignée sur les axes."
#: doc/classes/Rect2.xml
msgid ""
@@ -60671,6 +64421,9 @@ msgid ""
"top-left corner is the origin and [code]width[/code] and [code]height[/code] "
"are positive."
msgstr ""
+"Retourne un [Rect2] avec la même position et aire, modifié de sorte que le "
+"coin supérieur gauche est l'origine et [code]width[/code] et "
+"[code]height[/code] soient positifs."
#: doc/classes/Rect2.xml
msgid "Returns the intersection of this [Rect2] and b."
@@ -60692,11 +64445,19 @@ msgid ""
"var rect2 = rect.expand(Vector2(0, -1))\n"
"[/codeblock]"
msgstr ""
+"Retourne une copie de ce [Rect2] élargi pour inclure le point donné.\n"
+"[b]Exemple :[/b]\n"
+"[codeblock]\n"
+"# position (-3, 2), size (1, 1)\n"
+"var rect = Rect2(Vector2(-3, 2), Vector2(1, 1))\n"
+"# position (-3, -1), size (3, 4), contient donc à la fois `rect` et Vector2("
+"0, -1)\n"
+"var rect2 = rect.expand(Vector2(0, -1))\n"
+"/[codeblock]"
#: doc/classes/Rect2.xml
-#, fuzzy
msgid "Returns the area of the [Rect2]. See also [method has_no_area]."
-msgstr "Retourne la zone du [Rect2]."
+msgstr "Retourne l'aire du [Rect2]. Voir aussi [method has_no_area]."
#: doc/classes/Rect2.xml
msgid ""
@@ -60711,12 +64472,16 @@ msgid ""
"Returns a copy of the [Rect2] grown a given amount of units towards all the "
"sides."
msgstr ""
+"Retourne une copie du [Rect2] aggrandi par une quantité donnée d'unités vers "
+"tous les côtés."
#: doc/classes/Rect2.xml
msgid ""
"Returns a copy of the [Rect2] grown a given amount of units towards each "
"direction individually."
msgstr ""
+"Retourne une copie du [Rect2] aggrandi par une quantité donnée d'unités vers "
+"chaque direction individuellement."
#: doc/classes/Rect2.xml
msgid ""
@@ -60733,6 +64498,10 @@ msgid ""
"[b]Note:[/b] If the [Rect2] has a negative size and is not flat or empty, "
"[method has_no_area] will return [code]true[/code]."
msgstr ""
+"Retourne [code]true[/code] si le [Rect2] est plat ou vide, ou "
+"[code]false[/code] sinon. Voir aussi [method get_area].\n"
+"[b]Note :[/b] Si le [Rect2] a une taille négative et n'est pas plat ou vide, "
+"[method has_no_area] retournera [code]true[/code]."
#: doc/classes/Rect2.xml
msgid ""
@@ -60751,6 +64520,11 @@ msgid ""
"If [code]include_borders[/code] is [code]true[/code], they will also be "
"considered overlapping if their borders touch, even without intersection."
msgstr ""
+"Retourne [code]true[/code] si le [Rect2] se chevauche avec [code]b[/code] "
+"(c'est-à-dire qu'ils ont au moins un point en commun).\n"
+"Si [code]include_borders[/code] est [code]true[/code], ils seront également "
+"considérés comme se chevauchant si leurs bordures touchent, même sans "
+"intersection."
#: doc/classes/Rect2.xml
msgid ""
@@ -60758,6 +64532,9 @@ msgid ""
"approximately equal, by calling [code]is_equal_approx[/code] on each "
"component."
msgstr ""
+"Retourne [code]true[/code] si ce [Rect2] et [code]rect[/code] sont "
+"approximativement égaux, en appelant [code]is_equal_approx[/code] sur chaque "
+"composant."
#: doc/classes/Rect2.xml
msgid "Returns a larger [Rect2] that contains this [Rect2] and [code]b[/code]."
@@ -60774,12 +64551,16 @@ msgid ""
"Rectangle shape for 2D collisions. This shape is useful for modeling box-"
"like 2D objects."
msgstr ""
+"Une forme rectangulaire pour les collisions 2D. Cette forme est utile pour "
+"les objets 2D de type boîte."
#: doc/classes/RectangleShape2D.xml
msgid ""
"The rectangle's half extents. The width and height of this shape is twice "
"the half extents."
msgstr ""
+"La demi-taille du rectangle. La largeur et la hauteur de cette forme sont "
+"deux fois plus grandes."
#: doc/classes/Reference.xml
msgid "Base class for reference-counted objects."
@@ -60808,6 +64589,9 @@ msgid ""
"what you are doing.\n"
"Returns whether the initialization was successful."
msgstr ""
+"Initialise le compteur de référence interne. Utilisez ceci seulement si vous "
+"savez vraiment ce que vous faites.\n"
+"Retourne si l'initialisation a été réussie."
#: doc/classes/Reference.xml
msgid ""
@@ -60816,6 +64600,10 @@ msgid ""
"Returns [code]true[/code] if the increment was successful, [code]false[/"
"code] otherwise."
msgstr ""
+"Augmente le compteur de référence interne. Utilisez ceci seulement si vous "
+"savez vraiment ce que vous faites.\n"
+"Retourne [code]true[/code] si l'augmentation a réussi, [code]false[/code] "
+"sinon."
#: doc/classes/Reference.xml
msgid ""
@@ -60824,6 +64612,10 @@ msgid ""
"Returns [code]true[/code] if the decrement was successful, [code]false[/"
"code] otherwise."
msgstr ""
+"Diminue le compteur de référence interne. Utilisez ceci seulement si vous "
+"savez vraiment ce que vous faites.\n"
+"Retourne [code]true[/code] si la diminution a réussi, [code]false[/code] "
+"sinon."
#: doc/classes/ReferenceRect.xml
msgid "Reference frame for GUI."
@@ -60836,6 +64628,10 @@ msgid ""
"display a rectangle filled with a solid color, consider using [ColorRect] "
"instead."
msgstr ""
+"Une boîte rectangulaire qui n'affiche que la couleur [member border_color] "
+"sur ses bordures. [ReferenceRect] n'a pas de [Color] de remplissage. Si vous "
+"devez afficher un rectangle rempli avec une couleur, utilisez plutôt "
+"[ColorRect]."
#: doc/classes/ReferenceRect.xml
msgid "Sets the border [Color] of the [ReferenceRect]."
@@ -60846,19 +64642,24 @@ msgid ""
"Sets the border width of the [ReferenceRect]. The border grows both inwards "
"and outwards with respect to the rectangle box."
msgstr ""
+"Définit la largeur de la bordure du [ReferenceRect]. La bordure va à la fois "
+"vers l'intérieur et vers l'extérieur par rapport aux limites du rectangle."
#: doc/classes/ReferenceRect.xml
msgid ""
"If set to [code]true[/code], the [ReferenceRect] will only be visible while "
"in editor. Otherwise, [ReferenceRect] will be visible in game."
msgstr ""
+"Si définit à [code]true[/code], le [ReferenceRect] ne sera visible que dans "
+"l'éditeur. Sinon, [ReferenceRect] sera aussi visible dans le jeu."
#: doc/classes/ReflectionProbe.xml
-#, fuzzy
msgid ""
"Captures its surroundings to create fast, accurate reflections from a given "
"point."
-msgstr "Capture son environnement pour créer des réflexions."
+msgstr ""
+"Capture son environnement pour créer des réflexions rapides et précises "
+"depuis un point donné."
#: doc/classes/ReflectionProbe.xml
msgid ""
@@ -60934,6 +64735,8 @@ msgid ""
"Sets the ambient light color to be used when this probe is set to [member "
"interior_enable]."
msgstr ""
+"Définit la couleur de la lumière ambiante à utiliser lorsque cette sonde est "
+"définie à [membrer interior_enable]."
#: doc/classes/ReflectionProbe.xml
msgid ""
@@ -60941,22 +64744,25 @@ msgid ""
"light for this reflection probe when set to [member interior_enable]. Useful "
"so that ambient light matches the color of the room."
msgstr ""
+"Définit la valeur de contribution pour la quantité de lumière ambiante "
+"affectée par la réflexion pour cette sonde que [member interior_enable] est "
+"activé. Utile pour que la lumière ambiante corresponde à la couleur de la "
+"pièce."
#: doc/classes/ReflectionProbe.xml
msgid ""
"Sets the energy multiplier for this reflection probe's ambient light "
"contribution when set to [member interior_enable]."
msgstr ""
+"Définit le multiplicateur d'énergie pour cette sonde de réflexion de la "
+"lumière ambiante quand défini à [member interior_enable]."
#: doc/classes/ReflectionProbe.xml
-#, fuzzy
msgid ""
"If [code]true[/code], reflections will ignore sky contribution. Ambient "
"lighting is then controlled by the [code]interior_ambient_*[/code] "
"properties."
msgstr ""
-"Retourne la profondeur de la texture. La profondeur est la 3ème dimension "
-"(généralement l'axe Z)."
#: doc/classes/ReflectionProbe.xml
msgid ""
@@ -61504,9 +65310,8 @@ msgid ""
msgstr ""
#: doc/classes/ResourceImporter.xml
-#, fuzzy
msgid "Base class for the implementation of core resource importers."
-msgstr "Classe de base pour une implémentation d’interface AR / VR."
+msgstr ""
#: doc/classes/ResourceImporter.xml
msgid ""
@@ -61520,9 +65325,8 @@ msgid "Import plugins"
msgstr "Importer des plugins"
#: doc/classes/ResourceImporter.xml
-#, fuzzy
msgid "The default import order."
-msgstr "La police par défaut du thème."
+msgstr ""
#: doc/classes/ResourceImporter.xml
msgid ""
@@ -61545,13 +65349,10 @@ msgid ""
msgstr ""
#: doc/classes/ResourceInteractiveLoader.xml
-#, fuzzy
msgid ""
"Returns the loaded resource if the load operation completed successfully, "
"[code]null[/code] otherwise."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères commence par la chaîne "
-"de caractères donnée, ou [code]false[/code] le cas échéant."
#: doc/classes/ResourceInteractiveLoader.xml
msgid ""
@@ -61953,9 +65754,8 @@ msgid ""
msgstr ""
#: doc/classes/RichTextLabel.xml
-#, fuzzy
msgid "Returns the current selection text. Does not include BBCodes."
-msgstr "Retourne le numéro de la ligne actuelle."
+msgstr ""
#: doc/classes/RichTextLabel.xml
msgid ""
@@ -62251,24 +66051,20 @@ msgid "Makes text fill width."
msgstr "Rempli le texte en largeur."
#: doc/classes/RichTextLabel.xml
-#, fuzzy
msgid "Aligns top of the inline image to the top of the text."
-msgstr "La hauteur de la boite mesuré depuis son centre."
+msgstr ""
#: doc/classes/RichTextLabel.xml
-#, fuzzy
msgid "Aligns center of the inline image to the center of the text."
-msgstr "Aligne les enfants avec le centre du conteneur."
+msgstr ""
#: doc/classes/RichTextLabel.xml
-#, fuzzy
msgid "Aligns bottom of the inline image to the baseline of the text."
-msgstr "La hauteur de la boite mesuré depuis son centre."
+msgstr ""
#: doc/classes/RichTextLabel.xml
-#, fuzzy
msgid "Aligns bottom of the inline image to the bottom of the text."
-msgstr "Aligne les enfants avec le centre du conteneur."
+msgstr ""
#: doc/classes/RichTextLabel.xml
msgid "Each list item has a number marker."
@@ -62349,7 +66145,6 @@ msgid "The default text font."
msgstr "La police par défaut du texte."
#: doc/classes/RichTextLabel.xml
-#, fuzzy
msgid "The background used when the [RichTextLabel] is focused."
msgstr "L'arrière-plan utilisé quand le [RichTextLabel] a le focus."
@@ -62491,16 +66286,15 @@ msgid "Locks the specified linear or rotational axis."
msgstr "Verrouille l'axe linéaire et de rotation spécifié."
#: doc/classes/RigidBody.xml
-#, fuzzy
msgid ""
"Damps the body's rotational forces. If this value is different from -1.0 it "
"will be added to any angular damp derived from the world or areas.\n"
"See [member ProjectSettings.physics/3d/default_angular_damp] for more "
"details about damping."
msgstr ""
-"La vitesse à laquelle les objets arrêtent de tourner dans cette zone. "
-"Représente la vitesse angulaire perdue par seconde.\n"
-"Voir [membre ProjectSettings.physics/2d/default_angular_damp] pour plus de "
+"Amortit les forces de rotation du corps. Si cette valeur est différente de -"
+"1.0, elle sera ajoutée aux amortissements obtenues du monde et des aires.\n"
+"Voir [membre ProjectSettings.physics/3d/default_angular_damp] pour plus de "
"détails sur l'amortissement."
#: doc/classes/RigidBody.xml
@@ -62823,9 +66617,8 @@ msgid "The body's total applied force."
msgstr "La force appliquée totale du corps."
#: doc/classes/RigidBody2D.xml
-#, fuzzy
msgid "The body's total applied torque."
-msgstr "La force appliquée totale du corps."
+msgstr "La force totale appliquée au corps."
#: doc/classes/RigidBody2D.xml
msgid ""
@@ -63387,9 +67180,8 @@ msgid "Path to an [AnimationTree] node to use as a basis for root motion."
msgstr ""
#: doc/classes/RootMotionView.xml
-#, fuzzy
msgid "The grid's cell size in 3D units."
-msgstr "La taille de cellule du TileMap."
+msgstr "La taille de cellule de la grille en unités 3D."
#: doc/classes/RootMotionView.xml
msgid "The grid's color."
@@ -63402,14 +67194,11 @@ msgid ""
msgstr ""
#: doc/classes/RootMotionView.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the grid's points will all be on the same Y coordinate "
"([i]local[/i] Y = 0). If [code]false[/code], the points' original Y "
"coordinate is preserved."
msgstr ""
-"Si [code]true[/code], l’état de la clé est pressé. Si [code]false[/code], "
-"l’état de la clé est libéré."
#: doc/classes/SceneState.xml
msgid "A script interface to a scene file's data."
@@ -63806,13 +67595,11 @@ msgid ""
msgstr ""
#: doc/classes/SceneTree.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the application automatically accepts quitting.\n"
"For mobile platforms, see [member quit_on_go_back]."
msgstr ""
-"Si [code]true[/code], l'application accepte automatiquement de se fermer. "
-"Activé par défaut.\n"
+"Si [code]true[/code], l'application accepte automatiquement de se fermer.\n"
"Pour les plateformes mobiles, voir [method set_quit_on_go_back]."
#: doc/classes/SceneTree.xml
@@ -63899,9 +67686,8 @@ msgstr ""
"les nouvelles connexions entrantes."
#: doc/classes/SceneTree.xml
-#, fuzzy
msgid "The [SceneTree]'s root [Viewport]."
-msgstr "La [Window] racine de [SceneTree]."
+msgstr "La [Viewport] racine du [SceneTree]."
#: doc/classes/SceneTree.xml
msgid ""
@@ -63939,9 +67725,8 @@ msgid ""
msgstr ""
#: doc/classes/SceneTree.xml
-#, fuzzy
msgid "Emitted whenever global menu item is clicked."
-msgstr "Émis lorsqu’un élément est sélectionné."
+msgstr "Émis quand le menu global est cliqué."
#: doc/classes/SceneTree.xml
msgid ""
@@ -63983,9 +67768,8 @@ msgid "Emitted whenever a node is removed from the [SceneTree]."
msgstr "Émit quand un nœud est retiré du [SceneTree]."
#: doc/classes/SceneTree.xml
-#, fuzzy
msgid "Emitted whenever a node is renamed."
-msgstr "Émis chaque fois qu’un nœud est renommé."
+msgstr "Émis quand un nœud est renommé."
#: doc/classes/SceneTree.xml
msgid ""
@@ -64085,7 +67869,6 @@ msgid "One-shot timer."
msgstr "Minuteur à un coup."
#: doc/classes/SceneTreeTimer.xml
-#, fuzzy
msgid ""
"A one-shot timer managed by the scene tree, which emits [signal timeout] on "
"completion. See also [method SceneTree.create_timer].\n"
@@ -64111,16 +67894,16 @@ msgstr ""
" yield(get_tree().create_timer(1.0), \"timeout\")\n"
" print(\"Minuteur terminé.\")\n"
"[/codeblock]\n"
-"Le minuteur sera automatiquement une fois terminé."
+"Le minuteur sera automatiquement une fois terminé. Pour garder le minuteur, "
+"vous pouvez maintenir une référence vers lui. Voir [Reference]."
#: doc/classes/SceneTreeTimer.xml
msgid "The time remaining (in seconds)."
msgstr "Le temps restant (en secondes)."
#: doc/classes/SceneTreeTimer.xml doc/classes/Timer.xml
-#, fuzzy
msgid "Emitted when the timer reaches 0."
-msgstr "Émis lorsque la minuterie atteint 0."
+msgstr "Émis quand le minuteur atteint 0."
#: doc/classes/SceneTreeTween.xml
msgid ""
@@ -64371,7 +68154,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -64411,15 +68195,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -64496,7 +68281,6 @@ msgstr ""
"[/codeblock]"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Creates and appends an [IntervalTweener]. This method can be used to create "
"delays in the tween animation, as an alternative to using the delay in other "
@@ -64526,7 +68310,7 @@ msgstr ""
"délais des autres [Tweener] ou quand il n'y a pas d'animation (dans ce cas "
"le [SceneTreeTween] se comportement comme un minuteur). [code]time[/code] "
"est le durée du délai, en secondes.\n"
-"Exemple : créer un délai de 2s dans l'exécution du code.\n"
+"Exemple : créer un délai dans l'exécution du code.\n"
"[codeblock]\n"
"# ... du code\n"
"yield(create_tween().tween_interval(2), \"finished\")\n"
@@ -64600,7 +68384,6 @@ msgstr ""
"[/codeblock]"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Creates and appends a [PropertyTweener]. This method tweens a "
"[code]property[/code] of an [code]object[/code] between an initial value and "
@@ -64642,14 +68425,14 @@ msgstr ""
"tween.tween_property($Sprite, \"position\", Vector2(200, 300), 1)\n"
"[/codeblock]\n"
"déplacera la sprite de sa position actuelle à la position (100, 200) puis "
-"ensuite à (200, 300). Si vous utilisez [method PropertyTweener.from] ou "
-"[method PropertyTweener.from_current], la position de départ sera celle "
+"ensuite à (200, 300). Si vous utilisez [method PropertyTweener.from] ou ["
+"method PropertyTweener.from_current], la position de départ sera celle "
"spécifiée et non l'actuelle. Voir les autres méthodes de [PropertyTweener] "
"pour connaitre les possibilités.\n"
"[b]Note :[/b] Vous pouvez trouver les noms corrects des propriétés en "
"survolant ces propriétés dans l'inspecteur de Godot. Vous pouvez aussi "
-"fournir un seul composant de cette propriété directement en utilisant "
-"[code]\"property:component\"[/code] (ex. [code]position:x[/code]), alors "
+"fournir un seul composant de cette propriété directement en utilisant [code]"
+"\"property:component\"[/code] (ex. [code]position:x[/code]), alors "
"l'interpolation ne se fera que sur cet unique composant.\n"
"Exemple : déplacer un objet deux fois depuis la même position vers "
"différentes positions, avec différents types de transition.\n"
@@ -64697,11 +68480,10 @@ msgid "If [SceneTree] is paused, the [SceneTreeTween] will also pause."
msgstr "Si le [SceneTree] est en pause, le [SceneTreeTween] le sera aussi."
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"The [SceneTreeTween] will process regardless of whether [SceneTree] is "
"paused."
-msgstr "Arrête la mise à jour quand le [SceneTree] est en pause."
+msgstr ""
#: doc/classes/Script.xml
msgid "A class stored as a resource."
@@ -65037,7 +68819,6 @@ msgid ""
msgstr ""
#: doc/classes/Shader.xml
-#, fuzzy
msgid "A custom shader program."
msgstr "Un programme de shader personnalisé."
@@ -65387,9 +69168,8 @@ msgid ""
msgstr ""
#: doc/classes/Skeleton.xml
-#, fuzzy
msgid "Sets the pose transform for bone [code]bone_idx[/code]."
-msgstr "Définit le décalage à partir de [code]0.5[/code]."
+msgstr ""
#: doc/classes/Skeleton.xml
msgid "Sets the rest transform for bone [code]bone_idx[/code]."
@@ -65729,14 +69509,12 @@ msgid ""
msgstr ""
#: doc/classes/SoftBody.xml
-#, fuzzy
msgid "Returns local translation of a vertex in the surface array."
-msgstr "Renvoie la matrice de transformation d’une forme dans une zone."
+msgstr ""
#: doc/classes/SoftBody.xml
-#, fuzzy
msgid "Returns [code]true[/code] if vertex is set to pinned."
-msgstr "Retourne [code]true[/code] si l'[AABB] est plate ou vide."
+msgstr ""
#: doc/classes/SoftBody.xml
msgid ""
@@ -65772,13 +69550,10 @@ msgid "[NodePath] to a [CollisionObject] this SoftBody should avoid clipping."
msgstr ""
#: doc/classes/SoftBody.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the [SoftBody] is simulated in physics. Can be set to "
"[code]false[/code] to pause the physics simulation."
msgstr ""
-"Si [code]true[/code], l’état de la clé est pressé. Si [code]false[/code], "
-"l’état de la clé est libéré."
#: doc/classes/SoftBody.xml
msgid "If [code]true[/code], the [SoftBody] will respond to [RayCast]s."
@@ -66048,11 +69823,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr "La [Transform] globale de ce nœud."
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -66480,7 +70274,6 @@ msgstr ""
"à un point donné."
#: doc/classes/SpatialMaterial.xml
-#, fuzzy
msgid ""
"Forces a conversion of the [member albedo_texture] from sRGB space to linear "
"space."
@@ -66672,11 +70465,10 @@ msgid ""
msgstr ""
#: doc/classes/SpatialMaterial.xml
-#, fuzzy
msgid ""
"If [code]true[/code], enables the vertex grow setting. See [member "
"params_grow_amount]."
-msgstr "Si [code]true[/code], active le drapeau spécifié."
+msgstr ""
#: doc/classes/SpatialMaterial.xml
msgid "Grows object vertices in the direction of their normals."
@@ -66963,9 +70755,8 @@ msgid "Texture specifying per-pixel depth."
msgstr "La texture spécifiant la profondeur par pixel."
#: doc/classes/SpatialMaterial.xml
-#, fuzzy
msgid "Texture specifying per-pixel subsurface scattering."
-msgstr "La texture spécifiant par pixel de diffusion souterraine."
+msgstr "La texture spécifiant la transluminescence par pixel."
#: doc/classes/SpatialMaterial.xml
msgid "Texture specifying per-pixel transmission color."
@@ -67177,10 +70968,9 @@ msgstr ""
"emission_texture]."
#: doc/classes/SpatialMaterial.xml
-#, fuzzy
msgid "Use alpha scissor. Set by [member params_use_alpha_scissor]."
msgstr ""
-"Utilise un ciseau pour l'alpha. Définit par [member "
+"Utilise un ciseau pour l'opacité. Définit par [member "
"params_use_alpha_scissor]."
#: doc/classes/SpatialMaterial.xml
@@ -67604,9 +71394,8 @@ msgstr ""
"collision."
#: doc/classes/SpringArm.xml
-#, fuzzy
msgid "Returns the spring arm's current length."
-msgstr "Retourne la chaîne de caractères convertie en minuscules."
+msgstr ""
#: doc/classes/SpringArm.xml
msgid ""
@@ -67834,20 +71623,28 @@ msgstr "La taille d'un des pixels de la sprite pour définir sa taille en 3D."
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
"This is because opaque objects are not sorted, while transparent objects are "
"sorted from back to front (subject to priority)."
msgstr ""
+"Définit la priorité de rendu pour le texte. Les objets plus prioritaires "
+"seront affichés par-dessus les objets les moins prioritaites.\n"
+"[b]Note :[/b] Cela ne s'applique que si [member alpha_cut] est défini à ["
+"constant ALPHA_CUT_DISABLED] (c'est la valeur par défaut).\n"
+"[b]Note :[/b] Cela ne s'applique qu'au tri des objets transparents. Cela "
+"n'affectera pas la façon dont les objets transparents sont triés par rapport "
+"aux objets opaques. C'est parce que les objets opaques ne sont pas triés, "
+"alors que les objets transparents sont triés de l'arrière vers l'avant (et "
+"suivant leur priorité)."
#: doc/classes/SpriteBase3D.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the [Light] in the [Environment] has effects on the "
"sprite."
-msgstr "Si [code]true[/code], ce [HTTPClient] a une réponse disponible."
+msgstr ""
#: doc/classes/SpriteBase3D.xml
msgid ""
@@ -67907,13 +71704,10 @@ msgid "Removes all animations. A \"default\" animation will be created."
msgstr "Retire toutes les animations. Une animation \"défaut\" sera créée."
#: doc/classes/SpriteFrames.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the given animation is configured to loop when "
"it finishes playing. Otherwise, returns [code]false[/code]."
msgstr ""
-"Retourne [code]true[/code] si la piste donnée est importée. Sinon retourne "
-"[code]false[/code]."
#: doc/classes/SpriteFrames.xml
msgid ""
@@ -68235,9 +72029,8 @@ msgid ""
msgstr ""
#: doc/classes/StreamPeerBuffer.xml
-#, fuzzy
msgid "Data buffer stream peer."
-msgstr "Homologue de flux SSL."
+msgstr ""
#: doc/classes/StreamPeerBuffer.xml
msgid ""
@@ -68718,10 +72511,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."
@@ -69114,22 +72929,20 @@ msgstr ""
"répétitions est donné en argument."
#: doc/classes/String.xml
-#, fuzzy
msgid ""
"Replaces occurrences of a case-sensitive substring with the given one inside "
"the string."
msgstr ""
-"Remplacer les occurrences d'une sous-chaine sensible à la casse avec l'autre "
-"donnée."
+"Remplace les occurrences sensibles à la casse à l'intérieur d'une chaine par "
+"la sous-chaine donnée."
#: doc/classes/String.xml
-#, fuzzy
msgid ""
"Replaces occurrences of a case-insensitive substring with the given one "
"inside the string."
msgstr ""
-"Remplacer les occurrences d'une sous-chaine insensible à la casse avec "
-"l'autre donnée."
+"Remplace les occurrences insensibles à la casse à l'intérieur d'une chaine "
+"par la sous-chaine donnée."
#: doc/classes/String.xml
msgid ""
@@ -69445,9 +73258,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
@@ -69644,7 +73459,6 @@ msgstr ""
"[code]corner[/code] spécifié. Voir [enum Corner] pour les valeurs possibles."
#: doc/classes/StyleBoxFlat.xml
-#, fuzzy
msgid "Sets the corner radius to [code]radius[/code] pixels for all corners."
msgstr ""
"Définit le rayon d’angle sur [code]radius[/code] pixels pour tous les coins."
@@ -70380,11 +74194,11 @@ msgstr ""
"est désactivé."
#: doc/classes/TabContainer.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is hidden."
msgstr ""
-"Retourne [code]true[/code] si la piste à l'index [code]idx[/code] est active."
+"Retourne [code]true[/code] si l'onglet à l'index [code]tab_idx[/code] est "
+"masqué."
#: doc/classes/TabContainer.xml doc/classes/Tabs.xml
msgid ""
@@ -70427,12 +74241,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]."
@@ -70452,13 +74266,10 @@ msgid ""
msgstr ""
#: doc/classes/TabContainer.xml
-#, fuzzy
msgid ""
"If [code]true[/code], all tabs are drawn in front of the panel. If "
"[code]false[/code], inactive tabs are drawn behind the panel."
msgstr ""
-"Si [code]true[/code], l’état de la clé est pressé. Si [code]false[/code], "
-"l’état de la clé est libéré."
#: doc/classes/TabContainer.xml
msgid ""
@@ -70609,12 +74420,11 @@ msgid "Tabs control."
msgstr "Contrôle des onglets."
#: doc/classes/Tabs.xml
-#, fuzzy
msgid ""
"Simple tabs control, similar to [TabContainer] but is only in charge of "
"drawing tabs, not interacting with children."
msgstr ""
-"Contrôle des onglets simples, similaire à [TabContainer] mais il est "
+"Un contrôle simple des onglets, similaire à [TabContainer] mais il est "
"uniquement chargé du dessin des onglets, et non de l’interaction avec les "
"enfants."
@@ -70692,12 +74502,10 @@ msgid "Select tab at index [code]tab_idx[/code]."
msgstr "Sélectionne l'onglet à l'index [code]tab_idx[/code]."
#: doc/classes/Tabs.xml
-#, fuzzy
msgid ""
"if [code]true[/code], the mouse's scroll wheel can be used to navigate the "
"scroll view."
msgstr ""
-"Si [code]true[/code], l’état du bouton de la souris est un double-clic."
#: doc/classes/Tabs.xml
msgid "The alignment of all tabs. See [enum TabAlign] for details."
@@ -70940,9 +74748,8 @@ msgid "Returns the amount of total lines in the text."
msgstr "Retourne le nombre total de lignes dans le texte."
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid "Returns the height of a largest line."
-msgstr "Retourne la hauteur du contenu."
+msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
@@ -70953,14 +74760,12 @@ msgstr ""
"code]."
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid "Returns the number of times the given line is wrapped."
-msgstr "Renvoie le nombre de lignes visibles."
+msgstr ""
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid "Returns an array of [String]s representing each wrapped index."
-msgstr "Retourne une représentation [String] de l'évènement."
+msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
@@ -71005,19 +74810,16 @@ msgid "Returns the selection end line."
msgstr "Retourne la ligne de fin de sélection."
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid "Returns the total width of all gutters and internal padding."
-msgstr "Retourne le nombre de pistes dans l'animation."
+msgstr ""
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid "Returns the total amount of lines that could be drawn."
-msgstr "Retourne la position du contact sur le collisionneur."
+msgstr ""
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid "Returns the number of visible lines, including wrapped text."
-msgstr "Renvoie le nombre de lignes visibles."
+msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
@@ -71060,34 +74862,26 @@ msgstr ""
"marque-page."
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] when the specified [code]line[/code] has a "
"breakpoint."
msgstr ""
-"Retourne [code]true[/code] si la piste à l'index [code]idx[/code] est active."
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] when the specified [code]line[/code] is marked as "
"safe."
msgstr ""
-"Retourne [code]true[/code] si la piste à l'index [code]idx[/code] est active."
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid "Returns if the given line is wrapped."
-msgstr "Renvoie le texte de la colonne donnée."
+msgstr ""
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid ""
"Returns whether the mouse is over selection. If [code]edges[/code] is "
"[code]true[/code], the edges are considered part of the selection."
msgstr ""
-"Renvoie [code]true[/code] (vrai) si [code]a[/code] et [code]b[/code] sont "
-"approximativement égaux l'un à l'autre."
#: doc/classes/TextEdit.xml
msgid "Returns [code]true[/code] if the selection is active."
@@ -71164,13 +74958,13 @@ msgstr "Définit le texte pour la ligne spécifiée."
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
-"Ajoute un marque-page pour la ligne [code]line[/code] si [code]bookmark[/"
-"code] est [code]true[/code]. Supprime le marque-page si [code]bookmark[/"
-"code] est [code]false[/code].\n"
+"Ajoute un marque-page pour la ligne [code]line[/code] si "
+"[code]bookmark[/code] est [code]true[/code]. Supprime le marque-page si "
+"[code]bookmark[/code] est [code]false[/code].\n"
"Les marque-pages sont affichés dans [member breakpoint_gutter]."
#: doc/classes/TextEdit.xml
@@ -71236,6 +75030,10 @@ 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
+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."
@@ -71337,13 +75135,10 @@ msgid ""
msgstr ""
#: doc/classes/TextEdit.xml
-#, fuzzy
msgid ""
"If [code]true[/code], any custom color properties that have been set for "
"this [TextEdit] will be visible."
msgstr ""
-"Si [code]true[/code], les présélections de couleurs enregistrées sont "
-"visibles."
#: doc/classes/TextEdit.xml
msgid "String value of the [TextEdit]."
@@ -71493,9 +75288,8 @@ msgstr ""
"Définit le [StyleBox] de ce [TextEdit] quand [member readonly] est activé."
#: doc/classes/TextMesh.xml
-#, fuzzy
msgid "Generate an [PrimitiveMesh] from the text."
-msgstr "Générer un [TriangleMesh] à partir du maillage."
+msgstr "Génère un [PrimitiveMesh] à partir du texte."
#: doc/classes/TextMesh.xml
msgid ""
@@ -71520,9 +75314,8 @@ msgid ""
msgstr ""
#: doc/classes/TextMesh.xml
-#, fuzzy
msgid "[Font] used for the [TextMesh]'s text."
-msgstr "[Font] utilisée pour le texte du [Label]."
+msgstr "La [Font] utilisée pour le texte du [TextMesh]."
#: doc/classes/TextMesh.xml
msgid ""
@@ -71531,14 +75324,12 @@ msgid ""
msgstr ""
#: doc/classes/TextMesh.xml
-#, fuzzy
msgid "The size of one pixel's width on the text to scale it in 3D."
-msgstr "La taille d'un des pixels de la sprite pour définir sa taille en 3D."
+msgstr "La taille d'un des pixels du texte pour définir sa taille en 3D."
#: doc/classes/TextMesh.xml
-#, fuzzy
msgid "The text to generate mesh from."
-msgstr "Le type à partir duquel obtenir la constante."
+msgstr ""
#: doc/classes/Texture.xml
msgid "Texture for 2D and 3D."
@@ -71596,9 +75387,8 @@ msgid "Returns the texture width."
msgstr "Renvoie la largeur de texture."
#: doc/classes/Texture.xml
-#, fuzzy
msgid "Returns [code]true[/code] if this [Texture] has an alpha channel."
-msgstr "Retourne [code]true[/code] (vrai) si la chaîne de caractères est vide."
+msgstr ""
#: doc/classes/Texture.xml
msgid ""
@@ -71657,9 +75447,8 @@ msgid "Texture is a video surface."
msgstr "La texture est une surface vidéo."
#: doc/classes/Texture3D.xml
-#, fuzzy
msgid "Texture with 3 dimensions."
-msgstr "Retourne les dimensions de bitmap."
+msgstr ""
#: doc/classes/Texture3D.xml
msgid ""
@@ -72243,46 +76032,33 @@ msgid "Clears all values on the theme."
msgstr "Efface toutes les valeurs de ce thème."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the [Color] at [code]name[/code] if the theme has [code]node_type[/"
"code]."
-msgstr "Multiplie le transform [code]a[/code] par le transform [code]b[/code]."
+msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the constant at [code]name[/code] if the theme has [code]node_type[/"
"code]."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de "
-"la chaîne égale à [code]0[/code])."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the [Font] at [code]name[/code] if the theme has [code]node_type[/"
"code]."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de "
-"la chaîne égale à [code]0[/code])."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears the icon at [code]name[/code] if the theme has [code]node_type[/code]."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de "
-"la chaîne égale à [code]0[/code])."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Clears [StyleBox] at [code]name[/code] if the theme has [code]node_type[/"
"code]."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de "
-"la chaîne égale à [code]0[/code])."
#: doc/classes/Theme.xml
msgid ""
@@ -72305,13 +76081,10 @@ msgid "Sets the theme's values to a copy of a given theme."
msgstr "Définit les valeurs du thème à partir d'une copie d'un thème donné."
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns the [Color] at [code]name[/code] if the theme has [code]node_type[/"
"code]."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de "
-"la chaîne égale à [code]0[/code])."
#: doc/classes/Theme.xml
msgid ""
@@ -72326,13 +76099,10 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns the constant at [code]name[/code] if the theme has [code]node_type[/"
"code]."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de "
-"la chaîne égale à [code]0[/code])."
#: doc/classes/Theme.xml
msgid ""
@@ -72368,13 +76138,10 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns the icon [Texture] at [code]name[/code] if the theme has "
"[code]node_type[/code]."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de "
-"la chaîne égale à [code]0[/code])."
#: doc/classes/Theme.xml
msgid ""
@@ -72451,11 +76218,9 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns a list of all type variations for the given [code]base_type[/code]."
msgstr ""
-"Retourne l'index de l'élément avec l'identifiant [code]id[/code] spécifié."
#: doc/classes/Theme.xml
msgid ""
@@ -72475,13 +76240,10 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if this theme has a valid [member default_font] "
"value."
msgstr ""
-"Retourne [code]true[/code] si la chaîne de caractères est vide (longueur de "
-"la chaîne égale à [code]0[/code])."
#: doc/classes/Theme.xml
msgid ""
@@ -72515,13 +76277,10 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if [code]theme_type[/code] is marked as a "
"variation of [code]base_type[/code]."
msgstr ""
-"Retourne [code]true[/code] si la piste donnée est importée. Sinon retourne "
-"[code]false[/code]."
#: doc/classes/Theme.xml
msgid ""
@@ -72648,9 +76407,8 @@ msgid ""
msgstr ""
#: doc/classes/Theme.xml
-#, fuzzy
msgid "Theme's [Color] item type."
-msgstr "Le type [Color] du thème."
+msgstr "Le type de l'élément [Color] du thème."
#: doc/classes/Theme.xml
msgid "Theme's constant item type."
@@ -72819,13 +76577,10 @@ msgid ""
msgstr ""
#: doc/classes/TileMap.xml
-#, fuzzy
msgid ""
"Returns an array of all cells with the given tile index specified in "
"[code]id[/code]."
msgstr ""
-"Renvoie la texture de l’atlas de police de caractères à l’index [code]idx[/"
-"code]."
#: doc/classes/TileMap.xml
msgid "Returns a rectangle enclosing the used (non-empty) tiles of the map."
@@ -72940,9 +76695,8 @@ msgid ""
msgstr ""
#: doc/classes/TileMap.xml
-#, fuzzy
msgid "If [code]true[/code], this TileMap bakes a navigation region."
-msgstr "Si [code]true[/code], l'animation nommée existe."
+msgstr ""
#: doc/classes/TileMap.xml
#, fuzzy
@@ -72976,11 +76730,10 @@ msgstr ""
"valeurs possibles."
#: doc/classes/TileMap.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the TileMap's direct children will be drawn in order "
"of their Y coordinate."
-msgstr "Si [code]true[/code], la frontière de la ligne sera anti-aliasée."
+msgstr ""
#: doc/classes/TileMap.xml
msgid ""
@@ -73136,7 +76889,6 @@ msgid "Tile origin at its bottom-left corner."
msgstr "Origine de tuile à son coin inférieur gauche."
#: doc/classes/TileSet.xml
-#, fuzzy
msgid "Tile library for tilemaps."
msgstr "La bibliothèque des tuiles pour les cartes."
@@ -73978,7 +77730,6 @@ msgstr ""
"[InputEventAction]."
#: doc/classes/TouchScreenButton.xml
-#, fuzzy
msgid "The button's bitmask."
msgstr "Le masque binaire du bouton."
@@ -74138,13 +77889,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 ""
@@ -74389,9 +78140,8 @@ msgid "Clears the server from all translations."
msgstr "Efface le serveur de toutes les traductions."
#: doc/classes/TranslationServer.xml
-#, fuzzy
msgid "Returns an array of all loaded locales of the project."
-msgstr "Renvoie la valeur absolue du paramètre."
+msgstr ""
#: doc/classes/TranslationServer.xml
msgid ""
@@ -74634,9 +78384,8 @@ msgid ""
msgstr ""
#: doc/classes/Tree.xml
-#, fuzzy
msgid "Causes the [Tree] to jump to the specified [TreeItem]."
-msgstr "Définit la position du nœud spécifié."
+msgstr ""
#: doc/classes/Tree.xml
msgid ""
@@ -75074,13 +78823,10 @@ msgstr ""
"[code]column[/code]."
#: doc/classes/TreeItem.xml
-#, fuzzy
msgid ""
"Returns the [Texture] of the button at index [code]button_idx[/code] in "
"column [code]column[/code]."
msgstr ""
-"Rentourne [code]true[/code] (vrai) si le bouton d'index [code]button[/code] "
-"est préssé. Voir [enum JoyButtonList]."
#: doc/classes/TreeItem.xml
msgid ""
@@ -75095,13 +78841,10 @@ msgid "Returns the number of buttons in column [code]column[/code]."
msgstr "Retourne le nombre de boutons dans la colonne [code]column[/code]."
#: doc/classes/TreeItem.xml
-#, fuzzy
msgid ""
"Returns the id for the button at index [code]button_idx[/code] in column "
"[code]column[/code]."
msgstr ""
-"Rentourne [code]true[/code] (vrai) si le bouton d'index [code]button[/code] "
-"est préssé. Voir [enum JoyButtonList]."
#: doc/classes/TreeItem.xml
msgid ""
@@ -75112,9 +78855,8 @@ msgstr ""
"[code]button_idx[/code] dans la colonne [code]column[/code]."
#: doc/classes/TreeItem.xml
-#, fuzzy
msgid "Returns the column's cell mode."
-msgstr "Retourne le mode de la cellule de la colonne."
+msgstr "Retourne le mode des cellules de la colonne."
#: doc/classes/TreeItem.xml
msgid ""
@@ -75136,9 +78878,8 @@ msgid "Returns [code]true[/code] if [code]expand_right[/code] is set."
msgstr "Retourne [code]true[/code] si [code]expand_right[/code] est défini."
#: doc/classes/TreeItem.xml
-#, fuzzy
msgid "Returns the given column's icon [Texture]. Error if no icon is set."
-msgstr "Retourne l'alignement du texte de la colonne donnée."
+msgstr ""
#: doc/classes/TreeItem.xml
msgid "Returns the column's icon's maximum width."
@@ -75160,18 +78901,22 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
+"Retourne le TreeItem suivant dans l'arborescence, ou l'objet null s'il n'y "
+"en a pas."
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
msgstr ""
-"Retourne le TreeItem suivant visible dans l'arborescence ou null si aucun.\n"
+"Retourne le TreeItem voisin suivant visible dans l'arborescence, ou null si "
+"aucun.\n"
"Si [code]wrap[/code] est activé, la méthode repartira depuis le premier "
"élément visible de l'arborescence si elle est appelé sur le dernier élément, "
"sinon elle retournera [code]null[/code]."
@@ -75182,21 +78927,22 @@ msgstr "Renvoie le TreeItem parent ou un objet nul s’il n’y en a pas."
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
-"Retourne le TreeItem précédent dans l'arbre ou un objet nul s'il n'y en a "
-"pas."
+"Retourne le TreeItem précédent dans l'arborescence, ou l'objet null s'il n'y "
+"en a pas."
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
msgstr ""
-"Retourne le TreeItem précédent visible dans l'arborescence ou null si "
-"aucun.\n"
+"Retourne le TreeItem voisin précédent visible dans l'arborescence, ou null "
+"si aucun.\n"
"Si [code]wrap[/code] est activé, la méthode repartira depuis le dernier "
"élément visible de l'arborescence si elle est appelé sur le premier élément, "
"sinon elle retournera [code]null[/code]."
@@ -75278,12 +79024,10 @@ msgid "Selects the column [code]column[/code]."
msgstr "Sélectionne la colonne [code]column[/code]."
#: doc/classes/TreeItem.xml
-#, fuzzy
msgid ""
"Sets the given column's button [Texture] at index [code]button_idx[/code] to "
"[code]button[/code]."
msgstr ""
-"Déplace l’élément de l’index [code]from_idx[/code] à [code]to_idx[/code]."
#: doc/classes/TreeItem.xml
msgid ""
@@ -75583,7 +79327,6 @@ msgid ""
msgstr ""
#: doc/classes/Tween.xml
-#, fuzzy
msgid ""
"Resets all tweens to their initial values (the ones given, not those before "
"the tween)."
@@ -76697,9 +80440,8 @@ msgid "Vertical box container."
msgstr "Conteneur vertical."
#: doc/classes/VBoxContainer.xml
-#, fuzzy
msgid "Vertical box container. See [BoxContainer]."
-msgstr "Conteneur vertical. Voir [BoxContainer]."
+msgstr "Conteneur de boites vertical. Voir [BoxContainer]."
#: doc/classes/VBoxContainer.xml
msgid "The vertical space between the [VBoxContainer]'s elements."
@@ -76923,9 +80665,8 @@ msgid ""
msgstr ""
#: doc/classes/Vector2.xml doc/classes/Vector3.xml
-#, fuzzy
msgid "Returns this vector projected onto the vector [code]b[/code]."
-msgstr "Retourne le vecteur projeté sur le vecteur [code]b[/code]."
+msgstr "Retourne ce vecteur projeté sur le vecteur [code]b[/code]."
#: doc/classes/Vector2.xml
msgid ""
@@ -76934,13 +80675,12 @@ msgid ""
msgstr ""
#: doc/classes/Vector2.xml
-#, fuzzy
msgid ""
"Returns the vector rotated by [code]angle[/code] (in radians). See also "
"[method @GDScript.deg2rad]."
msgstr ""
-"Retourne le vecteur pivoté par [code]phi[/code] en radians. Voir aussi "
-"[method @GDScript.deg2rad]."
+"Retourne le vecteur pivoté par [code]angle[/code] (en radians). Voir aussi ["
+"method @GDScript.deg2rad]."
#: doc/classes/Vector2.xml doc/classes/Vector3.xml
msgid ""
@@ -77258,11 +80998,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -77343,8 +81083,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -77426,9 +81166,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]."
@@ -77543,7 +81282,6 @@ msgid ""
msgstr ""
#: modules/gdnative/doc_classes/VideoStreamGDNative.xml
-#, fuzzy
msgid "[VideoStream] resource for video formats implemented via GDNative."
msgstr ""
"La ressource [VideoStream] pour les formats vidéo implémentés via GDNative."
@@ -77699,12 +81437,10 @@ msgid "Returns the topmost modal in the stack."
msgstr "Retourne la vue exclusive la plus en avant dans la pile."
#: doc/classes/Viewport.xml
-#, fuzzy
msgid ""
"Returns the mouse's position in this [Viewport] using the coordinate system "
"of this [Viewport]."
msgstr ""
-"Retourne la position de la souris par rapport à la position de cet élément."
#: doc/classes/Viewport.xml
msgid "Returns information about the viewport from the rendering pipeline."
@@ -77715,9 +81451,8 @@ msgid "Returns the [enum ShadowAtlasQuadrantSubdiv] of the specified quadrant."
msgstr ""
#: doc/classes/Viewport.xml
-#, fuzzy
msgid "Returns the size override set with [method set_size_override]."
-msgstr "Renvoie le mode de remplacement de l’espace pour la zone."
+msgstr ""
#: doc/classes/Viewport.xml
msgid ""
@@ -77747,9 +81482,8 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-#, fuzzy
msgid "Returns [code]true[/code] if there are visible modals on-screen."
-msgstr "Retourne [code]true[/code] si la colonne donnée est cochée."
+msgstr ""
#: doc/classes/Viewport.xml
msgid "Returns [code]true[/code] if the drag operation is successful."
@@ -77812,9 +81546,8 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-#, fuzzy
msgid "If [code]true[/code], the viewport will be used in AR/VR process."
-msgstr "Si [code]true[/code], la texture sera centrée."
+msgstr ""
#: doc/classes/Viewport.xml
msgid "If [code]true[/code], the viewport will process 2D audio streams."
@@ -77976,9 +81709,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
@@ -77997,10 +81731,8 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-#, fuzzy
msgid "If [code]true[/code], the size override affects stretch as well."
msgstr ""
-"Si [code]true[/code], le mouvement linéaire à travers l’axe Z est limité."
#: doc/classes/Viewport.xml
msgid ""
@@ -78011,8 +81743,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 ""
@@ -78027,9 +81763,8 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-#, fuzzy
msgid "The custom [World] which can be used as 3D environment source."
-msgstr "Une constante [Transform], qui peut être utilisée comme nœud d’entrée."
+msgstr ""
#: doc/classes/Viewport.xml
msgid "The custom [World2D] which can be used as 2D environment source."
@@ -78130,14 +81865,12 @@ msgid "Amount of surface changes in frame."
msgstr "Le nombre de surfaces changées à chaque trame."
#: doc/classes/Viewport.xml
-#, fuzzy
msgid "Amount of draw calls in frame."
-msgstr "Le nombre d'appels d'affichage à chaque trame."
+msgstr "Le nombre d'appels de dessin à chaque trame."
#: doc/classes/Viewport.xml
-#, fuzzy
msgid "Amount of items or joined items in frame."
-msgstr "Quantité d’objets dans le cadre."
+msgstr ""
#: doc/classes/Viewport.xml
msgid "Represents the size of the [enum RenderInfo] enum."
@@ -78384,15 +82117,14 @@ msgid "This enabler will stop [Particles2D] nodes."
msgstr "Cet activateur arrêtera les nœuds [Particles2D]."
#: doc/classes/VisibilityEnabler2D.xml
-#, fuzzy
msgid "This enabler will stop the parent's [method Node._process] function."
-msgstr "Cet activateur arrêtera la fonction _process du parent."
+msgstr "Cet activateur arrêtera la fonction [method Node._process] du parent."
#: doc/classes/VisibilityEnabler2D.xml
-#, fuzzy
msgid ""
"This enabler will stop the parent's [method Node._physics_process] function."
-msgstr "Cet activateur arrêtera la fonction _physics_process du parent."
+msgstr ""
+"Cet activateur arrêtera la fonction [method Node._physics_process] du parent."
#: doc/classes/VisibilityEnabler2D.xml
msgid "This enabler will stop [AnimatedSprite] nodes animations."
@@ -78446,15 +82178,12 @@ msgid ""
msgstr ""
#: doc/classes/VisibilityNotifier.xml
-#, fuzzy
msgid "Emitted when the VisibilityNotifier enters a [Camera]'s view."
-msgstr ""
-"Émis lorsque le VisibilityNotifier3D entre dans la vue d’un [Camera3D]."
+msgstr "Émis lorsque le VisibilityNotifier entre dans la vue d’un [Camera]."
#: doc/classes/VisibilityNotifier.xml
-#, fuzzy
msgid "Emitted when the VisibilityNotifier exits a [Camera]'s view."
-msgstr "Émis lorsque le VisibilityNotifier3D quitte la vue d'un [Camera3D]."
+msgstr "Émis lorsque le VisibilityNotifier quitte la vue d'un [Camera]."
#: doc/classes/VisibilityNotifier.xml
msgid "Emitted when the VisibilityNotifier enters the screen."
@@ -78487,9 +82216,8 @@ msgid ""
msgstr ""
#: doc/classes/VisibilityNotifier2D.xml
-#, fuzzy
msgid "The VisibilityNotifier2D's bounding rectangle."
-msgstr "Rectangle englobant de VisibilityNotifier2D."
+msgstr "Le rectangle englobant du VisibilityNotifier2D."
#: doc/classes/VisibilityNotifier2D.xml
msgid "Emitted when the VisibilityNotifier2D enters the screen."
@@ -78527,6 +82255,8 @@ msgid ""
"Returns the [AABB] (also known as the bounding box) for this "
"[VisualInstance]. See also [method get_transformed_aabb]."
msgstr ""
+"Retourne le [AABB] (\"bounding box\") pour cette [VisualInstance]. Voir "
+"aussi [method get_transformed_aaabb]."
#: doc/classes/VisualInstance.xml
msgid ""
@@ -78534,6 +82264,8 @@ msgid ""
"example, if the Node is a [MeshInstance], this will return the RID of the "
"associated [Mesh]."
msgstr ""
+"Retourne le RID de la ressource associée à cette [VisualInstance]. Par "
+"exemple, si le nœud est une [MeshInstance], cela retournera le RID du [Mesh]."
#: doc/classes/VisualInstance.xml
msgid ""
@@ -78541,12 +82273,18 @@ msgid ""
"by [method VisualServer.instance_create]. This RID is needed if you want to "
"call [VisualServer] functions directly on this [VisualInstance]."
msgstr ""
+"Retourne le RID de cette instance. Ce RID est le même que le RID retourné "
+"par [method VisualServer.instance_create]. Ce RID est nécessaire si vous "
+"voulez appeler les fonctions [VisualServer] directement sur cette "
+"[VisualInstance]."
#: doc/classes/VisualInstance.xml
msgid ""
"Returns [code]true[/code] when the specified layer is enabled in [member "
"layers] and [code]false[/code] otherwise."
msgstr ""
+"Retourne [code]true[/code] si le calque spécifié est actif, ou "
+"[code]false[/code] sinon."
#: doc/classes/VisualInstance.xml
msgid ""
@@ -78555,6 +82293,11 @@ msgid ""
"Transformed in this case means the [AABB] plus the position, rotation, and "
"scale of the [Spatial]'s [Transform]. See also [method get_aabb]."
msgstr ""
+"Retourne la [AABB] (\"bounding box\") transformée pour cette "
+"[VisualInstance].\n"
+"Transformé dans ce cas veut dire la [AABB] plus sa position, la rotation et "
+"la mise à l'échelle de la [Transform] du [Spatial]. Voir aussi [method "
+"get_aabb]."
#: doc/classes/VisualInstance.xml
msgid ""
@@ -78562,6 +82305,9 @@ msgid ""
"changes how the engine handles the [VisualInstance] under the hood. "
"Equivalent to [method VisualServer.instance_set_base]."
msgstr ""
+"Définit la ressource qui est instanciée par cette [VisualInstance] qui "
+"modifie la façon dont le moteur gère la [VisualInstance] en interne. "
+"Équivalent à [method VisualServer.instance_set_base]."
#: doc/classes/VisualInstance.xml
msgid "Enables a particular layer in [member layers]."
@@ -78573,10 +82319,14 @@ msgid ""
"This object will only be visible for [Camera]s whose cull mask includes the "
"render object this [VisualInstance] is set to."
msgstr ""
+"Le(s) calque(s) de rendu où cette [VisualInstance] est dessinée.\n"
+"Cet objet ne sera visible que pour les [Camera] où le masque de cull inclut "
+"l'objet de rendu auquel [VisualInstance] est défini."
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "A script implemented in the Visual Script programming environment."
msgstr ""
+"Un script implémenté dans l'environnement de programmation Visual Script."
#: modules/visual_script/doc_classes/VisualScript.xml
msgid ""
@@ -78605,6 +82355,8 @@ msgid ""
"Add a variable to the VisualScript, optionally giving it a default value or "
"marking it as exported."
msgstr ""
+"Ajouter une variable au VisualScript, en option lui donnant une valeur par "
+"défaut ou la marquant comme exporté."
#: modules/visual_script/doc_classes/VisualScript.xml
msgid ""
@@ -78660,7 +82412,7 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "Returns the id of a function's entry point node."
-msgstr ""
+msgstr "Retourne l'identifiant d'un nœud de point d'entrée de la fonction."
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "Returns the position of the center of the screen for a given function."
@@ -78687,6 +82439,8 @@ msgid ""
"Returns the information for a given variable as a dictionary. The "
"information includes its name, type, hint and usage."
msgstr ""
+"Retourne les informations d'une variable donnée dans un dictionnaire. Les "
+"informations comprennent son nom, son type, un indice et son usage."
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "Returns whether a signal exists with the specified name."
@@ -78747,16 +82501,23 @@ msgid ""
"Unlike [method data_connect], there isn't a [code]to_port[/code], since the "
"target node can have only one sequence port."
msgstr ""
+"Connecte deux ports d'une séquence. L'exécution passera de "
+"[code]from_output[/code] de [code]from_node[/code] vers [code]to_node[/code]."
+"\n"
+"Contrairement à [method data_connect], il n'y a pas ∂e [code]to_port[/code], "
+"puisque le nœud cible ne peut avoir qu'un seul port dans la séquence."
#: modules/visual_script/doc_classes/VisualScript.xml
msgid ""
"Disconnect two sequence ports previously connected with [method "
"sequence_connect]."
msgstr ""
+"Déconnecte deux ports de séquence précédemment connectés avec [method "
+"sequence_connect]."
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "Position the center of the screen for a function."
-msgstr ""
+msgstr "Positionne le centre de l'écran sur une fonction."
#: modules/visual_script/doc_classes/VisualScript.xml
msgid "Set the base type of the script."
@@ -78787,13 +82548,15 @@ msgstr "Émis quand les ports d'un nœud ont changés."
#: modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
msgid "A Visual Script node representing a constant from the base types."
-msgstr ""
+msgstr "Un nœud Visual Script représentant une constante d'un type de base."
#: modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
msgid ""
"A Visual Script node representing a constant from base types, such as "
"[constant Vector3.AXIS_X]."
msgstr ""
+"Un nœud Visual Script représentant une constante des types de base, comme ["
+"constant Vector3.AXIS_X]."
#: modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
msgid "The type to get the constant from."
@@ -78805,7 +82568,7 @@ msgstr "Le nom de la constante à retourner."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "A Visual Script node used to call built-in functions."
-msgstr ""
+msgstr "Un nœud Visual Script utilisé pour appeler des fonctions intégrées."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid ""
@@ -78813,6 +82576,9 @@ msgid ""
"function or an utility function.\n"
"See also [@GDScript], for the same functions in the GDScript language."
msgstr ""
+"Une fonction intégrée utilisée dans un [VisualScript]. C'est généralement "
+"une fonction de mathématiques ou une fonction utilitaire.\n"
+"Voir aussi @[GDScript], pour les mêmes fonctions dans le langage GDScript."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "The function to be executed."
@@ -78859,6 +82625,8 @@ msgid ""
"Return the arc tangent of the input, using the signs of both parameters to "
"determine the exact angle."
msgstr ""
+"Retourner l'arc tangente de l'entrée, en utilisant les signes des deux "
+"paramètres pour déterminer l'angle exact."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "Return the square root of the input."
@@ -78877,6 +82645,8 @@ msgid ""
"Return the positive remainder of one input divided by the other, using "
"floating-point numbers."
msgstr ""
+"Retourner le reste positif d'une entrée divisée par l'autre, en utilisant "
+"des flottants."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "Return the input rounded down."
@@ -78899,6 +82669,8 @@ msgid ""
"Return the sign of the input, turning it into 1, -1, or 0. Useful to "
"determine if the input is positive or negative."
msgstr ""
+"Retourner le signe de l'entrée, le transformant en 1, -1, ou 0. Utile pour "
+"déterminer si l'entrée est positive ou négative."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "Return the input raised to a given power."
@@ -78909,18 +82681,26 @@ msgid ""
"Return the natural logarithm of the input. Note that this is not the typical "
"base-10 logarithm function calculators use."
msgstr ""
+"Retourner le logarithme népérien de l'entrée. Notez que ce n'est pas "
+"l'utilisation typique des calculatrices avec la fonction logarithme en "
+"base-10."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid ""
"Return the mathematical constant [b]e[/b] raised to the specified power of "
"the input. [b]e[/b] has an approximate value of 2.71828."
msgstr ""
+"Retourner la constante mathématique [b]e[/b] à la puissance spécifiée par "
+"l'entrée. [b]e[/b] a une valeur approximativement égal à 2.71828."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid ""
"Return whether the input is NaN (Not a Number) or not. NaN is usually "
"produced by dividing 0 by 0, though other ways exist."
msgstr ""
+"Retourne si l'entrée la valeur spéciale NaN qui signifie que ce n'est pas un "
+"nombre (\"Not a Number\") ou non. NaN est généralement produit en divisant 0 "
+"par 0, entre autre."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid ""
@@ -78928,6 +82708,8 @@ msgid ""
"Infinity is usually produced by dividing a number by 0, though other ways "
"exist."
msgstr ""
+"Retourne si l'entrée est un nombre flottant infini ou non. L'infini est "
+"généralement produit en divisant un nombre par 0, entre autre."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid ""
@@ -78940,7 +82722,6 @@ msgstr ""
"progressive."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
-#, fuzzy
msgid ""
"Return the number of digit places after the decimal that the first non-zero "
"digit occurs."
@@ -78950,13 +82731,16 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "Return the input snapped to a given step."
-msgstr ""
+msgstr "Retourner l'entrée arrondie à l'étape donnée la plus proche."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid ""
"Return a number linearly interpolated between the first two inputs, based on "
"the third input. Uses the formula [code]a + (a - b) * t[/code]."
msgstr ""
+"Retourner un nombre linéairement interpolé entre les deux premières entrées, "
+"basé sur la troisième entrée. Utilise la formule [code]a + (a - b) * "
+"t[/code]."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "Moves the number toward a value, based on the third input."
@@ -78983,12 +82767,17 @@ msgid ""
"N (where N is smaller than 2^32 - 1), you can use it with the remainder "
"function."
msgstr ""
+"Retourner une entier de 32 bits aléatoire. Pour obtenir une valeur aléatoire "
+"entre 0 et N (où N est plus petit que 2^32 - 1), vous pouvez l'utiliser avec "
+"la fonction modulo (retournant le reste de la division euclidienne)."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid ""
"Return a random floating-point value between 0 and 1. To obtain a random "
"value between 0 to N, you can use it with multiplication."
msgstr ""
+"Retourner un flottant aléatoire entre 0 et 1. Pour obtenir une valeur "
+"aléatoire entre 0 à N, vous pouvez multiplier cette valeur avec N."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "Return a random floating-point value between the two inputs."
@@ -79037,6 +82826,9 @@ msgid ""
"never outside it. Equivalent to [code]min(max(input, range_low), range_high)"
"[/code]."
msgstr ""
+"Retourner l'entrée limitée à l'intervalle donné, s'assurant que le résultat "
+"n'est jamais en dehors de l'intervalle. Équivalent à [code]min(max(input, "
+"minimum), maximum)[/code]."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "Return the nearest power of 2 to the input."
@@ -79059,6 +82851,8 @@ msgid ""
"Return the type of the input as an integer. Check [enum Variant.Type] for "
"the integers that might be returned."
msgstr ""
+"Retourner le type d'entrée en entier. Regardez [enum Variant.Type] pour les "
+"valeurs des entiers qui peuvent être retournés."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "Checks if a type is registered in the [ClassDB]."
@@ -79111,6 +82905,8 @@ msgid ""
"Return the [Color] with the given name and alpha ranging from 0 to 1.\n"
"[b]Note:[/b] Names are defined in [code]color_names.inc[/code]."
msgstr ""
+"Retourner la [Color] avec le nom donné et alpha allant de 0 à 1.\n"
+"[b]Note :[/b] Les noms sont définis dans [code]color_names.inc[/code]."
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid ""
@@ -79122,6 +82918,14 @@ msgid ""
"return t * t * (3.0 - 2.0 * t)\n"
"[/codeblock]"
msgstr ""
+"Retourner un nombre correctement interpolé entre les deux premières entrées, "
+"en fonction de la troisième entrée. Comme [constant MATH_LERP], mais "
+"interpole plus rapidement au début et plus lentement à la fin. Utiliser la "
+"formule d'interpolation de Hermite:\n"
+"[codeblock]\n"
+"var t = clamp((weight - from) / (to - from), 0.0, 1.0)\n"
+"return t * t * (3.0 - 2.0 * t)\n"
+"[/codeblock]"
#: modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
msgid "Represents the size of the [enum BuiltinFunc] enum."
@@ -79236,6 +83040,8 @@ msgid ""
"A Visual Script node which calls a base type constructor. It can be used for "
"type conversion as well."
msgstr ""
+"Un nœud Visual Script qui appelle un constructeur de type de base. Il peut "
+"également être utilisé pour la conversion de type."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid "A scripted Visual Script node."
@@ -79244,6 +83050,8 @@ msgstr "Un nœud Visual Script scripté."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid "A custom Visual Script node which can be scripted in powerful ways."
msgstr ""
+"Un nœud Visual Script personnalisé qui peut être scripté de plein de "
+"manières."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid "Return the node's title."
@@ -79297,6 +83105,8 @@ msgid ""
"Return the specified output port's hint. See the [enum @GlobalScope."
"PropertyHint] hints."
msgstr ""
+"Retourne l'indice du port de sortie spécifié. Voir les indices dans [enum "
+"@GlobalScope.PropertyHint]."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid "Return the specified output port's hint string."
@@ -79307,10 +83117,11 @@ msgid "Return the specified output port's name."
msgstr "Retourne le nom du port de sortie spécifié."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
-#, fuzzy
msgid ""
"Return the specified output port's type. See the [enum Variant.Type] values."
-msgstr "Représente la taille de l'énumération [enum Variant.Type]."
+msgstr ""
+"Retourne le type du port de sortie spécifié. Voir [enum Variant.Type] "
+"valeurs."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid ""
@@ -79318,6 +83129,9 @@ msgid ""
"[b]sequence[/b] port (if there is none, on the place that is usually taken "
"by it)."
msgstr ""
+"Retourne le texte du nœud personnalisé, qui est affiché juste à côté du port "
+"d'entrée [b]séquence[/b] (s'il n'y en a aucun, à l'emplacement où "
+"habituellement pris par lui)."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid ""
@@ -79350,18 +83164,24 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid "The start mode used the first time when [method _step] is called."
msgstr ""
+"Le mode de démarrage a utilisé la première fois que [method _step] est "
+"appelée."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid ""
"The start mode used when [method _step] is called after coming back from a "
"[constant STEP_PUSH_STACK_BIT]."
msgstr ""
+"Le mode de démarrage utilisé lorsque [method _step] est appelé après être "
+"revenu de [constant STEP_PUSH_STACK_BIT]."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid ""
"The start mode used when [method _step] is called after resuming from "
"[constant STEP_YIELD_BIT]."
msgstr ""
+"Le mode de démarrage utilisé lorsque [method _step] est appelé après être "
+"revenu de [constant STEP_YIELD_BIT]."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid ""
@@ -79377,6 +83197,9 @@ msgid ""
"Hint used by [method _step] to tell that control should return back, either "
"hitting a previous [constant STEP_PUSH_STACK_BIT] or exiting the function."
msgstr ""
+"L'indice utilisé par [method _step] pour dire que la commande doit revenir, "
+"soit en atteignant un précédent [constant STEP_PUSH_STACK_BIT] ou en sortant "
+"de la fonction."
#: modules/visual_script/doc_classes/VisualScriptCustomNode.xml
msgid ""
@@ -79392,11 +83215,17 @@ msgid ""
"Using this requires you to have at least one working memory slot, which is "
"used for the [VisualScriptFunctionState]."
msgstr ""
+"L'indice utilisé par [method _step] pour dire que la fonction doit être "
+"attendue.\n"
+"En utilisant cela, vous devez avoir au moins un emplacement de mémoire "
+"fonctionnel, qui est utilisé pour [VisualScriptFunctionState]."
#: modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
msgid ""
"A Visual Script node which deconstructs a base type instance into its parts."
msgstr ""
+"Un nœud Visual Script qui déconstruit une instance de type de base en ses "
+"différentes parties."
#: modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
msgid "The type to deconstruct."
@@ -79407,12 +83236,16 @@ msgid ""
"Add a custom Visual Script node to the editor. It'll be placed under "
"\"Custom Nodes\" with the [code]category[/code] as the parameter."
msgstr ""
+"Ajoute un nœud Visual Script personnalisé à l'éditeur. Il sera placé sous "
+"\"Nœuds personnalisés\" avec la [code]category[/code] en paramètre."
#: modules/visual_script/doc_classes/VisualScriptEditor.xml
msgid ""
"Remove a custom Visual Script node from the editor. Custom nodes already "
"placed on scripts won't be removed."
msgstr ""
+"Retire un nœud Visual Script personnalisé de l'éditeur. Les nœuds "
+"personnalisés déjà placés sur des scripts ne seront pas supprimés."
#: modules/visual_script/doc_classes/VisualScriptEditor.xml
msgid "Emitted when a custom Visual Script node is added or removed."
@@ -79430,6 +83263,11 @@ msgid ""
"[b]Output Ports:[/b]\n"
"- Sequence"
msgstr ""
+"Émet un signal spécifié quand il est exécuté.\n"
+"[b]Ports d'entrée :[/b]\n"
+"- Séquence : [code]emit[/code]\n"
+"[b]Ports de sortie :[/b]\n"
+"- Séquence"
#: modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
msgid "The signal to emit."
@@ -79437,16 +83275,15 @@ msgstr "Le signal à émettre."
#: modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
msgid "A Visual Script node returning a singleton from [@GlobalScope]."
-msgstr ""
+msgstr "Un nœud Visual Script retournant un singleton parmi @[GlobalScope]."
#: modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
msgid "The singleton's name."
msgstr "Le nom du singleton."
#: modules/visual_script/doc_classes/VisualScriptExpression.xml
-#, fuzzy
msgid "A Visual Script node that can execute a custom expression."
-msgstr "Un nœud Visual Script utilisé pour annoter le script."
+msgstr "Un nœud Visual Script qui peut exécuter une expression personnalisée."
#: modules/visual_script/doc_classes/VisualScriptExpression.xml
msgid ""
@@ -79467,9 +83304,8 @@ msgid ""
msgstr ""
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
-#, fuzzy
msgid "A Visual Script node for calling a function."
-msgstr "Un nœud Visual Script utilisé pour annoter le script."
+msgstr "Un nœud Visual Script pour appeler une fonction."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid ""
@@ -79483,6 +83319,8 @@ msgid ""
"The script to be used when [member call_mode] is set to [constant "
"CALL_MODE_INSTANCE]."
msgstr ""
+"Le script à utiliser lorsque [member call_mode] est défini à [constant "
+"CALL_MODE_INSTANCE]."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
#: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
@@ -79490,18 +83328,24 @@ msgid ""
"The base type to be used when [member call_mode] is set to [constant "
"CALL_MODE_INSTANCE]."
msgstr ""
+"Le type de base à utiliser lorsque [member call_mode] est défini à [constant "
+"CALL_MODE_INSTANCE]."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid ""
"The type to be used when [member call_mode] is set to [constant "
"CALL_MODE_BASIC_TYPE]."
msgstr ""
+"Le type à utiliser lorsque [member call_mode] est défini à [constant "
+"CALL_MODE_BASIC_TYPE]."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid ""
"[code]call_mode[/code] determines the target object on which the method will "
"be called. See [enum CallMode] for options."
msgstr ""
+"[code]call_mode[/code] détermine l'objet cible sur lequel la méthode sera "
+"appelée. Voir [enum CallMode] pour les options."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid "The name of the function to be called."
@@ -79513,12 +83357,16 @@ msgid ""
"The node path to use when [member call_mode] is set to [constant "
"CALL_MODE_NODE_PATH]."
msgstr ""
+"Le chemin nœud à utiliser lorsque [member call_mode] est défini à [constant "
+"CALL_MODE_NODE_PATH]."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid ""
"The mode for RPC calls. See [method Node.rpc] for more details and [enum "
"RPCCallMode] for available options."
msgstr ""
+"Le mode pour les appels RPC. Voir [method Node.rpc] pour plus de détails et ["
+"enum RPCCallMode] pour les options disponibles."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid ""
@@ -79534,12 +83382,17 @@ msgid ""
"Can't be higher than the number of available default arguments in the "
"method's declaration."
msgstr ""
+"Le nombre d'arguments par défaut qui seront utilisés lors de l'appel de la "
+"fonction. Ne peut être supérieur au nombre d'arguments par défaut "
+"disponibles dans la déclaration de la méthode."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid ""
"If [code]false[/code], call errors (e.g. wrong number of arguments) will be "
"ignored."
msgstr ""
+"Si [code]false[/code], les erreurs d'appel (par exemple le nombre erroné "
+"d'arguments) seront ignorées."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid "The method will be called on this [Object]."
@@ -79548,12 +83401,15 @@ msgstr "La méthode sera appelée sur cet [Object]."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid "The method will be called on the given [Node] in the scene tree."
msgstr ""
+"La méthode sera appelée sur le [Node] donné dans l'arborescence de la scène."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid ""
"The method will be called on an instanced node with the given type and "
"script."
msgstr ""
+"La méthode sera appelée sur un nœud instancié avec le type et le script "
+"donnés."
#: modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
msgid "The method will be called on a GDScript basic type (e.g. [Vector2])."
@@ -79585,6 +83441,8 @@ msgid ""
"The method will be called remotely for the given peer, using an unreliable "
"protocol."
msgstr ""
+"La méthode sera appelée à distance pour le pair donné, en utilisant un "
+"protocole non fiable."
#: modules/visual_script/doc_classes/VisualScriptFunctionState.xml
msgid "A Visual Script node representing a function state."
@@ -79595,12 +83453,16 @@ msgid ""
"[VisualScriptFunctionState] is returned from [VisualScriptYield] and can be "
"used to resume a paused function call."
msgstr ""
+"[VisualScriptFunctionState] est retourné depuis [VisualScriptYield] et peut "
+"être utilisé pour reprendre un appel de fonction en pause."
#: modules/visual_script/doc_classes/VisualScriptFunctionState.xml
msgid ""
"Connects this [VisualScriptFunctionState] to a signal in the given object to "
"automatically resume when it's emitted."
msgstr ""
+"Connecte ce [VisualScriptFunctionState] à un signal dans l'objet donné pour "
+"reprendre automatiquement lorsqu'il est émis."
#: modules/visual_script/doc_classes/VisualScriptFunctionState.xml
msgid "Returns whether the function state is valid."
@@ -79609,61 +83471,63 @@ msgstr "Retourne si l'état de la fonction est valide."
#: modules/visual_script/doc_classes/VisualScriptFunctionState.xml
msgid "Resumes the function to run from the point it was yielded."
msgstr ""
+"Reprend la fonction à exécuter à partir du point où elle a été suspendue."
#: modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
-#, fuzzy
msgid "A Visual Script node returning a constant from [@GlobalScope]."
-msgstr "Un nœud Visual Script utilisé pour annoter le script."
+msgstr "Un nœud Visual Script retournant une constante de [@GlobalScope]."
#: modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
msgid "The constant to be used."
msgstr "La constante à utiliser."
#: modules/visual_script/doc_classes/VisualScriptIndexGet.xml
-#, fuzzy
msgid "A Visual Script node for getting a value from an array or a dictionary."
msgstr ""
-"Nœud de script visuel utilisé pour créer un tableau à partir d’une liste "
-"d’éléments."
+"Un nœud Visual Script pour obtenir une valeur d'un tableau ou d'un "
+"dictionnaire."
#: modules/visual_script/doc_classes/VisualScriptIndexGet.xml
msgid ""
"[VisualScriptIndexGet] will return the value stored in an array or a "
"dictionary under the given index."
msgstr ""
+"[VisualScriptIndexGet] retourne la valeur enregistrée dans un tableau ou un "
+"dictionnaire à l'index donné."
#: modules/visual_script/doc_classes/VisualScriptIndexSet.xml
-#, fuzzy
msgid "A Visual Script node for setting a value in an array or a dictionary."
msgstr ""
-"Nœud de script visuel utilisé pour créer un tableau à partir d’une liste "
-"d’éléments."
+"Un nœud Visual Script pour définir une valeur dans un tableau ou un "
+"dictionnaire."
#: modules/visual_script/doc_classes/VisualScriptIndexSet.xml
msgid ""
"[VisualScriptIndexSet] will set the value stored in an array or a dictionary "
"under the given index to the provided new value."
msgstr ""
+"[VisualScriptIndexSet] définira la valeur enregistrée dans un tableau ou un "
+"dictionnaire à l'index donné avec la nouvelle valeur fournie."
#: modules/visual_script/doc_classes/VisualScriptInputAction.xml
-#, fuzzy
msgid "A Visual Script node returning a state of an action."
-msgstr "Un nœud Visual Script utilisé pour annoter le script."
+msgstr "Un nœud Visual Script retournant l'état de l'action."
#: modules/visual_script/doc_classes/VisualScriptInputAction.xml
msgid ""
"[VisualScriptInputAction] can be used to check if an action is pressed or "
"released."
msgstr ""
+"[VisualScriptInputAction] peut être utilisé pour vérifier si une action est "
+"pressée ou relâchée."
#: modules/visual_script/doc_classes/VisualScriptInputAction.xml
msgid "Name of the action."
msgstr "Le nom de l'action."
#: modules/visual_script/doc_classes/VisualScriptInputAction.xml
-#, fuzzy
msgid "State of the action to check. See [enum Mode] for options."
-msgstr "La fonction à calculer. Voir [enum Function] pour les options."
+msgstr "L'état de l'action à vérifier. Voir [enum Mode] pour les options."
#: modules/visual_script/doc_classes/VisualScriptInputAction.xml
msgid "[code]True[/code] if action is pressed."
@@ -79702,32 +83566,31 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScriptLists.xml
msgid "A Visual Script virtual class for in-graph editable nodes."
msgstr ""
+"Une classe virtuelle Visual Script pour les nœuds modifiables dans le graphe."
#: modules/visual_script/doc_classes/VisualScriptLists.xml
msgid ""
"A Visual Script virtual class that defines the shape and the default "
"behavior of the nodes that have to be in-graph editable nodes."
msgstr ""
+"Une classe virtuelle Visual Script qui définit la forme et le comportement "
+"par défaut des nœuds qui doivent être des nœuds modifiables dans le graphe."
#: modules/visual_script/doc_classes/VisualScriptLists.xml
-#, fuzzy
msgid "Adds an input port to the Visual Script node."
-msgstr "Un nœud Visual Script scripté."
+msgstr "Ajoute un port d'entrée au nœud Visual Script."
#: modules/visual_script/doc_classes/VisualScriptLists.xml
-#, fuzzy
msgid "Adds an output port to the Visual Script node."
-msgstr "Un nœud Visual Script scripté."
+msgstr "Ajoute un port de sortie au nœud Visual Script."
#: modules/visual_script/doc_classes/VisualScriptLists.xml
-#, fuzzy
msgid "Removes an input port from the Visual Script node."
-msgstr "Supprime un nœud de la sélection."
+msgstr "Supprime un port d'entrée du nœud Visual Script."
#: modules/visual_script/doc_classes/VisualScriptLists.xml
-#, fuzzy
msgid "Removes an output port from the Visual Script node."
-msgstr "Supprime un nœud de la sélection."
+msgstr "Supprime un port de sortie du nœud Visual Script."
#: modules/visual_script/doc_classes/VisualScriptLists.xml
msgid "Sets the name of an input port."
@@ -79860,13 +83723,15 @@ msgstr ""
#: modules/visual_script/doc_classes/VisualScriptNode.xml
msgid "Returns the [VisualScript] instance the node is bound to."
-msgstr ""
+msgstr "Retourne l'instance [VisualScript] liée à ce nœud."
#: modules/visual_script/doc_classes/VisualScriptNode.xml
msgid ""
"Notify that the node's ports have changed. Usually used in conjunction with "
"[VisualScriptCustomNode] ."
msgstr ""
+"Notifie quand les ports de ce nœud ont changé. Habituellement utilisé avec "
+"[VisualScriptCustomNode] ."
#: modules/visual_script/doc_classes/VisualScriptNode.xml
msgid "Change the default value of a given port."
@@ -79877,11 +83742,8 @@ msgid "Emitted when the available input/output ports are changed."
msgstr "Émis quand les ports entrants/sortants sont changés."
#: modules/visual_script/doc_classes/VisualScriptOperator.xml
-#, fuzzy
msgid "A Visual Script node that performs an operation on two values."
-msgstr ""
-"Nœud de script visuel utilisé pour créer un tableau à partir d’une liste "
-"d’éléments."
+msgstr "Un nœud Visual Script qui effectue une opération sur deux valeurs."
#: modules/visual_script/doc_classes/VisualScriptOperator.xml
msgid ""
@@ -79893,21 +83755,18 @@ msgid ""
msgstr ""
#: modules/visual_script/doc_classes/VisualScriptOperator.xml
-#, fuzzy
msgid ""
"The operation to be performed. See [enum Variant.Operator] for available "
"options."
msgstr ""
-"Type de multiplication à effectuer. Voir [enum Operator] pour les options."
+"Le type d'opération à effectuer. Voir [enum Variant.Operator] pour les "
+"options disponibles."
#: modules/visual_script/doc_classes/VisualScriptOperator.xml
-#, fuzzy
msgid ""
"The type of the values for this operation. See [enum Variant.Type] for "
"available options."
msgstr ""
-"Définit la valeur d’un paramètre de zone. Voir [enum AreaParameter] pour une "
-"liste de paramètres disponibles."
#: modules/visual_script/doc_classes/VisualScriptPreload.xml
msgid "Creates a new [Resource] or loads one from the filesystem."
@@ -79928,17 +83787,17 @@ msgid "The [Resource] to load."
msgstr "La [Resource] à charger."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
-#, fuzzy
msgid "A Visual Script node returning a value of a property from an [Object]."
msgstr ""
-"Nœud de script visuel utilisé pour créer un tableau à partir d’une liste "
-"d’éléments."
+"Un nœud Visual Script retournant une valeur d'une propriété d'un [Object]."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
msgid ""
"[VisualScriptPropertyGet] can return a value of any property from the "
"current object or other objects."
msgstr ""
+"[VisualScriptPropertyGet] peut renvoyer une valeur de toute propriété de "
+"l'objet courant ou d'autres objets."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -79946,6 +83805,8 @@ msgid ""
"The script to be used when [member set_mode] is set to [constant "
"CALL_MODE_INSTANCE]."
msgstr ""
+"Le script à utiliser lorsque [member set_mode] est défini à [constant "
+"CALL_MODE_INSTANCE]."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -79953,6 +83814,8 @@ msgid ""
"The base type to be used when [member set_mode] is set to [constant "
"CALL_MODE_INSTANCE]."
msgstr ""
+"Le type de base à utiliser lorsque [member set_mode] est défini à [constant "
+"CALL_MODE_INSTANCE]."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -79960,12 +83823,16 @@ msgid ""
"The type to be used when [member set_mode] is set to [constant "
"CALL_MODE_BASIC_TYPE]."
msgstr ""
+"Le type à utiliser lorsque [member set_mode] est défini à [constant "
+"CALL_MODE_BASIC_TYPE]."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
msgid ""
"The indexed name of the property to retrieve. See [method Object."
"get_indexed] for details."
msgstr ""
+"Le nom indexé de la propriété à récupérer. Voir [method Object.get_indexed] "
+"pour plus de détails."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -79973,34 +83840,40 @@ msgid ""
"The node path to use when [member set_mode] is set to [constant "
"CALL_MODE_NODE_PATH]."
msgstr ""
+"Le chemin du nœud à utiliser lorsque [member set_mode] est défini à ["
+"constant CALL_MODE_NODE_PATH]."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
msgid ""
"The name of the property to retrieve. Changing this will clear [member "
"index]."
msgstr ""
+"Le nom de la propriété à récupérer. Changer cela effecera [member index]."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
msgid ""
"[code]set_mode[/code] determines the target object from which the property "
"will be retrieved. See [enum CallMode] for options."
msgstr ""
+"[code]set_mode[/code] détermine l'objet cible à partir duquel la propriété "
+"sera récupérée. Voir [enum CallMode] pour les options."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
msgid "The property will be retrieved from this [Object]."
msgstr "La propriété sera récupérée depuis cet [Object]."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
-#, fuzzy
msgid "The property will be retrieved from the given [Node] in the scene tree."
msgstr ""
-"Le propriété est sérialisé et sauvegardé dans le fichier de la scène(défaut)."
+"La propriété sera récupérée du [Node] donné dans l'arborescence de la scène."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
msgid ""
"The property will be retrieved from an instanced node with the given type "
"and script."
msgstr ""
+"La propriété sera récupérée à partir d'un nœud instancié avec le type et le "
+"script donnés."
#: modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
msgid ""
@@ -80010,23 +83883,23 @@ msgstr ""
"[Vector2])."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
-#, fuzzy
msgid "A Visual Script node that sets a property of an [Object]."
-msgstr "Un nœud Visual Script utilisé pour annoter le script."
+msgstr "Un nœud de script visuel qui définit une propriété d'un [Object]."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid ""
"[VisualScriptPropertySet] can set the value of any property from the current "
"object or other objects."
msgstr ""
+"[VisualScriptPropertySet] peut définir la valeur de toute propriété à partir "
+"de l'objet courant ou d'autres objets."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
-#, fuzzy
msgid ""
"The additional operation to perform when assigning. See [enum AssignOp] for "
"options."
msgstr ""
-"L'opérateur additionelle à effectuer lors de l'assignation. Voir [enum "
+"L'opérateur d'addition à effectuer lors de l'assignation. Voir [enum "
"AssignOp] pour les options."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -80034,32 +83907,37 @@ msgid ""
"The indexed name of the property to set. See [method Object.set_indexed] for "
"details."
msgstr ""
+"Le nom indexé de la propriété à définir. Voir [method Object.set_indexed] "
+"pour plus de détails."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid ""
"The name of the property to set. Changing this will clear [member index]."
-msgstr ""
+msgstr "Le nom de la propriété à définir. Changer cela effecera [member index]."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid ""
"[code]set_mode[/code] determines the target object on which the property "
"will be set. See [enum CallMode] for options."
msgstr ""
+"[code]set_mode[/code] détermine l'objet cible sur lequel la propriété sera "
+"définie. Voir [enum CallMode] pour les options."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid "The property will be set on this [Object]."
msgstr "La propriété sera définie dans cet [Object]."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
-#, fuzzy
msgid "The property will be set on the given [Node] in the scene tree."
msgstr ""
-"Le propriété est sérialisé et sauvegardé dans le fichier de la scène(défaut)."
+"La propriété sera placée sur le [Node] donné dans l'arborescence de la scène."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid ""
"The property will be set on an instanced node with the given type and script."
msgstr ""
+"La propriété sera définie sur un nœud instancié avec le type et le script "
+"donnés."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid "The property will be set on a GDScript basic type (e.g. [Vector2])."
@@ -80105,36 +83983,48 @@ msgid ""
"A modulo operation will be performed on the property and the value. "
"Equivalent of doing [code]%=[/code]."
msgstr ""
+"Une opération modulo sera effectuée sur la propriété et la valeur. Revient à "
+"écrire [code]%=[/code]."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid ""
"The property will be binarly shifted to the left by the given value. "
"Equivalent of doing [code]<<[/code]."
msgstr ""
+"La propriété sera transférée à gauche par la valeur donnée. Revient de "
+"écrire [code]<<[/code]."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid ""
"The property will be binarly shifted to the right by the given value. "
"Equivalent of doing [code]>>[/code]."
msgstr ""
+"La propriété sera transférée à droite par la valeur donnée. Revient de "
+"écrire [code]>>[/code]."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid ""
"A binary [code]AND[/code] operation will be performed on the property. "
"Equivalent of doing [code]&=[/code]."
msgstr ""
+"Une opération binaire [code]AND[/code] (et) sera effectuée sur la propriété. "
+"Revient à écrire [code]&=[/code]."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid ""
"A binary [code]OR[/code] operation will be performed on the property. "
"Equivalent of doing [code]|=[/code]."
msgstr ""
+"Une opération binaire [code]OR[/code] (ou) sera effectuée sur la propriété. "
+"Revient à écrire [code]|=[/code]."
#: modules/visual_script/doc_classes/VisualScriptPropertySet.xml
msgid ""
"A binary [code]XOR[/code] operation will be performed on the property. "
"Equivalent of doing [code]^=[/code]."
msgstr ""
+"Une opération binaire [code]XOR[/code] (ou exclusif) sera effectuée sur la "
+"propriété. Revient à écrire [code]^=[/code]."
#: modules/visual_script/doc_classes/VisualScriptReturn.xml
msgid "Exits a function and returns an optional value."
@@ -80269,9 +84159,8 @@ msgid ""
msgstr ""
#: modules/visual_script/doc_classes/VisualScriptTypeCast.xml
-#, fuzzy
msgid "A Visual Script node that casts the given value to another type."
-msgstr "Un nœud Visual Script utilisé pour annoter le script."
+msgstr ""
#: modules/visual_script/doc_classes/VisualScriptTypeCast.xml
msgid ""
@@ -80339,9 +84228,8 @@ msgid ""
msgstr ""
#: modules/visual_script/doc_classes/VisualScriptYield.xml
-#, fuzzy
msgid "A Visual Script node used to pause a function execution."
-msgstr "Un nœud Visual Script utilisé pour annoter le script."
+msgstr "Un nœud Visual Script pour mettre en pause l'exécution d'une fonction."
#: modules/visual_script/doc_classes/VisualScriptYield.xml
msgid ""
@@ -80350,11 +84238,11 @@ msgid ""
msgstr ""
#: modules/visual_script/doc_classes/VisualScriptYield.xml
-#, fuzzy
msgid ""
"The mode to use for yielding. See [enum YieldMode] for available options."
msgstr ""
-"Type de multiplication à effectuer. Voir [enum Operator] pour les options."
+"Le mode à utiliser pour suspendre. Voir [enum YieldMode] pour les options "
+"disponibles."
#: modules/visual_script/doc_classes/VisualScriptYield.xml
msgid "The time to wait when [member mode] is set to [constant YIELD_WAIT]."
@@ -80373,9 +84261,8 @@ msgid "Yields a function and waits the given time."
msgstr ""
#: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
-#, fuzzy
msgid "A Visual Script node yielding for a signal."
-msgstr "Un nœud Visual Script utilisé pour annoter le script."
+msgstr "Un nœud Visual Script pour attendre un signal."
#: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
msgid ""
@@ -80390,6 +84277,8 @@ msgid ""
"[code]call_mode[/code] determines the target object to wait for the signal "
"emission. See [enum CallMode] for options."
msgstr ""
+"[code]call_mode[/code] détermine l'objet cible à attendre avant l'émission "
+"du signal. Voir [enum CallMode] pour les options."
#: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
msgid "The signal name to be waited for."
@@ -80401,11 +84290,11 @@ msgstr "Un signal depuis cet [Object] sera utilisé."
#: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
msgid "A signal from the given [Node] in the scene tree will be used."
-msgstr ""
+msgstr "Un signal du [Node] donné dans l'arborescence de la scène sera utilisé."
#: modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
msgid "A signal from an instanced node with the given type will be used."
-msgstr ""
+msgstr "Un signal d'un nœud instancié avec le type donné sera utilisé."
#: doc/classes/VisualServer.xml
msgid "Server for anything visible."
@@ -80444,12 +84333,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid "Sets images to be rendered in the window margin."
msgstr ""
+"Définit des images dont le rendu sera fait dans les marges de la fenêtre."
#: doc/classes/VisualServer.xml
msgid ""
"Sets margin size, where black bars (or images, if [method "
"black_bars_set_images] was used) are rendered."
msgstr ""
+"Définit la taille de la marge, où des barres noires (ou des images, si ["
+"method black_bars_set_images] est utilisé) sont rendues."
#: doc/classes/VisualServer.xml
msgid ""
@@ -80514,6 +84406,10 @@ msgid ""
"the vertical aspect ratio which is equivalent to [constant Camera."
"KEEP_HEIGHT]."
msgstr ""
+"Si [code]true[/code], conserve le rapport d'aspect horizontal qui est "
+"équivalent à [constant Camera.KEEP_WIDTH]. Si [code]false[/code], conserve "
+"le rapport d'aspect vertical qui est équivalent à [constant Camera."
+"KEEP_HEIGHT]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -80534,12 +84430,9 @@ msgid "Adds a circle command to the [CanvasItem]'s draw commands."
msgstr "Ajouter un cercle aux commandes de dessin du [CanvasItem]."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"If ignore is [code]true[/code], the VisualServer does not perform clipping."
msgstr ""
-"Si [code]true[/code], le multithreading est utilisé pour améliorer les "
-"performances."
#: doc/classes/VisualServer.xml
msgid "Adds a line command to the [CanvasItem]'s draw commands."
@@ -80554,6 +84447,8 @@ msgid ""
"Adds a [MultiMesh] to the [CanvasItem]'s draw commands. Only affects its "
"aabb at the moment."
msgstr ""
+"Ajoute un [MultiMesh] aux commandes d'affichage du [CanvasItem]. N'affecte "
+"que son aabb pour le moment."
#: doc/classes/VisualServer.xml
msgid ""
@@ -80575,6 +84470,8 @@ msgid ""
"Adds a polyline, which is a line from multiple points with a width, to the "
"[CanvasItem]'s draw commands."
msgstr ""
+"Ajoute une suite de lignes, qui est une ligne de plusieurs points avec une "
+"largeur, aux commandes d'affichage du [CanvasItem]."
#: doc/classes/VisualServer.xml
msgid "Adds a primitive to the [CanvasItem]'s draw commands."
@@ -80599,6 +84496,8 @@ msgstr "Ajouter un rectangle texturé aux commandes de dessin du [CanvasItem]."
msgid ""
"Adds a texture rect with region setting to the [CanvasItem]'s draw commands."
msgstr ""
+"Ajoute un rectangle de texture, avec des réglages de la région à afficher, "
+"aux commandes d'affichage du [CanvasItem]."
#: doc/classes/VisualServer.xml
msgid "Adds a triangle array to the [CanvasItem]'s draw commands."
@@ -80607,7 +84506,7 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid "Clears the [CanvasItem] and removes all commands in it."
-msgstr ""
+msgstr "Efface le [CanvasItem] et enlève toutes les commandes."
#: doc/classes/VisualServer.xml
msgid ""
@@ -80624,7 +84523,6 @@ msgstr ""
"méthode statique [method free_rid] du VisualServer."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Sets clipping for the [CanvasItem]."
msgstr "Définit la coupure pour le [CanvasItem]."
@@ -80670,6 +84568,9 @@ msgid ""
"Sets the parent for the [CanvasItem]. The parent can be another canvas item, "
"or it can be the root canvas that is attached to the viewport."
msgstr ""
+"Définit le parent du [CanvasItem]. Le parent peut être un autre élément de "
+"toile, ou il peut être la toile racine qui est attachée à la fenêtre "
+"d'affichage."
#: doc/classes/VisualServer.xml
msgid "Sets the color that modulates the [CanvasItem] without children."
@@ -80691,9 +84592,8 @@ msgid "Sets if the [CanvasItem] uses its parent's material."
msgstr "Définit si le [CanvasItem] utilise le même matériau que son parent."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Sets if the canvas item (including its children) is visible."
-msgstr "Masquer le [CanvasItem] s’il est actuellement visible."
+msgstr "Définit si la toile (y compris ses enfants) est visible."
#: doc/classes/VisualServer.xml
msgid ""
@@ -80776,9 +84676,8 @@ msgid "Sets a canvas light's energy."
msgstr "Définit l'énergie d'une lumière du canevas."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Sets a canvas light's height."
-msgstr "Définit la hauteur d’une toile."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
@@ -80792,19 +84691,23 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid "The mode of the light, see [enum CanvasLightMode] constants."
-msgstr ""
+msgstr "Le mode de la lumière, voir les constantes [enum CanvasLightMode]."
#: doc/classes/VisualServer.xml
msgid ""
"Sets the texture's scale factor of the light. Equivalent to [member Light2D."
"texture_scale]."
msgstr ""
+"Définit le facteur d'échelle de la texture de lumière. Équivalent à [member "
+"Light2D.texture_scale]"
#: doc/classes/VisualServer.xml
msgid ""
"Sets the width of the shadow buffer, size gets scaled to the next power of "
"two for this."
msgstr ""
+"Définit la largeur du tampon d'ombre, la taille est arrondie à la puissance "
+"de deux suivante pour cela."
#: doc/classes/VisualServer.xml
msgid "Sets the color of the canvas light's shadow."
@@ -80876,11 +84779,11 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid "Sets the shape of the occluder polygon."
-msgstr ""
+msgstr "Définit la forme du polygone occulteur."
#: doc/classes/VisualServer.xml
msgid "Sets the shape of the occluder polygon as lines."
-msgstr ""
+msgstr "Définit la forme du polygone occulteur avec des lignes."
#: doc/classes/VisualServer.xml
msgid ""
@@ -80942,6 +84845,8 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid "Sets the ambient light parameters. See [Environment] for more details."
msgstr ""
+"Définit les paramètres de lumière ambiante. Voir [Environnement] pour plus "
+"de détails."
#: doc/classes/VisualServer.xml
msgid ""
@@ -80983,18 +84888,24 @@ msgid ""
"Sets the variables to be used with the scene fog. See [Environment] for more "
"details."
msgstr ""
+"Définit les variables à utiliser avec le brouillard de scène. Voir "
+"[Environnement] pour plus de détails."
#: doc/classes/VisualServer.xml
msgid ""
"Sets the variables to be used with the fog depth effect. See [Environment] "
"for more details."
msgstr ""
+"Définit les variables à utiliser avec l'effet de profondeur du brouillard. "
+"Voir [Environnement] pour plus de détails."
#: doc/classes/VisualServer.xml
msgid ""
"Sets the variables to be used with the fog height effect. See [Environment] "
"for more details."
msgstr ""
+"Définit les variables à utiliser avec l'effet de hauteur du brouillard. Voir "
+"[Environnement] pour plus de détails."
#: doc/classes/VisualServer.xml
msgid ""
@@ -81013,12 +84924,16 @@ msgid ""
"Sets a custom field of view for the background [Sky]. Equivalent to [member "
"Environment.background_sky_custom_fov]."
msgstr ""
+"Définit un angle de vue personnalisé pour le ciel [Sky] en arrière-plan. "
+"Équivalent à [member Environnement.background_sky_custom_fov]"
#: doc/classes/VisualServer.xml
msgid ""
"Sets the rotation of the background [Sky] expressed as a [Basis]. Equivalent "
"to [member Environment.background_sky_orientation]."
msgstr ""
+"Définit la rotation du ciel [Sky] en arrière-plan exprimé avec une [Basis]. "
+"Équivalent à [member Environnement.background_sky_orientation]"
#: doc/classes/VisualServer.xml
msgid ""
@@ -81062,6 +84977,7 @@ msgstr "Essaye de supprimer un objet dans le VisualServer."
#: doc/classes/VisualServer.xml
msgid "Returns a certain information, see [enum RenderInfo] for options."
msgstr ""
+"Retourne une information précise, voir [enum RenderInfo] pour les options."
#: doc/classes/VisualServer.xml
msgid "Returns the id of the test cube. Creates one if none exists."
@@ -81079,6 +84995,10 @@ msgid ""
"[b]Note:[/b] When running a headless or server binary, this function returns "
"an empty string."
msgstr ""
+"Retourne le nom de l'adaptateur vidéo (par exemple \"GeForce GTX 1080/PCIe/"
+"SSE2\").\n"
+"[b]Note :[/b] Lors de l'exécution d'une version sans graphique ou de "
+"serveur, cette fonction retourne une chaîne vide."
#: doc/classes/VisualServer.xml
msgid ""
@@ -81086,6 +85006,10 @@ msgid ""
"[b]Note:[/b] When running a headless or server binary, this function returns "
"an empty string."
msgstr ""
+"Retourne le vendeur de l'adaptateur vidéo (par exemple \"NVIDIA Corporation\""
+").\n"
+"[b]Note :[/b] Lors de l'exécution d'une version sans graphique ou de "
+"serveur, cette fonction retourne une chaîne vide."
#: doc/classes/VisualServer.xml
msgid "Returns the id of a white texture. Creates one if none exists."
@@ -81128,21 +85052,24 @@ msgstr ""
"Retourne la taille de la cellule définit par [method gi_probe_set_cell_size]."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns the data used by the GI probe."
-msgstr "Renvoie l’espace affecté à la zone."
+msgstr "Retourne les données utilisées par la sonde GI."
#: doc/classes/VisualServer.xml
msgid ""
"Returns the dynamic range set for this GI probe. Equivalent to [member "
"GIProbe.dynamic_range]."
msgstr ""
+"Retourne la gamme dynamique pour cette sonde GI. Équivalent à [member GIProbe"
+".dynamic_range]"
#: doc/classes/VisualServer.xml
msgid ""
"Returns the energy multiplier for this GI probe. Equivalent to [member "
"GIProbe.energy]."
msgstr ""
+"Retourne le multiplicateur d'énergie pour cette sonde GI. Équivalent à ["
+"member GIProbe.energy]"
#: doc/classes/VisualServer.xml
msgid ""
@@ -81155,6 +85082,8 @@ msgid ""
"Returns the propagation value for this GI probe. Equivalent to [member "
"GIProbe.propagation]."
msgstr ""
+"Retourne la valeur de propagation de cette sonde GI. Équivalent à [member "
+"GIProbe.propagation]"
#: doc/classes/VisualServer.xml
msgid "Returns the Transform set by [method gi_probe_set_to_cell_xform]."
@@ -81165,15 +85094,14 @@ msgid ""
"Returns [code]true[/code] if the GI probe data associated with this GI probe "
"is compressed. Equivalent to [member GIProbe.compress]."
msgstr ""
+"Retourne [code]true[/code] si les données de cette sonde GI sont "
+"compressées. Équivalent à [member GIProbe.compress]"
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if the GI probe is set to interior, meaning it "
"does not account for sky light. Equivalent to [member GIProbe.interior]."
msgstr ""
-"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. "
-"Équivalent à [member ReflectionProbe.interior]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -81239,9 +85167,8 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Sets the to cell [Transform] for this GI probe."
-msgstr "Retourne la matrice de transformation globale de cet élément."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
@@ -81324,9 +85251,8 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Sets the material to be used to draw the [ImmediateGeometry]."
-msgstr "Retourne le matériel affecté à la [ImmediateGeometry3D]."
+msgstr "Définit le matériel utilisé pour afficher le [ImmediateGeometry]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -81608,13 +85534,10 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"If [code]true[/code], light will subtract light instead of adding light. "
"Equivalent to [member Light.light_negative]."
msgstr ""
-"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. "
-"Équivalent à [member ReflectionProbe.interior]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -81632,13 +85555,10 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"If [code]true[/code], light will cast shadows. Equivalent to [member Light."
"shadow_enabled]."
msgstr ""
-"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. "
-"Équivalent à [member ReflectionProbe.interior]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -81675,19 +85595,16 @@ msgstr ""
"en utilisant la [method instance_set_base] utilisant le RID retourné."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns the size of the lightmap capture area."
-msgstr "Renvoie le sinus du paramètre."
+msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns the energy multiplier used by the lightmap capture."
-msgstr "Renvoie le nombre de textures dans l’atlas BitmapFont."
+msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns the octree used by the lightmap capture."
-msgstr "Renvoie l’espace affecté à la zone."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
@@ -81695,9 +85612,8 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns the cell transform for this lightmap capture's octree."
-msgstr "Retourne la matrice de transformation de la toile de cet objet."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "Returns [code]true[/code] if capture is in \"interior\" mode."
@@ -81765,13 +85681,10 @@ msgid "Returns the value of a certain material's parameter."
msgstr "Retourne la valeur du paramètre du matériau."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"Returns the default value for the param if available. Returns [code]null[/"
"code] otherwise."
msgstr ""
-"Retourne la valeur par défaut du paramètre nommé [code]name[/code] du "
-"matériau."
#: doc/classes/VisualServer.xml
msgid ""
@@ -81788,9 +85701,8 @@ msgid "Sets an object's next material."
msgstr "Définit le prochain matériau d’un objet."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Sets a material's parameter."
-msgstr "Définit le paramètre d’un matériau."
+msgstr "Définit le paramètre d'un matériau."
#: doc/classes/VisualServer.xml
msgid "Sets a material's render priority."
@@ -81853,7 +85765,7 @@ msgstr "Supprime la surface d'un maillage."
#: doc/classes/VisualServer.xml
#, fuzzy
msgid "Sets a mesh's blend shape count."
-msgstr "Retourne le nombre de formes de mélange d’un maillage."
+msgstr "Définit le nombre de formes de mélange d’un maillage."
#: doc/classes/VisualServer.xml
msgid "Sets a mesh's blend shape mode."
@@ -81868,19 +85780,16 @@ msgid "Returns a mesh's surface's aabb."
msgstr "Retourne l’aabb de la surface d'un maillage."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns a mesh's surface's vertex buffer."
-msgstr "Retourne l’aabb personnalisé d’un maillage."
+msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns a mesh's surface's amount of indices."
-msgstr "Renvoie le nombre de points de la Ligne2D."
+msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns a mesh's surface's amount of vertices."
-msgstr "Renvoie le nombre de points de la Ligne2D."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "Returns a mesh's surface's buffer arrays."
@@ -81891,32 +85800,28 @@ msgid "Returns a mesh's surface's arrays for blend shapes."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns the format of a mesh's surface."
-msgstr "Retourne le nom de la méthode d'une piste de méthode."
+msgstr "Retourne le format d'une surface d'un maillage."
#: doc/classes/VisualServer.xml
msgid "Function is unused in Godot 3.x."
msgstr "Cette fonction n'est pas utilisée dans Godot 3.x."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns a mesh's surface's index buffer."
-msgstr "Retourne le mode de forme de mélange d’un maillage."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "Returns a mesh's surface's material."
msgstr "Retourne le matériau de la surface du maillage."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns the primitive type of a mesh's surface."
-msgstr "Retourne le nom de la méthode d'une piste de méthode."
+msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns the aabb of a mesh's surface's skeleton."
-msgstr "Retourne la traduction d’un message."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "Sets a mesh's surface's material."
@@ -82190,13 +86095,10 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"If [code]true[/code], uses fractional delta which smooths the movement of "
"the particles. Equivalent to [member Particles.fract_delta]."
msgstr ""
-"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. "
-"Équivalent à [member ReflectionProbe.interior]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -82266,13 +86168,12 @@ msgstr ""
"retourné."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"If [code]true[/code], reflections will ignore sky contribution. Equivalent "
"to [member ReflectionProbe.interior_enable]."
msgstr ""
"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. "
-"Équivalent à [member ReflectionProbe.interior]."
+"Équivalent à [member ReflectionProbe.interior_enable]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -82308,23 +86209,17 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"Sets the ambient light color for this reflection probe when set to interior "
"mode. Equivalent to [member ReflectionProbe.interior_ambient_color]."
msgstr ""
-"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. "
-"Équivalent à [member ReflectionProbe.interior]."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"Sets the energy multiplier for this reflection probes ambient light "
"contribution when set to interior mode. Equivalent to [member "
"ReflectionProbe.interior_ambient_energy]."
msgstr ""
-"Si [code]true[/code], les réflexions ignoreront la contribution du ciel. "
-"Équivalent à [member ReflectionProbe.interior]."
#: doc/classes/VisualServer.xml
msgid ""
@@ -82442,9 +86337,8 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Enables or disables occlusion culling."
-msgstr "Active ou désactive une lumière du canevas."
+msgstr "Active ou désactive le culling de l'occlusion."
#: doc/classes/VisualServer.xml
msgid ""
@@ -82461,7 +86355,6 @@ msgstr ""
"méthode statique [method free_rid] du VisualServer."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns a shader's code."
msgstr "Retourne le code d'un shader."
@@ -82474,7 +86367,6 @@ msgid "Returns the parameters of a shader."
msgstr "Retourne les paramètres d'un shader."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Sets a shader's code."
msgstr "Définit le code d'un shader."
@@ -82559,14 +86451,12 @@ msgstr ""
"utilisant la [method instance_set_base] utilisant le RID retourné."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Allocates the GPU memory for the texture."
-msgstr "La largeur de la texture."
+msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Binds the texture to a texture slot."
-msgstr "Alignez le texte à gauche."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
@@ -82589,9 +86479,8 @@ msgstr ""
"Crée une texture, alloue l'espace pour une image, et remplit avec l'image."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns a list of all the textures and their information."
-msgstr "Retourne le nombre de pistes dans l'animation."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
@@ -82610,9 +86499,8 @@ msgid "Returns the flags of a texture."
msgstr "Retourne les drapeaux de la texture."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Returns the format of the texture's image."
-msgstr "Renvoie le reste de deux vecteurs."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "Returns the texture's height."
@@ -82713,13 +86601,10 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"If [code]true[/code], the image will be stored in the texture's images array "
"if overwritten."
msgstr ""
-"Si [code]true[/code], la [SpinBox] sera modifiable. Sinon, elle sera en "
-"lecture seule."
#: doc/classes/VisualServer.xml
msgid "Sets a viewport's camera."
@@ -82730,7 +86615,6 @@ msgid "Sets a viewport's canvas."
msgstr "Définit le canevas de la fenêtre d'affichage."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"Copies viewport to a region of the screen specified by [code]rect[/code]. If "
"[member Viewport.render_direct_to_screen] is [code]true[/code], then "
@@ -82767,7 +86651,7 @@ msgstr ""
" $Viewport.set_attach_to_screen_rect(Rect2(0, 0, 600, 600))\n"
"[/codeblock]\n"
"Utiliser cette méthode peut permettre d'améliorer considérablement les "
-"performances, surtout sur les appareils peut puissants. Par contre, cela "
+"performances, surtout sur les appareils peu puissants. Par contre, cela "
"nécessite de gérer manuellement les fenêtres d'affichage. Pour plus "
"d'optimisations, voir [method viewport_set_render_direct_to_screen]."
@@ -82856,9 +86740,12 @@ msgstr ""
"Définit la matrice de transformation globale de la fenêtre d'affichage."
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
-msgstr "Si [code]true[/code], l'interpolation fait une boucle."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -82942,11 +86829,19 @@ msgid ""
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid ""
"Sets the viewport's 2D/3D mode. See [enum ViewportUsage] constants for "
"options."
-msgstr "Convertit le format de l’image. Voir les constantes [enum Format]."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
@@ -83011,16 +86906,12 @@ msgid "Number of weights/bones per vertex."
msgstr "Nombre de poids / os par sommet."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "The minimum Z-layer for canvas items."
-msgstr ""
-"Le niveau minimal du calque de profondeur pour les éléments de canevas."
+msgstr "Le niveau minimal du calque de profondeur pour les éléments de canevas."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "The maximum Z-layer for canvas items."
-msgstr ""
-"Le niveau maximal du calque de profondeur pour les éléments de canevas."
+msgstr "Le niveau maximal du calque de profondeur pour les éléments de canevas."
#: doc/classes/VisualServer.xml
msgid ""
@@ -83082,7 +86973,6 @@ msgid "A 3-dimensional texture with width, height, and depth."
msgstr "Une texture à 3 dimensions, largeur et hauteur, et profondeur."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Repeats the texture (instead of clamp to edge)."
msgstr "Répète la texture (plutôt que de s'arrêter aux bordures)."
@@ -83476,9 +87366,8 @@ msgid "Number of draw calls during this frame."
msgstr "Nombre d'appels d'affichage pour cette trame."
#: doc/classes/VisualServer.xml
-#, fuzzy
msgid "Number of 2d items drawn this frame."
-msgstr "Nombre de changements de surface pendant cette image."
+msgstr "Le nombre d'éléments 2D affichés dans cette trame."
#: doc/classes/VisualServer.xml
msgid "Number of 2d draw calls during this frame."
@@ -84153,11 +88042,8 @@ msgstr "Sera traduit en [code]uniform bool[/code] dans le code du shader."
#: doc/classes/VisualShaderNodeScalarUniform.xml
#: doc/classes/VisualShaderNodeTransformUniform.xml
#: doc/classes/VisualShaderNodeVec3Uniform.xml
-#, fuzzy
msgid "A default value to be assigned within the shader."
msgstr ""
-"Un opérateur scalaire à virgule flottante à utiliser dans le graphique du "
-"nuanceur visuel."
#: doc/classes/VisualShaderNodeBooleanUniform.xml
#: doc/classes/VisualShaderNodeColorUniform.xml
@@ -84450,7 +88336,6 @@ msgid ""
msgstr ""
#: doc/classes/VisualShaderNodeCompare.xml
-#, fuzzy
msgid ""
"The result will be true if all of component in vector satisfy the comparison "
"condition."
@@ -84459,7 +88344,6 @@ msgstr ""
"condition de comparaison."
#: doc/classes/VisualShaderNodeCompare.xml
-#, fuzzy
msgid ""
"The result will be true if any of component in vector satisfy the comparison "
"condition."
@@ -84468,11 +88352,8 @@ msgstr ""
"condition de comparaison."
#: doc/classes/VisualShaderNodeCubeMap.xml
-#, fuzzy
msgid "A [CubeMap] sampling node to be used within the visual shader graph."
msgstr ""
-"Un opérateur scalaire à virgule flottante à utiliser dans le graphique du "
-"nuanceur visuel."
#: doc/classes/VisualShaderNodeCubeMap.xml
msgid ""
@@ -84539,11 +88420,8 @@ msgid ""
msgstr ""
#: doc/classes/VisualShaderNodeCubeMapUniform.xml
-#, fuzzy
msgid "A [CubeMap] uniform node to be used within the visual shader graph."
msgstr ""
-"Un tableau uniforme de texture 2D à utiliser dans le graphique de l'ombrage "
-"visuel."
#: doc/classes/VisualShaderNodeCubeMapUniform.xml
msgid ""
@@ -85219,13 +89097,12 @@ msgid "Defaults to black color."
msgstr "Par défaut à la couleur noire."
#: doc/classes/VisualShaderNodeTextureUniformTriplanar.xml
-#, fuzzy
msgid ""
"Performs a uniform texture lookup with triplanar within the visual shader "
"graph."
msgstr ""
-"Effectue une recherche de texture uniforme avec triplanaire dans le "
-"graphique de nuanceur visuel."
+"Effectue une projection de texture uniforme en triplanaire dans le graphe du "
+"Visual Shader."
#: doc/classes/VisualShaderNodeTextureUniformTriplanar.xml
msgid ""
@@ -85234,12 +89111,11 @@ msgid ""
msgstr ""
#: doc/classes/VisualShaderNodeTransformCompose.xml
-#, fuzzy
msgid ""
"Composes a [Transform] from four [Vector3]s within the visual shader graph."
msgstr ""
-"Compose un [Transform] à partir de quatre [Vector3] dans le graphique du "
-"nuanceur visuel."
+"Compose un [Transform] à partir de quatre [Vector3] dans le graphe du Visual "
+"Shader."
#: doc/classes/VisualShaderNodeTransformCompose.xml
msgid ""
@@ -85353,11 +89229,10 @@ msgid "Translated to [code]uniform mat4[/code] in the shader language."
msgstr "Sera traduit en [code]uniform mat4[/code] dans le code du shader."
#: doc/classes/VisualShaderNodeTransformVecMult.xml
-#, fuzzy
msgid ""
"Multiplies a [Transform] and a [Vector3] within the visual shader graph."
msgstr ""
-"Multiplie un [Transform] et un [Vector3] dans le graphique de shader visuel."
+"Multiplie un [Transform] et un [Vector3] dans le graphe du Visual Shader."
#: doc/classes/VisualShaderNodeTransformVecMult.xml
msgid ""
@@ -85400,7 +89275,7 @@ msgstr ""
#: doc/classes/VisualShaderNodeUniform.xml
#, fuzzy
msgid "A base type for the uniforms within the visual shader graph."
-msgstr "Type de base pour les uniformes dans le graphique du nuanceur visuel."
+msgstr "Le type de base pour les uniformes dans le graphe du Visual Shader."
#: doc/classes/VisualShaderNodeUniform.xml
msgid ""
@@ -85957,10 +89832,9 @@ msgid "Closes this data channel, notifying the other peer."
msgstr "Ferme ce canal de données, en notifiant l’autre homologue."
#: modules/webrtc/doc_classes/WebRTCDataChannel.xml
-#, fuzzy
msgid ""
"Returns the number of bytes currently queued to be sent over this channel."
-msgstr "Retourne le nombre de traqueurs actuellement enregistrés."
+msgstr ""
#: modules/webrtc/doc_classes/WebRTCDataChannel.xml
msgid ""
@@ -86051,7 +89925,6 @@ msgid "The channel was created, but it's still trying to connect."
msgstr "Le canal a été créé, mais il essaie toujours de se connecter."
#: modules/webrtc/doc_classes/WebRTCDataChannel.xml
-#, fuzzy
msgid "The channel is currently open, and data can flow over it."
msgstr "Le canal est actuellement ouvert, et les données peuvent y circuler."
@@ -86160,9 +90033,8 @@ msgid ""
msgstr ""
#: modules/webrtc/doc_classes/WebRTCPeerConnection.xml
-#, fuzzy
msgid "Interface to a WebRTC peer connection."
-msgstr "Interface vers une connexion homologue WebRTC."
+msgstr "L'interface de connexion par pair via WebRTC."
#: modules/webrtc/doc_classes/WebRTCPeerConnection.xml
msgid ""
@@ -87216,14 +91088,12 @@ msgid ""
msgstr ""
#: doc/classes/WindowDialog.xml
-#, fuzzy
msgid "The vertical offset of the title text."
-msgstr "Décalage vertical du texte du titre."
+msgstr "Le décalage vertical du texte du titre."
#: doc/classes/WindowDialog.xml
-#, fuzzy
msgid "The font used to draw the title."
-msgstr "La police utilisée pour le texte en gras."
+msgstr ""
#: doc/classes/WindowDialog.xml
msgid "The icon for the close button."
@@ -87269,10 +91139,9 @@ msgid ""
msgstr ""
#: doc/classes/World.xml
-#, fuzzy
msgid ""
"The [RID] of this world's navigation map. Used by the [NavigationServer]."
-msgstr "Retourne le [RID] de la énième forme d'une zone."
+msgstr ""
#: doc/classes/World.xml
msgid "The World's visual scenario."
@@ -87307,10 +91176,9 @@ msgid ""
msgstr ""
#: doc/classes/World2D.xml
-#, fuzzy
msgid ""
"The [RID] of this world's navigation map. Used by the [Navigation2DServer]."
-msgstr "Retourne le [RID] de la énième forme d'une zone."
+msgstr ""
#: doc/classes/World2D.xml
msgid ""
diff --git a/doc/translations/gl.po b/doc/translations/gl.po
index 39d5ab2f2b..207a818761 100644
--- a/doc/translations/gl.po
+++ b/doc/translations/gl.po
@@ -848,7 +848,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7685,8 +7692,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9966,7 +9973,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10131,7 +10144,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11742,7 +11761,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12140,10 +12164,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 +19451,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 +19471,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 +19492,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
@@ -20143,7 +20177,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23529,7 +23563,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25360,7 +25394,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28401,13 +28435,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29820,7 +29855,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30394,10 +30432,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30409,6 +30451,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30720,6 +30768,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 ""
@@ -32437,7 +32490,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32453,7 +32506,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32483,7 +32536,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36120,7 +36173,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 +36284,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 ""
@@ -36575,7 +36636,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36836,7 +36897,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36950,6 +37011,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39647,7 +39754,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39659,7 +39772,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45263,6 +45377,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49810,8 +49931,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
@@ -54187,7 +54308,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54227,15 +54349,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55711,11 +55834,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57385,7 +57527,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58180,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
@@ -58777,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
@@ -60250,8 +60418,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60316,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."
@@ -63870,13 +64042,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63888,13 +64061,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65702,11 +65876,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65786,8 +65960,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66390,9 +66564,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 +66596,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
@@ -70775,7 +70954,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70860,6 +71043,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/hi.po b/doc/translations/hi.po
index a104e2ae6d..2df4b9bbe4 100644
--- a/doc/translations/hi.po
+++ b/doc/translations/hi.po
@@ -847,7 +847,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7684,8 +7691,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9965,7 +9972,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10130,7 +10143,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11741,7 +11760,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12139,10 +12163,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 +19450,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 +19470,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 +19491,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
@@ -20142,7 +20176,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23528,7 +23562,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25359,7 +25393,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28400,13 +28434,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29819,7 +29854,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30393,10 +30431,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30408,6 +30450,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30719,6 +30767,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 ""
@@ -32436,7 +32489,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32452,7 +32505,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32482,7 +32535,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36119,7 +36172,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 +36283,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 ""
@@ -36574,7 +36635,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36835,7 +36896,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36949,6 +37010,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39646,7 +39753,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39658,7 +39771,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45262,6 +45376,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49809,8 +49930,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
@@ -54186,7 +54307,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54226,15 +54348,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55710,11 +55833,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57384,7 +57526,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58179,7 +58321,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 +58942,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
@@ -60249,8 +60417,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60315,6 +60483,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."
@@ -63869,13 +64041,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63887,13 +64060,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65701,11 +65875,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65785,8 +65959,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66389,9 +66563,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 +66595,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
@@ -70774,7 +70953,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70859,6 +71042,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/hu.po b/doc/translations/hu.po
index 280424c8c0..221206451a 100644
--- a/doc/translations/hu.po
+++ b/doc/translations/hu.po
@@ -866,7 +866,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7703,8 +7710,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9984,7 +9991,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10149,7 +10162,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11760,7 +11779,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12158,10 +12182,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 +19469,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 +19489,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 +19510,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
@@ -20161,7 +20195,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23547,7 +23581,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25378,7 +25412,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28419,13 +28453,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29838,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30412,10 +30450,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30427,6 +30469,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30738,6 +30786,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 ""
@@ -32455,7 +32508,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32471,7 +32524,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32501,7 +32554,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36138,7 +36191,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 +36302,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 ""
@@ -36593,7 +36654,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36854,7 +36915,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36968,6 +37029,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39665,7 +39772,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39677,7 +39790,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45281,6 +45395,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49828,8 +49949,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
@@ -54205,7 +54326,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54245,15 +54367,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55729,11 +55852,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57403,7 +57545,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58198,7 +58340,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 +58961,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
@@ -60268,8 +60436,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60334,6 +60502,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."
@@ -63888,13 +64060,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63906,13 +64079,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65720,11 +65894,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65804,8 +65978,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66408,9 +66582,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 +66614,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
@@ -70793,7 +70972,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70878,6 +71061,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/id.po b/doc/translations/id.po
index 2f741d544d..39310a6160 100644
--- a/doc/translations/id.po
+++ b/doc/translations/id.po
@@ -15,12 +15,13 @@
# ProgrammerIndonesia 44 <elo.jhy@gmail.com>, 2022.
# Reza Almanda <rezaalmanda27@gmail.com>, 2022.
# Tsaqib Fadhlurrahman Soka <sokatsaqib@gmail.com>, 2022.
+# yusuf afandi <afandi.yusuf.04@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-05-28 14:11+0000\n"
-"Last-Translator: Reza Almanda <rezaalmanda27@gmail.com>\n"
+"PO-Revision-Date: 2022-07-09 21:12+0000\n"
+"Last-Translator: yusuf afandi <afandi.yusuf.04@gmail.com>\n"
"Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/id/>\n"
"Language: id\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"
@@ -122,7 +123,7 @@ msgstr "Metode ini menerima sejumlah argumen setelah yang dijelaskan di sini."
#: doc/tools/make_rst.py
msgid "This method is used to construct a type."
-msgstr ""
+msgstr "Metode ini digunakan untuk mengkonstruksi sebuah tipe."
#: doc/tools/make_rst.py
msgid ""
@@ -1198,10 +1199,22 @@ msgstr ""
"atau peringatan dicetak."
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+#, fuzzy
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
-"Seperti [metode cetak], tetapi hanya mencetak saat digunakan dalam mode "
-"debug."
+"Mencetak trek tumpukan di lokasi kode, hanya berfungsi saat dijalankan "
+"dengan debugger dihidupkan.\n"
+"Output di konsol akan terlihat seperti ini:\n"
+"[codeblock]\n"
+"Frame 0 - res://test.gd:16 dalam fungsi '_process'\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
#, fuzzy
@@ -8096,8 +8109,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10377,7 +10390,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10542,7 +10561,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -12153,7 +12178,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12551,10 +12581,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 +19870,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 +19890,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 +19911,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
@@ -20556,7 +20596,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23946,7 +23986,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25783,7 +25823,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28825,13 +28865,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30244,7 +30285,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30818,10 +30862,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30833,6 +30881,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -31144,6 +31198,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 ""
@@ -32861,7 +32920,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32877,7 +32936,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32907,7 +32966,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36564,7 +36623,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 +36735,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 ""
@@ -37020,7 +37087,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37281,7 +37348,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37397,6 +37464,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -40094,7 +40207,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40106,7 +40225,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45728,6 +45848,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50277,8 +50404,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
@@ -54655,7 +54782,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54695,15 +54823,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56179,11 +56308,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57853,7 +58001,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58650,7 +58798,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 +59419,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
@@ -60724,8 +60898,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60790,6 +60964,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."
@@ -64345,13 +64523,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64363,13 +64542,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -66177,11 +66357,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66261,8 +66441,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66865,9 +67045,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 +67077,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
@@ -71255,7 +71440,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71340,6 +71529,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/is.po b/doc/translations/is.po
index 4dd42d807e..e3080abf39 100644
--- a/doc/translations/is.po
+++ b/doc/translations/is.po
@@ -847,7 +847,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7684,8 +7691,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9965,7 +9972,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10130,7 +10143,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11741,7 +11760,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12139,10 +12163,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 +19450,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 +19470,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 +19491,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
@@ -20142,7 +20176,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23528,7 +23562,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25359,7 +25393,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28400,13 +28434,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29819,7 +29854,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30393,10 +30431,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30408,6 +30450,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30719,6 +30767,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 ""
@@ -32436,7 +32489,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32452,7 +32505,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32482,7 +32535,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36119,7 +36172,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 +36283,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 ""
@@ -36574,7 +36635,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36835,7 +36896,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36949,6 +37010,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39646,7 +39753,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39658,7 +39771,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45262,6 +45376,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49809,8 +49930,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
@@ -54186,7 +54307,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54226,15 +54348,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55710,11 +55833,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57384,7 +57526,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58179,7 +58321,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 +58942,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
@@ -60249,8 +60417,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60315,6 +60483,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."
@@ -63869,13 +64041,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63887,13 +64060,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65701,11 +65875,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65785,8 +65959,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66389,9 +66563,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 +66595,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
@@ -70774,7 +70953,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70859,6 +71042,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/it.po b/doc/translations/it.po
index 9157d2ecc0..e07c906b29 100644
--- a/doc/translations/it.po
+++ b/doc/translations/it.po
@@ -25,12 +25,13 @@
# Andrea Leganza <neogene@gmail.com>, 2021.
# Federico Caprini <caprinifede@gmail.com>, 2022.
# Alessandro Casalino <alessandro.casalino93@gmail.com>, 2022.
+# AndreWharn <andrewharnofficial@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-04-25 15:12+0000\n"
-"Last-Translator: Micila Micillotto <micillotto@gmail.com>\n"
+"PO-Revision-Date: 2022-07-31 16:43+0000\n"
+"Last-Translator: Mirko <miknsop@gmail.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/it/>\n"
"Language: it\n"
@@ -38,7 +39,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.12.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -61,6 +62,7 @@ msgid "Theme Properties"
msgstr "Proprietà del tema"
#: doc/tools/make_rst.py
+#, fuzzy
msgid "Signals"
msgstr "Segnali"
@@ -101,18 +103,16 @@ msgid "Default"
msgstr "Predefinito"
#: doc/tools/make_rst.py
-#, fuzzy
msgid "Setter"
-msgstr "Impostatore"
+msgstr "Setter"
#: doc/tools/make_rst.py
msgid "value"
msgstr "valore"
#: doc/tools/make_rst.py
-#, fuzzy
msgid "Getter"
-msgstr "Acchiappatore"
+msgstr "Getter"
#: doc/tools/make_rst.py
msgid ""
@@ -137,9 +137,8 @@ msgstr ""
"qui."
#: doc/tools/make_rst.py
-#, fuzzy
msgid "This method is used to construct a type."
-msgstr "Questo metodo viene utilizzato per creare un tipo di variabile."
+msgstr "Questo metodo viene utilizzato per creare un tipo."
#: doc/tools/make_rst.py
msgid ""
@@ -1372,10 +1371,22 @@ msgstr ""
"messaggi di debug ed errore che vengono mostrati con la stack trace."
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+#, fuzzy
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
-"Come [method print], ma stampa solo quando viene utilizzato in modalità "
-"debug."
+"Stampa un stack trace nella posizione del codice, funziona solo quando il "
+"debugger è attivato.\n"
+"L'output nella console apparirà come:\n"
+"[codeblock]\n"
+"Frame 0 - res://test.gd:16 in function '_process'\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -8702,8 +8713,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10991,7 +11002,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -11156,7 +11173,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -12771,7 +12794,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -13170,10 +13198,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 +20593,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 +20613,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 +20634,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
@@ -21281,7 +21319,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -24681,7 +24719,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -26521,7 +26559,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -29585,13 +29623,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -31009,7 +31048,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -31584,10 +31626,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -31598,6 +31644,13 @@ msgid "Mouse and input coordinates"
msgstr ""
#: doc/classes/InputEventMouseMotion.xml
+#, fuzzy
+msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr "Ritorna [code]true[/code] se [code]s[/code] è zero o quasi zero."
+
+#: doc/classes/InputEventMouseMotion.xml
msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
@@ -31914,6 +31967,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 ""
@@ -33641,7 +33699,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33657,7 +33715,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33690,7 +33748,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -37368,7 +37426,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 +37539,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 ""
@@ -37834,7 +37900,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -38098,7 +38164,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -38217,6 +38283,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -40922,7 +41034,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40934,7 +41052,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -46584,6 +46703,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -51136,8 +51262,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
@@ -55524,7 +55650,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55564,15 +55691,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56833,7 +56961,7 @@ msgstr ""
#: doc/classes/Spatial.xml
msgid "Introduction to 3D"
-msgstr ""
+msgstr "Introduzione al 3D"
#: doc/classes/Spatial.xml doc/classes/Vector3.xml
msgid "All 3D Demos"
@@ -57050,11 +57178,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -58729,7 +58876,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -59529,7 +59676,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 +60297,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
@@ -61619,8 +61792,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -61688,6 +61861,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."
@@ -65276,13 +65456,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -65294,13 +65475,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -67132,11 +67314,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -67216,8 +67398,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -67830,9 +68012,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 +68047,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
@@ -72251,11 +72438,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
-"Se [code] vero [/code], i nodi figli sono ordinati, altrimenti l'ordinamento "
-"è disabilitato."
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -72339,6 +72527,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/ja.po b/doc/translations/ja.po
index 75d4179693..fe76c741d0 100644
--- a/doc/translations/ja.po
+++ b/doc/translations/ja.po
@@ -1333,8 +1333,22 @@ msgstr ""
"ãŸã¨ãã«ã‚¹ã‚¿ãƒƒã‚¯ãƒˆãƒ¬ãƒ¼ã‚¹ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
-msgstr "[method print] ã¨åŒæ§˜ã§ã™ãŒã€ã—ã‹ã—デãƒãƒƒã‚°ãƒ¢ãƒ¼ãƒ‰æ™‚ã«ã®ã¿è¡¨ç¤ºã—ã¾ã™ã€‚"
+#, fuzzy
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
+msgstr ""
+"コードä½ç½®ã®ã‚¹ã‚¿ãƒƒã‚¯ãƒˆãƒ©ãƒƒã‚¯ã‚’表示ã—ã¾ã™ã€‚デãƒãƒƒã‚¬ã‚’有効ã«ã—ã¦å®Ÿè¡Œã—ãŸæ™‚ã«ã®"
+"ã¿å‹•作ã—ã¾ã™ã€‚\n"
+"コンソール内ã§ã®å‡ºåŠ›ã¯ã“ã®ã‚ˆã†ã«ãªã‚Šã¾ã™:\n"
+"[codeblock]\n"
+"Frame 0 - res://test.gd:16 in function '_process'\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -9918,8 +9932,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -12677,8 +12691,14 @@ msgstr ""
"ã¾ã™ã€‚"
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
-msgstr "ã“ã®ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªãŒå†ç”Ÿã•れã¦ã„ã‚‹ãƒã‚¹ã€‚"
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
+msgstr ""
#: doc/classes/AudioStreamPlayer.xml
msgid ""
@@ -12860,9 +12880,14 @@ msgstr ""
"ã¾ã™ã€‚"
#: doc/classes/AudioStreamPlayer3D.xml
-#, fuzzy
-msgid "The bus on which this audio is playing."
-msgstr "ã“ã®ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªãŒå†ç”Ÿã•れã¦ã„ã‚‹ãƒã‚¹ã€‚"
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
+msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
msgid ""
@@ -14706,7 +14731,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -15107,10 +15137,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 +22593,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 +22613,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 +22634,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
@@ -23281,7 +23321,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -26704,7 +26744,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -28546,7 +28586,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -31638,13 +31678,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -33071,7 +33112,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -33645,10 +33689,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -33659,6 +33707,14 @@ msgid "Mouse and input coordinates"
msgstr ""
#: doc/classes/InputEventMouseMotion.xml
+#, fuzzy
+msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+"文字列ã®é•·ã•㌠[code]0[/code] ã«ç­‰ã—ã‘れ㰠[code]true[/code] ã‚’è¿”ã—ã¾ã™ã€‚"
+
+#: doc/classes/InputEventMouseMotion.xml
msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
@@ -33977,6 +34033,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 ""
@@ -35737,7 +35798,7 @@ msgstr "円柱ã®é«˜ã•。"
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -35753,7 +35814,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -35789,7 +35850,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -39508,7 +39569,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 +39684,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 ""
@@ -39978,7 +40047,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -40245,7 +40314,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -40366,6 +40435,53 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+#, fuzzy
+msgid "Set the max packet size that this peer can handle."
+msgstr "指定ã•れãŸåå‰ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ãƒŽãƒ¼ãƒ‰ã‚’è¿”ã—ã¾ã™ã€‚"
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -43074,7 +43190,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -43086,7 +43208,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -48758,6 +48881,14 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+#, fuzzy
+msgid "Sorts the elements of the array in ascending order."
+msgstr "インデックスã«ã‚ˆã‚Šé…列ã‹ã‚‰è¦ç´ ã‚’削除ã—ã¾ã™ã€‚"
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -53345,8 +53476,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
@@ -57773,7 +57904,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -57813,15 +57945,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -59307,11 +59440,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -61257,7 +61409,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -62077,7 +62229,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 +62850,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
@@ -64184,8 +64362,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -64251,6 +64429,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."
@@ -67873,13 +68056,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -67891,13 +68075,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -69730,11 +69915,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -69814,8 +69999,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -70432,9 +70617,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 +70650,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
@@ -74921,9 +75111,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
-msgstr "[code]true[/code]ã®å ´åˆã€é ‚点色をアルベド色ã¨ã—ã¦ä½¿ç”¨ã—ã¾ã™ã€‚"
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -75007,6 +75200,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/ko.po b/doc/translations/ko.po
index a30a93f652..ac9274cee6 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"
@@ -1003,7 +1004,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7858,8 +7866,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10140,7 +10148,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10305,7 +10319,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11918,7 +11938,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12316,10 +12341,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 +19677,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 +19697,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 +19718,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
@@ -20429,7 +20464,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23821,7 +23856,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25659,7 +25694,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28702,13 +28737,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30129,7 +30165,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30703,10 +30742,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30718,6 +30761,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -31030,6 +31079,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 ""
@@ -32750,7 +32804,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32766,7 +32820,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32796,7 +32850,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36462,7 +36516,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 +36629,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 ""
@@ -36922,7 +36984,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37185,7 +37247,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37303,6 +37365,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -40126,7 +40234,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40138,7 +40252,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45768,6 +45883,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50318,8 +50440,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
@@ -54697,7 +54819,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54737,15 +54860,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56221,11 +56345,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57895,7 +58038,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58692,7 +58835,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 +59456,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
@@ -60770,8 +60939,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60836,6 +61005,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."
@@ -64398,13 +64572,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64416,13 +64591,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -66232,11 +66408,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66316,8 +66492,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66936,9 +67112,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 +67144,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
@@ -71338,7 +71519,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71423,6 +71608,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/lt.po b/doc/translations/lt.po
index 1139bf4f82..79790f5e70 100644
--- a/doc/translations/lt.po
+++ b/doc/translations/lt.po
@@ -857,7 +857,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7694,8 +7701,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9975,7 +9982,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10140,7 +10153,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11751,7 +11770,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12149,10 +12173,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 +19460,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 +19480,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 +19501,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
@@ -20152,7 +20186,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23538,7 +23572,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25369,7 +25403,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28410,13 +28444,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29829,7 +29864,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30403,10 +30441,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30418,6 +30460,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30729,6 +30777,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 ""
@@ -32446,7 +32499,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32462,7 +32515,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32492,7 +32545,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36129,7 +36182,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 +36293,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 ""
@@ -36584,7 +36645,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36845,7 +36906,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36959,6 +37020,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39656,7 +39763,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39668,7 +39781,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45272,6 +45386,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49819,8 +49940,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
@@ -54196,7 +54317,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54236,15 +54358,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55720,11 +55843,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57394,7 +57536,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58189,7 +58331,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 +58952,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
@@ -60259,8 +60427,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60325,6 +60493,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."
@@ -63879,13 +64051,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63897,13 +64070,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65711,11 +65885,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65795,8 +65969,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66399,9 +66573,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 +66605,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
@@ -70784,7 +70963,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70869,6 +71052,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/lv.po b/doc/translations/lv.po
index 627035b696..1f63bf69bb 100644
--- a/doc/translations/lv.po
+++ b/doc/translations/lv.po
@@ -862,7 +862,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7699,8 +7706,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9980,7 +9987,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10145,7 +10158,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11756,7 +11775,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12154,10 +12178,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 +19465,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 +19485,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 +19506,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
@@ -20157,7 +20191,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23546,7 +23580,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25377,7 +25411,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28418,13 +28452,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29837,7 +29872,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30411,10 +30449,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30426,6 +30468,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30737,6 +30785,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 ""
@@ -32454,7 +32507,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32470,7 +32523,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32500,7 +32553,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36137,7 +36190,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 +36301,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 ""
@@ -36592,7 +36653,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36853,7 +36914,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36967,6 +37028,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39664,7 +39771,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39676,7 +39789,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45280,6 +45394,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49827,8 +49948,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
@@ -54204,7 +54325,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54244,15 +54366,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55728,11 +55851,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57402,7 +57544,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58197,7 +58339,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 +58960,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
@@ -60267,8 +60435,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60333,6 +60501,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."
@@ -63887,13 +64059,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63905,13 +64078,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65719,11 +65893,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65803,8 +65977,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66407,9 +66581,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 +66613,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
@@ -70792,7 +70971,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70877,6 +71060,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/mr.po b/doc/translations/mr.po
index d4e8907c1d..32832a4d8f 100644
--- a/doc/translations/mr.po
+++ b/doc/translations/mr.po
@@ -845,7 +845,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7682,8 +7689,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9963,7 +9970,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10128,7 +10141,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11739,7 +11758,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12137,10 +12161,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 +19448,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 +19468,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 +19489,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
@@ -20140,7 +20174,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23526,7 +23560,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25357,7 +25391,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28398,13 +28432,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29817,7 +29852,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30391,10 +30429,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30406,6 +30448,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30717,6 +30765,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 ""
@@ -32434,7 +32487,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32450,7 +32503,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32480,7 +32533,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36117,7 +36170,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 +36281,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 ""
@@ -36572,7 +36633,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36833,7 +36894,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36947,6 +37008,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39644,7 +39751,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39656,7 +39769,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45260,6 +45374,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49807,8 +49928,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
@@ -54184,7 +54305,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54224,15 +54346,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55708,11 +55831,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57382,7 +57524,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58177,7 +58319,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 +58940,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
@@ -60247,8 +60415,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60313,6 +60481,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."
@@ -63867,13 +64039,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63885,13 +64058,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65699,11 +65873,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65783,8 +65957,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66387,9 +66561,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 +66593,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
@@ -70772,7 +70951,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70857,6 +71040,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/nb.po b/doc/translations/nb.po
index 9aa8c17200..42dca83c45 100644
--- a/doc/translations/nb.po
+++ b/doc/translations/nb.po
@@ -857,7 +857,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7694,8 +7701,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9975,7 +9982,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10140,7 +10153,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11751,7 +11770,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12149,10 +12173,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 +19460,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 +19480,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 +19501,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
@@ -20152,7 +20186,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23538,7 +23572,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25369,7 +25403,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28410,13 +28444,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29829,7 +29864,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30403,10 +30441,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30418,6 +30460,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30729,6 +30777,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 ""
@@ -32446,7 +32499,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32462,7 +32515,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32492,7 +32545,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36129,7 +36182,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 +36293,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 ""
@@ -36584,7 +36645,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36845,7 +36906,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36959,6 +37020,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39656,7 +39763,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39668,7 +39781,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45272,6 +45386,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49819,8 +49940,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
@@ -54196,7 +54317,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54236,15 +54358,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55720,11 +55843,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57394,7 +57536,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58189,7 +58331,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 +58952,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
@@ -60259,8 +60427,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60325,6 +60493,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."
@@ -63879,13 +64051,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63897,13 +64070,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65711,11 +65885,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65795,8 +65969,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66399,9 +66573,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 +66605,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
@@ -70784,7 +70963,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70869,6 +71052,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/ne.po b/doc/translations/ne.po
index f129446976..0ba02ba939 100644
--- a/doc/translations/ne.po
+++ b/doc/translations/ne.po
@@ -845,7 +845,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7682,8 +7689,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9963,7 +9970,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10128,7 +10141,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11739,7 +11758,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12137,10 +12161,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 +19448,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 +19468,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 +19489,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
@@ -20140,7 +20174,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23526,7 +23560,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25357,7 +25391,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28398,13 +28432,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29817,7 +29852,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30391,10 +30429,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30406,6 +30448,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30717,6 +30765,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 ""
@@ -32434,7 +32487,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32450,7 +32503,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32480,7 +32533,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36117,7 +36170,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 +36281,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 ""
@@ -36572,7 +36633,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36833,7 +36894,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36947,6 +37008,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39644,7 +39751,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39656,7 +39769,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45260,6 +45374,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49807,8 +49928,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
@@ -54184,7 +54305,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54224,15 +54346,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55708,11 +55831,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57382,7 +57524,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58177,7 +58319,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 +58940,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
@@ -60247,8 +60415,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60313,6 +60481,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."
@@ -63867,13 +64039,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63885,13 +64058,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65699,11 +65873,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65783,8 +65957,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66387,9 +66561,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 +66593,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
@@ -70772,7 +70951,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70857,6 +71040,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/nl.po b/doc/translations/nl.po
index 7a96e774df..3053cadb2b 100644
--- a/doc/translations/nl.po
+++ b/doc/translations/nl.po
@@ -906,7 +906,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7751,8 +7758,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10032,7 +10039,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10197,7 +10210,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11808,7 +11827,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12206,10 +12230,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 +19517,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 +19537,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 +19558,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
@@ -20209,7 +20243,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23598,7 +23632,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25429,7 +25463,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28470,13 +28504,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29889,7 +29924,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30463,10 +30501,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30478,6 +30520,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30789,6 +30837,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 ""
@@ -32506,7 +32559,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32522,7 +32575,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32552,7 +32605,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36189,7 +36242,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 +36353,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 ""
@@ -36644,7 +36705,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36905,7 +36966,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37019,6 +37080,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39716,7 +39823,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39728,7 +39841,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45332,6 +45446,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49879,8 +50000,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
@@ -54257,7 +54378,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54297,15 +54419,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55781,11 +55904,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57455,7 +57597,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58250,7 +58392,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 +59013,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
@@ -60320,8 +60488,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60386,6 +60554,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."
@@ -63940,13 +64112,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63958,13 +64131,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65772,11 +65946,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65856,8 +66030,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66460,9 +66634,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 +66666,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
@@ -70845,7 +71024,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70930,6 +71113,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/pl.po b/doc/translations/pl.po
index 640cfea1c8..729b6a654c 100644
--- a/doc/translations/pl.po
+++ b/doc/translations/pl.po
@@ -1279,8 +1279,22 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
-msgstr "Jak [method print], ale wypisuje tylko w trybie debugowania."
+#, fuzzy
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
+msgstr ""
+"Wypisuje zrzut stosu w miejscu kodu, działa tylko przy uruchamianiu z "
+"włączonym debuggerem.\n"
+"Wynik w konsoli wyglądać może tak:\n"
+"[codeblock]\n"
+"Frame 0 - res://test.gd:16 in function '_process'\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -8189,8 +8203,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10471,7 +10485,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10636,7 +10656,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -12250,7 +12276,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12651,10 +12682,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 +19996,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 +20016,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 +20037,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
@@ -20681,7 +20722,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -24080,7 +24121,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25917,7 +25958,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28976,13 +29017,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30398,7 +30440,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30972,10 +31017,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30987,6 +31036,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -31302,6 +31357,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 ""
@@ -33035,7 +33095,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33051,7 +33111,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33084,7 +33144,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36769,7 +36829,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 +36942,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 ""
@@ -37232,7 +37300,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37496,7 +37564,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37615,6 +37683,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -40312,7 +40426,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40324,7 +40444,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45976,6 +46097,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50526,8 +50654,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
@@ -54916,7 +55044,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54956,15 +55085,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56441,11 +56571,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -58118,7 +58267,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58915,7 +59064,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 +59685,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
@@ -60994,8 +61169,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -61063,6 +61238,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."
@@ -64634,13 +64816,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64652,13 +64835,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -66469,11 +66653,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66553,8 +66737,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -67169,9 +67353,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 +67388,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
@@ -71581,11 +71770,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
-"Jeśli [code]true[/code], potomne węzły są sortowane. W innym przypadku jest "
-"wyłączone."
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -71669,6 +71859,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/pt.po b/doc/translations/pt.po
index 54c5f5f2ef..c99a8e1cd6 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 ""
@@ -1326,9 +1340,22 @@ msgstr ""
"rastreamento de pilha quando um erro ou aviso é impresso ."
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+#, fuzzy
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
-"Igual [method print], mas só imprime quando usado em modo de depuração."
+"Imprime a pilha de chamadas no local do código, só funciona com o depurador "
+"ativado.\n"
+"Saída no console vai parecer assim:\n"
+"[codeblock]\n"
+"Frame 0 - res://test.gd:16 in function '_process'\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1463,7 +1490,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 +1498,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 +4605,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 +5823,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 +6517,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 +6807,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)."
@@ -8497,8 +8519,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10778,7 +10800,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10943,7 +10971,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -12559,7 +12593,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12958,10 +12997,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 +13790,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 +14861,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 +16429,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 +20330,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 +20350,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 +20371,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
@@ -21010,7 +21056,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -24406,7 +24452,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -26243,7 +26289,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -29285,13 +29331,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30704,7 +30751,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -31278,10 +31328,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -31293,6 +31347,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -31608,6 +31668,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 ""
@@ -33336,7 +33401,7 @@ msgstr "A altura do cilindro."
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33352,7 +33417,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33383,7 +33448,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -37046,7 +37111,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 +37224,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 ""
@@ -37504,7 +37577,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37769,7 +37842,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37887,6 +37960,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -38441,7 +38560,7 @@ msgstr ""
#: doc/classes/Node.xml
msgid "Nodes and Scenes"
-msgstr ""
+msgstr "Nós e Cenas"
#: doc/classes/Node.xml
msgid "All Demos"
@@ -40584,7 +40703,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40596,7 +40721,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -46205,6 +46331,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49310,68 +49443,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 +49566,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 +49621,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 +49638,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 +49653,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 +49711,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 +49721,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 +49731,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 +49741,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 +49751,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 +50951,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
@@ -55136,7 +55331,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55176,15 +55372,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56662,11 +56859,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -58354,7 +58570,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -59151,7 +59367,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 +59988,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
@@ -61225,8 +61467,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -61291,6 +61533,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."
@@ -64859,13 +65106,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64877,13 +65125,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -66695,11 +66944,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66779,8 +67028,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -67385,9 +67634,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 +67666,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
@@ -71773,7 +72027,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71858,6 +72116,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/pt_BR.po b/doc/translations/pt_BR.po
index b32492887a..ea624fdf2c 100644
--- a/doc/translations/pt_BR.po
+++ b/doc/translations/pt_BR.po
@@ -41,12 +41,13 @@
# Fabio Moura de Oliveira <ccmaismais@yahoo.com>, 2022.
# Daniel Abrante <danielabrante@protonmail.com>, 2022.
# lucas rossy brasil coelho <lucasrossy270@gmail.com>, 2022.
+# Felipe Kinoshita <kinofhek@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-16 18:58+0000\n"
-"Last-Translator: lucas rossy brasil coelho <lucasrossy270@gmail.com>\n"
+"PO-Revision-Date: 2022-08-04 06:40+0000\n"
+"Last-Translator: Felipe Kinoshita <kinofhek@gmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot-class-reference/pt_BR/>\n"
"Language: pt_BR\n"
@@ -54,7 +55,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.14-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -1368,9 +1369,22 @@ msgstr ""
"rastreamento de pilha quando um erro ou aviso é impresso ."
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+#, fuzzy
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
-"Igual [method print], mas só imprime quando usado em modo de depuração."
+"Imprime a pilha de chamadas no local do código, só funciona com o depurador "
+"habilitado.\n"
+"Saída no console vai parecer assim:\n"
+"[codeblock]\n"
+"Frame 0 - res://test.gd:16 in function '_process'\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -8742,8 +8756,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -11025,7 +11039,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -11190,7 +11210,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -12808,7 +12834,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -13209,10 +13240,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 +20625,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 +20645,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 +20666,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
@@ -21310,7 +21351,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -24713,7 +24754,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -26552,7 +26593,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -29619,13 +29660,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -31043,7 +31085,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -31617,10 +31662,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -31632,6 +31681,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -31951,6 +32006,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 ""
@@ -33679,7 +33739,7 @@ msgstr "A altura do cilindro."
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33695,7 +33755,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33728,7 +33788,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -37411,7 +37471,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 +37585,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 ""
@@ -37876,7 +37944,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -38142,7 +38210,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -38261,6 +38329,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -40958,7 +41072,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40970,7 +41090,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -46624,6 +46745,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -51178,8 +51306,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
@@ -55568,7 +55696,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55608,15 +55737,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -57096,11 +57226,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -58791,7 +58940,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -59588,7 +59737,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 +60358,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
@@ -61677,8 +61852,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -61746,6 +61921,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."
@@ -65325,13 +65505,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -65343,13 +65524,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -67163,11 +67345,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -67247,8 +67429,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -67861,9 +68043,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 +68078,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
@@ -72276,11 +72463,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
-"Se [code]true[/code], os nós filhos são organizados, do contrário, a "
-"organização é desabilitada."
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -72364,6 +72552,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
@@ -76558,6 +76755,13 @@ msgid ""
"the same space as the parent YSort, allowing to better organize a scene or "
"divide it in multiple ones, yet keep the unique sorting."
msgstr ""
+"Classifique todos os nós filhos com base em suas posições Y. O nó filho deve "
+"herdar de [CanvasItem] para ser classificado. Os nós que têm uma posição Y "
+"mais alta serão desenhados mais tarde, então eles aparecerão no topo dos nós "
+"que têm uma posição Y mais baixa. O aninhamento de nós YSort é possível. Os "
+"nós YSort filhos serão classificados no mesmo espaço que o YSort pai, "
+"permitindo organizar melhor uma cena ou dividi-la em várias outras, mas "
+"manter a classificação única."
#: doc/classes/YSort.xml
msgid ""
diff --git a/doc/translations/ro.po b/doc/translations/ro.po
index 260a63446f..332dbd0801 100644
--- a/doc/translations/ro.po
+++ b/doc/translations/ro.po
@@ -873,7 +873,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7714,8 +7721,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9995,7 +10002,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10160,7 +10173,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11771,7 +11790,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12169,10 +12193,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 +19480,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 +19500,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 +19521,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
@@ -20172,7 +20206,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23561,7 +23595,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25392,7 +25426,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28433,13 +28467,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29852,7 +29887,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30426,10 +30464,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30441,6 +30483,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30752,6 +30800,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 ""
@@ -32469,7 +32522,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32485,7 +32538,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32515,7 +32568,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36152,7 +36205,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 +36316,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 ""
@@ -36607,7 +36668,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36868,7 +36929,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36983,6 +37044,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39680,7 +39787,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39692,7 +39805,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45296,6 +45410,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49843,8 +49964,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
@@ -54220,7 +54341,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54260,15 +54382,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55744,11 +55867,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57418,7 +57560,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58213,7 +58355,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 +58976,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
@@ -60283,8 +60451,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60349,6 +60517,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."
@@ -63903,13 +64075,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63921,13 +64094,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65735,11 +65909,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65819,8 +65993,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66423,9 +66597,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 +66629,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
@@ -70808,7 +70987,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70893,6 +71076,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/ru.po b/doc/translations/ru.po
index 36dbb7d50d..b148868ce6 100644
--- a/doc/translations/ru.po
+++ b/doc/translations/ru.po
@@ -48,21 +48,23 @@
# Bozhko Artyom Dmitrievich <jek_sun@mail.ru>, 2022.
# FuzzMix <fmwolfiechad@gmail.com>, 2022.
# МÐÐ69К <weblate@mah69k.net>, 2022.
+# Vadim Mitroshkin <Vadim7540@yandex.ru>, 2022.
+# SonicStalker Games <dmitriyusolsev1971@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-08 06:47+0000\n"
-"Last-Translator: FuzzMix <fmwolfiechad@gmail.com>\n"
+"PO-Revision-Date: 2022-08-04 06:40+0000\n"
+"Last-Translator: SonicStalker Games <dmitriyusolsev1971@gmail.com>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"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"
+"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.14-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -154,7 +156,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 +536,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 +561,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]. Это "
@@ -619,11 +621,11 @@ msgstr ""
"[codeblock]\n"
"- Меньше -1,0 (не включаÑ): Облегчение вхождениÑ-выхождениÑ\n"
"- 1.0: Линейный\n"
-"- От -1,0 до 0,0 (не включаÑ): Облегчение в\n"
+"- От -1,0 до 0,0 (не включаÑ): Облегчение выхождениÑ-вхождениÑ\n"
"- 0.0: ПоÑтоÑнный\n"
-"- От 0,0 до 1,0 (не включаÑ): Облегчение\n"
+"- От 0,0 до 1,0 (не включаÑ): Облегчение выхождениÑ(только выход)\n"
"- 1.0: Линейный\n"
-"- Больше 1,0 (не включаÑ): Облегчение\n"
+"- Больше 1,0 (не включаÑ): Облегчение вхождениÑ(только вход)\n"
"[/codeblock]\n"
"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/"
"ease_cheatsheet.png]ease() Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÐºÑ€Ð¸Ð²Ð¾Ð¹ шпаргалка[/url]\n"
@@ -1006,7 +1008,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 +1033,7 @@ msgstr ""
"Ð›Ð¸Ð½ÐµÐ¹Ð½Ð°Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»ÑÑ†Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ Ð´Ð²ÑƒÐ¼Ñ ÑƒÐ³Ð»Ð°Ð¼Ð¸ (в радианах) по нормализованному "
"значению.\n"
"Ðналогично [методу lerp], но корректно интерполируетÑÑ, когда углы "
-"оборачивают вокруг [constant @GDScript.TAU]. Чтобы выполнить упрощенную "
+"оборачивают вокруг [конÑтанты @GDScript.TAU]. Чтобы выполнить упрощенную "
"интерполÑцию Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [метода lerp_angle], объедините его Ñ [методом ease] "
"или [методом smoothstep].\n"
"[codeblock]\n"
@@ -1043,7 +1044,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 +1300,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 +1321,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 +1346,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
@@ -1403,8 +1403,22 @@ msgstr ""
"траÑÑировка Ñтека при печати ошибки или предупреждениÑ."
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
-msgstr "Как [method print], но печатает только в режиме отладки."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
+msgstr ""
+"Как [method print], но включает в ÑÐµÐ±Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¹ кадр Ñтека когда запушен Ñ "
+"включенным отладчиком.\n"
+"Вывод в конÑоли будет выглÑдеть примерно так:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1525,7 +1539,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Converts an angle expressed in radians to degrees.\n"
"[codeblock]\n"
@@ -1534,7 +1547,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 +1594,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 +1672,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 +1726,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 +1736,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 ""
@@ -1780,19 +1832,30 @@ msgstr ""
"Возвращает результат плавной интерполÑции Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ [code]s[/code] между "
"[code]0[/code] и [code]1[/code], в завиÑимоÑти от того, где находитÑÑ "
"[code]s[/code] отноÑительно [code]from[/code] и [code]to[/code].\n"
+"\n"
"Возвращаемое значение равно [code]0[/code], еÑли [code]s <= from[/code] и "
"[code]1[/code], еÑли[code]s >= to[/code]. ЕÑли [code]s[/code] находитÑÑ "
"между [code]from[/code] и [code]to[/code], то возвращаемое значение Ñледует "
"S-образной кривой, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ ÑоответÑтвует значению [code]s[/code] между "
"[code]0[/code] и [code]1[/code].\n"
+"\n"
"S-Ð¾Ð±Ñ€Ð°Ð·Ð½Ð°Ñ ÐºÑ€Ð¸Ð²Ð°Ñ ÑвлÑетÑÑ ÐºÑƒÐ±Ð¸Ñ‡ÐµÑким Ñрмитовым Ñплайном, заданным функцией "
"[code]f(s) = 3*s^2 - 2*s^3[/code].\n"
+"\n"
"[codeblock]\n"
"smoothstep(0, 2, -5.0) # Returns 0.0\n"
"smoothstep(0, 2, 0.5) # Returns 0.15625\n"
"smoothstep(0, 2, 1.0) # Returns 0.5\n"
"smoothstep(0, 2, 2.0) # Returns 1.0\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"\n"
+"Compared to [method ease] with a curve value of [code]-1.6521[/code], ["
+"method smoothstep] returns the smoothest possible curve with no sudden "
+"changes in the derivative. If you need to perform more advanced transitions, "
+"use [Tween] or [AnimationPlayer].\n"
+"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.5/img/"
+"smoothstep_ease_comparison.png]Comparison between smoothstep() and ease(x, -1"
+".6521) return values[/url]"
#: modules/gdscript/doc_classes/@GDScript.xml
#, fuzzy
@@ -9315,8 +9378,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -11607,7 +11670,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -11772,7 +11841,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -13398,7 +13473,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -13799,10 +13879,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 +21313,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 +21333,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 +21354,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
@@ -21949,7 +22039,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -25360,7 +25450,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -27200,7 +27290,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -30261,13 +30351,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -31684,7 +31775,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -32258,10 +32352,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -32272,6 +32370,15 @@ msgid "Mouse and input coordinates"
msgstr ""
#: doc/classes/InputEventMouseMotion.xml
+#, fuzzy
+msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+"Возвращает [code]true[/code] еÑли [code]a[/code] и [code]b[/code] "
+"приблизительно равны друг другу."
+
+#: doc/classes/InputEventMouseMotion.xml
msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
@@ -32586,6 +32693,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 ""
@@ -34335,7 +34447,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -34351,7 +34463,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -34384,7 +34496,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -38070,7 +38182,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 +38295,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 ""
@@ -38536,7 +38656,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -38801,7 +38921,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -38933,6 +39053,53 @@ msgstr ""
msgid "Control activation of this server."
msgstr "Управление активацией данного Ñервера."
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+#, fuzzy
+msgid "Set the max packet size that this peer can handle."
+msgstr "Возвращает длину вектора."
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
#, fuzzy
msgid ""
@@ -41705,7 +41872,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -41717,7 +41890,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -47383,6 +47557,14 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+#, fuzzy
+msgid "Sorts the elements of the array in ascending order."
+msgstr "УдалÑет Ñлемент из маÑÑива по индекÑу."
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -51969,8 +52151,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
@@ -56406,7 +56588,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56446,15 +56629,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -57937,11 +58121,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -59616,7 +59819,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -60441,7 +60644,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 +61265,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
@@ -62531,8 +62760,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -62598,6 +62827,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."
@@ -66203,15 +66437,16 @@ msgstr ""
#: doc/classes/TreeItem.xml
#, fuzzy
msgid ""
-"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."
msgstr ""
"Возвращает поÑледний Ñлемент маÑÑива, или[code]null[/code] еÑли маÑÑив "
"пуÑтой."
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -66224,15 +66459,16 @@ msgstr ""
#: doc/classes/TreeItem.xml
#, fuzzy
msgid ""
-"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."
msgstr ""
"Возвращает первый Ñлемент в маÑÑиве, или [code]null[/code] еÑли маÑÑив "
"пуÑтой."
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -68167,11 +68403,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -68251,8 +68487,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -68866,9 +69102,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 +69135,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
@@ -73299,9 +73540,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
-msgstr "ЕÑли [code]true[/code], текÑтура будет центрирована."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -73385,6 +73629,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/sk.po b/doc/translations/sk.po
index 9fb9613f0d..ddcdeb10f1 100644
--- a/doc/translations/sk.po
+++ b/doc/translations/sk.po
@@ -848,7 +848,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7685,8 +7692,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9966,7 +9973,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10131,7 +10144,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11742,7 +11761,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12140,10 +12164,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 +19451,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 +19471,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 +19492,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
@@ -20143,7 +20177,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23532,7 +23566,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25363,7 +25397,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28404,13 +28438,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29823,7 +29858,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30397,10 +30435,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30412,6 +30454,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30723,6 +30771,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 ""
@@ -32440,7 +32493,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32456,7 +32509,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32486,7 +32539,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36123,7 +36176,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 +36287,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 ""
@@ -36578,7 +36639,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36839,7 +36900,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36953,6 +37014,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39650,7 +39757,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39662,7 +39775,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45266,6 +45380,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49813,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
@@ -54190,7 +54311,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54230,15 +54352,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55714,11 +55837,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57388,7 +57530,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58183,7 +58325,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 +58946,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
@@ -60253,8 +60421,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60319,6 +60487,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."
@@ -63873,13 +64045,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63891,13 +64064,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65705,11 +65879,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65789,8 +65963,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66393,9 +66567,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 +66599,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
@@ -70778,7 +70957,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70863,6 +71046,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/sr_Cyrl.po b/doc/translations/sr_Cyrl.po
index 765c89be10..6a336f195b 100644
--- a/doc/translations/sr_Cyrl.po
+++ b/doc/translations/sr_Cyrl.po
@@ -859,7 +859,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7696,8 +7703,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9977,7 +9984,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10142,7 +10155,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11753,7 +11772,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12151,10 +12175,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 +19462,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 +19482,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 +19503,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
@@ -20154,7 +20188,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23543,7 +23577,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25374,7 +25408,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28415,13 +28449,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29834,7 +29869,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30408,10 +30446,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30423,6 +30465,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30734,6 +30782,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 ""
@@ -32451,7 +32504,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32467,7 +32520,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32497,7 +32550,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36134,7 +36187,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 +36298,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 ""
@@ -36589,7 +36650,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36850,7 +36911,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36964,6 +37025,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39661,7 +39768,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39673,7 +39786,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45277,6 +45391,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49824,8 +49945,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
@@ -54201,7 +54322,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54241,15 +54363,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55725,11 +55848,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57399,7 +57541,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58194,7 +58336,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 +58957,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
@@ -60264,8 +60432,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60330,6 +60498,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."
@@ -63884,13 +64056,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63902,13 +64075,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65716,11 +65890,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65800,8 +65974,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66404,9 +66578,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 +66610,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
@@ -70789,7 +70968,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70874,6 +71057,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/sv.po b/doc/translations/sv.po
index 706b410d30..b582952401 100644
--- a/doc/translations/sv.po
+++ b/doc/translations/sv.po
@@ -6,12 +6,13 @@
# Christoffer Sundbom <christoffer_karlsson@live.se>, 2021.
# Kent Jofur <kent.jofur@gmail.com>, 2021.
# Alex25820 <alexs25820@gmail.com>, 2021.
+# Björn Åkesson <bjorn.akesson@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: 2021-12-19 17:31+0000\n"
-"Last-Translator: Alex25820 <alexs25820@gmail.com>\n"
+"PO-Revision-Date: 2022-07-23 03:56+0000\n"
+"Last-Translator: Björn Åkesson <bjorn.akesson@gmail.com>\n"
"Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/sv/>\n"
"Language: sv\n"
@@ -19,7 +20,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.10\n"
+"X-Generator: Weblate 4.14-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -92,7 +93,7 @@ msgstr ""
#: doc/tools/make_rst.py
msgid "Getter"
-msgstr ""
+msgstr "Getter"
#: doc/tools/make_rst.py
msgid ""
@@ -848,7 +849,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7685,8 +7693,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -9966,7 +9974,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10131,7 +10145,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11742,7 +11762,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12140,10 +12165,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 +19452,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 +19472,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 +19493,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
@@ -20143,7 +20178,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23529,7 +23564,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25360,7 +25395,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28401,13 +28436,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29820,7 +29856,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30394,10 +30433,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30409,6 +30452,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30720,6 +30769,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 ""
@@ -32437,7 +32491,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32453,7 +32507,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32483,7 +32537,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36120,7 +36174,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 +36285,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 ""
@@ -36575,7 +36637,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36836,7 +36898,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -36950,6 +37012,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -37504,7 +37612,7 @@ msgstr ""
#: doc/classes/Node.xml
msgid "Nodes and Scenes"
-msgstr ""
+msgstr "Noder och scener"
#: doc/classes/Node.xml
msgid "All Demos"
@@ -39647,7 +39755,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39659,7 +39773,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45263,6 +45378,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49810,8 +49932,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
@@ -54187,7 +54309,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54227,15 +54350,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55711,11 +55835,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57385,7 +57528,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58180,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
@@ -58777,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
@@ -60250,8 +60419,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60316,6 +60485,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."
@@ -63870,13 +64043,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -63888,13 +64062,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65702,11 +65877,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65786,8 +65961,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66390,9 +66565,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 +66597,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
@@ -70775,7 +70955,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70860,6 +71044,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/th.po b/doc/translations/th.po
index 68c0dd503a..3b8c2afd36 100644
--- a/doc/translations/th.po
+++ b/doc/translations/th.po
@@ -933,7 +933,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7790,8 +7797,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10072,7 +10079,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10237,7 +10250,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11848,7 +11867,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12246,10 +12270,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 +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
@@ -19551,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
@@ -19568,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
@@ -20253,7 +20287,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23643,7 +23677,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25478,7 +25512,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28520,13 +28554,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29961,7 +29996,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30551,10 +30589,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30566,6 +30608,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30881,6 +30929,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 ""
@@ -32609,7 +32662,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32625,7 +32678,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32655,7 +32708,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36308,7 +36361,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 +36473,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 ""
@@ -36764,7 +36825,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37025,7 +37086,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37142,6 +37203,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39889,7 +39996,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39901,7 +40014,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45514,6 +45628,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50068,8 +50189,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
@@ -54448,7 +54569,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54488,15 +54610,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55972,11 +56095,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57647,7 +57789,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58444,7 +58586,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 +59207,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
@@ -60518,8 +60686,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60584,6 +60752,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."
@@ -64139,13 +64311,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64157,13 +64330,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65983,11 +66157,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66067,8 +66241,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66671,9 +66845,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 +66877,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
@@ -71060,7 +71239,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71145,6 +71328,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/tl.po b/doc/translations/tl.po
index 4361ff7318..6fe51a2de6 100644
--- a/doc/translations/tl.po
+++ b/doc/translations/tl.po
@@ -924,7 +924,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7761,8 +7768,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10046,7 +10053,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10211,7 +10224,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11822,7 +11841,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12223,10 +12247,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 +19534,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 +19554,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 +19575,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
@@ -20226,7 +20260,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23618,7 +23652,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25449,7 +25483,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28490,13 +28524,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29909,7 +29944,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30483,10 +30521,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30498,6 +30540,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30809,6 +30857,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 ""
@@ -32532,7 +32585,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32548,7 +32601,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32581,7 +32634,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36233,7 +36286,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 +36397,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 ""
@@ -36688,7 +36749,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -36949,7 +37010,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37063,6 +37124,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39760,7 +39867,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39772,7 +39885,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45379,6 +45493,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -49926,8 +50047,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
@@ -54303,7 +54424,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54343,15 +54465,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55827,11 +55950,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57501,7 +57643,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58296,7 +58438,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 +59059,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
@@ -60366,8 +60534,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60435,6 +60603,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."
@@ -63992,13 +64167,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64010,13 +64186,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65824,11 +66001,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -65908,8 +66085,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66515,9 +66692,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 +66724,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
@@ -70900,7 +71082,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -70985,6 +71171,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/tr.po b/doc/translations/tr.po
index 01b71d7673..ffa15621df 100644
--- a/doc/translations/tr.po
+++ b/doc/translations/tr.po
@@ -18,12 +18,15 @@
# 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.
+# Deleted User <noreply+46858@weblate.org>, 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-23 03:56+0000\n"
+"Last-Translator: Deleted User <noreply+46858@weblate.org>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/tr/>\n"
"Language: tr\n"
@@ -31,7 +34,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.14-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -83,7 +86,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,11 +94,11 @@ msgstr ""
#: doc/tools/make_rst.py
msgid "Default"
-msgstr ""
+msgstr "Varsayılan"
#: doc/tools/make_rst.py
msgid "Setter"
-msgstr ""
+msgstr "Ayarlayıcı"
#: doc/tools/make_rst.py
msgid "value"
@@ -103,7 +106,7 @@ msgstr "deÄŸer"
#: doc/tools/make_rst.py
msgid "Getter"
-msgstr ""
+msgstr "Alıcı"
#: doc/tools/make_rst.py
msgid ""
@@ -129,13 +132,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 ""
@@ -1309,10 +1314,22 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+#, fuzzy
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
-"[method print] yöntemi gibidir fakat yanlız hata ayıklama (debug) modunda "
-"kullanılır."
+"Kod içindeki istiflenme konumunu yazdırır ve yanlızca hata ayıklayıcı "
+"(debugger) açıkken çalışır.\n"
+"Konsoldaki çıktı aşağıdaki gibi bir şey olacaktır.\n"
+"[codeblock]\n"
+"Frame 0 - res://test.gd:16 in function '_process'\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -8465,8 +8482,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10747,7 +10764,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10912,7 +10935,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -12525,7 +12554,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12925,10 +12959,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 +20268,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 +20288,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 +20309,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
@@ -20950,7 +20994,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -24346,7 +24390,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -26187,7 +26231,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -29236,13 +29280,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30657,7 +30702,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -31231,10 +31279,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -31246,6 +31298,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -31560,6 +31618,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 ""
@@ -33283,7 +33346,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33299,7 +33362,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -33331,7 +33394,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -37003,7 +37066,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 +37179,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 ""
@@ -37465,7 +37536,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37729,7 +37800,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37848,6 +37919,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -40545,7 +40662,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40557,7 +40680,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -46198,6 +46322,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50748,8 +50879,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
@@ -55134,7 +55265,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55174,15 +55306,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56658,11 +56791,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -58334,7 +58486,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -59131,7 +59283,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 +59904,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
@@ -61209,8 +61387,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -61277,6 +61455,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."
@@ -64840,13 +65024,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64858,13 +65043,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -66674,11 +66860,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66758,8 +66944,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -67369,9 +67555,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 +67589,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
@@ -71775,10 +71966,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
-"Eğer [code]true[/code] ise düğümler sıraya sokulur, yoksa sıraya sokulmaz."
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -71862,6 +72055,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/uk.po b/doc/translations/uk.po
index e943465bca..b1272c6b3e 100644
--- a/doc/translations/uk.po
+++ b/doc/translations/uk.po
@@ -991,7 +991,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7843,8 +7850,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10125,7 +10132,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10290,7 +10303,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11904,7 +11923,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12302,10 +12326,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 +19630,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 +19650,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 +19671,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
@@ -20322,7 +20356,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23711,7 +23745,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25548,7 +25582,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28598,13 +28632,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30019,7 +30054,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30593,10 +30631,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30608,6 +30650,12 @@ msgstr "Мишка Ñ– координати введеннÑ"
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30920,6 +30968,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 ""
@@ -32639,7 +32692,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32655,7 +32708,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32685,7 +32738,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36354,7 +36407,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 +36520,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 ""
@@ -36814,7 +36875,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37077,7 +37138,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37195,6 +37256,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39892,7 +39999,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39904,7 +40017,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45536,6 +45650,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50086,8 +50207,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
@@ -54465,7 +54586,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54505,15 +54627,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55990,11 +56113,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57665,7 +57807,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58462,7 +58604,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 +59225,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
@@ -60541,8 +60709,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60607,6 +60775,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."
@@ -64171,13 +64344,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64189,13 +64363,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -66006,11 +66181,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66090,8 +66265,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66698,9 +66873,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 +66905,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
@@ -71102,7 +71282,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71187,6 +71371,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/vi.po b/doc/translations/vi.po
index 81411cebb9..60ab8769ab 100644
--- a/doc/translations/vi.po
+++ b/doc/translations/vi.po
@@ -1202,8 +1202,15 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
-msgstr "Giống [method print], nhưng chỉ in khi sử dụng trong chế độ gỡ lỗi."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
+msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -8138,8 +8145,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10420,7 +10427,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10585,7 +10598,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -12199,7 +12218,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12598,10 +12622,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 +19929,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 +19949,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 +19970,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
@@ -20621,7 +20655,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -24013,7 +24047,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25850,7 +25884,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28895,13 +28929,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -30317,7 +30352,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30891,10 +30929,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30906,6 +30948,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -31219,6 +31267,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 ""
@@ -32939,7 +32992,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32955,7 +33008,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32986,7 +33039,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36655,7 +36708,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 +36821,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 ""
@@ -37116,7 +37177,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37380,7 +37441,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37499,6 +37560,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -40196,7 +40303,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -40208,7 +40321,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45848,6 +45962,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50402,8 +50523,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
@@ -54786,7 +54907,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54826,15 +54948,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -56312,11 +56435,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57988,7 +58130,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58785,7 +58927,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 +59548,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
@@ -60863,8 +61031,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60930,6 +61098,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."
@@ -64495,13 +64668,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64513,13 +64687,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -66331,11 +66506,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66415,8 +66590,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -67026,9 +67201,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 +67234,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
@@ -71437,9 +71617,12 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-#, fuzzy
-msgid "If [code]true[/code], the viewport renders to hdr."
-msgstr "Nếu [code]true[/code], há»a tiết sẽ được căn ở trung tâm."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -71523,6 +71706,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/doc/translations/zh_CN.po b/doc/translations/zh_CN.po
index e39b32f496..7647bf0081 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-31 16:43+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"
@@ -71,7 +71,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.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -507,7 +507,7 @@ msgid ""
"a = dectime(60, 10, 0.1)) # a is 59.0\n"
"[/codeblock]"
msgstr ""
-"[b]注æ„:[/b][code]dectime[/code] 已被废弃,将在 Godot 4.0 中删除,请使用 "
+"[b]注æ„:[/b][code]dectime[/code] 已被废弃,将在 Godot 4.0 中移除,请使用 "
"[method move_toward] 代替。\n"
"返回 [code]value[/code] å‡åŽ» [code]step[/code] * [code]amount[/code] 的结"
"果。\n"
@@ -570,7 +570,6 @@ msgstr ""
"将(之å‰ä½¿ç”¨ [method inst2dict] 创建的)字典转æ¢å›žå®žä¾‹ã€‚适用于ååºåˆ—化。"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns an \"eased\" value of [code]x[/code] based on an easing function "
"defined with [code]curve[/code]. This easing function is based on an "
@@ -590,9 +589,9 @@ msgid ""
"See also [method smoothstep]. If you need to perform more advanced "
"transitions, use [Tween] or [AnimationPlayer]."
msgstr ""
-"返回 [code]x[/code] “缓动åŽâ€çš„值,结果基于使用 [code]curve[/code] 值定义的缓"
-"动函数。该缓动函数是基于指数的。[code]curve[/code] 值å¯ä»¥æ˜¯ä»»æ„浮点数,具体数"
-"值会导致以下行为:\n"
+"返回 [code]x[/code]“缓动åŽâ€çš„值,结果基于使用 [code]curve[/code] 值定义的缓动"
+"函数。该缓动函数是基于指数的。[code]curve[/code] 值å¯ä»¥æ˜¯ä»»æ„浮点数,具体数值"
+"会导致以下行为:\n"
"[codeblock]\n"
"- 低于 -1.0(开区间):缓入缓出\n"
"- -1.0:线性\n"
@@ -602,9 +601,9 @@ msgstr ""
"- 1.0:线性\n"
"- 大于 1.0(开区间):缓入\n"
"[/codeblock]\n"
-"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/"
+"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.5/img/"
"ease_cheatsheet.png]ease() 曲线值速查表[/url]\n"
-"请å‚阅 [method smoothstep]ã€‚å¦‚æžœä½ éœ€è¦æ‰§è¡Œæ›´é«˜çº§çš„过渡,请使用 [Tween] 或 "
+"å¦è¯·å‚阅 [method smoothstep]ã€‚å¦‚æžœä½ éœ€è¦æ‰§è¡Œæ›´é«˜çº§çš„过渡,请使用 [Tween] 或 "
"[AnimationPlayer]。"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -646,7 +645,7 @@ msgstr ""
"a = floor(2.99) # a = 2.0\n"
"a = floor(-2.99) # a = -3.0\n"
"[/codeblock]\n"
-"请å‚阅 [method ceil]ã€[method round]ã€[method stepify] å’Œ [int]。\n"
+"å¦è¯·å‚阅 [method ceil]ã€[method round]ã€[method stepify] å’Œ [int]。\n"
"[b]注æ„:[/b]è¯¥æ–¹æ³•è¿”å›žä¸€ä¸ªæµ®ç‚¹æ•°ã€‚å¦‚æžœä½ éœ€è¦æ•´æ•°ï¼Œè€Œ [code]s[/code] 是éžè´Ÿ"
"数,你å¯ä»¥ç›´æŽ¥ä½¿ç”¨ [code]int(s)[/code]。"
@@ -1323,8 +1322,21 @@ msgstr ""
"在打å°é”™è¯¯æˆ–警告时还会显示堆栈跟踪。"
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
-msgstr "与 [method print] 类似,但仅在调试模å¼ä¸‹ä½¿ç”¨æ—¶æ‰æ‰“å°ã€‚"
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
+msgstr ""
+"与 [method print] 类似,但在打开调试器è¿è¡Œæ—¶è¿˜ä¼šåŒ…å«å½“剿 ˆå¸§ã€‚\n"
+"控制å°ä¸­çš„输出应该是类似这样的:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1688,7 +1700,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns the result of smoothly interpolating the value of [code]s[/code] "
"between [code]0[/code] and [code]1[/code], based on the where [code]s[/code] "
@@ -1731,7 +1742,7 @@ msgstr ""
"与曲线值为 [code]-1.6521[/code] 的 [method ease] 相比,[method smoothstep] 返"
"回最平滑的曲线,导数没有çªç„¶å˜åŒ–ã€‚å¦‚æžœä½ éœ€è¦æ‰§è¡Œæ›´é«˜çº§çš„过渡,请使用 [Tween] "
"或 [AnimationPlayer]。\n"
-"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.4/img/"
+"[url=https://raw.githubusercontent.com/godotengine/godot-docs/3.5/img/"
"smoothstep_ease_comparison.png]smoothstep() 与 ease(x, -1.6521) 返回值的比较"
"[/url]"
@@ -4876,7 +4887,7 @@ msgstr ""
"custom_action]ä¿¡å·ã€‚\n"
"如果[code]right[/code]为 [code]true[/code],按钮会被放置在所有åŒçº§æŒ‰é’®çš„å³"
"边。\n"
-"您å¯ä»¥ä½¿ç”¨ [method remove_button] æ–¹æ³•ä»Žå¯¹è¯æ¡†ä¸­åˆ é™¤ä½¿ç”¨æ­¤æ–¹æ³•创建的按钮。"
+"您å¯ä»¥ä½¿ç”¨ [method remove_button] æ–¹æ³•ä»Žå¯¹è¯æ¡†ä¸­ç§»é™¤ä½¿ç”¨æ­¤æ–¹æ³•创建的按钮。"
#: doc/classes/AcceptDialog.xml
msgid ""
@@ -4887,7 +4898,7 @@ msgid ""
msgstr ""
"å‘å¯¹è¯æ¡†ä¸­æ·»åŠ ä¸€ä¸ªæ ‡ç­¾ä¸º[code]name[/code]å’Œä¸€ä¸ªå–æ¶ˆåŠ¨ä½œçš„æŒ‰é’®ï¼Œç„¶åŽè¿”回这个新"
"创建的按钮。\n"
-"您å¯ä»¥ä½¿ç”¨ [method remove_button] æ–¹æ³•ä»Žå¯¹è¯æ¡†ä¸­åˆ é™¤ä½¿ç”¨æ­¤æ–¹æ³•创建的按钮。"
+"您å¯ä»¥ä½¿ç”¨ [method remove_button] æ–¹æ³•ä»Žå¯¹è¯æ¡†ä¸­ç§»é™¤ä½¿ç”¨æ­¤æ–¹æ³•创建的按钮。"
#: doc/classes/AcceptDialog.xml
msgid ""
@@ -4897,7 +4908,7 @@ msgid ""
"[member CanvasItem.visible] property."
msgstr ""
"返回内置文本所使用的标签。\n"
-"[b]警告:[/b]这是个必è¦çš„内部节点,删除和释放它有å¯èƒ½é€ æˆå´©æºƒã€‚如果你希望éšè—"
+"[b]警告:[/b]这是个必è¦çš„内部节点,移除并释放它有å¯èƒ½é€ æˆå´©æºƒã€‚如果你希望éšè—"
"它或它的任æ„一个å­èŠ‚ç‚¹ï¼Œè¯·ä½¿ç”¨å®ƒä»¬çš„ [member CanvasItem.visible] 属性。"
#: doc/classes/AcceptDialog.xml
@@ -4908,7 +4919,7 @@ msgid ""
"[member CanvasItem.visible] property."
msgstr ""
"返回确定按钮 [Button] 实例。\n"
-"[b]警告:[/b]这是个必è¦çš„内部节点,删除和释放它有å¯èƒ½é€ æˆå´©æºƒã€‚如果你希望éšè—"
+"[b]警告:[/b]这是个必è¦çš„内部节点,移除并释放它有å¯èƒ½é€ æˆå´©æºƒã€‚如果你希望éšè—"
"它或它的任æ„一个å­èŠ‚ç‚¹ï¼Œè¯·ä½¿ç”¨å®ƒä»¬çš„ [member CanvasItem.visible] 属性。"
#: doc/classes/AcceptDialog.xml
@@ -5171,19 +5182,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."
@@ -5653,7 +5664,7 @@ msgstr "返回给定轨é“中给定键的方法轨é“上è¦è°ƒç”¨çš„傿•°å€¼ã€‚
#: doc/classes/Animation.xml
msgid "Removes a track by specifying the track index."
-msgstr "通过指定轨é“索引æ¥åˆ é™¤ä¸€ä¸ªè½¨é“。"
+msgstr "通过指定轨é“索引æ¥ç§»é™¤ä¸€ä¸ªè½¨é“。"
#: doc/classes/Animation.xml
msgid ""
@@ -5739,11 +5750,11 @@ msgstr "将轨é“上移。"
#: doc/classes/Animation.xml
msgid "Removes a key by index in a given track."
-msgstr "在指定的轨é“上按索引删除一个键。"
+msgstr "在指定的轨é“上按索引移除一个键。"
#: doc/classes/Animation.xml
msgid "Removes a key by position (seconds) in a given track."
-msgstr "按ä½ç½®ï¼ˆç§’)删除指定轨é“中的键。"
+msgstr "按ä½ç½®ï¼ˆç§’)移除指定轨é“中的键。"
#: doc/classes/Animation.xml
msgid "Enables/disables the given track. Tracks are enabled by default."
@@ -6074,11 +6085,11 @@ msgstr ""
#: doc/classes/AnimationNode.xml
msgid "Removes an input, call this only when inactive."
-msgstr "åˆ é™¤è¾“å…¥ï¼Œä»…åœ¨å¤„äºŽéžæ´»åŠ¨çŠ¶æ€æ—¶è°ƒç”¨æ­¤è¾“入。"
+msgstr "ç§»é™¤è¾“å…¥ï¼Œä»…åœ¨å¤„äºŽéžæ´»åŠ¨çŠ¶æ€æ—¶è°ƒç”¨æ­¤è¾“入。"
#: doc/classes/AnimationNode.xml
msgid "Adds or removes a path for the filter."
-msgstr "添加或删除筛选器的路径。"
+msgstr "添加或移除筛选器的路径。"
#: doc/classes/AnimationNode.xml
msgid ""
@@ -6094,7 +6105,7 @@ msgstr "如果为 [code]true[/code],则å¯ç”¨ç­›é€‰åŠŸèƒ½ã€‚"
#: doc/classes/AnimationNode.xml
msgid "Emitted when the node was removed from the graph."
-msgstr "当该节点从图中删除时触å‘。"
+msgstr "当该节点从图中移除时触å‘。"
#: doc/classes/AnimationNode.xml
msgid ""
@@ -6317,7 +6328,7 @@ msgstr "返回索引 [code]point[/code] 处的点的ä½ç½®ã€‚"
#: doc/classes/AnimationNodeBlendSpace1D.xml
msgid "Removes the point at index [code]point[/code] from the blend axis."
-msgstr "将索引 [code]point[/code] 处的点从混åˆè½´ä¸Šåˆ é™¤ã€‚"
+msgstr "将索引 [code]point[/code] 处的点从混åˆè½´ä¸Šç§»é™¤ã€‚"
#: doc/classes/AnimationNodeBlendSpace1D.xml
#: doc/classes/AnimationNodeBlendSpace2D.xml
@@ -6424,12 +6435,12 @@ msgstr ""
#: doc/classes/AnimationNodeBlendSpace2D.xml
msgid "Removes the point at index [code]point[/code] from the blend space."
-msgstr "从混åˆç©ºé—´ä¸­åˆ é™¤ç´¢å¼• [code]point[/code] 处的点。"
+msgstr "从混åˆç©ºé—´ä¸­ç§»é™¤ç´¢å¼• [code]point[/code] 处的点。"
#: doc/classes/AnimationNodeBlendSpace2D.xml
msgid ""
"Removes the triangle at index [code]triangle[/code] from the blend space."
-msgstr "从混åˆç©ºé—´ä¸­åˆ é™¤ç´¢å¼• [code]triangle[/code] 处的三角形。"
+msgstr "从混åˆç©ºé—´ä¸­ç§»é™¤ç´¢å¼• [code]triangle[/code] 处的三角形。"
#: doc/classes/AnimationNodeBlendSpace2D.xml
msgid ""
@@ -6475,7 +6486,7 @@ msgstr "æ··åˆç©ºé—´ Y è½´çš„å称。"
msgid ""
"Emitted every time the blend space's triangles are created, removed, or when "
"one of their vertices changes position."
-msgstr "æ¯å½“创建ã€åˆ é™¤æ··åˆç©ºé—´çš„三角形,或当其中一个顶点改å˜ä½ç½®æ—¶å‘出。"
+msgstr "æ¯å½“创建ã€ç§»é™¤æ··åˆç©ºé—´çš„三角形,或当其中一个顶点改å˜ä½ç½®æ—¶å‘出。"
#: doc/classes/AnimationNodeBlendSpace2D.xml
msgid "The interpolation between animations is linear."
@@ -6549,7 +6560,7 @@ msgstr "如果存在å称为 [code]name[/code] çš„å­èŠ‚ç‚¹ï¼Œåˆ™è¿”å›ž [code]t
#: doc/classes/AnimationNodeBlendTree.xml
msgid "Removes a sub-node."
-msgstr "删除一个å­èŠ‚ç‚¹ã€‚"
+msgstr "移除一个å­èŠ‚ç‚¹ã€‚"
#: doc/classes/AnimationNodeBlendTree.xml
msgid "Changes the name of a sub-node."
@@ -7879,9 +7890,9 @@ msgid ""
"list is modified once during the physics step, not immediately after objects "
"are moved. Consider using signals instead."
msgstr ""
-"返回相交的[Area]的列表。é‡å åŒºåŸŸçš„[member CollisionObject.collision_layer]å¿…"
-"须是这个区域[member CollisionObject.collision_mask]的一部分,这样æ‰èƒ½è¢«æ£€æµ‹"
-"到。\n"
+"返回相交的 [Area] 的列表。é‡å åŒºåŸŸçš„ [member CollisionObject."
+"collision_layer] 必须是这个区域 [member CollisionObject.collision_mask] 的一"
+"部分,这样æ‰èƒ½è¢«æ£€æµ‹åˆ°ã€‚\n"
"å‡ºäºŽæ€§èƒ½çš„è€ƒè™‘ï¼Œå› ç¢°æ’žéƒ½æ˜¯åŒæ—¶å¤„ç†çš„ï¼Œè¿™ä¸ªåˆ—è¡¨åœ¨ç‰©ç†æ­¥éª¤ä¸­åªä¿®æ”¹ä¸€æ¬¡ï¼Œè€Œä¸æ˜¯"
"在物体被移动åŽç«‹å³ä¿®æ”¹ã€‚è€ƒè™‘ä½¿ç”¨ä¿¡å·æ¥ä»£æ›¿ã€‚"
@@ -7894,9 +7905,9 @@ msgid ""
"list is modified once during the physics step, not immediately after objects "
"are moved. Consider using signals instead."
msgstr ""
-"返回相交的[PhysicsBody]的列表。é‡å ç‰©ä½“çš„[member CollisionObject."
-"collision_layer]必须是这个区域[member CollisionObject.collision_mask]的一部"
-"分,这样æ‰èƒ½è¢«æ£€æµ‹åˆ°ã€‚\n"
+"返回相交的 [PhysicsBody] 的列表。é‡å ç‰©ä½“çš„ [member CollisionObject."
+"collision_layer] 必须是这个区域 [member CollisionObject.collision_mask] 的一"
+"部分,这样æ‰èƒ½è¢«æ£€æµ‹åˆ°ã€‚\n"
"å‡ºäºŽæ€§èƒ½çš„è€ƒè™‘ï¼Œå› ç¢°æ’žéƒ½æ˜¯åŒæ—¶å¤„ç†çš„ï¼Œè¿™ä¸ªåˆ—è¡¨åœ¨ç‰©ç†æ­¥éª¤ä¸­åªä¿®æ”¹ä¸€æ¬¡ï¼Œè€Œä¸æ˜¯"
"在物体被移动åŽç«‹å³ä¿®æ”¹ã€‚è€ƒè™‘ä½¿ç”¨ä¿¡å·æ¥ä»£æ›¿ã€‚"
@@ -7945,7 +7956,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 ""
@@ -7975,8 +7986,8 @@ msgid ""
"The area's gravity vector (not normalized). If gravity is a point (see "
"[member gravity_point]), this will be the point of attraction."
msgstr ""
-"区域的未归一化的é‡åŠ›å‘é‡ã€‚如果é‡åŠ›ä½œç”¨åœ¨ä¸€ä¸ªç‚¹ä¸Šï¼Œåˆ™å®ƒå°†æ˜¯å¼•åŠ›ç‚¹ã€‚è¯·å‚阅 "
-"[member gravity_point]。"
+"区域的未归一化的é‡åŠ›å‘é‡ã€‚如果é‡åŠ›ä½œç”¨åœ¨ä¸€ä¸ªç‚¹ä¸Šï¼Œåˆ™å®ƒå°†æ˜¯å¼•åŠ›ç‚¹ï¼ˆè§ [member "
+"gravity_point])。"
#: doc/classes/Area.xml
msgid ""
@@ -7991,13 +8002,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 +8025,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."
@@ -8881,7 +8893,7 @@ msgid ""
"if the array is empty, without printing an error message. See also [method "
"pop_front]."
msgstr ""
-"删除并返回数组中的末尾元素。数组为空时,返回 [code]null[/code]。å¦è¯·å‚阅 "
+"移除并返回数组中的末尾元素。数组为空时,返回 [code]null[/code]。å¦è¯·å‚阅 "
"[method pop_front]。"
#: doc/classes/Array.xml
@@ -9141,11 +9153,11 @@ msgstr ""
#: doc/classes/ArrayMesh.xml
msgid "Removes all blend shapes from this [ArrayMesh]."
-msgstr "删除此[ArrayMesh]的所有混åˆå½¢çŠ¶ã€‚"
+msgstr "移除此 [ArrayMesh] 的所有混åˆå½¢çŠ¶ã€‚"
#: doc/classes/ArrayMesh.xml
msgid "Removes all surfaces from this [ArrayMesh]."
-msgstr "删除此[ArrayMesh]的所有表é¢ã€‚"
+msgstr "移除此 [ArrayMesh] 的所有表é¢ã€‚"
#: doc/classes/ArrayMesh.xml
msgid "Returns the number of blend shapes that the [ArrayMesh] holds."
@@ -9484,7 +9496,7 @@ msgstr ""
"è¿™æ˜¯é“¾æŽ¥åˆ°æŽ§åˆ¶å™¨è·Ÿè¸ªçš„è¾…åŠ©ç©ºé—´èŠ‚ç‚¹ã€‚å®ƒè¿˜ä¸ºæŽ§åˆ¶å™¨ä¸Šçš„æŒ‰é’®ç­‰çŠ¶æ€æä¾›äº†å‡ ä¸ªä¾¿æ·"
"的通é“。\n"
"控制器通过它们的 ID 链接。你å¯ä»¥åœ¨æŽ§åˆ¶å™¨å¯ç”¨ä¹‹å‰åˆ›å»ºæŽ§åˆ¶å™¨èŠ‚ç‚¹ã€‚å¦‚æžœä½ çš„æ¸¸æˆ"
-"æ€»æ˜¯ä½¿ç”¨ä¸¤ä¸ªæŽ§åˆ¶å™¨ï¼Œå³æ¯åªæ‰‹ä¸€ä¸ªï¼Œä½ å¯ä»¥é¢„先定义 ID 为 1 å’Œ 2 的控制器;一旦"
+"总是使用两个控制器(æ¯åªæ‰‹ä¸€ä¸ªï¼‰ï¼Œä½ å¯ä»¥é¢„先定义 ID 为 1 å’Œ 2 的控制器;一旦"
"确定了控制器,它们就会被激活。如果你希望使用é¢å¤–的控制器,应该对信å·åР以处"
"ç†ï¼Œå¹¶å°† ARVRController 节点添加到您场景中。\n"
"控制器节点的ä½ç½®ç”± [ARVRServer] 自动更新。这使得该节点éžå¸¸é€‚åˆæ·»åŠ å­èŠ‚ç‚¹ä»¥å®ž"
@@ -9571,14 +9583,13 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
-"控制器振动的程度。范围从 [code]0.0[/code] 到 [code]1.0[/code],精度 "
-"[code].01[/code]。如果更改,会相应地更新 [member ARVRPositionalTracker."
-"rumble]。\n"
+"控制器振动的程度。范围从 [code]0.0[/code] 到 [code]1.0[/code]。如果更改,"
+"会相应地更新 [member ARVRPositionalTracker.rumble]。\n"
"如果你想让控制器在é™å®šæ—¶é—´å†…振动,这是一个有用的属性,å¯ä»¥å°†å…¶åŠ¨ç”»åŒ–ã€‚"
#: doc/classes/ARVRController.xml
@@ -9614,8 +9625,8 @@ msgid ""
"[ARVRServer]."
msgstr ""
"需è¦å®žçŽ°è¿™ä¸ªç±»æ‰èƒ½ä½¿ AR 或 VR å¹³å°å¯ä¾› Godot 使用,并且应实现为 C++ æ¨¡å—æˆ– "
-"GDNative 模å—,注æ„,对于 GDNative,应使用å­ç±» ARVRScriptInterface。部分接å£"
-"å‘ GDScript 公开,因而,您å¯ä»¥æ£€æµ‹ã€å¯ç”¨å’Œé…ç½® AR 或 VR å¹³å°ã€‚\n"
+"GDNative 模å—(注æ„,对于 GDNative,应使用å­ç±» ARVRScriptInterface)。部分接"
+"å£å‘ GDScript 公开,因而,您å¯ä»¥æ£€æµ‹ã€å¯ç”¨å’Œé…ç½® AR 或 VR å¹³å°ã€‚\n"
"接å£åº”以这样的方å¼ç¼–写,åªéœ€å¯ç”¨å®ƒä»¬å°±å¯ä»¥ä¸ºæˆ‘们æä¾›å·¥ä½œé…置。您å¯ä»¥é€šè¿‡ "
"[ARVRServer] 查询å¯ç”¨æŽ¥å£ã€‚"
@@ -9636,7 +9647,7 @@ msgstr "返回 [enum Capabilities] 标签的组åˆï¼Œæä¾›å…³äºŽè¿™ä¸ªæŽ¥å£åŠŸ
#: doc/classes/ARVRInterface.xml
msgid "Returns the name of this interface (OpenVR, OpenHMD, ARKit, etc)."
-msgstr "返回该接å£çš„å称,如 OpenVRã€OpenHMDã€ARKit 等。"
+msgstr "返回该接å£çš„å称(OpenVRã€OpenHMDã€ARKit 等)。"
#: doc/classes/ARVRInterface.xml
msgid ""
@@ -9712,7 +9723,7 @@ msgstr "没有 ARVR 功能。"
#: doc/classes/ARVRInterface.xml
msgid ""
"This interface can work with normal rendering output (non-HMD based AR)."
-msgstr "此接å£å¯ä»¥ä¸Žæ­£å¸¸çš„æ¸²æŸ“输出一起工作,éžåŸºäºŽ HMD çš„ AR。"
+msgstr "此接å£å¯ä»¥ä¸Žæ­£å¸¸çš„æ¸²æŸ“输出一起工作(éžåŸºäºŽ HMD çš„ AR)。"
#: doc/classes/ARVRInterface.xml
msgid "This interface supports stereoscopic rendering."
@@ -9720,7 +9731,7 @@ msgstr "è¯¥æŽ¥å£æ”¯æŒç«‹ä½“渲染。"
#: doc/classes/ARVRInterface.xml
msgid "This interface supports AR (video background and real world tracking)."
-msgstr "è¯¥æŽ¥å£æ”¯æŒ AR,视频背景和真实世界跟踪。"
+msgstr "è¯¥æŽ¥å£æ”¯æŒ AR(视频背景和真实世界跟踪)。"
#: doc/classes/ARVRInterface.xml
msgid ""
@@ -9763,7 +9774,7 @@ msgstr "追踪行为符åˆé¢„期。"
msgid ""
"Tracking is hindered by excessive motion (the player is moving faster than "
"tracking can keep up)."
-msgstr "过度è¿åŠ¨ä¼šé˜»ç¢è¿½è¸ªï¼Œå³çŽ©å®¶çš„ç§»åŠ¨é€Ÿåº¦è¶…è¿‡è¿½è¸ªçš„é€Ÿåº¦ã€‚"
+msgstr "过度è¿åŠ¨ä¼šé˜»ç¢è¿½è¸ªï¼ˆçŽ©å®¶çš„ç§»åŠ¨é€Ÿåº¦å¤§äºŽè¿½è¸ªçš„é€Ÿåº¦ï¼‰ã€‚"
#: doc/classes/ARVRInterface.xml
msgid ""
@@ -9781,7 +9792,7 @@ msgstr "我们ä¸çŸ¥é“跟踪的状æ€ï¼Œæˆ–è€…è¿™ä¸ªæŽ¥å£æœªæä¾›å馈。"
msgid ""
"Tracking is not functional (camera not plugged in or obscured, lighthouses "
"turned off, etc.)."
-msgstr "追踪功能失效,å³ç›¸æœºæœªæ’ç”µæˆ–è¢«é®æŒ¡ï¼Œç¯å¡”关闭,等等。"
+msgstr "追踪功能失效(相机未æ’ç”µæˆ–è¢«é®æŒ¡ã€ç¯å¡”关闭,等等)。"
#: modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
msgid "GDNative wrapper for an ARVR interface."
@@ -10096,7 +10107,7 @@ msgstr "æ·»åŠ æ–°æŽ¥å£æ—¶è§¦å‘。"
#: doc/classes/ARVRServer.xml
msgid "Emitted when an interface is removed."
-msgstr "当接å£è¢«åˆ é™¤æ—¶è§¦å‘。"
+msgstr "当接å£è¢«ç§»é™¤æ—¶è§¦å‘。"
#: doc/classes/ARVRServer.xml
msgid ""
@@ -10117,9 +10128,9 @@ msgid ""
"available (i.e. a new controller is switched on that takes the place of the "
"previous one)."
msgstr ""
-"删除跟踪器时触å‘。如果适当,您应该删除所有 [ARVRController] 或 [ARVRAnchor] "
-"ç‚¹ã€‚è¿™ä¸æ˜¯å¼ºåˆ¶æ€§çš„ï¼ŒèŠ‚ç‚¹åªæ˜¯å˜ä¸ºä¸æ´»åŠ¨çŠ¶æ€ï¼Œå½“新的跟踪器å¯ç”¨æ—¶å°†å†æ¬¡æ¿€æ´»ï¼Œå³"
-"打开一个新的控制器æ¥ä»£æ›¿å‰ä¸€ä¸ªæŽ§åˆ¶å™¨ã€‚"
+"移除跟踪器时触å‘。如果适当,您应该删除所有 [ARVRController] 或 [ARVRAnchor] "
+"ç‚¹ã€‚è¿™ä¸æ˜¯å¼ºåˆ¶æ€§çš„ï¼ŒèŠ‚ç‚¹åªæ˜¯å˜ä¸ºä¸æ´»åŠ¨çŠ¶æ€ï¼Œå½“新的跟踪器å¯ç”¨æ—¶å°†å†æ¬¡æ¿€æ´»ï¼ˆå³"
+"打开一个新的控制器æ¥ä»£æ›¿å‰ä¸€ä¸ªæŽ§åˆ¶å™¨ï¼‰ã€‚"
#: doc/classes/ARVRServer.xml
msgid "The tracker tracks the location of a controller."
@@ -10247,7 +10258,7 @@ msgstr ""
#: doc/classes/AspectRatioContainer.xml
msgid ""
"Aligns child controls with the beginning (left or top) of the container."
-msgstr "å°†å­æŽ§ä»¶ä¸Žå®¹å™¨çš„å¼€å¤´å¯¹é½ï¼Œå·¦ä¾§æˆ–顶部。"
+msgstr "å°†å­æŽ§ä»¶ä¸Žå®¹å™¨çš„å¼€å¤´å¯¹é½ï¼ˆå·¦ä¾§æˆ–顶部)。"
#: doc/classes/AspectRatioContainer.xml
msgid "Aligns child controls with the center of the container."
@@ -10255,7 +10266,7 @@ msgstr "ä½¿å­æŽ§ä»¶ä¸Žå®¹å™¨çš„ä¸­å¿ƒå¯¹é½ã€‚"
#: doc/classes/AspectRatioContainer.xml
msgid "Aligns child controls with the end (right or bottom) of the container."
-msgstr "å°†å­æŽ§ä»¶ä¸Žå®¹å™¨çš„æœ«ç«¯å¯¹é½ï¼Œå³ä¾§æˆ–底部。"
+msgstr "å°†å­æŽ§ä»¶ä¸Žå®¹å™¨çš„æœ«ç«¯å¯¹é½ï¼ˆå³ä¾§æˆ–底部)。"
#: doc/classes/AStar.xml
msgid ""
@@ -10602,7 +10613,7 @@ msgstr "返回是å¦ç¦ç”¨ç‚¹ä»¥è¿›è¡Œå¯»è·¯ã€‚默认情况下,所有点å‡å¤„
msgid ""
"Removes the point associated with the given [code]id[/code] from the points "
"pool."
-msgstr "从点池中删除与给定 [code]id[/code] å…³è”的点。"
+msgstr "从点池中移除与给定 [code]id[/code] å…³è”的点。"
#: doc/classes/AStar.xml doc/classes/AStar2D.xml
msgid ""
@@ -11764,7 +11775,7 @@ msgid ""
"If [code]true[/code], the sound will be recorded. Note that restarting the "
"recording will remove the previously recorded sample."
msgstr ""
-"如果为 [code]true[/code],将录制声音。请注æ„ï¼Œé‡æ–°å¼€å§‹å½•音将删除先å‰å½•音的样"
+"如果为 [code]true[/code],将录制声音。请注æ„ï¼Œé‡æ–°å¼€å§‹å½•音将移除先å‰å½•音的样"
"本。"
#: doc/classes/AudioEffectRecord.xml
@@ -12057,7 +12068,7 @@ msgid ""
"Removes the effect at index [code]effect_idx[/code] from the bus at index "
"[code]bus_idx[/code]."
msgstr ""
-"将索引 [code]effect_idx[/code] 的效果从索引 [code]bus_idx[/code] 的总线上删"
+"将索引 [code]effect_idx[/code] 的效果从索引 [code]bus_idx[/code] 的总线上移"
"除。"
#: doc/classes/AudioServer.xml
@@ -12370,11 +12381,21 @@ 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."
-msgstr "播放此音频的总线。"
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
+msgstr ""
+"这个音频在哪个总线上播放。\n"
+"[b]注æ„:[/b]设置这个属性时,请记ä½å®ƒå¹¶ä¸ä¼šå¯¹ç»™å®šçš„å称是å¦ä¸ŽçŽ°æœ‰æ€»çº¿åŒ¹é…进行"
+"校验。这是因为音频总线布局å¯ä»¥åœ¨è®¾ç½®è¿™ä¸ªå±žæ€§åŽå†åŠ è½½ã€‚å¦‚æžœè¿™ä¸ªç»™å®šçš„å称在è¿"
+"行时无法解æžï¼Œå°±ä¼šå›žé€€åˆ° [code]\"Master\"[/code]。"
#: doc/classes/AudioStreamPlayer.xml
msgid ""
@@ -12567,8 +12588,18 @@ msgstr ""
"频。"
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
-msgstr "播放此音频的总线。"
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
+msgstr ""
+"播放音频的总线。\n"
+"[b]注æ„:[/b]设置这个属性时,请记ä½å®ƒå¹¶ä¸ä¼šå¯¹ç»™å®šçš„å称是å¦ä¸ŽçŽ°æœ‰æ€»çº¿åŒ¹é…进行"
+"校验。这是因为音频总线布局å¯ä»¥åœ¨è®¾ç½®è¿™ä¸ªå±žæ€§åŽå†åŠ è½½ã€‚å¦‚æžœè¿™ä¸ªç»™å®šçš„å称在è¿"
+"行时无法解æžï¼Œå°±ä¼šå›žé€€åˆ° [code]\"Master\"[/code]。"
#: doc/classes/AudioStreamPlayer3D.xml
msgid ""
@@ -13323,7 +13354,7 @@ 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]已弃用。[/i]由于冗余,此属性已弃用,将在 Godot 4.0 中删除。此属性在设置åŽ"
+"[i]已弃用。[/i]由于冗余,此属性已弃用,将在 Godot 4.0 中移除。此属性在设置åŽ"
"ä¸ä¼šæœ‰ä»»ä½•å½±å“。请改用 [member Control.focus_mode]。"
#: doc/classes/BaseButton.xml
@@ -13459,7 +13490,7 @@ msgstr ""
"用于 3D 旋转和缩放的 3×3 çŸ©é˜µã€‚å‡ ä¹Žæ€»æ˜¯ç”¨ä½œå˜æ¢çš„æ­£äº¤åŸºã€‚\n"
"åŒ…å« 3 个å‘é‡å­—段 Xã€Y å’Œ Z ä½œä¸ºå…¶åˆ—ï¼Œé€šå¸¸è¢«è§£é‡Šä¸ºå˜æ¢çš„局部基å‘é‡ã€‚对于这ç§"
"ç”¨é€”ï¼Œå®ƒä¾æ¬¡ç”±ä¸€ä¸ªç¼©æ”¾çŸ©é˜µå’Œä¸€ä¸ªæ—‹è½¬çŸ©é˜µç»„æˆï¼ˆM=R.S)。\n"
-"也å¯ä»¥ä½œä¸ºä¸‰ç»´å‘é‡çš„æ•°ç»„æ¥è®¿é—®ã€‚这些å‘é‡é€šå¸¸æ˜¯ç›¸äº’正交的,但ä¸ä¸€å®šæ˜¯å½’一化的"
+"也å¯ä»¥ä½œä¸º 3D å‘é‡çš„æ•°ç»„æ¥è®¿é—®ã€‚这些å‘é‡é€šå¸¸æ˜¯ç›¸äº’正交的,但ä¸ä¸€å®šæ˜¯å½’一化的"
"(由于缩放)。\n"
"更多信æ¯è¯·é˜…è¯»æ–‡æ¡£ä¸­çš„ã€ŠçŸ©é˜µå’Œå˜æ¢ã€‹ä¸€æ–‡ã€‚"
@@ -14396,9 +14427,9 @@ msgid ""
"to the position and orientation of the camera by subclassed cameras such as "
"[ClippedCamera], [InterpolatedCamera] and [ARVRCamera]."
msgstr ""
-"è¿”å›žç›¸æœºçš„å˜æ¢åŠ ä¸Šåž‚ç›´[member v_offset]和水平[member h_offset]çš„åç§»é‡ï¼›ä»¥åŠ"
-"ç”±å­ç±»ç›¸æœºå¦‚[ClippedCamera]ã€[InterpolatedCamera]å’Œ[ARVRCamera]对相机的ä½ç½®å’Œ"
-"æ–¹å‘åšå‡ºçš„任何其他调整。"
+"è¿”å›žç›¸æœºçš„å˜æ¢åŠ ä¸Šåž‚ç›´ [member v_offset] 和水平 [member h_offset] çš„åç§»é‡ï¼›"
+"以åŠç”±å­ç±»ç›¸æœºå¦‚ [ClippedCamera]ã€[InterpolatedCamera] å’Œ [ARVRCamera] 对相机"
+"çš„ä½ç½®å’Œæ–¹å‘åšå‡ºçš„任何其他调整。"
#: doc/classes/Camera.xml
msgid ""
@@ -14509,8 +14540,8 @@ msgid ""
"angle in degrees, and the [code]z_near[/code] and [code]z_far[/code] clip "
"planes in world space units."
msgstr ""
-"å°†æ‘„åƒæœºçš„æŠ•影设置为é€è§†æ¨¡å¼ï¼Œå‚阅[constant PROJECTION_PERSPECTIVE]),指定"
-"[code]fov[/code] 视野角度,å•ä½åº¦ï¼Œä»¥åŠä¸–界空间å•ä½çš„[code]z_near[/code]å’Œ"
+"å°†æ‘„åƒæœºçš„æŠ•影设置为é€è§†æ¨¡å¼ï¼ˆè§ [constant PROJECTION_PERSPECTIVE]),指定 "
+"[code]fov[/code] 视野角度,å•ä½ä¸ºåº¦ï¼Œä»¥åŠä¸–界空间å•ä½çš„[code]z_near[/code]å’Œ"
"[code]z_far[/code]è£å‰ªå¹³é¢ã€‚"
#: doc/classes/Camera.xml
@@ -14549,9 +14580,17 @@ msgstr "æè¿°æ­¤ç›¸æœºæ¸²æŸ“哪些 3D 渲染层的剔除掩ç ã€‚"
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
-"如果为 [code]true[/code],则说明祖级的 [Viewport] 当剿­£åœ¨ä½¿ç”¨è¿™ä¸ªæ‘„åƒå¤´ã€‚"
+"如果为 [code]true[/code],则祖级 [Viewport] 正在使用这个相机。\n"
+"如果场景中有多个相机,总会有一个被设为当å‰ç›¸æœºã€‚例如,å‡è®¾åœºæ™¯ä¸­å­˜åœ¨ä¸¤ä¸ª "
+"[Camera] èŠ‚ç‚¹å¹¶ä¸”åªæœ‰ä¸€ä¸ªä¸ºå½“å‰ç›¸æœºï¼Œé‚£ä¹ˆå¦‚果把æŸä¸€ä¸ªç›¸æœºçš„ [member current] "
+"设为 [code]false[/code] 就会导致å¦ä¸€ä¸ªç›¸æœºè¢«è®¾ä¸ºå½“å‰ç›¸æœºã€‚"
#: doc/classes/Camera.xml
msgid ""
@@ -14771,7 +14810,7 @@ msgstr "将相机与跟踪的节点对é½ã€‚"
msgid ""
"Removes any [Camera2D] from the ancestor [Viewport]'s internal currently-"
"assigned camera."
-msgstr "从父级[Viewport]的内部当å‰åˆ†é…的相机中删除任何[Camera2D]。"
+msgstr "从父级 [Viewport] 的内部当å‰åˆ†é…的相机中移除任何 [Camera2D]。"
#: doc/classes/Camera2D.xml
msgid "Forces the camera to update scroll immediately."
@@ -14962,7 +15001,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 +15042,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 +15084,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] 回调进行更新。"
@@ -16734,7 +16775,7 @@ msgstr "添加碰撞例外,以使相机ä¸ä¼šä¸ŽæŒ‡å®šçš„[RID]碰撞。"
#: doc/classes/ClippedCamera.xml
msgid "Removes all collision exceptions."
-msgstr "删除所有碰撞例外。"
+msgstr "移除所有碰撞例外。"
#: doc/classes/ClippedCamera.xml
msgid "Returns the distance the camera has been offset due to a collision."
@@ -16750,11 +16791,11 @@ msgstr ""
#: doc/classes/ClippedCamera.xml
msgid "Removes a collision exception with the specified node."
-msgstr "删除与指定节点的碰撞例外。"
+msgstr "移除与指定节点的碰撞例外。"
#: doc/classes/ClippedCamera.xml
msgid "Removes a collision exception with the specified [RID]."
-msgstr "删除指定 [RID] 的碰撞例外。"
+msgstr "移除指定 [RID] 的碰撞例外。"
#: doc/classes/ClippedCamera.xml
msgid ""
@@ -16766,11 +16807,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 ""
@@ -16921,11 +16962,11 @@ msgstr "返回具有给定形状所有者的给定 id 的形状 [Shape] çš„å­ç´
#: doc/classes/CollisionObject.xml
msgid "Returns the shape owner's [Transform]."
-msgstr "返回形状所有者的[Transform]。"
+msgstr "返回形状所有者的 [Transform]。"
#: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml
msgid "Removes a shape from the given shape owner."
-msgstr "从给定的形状所有者中删除一个形状。"
+msgstr "从给定的形状所有者中移除一个形状。"
#: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml
msgid "If [code]true[/code], disables the given shape owner."
@@ -16933,7 +16974,7 @@ msgstr "如果为 [code]true[/code],则ç¦ç”¨ç»™å®šçš„形状所有者。"
#: doc/classes/CollisionObject.xml
msgid "Sets the [Transform] of the given shape owner."
-msgstr "设置给定形状所有者的[Transform]。"
+msgstr "设置给定形状所有者的 [Transform]。"
#: doc/classes/CollisionObject.xml
msgid ""
@@ -17006,7 +17047,7 @@ msgstr "当鼠标指针退出此对象的所有形状时å‘出。"
#: doc/classes/CollisionObject2D.xml
msgid "Base node for 2D collision objects."
-msgstr "二维碰撞对象的基础节点。"
+msgstr "2D 碰撞对象的基础节点。"
#: doc/classes/CollisionObject2D.xml
msgid ""
@@ -17042,7 +17083,7 @@ msgid ""
"Returns the [code]one_way_collision_margin[/code] of the shape owner "
"identified by given [code]owner_id[/code]."
msgstr ""
-"返回由给定的[code]owner_id[/code]标识的形状所有者的"
+"返回由给定的 [code]owner_id[/code] 标识的形状所有者的 "
"[code]one_way_collision_margin[/code]。"
#: doc/classes/CollisionObject2D.xml
@@ -17051,26 +17092,26 @@ msgid ""
"this [CollisionObject2D] will not be reported to collided with "
"[CollisionObject2D]s."
msgstr ""
-"返回 [code]true[/code],如果æºäºŽè¿™ä¸ª[CollisionObject2D]的形状所有者的碰撞ä¸ä¼š"
-"被报告给[CollisionObject2D]s。"
+"返回 [code]true[/code],如果æºäºŽè¿™ä¸ª [CollisionObject2D] 的形状所有者的碰撞ä¸"
+"会被报告给 [CollisionObject2D]。"
#: doc/classes/CollisionObject2D.xml
msgid "Adds a [Shape2D] to the shape owner."
-msgstr "给形状所有者添加一个[Shape2D]。"
+msgstr "给形状所有者添加一个 [Shape2D]。"
#: doc/classes/CollisionObject2D.xml
msgid "Returns the [Shape2D] with the given id from the given shape owner."
-msgstr "从给定的形状所有者那里返回给定id的[Shape2D]。"
+msgstr "从给定的形状所有者那里返回给定 id 的 [Shape2D]。"
#: doc/classes/CollisionObject2D.xml
msgid ""
"Returns the child index of the [Shape2D] with the given id from the given "
"shape owner."
-msgstr "从给定的形状所有者那里返回给定idçš„[Shape2D]çš„å­ç´¢å¼•。"
+msgstr "从给定的形状所有者那里返回给定 id çš„ [Shape2D] çš„å­ç´¢å¼•。"
#: doc/classes/CollisionObject2D.xml
msgid "Returns the shape owner's [Transform2D]."
-msgstr "返回形状所有者的[Transform2D]。"
+msgstr "返回形状所有者的 [Transform2D]。"
#: doc/classes/CollisionObject2D.xml
msgid ""
@@ -17078,20 +17119,20 @@ msgid ""
"originating from this [CollisionObject2D] will not be reported to collided "
"with [CollisionObject2D]s."
msgstr ""
-"如果[code]enable[/code]为 [code]true[/code],则æºè‡ªè¿™ä¸ª[CollisionObject2D]çš„"
-"形状所有者的碰撞将ä¸ä¼šè¢«æŠ¥å‘Šç»™[CollisionObject2D]。"
+"如果 [code]enable[/code] 为 [code]true[/code],则æºè‡ªè¿™ä¸ª "
+"[CollisionObject2D] 的形状所有者的碰撞将ä¸ä¼šè¢«æŠ¥å‘Šç»™ [CollisionObject2D]。"
#: doc/classes/CollisionObject2D.xml
msgid ""
"Sets the [code]one_way_collision_margin[/code] of the shape owner identified "
"by given [code]owner_id[/code] to [code]margin[/code] pixels."
msgstr ""
-"将由给定的[code]owner_id[/code]标识的形状所有者的"
-"[code]one_way_collision_margin[/code]设置为[code]margin[/code]åƒç´ ã€‚"
+"将由给定的 [code]owner_id[/code] 标识的形状所有者的 "
+"[code]one_way_collision_margin[/code] 设置为 [code]margin[/code] åƒç´ ã€‚"
#: doc/classes/CollisionObject2D.xml
msgid "Sets the [Transform2D] of the given shape owner."
-msgstr "设置给定形状所有者的[Transform2D]。"
+msgstr "设置给定形状所有者的 [Transform2D]。"
#: doc/classes/CollisionObject2D.xml
msgid ""
@@ -17946,7 +17987,7 @@ msgstr "é“奇è“色。"
#: doc/classes/Color.xml
msgid "Firebrick color."
-msgstr "ç«ç –的颜色。"
+msgstr "è€ç«ç –红色。"
#: doc/classes/Color.xml
msgid "Floral white color."
@@ -17958,11 +17999,11 @@ msgstr "森林绿色。"
#: doc/classes/Color.xml
msgid "Fuchsia color."
-msgstr "紫红色的颜色。"
+msgstr "洋红色。"
#: doc/classes/Color.xml
msgid "Gainsboro color."
-msgstr "庚斯伯勒颜色。"
+msgstr "庚斯伯勒ç°è‰²ã€‚"
#: doc/classes/Color.xml
msgid "Ghost white color."
@@ -17974,7 +18015,7 @@ msgstr "金色。"
#: doc/classes/Color.xml
msgid "Goldenrod color."
-msgstr "金黄的颜色。"
+msgstr "金èŠè‰²ã€‚"
#: doc/classes/Color.xml
msgid "Gray color."
@@ -17994,7 +18035,7 @@ msgstr "蜜露色。"
#: doc/classes/Color.xml
msgid "Hot pink color."
-msgstr "炙热的粉红色。"
+msgstr "亮粉色。"
#: doc/classes/Color.xml
msgid "Indian red color."
@@ -18018,7 +18059,7 @@ msgstr "è–°è¡£è‰è‰²ã€‚"
#: doc/classes/Color.xml
msgid "Lavender blush color."
-msgstr "è–°è¡£è‰è…®çº¢çš„颜色。"
+msgstr "è–°è¡£è‰ç´«çº¢è‰²ã€‚"
#: doc/classes/Color.xml
msgid "Lawn green color."
@@ -18042,7 +18083,7 @@ msgstr "æ·¡é’色。"
#: doc/classes/Color.xml
msgid "Light goldenrod color."
-msgstr "淡淡的金黄色。"
+msgstr "亮金èŠé»„色。"
#: doc/classes/Color.xml
msgid "Light gray color."
@@ -18388,7 +18429,7 @@ msgstr ""
#: doc/classes/ColorPicker.xml
msgid ""
"Removes the given color from the list of color presets of this color picker."
-msgstr "从这个å–色器的颜色预设列表中删除给定的颜色。"
+msgstr "从这个å–色器的颜色预设列表中移除给定的颜色。"
#: doc/classes/ColorPicker.xml
msgid "Returns the list of colors in the presets of the color picker."
@@ -18449,7 +18490,7 @@ msgstr "添加预设时å‘出。"
#: doc/classes/ColorPicker.xml
msgid "Emitted when a preset is removed."
-msgstr "删除预设时å‘出。"
+msgstr "移除预设时å‘出。"
#: doc/classes/ColorPicker.xml
msgid "The width of the hue selection slider."
@@ -18527,7 +18568,7 @@ msgid ""
msgstr ""
"返回控件的 [PopupPanel],它å…许你连接到弹出信å·ã€‚è¿™å…许你在显示或éšè— "
"ColorPicker 时事件处ç†ã€‚\n"
-"[b]警告:[/b]这是一个必需的内部节点,删除和释放它å¯èƒ½ä¼šå¯¼è‡´å´©æºƒã€‚如果你希望éš"
+"[b]警告:[/b]这是一个必需的内部节点,移除并释放它å¯èƒ½ä¼šå¯¼è‡´å´©æºƒã€‚如果你希望éš"
"è—它或其任何å­é¡¹ï¼Œè¯·ä½¿ç”¨å…¶ [member CanvasItem.visible] 属性。"
#: doc/classes/ColorPickerButton.xml
@@ -18888,7 +18929,7 @@ msgstr ""
#: doc/classes/ConfigFile.xml
msgid "Removes the entire contents of the config."
-msgstr "删除é…置的全部内容。"
+msgstr "移除é…置的全部内容。"
#: doc/classes/ConfigFile.xml
msgid ""
@@ -19016,7 +19057,7 @@ msgid ""
"if it ends up empty once the key has been removed."
msgstr ""
"为指定章节的指定键赋值。如果节或键ä¸å­˜åœ¨ï¼Œåˆ™åˆ›å»ºå®ƒä»¬ã€‚如果指定的键存在,传递 "
-"[code]null[/code] 值就会删除指定的键,如果键被删除åŽï¼Œé”®æœ€ç»ˆæ˜¯ç©ºçš„,就会删除"
+"[code]null[/code] 值就会移除指定的键,如果键被移除åŽï¼Œé”®æœ€ç»ˆæ˜¯ç©ºçš„,就会移除"
"节。"
#: doc/classes/ConfirmationDialog.xml
@@ -19048,7 +19089,7 @@ msgid ""
"[member CanvasItem.visible] property."
msgstr ""
"è¿”å›žå–æ¶ˆæŒ‰é’®ã€‚\n"
-"[b]警告:[/b]这是一个必需的内部节点,删除和释放它å¯èƒ½ä¼šå¯¼è‡´å´©æºƒã€‚如果你希望éš"
+"[b]警告:[/b]这是一个必需的内部节点,移除并释放它å¯èƒ½ä¼šå¯¼è‡´å´©æºƒã€‚如果你希望éš"
"è—它或其任何å­é¡¹ï¼Œè¯·ä½¿ç”¨å…¶ [member CanvasItem.visible] 属性。"
#: doc/classes/Container.xml
@@ -21229,7 +21270,7 @@ msgid ""
"points] property using the convex hull algorithm. Removing all unneeded "
"points. See [method Geometry.convex_hull_2d] for details."
msgstr ""
-"基于所æä¾›ç‚¹çš„集åˆï¼Œä½¿ç”¨å‡¸åŒ…ç®—æ³•åˆ›å»ºå’Œåˆ†é… [member points]属性。删除所有ä¸éœ€"
+"基于所æä¾›ç‚¹çš„集åˆï¼Œä½¿ç”¨å‡¸åŒ…ç®—æ³•åˆ›å»ºå’Œåˆ†é… [member points]属性。移除所有ä¸éœ€"
"è¦çš„点。详情请å‚阅 [method Geometry.convex_hull_2d]。"
#: doc/classes/ConvexPolygonShape2D.xml
@@ -21397,8 +21438,8 @@ msgid ""
"Each particle's color will vary along this [GradientTexture] over its "
"lifetime (multiplied with [member color])."
msgstr ""
-"æ¯ä¸ªç²’å­çš„颜色将在其生命周期内éšç€è¿™ä¸ª[GradientTexture]å˜åŒ–,å³ä¸Ž[member "
-"color]相乘。"
+"æ¯ä¸ªç²’å­çš„颜色将在其生命周期内éšç€è¿™ä¸ª [GradientTexture] å˜åŒ–(与 [member "
+"color] 相乘)。"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -21615,7 +21656,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 +21681,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 +21702,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 +21717,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 +21754,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 +21973,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 +22111,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"
@@ -22465,8 +22506,8 @@ msgid ""
"V around the outline of the [member polygon]), the bottom-left quarter to "
"the front end face, and the bottom-right quarter to the back end face."
msgstr ""
-"用于生æˆçš„网格的æè´¨ã€‚UV å°†æè´¨çš„上åŠéƒ¨åˆ†æ˜ å°„到挤出的形状,å³U沿挤出物的长"
-"度,V 围绕 [member polygon]的轮廓,左下角的四分之一映射到å‰ç«¯é¢ï¼Œå³ä¸‹è§’的四分"
+"用于生æˆçš„网格的æè´¨ã€‚UV å°†æè´¨çš„上åŠéƒ¨åˆ†æ˜ å°„到挤出的形状(U 沿挤出物的长度,"
+"V 围绕 [member polygon] 的轮廓),左下角的四分之一映射到å‰ç«¯é¢ï¼Œå³ä¸‹è§’的四分"
"之一映射到åŽç«¯é¢ã€‚"
#: modules/csg/doc_classes/CSGPolygon.xml
@@ -22789,11 +22830,11 @@ msgstr ""
#: modules/csg/doc_classes/CSGShape.xml
msgid ""
"Geometry of both primitives is merged, intersecting geometry is removed."
-msgstr "åˆå¹¶ä¸¤ä¸ªå›¾å…ƒçš„几何体,删除相交的几何体。"
+msgstr "åˆå¹¶ä¸¤ä¸ªå›¾å…ƒçš„几何体,移除相交的几何体。"
#: modules/csg/doc_classes/CSGShape.xml
msgid "Only intersecting geometry remains, the rest is removed."
-msgstr "ä»…ä¿ç•™ç›¸äº¤çš„几何,其余的将被删除。"
+msgstr "ä»…ä¿ç•™ç›¸äº¤çš„几何,其余的将被移除。"
#: modules/csg/doc_classes/CSGShape.xml
msgid ""
@@ -22896,7 +22937,7 @@ msgstr ""
msgid ""
"A script implemented in the C# programming language (Mono-enabled builds "
"only)."
-msgstr "用C#编程语言实现的脚本(仅å¯ç”¨Mono的版本)。"
+msgstr "用 C# 编程语言实现的脚本(仅 Mono 版本中存在)。"
#: modules/mono/doc_classes/CSharpScript.xml
msgid ""
@@ -22904,14 +22945,14 @@ msgid ""
"class and is only available in Mono-enabled Godot builds.\n"
"See also [GodotSharp]."
msgstr ""
-"此类表示C#脚本。它与[GDScript]类的C#等效,并且仅在å¯ç”¨äº†Monoçš„Godot版本中å¯"
-"用。\n"
-"å¦è¯·å‚阅[GodotSharp]。"
+"这个类表示 C# 脚本,是 [GDScript] 类在 C# 中的对等体,仅在å¯ç”¨äº† Mono çš„ "
+"Godot 版本中å¯ç”¨ã€‚\n"
+"å¦è¯·å‚阅 [GodotSharp]。"
#: modules/mono/doc_classes/CSharpScript.xml
#: modules/gdnative/doc_classes/PluginScript.xml
msgid "Returns a new instance of the script."
-msgstr "返回脚本的新实例。"
+msgstr "返回该脚本的新实例。"
#: doc/classes/CubeMap.xml
msgid "A CubeMap is a 6-sided 3D texture."
@@ -23228,11 +23269,11 @@ msgstr "釿–°è®¡ç®—曲线的烘焙点缓存。"
msgid ""
"Removes points that are closer than [code]CMP_EPSILON[/code] (0.00001) units "
"to their neighbor on the curve."
-msgstr "删除比曲线上的相邻点近[code]CMP_EPSILON[/code](0.00001)个å•ä½çš„点。"
+msgstr "移除比曲线上的相邻点近 [code]CMP_EPSILON[/code](0.00001)个å•ä½çš„点。"
#: doc/classes/Curve.xml doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid "Removes all points from the curve."
-msgstr "从曲线中删除所有点。"
+msgstr "从曲线中移除所有点。"
#: doc/classes/Curve.xml doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid "Returns the number of points describing the curve."
@@ -23281,7 +23322,7 @@ msgstr ""
#: doc/classes/Curve.xml
msgid "Removes the point at [code]index[/code] from the curve."
-msgstr "从曲线中删除 [code]index[/code] 处的点。"
+msgstr "从曲线中移除 [code]index[/code] 处的点。"
#: doc/classes/Curve.xml
msgid ""
@@ -23423,9 +23464,9 @@ msgid ""
"the index is out of bounds, the function sends an error to the console, and "
"returns [code](0, 0)[/code]."
msgstr ""
-"返回指å‘顶点[code]idx[/code]的控制点ä½ç½®ã€‚返回的ä½ç½®æ˜¯ç›¸å¯¹äºŽé¡¶ç‚¹[code]idx[/"
-"code]çš„ã€‚å¦‚æžœç´¢å¼•è¶…å‡ºäº†èŒƒå›´ï¼Œå‡½æ•°ä¼šå‘æŽ§åˆ¶å°å‘é€ä¸€æ¡é”™è¯¯ï¼Œå¹¶è¿”回 [code](0, 0)"
-"[/code]。"
+"返回指å‘顶点 [code]idx[/code] 的控制点ä½ç½®ã€‚返回的ä½ç½®æ˜¯ç›¸å¯¹äºŽé¡¶ç‚¹ "
+"[code]idx[/code] çš„ã€‚å¦‚æžœç´¢å¼•è¶…å‡ºäº†èŒƒå›´ï¼Œå‡½æ•°ä¼šå‘æŽ§åˆ¶å°å‘é€ä¸€æ¡é”™è¯¯ï¼Œå¹¶è¿”回 "
+"[code](0, 0)[/code]。"
#: doc/classes/Curve2D.xml
msgid ""
@@ -23434,9 +23475,9 @@ msgid ""
"code]. If the index is out of bounds, the function sends an error to the "
"console, and returns [code](0, 0)[/code]."
msgstr ""
-"返回从顶点[code]idx[/code]引出的控制点ä½ç½®ã€‚返回的ä½ç½®æ˜¯ç›¸å¯¹äºŽé¡¶ç‚¹ "
-"[code]idx[/code]ã€‚å¦‚æžœç´¢å¼•è¶Šç•Œï¼Œå‡½æ•°ä¼šå‘æŽ§åˆ¶å°å‘é€é”™è¯¯ï¼Œå¹¶è¿”回 [code](0, 0)[/"
-"code]。"
+"返回从顶点 [code]idx[/code] 引出的控制点ä½ç½®ã€‚返回的ä½ç½®æ˜¯ç›¸å¯¹äºŽé¡¶ç‚¹ "
+"[code]idx[/code]ã€‚å¦‚æžœç´¢å¼•è¶Šç•Œï¼Œå‡½æ•°ä¼šå‘æŽ§åˆ¶å°å‘é€é”™è¯¯ï¼Œå¹¶è¿”回 [code](0, "
+"0)[/code]。"
#: doc/classes/Curve2D.xml
msgid ""
@@ -23566,7 +23607,7 @@ msgstr ""
#: doc/classes/Curve3D.xml
msgid "Describes a Bézier curve in 3D space."
-msgstr "æè¿°äºŒç»´ç©ºé—´çš„è´å…¹å°”曲线。"
+msgstr "æè¿° 3D 空间的è´å…¹å°”曲线。"
#: doc/classes/Curve3D.xml
msgid ""
@@ -24096,7 +24137,7 @@ msgstr "GDScript 基础:字典"
#: doc/classes/Dictionary.xml
msgid "Clear the dictionary, removing all key/value pairs."
-msgstr "清除字典,删除所有键/值对。"
+msgstr "清除字典,移除所有键/值对。"
#: doc/classes/Dictionary.xml
msgid ""
@@ -24231,17 +24272,24 @@ 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 ""
"远处阴影分裂的é¢å¤–åç½®é‡ã€‚如果自身阴影åªäº§ç”Ÿè¿œå¤„的分裂,增加这个值å¯ä»¥ä¿®å¤å®ƒ"
-"们。"
+"们。当 [member directional_shadow_mode] 为 [constant SHADOW_ORTHOGONAL] 时会"
+"被忽略。"
#: 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],则会牺牲阴影细节,以æ¢å–更平滑的分割之间的过渡。"
+"如果为 [code]true[/code],会牺牲阴影的细节,æ¢å–分割区域之间更平滑的过渡。å¯"
+"用阴影混åˆåˆ†å‰²åŒæ—¶ä¹Ÿä¼šå¸¦æ¥ä¸€äº›æ€§èƒ½æ¶ˆè€—。当 [member directional_shadow_mode] "
+"为 [constant SHADOW_ORTHOGONAL] 时会被忽略。"
#: doc/classes/DirectionalLight.xml
msgid ""
@@ -24250,8 +24298,14 @@ 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]."
@@ -24267,33 +24321,33 @@ 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 ""
-"相机到影å­åˆ†å‰²1çš„è·ç¦»ã€‚相对于[member directional_shadow_max_distance]ã€‚åªæœ‰å½“"
-"[member directional_shadow_mode]是[code]SHADOW_PARALLEL_2_SPLITS[/code]或"
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]æ—¶æ‰ä½¿ç”¨ã€‚"
+"相机到阴影分割 1 çš„è·ç¦»ã€‚相对于 [member directional_shadow_max_distance]。åª"
+"有当 [member directional_shadow_mode] 为 [constant SHADOW_PARALLEL_2_SPLITS] "
+"或 [constant SHADOW_PARALLEL_4_SPLITS] æ—¶æ‰ä½¿ç”¨ã€‚"
#: 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 ""
-"阴影分割1到分割2çš„è·ç¦»ã€‚相对于[member directional_shadow_max_distance]。仅在"
-"[member directional_shadow_mode]为[code]SHADOW_PARALLEL_2_SPLITS[/code]或"
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]时使用。"
+"阴影分割 1 到分割 2 çš„è·ç¦»ã€‚相对于 [member directional_shadow_max_distance]。"
+"仅在 [member directional_shadow_mode] 为 [constant SHADOW_PARALLEL_2_SPLITS] "
+"或 [constant SHADOW_PARALLEL_4_SPLITS] 时使用。"
#: 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 ""
-"从影å­åˆ†å‰²2到分割3çš„è·ç¦»ã€‚相对于[member directional_shadow_max_distance]。åª"
-"有当[member directional_shadow_mode]为[code]SHADOW_PARALLEL_4_SPLITS[/code]时"
-"æ‰ä½¿ç”¨ã€‚"
+"从阴影分割 2 到分割 3 çš„è·ç¦»ã€‚相对于 [member "
+"directional_shadow_max_distance]ã€‚åªæœ‰å½“ [member directional_shadow_mode] 为 "
+"[constant SHADOW_PARALLEL_4_SPLITS] æ—¶æ‰ä½¿ç”¨ã€‚"
#: doc/classes/DirectionalLight.xml
msgid ""
@@ -24533,8 +24587,8 @@ msgid ""
"Closes the current stream opened with [method list_dir_begin] (whether it "
"has been fully processed with [method get_next] does not matter)."
msgstr ""
-"关闭用 [method list_dir_begin] æ‰“å¼€çš„å½“å‰æµï¼Œå¹¶ä¸å…³æ³¨æ˜¯å¦å·²ç»ç”¨ [method "
-"get_next] 完æˆå¤„ç†ã€‚"
+"关闭用 [method list_dir_begin] æ‰“å¼€çš„å½“å‰æµï¼ˆå¹¶ä¸å…³æ³¨æ˜¯å¦å·²ç»ç”¨ [method "
+"get_next] 完æˆå¤„ç†ï¼‰ã€‚"
#: doc/classes/Directory.xml
msgid ""
@@ -24748,8 +24802,8 @@ msgid ""
"[constant PacketPeerDTLS.STATUS_HANDSHAKING], as it is normal that 50% of "
"the new connections will be invalid due to cookie exchange."
msgstr ""
-"å°è¯•与给定的 [code]udp_peer[/code] å¯åЍ DTLS æ¡æ‰‹ï¼Œè¯¥ peer 必须已ç»è¿žæŽ¥ï¼Œè¯·å‚"
-"阅 [method PacketPeerUDP.connect_to_host]。\n"
+"å°è¯•与给定的 [code]udp_peer[/code] å¯åЍ DTLS æ¡æ‰‹ï¼Œè¯¥ peer 必须已ç»è¿žæŽ¥ï¼ˆè§ "
+"[method PacketPeerUDP.connect_to_host])。\n"
"[b]注æ„:[/b]你必须检查返回 PacketPeerUDP çš„çŠ¶æ€æ˜¯å¦ä¸º [constant "
"PacketPeerDTLS.STATUS_HANDSHAKING],因为正常情况下,50% 的新连接会因为 "
"cookie 交æ¢è€Œæ— æ•ˆã€‚"
@@ -24905,9 +24959,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 +24969,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 +25004,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."
@@ -25182,9 +25236,9 @@ msgid ""
"appear in the inspector when selecting a node that extends the class "
"specified by [code]class_name[/code]."
msgstr ""
-"如果[code]class_name[/code]指定的类中的[code]property[/code]被ç¦ç”¨ï¼Œåˆ™è¿”回 "
-"[code]true[/code]。当属性被ç¦ç”¨æ—¶ï¼Œå½“[code]class_name[/code]类被指定为类的(ç»§"
-"承)父节点时,它将ä¸ä¼šå‡ºçŽ°åœ¨æ£€æŸ¥å™¨ä¸­ã€‚"
+"如果 [code]class_name[/code] 指定的类中的 [code]property[/code] 属性被ç¦ç”¨ï¼Œ"
+"则返回 [code]true[/code]。ç¦ç”¨æŸä¸€å±žæ€§åŽï¼Œå½“选中继承自 "
+"[code]class_name[/code] 类的节点时,该属性将ä¸ä¼šå‡ºçŽ°åœ¨æ£€æŸ¥å™¨ä¸­ã€‚"
#: doc/classes/EditorFeatureProfile.xml
msgid ""
@@ -25200,17 +25254,19 @@ msgid ""
"format obtained by using the feature profile manager's [b]Export[/b] button "
"or the [method save_to_file] method."
msgstr ""
-"从文件中加载一个编辑器功能é…置文件。该文件必须éµå¾ªJSONæ ¼å¼ï¼Œé€šè¿‡ä½¿ç”¨åŠŸèƒ½é…ç½®"
-"文件管ç†å™¨çš„[b]Export[/b]按钮或[method save_to_file]方法获得。"
+"从文件中加载一个编辑器功能é…置文件。该文件必须éµå¾ª JSON "
+"æ ¼å¼ï¼Œé€šè¿‡ä½¿ç”¨åŠŸèƒ½é…置文件管ç†å™¨çš„[b]导出[/b]按钮或 [method save_to_file] "
+"方法获得。"
#: doc/classes/EditorFeatureProfile.xml
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
-"将编辑器的功能é…ç½®ä¿å­˜åˆ°JSONæ ¼å¼çš„æ–‡ä»¶ä¸­ã€‚ç„¶åŽå¯ä»¥ä½¿ç”¨ç‰¹å¾é…置文件管ç†å™¨çš„[b]"
-"导入[/b]按钮或[method load_from_file]按钮导入它。"
+"将编辑器的功能é…ç½®ä¿å­˜åˆ° JSON "
+"æ ¼å¼çš„æ–‡ä»¶ä¸­ã€‚ç„¶åŽå¯ä»¥ä½¿ç”¨åŠŸèƒ½é…置文件管ç†å™¨çš„[b]导入[/b]按钮或 [method "
+"load_from_file] 方法导入它。"
#: doc/classes/EditorFeatureProfile.xml
msgid ""
@@ -25218,8 +25274,9 @@ msgid ""
"by [code]class_name[/code]. When disabled, the class won't appear in the "
"Create New Node dialog."
msgstr ""
-"如果 [code]disable[/code] 是 [code]true[/code],则ç¦ç”¨ [code]class_name[/"
-"code] 指定的类。被ç¦ç”¨æ—¶ï¼Œè¯¥ç±»ä¸ä¼šå‡ºçŽ°åœ¨â€œåˆ›å»ºæ–° Nodeâ€å¯¹è¯æ¡†ä¸­ã€‚"
+"如果 [code]disable[/code] 为 [code]true[/code],则ç¦ç”¨ "
+"[code]class_name[/code] 指定的类。ç¦ç”¨åŽï¼Œè¯¥ç±»ä¸ä¼šå‡ºçŽ°åœ¨â€œåˆ›å»ºæ–° "
+"Nodeâ€å¯¹è¯æ¡†ä¸­ã€‚"
#: doc/classes/EditorFeatureProfile.xml
msgid ""
@@ -25228,9 +25285,9 @@ msgid ""
"appear in the Create New Node dialog but the inspector will be read-only "
"when selecting a node that extends the class."
msgstr ""
-"如果 [code]disable[/code] 为 [code]true[/code],则ç¦ç”¨ [code]class_name[/"
-"code] 指定的类的编辑。ç¦ç”¨æ—¶ï¼Œç±»ä»ç„¶ä¼šå‡ºçŽ°åœ¨â€œåˆ›å»ºæ–° Nodeâ€å¯¹è¯æ¡†ä¸­ï¼Œä½†åœ¨é€‰æ‹©ç»§"
-"承的节点时,检查器将åªè¯»ã€‚"
+"如果 [code]disable[/code] 为 [code]true[/code],则ç¦ç”¨ "
+"[code]class_name[/code] 指定的类的编辑。ç¦ç”¨åŽï¼Œè¯¥ç±»ä»ç„¶ä¼šå‡ºçŽ°åœ¨â€œåˆ›å»ºæ–° "
+"Nodeâ€å¯¹è¯æ¡†ä¸­ï¼Œä½†åœ¨é€‰ä¸­ç»§æ‰¿çš„节点时,检查器将åªè¯»ã€‚"
#: doc/classes/EditorFeatureProfile.xml
msgid ""
@@ -25239,9 +25296,10 @@ msgid ""
"When a property is disabled, it won't appear in the inspector when selecting "
"a node that extends the class specified by [code]class_name[/code]."
msgstr ""
-"如果 [code]disable[/code] 是 [code]true[/code],则ç¦ç”¨ [code]class_name[/"
-"code] 指定的类中的 [code]property[/code] 的编辑。当属性被ç¦ç”¨æ—¶ï¼Œå½“选择继承 "
-"[code]class_name[/code] 指定的类的节点时,它将ä¸ä¼šå‡ºçŽ°åœ¨æ£€æŸ¥å™¨ä¸­ã€‚"
+"如果 [code]disable[/code] 为 [code]true[/code],则ç¦ç”¨ "
+"[code]class_name[/code] 指定的类中的 [code]property[/code] "
+"属性的编辑。ç¦ç”¨æŸä¸€å±žæ€§åŽï¼Œé€‰ä¸­ç»§æ‰¿è‡ª [code]class_name[/code] "
+"指定的类的节点时,这个属性将ä¸ä¼šå‡ºçŽ°åœ¨æ£€æŸ¥å™¨ä¸­ã€‚"
#: doc/classes/EditorFeatureProfile.xml
msgid ""
@@ -25272,7 +25330,7 @@ msgstr ""
msgid ""
"The AssetLib tab. If this feature is disabled, the AssetLib tab won't "
"display."
-msgstr "AssetLib选项å¡ã€‚如果ç¦ç”¨æ­¤åŠŸèƒ½ï¼Œåˆ™ä¸ä¼šæ˜¾ç¤ºAssetLib选项å¡ã€‚"
+msgstr "AssetLib 选项å¡ã€‚如果ç¦ç”¨æ­¤åŠŸèƒ½ï¼Œåˆ™ä¸ä¼šæ˜¾ç¤º AssetLib 选项å¡ã€‚"
#: doc/classes/EditorFeatureProfile.xml
msgid ""
@@ -25320,7 +25378,7 @@ msgstr ""
#: doc/classes/EditorFileDialog.xml
msgid "Removes all filters except for \"All Files (*)\"."
-msgstr "删除除“All Files(*)â€ç­›é€‰å™¨ä¹‹å¤–的所有筛选器。"
+msgstr "移除“All Files(*)â€ç­›é€‰å™¨ä¹‹å¤–的所有筛选器。"
#: doc/classes/EditorFileDialog.xml
msgid ""
@@ -25934,7 +25992,7 @@ msgstr ""
msgid ""
"Emitted when the Edit button of an [Object] has been pressed in the "
"inspector. This is mainly used in the remote scene tree inspector."
-msgstr "在检查器中按下[Object]的编辑按钮时触å‘。主è¦ç”¨äºŽè¿œç¨‹åœºæ™¯æ ‘检查器中。"
+msgstr "在检查器中按下 [Object] 的编辑按钮时触å‘。主è¦ç”¨äºŽè¿œç¨‹åœºæ™¯æ ‘检查器中。"
#: doc/classes/EditorInspector.xml
msgid "Emitted when a property is edited in the inspector."
@@ -25946,8 +26004,8 @@ msgid ""
"by clicking the \"key\" icon next to a property when the Animation panel is "
"toggled."
msgstr ""
-"当属性在检查器中被键入时触å‘。当切æ¢åŠ¨ç”»é¢æ¿æ—¶ï¼Œå¯é€šè¿‡ç‚¹å‡»å±žæ€§æ—边的 \"é”® "
-"\"图标对属性进行键控。"
+"当属性在检查器中被键入时触å‘ã€‚å½“åŠ¨ç”»é¢æ¿æ‰“开时,å¯é€šè¿‡ç‚¹å‡»å±žæ€§æ—边的“钥匙â€å›¾"
+"标为属性添加关键帧。"
#: doc/classes/EditorInspector.xml
msgid "Emitted when a property is selected in the inspector."
@@ -26055,7 +26113,7 @@ msgid ""
"built-in editor for this property, otherwise allows to insert a custom "
"editor before the built-in one."
msgstr ""
-"å…许被调用在检查器中添加特定属性的编辑器。通常这些编辑器继承"
+"å…许被调用在检查器中添加特定属性的编辑器。通常这些编辑器继承 "
"[EditorProperty]。返回 [code]true[/code]删除该属性的内置编辑器,å¦åˆ™å…许在内"
"ç½®ç¼–è¾‘å™¨ä¹‹å‰æ’入一个自定义编辑器。"
@@ -26133,8 +26191,8 @@ msgid ""
"code] and [code]interface/editor/custom_display_scale[/code] editor "
"settings. Editor must be restarted for changes to be properly applied."
msgstr ""
-"返回编辑器用户 UI 的实际比例,[code]1.0[/code] 比例为 100%。这å¯ä»¥ç”¨æ¥è°ƒæ•´ç”±"
-"æ’件添加的用户 UI çš„ä½ç½®å’Œå°ºå¯¸ã€‚\n"
+"返回编辑器用户 UI 的实际比例([code]1.0[/code] 表示比例为 100%)。这å¯ä»¥ç”¨æ¥"
+"调整由æ’件添加的用户 UI çš„ä½ç½®å’Œå°ºå¯¸ã€‚\n"
"[b]注æ„:[/b]这个值是通过 [code]interface/editor/display_scale[/code] å’Œ "
"[code]interface/editor/custom_display_scale[/code] 编辑器设置项æ¥è®¾ç½®ã€‚编辑器"
"å¿…é¡»é‡æ–°å¯åЍæ‰èƒ½æ­£ç¡®åº”用这些å˜åŒ–。"
@@ -26310,8 +26368,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 +26383,7 @@ msgid ""
"editor."
msgstr ""
"编辑器使用æ’ä»¶æ¥æ‰©å±•功能。最常è§çš„æ’ä»¶ç±»åž‹æ˜¯ç¼–è¾‘ç»™å®šçš„èŠ‚ç‚¹æˆ–èµ„æºç±»åž‹ã€å¯¼å…¥æ’"
-"件和导出æ’件。å¦è¯·å‚阅[EditorScript]å‘编辑器添加函数。"
+"件和导出æ’件。å¦è¯·å‚阅 [EditorScript] å‘编辑器添加函数。"
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -26344,7 +26402,7 @@ msgstr ""
"å°†æŽ§ä»¶æ·»åŠ åˆ°åº•éƒ¨é¢æ¿ï¼ˆåŒ…å«â€œè¾“出â€â€œè°ƒè¯•â€â€œåŠ¨ç”»â€ç­‰ï¼‰ã€‚返回对添加的按钮的引用。您"
"å¯ä»¥æ ¹æ®éœ€è¦éšè—/显示按钮。åœç”¨æ’ä»¶åŽï¼Œè¯·ç¡®ä¿ä½¿ç”¨ [method "
"remove_control_from_bottom_panel] 移除自定义控件,并使用 [method Node."
-"queue_free] 释放。"
+"queue_free] 将其释放。"
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -26357,11 +26415,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 +26593,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 +26627,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 +26719,7 @@ msgid ""
" return false\n"
"[/codeblock]"
msgstr ""
-"当3D编辑器的视窗被更新时,由引擎调用。使用 [code]overlay[/code] 控件 "
+"引擎会在 3D 编辑器的视区å‘生更新时调用。使用 [code]overlay[/code] 控件 "
"[Control] 进行绘制。你å¯ä»¥é€šè¿‡è°ƒç”¨ [method update_overlays] 更新覆盖手动更新"
"视窗。\n"
"[codeblock]\n"
@@ -26993,9 +27051,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 +28932,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"
@@ -29100,7 +29158,7 @@ msgid ""
"The global color saturation value of the rendered scene (default value is "
"1). Effective only if [code]adjustment_enabled[/code] is [code]true[/code]."
msgstr ""
-"渲染场景的全局色彩饱和度值,默认值为1ã€‚åªæœ‰åœ¨ [code]adjustment_enabled[/"
+"渲染场景的全局色彩饱和度值(默认值为 1ï¼‰ã€‚åªæœ‰åœ¨ [code]adjustment_enabled[/"
"code] 为 [code]true[/code] æ—¶æ‰æœ‰æ•ˆã€‚"
#: doc/classes/Environment.xml
@@ -29543,7 +29601,7 @@ msgid ""
"The screen-space ambient occlusion bias. This should be kept high enough to "
"prevent \"smooth\" curves from being affected by ambient occlusion."
msgstr ""
-"å±å¹•空间环境光é®è”½åå·®ã€‚è¯¥å€¼åº”ä¿æŒåœ¨è¶³å¤Ÿé«˜çš„æ°´å¹³ï¼Œä»¥é˜²æ­¢â€œå¹³æ»‘â€æ›²çº¿å—到环境光"
+"å±å¹•空间环境光é®è”½åç½®ã€‚è¯¥å€¼åº”ä¿æŒåœ¨è¶³å¤Ÿé«˜çš„æ°´å¹³ï¼Œä»¥é˜²æ­¢â€œå¹³æ»‘â€æ›²çº¿å—到环境光"
"é®è”½çš„å½±å“。"
#: doc/classes/Environment.xml
@@ -29579,13 +29637,13 @@ msgstr ""
msgid ""
"The primary screen-space ambient occlusion intensity. See also [member "
"ssao_radius]."
-msgstr "主è¦çš„å±å¹•空间环境光é®è”½å¼ºåº¦ã€‚å‚阅[member ssao_radius]。"
+msgstr "主å±å¹•的空间环境光é®è”½å¼ºåº¦ã€‚å¦è¯·å‚阅 [member ssao_radius]。"
#: doc/classes/Environment.xml
msgid ""
"The secondary screen-space ambient occlusion intensity. See also [member "
"ssao_radius2]."
-msgstr "主è¦çš„å±å¹•空间环境光é®è”½å¼ºåº¦ã€‚å‚阅 [member ssao_radius]。"
+msgstr "次å±å¹•的空间环境光é®è”½å¼ºåº¦ã€‚å¦è¯·å‚阅 [member ssao_radius2]。"
#: doc/classes/Environment.xml
msgid ""
@@ -29627,11 +29685,11 @@ msgstr "用于色调映射的默认æ›å…‰ã€‚"
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
-"è¦ä½¿ç”¨çš„色调映射模å¼ã€‚色调映射是“转æ¢â€HDR 值以适åˆåœ¨ LDR 显示器上呈现的过程。"
-"(Godot å°šä¸æ”¯æŒåœ¨ HDR 显示器上进行渲染。)"
+"è¦ä½¿ç”¨çš„色调映射模å¼ã€‚色调映射是将 HDR 值“转æ¢â€ä¸ºé€‚åˆåœ¨ SDR "
+"显示器上呈现的值过程。(Godot å°šä¸æ”¯æŒåœ¨ HDR 显示器上进行渲染。)"
#: doc/classes/Environment.xml
msgid ""
@@ -31803,9 +31861,9 @@ msgid ""
"inside the segment ([code]s1[/code], [code]s2[/code]) or outside of it, i.e. "
"somewhere on the line extending from the segment."
msgstr ""
-"返回由([code]s1[/code], [code]s2[/code])定义的二维线上最接近[code]point[/"
-"code]的二维点。返回的点å¯ä»¥åœ¨çº¿æ®µï¼ˆ[code]s1[/code], [code]s2[/code])内,也å¯"
-"以在线段外,å³åœ¨ä»Žçº¿æ®µå»¶ä¼¸å‡ºæ¥çš„æŸå¤„ã€‚"
+"返回由 ([code]s1[/code], [code]s2[/code]) 定义的 2D 线上最接近 [code]point[/"
+"code] çš„ 2D 点。返回的点å¯ä»¥åœ¨çº¿æ®µ ([code]s1[/code], [code]s2[/code]) 内,也"
+"å¯ä»¥åœ¨çº¿æ®µå¤–,å³åœ¨ä»Žçº¿æ®µå»¶ä¼¸å‡ºæ¥çš„æŸå¤„ã€‚"
#: doc/classes/Geometry.xml
msgid ""
@@ -31906,13 +31964,14 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
-"给定表示图å—çš„[Vector2]数组,构建一个地图集。返回的字典有两个键:"
-"[code]points[/code]是[Vector2]çš„å‘é‡ï¼Œç”¨äºŽæŒ‡å®šæ¯ä¸ªå›¾å—çš„ä½ç½®ï¼Œ[code]size[/"
-"code]åŒ…å«æ•´ä¸ªå›¾é›†çš„æ•´ä½“大å°ï¼Œä½œä¸º[Vector2]。"
+"给定表示图å—çš„ [Vector2] "
+"数组,构建一个地图集。返回的字典有两个键:[code]points[/code] 是 [Vector2] "
+"的数组,用于指定æ¯ä¸ªå›¾å—çš„ä½ç½®ï¼Œ[code]size[/code] åŒ…å«æ•´ä¸ªå›¾é›†çš„æ•´ä½“大å°ï¼Œ"
+"是一个 [Vector2]。"
#: doc/classes/Geometry.xml
msgid ""
@@ -33192,9 +33251,7 @@ msgstr "å°å›¾çŸ©å½¢çš„大å°ã€‚地图自身基于网格区域的大å°ï¼Œå¹¶è¢«
msgid ""
"If [code]true[/code], enables disconnection of existing connections in the "
"GraphEdit by dragging the right end."
-msgstr ""
-"如果为 [code]true[/code],通过拖动å³ç«¯ï¼Œå¯ä»¥æ–­å¼€å›¾å½¢ç¼–辑GraphEdit中现有的连"
-"接。"
+msgstr "如果为 [code]true[/code],通过拖动å³ç«¯ï¼Œå¯ä»¥æ–­å¼€ GraphEdit 中现有的连接。"
#: doc/classes/GraphEdit.xml
msgid "The scroll offset."
@@ -33251,9 +33308,9 @@ msgid ""
"code] slot of the [code]from[/code] GraphNode and the [code]to_slot[/code] "
"slot of the [code]to[/code] GraphNode is attempted to be created."
msgstr ""
-"当试图创建[code]æ¥è‡ªfrom[/code]图形节点GraphNode1çš„[code]from_slot[/code]槽和"
-"[code]to[/code]图形节点GraphNode2çš„[code]to_slot[/code]槽之间的连接时,会å‘图"
-"形编辑GraphEditå‘出。"
+"å°è¯•创建从 [code]from[/code] GraphNode çš„ [code]from_slot[/code] 槽到 "
+"[code]to[/code] GraphNode çš„ [code]to_slot[/code] 槽之间的连接时,会å‘该 "
+"GraphEdit å‘出。"
#: doc/classes/GraphEdit.xml
msgid ""
@@ -33280,9 +33337,9 @@ msgid ""
"slot of [code]from[/code] GraphNode and [code]to_slot[/code] slot of "
"[code]to[/code] GraphNode is attempted to be removed."
msgstr ""
-"当试图移除 [code]from[/code] 图形节点GraphNode1的 [code]from_slot[/code]槽和"
-"[code]to[/code] 图形节点GraphNode çš„[code]to_slot[/code] 槽之间的连接时,会å‘"
-"é€åˆ°å›¾å½¢ç¼–辑GraphEdit。"
+"å°è¯•移除从 [code]from[/code] GraphNode çš„ [code]from_slot[/code] 槽到 "
+"[code]to[/code] GraphNode çš„ [code]to_slot[/code] 槽之间的连接时,会å‘该 "
+"GraphEdit å‘出。"
#: doc/classes/GraphEdit.xml
msgid ""
@@ -33506,9 +33563,8 @@ msgstr ""
msgid ""
"Sets the [Color] of the right (output) side of the slot [code]idx[/code] to "
"[code]color_right[/code]."
-msgstr ""
-"å°†æ’æ§½[code]idx[/code]çš„å³ä¾§ï¼ˆè¾“出)的颜色[Color]设置为[code]color_right[/"
-"code]。"
+msgstr "å°†æ’æ§½ [code]idx[/code] çš„å³ä¾§ï¼ˆè¾“出)的颜色 [Color] 设置为 "
+"[code]color_right[/code]。"
#: doc/classes/GraphNode.xml
msgid ""
@@ -33544,7 +33600,7 @@ msgstr ""
#: doc/classes/GraphNode.xml
msgid "If [code]true[/code], the GraphNode is a comment node."
-msgstr "如果为 [code]true[/code],则 GraphNode 是注释节点。"
+msgstr "如果为 [code]true[/code],则该 GraphNode 是注释节点。"
#: doc/classes/GraphNode.xml
msgid ""
@@ -33572,7 +33628,7 @@ msgstr ""
#: doc/classes/GraphNode.xml
msgid "If [code]true[/code], the GraphNode is selected."
-msgstr "如果为 [code]true[/code],图形节点GraphNode被选中。"
+msgstr "如果为 [code]true[/code],则该 GraphNode 被选中。"
#: doc/classes/GraphNode.xml
msgid ""
@@ -35492,7 +35548,6 @@ msgid "A node with the ability to send HTTP(S) requests."
msgstr "具有å‘é€ HTTP(S) 请求能力的节点。"
#: doc/classes/HTTPRequest.xml
-#, fuzzy
msgid ""
"A node with the ability to send HTTP requests. Uses [HTTPClient] "
"internally.\n"
@@ -35587,7 +35642,7 @@ msgstr ""
" # 执行 POST 请求。截止到文档编写时,下é¢çš„ URL 会返回 JSON。\n"
" # 注æ„:请勿使用å•个 HTTPRequest 节点进行连续请求。\n"
" # 下é¢çš„ä»£ç æ®µä»…ä¾›å‚考。\n"
-" var body = {\"name\": \"Godette\"}\n"
+" var body = to_json({\"name\": \"Godette\"})\n"
" error = http_request.request(\"https://httpbin.org/post\", [], true, "
"HTTPClient.METHOD_POST, body)\n"
" if error != OK:\n"
@@ -35760,19 +35815,20 @@ msgstr "å…许的最大é‡å®šå‘数。用于防止无é™é‡å®šå‘循环。"
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
-msgstr ""
-"如果设为大于 [code]0.0[/code] 的值,在ç»è¿‡ [code]timeout[/code] ç§’ä»æœª[i]完æˆ"
-"[/i]请求时,该 HTTP 请求就会超时。对于 REST API 等较å°çš„ HTTP 请求,将 "
-"[member timeout] 设为大于 [code]0.0[/code] 的值å¯ä»¥å®šæ—¶é˜²æ­¢åº”用程åºåœ¨å¤±è´¥æ—¶é™·"
-"入长时间的无å“应状æ€ã€‚ä¸‹è½½æ–‡ä»¶æ—¶è¯·ä¿æŒ [code]0.0[/code],防止在需è¦èŠ±è´¹è¾ƒé•¿æ—¶"
-"间下载时导致下载失败。"
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
+msgstr ""
+"如果在请求开始å‰è®¾ä¸ºå¤§äºŽ [code]0.0[/code] 的值,在ç»è¿‡ [code]timeout[/code] "
+"ç§’ä»æœª[i]完æˆ[/i]请求时,该 HTTP 请求就会超时。对于 REST API 等较å°çš„ HTTP 请"
+"求,将 [member timeout] 设为 [code]10.0[/code] 到 [code]30.0[/code] 之间的值"
+"å¯ä»¥å®šæ—¶é˜²æ­¢åº”用程åºåœ¨å¤±è´¥æ—¶é™·å…¥é•¿æ—¶é—´çš„æ— å“应状æ€ã€‚ä¸‹è½½æ–‡ä»¶æ—¶è¯·ä¿æŒ "
+"[code]0.0[/code],防止在需è¦èŠ±è´¹è¾ƒé•¿æ—¶é—´ä¸‹è½½æ—¶å¯¼è‡´ä¸‹è½½å¤±è´¥ã€‚"
#: doc/classes/HTTPRequest.xml
msgid "If [code]true[/code], multithreading is used to improve performance."
@@ -35999,7 +36055,7 @@ msgstr ""
msgid ""
"Stretches the image and enlarges it by a factor of 2. No interpolation is "
"done."
-msgstr "拉伸图åƒå¹¶å°†å…¶æ”¾å¤§2å€ï¼Œä¸è¿›è¡Œæ’值。"
+msgstr "拉伸图åƒå¹¶å°†å…¶æ”¾å¤§ 2 å€ï¼Œä¸è¿›è¡Œæ’值。"
#: doc/classes/Image.xml
msgid "Fills the image with [code]color[/code]."
@@ -36039,7 +36095,7 @@ msgstr ""
"错误。\n"
"[b]注æ„:[/b]多级æ¸è¿œçº¹ç†çš„ç”Ÿæˆæ˜¯åœ¨ CPU 上完æˆçš„,是å•线程的,并且[i]总是[/i]"
"在主线程上完æˆã€‚è¿™æ„味ç€åœ¨æ¸¸æˆè¿‡ç¨‹ä¸­ç”Ÿæˆå¤šçº§æ¸è¿œçº¹ç†ä¼šå¯¼è‡´æ˜Žæ˜¾çš„å¡é¡¿ï¼Œå³ä½¿ä»Ž "
-"[Thread] 调用[method generate_mipmaps]。"
+"[Thread] 调用 [method generate_mipmaps]。"
#: doc/classes/Image.xml
msgid "Returns a copy of the image's raw data."
@@ -36289,7 +36345,7 @@ msgstr ""
#: doc/classes/Image.xml
msgid "Shrinks the image by a factor of 2."
-msgstr "将图åƒç¼©å°2å€ã€‚"
+msgstr "将图åƒç¼©å° 2 å€ã€‚"
#: doc/classes/Image.xml
msgid "Converts the raw data from the sRGB colorspace to a linear scale."
@@ -36315,7 +36371,7 @@ msgstr "[Image] 资æºå…许的最大高度。"
#: doc/classes/Image.xml
msgid "Texture format with a single 8-bit depth representing luminance."
-msgstr "çº¹ç†æ ¼å¼ï¼Œå…·æœ‰ä»£è¡¨äº®åº¦çš„å•一8使·±åº¦ã€‚"
+msgstr "çº¹ç†æ ¼å¼ï¼Œå…·æœ‰ä»£è¡¨äº®åº¦çš„å•一 8 使·±åº¦ã€‚"
#: doc/classes/Image.xml
msgid ""
@@ -36393,16 +36449,16 @@ msgid ""
"OpenGL texture format [code]GL_RGB32F[/code] where there are three "
"components, each a 32-bit floating-point values."
msgstr ""
-"OpenGLçº¹ç†æ ¼å¼[code]GL_RGB32F[/code],其中有三个部分,æ¯ä¸ªéƒ¨åˆ†éƒ½æ˜¯32使µ®ç‚¹"
-"值。"
+"OpenGL çº¹ç†æ ¼å¼ [code]GL_RGB32F[/code],其中有三个部分,æ¯ä¸ªéƒ¨åˆ†éƒ½æ˜¯ 32 使µ®"
+"点值。"
#: doc/classes/Image.xml
msgid ""
"OpenGL texture format [code]GL_RGBA32F[/code] where there are four "
"components, each a 32-bit floating-point values."
msgstr ""
-"OpenGLçº¹ç†æ ¼å¼[code]GL_RGBA32F[/code],其中有四个部分,æ¯ä¸ªéƒ¨åˆ†éƒ½æ˜¯32使µ®ç‚¹"
-"值。"
+"OpenGL çº¹ç†æ ¼å¼ [code]GL_RGBA32F[/code],其中有四个部分,æ¯ä¸ªéƒ¨åˆ†éƒ½æ˜¯ 32 使µ®"
+"点值。"
#: doc/classes/Image.xml
msgid ""
@@ -36690,7 +36746,7 @@ msgstr "表示 [enum Format] 枚举的大å°ã€‚"
msgid ""
"Performs nearest-neighbor interpolation. If the image is resized, it will be "
"pixelated."
-msgstr "执行最近邻æ’值.如果调整图åƒå¤§å°,它将被åƒç´ åŒ–."
+msgstr "执行最近邻æ’值。如果调整图åƒå¤§å°ï¼Œå®ƒå°†è¢«åƒç´ åŒ–。"
#: doc/classes/Image.xml
msgid ""
@@ -36707,8 +36763,8 @@ msgid ""
"This mode often gives better results compared to [constant "
"INTERPOLATE_BILINEAR], at the cost of being slower."
msgstr ""
-"执行三次æ’值.如果调整图åƒå¤§å°,则图åƒå°†æ¨¡ç³Š.与[constant INTERPOLATE_BILINEAR]"
-"相比,此模å¼é€šå¸¸ä¼šäº§ç”Ÿæ›´å¥½çš„结果,但代价是速度较慢."
+"执行三次æ’值。如果调整图åƒå¤§å°ï¼Œåˆ™å›¾åƒå°†æ¨¡ç³Šã€‚与 [constant "
+"INTERPOLATE_BILINEAR] 相比,此模å¼é€šå¸¸ä¼šäº§ç”Ÿæ›´å¥½çš„结果,但代价是速度较慢。"
#: doc/classes/Image.xml
msgid ""
@@ -36740,36 +36796,36 @@ msgid ""
"Performs Lanczos interpolation. This is the slowest image resizing mode, but "
"it typically gives the best results, especially when downscalng images."
msgstr ""
-"执行Lanczosæ’值.这是最慢的图åƒè°ƒæ•´å¤§å°æ¨¡å¼,但通常å¯ä»¥æä¾›æœ€ä½³æ•ˆæžœ,尤其是在缩"
-"å°å›¾åƒæ—¶."
+"执行 Lanczos æ’值。这是最慢的图åƒè°ƒæ•´å¤§å°æ¨¡å¼ï¼Œä½†é€šå¸¸å¯ä»¥æä¾›æœ€ä½³æ•ˆæžœï¼Œå°¤å…¶æ˜¯"
+"在缩å°å›¾åƒæ—¶ã€‚"
#: doc/classes/Image.xml
msgid "Image does not have alpha."
-msgstr "图片没有Alpha通é“."
+msgstr "图片没有 Alpha 通é“。"
#: doc/classes/Image.xml
msgid "Image stores alpha in a single bit."
-msgstr "图åƒå°†Alpha存储在å•个bit中."
+msgstr "图åƒå°† Alpha 存储在å•个 bit 中。"
#: doc/classes/Image.xml
msgid "Image uses alpha."
-msgstr "图åƒä½¿ç”¨é˜¿å°”法。"
+msgstr "图åƒä½¿ç”¨ Alpha。"
#: doc/classes/Image.xml
msgid "Use S3TC compression."
-msgstr "使用S3TC压缩。"
+msgstr "使用 S3TC 压缩。"
#: doc/classes/Image.xml
msgid "Use PVRTC2 compression."
-msgstr "使用PVRTC2压缩。"
+msgstr "使用 PVRTC2 压缩。"
#: doc/classes/Image.xml
msgid "Use PVRTC4 compression."
-msgstr "使用PVRTC4压缩。"
+msgstr "使用 PVRTC4 压缩。"
#: doc/classes/Image.xml
msgid "Use ETC compression."
-msgstr "使用ETC压缩。"
+msgstr "使用 ETC 压缩。"
#: doc/classes/Image.xml
msgid "Use ETC2 compression."
@@ -36988,7 +37044,7 @@ msgstr ""
#: doc/classes/ImmediateGeometry.xml
msgid ""
"Simple helper to draw an UV sphere with given latitude, longitude and radius."
-msgstr "用于绘制给定ç»çº¬åº¦å’ŒåŠå¾„çš„UVçƒä½“的简å•辅助工具。"
+msgstr "用于绘制给定ç»çº¬åº¦å’ŒåŠå¾„çš„ UV çƒä½“的简å•辅助工具。"
#: doc/classes/ImmediateGeometry.xml
msgid ""
@@ -37008,11 +37064,11 @@ msgstr ""
#: doc/classes/ImmediateGeometry.xml
msgid "Clears everything that was drawn using begin/end."
-msgstr "清除使用begin/end绘制的一切内容。"
+msgstr "清除使用 begin/end 绘制的一切内容。"
#: doc/classes/ImmediateGeometry.xml
msgid "Ends a drawing context and displays the results."
-msgstr "ç»“æŸæ­£åœ¨ç»˜åˆ¶çš„context并显示其结果。"
+msgstr "ç»“æŸæ­£åœ¨ç»˜åˆ¶çš„上下文并显示其结果。"
#: doc/classes/ImmediateGeometry.xml
msgid "The current drawing color."
@@ -37064,10 +37120,10 @@ msgid ""
"[method parse_input_event] instead."
msgstr ""
"这将模拟按下指定的按键动作。\n"
-"强度å¯ä»¥ç”¨äºŽéžå¸ƒå°”è¿ç®—的动作,它的范围在0 到 1之间,代表给定动作的力度。\n"
-"[b]注æ„:[/b]这个方法ä¸ä¼šå¼•起任何[method Node._input]调用。它旨在与[method "
-"is_action_pressed]和[method is_action_just_pressed]一起使用。如果你想模拟"
-"[code]_input[/code],请使用[method parse_input_event]代替。"
+"强度å¯ä»¥ç”¨äºŽéžå¸ƒå°”è¿ç®—的动作,它的范围在 0 到 1 之间,代表给定动作的力度。\n"
+"[b]注æ„:[/b]这个方法ä¸ä¼šå¼•起任何 [method Node._input] 调用。它旨在与 "
+"[method is_action_pressed] 和 [method is_action_just_pressed] 一起使用。如果"
+"你想模拟 [code]_input[/code],请使用 [method parse_input_event] 代替。"
#: doc/classes/Input.xml
msgid "If the specified action is already pressed, this will release it."
@@ -37156,8 +37212,8 @@ msgid ""
"get_action_strength(\"negative_action\")[/code]."
msgstr ""
"通过指定两个动作æ¥èŽ·å–轴的输入,一个是负的,一个是正的。\n"
-"这是写[code]Input.get_action_strength(\"positive_action\")-Input."
-"get_action_strength(\"negative_action\")[/code]的简写。"
+"这是 [code]Input.get_action_strength(\"positive_action\")-Input."
+"get_action_strength(\"negative_action\")[/code] 的简写。"
#: doc/classes/Input.xml
msgid ""
@@ -37167,7 +37223,7 @@ msgstr "返回一个 [Array],包å«å½“剿‰€æœ‰è¿žæŽ¥æ‰‹æŸ„的设备 ID。"
#: doc/classes/Input.xml
msgid "Returns the currently assigned cursor shape (see [enum CursorShape])."
-msgstr "è¿”å›žå½“å‰æŒ‡å®šçš„光标形状(å‚阅 [enum CursorShape])。"
+msgstr "è¿”å›žå½“å‰æŒ‡å®šçš„å…‰æ ‡å½¢çŠ¶ï¼ˆè§ [enum CursorShape])。"
#: doc/classes/Input.xml
msgid ""
@@ -37178,11 +37234,11 @@ msgid ""
"measurement for each axis is m/s² while on iOS it's a multiple of the "
"Earth's gravitational acceleration [code]g[/code] (~9.81 m/s²)."
msgstr ""
-"如果设备有加速度传感器,则返回设备的é‡åŠ›ã€‚å¦åˆ™ï¼Œè¯¥æ–¹æ³•返回[constant Vector3."
+"如果设备有加速度传感器,则返回设备的é‡åŠ›ã€‚å¦åˆ™ï¼Œè¯¥æ–¹æ³•返回 [constant Vector3."
"ZERO]。\n"
-"[b]注æ„:[/b]这个方法åªåœ¨Androidå’ŒiOS上工作。在其他平å°ä¸Šï¼Œå®ƒæ€»æ˜¯è¿”回"
-"[constant Vector3.ZERO]。在Android上,æ¯ä¸ªè½´çš„æµ‹é‡å•使˜¯m/s²,而在iOS上,它是"
-"地çƒé‡åŠ›åŠ é€Ÿåº¦çš„å€æ•°[code]g[/code](~9.81 m/s²)。"
+"[b]注æ„:[/b]这个方法åªåœ¨ Android å’Œ iOS 上工作。在其他平å°ä¸Šï¼Œå®ƒæ€»æ˜¯è¿”回 "
+"[constant Vector3.ZERO]。在 Android 上,æ¯ä¸ªè½´çš„æµ‹é‡å•使˜¯ m/s²,而在 iOS "
+"上,它是地çƒé‡åŠ›åŠ é€Ÿåº¦çš„å€æ•° [code]g[/code](~9.81 m/s²)。"
#: doc/classes/Input.xml
msgid ""
@@ -37192,16 +37248,16 @@ msgid ""
"[b]Note:[/b] This method only works on Android and iOS. On other platforms, "
"it always returns [constant Vector3.ZERO]."
msgstr ""
-"如果设备有陀螺仪传感器,则返回围绕设备Xã€Yã€Z轴的旋转速率,å•ä½ä¸ºrad/s。å¦"
-"则,该方法返回[constant Vector3.ZERO]。\n"
-"[b]注æ„:[/b]这个方法åªåœ¨Androidå’ŒiOS上工作。在其他平å°ä¸Šï¼Œæ€»æ˜¯è¿”回[constant "
-"Vector3.ZERO]。"
+"如果设备有陀螺仪传感器,则返回围绕设备 Xã€Yã€Z 轴的旋转速率,å•ä½ä¸º rad/s。å¦"
+"则,该方法返回 [constant Vector3.ZERO]。\n"
+"[b]注æ„:[/b]这个方法åªåœ¨ Android å’Œ iOS 上工作。在其他平å°ä¸Šï¼Œæ€»æ˜¯è¿”回 "
+"[constant Vector3.ZERO]。"
#: doc/classes/Input.xml
msgid ""
"Returns the current value of the joypad axis at given index (see [enum "
"JoystickList])."
-msgstr "è¿”å›žç»™å®šç´¢å¼•çš„æ¸¸æˆæ‰‹æŸ„轴的当å‰å€¼ï¼Œå‚阅[enum JoystickList]。"
+msgstr "è¿”å›žç»™å®šç´¢å¼•çš„æ¸¸æˆæ‰‹æŸ„轴的当å‰å€¼ï¼ˆè§ [enum JoystickList])。"
#: doc/classes/Input.xml
msgid "Returns the index of the provided axis name."
@@ -37222,15 +37278,16 @@ msgid ""
"Receives a gamepad button from [enum JoystickList] and returns its "
"equivalent name as a string."
msgstr ""
-"从[enum JoystickList]ä¸­æŽ¥æ”¶æ¸¸æˆæ‰‹æŸ„按钮,并将其对应的å称作为一个字符串返回。"
+"从 [enum JoystickList] ä¸­æŽ¥æ”¶æ¸¸æˆæ‰‹æŸ„按钮,并将其对应的å称作为一个字符串返"
+"回。"
#: doc/classes/Input.xml
msgid ""
"Returns a SDL2-compatible device GUID on platforms that use gamepad "
"remapping. Returns [code]\"Default Gamepad\"[/code] otherwise."
msgstr ""
-"åœ¨ä½¿ç”¨æ¸¸æˆæ‰‹æŸ„釿˜ å°„的平å°ä¸Šè¿”回一个SDL2兼容的设备GUID。å¦åˆ™è¿”回 "
-"[code]\"Default Gamepad\"[/code]é»˜è®¤æ¸¸æˆæ‰‹æŸ„。"
+"åœ¨ä½¿ç”¨æ¸¸æˆæ‰‹æŸ„釿˜ å°„的平å°ä¸Šè¿”回一个 SDL2 兼容的设备 GUID。å¦åˆ™è¿”回 "
+"[code]\"Default Gamepad\"[/code] é»˜è®¤æ¸¸æˆæ‰‹æŸ„。"
#: doc/classes/Input.xml
msgid "Returns the name of the joypad at the specified device index."
@@ -37471,7 +37528,7 @@ msgstr ""
#: doc/classes/Input.xml
msgid ""
"Removes all mappings from the internal database that match the given GUID."
-msgstr "从内部数æ®åº“中删除与给定GUID匹é…的所有映射."
+msgstr "从内部数æ®åº“中删除与给定 GUID 匹é…的所有映射。"
#: doc/classes/Input.xml
msgid ""
@@ -37481,9 +37538,9 @@ msgid ""
"[b]Note:[/b] This value can be immediately overwritten by the hardware "
"sensor value on Android and iOS."
msgstr ""
-"设置加速度传感器的加速度值。å¯ä»¥ç”¨äºŽåœ¨æ²¡æœ‰ç¡¬ä»¶ä¼ æ„Ÿå™¨çš„设备上进行调试,例如在"
-"PC上的编辑器中。\n"
-"[b]注æ„:[/b]这个值在Androidå’ŒiOS上å¯ç«‹å³è¢«ç¡¬ä»¶ä¼ æ„Ÿå™¨çš„值所覆盖。"
+"设置加速度传感器的加速度值。å¯ä»¥ç”¨äºŽåœ¨æ²¡æœ‰ç¡¬ä»¶ä¼ æ„Ÿå™¨çš„设备上进行调试,例如在 "
+"PC 上的编辑器中。\n"
+"[b]注æ„:[/b]这个值在 Android å’Œ iOS 上å¯ç«‹å³è¢«ç¡¬ä»¶ä¼ æ„Ÿå™¨çš„值所覆盖。"
#: doc/classes/Input.xml
msgid ""
@@ -37518,7 +37575,7 @@ msgid ""
"[b]Note:[/b] This method generates an [InputEventMouseMotion] to update "
"cursor immediately."
msgstr ""
-"è®¾ç½®è§†çª—ä¸­ä½¿ç”¨çš„é»˜è®¤å…‰æ ‡å½¢çŠ¶ï¼Œè€Œä¸æ˜¯ [constant CURSOR_ARROW]。\n"
+"è®¾ç½®è¯¥è§†åŒºä¸­ä½¿ç”¨çš„é»˜è®¤å…‰æ ‡å½¢çŠ¶ï¼Œè€Œä¸æ˜¯ [constant CURSOR_ARROW]。\n"
"[b]注æ„:[/b]å¦‚æžœè¦æ›´æ”¹ [Control] 节点的默认光标形状,请改用 [member Control."
"mouse_default_cursor_shape]。\n"
"[b]注æ„:[/b]这个方法会生æˆä¸€ä¸ª [InputEventMouseMotion] ä»¥ç«‹å³æ›´æ–°å…‰æ ‡ã€‚"
@@ -37623,14 +37680,19 @@ 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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
"如果为 [code]true[/code],会对æ“作系统å‘é€çš„类似输入事件进行累积。当å¯ç”¨è¾“å…¥"
"累积时,在一帧中产生的所有输入事件将被åˆå¹¶ï¼Œå¹¶åœ¨è¯¥å¸§å®Œæˆæ¸²æŸ“æ—¶å‘出。因此,这"
"é™åˆ¶äº†æ¯ç§’的输入方法调用次数,使之与渲染FPS相一致。\n"
-"输入累加在默认情况下是å¯ç”¨çš„。它å¯ä»¥è¢«ç¦ç”¨ï¼Œå°†ä»¥å¢žåŠ CPU使用率为代价,获得ç¨å¾®"
+"输入累积在默认情况下是å¯ç”¨çš„。它å¯ä»¥è¢«ç¦ç”¨ï¼Œå°†ä»¥å¢žåŠ CPU使用率为代价,获得ç¨å¾®"
"æ›´ç²¾ç¡®åŠæ›´çµæ•的输入。在需è¦è‡ªç”±ç»˜åˆ¶çº¿æ¡çš„åº”ç”¨ä¸­ï¼Œä¸€èˆ¬åº”ç”¨åœ¨ç”¨æˆ·ç»˜åˆ¶çº¿æ¡æ—¶ç¦"
-"用输入累加,以获得紧跟实际输入的结果。"
+"用输入累加,以获得紧跟实际输入的结果。\n"
+"[b]注æ„:[/b]输入累积是默认[i]å¯ç”¨[/i]的。推è那些ä¸éœ€è¦éžå¸¸æ´»è·ƒè¾“入的游æˆä¿"
+"æŒå¯ç”¨ï¼Œèƒ½å¤Ÿé™ä½Ž CPU å ç”¨ã€‚"
#: doc/classes/Input.xml
msgid "Emitted when a joypad device has been connected or disconnected."
@@ -38038,7 +38100,8 @@ msgstr ""
msgid ""
"Stores information about joystick motions. One [InputEventJoypadMotion] "
"represents one axis at a time."
-msgstr "存储关于æ“纵æ†è¿åŠ¨çš„ä¿¡æ¯ã€‚一个[InputEventJoypadMotion]一次代表一个轴。"
+msgstr ""
+"存储关于æ“纵æ†è¿åŠ¨çš„ä¿¡æ¯ã€‚一个 [InputEventJoypadMotion] 一次代表一个轴。"
#: doc/classes/InputEventJoypadMotion.xml
msgid "Axis identifier. Use one of the [enum JoystickList] axis constants."
@@ -38358,21 +38421,28 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
msgstr ""
"包å«é¼ æ ‡å’Œç¬”çš„è¿åŠ¨ä¿¡æ¯ã€‚支æŒç›¸å¯¹ã€ç»å¯¹ä½ç½®å’Œé€Ÿåº¦ã€‚è§ [method Node._input]。\n"
-"[b]注æ„:[/b]默认情况下,这个事件最多åªèƒ½åœ¨æ¯ä¸€å¸§æ¸²æŸ“中å‘å‡ºä¸€æ¬¡ã€‚å¦‚æžœä½ éœ€è¦æ›´"
-"精确的输入报告,请将 [member Input.use_accumulated_input] 设为 [code]false[/"
-"code],让事件尽å¯èƒ½é¢‘ç¹åœ°å‘射。如果你使用 InputEventMouseMotion æ¥ç”»çº¿ï¼Œè¯·è€ƒ"
-"è™‘åŒæ—¶å®žçް [url=https://en.wikipedia.org/wiki/"
-"Bresenham%27s_line_algorithm]Bresenham 的线æ¡ç®—法[/url],以é¿å…在用户快速移动"
-"鼠标时出现å¯è§çš„线æ¡ç©ºéš™ã€‚"
+"[b]注æ„:[/b]è¿™ä¸ªäº‹ä»¶çš„è¡Œä¸ºå— [member Input.use_accumulated_input] å–值的影"
+"å“。设为 [code]true[/code] 时(默认),从æ“作系统获å–到的鼠标/笔的移动事件会"
+"被åˆå¹¶ï¼Œæ¯ä¸ªæ¸²æŸ“帧最多åªä¼šå‘出一个累积事件。设为 [code]false[/code] 时,收到"
+"几个事件就会å‘å‡ºå‡ ä¸ªäº‹ä»¶ï¼Œå³æ¯ä¸ªæ¸²æŸ“帧å¯èƒ½å‘出多次,能够精确地汇报输入,但代"
+"价是å ç”¨ CPU。\n"
+"[b]注æ„:[/b]如果你使用 InputEventMouseMotion æ¥ç”»çº¿ï¼Œè¯·è€ƒè™‘åŒæ—¶å®žçް"
+"[url=https://zh.wikipedia.org/zh-cn/"
+"%E5%B8%83%E9%9B%B7%E6%A3%AE%E6%BC%A2%E5%A7%86%E7%9B%B4%E7%B7%9A%E6%BC%94%E7%AE%97%E6%B3%95]"
+"布雷森汉姆直线算法[/url],以é¿å…在用户快速移动鼠标时出现å¯è§çš„线æ¡ç©ºéš™ã€‚"
#: doc/classes/InputEventMouseMotion.xml
msgid "Mouse and input coordinates"
@@ -38380,6 +38450,14 @@ msgstr "é¼ æ ‡å’Œè¾“å…¥åæ ‡"
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+"使用手写笔的橡皮端时,返回 [code]true[/code]。\n"
+"[b]注æ„:[/b]这个属性在 Linuxã€macOS å’Œ Windows 上实现。"
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr "表示用户对笔施加的压力。范围从 [code]0.0[/code] 到 [code]1.0[/code] 。"
@@ -38520,15 +38598,15 @@ msgstr ""
#: doc/classes/InputMap.xml
msgid ""
"Adds an [InputEvent] to an action. This [InputEvent] will trigger the action."
-msgstr "给一个动作添加一个[InputEvent]。这个[InputEvent]将触å‘这个动作。"
+msgstr "ç»™æŸä¸ªåŠ¨ä½œæ·»åŠ ä¸€ä¸ª [InputEvent]。这个 [InputEvent] 将触å‘这个动作。"
#: doc/classes/InputMap.xml
msgid "Removes an [InputEvent] from an action."
-msgstr "从一个动作中删除一个[InputEvent]。"
+msgstr "从æŸä¸ªåŠ¨ä½œä¸­åˆ é™¤ä¸€ä¸ª [InputEvent]。"
#: doc/classes/InputMap.xml
msgid "Removes all events from an action."
-msgstr "从动作中删除所有事件。"
+msgstr "从æŸä¸ªåŠ¨ä½œä¸­åˆ é™¤æ‰€æœ‰äº‹ä»¶ã€‚"
#: doc/classes/InputMap.xml
msgid "Returns a deadzone value for the action."
@@ -38538,7 +38616,7 @@ msgstr "返回该æ“作的死区值。"
msgid ""
"Returns [code]true[/code] if the action has the given [InputEvent] "
"associated with it."
-msgstr "如果该动作有给定的[InputEvent]与之相关,则返回 [code]true[/code]。"
+msgstr "如果该动作有给定的 [InputEvent] 与之相关,则返回 [code]true[/code]。"
#: doc/classes/InputMap.xml
msgid "Sets a deadzone value for the action."
@@ -38551,12 +38629,13 @@ msgid ""
"An [InputEvent] can then be added to this action with [method "
"action_add_event]."
msgstr ""
-"在[InputMap]上添加一个空的动作,有一个å¯é…置的死区[code]deadzone[/code]。\n"
-"ç„¶åŽå¯ä»¥ç”¨[method action_add_event]给这个动作添加一个[InputEvent]。"
+"在 [InputMap] 上添加一个空的动作,有一个å¯é…置的死区 [code]deadzone[/"
+"code]。\n"
+"ç„¶åŽå¯ä»¥ç”¨ [method action_add_event] 给这个动作添加一个 [InputEvent]。"
#: doc/classes/InputMap.xml
msgid "Removes an action from the [InputMap]."
-msgstr "从[InputMap]中删除一个动作。"
+msgstr "从 [InputMap] 中删除一个动作。"
#: doc/classes/InputMap.xml
msgid ""
@@ -38590,21 +38669,21 @@ msgstr ""
#: doc/classes/InputMap.xml
msgid "Returns an array of all actions in the [InputMap]."
-msgstr "返回[InputMap]中所有动作的数组。"
+msgstr "返回 [InputMap] 中所有动作的数组。"
#: doc/classes/InputMap.xml
msgid ""
"Returns [code]true[/code] if the [InputMap] has a registered action with the "
"given name."
-msgstr "如果[InputMap]有一个给定å称的注册动作,返回 [code]true[/code]。"
+msgstr "如果 [InputMap] 有一个给定å称的注册动作,返回 [code]true[/code]。"
#: doc/classes/InputMap.xml
msgid ""
"Clears all [InputEventAction] in the [InputMap] and load it anew from "
"[ProjectSettings]."
msgstr ""
-"清除[InputMap]中的所有[InputEventAction],并从[ProjectSettings]é¡¹ç›®è®¾ç½®ä¸­é‡æ–°"
-"加载它。"
+"清除 [InputMap] 中的所有 [InputEventAction],并从 [ProjectSettings] 项目设置"
+"䏭釿–°åŠ è½½å®ƒã€‚"
#: doc/classes/InstancePlaceholder.xml
msgid "Placeholder for the root [Node] of a [PackedScene]."
@@ -38643,7 +38722,7 @@ msgid ""
"Object.call_deferred] if calling from a thread."
msgstr ""
"获å–调用 [method replace_by_instance] 时默认加载的 [PackedScene] èµ„æºæ–‡ä»¶çš„è·¯"
-"å¾„ã€‚ä¸æ˜¯çº¿ç¨‹å®‰å…¨çš„。如果从线程调用,请使用[method Object.call_deferred]。"
+"å¾„ã€‚ä¸æ˜¯çº¿ç¨‹å®‰å…¨çš„。如果从线程调用,请使用 [method Object.call_deferred]。"
#: doc/classes/InstancePlaceholder.xml
msgid ""
@@ -38737,7 +38816,7 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid "[i]Deprecated.[/i] Camera which moves toward another node."
-msgstr "[i] 已弃用。[/i] å‘å¦ä¸€ä¸ªèŠ‚ç‚¹ç§»åŠ¨çš„ç›¸æœºã€‚"
+msgstr "[i] 已弃用。[/i]å‘å¦ä¸€ä¸ªèŠ‚ç‚¹ç§»åŠ¨çš„ç›¸æœºã€‚"
#: doc/classes/InterpolatedCamera.xml
msgid ""
@@ -38747,10 +38826,10 @@ msgid ""
"If it is not [member enabled] or does not have a valid target set, "
"InterpolatedCamera acts like a normal Camera."
msgstr ""
-"[i]å·²ç»å¼ƒç”¨ï¼ˆå°†åœ¨Godot 4.0 中删除)。[/i]æ’值相机是一ç§[Camera],å¯ä»¥å¹³ç¨³åœ°ç§»"
+"[i]已弃用(将在Godot 4.0 中删除)。[/i]æ’å€¼ç›¸æœºæ˜¯ä¸€ç§ [Camera],å¯ä»¥å¹³ç¨³åœ°ç§»"
"动,以匹é…目标节点的ä½ç½®å’Œæ—‹è½¬ã€‚\n"
-"å¦‚æžœå®ƒä¸æ˜¯[member enabled]或没有有效的目标集,InterpolatedCamera 的行为就åƒä¸€"
-"个正常的相机。"
+"å¦‚æžœå®ƒä¸æ˜¯ [member enabled] 或没有有效的目标集,InterpolatedCamera 的行为就åƒ"
+"一个正常的相机。"
#: doc/classes/InterpolatedCamera.xml
msgid "Sets the node to move toward and orient with."
@@ -38764,13 +38843,18 @@ msgstr "如果为 [code]true[/code],并且设置了目标,相机将自动移
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr "该相机的处ç†å›žè°ƒã€‚è§ [enum InterpolatedCameraProcessMode]。"
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr "相机å‘其目标移动的速度。较高的值将导致相机的è¿åŠ¨æ›´ç´§å¯†ã€‚"
#: doc/classes/InterpolatedCamera.xml
msgid "The target's [NodePath]."
-msgstr "目标的[NodePath]。"
+msgstr "目标的 [NodePath]。"
#: doc/classes/IntervalTweener.xml
msgid "Creates an idle interval in a [SceneTreeTween] animation."
@@ -38821,7 +38905,7 @@ msgstr ""
#: doc/classes/IP.xml
msgid "Returns all the user's current IPv4 and IPv6 addresses as an array."
-msgstr "以数组形å¼è¿”回所有用户的当å‰IPv4å’ŒIPv6地å€ã€‚"
+msgstr "以数组形å¼è¿”å›žæ‰€æœ‰ç”¨æˆ·çš„å½“å‰ IPv4 å’Œ IPv6 地å€ã€‚"
#: doc/classes/IP.xml
msgid ""
@@ -38879,8 +38963,8 @@ msgid ""
"method). The address type returned depends on the [enum Type] constant given "
"as [code]ip_type[/code]."
msgstr ""
-"åœ¨è§£æžæ—¶è¿”回一个给定的主机åçš„IPv4或IPv6地å€ï¼ˆé˜»å¡žç±»åž‹æ–¹æ³•)。返回的地å€ç±»åž‹"
-"å–决于作为[code]ip_type[/code]çš„[enum Type]常é‡ã€‚"
+"åœ¨è§£æžæ—¶è¿”回一个给定的主机åçš„ IPv4 或 IPv6 地å€ï¼ˆé˜»å¡žç±»åž‹æ–¹æ³•)。返回的地å€"
+"类型å–决于作为 [code]ip_type[/code] çš„ [enum Type] 常é‡ã€‚"
#: doc/classes/IP.xml
msgid ""
@@ -38921,7 +39005,7 @@ msgid ""
"Maximum number of concurrent DNS resolver queries allowed, [constant "
"RESOLVER_INVALID_ID] is returned if exceeded."
msgstr ""
-"å…许的最大并å‘DNSè§£æžå™¨æŸ¥è¯¢æ•°é‡ï¼Œå¦‚果超过,则返回[constant "
+"å…è®¸çš„æœ€å¤§å¹¶å‘ DNS è§£æžå™¨æŸ¥è¯¢æ•°é‡ï¼Œå¦‚果超过,则返回 [constant "
"RESOLVER_INVALID_ID]。"
#: doc/classes/IP.xml
@@ -38952,7 +39036,6 @@ msgid ""
msgstr "æä¾›å¯é€‰ä¸­é¡¹ç›®ï¼ˆå’Œ/或图标)列表的控件,既å¯ä»¥æ˜¯å•列,也å¯ä»¥æ˜¯å¤šåˆ—。"
#: doc/classes/ItemList.xml
-#, fuzzy
msgid ""
"This control provides a selectable list of items that may be in a single (or "
"multiple columns) with option of text, icons, or both text and icon. "
@@ -38982,12 +39065,19 @@ msgstr ""
"本ã€å›¾æ ‡æˆ–åŒæ—¶é€‰æ‹©æ–‡æœ¬å’Œå›¾æ ‡ã€‚支æŒå·¥å…·æç¤ºï¼Œåˆ—表中的æ¯ä¸ªé¡¹ç›®éƒ½å¯ä»¥æ˜¯ä¸åŒ"
"的。\n"
"列表中å¯é€‰æ‹©çš„项目å¯ä»¥è¢«é€‰æ‹©æˆ–å–æ¶ˆé€‰æ‹©ï¼Œå¹¶ä¸”å¯ä»¥å¯ç”¨å¤šé‡é€‰æ‹©ã€‚用鼠标å³é”®é€‰æ‹©"
-"也å¯ä»¥è¢«å¯ç”¨ï¼Œä»¥å…许使用弹出å¼ä¸Šä¸‹æ–‡èœå•。项目也å¯ä»¥é€šè¿‡åŒå‡»å®ƒä»¬æˆ–按Enter回车"
-"é”®æ¥ \"激活\"。\n"
-"é¡¹ç›®æ–‡æœ¬åªæ”¯æŒå•行字符串,字符串中的æ¢è¡Œå­—符(例如[code]\\n[/code])ä¸ä¼šäº§ç”Ÿ"
-"æ¢è¡Œã€‚在[constant ICON_MODE_TOP]模å¼ä¸‹ï¼Œæ–‡æœ¬è‡ªé€‚应(warp)是å¯ç”¨çš„,但默认情况"
-"下会调整列的宽度以完全适åˆå…¶å†…容。你需è¦è®¾ç½®[member fixed_column_width]大于0"
-"æ¥åŒ…使–‡æœ¬ã€‚"
+"也å¯ä»¥è¢«å¯ç”¨ï¼Œä»¥å…许使用弹出å¼ä¸Šä¸‹æ–‡èœå•。项目也å¯ä»¥é€šè¿‡åŒå‡»å®ƒä»¬æˆ–按回车键"
+"æ¥â€œæ¿€æ´»â€ã€‚\n"
+"é¡¹ç›®æ–‡æœ¬åªæ”¯æŒå•行字符串,字符串中的æ¢è¡Œå­—符(例如 [code]\\n[/code])ä¸ä¼šäº§ç”Ÿ"
+"æ¢è¡Œã€‚文本æ¢è¡Œä¼šåœ¨ [constant ICON_MODE_TOP] 模å¼ä¸‹å¯ç”¨ï¼Œä½†é»˜è®¤æƒ…况下会调整列"
+"的宽度以完全适åˆå…¶å†…容。你需è¦å°† [member fixed_column_width] 设为大于 0 的值"
+"æ‰èƒ½è®©æ–‡æœ¬æ¢è¡Œã€‚\n"
+"[b]å¢žé‡æœç´¢ï¼š[/b]与 [PopupMenu] å’Œ [Tree] 类似,[ItemList] 也支æŒåœ¨èšç„¦æŽ§ä»¶æ—¶"
+"在列表中进行æœç´¢ã€‚按下与æŸä¸ªæ¡ç›®å称首字æ¯ä¸€è‡´çš„æŒ‰é”®ï¼Œå°±ä¼šé€‰ä¸­ä»¥è¯¥å­—æ¯å¼€å¤´çš„"
+"第一个æ¡ç›®ã€‚在此之åŽï¼Œè¿›è¡Œå¢žé‡æœç´¢çš„办法有两ç§ï¼š1)在超时å‰å†æ¬¡æŒ‰ä¸‹åŒä¸€ä¸ªæŒ‰"
+"键,选中以该字æ¯å¼€å¤´çš„下一个æ¡ç›®ã€‚2ï¼‰åœ¨è¶…æ—¶å‰æŒ‰ä¸‹å‰©ä½™å­—æ¯å¯¹åº”的按键,直接匹é…"
+"并选中所需的æ¡ç›®ã€‚这两个动作都会在最åŽä¸€æ¬¡æŒ‰é”®è¶…æ—¶åŽé‡ç½®å›žåˆ—表顶端。你å¯ä»¥é€š"
+"过 [member ProjectSettings.gui/timers/incremental_search_max_interval_msec] "
+"修改超时时长。"
#: doc/classes/ItemList.xml
msgid "Adds an item to the item list with no text, only an icon."
@@ -39000,9 +39090,9 @@ msgid ""
"with no icon.\n"
"If selectable is [code]true[/code], the list item will be selectable."
msgstr ""
-"将一个项目添加到项目列表中,并指定文本。指定一个图标[code]icon[/code],或者图"
-"标[code]icon[/code]使用空[code]null[/code]作为没有图标的列表项。\n"
-"如果å¯é€‰æ‹©å¡«[code]true[/code],列表项将是å¯é€‰æ‹©çš„。"
+"将一个项目添加到项目列表中,并指定文本。指定一个图标 [code]icon[/code],或者"
+"图标 [code]icon[/code] 使用空 [code]null[/code] 作为没有图标的列表项。\n"
+"如果å¯é€‰æ‹©å¡« [code]true[/code],列表项将是å¯é€‰æ‹©çš„。"
#: doc/classes/ItemList.xml
msgid "Removes all items from the list."
@@ -39033,13 +39123,13 @@ msgstr "返回当å‰åˆ—表中的项目数。"
msgid ""
"Returns the custom background color of the item specified by [code]idx[/"
"code] index."
-msgstr "返回由[code]idx[/code]索引指定的项目的自定义背景颜色。"
+msgstr "返回由 [code]idx[/code] 索引指定的项目的自定义背景颜色。"
#: doc/classes/ItemList.xml
msgid ""
"Returns the custom foreground color of the item specified by [code]idx[/"
"code] index."
-msgstr "返回由[code]idx[/code]ç´¢å¼•æŒ‡å®šé¡¹ç›®çš„è‡ªå®šä¹‰å‰æ™¯é¢œè‰²ã€‚"
+msgstr "返回由 [code]idx[/code] ç´¢å¼•æŒ‡å®šé¡¹ç›®çš„è‡ªå®šä¹‰å‰æ™¯é¢œè‰²ã€‚"
#: doc/classes/ItemList.xml
msgid "Returns the icon associated with the specified index."
@@ -39047,13 +39137,13 @@ msgstr "返回与指定索引相关的图标。"
#: doc/classes/ItemList.xml
msgid "Returns a [Color] modulating item's icon at the specified index."
-msgstr "返回指定索引处的[Color]颜色调制(modulating) 项的图标。"
+msgstr "返回指定索引处的 [Color] 颜色调制项的图标。"
#: doc/classes/ItemList.xml
msgid ""
"Returns the region of item's icon used. The whole icon will be used if the "
"region has no area."
-msgstr "返回项目图标的使用区域。如果该区域大å°ä¸º0,整个图标将被使用。"
+msgstr "返回项目图标的使用区域。如果该区域大å°ä¸º 0,整个图标将被使用。"
#: doc/classes/ItemList.xml
msgid "Returns the metadata value of the specified index."
@@ -39133,13 +39223,13 @@ msgstr ""
msgid ""
"Sets the background color of the item specified by [code]idx[/code] index to "
"the specified [Color]."
-msgstr "将[code]idx[/code]索引指定的项目的背景色设置为指定的颜色[Color]。"
+msgstr "将 [code]idx[/code] 索引指定的项目的背景色设置为指定的颜色 [Color]。"
#: doc/classes/ItemList.xml
msgid ""
"Sets the foreground color of the item specified by [code]idx[/code] index to "
"the specified [Color]."
-msgstr "å°†[code]idx[/code]ç´¢å¼•æŒ‡å®šé¡¹ç›®çš„å‰æ™¯é¢œè‰²è®¾ç½®ä¸ºæŒ‡å®šçš„颜色[Color]。"
+msgstr "å°† [code]idx[/code] ç´¢å¼•æŒ‡å®šé¡¹ç›®çš„å‰æ™¯é¢œè‰²è®¾ç½®ä¸ºæŒ‡å®šçš„颜色 [Color]。"
#: doc/classes/ItemList.xml
msgid ""
@@ -39148,17 +39238,17 @@ msgid ""
"(when double-clicking or pressing Enter)."
msgstr ""
"ç¦ç”¨ï¼ˆæˆ–å¯ç”¨ï¼‰æŒ‡å®šç´¢å¼•上的项目。\n"
-"ç¦ç”¨çš„项目ä¸èƒ½è¢«é€‰ä¸­ï¼Œä¹Ÿä¸ä¼šè§¦å‘激活信å·ï¼ˆå½“åŒå‡»æˆ–按Enter回车键)。"
+"ç¦ç”¨çš„项目ä¸èƒ½è¢«é€‰ä¸­ï¼Œä¹Ÿä¸ä¼šè§¦å‘激活信å·ï¼ˆå½“åŒå‡»æˆ–按回车键)。"
#: doc/classes/ItemList.xml
msgid ""
"Sets (or replaces) the icon's [Texture] associated with the specified index."
-msgstr "设置(或替æ¢ï¼‰ä¸ŽæŒ‡å®šç´¢å¼•相关的图标的纹ç†[Texture]。"
+msgstr "设置(或替æ¢ï¼‰ä¸ŽæŒ‡å®šç´¢å¼•ç›¸å…³çš„å›¾æ ‡çš„çº¹ç† [Texture]。"
#: doc/classes/ItemList.xml
msgid ""
"Sets a modulating [Color] of the item associated with the specified index."
-msgstr "设置与指定索引相关的项目的调制颜色[Color]。"
+msgstr "设置与指定索引相关的项目的调制颜色 [Color]。"
#: doc/classes/ItemList.xml
msgid ""
@@ -39237,19 +39327,20 @@ msgid ""
"affected."
msgstr ""
"所有图标将被调整到的尺寸。\n"
-"如果X或Y分é‡ä¸å¤§äºŽ0,图标的大å°å°†ä¸ä¼šå—到影å“。"
+"如果 X 或 Y 分é‡ä¸å¤§äºŽ 0,图标的大å°å°†ä¸ä¼šå—到影å“。"
#: doc/classes/ItemList.xml
msgid ""
"The icon position, whether above or to the left of the text. See the [enum "
"IconMode] constants."
-msgstr "图标的ä½ç½®ï¼Œæ˜¯åœ¨æ–‡æœ¬çš„上方还是在文本的左边。å‚阅[enum IconMode]常é‡ã€‚"
+msgstr ""
+"图标的ä½ç½®ï¼Œæ˜¯åœ¨æ–‡æœ¬çš„上方还是在文本的左边。å‚阅 [enum IconMode] 常é‡ã€‚"
#: doc/classes/ItemList.xml
msgid ""
"The scale of icon applied after [member fixed_icon_size] and transposing "
"takes effect."
-msgstr "在[member fixed_icon_size]和转置生效åŽåº”用的图标比例。"
+msgstr "在 [member fixed_icon_size] 和转置生效åŽåº”用的图标比例。"
#: doc/classes/ItemList.xml
msgid ""
@@ -39294,7 +39385,7 @@ msgstr "å…许å•选或多选。å‚阅[enum SelectMode]常é‡ã€‚"
msgid ""
"Triggered when specified list item is activated via double-clicking or by "
"pressing Enter."
-msgstr "当指定的列表项目通过åŒå‡»æˆ–按Enter激活时触å‘。"
+msgstr "当指定的列表项目通过åŒå‡»æˆ–按回车键激活时触å‘。"
#: doc/classes/ItemList.xml
msgid ""
@@ -39326,7 +39417,7 @@ msgstr "在å…许多选的列表上更改多选时触å‘。"
msgid ""
"Triggered when a left mouse click is issued within the rect of the list but "
"on empty space."
-msgstr "当鼠标左键在列表的矩形(rect)范围内但在空白处å•击时,会被触å‘。"
+msgstr "当鼠标左键在列表的矩形范围内但在空白处å•击时,会被触å‘。"
#: doc/classes/ItemList.xml
msgid ""
@@ -39334,8 +39425,8 @@ msgid ""
"on empty space.\n"
"[member allow_rmb_select] must be enabled."
msgstr ""
-"当在列表的矩形(rect)范围内但在空白处å•击鼠标å³é”®æ—¶è¢«è§¦å‘。\n"
-"[member allow_rmb_select]必须被å¯ç”¨ã€‚"
+"当在列表的矩形范围内但在空白处å•击鼠标å³é”®æ—¶è¢«è§¦å‘。\n"
+"[member allow_rmb_select] 必须被å¯ç”¨ã€‚"
#: doc/classes/ItemList.xml
msgid "Icon is drawn above the text."
@@ -39351,7 +39442,7 @@ msgstr "ä»…å…许选择å•个项目。"
#: doc/classes/ItemList.xml
msgid "Allows selecting multiple items by holding Ctrl or Shift."
-msgstr "å…许通过按ä½Ctrl或Shift选择多个项目。"
+msgstr "å…è®¸é€šè¿‡æŒ‰ä½ Ctrl 或 Shift 选择多个项目。"
#: doc/classes/ItemList.xml doc/classes/Tree.xml
msgid "Default text [Color] of the item."
@@ -39359,7 +39450,7 @@ msgstr "项目的默认文本颜色 [Color]。"
#: doc/classes/ItemList.xml doc/classes/Tree.xml
msgid "Text [Color] used when the item is selected."
-msgstr "选择项目时使用的文本颜色[Color]。"
+msgstr "选择项目时使用的文本颜色 [Color]。"
#: doc/classes/ItemList.xml
msgid ""
@@ -39395,27 +39486,27 @@ msgstr "[ItemList] 的默认样å¼ç›’ [StyleBox],å³åœ¨æŽ§ä»¶æœªèŽ·å¾—ç„¦ç‚¹æ—
#: doc/classes/ItemList.xml
msgid "[StyleBox] used when the [ItemList] is being focused."
-msgstr "当[ItemList]被èšç„¦æ—¶ä½¿ç”¨çš„æ ·å¼ç›’[StyleBox]。"
+msgstr "当 [ItemList] 被èšç„¦æ—¶ä½¿ç”¨çš„æ ·å¼ç›’ [StyleBox]。"
#: doc/classes/ItemList.xml
msgid "[StyleBox] used for the cursor, when the [ItemList] is being focused."
-msgstr "当[ItemList]被èšç„¦æ—¶ï¼Œç”¨äºŽå…‰æ ‡çš„æ ·å¼ç›’[StyleBox]。"
+msgstr "当 [ItemList] 被èšç„¦æ—¶ï¼Œç”¨äºŽå…‰æ ‡çš„æ ·å¼ç›’ [StyleBox]。"
#: doc/classes/ItemList.xml
msgid ""
"[StyleBox] used for the cursor, when the [ItemList] is not being focused."
-msgstr "当[ItemList]没有被èšç„¦æ—¶ï¼Œç”¨äºŽå…‰æ ‡çš„æ ·å¼ç›’[StyleBox]。"
+msgstr "当 [ItemList] 没有被èšç„¦æ—¶ï¼Œç”¨äºŽå…‰æ ‡çš„æ ·å¼ç›’ [StyleBox]。"
#: doc/classes/ItemList.xml
msgid ""
"[StyleBox] for the selected items, used when the [ItemList] is not being "
"focused."
-msgstr "所选项的样å¼ç›’[StyleBox],当[ItemList]没有获得焦点时使用。"
+msgstr "所选项的样å¼ç›’ [StyleBox],当 [ItemList] 没有获得焦点时使用。"
#: doc/classes/ItemList.xml
msgid ""
"[StyleBox] for the selected items, used when the [ItemList] is being focused."
-msgstr "所选项的样å¼ç›’[StyleBox],当[ItemList]没有获得焦点时使用。"
+msgstr "所选项的样å¼ç›’ [StyleBox],当 [ItemList] 没有获得焦点时使用。"
#: doc/classes/JavaScript.xml
msgid ""
@@ -39644,7 +39735,7 @@ msgstr "创建 Android æ’ä»¶"
#: doc/classes/Joint.xml
msgid "Base class for all 3D joints."
-msgstr "所有3D关节的基类。"
+msgstr "所有 3D 关节的基类。"
#: doc/classes/Joint.xml
msgid ""
@@ -39668,11 +39759,11 @@ msgstr "如果为 [code]true[/code],则节点的两个主体无法相互碰撞
#: doc/classes/Joint.xml
msgid "The node attached to the first side (A) of the joint."
-msgstr "连接到关节第一侧(A)的节点。"
+msgstr "连接到关节第一侧(A)的节点。"
#: doc/classes/Joint.xml
msgid "The node attached to the second side (B) of the joint."
-msgstr "连接到关节第二侧(B)的节点。"
+msgstr "连接到关节第二侧(B)的节点。"
#: doc/classes/Joint.xml
msgid ""
@@ -39931,9 +40022,9 @@ msgid ""
"- [code]params[/code]: An array or dictionary of parameters being passed to "
"the method."
msgstr ""
-"返回JSON-RPC通知形å¼çš„字典。通知是一次性的信æ¯ï¼Œä¸éœ€è¦æœ‰å“应。\n"
-"- [code]method[/code]:被调用的方法的å称。\n"
-"- [code]params[/code]:ä¼ é€’ç»™è¯¥æ–¹æ³•çš„å‚æ•°çš„æ•°ç»„或字典。"
+"返回 JSON-RPC 通知形å¼çš„字典。通知是一次性的信æ¯ï¼Œä¸éœ€è¦æœ‰å“应。\n"
+"- [code]method[/code]:被调用的方法的å称。\n"
+"- [code]params[/code]ï¼šä¼ é€’ç»™è¯¥æ–¹æ³•çš„å‚æ•°çš„æ•°ç»„或字典。"
#: doc/classes/JSONRPC.xml
msgid ""
@@ -39946,11 +40037,11 @@ msgid ""
"- [code]id[/code]: Uniquely identifies this request. The server is expected "
"to send a response with the same ID."
msgstr ""
-"以JSON-RPC请求的形å¼è¿”回字典。请求被å‘é€åˆ°æœåŠ¡å™¨ï¼Œå¹¶æœŸæœ›å¾—åˆ°å“应。ID 字段用于"
-"æœåŠ¡å™¨æŒ‡å®šå®ƒæ­£åœ¨å“应的确切请求。\n"
-"- [code]method[/code]:被调用的方法的å称。\n"
-"- [code]params[/code]:ä¼ é€’ç»™è¯¥æ–¹æ³•çš„å‚æ•°çš„æ•°ç»„或字典。\n"
-"- [code]id[/code]:唯一标识此请求。æœåŠ¡å™¨åº”å‘é€å…·æœ‰ç›¸åŒ ID çš„å“应。"
+"以 JSON-RPC 请求的形å¼è¿”回字典。请求被å‘é€åˆ°æœåŠ¡å™¨ï¼Œå¹¶æœŸæœ›å¾—åˆ°å“应。ID 字段用"
+"于æœåŠ¡å™¨æŒ‡å®šå®ƒæ­£åœ¨å“应的确切请求。\n"
+"- [code]method[/code]:被调用的方法的å称。\n"
+"- [code]params[/code]ï¼šä¼ é€’ç»™è¯¥æ–¹æ³•çš„å‚æ•°çš„æ•°ç»„或字典。\n"
+"- [code]id[/code]:唯一标识此请求。æœåŠ¡å™¨åº”å‘é€å…·æœ‰ç›¸åŒ ID çš„å“应。"
#: doc/classes/JSONRPC.xml
msgid ""
@@ -39990,9 +40081,8 @@ msgid ""
"[code]action[/code]: The action to be run, as a Dictionary in the form of a "
"JSON-RPC request or notification."
msgstr ""
-"给定采用 JSON-RPC 请求形å¼çš„字典:解压请求并è¿è¡Œå®ƒã€‚通过查看å为 \"method\" "
-"的字段并在 JSONRPC 对象中查找等效命å的函数æ¥è§£æžæ–¹æ³•。如果找到,则调用该方"
-"法。\n"
+"给定采用 JSON-RPC 请求形å¼çš„字典:解压请求并è¿è¡Œå®ƒã€‚通过查看å为“methodâ€çš„å­—"
+"段并在 JSONRPC 对象中查找等效命å的函数æ¥è§£æžæ–¹æ³•。如果找到,则调用该方法。\n"
"è¦æ·»åŠ æ–°çš„å—æ”¯æŒæ–¹æ³•,请扩展 JSONRPC 类并在你的å­ç±»ä¸Šè°ƒç”¨ [method "
"process_action]。\n"
"[code]action[/code]:è¦è¿è¡Œçš„动作,作为 JSON-RPC 请求或通知形å¼çš„字典。"
@@ -40191,8 +40281,8 @@ msgid ""
"platform's motion, it will always be first in the slide collisions."
msgstr ""
"沿ç€å‘é‡ç§»åŠ¨ç‰©ä½“ã€‚å¦‚æžœè¿™ä¸ªç‰©ä½“ä¸Žå¦ä¸€ä¸ªç‰©ä½“相撞,它将沿ç€å¦ä¸€ä¸ªç‰©ä½“滑动,而ä¸"
-"是立å³åœæ­¢ã€‚如果å¦ä¸€ä¸ªç‰©ä½“是[KinematicBody]或[RigidBody],它也会被å¦ä¸€ä¸ªç‰©ä½“"
-"çš„è¿åŠ¨æ‰€å½±å“。你å¯ä»¥ç”¨å®ƒæ¥åˆ¶ä½œç§»åŠ¨å’Œæ—‹è½¬çš„å¹³å°ï¼Œæˆ–者让节点推动其他节点。\n"
+"是立å³åœæ­¢ã€‚如果å¦ä¸€ä¸ªç‰©ä½“是 [KinematicBody] 或 [RigidBody],它也会被å¦ä¸€ä¸ªç‰©"
+"体的è¿åŠ¨æ‰€å½±å“。你å¯ä»¥ç”¨å®ƒæ¥åˆ¶ä½œç§»åŠ¨å’Œæ—‹è½¬çš„å¹³å°ï¼Œæˆ–者让节点推动其他节点。\n"
"这个方法应该在 [method Node._physics_process] 中使用,或者在被 [method Node."
"_physics_process] è°ƒç”¨çš„æ–¹æ³•ä¸­ä½¿ç”¨ï¼Œå› ä¸ºå®ƒåœ¨è®¡ç®—æ—¶ï¼Œè‡ªåŠ¨ä½¿ç”¨ç‰©ç†æ­¥éª¤çš„ "
"[code]delta[/code] 值。å¦åˆ™ï¼Œæ¨¡æ‹Ÿå°†ä»¥ä¸æ­£ç¡®çš„速度è¿è¡Œã€‚\n"
@@ -40385,7 +40475,7 @@ msgid ""
"value is always positive and only valid after calling [method "
"move_and_slide] and when [method is_on_floor] returns [code]true[/code]."
msgstr ""
-"æ ¹æ®[code]up_direction[/code]返回最åŽä¸€ä¸ªç¢°æ’žç‚¹çš„地æ¿ç¢°æ’žè§’度,默认为"
+"æ ¹æ® [code]up_direction[/code] 返回最åŽä¸€ä¸ªç¢°æ’žç‚¹çš„地æ¿ç¢°æ’žè§’度,默认为 "
"[code]Vector2.UP[/code]。此值始终为正值,并且仅在调用 [method "
"move_and_slide] åŽä¸”当 [method is_on_floor] 返回 [code]true[/code] 时有效。"
@@ -40395,8 +40485,8 @@ msgid ""
"latest collision that occurred during the last call to [method "
"move_and_slide]."
msgstr ""
-"返回[KinematicCollision2D],它包å«åœ¨æœ€åŽä¸€æ¬¡è°ƒç”¨[method move_and_slide]æ—¶å‘生"
-"的最新碰撞信æ¯ã€‚"
+"返回 [KinematicCollision2D],它包å«åœ¨æœ€åŽä¸€æ¬¡è°ƒç”¨ [method move_and_slide] æ—¶"
+"å‘生的最新碰撞信æ¯ã€‚"
#: doc/classes/KinematicBody2D.xml
msgid ""
@@ -40544,9 +40634,9 @@ msgid ""
"colliding object, the remaining motion, and the collision position. This "
"information can be used to calculate a collision response."
msgstr ""
-"包å«[KinematicBody]碰撞的碰撞数æ®ã€‚当[KinematicBody]使用[method "
-"KinematicBody.move_and_collide]移动时,如果它检测到与å¦ä¸€ä¸ªç‰©ä½“的碰撞就会åœ"
-"止。如果检测到碰撞,将返回一个KinematicCollision对象。\n"
+"åŒ…å« [KinematicBody] 碰撞的碰撞数æ®ã€‚当 [KinematicBody] 使用 [method "
+"KinematicBody.move_and_collide] 移动时,如果它检测到与å¦ä¸€ä¸ªç‰©ä½“的碰撞就会åœ"
+"止。如果检测到碰撞,将返回一个 KinematicCollision 对象。\n"
"这个对象包å«å…³äºŽç¢°æ’žçš„ä¿¡æ¯ï¼ŒåŒ…括碰撞的物体ã€å‰©ä½™çš„è¿åŠ¨å’Œç¢°æ’žçš„ä½ç½®ã€‚这些信æ¯"
"å¯ä»¥ç”¨æ¥è®¡ç®—碰撞å“应。"
@@ -40555,8 +40645,8 @@ msgid ""
"The collision angle according to [code]up_direction[/code], which is "
"[code]Vector3.UP[/code] by default. This value is always positive."
msgstr ""
-"æ ¹æ®[code]up_direction[/code]的碰撞角度,默认为[code]Vector3.UP[/code]。这个"
-"值总是为正。"
+"æ ¹æ® [code]up_direction[/code] 的碰撞角度,默认为 [code]Vector3.UP[/code]。这"
+"个值总是为正。"
#: doc/classes/KinematicCollision.xml doc/classes/KinematicCollision2D.xml
msgid "The colliding body."
@@ -40793,19 +40883,19 @@ msgstr "通过展开行æ¥å¯¹é½æ•´ä¸ªæ–‡æœ¬ã€‚"
#: doc/classes/Label.xml
msgid "Default text [Color] of the [Label]."
-msgstr "[Label]标签的默认文本颜色[Color]。"
+msgstr "[Label] 标签的默认文本颜色 [Color]。"
#: doc/classes/Label.xml
msgid "[Color] of the text's shadow effect."
-msgstr "文本阴影效果的颜色[Color]。"
+msgstr "文本阴影效果的颜色 [Color]。"
#: doc/classes/Label.xml
msgid "The tint of [Font]'s outline. See [member DynamicFont.outline_color]."
-msgstr "[Font]轮廓的色调。å‚阅[member DynamicFont.outline_color]。"
+msgstr "[Font] è½®å»“çš„è‰²è°ƒã€‚è§ [member DynamicFont.outline_color]。"
#: doc/classes/Label.xml
msgid "Vertical space between lines in multiline [Label]."
-msgstr "多行[Label]中å„行之间的垂直空间。"
+msgstr "多行 [Label] 中å„行之间的垂直空间。"
#: doc/classes/Label.xml
msgid ""
@@ -40930,7 +41020,7 @@ msgstr "对 [Font] 轮廓的染色。"
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -40938,8 +41028,8 @@ msgid ""
"sorted from back to front (subject to priority)."
msgstr ""
"设置文本轮廓的渲染优先级。优先级高的物体将被排åºåœ¨ä¼˜å…ˆçº§ä½Žçš„物体å‰é¢ã€‚\n"
-"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant ALPHA_CUT_DISABLED](默认"
-"值)时适用。\n"
+"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant "
+"ALPHA_CUT_DISABLED](默认值)时适用。\n"
"[b]注æ„:[/b]ä»…é€‚ç”¨äºŽé€æ˜Žç‰©ä½“的排åºã€‚è¿™ä¸ä¼šå½±å“逿˜Žç‰©ä½“相对于ä¸é€æ˜Žç‰©ä½“的排åº"
"æ–¹å¼ã€‚这是因为ä¸é€æ˜Žå¯¹è±¡ä¸è¢«æŽ’åºï¼Œè€Œé€æ˜Žå¯¹è±¡åˆ™ä»ŽåŽå¾€å‰æŽ’åºï¼ˆå–决于优先级)。"
@@ -40951,7 +41041,7 @@ msgstr "标签上一个åƒç´ å®½åº¦çš„大å°ï¼Œä»¥ 3D 缩放。"
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -40959,8 +41049,8 @@ msgid ""
"sorted from back to front (subject to priority)."
msgstr ""
"设置文本的渲染优先级。优先级高的物体将被排åºåœ¨ä¼˜å…ˆçº§ä½Žçš„物体å‰é¢ã€‚\n"
-"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant ALPHA_CUT_DISABLED](默认"
-"值)时适用。\n"
+"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant "
+"ALPHA_CUT_DISABLED](默认值)时适用。\n"
"[b]注æ„:[/b]ä»…é€‚ç”¨äºŽé€æ˜Žç‰©ä½“的排åºã€‚è¿™ä¸ä¼šå½±å“逿˜Žç‰©ä½“相对于ä¸é€æ˜Žç‰©ä½“的排åº"
"æ–¹å¼ã€‚这是因为ä¸é€æ˜Žå¯¹è±¡ä¸è¢«æŽ’åºï¼Œè€Œé€æ˜Žå¯¹è±¡åˆ™ä»ŽåŽå¾€å‰æŽ’åºï¼ˆå–决于优先级)。"
@@ -40987,9 +41077,9 @@ msgstr "如果打开,环境中的ç¯å…‰ä¼šå½±å“该标签。"
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
-msgstr "如果打开,从åŽé¢ä¹Ÿå¯ä»¥çœ‹åˆ°æ–‡æœ¬ï¼Œå¦‚æžœä¸æ‰“开,从åŽé¢çœ‹å®ƒæ˜¯ä¸å¯è§çš„。"
+msgstr "如果打开,从åŽé¢ä¹Ÿå¯ä»¥çœ‹åˆ°æ–‡æœ¬ã€‚å¦‚æžœä¸æ‰“开,从åŽé¢çœ‹è¯¥æ–‡æœ¬æ˜¯ä¸å¯è§çš„。"
#: doc/classes/Label3D.xml doc/classes/SpatialMaterial.xml
#: doc/classes/SpriteBase3D.xml
@@ -41143,7 +41233,7 @@ msgstr "如果为 [code]true[/code],ç¯å…‰åªåœ¨ç¼–辑器中出现,在è¿è¡Œ
#: doc/classes/Light.xml
msgid "The light's bake mode. See [enum BakeMode]."
-msgstr "ç¯å…‰çš„烘焙模å¼ã€‚å‚阅[enum BakeMode]。"
+msgstr "ç¯å…‰çš„烘焙模å¼ã€‚è§ [enum BakeMode]。"
#: doc/classes/Light.xml
msgid ""
@@ -43579,11 +43669,14 @@ msgid ""
"[method Mesh.surface_get_material] to get materials associated with the "
"[Mesh] resource."
msgstr ""
+"返回该 [Mesh] 资æºä¸ŠæŸä¸ªè¡¨é¢çš„ [Material] 覆盖项。\n"
+"[b]注æ„:[/b]这个函数åªä¼šè¿”回与这个 [MeshInstance] 相关è”çš„[i]覆盖[/i]æè´¨ã€‚"
+"è¦èŽ·å–与该 [Mesh] 相关è”çš„æè´¨ï¼Œè¯·è€ƒè™‘使用 [method get_active_material] 或 "
+"[method Mesh.surface_get_material]。"
#: doc/classes/MeshInstance.xml
-#, fuzzy
msgid "Returns the number of surface override materials."
-msgstr "è¿”å›žè¡¨é¢æè´¨çš„æ•°é‡ã€‚"
+msgstr "è¿”å›žè¡¨é¢æè´¨è¦†ç›–é¡¹çš„æ•°é‡ã€‚"
#: doc/classes/MeshInstance.xml
msgid ""
@@ -43638,6 +43731,8 @@ msgid ""
"resource. This material is associated with this [MeshInstance] rather than "
"with the [Mesh] resource."
msgstr ""
+"设置该 [Mesh] 资æºçš„æŒ‡å®šè¡¨é¢çš„ [Material] 覆盖项。这个æè´¨ä¼šä¸Žè¿™ä¸ª "
+"[MeshInstance] å…³è”ï¼Œè€Œä¸æ˜¯ä¸Ž [Mesh] 资æºå…³è”。"
#: doc/classes/MeshInstance.xml
msgid "The [Mesh] resource for the instance."
@@ -44632,7 +44727,6 @@ msgid "Mesh-based navigation and pathfinding node."
msgstr "基于网格的导航和寻路节点。"
#: doc/classes/Navigation.xml
-#, fuzzy
msgid ""
"[i]Deprecated.[/i] [Navigation] node and [method get_simple_path] are "
"deprecated and will be removed in a future version. Use [method "
@@ -44643,6 +44737,8 @@ msgid ""
"class also assists with aligning navigation agents with the meshes they are "
"navigating on."
msgstr ""
+"[i]已弃用。[/i][Navigation] 节点和 [method get_simple_path] 已弃用,会在将æ¥"
+"的版本中移除。请用 [method NavigationServer.map_get_path] 替代。\n"
"在 [NavigationMesh] 的集åˆä¸­æä¾›å¯¼èˆªå’Œå¯»è·¯åŠŸèƒ½ã€‚é»˜è®¤æƒ…å†µä¸‹ï¼Œè¿™äº›å°†è‡ªåŠ¨ä»Žå­ "
"[NavigationMeshInstance] 节点中收集。除了基本的寻路之外,这个类还能帮助导航代"
"ç†ä¸Žå…¶æ‰€å¯¼èˆªçš„网格对é½ã€‚"
@@ -44690,7 +44786,6 @@ msgid "Returns the [RID] of the navigation map on the [NavigationServer]."
msgstr "返回这个导航地图在 [NavigationServer] 上的 [RID]。"
#: doc/classes/Navigation.xml
-#, fuzzy
msgid ""
"[i]Deprecated.[/i] [Navigation] node and [method get_simple_path] are "
"deprecated and will be removed in a future version. Use [method "
@@ -44700,6 +44795,8 @@ msgid ""
"agent properties associated with each [NavigationMesh] (radius, height, "
"etc.) are considered in the path calculation, otherwise they are ignored."
msgstr ""
+"[i]已弃用。[/i][Navigation] 节点和 [method get_simple_path] 已弃用,会在将æ¥"
+"的版本中移除。请用 [method NavigationServer.map_get_path] 替代。\n"
"è¿”å›žä¸¤ä¸ªç»™å®šç‚¹ä¹‹é—´çš„è·¯å¾„ã€‚ç‚¹éƒ½æ˜¯åœ¨å±€éƒ¨åæ ‡ç©ºé—´ä¸­çš„。如果 [code]optimize[/"
"code] 为 [code]true[/code](默认),则计算路径时会考虑æ¯ä¸ª [NavigationMesh] "
"所关è”的代ç†çš„属性(åŠå¾„ã€é«˜åº¦ç­‰ï¼‰ï¼Œå¦åˆ™ä¼šè¢«å¿½ç•¥ã€‚"
@@ -44744,7 +44841,6 @@ msgid "2D navigation and pathfinding node."
msgstr "2D 导航和寻路节点。"
#: doc/classes/Navigation2D.xml
-#, fuzzy
msgid ""
"[i]Deprecated.[/i] [Navigation2D] node and [method get_simple_path] are "
"deprecated and will be removed in a future version. Use [method "
@@ -44753,6 +44849,8 @@ msgid ""
"as a collection of [NavigationPolygon] resources. By default, these are "
"automatically collected from child [NavigationPolygonInstance] nodes."
msgstr ""
+"[i]已弃用。[/i][Navigation2D] 节点和 [method get_simple_path] 已弃用,会在将"
+"æ¥çš„版本中移除。请用 [method Navigation2DServer.map_get_path] 替代。\n"
"Navigation2D 在 2D 区域内æä¾›å¯¼èˆªå’Œå¯»è·¯ï¼Œè¯¥åŒºåŸŸä»¥ [NavigationPolygon] 资æºåˆ"
"é›†çš„å½¢å¼æŒ‡å®šã€‚é»˜è®¤æƒ…å†µä¸‹ï¼Œè¿™äº›èµ„æºæ˜¯è‡ªåŠ¨ä»Žå­é¡¹ [NavigationPolygonInstance] 节"
"点中收集的。"
@@ -44772,7 +44870,6 @@ msgstr ""
"[NavigationPolygonInstance]。"
#: doc/classes/Navigation2D.xml
-#, fuzzy
msgid ""
"[i]Deprecated.[/i] [Navigation2D] node and [method get_simple_path] are "
"deprecated and will be removed in a future version. Use [method "
@@ -44781,6 +44878,8 @@ msgid ""
"space. If [code]optimize[/code] is [code]true[/code] (the default), the path "
"is smoothed by merging path segments where possible."
msgstr ""
+"[i]已弃用。[/i][Navigation2D] 节点和 [method get_simple_path] 已弃用,会在将"
+"æ¥çš„版本中移除。请用 [method Navigation2DServer.map_get_path] 替代。\n"
"è¿”å›žä¸¤ä¸ªç»™å®šç‚¹ä¹‹é—´çš„è·¯å¾„ã€‚ç‚¹æ˜¯åœ¨å±€éƒ¨åæ ‡ç©ºé—´ä¸­çš„。如果 [code]optimize[/code] "
"为 [code]true[/code](默认值),路径将尽å¯èƒ½åœ°åˆå¹¶è·¯å¾„段,从而平滑。"
@@ -44947,6 +45046,8 @@ msgid ""
"returns both 2D and 3D created navigation maps as there is technically no "
"distinction between them."
msgstr ""
+"返回该 NavigationServer 上所有已创建的导航地图的 [RID]ã€‚ä¼šåŒæ—¶è¿”回已创建的 "
+"2D å’Œ 3D 导航地图,因为ç†è®ºä¸Šå®ƒä»¬ä¹‹é—´æ˜¯æ²¡æœ‰åŒºåˆ«çš„。"
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid "Create a new map."
@@ -44980,6 +45081,21 @@ msgid ""
"but it can also introduce bugs if used inappropriately without much "
"foresight."
msgstr ""
+"这个函数会立å³å¼ºåˆ¶è¿›è¡ŒæŒ‡å®šå¯¼èˆªåœ°å›¾çš„åŒæ­¥ï¼Œå‚æ•° [code]map[/code] 为 [RID] ç±»"
+"型。默认情况下,导航地图仅会在æ¯ä¸ªç‰©ç†å¸§çš„æœ«å°¾è¿›è¡ŒåŒæ­¥ã€‚这个函数å¯ç”¨äºŽç«‹å³"
+"ï¼ˆé‡æ–°ï¼‰è®¡ç®—该导航地图的所有导航网格和地区连接。这样就能够在修改地图åŽï¼Œåœ¨åŒ"
+"一帧中立å³å¯¹å¯¼èˆªè·¯å¾„è¿›è¡ŒæŸ¥è¯¢ï¼ˆéœ€è¦æ—¶å¯ä»¥è¿›è¡Œå¤šæ¬¡åŒæ­¥ï¼‰ã€‚\n"
+"由于技术上的é™åˆ¶ï¼Œå½“å‰çš„ NavigationServer 命令队列会被清空。这æ„å‘³ç€æ‰€æœ‰å·²åœ¨"
+"当å‰ç‰©ç†å¸§ä¸­å…¥é˜Ÿçš„命令都会被执行,å³ä¾¿è¿™äº›å‘½ä»¤ä¸ŽæŒ‡å®šçš„地图无关,针对的是其他"
+"地图ã€åœ°åŒºã€ä»£ç†ã€‚消耗较大的导航网格以åŠåœ°åŒºè¿žæŽ¥çš„计算åªä¼šå¯¹æŒ‡å®šçš„地图进行。"
+"其他地图会在该物ç†å¸§çš„æœ«å°¾è¿›è¡Œå¸¸è§„çš„åŒæ­¥ã€‚如果指定的地图在进行强制更新åŽåˆæ”¶"
+"到了修改,那么它也会在其他地图更新时å—到更新。\n"
+"这个函数ä¸ä¼šè§¦åŠé¿éšœå¤„ç†ä»¥åŠ [code]safe_velocity[/code] ä¿¡å·çš„分å‘,这些还是"
+"会在该物ç†å¸§çš„æœ«å°¾é’ˆå¯¹æ‰€æœ‰åœ°å›¾çš„代ç†è¿›è¡Œå¤„ç†ã€‚\n"
+"[b]注æ„:[/b]èƒ½åŠ›è¶Šå¤§ï¼Œè´£ä»»è¶Šå¤§ã€‚åªæœ‰çœŸæ­£æ˜Žç™½è‡ªå·±åœ¨å¹²ä»€ä¹ˆçš„用户æ‰åº”该在真正有"
+"éœ€è¦æ—¶ä½¿ç”¨è¿™ä¸ªå‡½æ•°ã€‚å¼ºåˆ¶è¿›è¡Œå¯¼èˆªåœ°å›¾çš„ç«‹å³æ›´æ–°éœ€è¦å¯¹ NavigationServer 加é”å¹¶"
+"清空整个 NavigationServer 的命令队列。这样åšä¸ä»…ä¼šå¤§å¹…å½±å“æ¸¸æˆçš„æ€§èƒ½ï¼Œå¦‚果使"
+"用ä¸å½“ã€ç¼ºä¹è¿œè§ï¼Œè¿˜å¯èƒ½å¼•å…¥ bug。"
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid ""
@@ -45113,6 +45229,15 @@ msgid ""
"(which should be avoided in general) the result might not be what is "
"expected."
msgstr ""
+"å¦‚æžœç»™å‡ºçš„ä¸–ç•Œç©ºé—´åæ ‡ç‚¹ [code]point[/code] ç›®å‰ç”±ç»™å‡ºçš„导航地区 "
+"[code]region[/code] 拥有,则返回 [code]true[/code]ã€‚è¿™é‡Œçš„â€œæ‹¥æœ‰â€æŒ‡çš„æ˜¯è¯¥åœ°åŒº"
+"的导航网格多边形é¢ä¸­åŒ…å«è¿™ä¸ªå¯èƒ½çš„ä½ç½®ï¼Œå¹¶ä¸”与给出的地区的导航地区上所有其他"
+"导航地区的导航网格相比,它与这个点的è·ç¦»æ˜¯æœ€è¿‘的。\n"
+"如果有多个导航网格包å«è¿™ä¸ªç‚¹å¹¶ä¸”è·ç¦»ç›¸ç­‰ï¼Œå“ªä¸ªå¯¼èˆªåœ°åŒºçš„多边形先被处ç†ï¼Œé‚£ä¸ª"
+"å¯¼èˆªåœ°åŒºå°±èŽ·å–æ‰€æœ‰æƒã€‚多边形的处ç†é¡ºåºä¸Žå¯¼èˆªåœ°åŒºåœ¨ NavigationServer 上的注册"
+"顺åºä¸€è‡´ã€‚\n"
+"[b]注æ„:[/b]如果ä¸åŒå¯¼èˆªåœ°åŒºçš„导航网格存在é‡å ï¼ˆé€šå¸¸åº”当é¿å…),å¯èƒ½å¾—到预料"
+"之外的结果。"
#: doc/classes/Navigation2DServer.xml doc/classes/NavigationServer.xml
msgid "Sets the [code]enter_cost[/code] for this [code]region[/code]."
@@ -45379,6 +45504,10 @@ msgid ""
"it will constantly overshoot or undershoot the distance to the next point on "
"each physics frame update."
msgstr ""
+"è·ç¦»é˜ˆå€¼ï¼Œç”¨äºŽç¡®å®šæ˜¯å¦å·²åˆ°è¾¾æŸä¸ªè·¯å¾„点。使用这个值,代ç†å°±ä¸å¿…精确地到达æŸä¸ª"
+"路径点,到达æŸä¸ªåŒºåŸŸå†…å³å¯ã€‚如果这个值设得太大,该 NavigationAgent 将跳过路径"
+"上的点,å¯èƒ½å¯¼è‡´å…¶ç¦»å¼€è¯¥å¯¼èˆªç½‘格。如果这个值设得太å°ï¼Œè¯¥ NavigationAgent 将陷"
+"入釿–°å¯»è·¯çš„æ­»å¾ªçŽ¯ï¼Œå› ä¸ºå®ƒåœ¨æ¯æ¬¡ç‰©ç†å¸§æ›´æ–°åŽéƒ½ä¼šè¶…过或者到ä¸äº†ä¸‹ä¸€ä¸ªç‚¹ã€‚"
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -45389,7 +45518,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 "
@@ -45398,6 +45527,11 @@ msgid ""
"bake [NavigationMesh] resources with a different [member NavigationMesh."
"agent_radius] property and use different navigation maps for each actor size."
msgstr ""
+"该é¿éšœä»£ç†çš„åŠå¾„。这是该é¿éšœä»£ç†çš„“身体â€ï¼Œä¸æ˜¯é¿éšœæœºåˆ¶çš„èµ·å§‹åŠå¾„(由 [member "
+"neighbor_dist] 控制)。\n"
+"ä¸ä¼šå½±å“正常的寻路。è¦ä¿®æ”¹è§’色的寻路åŠå¾„,请在烘焙 [NavigationMesh] èµ„æºæ—¶ä½¿"
+"用ä¸åŒçš„ [member NavigationMesh.agent_radius] 属性,针对ä¸åŒçš„角色大å°ä½¿ç”¨ä¸"
+"åŒçš„导航地图。"
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -45408,6 +45542,9 @@ msgid ""
"overshoot or undershoot the distance to the final target point on each "
"physics frame update."
msgstr ""
+"è·ç¦»é˜ˆå€¼ï¼Œç”¨äºŽç¡®å®šæ˜¯å¦å·²åˆ°è¾¾æœ€ç»ˆçš„目标点。使用这个值,代ç†å°±ä¸å¿…精确地到达最"
+"终的目标,到达该区域内å³å¯ã€‚如果这个值设得太å°ï¼Œè¯¥ NavigationAgent 将陷入釿–°"
+"å¯»è·¯çš„æ­»å¾ªçŽ¯ï¼Œå› ä¸ºå®ƒåœ¨æ¯æ¬¡ç‰©ç†å¸§æ›´æ–°åŽéƒ½ä¼šè¶…过或者到ä¸äº†æœ€ç»ˆçš„目标点。"
#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
msgid ""
@@ -45522,6 +45659,17 @@ 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 ""
+"该é¿éšœä»£ç†çš„åŠå¾„。这是该é¿éšœä»£ç†çš„“身体â€ï¼Œä¸æ˜¯é¿éšœæœºåˆ¶çš„èµ·å§‹åŠå¾„(由 [member "
+"neighbor_dist] 控制)。\n"
+"ä¸ä¼šå½±å“正常的寻路。"
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr "ç”¨äºŽæ¨¡æ‹Ÿå¯æ­¥è¡ŒåŒºåŸŸå’Œéšœç¢ç‰©çš„网格。"
@@ -45660,11 +45808,11 @@ msgstr ""
msgid ""
"If the baking [AABB] has a volume the navigation mesh baking will be "
"restricted to its enclosing area."
-msgstr ""
+msgstr "如果烘焙 [AABB] 存在体积,对该导航网格的烘焙会被é™åˆ¶åœ¨å…¶å†…部区域中。"
#: doc/classes/NavigationMesh.xml
msgid "The position offset applied to the [member filter_baking_aabb] [AABB]."
-msgstr ""
+msgstr "应用于 [member filter_baking_aabb] [AABB] çš„ä½ç½®åç§»é‡ã€‚"
#: doc/classes/NavigationMesh.xml
msgid "If [code]true[/code], marks spans that are ledges as non-walkable."
@@ -45837,7 +45985,6 @@ msgid "Helper class for creating and clearing navigation meshes."
msgstr "对导航网格进行创建和清ç†çš„辅助类。"
#: doc/classes/NavigationMeshGenerator.xml
-#, fuzzy
msgid ""
"This class is responsible for creating and clearing 3D navigation meshes "
"used as [NavigationMesh] resources inside [NavigationMeshInstance]. The "
@@ -45897,7 +46044,11 @@ msgstr ""
"è±¡ï¼Œé€šè¿‡åœ¨ç½‘æ ¼çš„åŒ…å›´åŒºåŸŸå‘¨è¾¹åˆ›å»ºä½“ç´ ä¸–ç•Œï¼Œæ¥æ£€æŸ¥åŽŸå§‹å‡ ä½•ä½“ä¸­é€‚åˆ "
"[NavigationMesh] 代ç†è¡Œèµ°çš„地形。\n"
"ç„¶åŽå°±ä¼šè¿”回最终的导航网格,ä¿å­˜åœ¨ [NavigationMesh] 中,å³å¯äº¤ä»˜ "
-"[NavigationMeshInstance] 使用。"
+"[NavigationMeshInstance] 使用。\n"
+"[b]注æ„:[/b]使用网格æ¥å®šä¹‰å¯è¡Œèµ°åŒºåŸŸå¹¶é®æŒ¡å¯¼èˆªçƒ˜ç„™å¹¶ä¸æ€»èƒ½æˆåŠŸã€‚çƒ˜ç„™å¯¼èˆªå¤„ç†"
+"网格原始几何体时,并没有几何体“ä½äºŽå†…部â€çš„æ¦‚念,这是有æ„而为之的。根æ®å½“å‰çƒ˜"
+"ç„™å‚æ•°çš„ä¸åŒï¼Œåªè¦é®æŒ¡ç½‘格足够大,大到能够将导航网格区域包å«åœ¨å…¶å†…部,烘焙时"
+"就会生æˆä¸€ä¸ªå¯¼èˆªç½‘格区域,ä½äºŽé®æŒ¡çš„原始几何体网格内部。"
#: doc/classes/NavigationMeshGenerator.xml
msgid ""
@@ -45937,18 +46088,18 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
msgstr ""
-"[NavigationMesh] 的实例。[Navigation] 节点根æ®å®ƒçš„ [NavigationMesh] èµ„æºæ¥ç¡®"
-"定哪些å¯ä»¥è¿›è¡Œå¯¼èˆªã€å“ªäº›ä¸èƒ½ã€‚\n"
+"[NavigationMesh] 的实例。[Navigation] 节点根æ®å®ƒçš„ [NavigationMesh] "
+"èµ„æºæ¥ç¡®å®šå“ªäº›å¯ä»¥è¿›è¡Œå¯¼èˆªã€å“ªäº›ä¸èƒ½ã€‚\n"
"默认情况下,这个节点会在默认的 [World] 导航地图中进行注册。如果这个节点是 "
"[Navigation] 节点的å­é¡¹ï¼Œå°±ä¼šåœ¨è¯¥å¯¼èˆªèŠ‚ç‚¹çš„å¯¼èˆªåœ°å›¾ä¸­è¿›è¡Œæ³¨å†Œã€‚\n"
"如果两个地图共享类似的边界,就å¯ä»¥ç›¸äº’连接。你å¯ä»¥é€šè¿‡ [method "
-"NavigationServer.map_set_edge_connection_margin] 设置两个顶点连接两æ¡è¾¹ç•Œæ‰€éœ€"
-"的最å°è·ç¦»ã€‚\n"
+"NavigationServer.map_set_edge_connection_margin] "
+"设置两个顶点连接两æ¡è¾¹ç•Œæ‰€éœ€çš„æœ€å°è·ç¦»ã€‚\n"
"[b]注æ„:[/b]将两个地区的导航网格相互é‡å å¹¶ä¸è¶³ä»¥å°†å…¶ç›¸è¿žã€‚它们必须共享类似的"
"边界。\n"
"从å¦ä¸€ä¸ªåœ°åŒºè¿›å…¥è¿™ä¸ªåœ°å›¾çš„æ¶ˆè€—å¯ä»¥é€šè¿‡ [member enter_cost] 进行控制。\n"
@@ -46274,18 +46425,18 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
msgstr ""
-"导航地图上的地区。[Navigation2DServer] æ ¹æ®å®ƒçš„ [NavigationPolygon] èµ„æºæ¥ç¡®"
-"定哪些å¯ä»¥è¿›è¡Œå¯¼èˆªã€å“ªäº›ä¸èƒ½ã€‚\n"
+"导航地图上的地区。[Navigation2DServer] æ ¹æ®å®ƒçš„ [NavigationPolygon] "
+"èµ„æºæ¥ç¡®å®šå“ªäº›å¯ä»¥è¿›è¡Œå¯¼èˆªã€å“ªäº›ä¸èƒ½ã€‚\n"
"默认情况下,这个节点会在默认的 [World2D] 导航地图中进行注册。如果这个节点是 "
"[Navigation2D] 节点的å­é¡¹ï¼Œå°±ä¼šåœ¨è¯¥å¯¼èˆªèŠ‚ç‚¹çš„å¯¼èˆªåœ°å›¾ä¸­è¿›è¡Œæ³¨å†Œã€‚\n"
"如果两个地图共享类似的边界,就å¯ä»¥ç›¸äº’连接。你å¯ä»¥é€šè¿‡ [method "
-"Navigation2DServer.map_set_edge_connection_margin] 设置两个顶点连接两æ¡è¾¹ç•Œæ‰€"
-"需的最å°è·ç¦»ã€‚\n"
+"Navigation2DServer.map_set_edge_connection_margin] "
+"设置两个顶点连接两æ¡è¾¹ç•Œæ‰€éœ€çš„æœ€å°è·ç¦»ã€‚\n"
"[b]注æ„:[/b]将两个地区的导航网格相互é‡å å¹¶ä¸è¶³ä»¥å°†å…¶ç›¸è¿žã€‚它们必须共享类似的"
"边界。\n"
"从å¦ä¸€ä¸ªåœ°åŒºè¿›å…¥è¿™ä¸ªåœ°å›¾çš„寻路消耗å¯ä»¥é€šè¿‡ [member enter_cost] 进行控制。\n"
@@ -46428,6 +46579,62 @@ msgstr ""
msgid "Control activation of this server."
msgstr "控制这个æœåŠ¡å™¨æ˜¯å¦æ¿€æ´»ã€‚"
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr "对 [NetworkedMultiplayerPeer] 的一ç§å®žçŽ°ï¼Œèƒ½å¤Ÿé€šè¿‡è„šæœ¬æŽ§åˆ¶ã€‚"
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+"对 [NetworkedMultiplayerPeer] 的一ç§å®žçŽ°ï¼Œèƒ½å¤Ÿä½œä¸º [member MultiplayerAPI."
+"network_peer] 使用并且通过脚本控制。\n"
+"其目的是为高级多人 API 添加新的åŽç«¯ï¼Œä¸å¿…使用 GDNative。"
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+"呿œ¬åœ° [MultiplayerAPI] 传递数æ®åŒ…。\n"
+"当你的脚本通过网络收到其他对等体的数æ®åŒ…时(å‘逿–¹å‘出 [signal "
+"packet_generated] ä¿¡å·ï¼‰ï¼Œå°†å…¶ä¼ é€’给这个方法会在本地进行传递。"
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr "使用给定的 [code]peer_id[/code] åˆå§‹åŒ–该对等体(必须在 1 å’Œ 2147483647 "
+"之间)。"
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr "设置连接的状æ€ã€‚è§ [enum NetworkedMultiplayerPeer.ConnectionStatus]。"
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr "设置这个对等体所能够处ç†çš„æœ€å¤§æ•°æ®åŒ…大å°ã€‚"
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+"当本地 [MultiplayerAPI] ç”Ÿæˆæ•°æ®åŒ…时触å‘。\n"
+"你的脚本应当获å–这个数æ®åŒ…并将其通过网络å‘é€ç»™è¯·æ±‚的对等体("
+"å¯¹æ–¹æ”¶åˆ°è¯¥æ•°æ®æ—¶åº”当调用 [method deliver_packet])。"
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -48461,7 +48668,6 @@ msgstr ""
"称设置为唯一å称。"
#: doc/classes/Node.xml
-#, fuzzy
msgid ""
"Emitted when a child node enters the scene tree, either because it entered "
"on its own or because this node entered with it.\n"
@@ -48469,7 +48675,9 @@ msgid ""
"NOTIFICATION_ENTER_TREE] and [signal tree_entered]."
msgstr ""
"在å­èŠ‚ç‚¹è¿›å…¥åœºæ™¯æ ‘æ—¶è§¦å‘,å¯ä»¥æ˜¯å› ä¸ºè¯¥å­èŠ‚ç‚¹è‡ªè¡Œè¿›å…¥ï¼Œä¹Ÿå¯ä»¥æ˜¯å› ä¸ºæœ¬èŠ‚ç‚¹å¸¦ç€"
-"该å­èŠ‚ç‚¹ä¸€èµ·è¿›å…¥ã€‚"
+"该å­èŠ‚ç‚¹ä¸€èµ·è¿›å…¥ã€‚\n"
+"这个信å·ä¼šåœ¨è¯¥å­èŠ‚ç‚¹è‡ªèº«çš„ [constant NOTIFICATION_ENTER_TREE] å’Œ [signal "
+"tree_entered] [i]之åŽ[/i]触å‘。"
#: doc/classes/Node.xml
msgid ""
@@ -48480,14 +48688,19 @@ msgid ""
"tree and valid. This signal is emitted [i]after[/i] the child node's own "
"[signal tree_exiting] and [constant NOTIFICATION_EXIT_TREE]."
msgstr ""
+"在å­èŠ‚ç‚¹å³å°†é€€å‡ºåœºæ™¯æ ‘时触å‘,å¯ä»¥æ˜¯å› ä¸ºè¯¥å­èŠ‚ç‚¹è‡ªè¡Œé€€å‡ºï¼Œä¹Ÿå¯ä»¥æ˜¯å› ä¸ºæœ¬èŠ‚ç‚¹"
+"带ç€è¯¥å­èŠ‚ç‚¹ä¸€èµ·é€€å‡ºã€‚\n"
+"æ”¶åˆ°è¿™ä¸ªä¿¡å·æ—¶ï¼Œè¯¥å­èŠ‚ [code]node[/code] ä»åœ¨æ ‘中并且有效。这个信å·ä¼šåœ¨è¯¥å­èŠ‚"
+"点自身的 [signal tree_exiting] å’Œ [constant NOTIFICATION_EXIT_TREE] [i]之åŽ[/"
+"i]触å‘。"
#: doc/classes/Node.xml
msgid "Emitted when the node is ready."
-msgstr "当节点准备好时触å‘。"
+msgstr "当该节点准备好时触å‘。"
#: doc/classes/Node.xml
msgid "Emitted when the node is renamed."
-msgstr "在é‡å‘½å节点时触å‘。"
+msgstr "当该节点被é‡å‘½å时触å‘。"
#: doc/classes/Node.xml
msgid ""
@@ -48495,34 +48708,39 @@ msgid ""
"This signal is emitted [i]after[/i] the related [constant "
"NOTIFICATION_ENTER_TREE] notification."
msgstr ""
+"当该节点进入树时触å‘。\n"
+"这个信å·ä¼šåœ¨ç›¸å…³çš„ [constant NOTIFICATION_ENTER_TREE] 通知[i]之åŽ[/i]触å‘。"
#: doc/classes/Node.xml
msgid "Emitted after the node exits the tree and is no longer active."
-msgstr "在节点退出树之åŽè§¦å‘,并且ä¸å†å¤„于活动状æ€ã€‚"
+msgstr "当该节点退出树之åŽè§¦å‘,并且ä¸å†å¤„于活动状æ€ã€‚"
#: doc/classes/Node.xml
-#, fuzzy
msgid ""
"Emitted when the node is still active but about to exit the tree. This is "
"the right place for de-initialization (or a \"destructor\", if you will).\n"
"This signal is emitted [i]before[/i] the related [constant "
"NOTIFICATION_EXIT_TREE] notification."
msgstr ""
-"当节点ä»å¤„于活动状æ€ä½†å³å°†é€€å‡ºæ ‘æ—¶å‘出。这是ååˆå§‹åŒ–的正确ä½ç½®ï¼ˆå¦‚果愿æ„,也"
-"å¯ä»¥ç§°ä¹‹ä¸ºâ€œæžæž„函数â€ï¼‰ã€‚"
+"当该节点ä»å¤„于活动状æ€ä½†å³å°†é€€å‡ºæ ‘æ—¶å‘出。这是ååˆå§‹åŒ–的正确ä½ç½®ï¼ˆå¦‚果愿æ„,"
+"也å¯ä»¥ç§°ä¹‹ä¸ºâ€œæžæž„函数â€ï¼‰ã€‚\n"
+"这个信å·ä¼šåœ¨ç›¸å…³çš„ [constant NOTIFICATION_EXIT_TREE] 通知[i]之å‰[/i]触å‘。"
#: doc/classes/Node.xml
msgid ""
"Notification received when the node enters a [SceneTree].\n"
"This notification is emitted [i]before[/i] the related [signal tree_entered]."
msgstr ""
+"当该节点进入 [SceneTree] 时收到的通知。\n"
+"这个通知会在相关的 [signal tree_entered] [i]之å‰[/i]å‘出。"
#: doc/classes/Node.xml
-#, fuzzy
msgid ""
"Notification received when the node is about to exit a [SceneTree].\n"
"This notification is emitted [i]after[/i] the related [signal tree_exiting]."
-msgstr "当该节点å³å°†é€€å‡º [SceneTree] 时收到的通知。"
+msgstr ""
+"当该节点å³å°†é€€å‡º [SceneTree] 时收到的通知。\n"
+"这个通知会在相关的 [signal tree_exiting] [i]之åŽ[/i]å‘出。"
#: doc/classes/Node.xml
msgid "Notification received when the node is moved in the parent."
@@ -50114,8 +50332,18 @@ msgid "See [enum ShadowDetail]."
msgstr "è§ [enum ShadowDetail]。"
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
-msgstr "è§ [enum ShadowMode]。"
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
+msgstr ""
+"为这个 [OmniLight] 使用的阴影渲染模å¼ã€‚è§ [enum ShadowMode]。\n"
+"[b]注æ„:[/b]在 GLES2 ä¸­ï¼Œåªæœ‰æ”¯æŒæ·±åº¦ç«‹æ–¹ä½“贴图功能的 GPU æ‰æ”¯æŒ [constant "
+"SHADOW_CUBE]。Radeon HD 4000 系列等较è€çš„ GPU "
+"䏿”¯æŒç«‹æ–¹ä½“è´´å›¾é˜´å½±ï¼Œå› æ­¤ä¼šå›žé€€åˆ°ä½¿ç”¨åŒæŠ›ç‰©é¢é˜´å½±ã€‚"
#: doc/classes/OmniLight.xml
msgid ""
@@ -50127,10 +50355,11 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
-"阴影被渲染æˆä¸€ä¸ªç«‹æ–¹ä½“贴图。比 [constant SHADOW_DUAL_PARABOLOID] æ…¢ï¼Œä½†è´¨é‡æ›´"
-"高。"
+"阴影被渲染至一个立方体贴图。比 [constant SHADOW_DUAL_PARABOLOID] "
+"æ…¢ï¼Œä½†è´¨é‡æ›´é«˜ã€‚ä»…åœ¨æ”¯æŒæ·±åº¦ç«‹æ–¹ä½“贴图功能的 GPU 上支æŒã€‚"
#: doc/classes/OmniLight.xml
msgid "Use more detail vertically when computing the shadow."
@@ -50202,7 +50431,7 @@ msgid ""
"code] with fixed y-coordinate value 0.0."
msgstr ""
"返回给定 x åæ ‡å¤„çš„ 1D 噪声值 [code][-1,1][/code]。\n"
-"[b]注æ„:[/b]这个方法实际上返回的是固定 Y åæ ‡å€¼ä¸º 0.0 的二维噪声值 [code]"
+"[b]注æ„:[/b]这个方法实际上返回的是固定 Y åæ ‡å€¼ä¸º 0.0 çš„ 2D 噪声值 [code]"
"[-1,1][/code]。"
#: modules/opensimplex/doc_classes/OpenSimplexNoise.xml
@@ -50768,7 +50997,6 @@ msgstr ""
"径。"
#: doc/classes/OS.xml
-#, fuzzy
msgid ""
"Returns the command-line arguments passed to the engine.\n"
"Command-line arguments can be written in any form, including both [code]--"
@@ -50808,6 +51036,10 @@ msgstr ""
" if argument.find(\"=\") > -1:\n"
" var key_value = argument.split(\"=\")\n"
" arguments[key_value[0].lstrip(\"--\")] = key_value[1]\n"
+" else:\n"
+" # å°†ä¸å¸¦å‚数的选项加入该字典,\n"
+" # å–值为空字符串。\n"
+" arguments[argument.lstrip(\"--\")] = \"\"\n"
"[/codeblock]"
#: doc/classes/OS.xml
@@ -51787,8 +52019,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 +52040,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 +52059,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 +52108,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 +52129,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 +52137,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 +52145,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 +52170,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 +52193,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 +52224,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 +52244,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 +52563,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 +52775,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 +52794,7 @@ msgid ""
msgstr ""
"如果传递给 [method instance]ï¼Œå‘æœ¬åœ°åœºæ™¯æä¾›æœ¬åœ°åœºæ™¯èµ„æºã€‚åªæœ‰ä¸»åœºæ™¯åº”该接收"
"主编辑状æ€ã€‚\n"
-"[b]注æ„:[/b]åªåœ¨ç¼–辑器构建中å¯ç”¨ã€‚"
+"[b]注æ„:[/b]仅在编辑器构建中å¯ç”¨ã€‚"
#: doc/classes/PackedScene.xml
msgid ""
@@ -52653,10 +52886,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 +52972,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 +53001,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 +53138,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 +53280,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 +53289,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 +53298,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 +53325,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
@@ -53997,11 +54230,11 @@ msgid ""
"[b]Note:[/b] Many of these monitors are not updated in real-time, so there "
"may be a short delay between changes."
msgstr ""
-"这个类æä¾›äº†å¯¹ä¸€äº›ä¸Žæ€§èƒ½æœ‰å…³çš„ä¸åŒç›‘控的访问,比如内存使用é‡ã€ç»˜åˆ¶è°ƒç”¨å’ŒFPS。"
-"这些与编辑器的[b]Monitor[/b]标签中的[b]Debugger[/b]颿¿æ‰€æ˜¾ç¤ºçš„æ•°å€¼ç›¸åŒã€‚通过"
-"使用这个类的[method get_monitor]方法,å¯ä»¥ä»Žä½ çš„代ç ä¸­è®¿é—®è¿™äº›æ•°æ®ã€‚\n"
+"这个类æä¾›äº†å¯¹ä¸€äº›ä¸Žæ€§èƒ½æœ‰å…³çš„ä¸åŒç›‘控的访问,比如内存使用é‡ã€ç»˜åˆ¶è°ƒç”¨å’Œ "
+"FPS。这些与编辑器[b]调试器[/b]颿¿çš„[b]监视[/b]标签中的所显示的数值相åŒã€‚通过"
+"使用这个类的 [method get_monitor] 方法,å¯ä»¥ä»Žä½ çš„代ç ä¸­è®¿é—®è¿™äº›æ•°æ®ã€‚\n"
"[b]注æ„:[/b]这些监视器中有几个åªåœ¨è°ƒè¯•模å¼ä¸‹å¯ç”¨ï¼Œå½“在å‘布版构建中使用时,将"
-"总是返回0。\n"
+"总是返回 0。\n"
"[b]注æ„:[/b]è¿™äº›ç›‘æŽ§å™¨ä¸­çš„è®¸å¤šä¸æ˜¯å®žæ—¶æ›´æ–°çš„,所以在å˜åŒ–之间å¯èƒ½ä¼šæœ‰çŸ­æš‚的延"
"迟。"
@@ -54079,7 +54312,7 @@ msgstr "孤儿节点的数é‡ï¼Œå­¤å„¿èŠ‚ç‚¹å³æ— æ³•被按父级追溯到根节
#: doc/classes/Performance.xml
msgid "3D objects drawn per frame."
-msgstr "æ¯å¸§ç»˜åˆ¶3D对象的数é‡ã€‚"
+msgstr "æ¯å¸§ç»˜åˆ¶ 3D 对象的数é‡ã€‚"
#: doc/classes/Performance.xml
msgid "Vertices drawn per frame. 3D only."
@@ -54235,30 +54468,30 @@ msgstr "对物体施加旋转冲é‡ã€‚"
#: doc/classes/Physics2DDirectBodyState.xml
#: doc/classes/PhysicsDirectBodyState.xml
msgid "Returns the collider's [RID]."
-msgstr "返回碰撞体的[RID]。"
+msgstr "返回该碰撞体的 [RID]。"
#: doc/classes/Physics2DDirectBodyState.xml
#: doc/classes/PhysicsDirectBodyState.xml
msgid "Returns the collider's object id."
-msgstr "返回碰撞体的对象 id。"
+msgstr "返回该碰撞体的对象 id。"
#: doc/classes/Physics2DDirectBodyState.xml
msgid ""
"Returns the collider object. This depends on how it was created (will return "
"a scene node if such was used to create it)."
msgstr ""
-"返回碰撞体对象。这å–决于它是如何创建的(如果是被作为场景节点创建的,那么将返"
-"回场景节点)。"
+"返回该碰撞体对象。这å–决于它是如何创建的(如果是被作为场景节点创建的,那么将"
+"返回场景节点)。"
#: doc/classes/Physics2DDirectBodyState.xml
#: doc/classes/PhysicsDirectBodyState.xml
msgid "Returns the contact position in the collider."
-msgstr "返回碰撞体中的接触ä½ç½®ã€‚"
+msgstr "返回该碰撞体中的接触ä½ç½®ã€‚"
#: doc/classes/Physics2DDirectBodyState.xml
#: doc/classes/PhysicsDirectBodyState.xml
msgid "Returns the collider's shape index."
-msgstr "返回碰撞体的形状索引。"
+msgstr "返回该碰撞体的形状索引。"
#: doc/classes/Physics2DDirectBodyState.xml
msgid ""
@@ -54266,13 +54499,13 @@ msgid ""
"[method Object.get_meta], and is set with [method Physics2DServer."
"shape_set_data]."
msgstr ""
-"返回碰撞形状的元数æ®ã€‚这个元数æ®ä¸åŒäºŽ [method Object.get_meta],是用 "
+"返回该碰撞形状的元数æ®ã€‚这个元数æ®ä¸åŒäºŽ [method Object.get_meta],是用 "
"[method Physics2DServer.shape_set_data] 设置的。"
#: doc/classes/Physics2DDirectBodyState.xml
#: doc/classes/PhysicsDirectBodyState.xml
msgid "Returns the linear velocity vector at the collider's contact point."
-msgstr "返回碰撞体接触点处的线速度å‘é‡ã€‚"
+msgstr "返回该碰撞体接触点处的线速度å‘é‡ã€‚"
#: doc/classes/Physics2DDirectBodyState.xml
msgid ""
@@ -54280,8 +54513,8 @@ msgid ""
"[b]Note:[/b] By default, this returns 0 unless bodies are configured to "
"monitor contacts. See [member RigidBody2D.contact_monitor]."
msgstr ""
-"返回此物体与其他物体的接触次数。\n"
-"[b]注æ„:[/b]默认情况下,除éžç‰©ä½“被设为监视接触者,å¦åˆ™è¿”回0。å‚阅 [member "
+"返回这个物体与其他物体的接触次数。\n"
+"[b]注æ„:[/b]默认情况下,除éžç‰©ä½“被设为监视接触者,å¦åˆ™è¿”回 0ã€‚è§ [member "
"RigidBody2D.contact_monitor]。"
#: doc/classes/Physics2DDirectBodyState.xml
@@ -54581,7 +54814,7 @@ msgstr ""
"通过 [Physics2DShapeQueryParameters] 对象检查给出的形状与空间的交点。返回的相"
"交形状是一个字典数组,包å«ä»¥ä¸‹å­—段:\n"
"[code]collider[/code]:碰撞的对象。\n"
-"[code]collider_id[/code]:碰撞对象的ID。\n"
+"[code]collider_id[/code]:碰撞对象的 ID。\n"
"[code]metadata[/code]:相交形状的元数æ®ã€‚这个元数æ®ä¸Ž [method Object."
"get_meta] ä¸åŒï¼Œæ˜¯ç”¨ [method Physics2DServer.shape_set_data] 设置的。\n"
"[code]rid[/code]:相交对象的 [RID]。\n"
@@ -54690,13 +54923,13 @@ msgid ""
"5: The shape index of the area where the object entered/exited."
msgstr ""
"设置当任何主体/区域进入或退出该区域时调用的函数。这个回调函数将被任何与区域交"
-"互的对象调用,并接å—5ä¸ªå‚æ•°:\n"
-"1: [constant AREA_BODY_ADDED]或[constant AREA_BODY_REMOVED],å–决于对象是å¦è¿›"
-"入或退出该区域。\n"
-"2:进入/退出该区域对象的[RID]。\n"
-"3:进入/退出该区域对象的实例ID。\n"
-"4:进入/离开该区域的物体的形状指数。\n"
-"5:物体进入/离开区域的形状指数。"
+"äº’çš„å¯¹è±¡è°ƒç”¨ï¼Œå¹¶æŽ¥å— 5 ä¸ªå‚æ•°ï¼š\n"
+"1:[constant AREA_BODY_ADDED] 或 [constant AREA_BODY_REMOVED],å–决于对象是å¦"
+"进入或退出该区域。\n"
+"2:进入/退出该区域对象的 [RID]。\n"
+"3:进入/退出该区域对象的实例 ID。\n"
+"4:进入/离开该区域的物体的形状指数。\n"
+"5:物体进入/离开区域的形状指数。"
#: doc/classes/Physics2DServer.xml
msgid ""
@@ -54812,7 +55045,7 @@ msgstr "è¿”å›žç‰©ä½“å‚æ•°çš„值。请å‚阅 [enum BodyParameter] 获å–å¯ç”¨å
#: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml
msgid "Returns the [RID] of the nth shape of a body."
-msgstr "返回 body 的第 n 个碰撞形状的 [RID]。"
+msgstr "返回物体的第 n 个碰撞形状的 [RID]。"
#: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml
msgid "Returns the number of shapes assigned to a body."
@@ -54839,7 +55072,7 @@ msgid ""
"Returns whether a body uses a callback function to calculate its own physics "
"(see [method body_set_force_integration_callback])."
msgstr ""
-"返回一个 body 是å¦ä½¿ç”¨å›žè°ƒå‡½æ•°æ¥è®¡ç®—它自己的物ç†å€¼ï¼ˆè§ [method "
+"返回一个物体是å¦ä½¿ç”¨å›žè°ƒå‡½æ•°æ¥è®¡ç®—它自己的物ç†å€¼ï¼ˆè§ [method "
"body_set_force_integration_callback])。"
#: doc/classes/Physics2DServer.xml
@@ -55024,7 +55257,7 @@ msgstr "è¿”å›žä¸€ä¸ªå…³èŠ‚çš„ç±»åž‹ï¼ˆè§ [enum JointType])。"
msgid ""
"Sets a joint parameter. See [enum JointParam] for a list of available "
"parameters."
-msgstr "è®¾ç½®å…³èŠ‚å‚æ•°ã€‚有关å¯ç”¨å‚数的列表,请å‚阅[enum JointParam]。"
+msgstr "è®¾ç½®å…³èŠ‚å‚æ•°ã€‚有关å¯ç”¨å‚数的列表,请å‚阅 [enum JointParam]。"
#: doc/classes/Physics2DServer.xml
msgid ""
@@ -55153,8 +55386,8 @@ msgid ""
"violating a constraint, to avoid leaving them in that state because of "
"numerical imprecision."
msgstr ""
-"常é‡ï¼Œç”¨äºŽè®¾ç½®/èŽ·å–æ‰€æœ‰ç‰©ç†çº¦æŸçš„默认求解器å置。解算器å差是一个控制两个物体"
-"在è¿å约æŸåŽ \"åå¼¹ \"程度的因素,以é¿å…由于数值ä¸ç²¾ç¡®è€Œä½¿å®ƒä»¬å¤„于这ç§çжæ€ã€‚"
+"常é‡ï¼Œç”¨äºŽè®¾ç½®/èŽ·å–æ‰€æœ‰ç‰©ç†çº¦æŸçš„默认求解器å置。解算器å置是一个控制两个物体"
+"在è¿å约æŸåŽâ€œåå¼¹â€ç¨‹åº¦çš„因素,以é¿å…由于数值ä¸ç²¾ç¡®è€Œä½¿å®ƒä»¬å¤„于这ç§çжæ€ã€‚"
#: doc/classes/Physics2DServer.xml
msgid ""
@@ -55206,8 +55439,8 @@ msgid ""
"supplied form is a convex polygon."
msgstr ""
"这是用于创建凸多边形的常é‡ã€‚一个多边形是由一个点的列表定义的。它å¯ä»¥ç”¨äºŽäº¤ç‚¹"
-"和内/外侧检查。与[member CollisionPolygon2D.polygon]属性ä¸åŒï¼Œç”¨[method "
-"shape_set_data]修改的多边形并ä¸éªŒè¯æ‰€æä¾›çš„ç‚¹çš„å½¢å¼æ˜¯ä¸€ä¸ªå‡¸å½¢å¤šè¾¹å½¢ã€‚"
+"和内/外侧检查。与 [member CollisionPolygon2D.polygon] 属性ä¸åŒï¼Œç”¨ [method "
+"shape_set_data] 修改的多边形并ä¸éªŒè¯æ‰€æä¾›çš„ç‚¹çš„å½¢å¼æ˜¯ä¸€ä¸ªå‡¸å½¢å¤šè¾¹å½¢ã€‚"
#: doc/classes/Physics2DServer.xml
msgid ""
@@ -55309,15 +55542,15 @@ msgstr ""
#: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml
msgid "Constant for static bodies."
-msgstr "StaticBody 的常é‡ã€‚"
+msgstr "陿€ç‰©ä½“的常é‡ã€‚"
#: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml
msgid "Constant for kinematic bodies."
-msgstr "KinematicBody 的常é‡ã€‚"
+msgstr "è¿åŠ¨å­¦ç‰©ä½“çš„å¸¸é‡ã€‚"
#: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml
msgid "Constant for rigid bodies."
-msgstr "RigidBody 的常é‡ã€‚"
+msgstr "刚体的常é‡ã€‚"
#: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml
msgid ""
@@ -55409,8 +55642,8 @@ msgid ""
"undamped spring, while 1 causes the system to reach equilibrium as fast as "
"possible (critical damping)."
msgstr ""
-"设置弹簧接头的阻尼比率。值为0表示无阻尼弹簧,而1导致系统尽å¯èƒ½å¿«åœ°è¾¾åˆ°å¹³è¡¡"
-"(临界阻尼)。"
+"设置弹簧接头的阻尼比率。值为 0 表示无阻尼弹簧,而 1 导致系统尽å¯èƒ½å¿«åœ°è¾¾åˆ°å¹³"
+"衡(临界阻尼)。"
#: doc/classes/Physics2DServer.xml
msgid ""
@@ -55424,13 +55657,13 @@ msgstr ""
msgid ""
"Enables continuous collision detection by raycasting. It is faster than "
"shapecasting, but less precise."
-msgstr "通过射线投射实现连续的碰撞检测。它比 shapecasting 更快,但ä¸å¤Ÿç²¾ç¡®ã€‚"
+msgstr "通过射线投射实现连续的碰撞检测。它比形状投射更快,但ä¸å¤Ÿç²¾ç¡®ã€‚"
#: doc/classes/Physics2DServer.xml
msgid ""
"Enables continuous collision detection by shapecasting. It is the slowest "
"CCD method, and the most precise."
-msgstr "通过形å˜å®žçŽ°è¿žç»­çš„ç¢°æ’žæ£€æµ‹ã€‚å®ƒæ˜¯æœ€æ…¢çš„CCD方法,也是最精确的。"
+msgstr "通过形å˜å®žçŽ°è¿žç»­çš„ç¢°æ’žæ£€æµ‹ã€‚å®ƒæ˜¯æœ€æ…¢çš„ CCD 方法,也是最精确的。"
#: doc/classes/Physics2DServer.xml doc/classes/PhysicsServer.xml
msgid ""
@@ -55630,7 +55863,7 @@ msgid ""
"monitor contacts. See [member RigidBody.contact_monitor]."
msgstr ""
"返回此物体与其他物体的接触次数。\n"
-"[b]注æ„:[/b]默认情况下,除éžç‰©ä½“被设为监视接触者,å¦åˆ™è¿”回0。å‚阅 [member "
+"[b]注æ„:[/b]默认情况下,除éžç‰©ä½“被设为监视接触者,å¦åˆ™è¿”回 0ã€‚è§ [member "
"RigidBody2D.contact_monitor]。"
#: doc/classes/PhysicsDirectBodyState.xml
@@ -55710,15 +55943,15 @@ msgid ""
"If the shape did not intersect anything, then an empty dictionary is "
"returned instead."
msgstr ""
-"检查通过[PhysicsShapeQueryParameters]对象给出的形状与空间的交点。如果它与一个"
-"以上的形状å‘生碰撞,则选择最近的。返回的对象是包å«ä»¥ä¸‹å­—段的字典:\n"
-"[code]collider_id[/code]:碰撞对象的ID。\n"
-"[code]linear_velocity[/code]:碰撞对象的速度[Vector3]。如果对象是一个[Area],"
-"结果是[code](0, 0, 0)[/code]。\n"
-"[code]normal[/code]:ç‰©ä½“åœ¨äº¤ç‚¹å¤„çš„è¡¨é¢æ³•线。\n"
-"[code]点[/code]:相交点。\n"
-"[code]rid[/code]:相交物体的[RID]。\n"
-"[code]shape[/code]:碰撞形状的形状索引。\n"
+"检查通过 [PhysicsShapeQueryParameters] 对象给出的形状与空间的交点。如果它与一"
+"个以上的形状å‘生碰撞,则选择最近的。返回的对象是包å«ä»¥ä¸‹å­—段的字典:\n"
+"[code]collider_id[/code]:碰撞对象的 ID。\n"
+"[code]linear_velocity[/code]:碰撞对象的速度 [Vector3]。如果对象是一个 "
+"[Area],结果是 [code](0, 0, 0)[/code]。\n"
+"[code]normal[/code]ï¼šç‰©ä½“åœ¨äº¤ç‚¹å¤„çš„è¡¨é¢æ³•线。\n"
+"[code]point[/code]:相交点。\n"
+"[code]rid[/code]:相交物体的 [RID]。\n"
+"[code]shape[/code]:碰撞形状的形状索引。\n"
"如果该形状没有与任何物体相交,那么将返回空的字典。"
#: doc/classes/PhysicsDirectSpaceState.xml
@@ -55767,17 +56000,17 @@ msgid ""
"determine if the ray should collide with [PhysicsBody]s or [Area]s, "
"respectively."
msgstr ""
-"在给定的空间中与一æ¡å°„线相交。返回的对象是具有下列字段的字典:\n"
-"[code]collider[/code]:碰撞的对象。\n"
-"[code]collider_id[/code]:碰撞对象的ID。\n"
-"[code]normal[/code]:ç‰©ä½“åœ¨ç›¸äº¤ç‚¹çš„è¡¨é¢æ³•线。\n"
-"[code]position[/code]:交å‰ç‚¹ã€‚\n"
-"[code]rid[/code]:相交物体的[RID]。\n"
-"[code]形状[/code]:碰撞形状的形状索引。\n"
+"在给定的空间中与一æ¡å°„线相交。返回的对象是具有下列字段的字典:\n"
+"[code]collider[/code]:碰撞的对象。\n"
+"[code]collider_id[/code]:碰撞对象的 ID。\n"
+"[code]normal[/code]ï¼šç‰©ä½“åœ¨ç›¸äº¤ç‚¹çš„è¡¨é¢æ³•线。\n"
+"[code]position[/code]:交å‰ç‚¹ã€‚\n"
+"[code]rid[/code]:相交物体的 [RID]。\n"
+"[code]shape[/code]:碰撞形状的形状索引。\n"
"如果射线没有与任何物体相交,那么将返回空的字典。\n"
-"此外,该方法å¯ä»¥æŽ¥å—一个[code]exclude[/code]对象或[RID]数组,该数组将被排除在"
-"碰撞之外,[code]collision_mask[/code]使ީç è¡¨ç¤ºè¦æ£€æŸ¥çš„物ç†å±‚,或者布尔值æ¥ç¡®"
-"定射线是å¦åº”该分别与[PhysicsBody]或[Area]å‘生碰撞。"
+"此外,该方法å¯ä»¥æŽ¥å—一个 [code]exclude[/code] 对象或 [RID] 数组,该数组将被排"
+"除在碰撞之外,[code]collision_mask[/code] 使ީç è¡¨ç¤ºè¦æ£€æŸ¥çš„物ç†å±‚,或者布尔"
+"值æ¥ç¡®å®šå°„线是å¦åº”该分别与 [PhysicsBody] 或 [Area] å‘生碰撞。"
#: doc/classes/PhysicsDirectSpaceState.xml
msgid ""
@@ -55792,13 +56025,13 @@ msgid ""
"The number of intersections can be limited with the [code]max_results[/code] "
"parameter, to reduce the processing time."
msgstr ""
-"通过[PhysicsShapeQueryParameters]对象给出的形状与空间检查交点。相交的形状会以"
-"数组的形å¼è¿”å›žï¼Œè¯¥æ•°ç»„åŒ…å«æœ‰ä»¥ä¸‹å­—段的字典:\n"
-"[code]collider[/code]:碰撞的对象。\n"
-"[code]collider_id[/code]:碰撞对象的ID。\n"
-"[code]rid[/code]:相交物体的[RID]。\n"
-"[code]shape[/code]:碰撞形状的形状索引。\n"
-"å¯ä»¥ç”¨[code]max_results[/code]傿•°é™åˆ¶ç›¸äº¤çš„æ•°é‡ï¼Œä»¥å‡å°‘å¤„ç†æ—¶é—´ã€‚"
+"通过 [PhysicsShapeQueryParameters] 对象给出的形状与空间检查交点。相交的形状会"
+"以数组的形å¼è¿”å›žï¼Œè¯¥æ•°ç»„åŒ…å«æœ‰ä»¥ä¸‹å­—段的字典:\n"
+"[code]collider[/code]:碰撞的对象。\n"
+"[code]collider_id[/code]:碰撞对象的 ID。\n"
+"[code]rid[/code]:相交物体的 [RID]。\n"
+"[code]shape[/code]:碰撞形状的形状索引。\n"
+"å¯ä»¥ç”¨ [code]max_results[/code] 傿•°é™åˆ¶ç›¸äº¤çš„æ•°é‡ï¼Œä»¥å‡å°‘å¤„ç†æ—¶é—´ã€‚"
#: doc/classes/PhysicsMaterial.xml
msgid "A material for physics properties."
@@ -55807,7 +56040,7 @@ msgstr "具有物ç†å±žæ€§çš„æè´¨ã€‚"
#: doc/classes/PhysicsMaterial.xml
msgid ""
"Provides a means of modifying the collision properties of a [PhysicsBody]."
-msgstr "æä¾›äº†ä¸€ç§ä¿®æ”¹[PhysicsBody]的碰撞属性的方法。"
+msgstr "æä¾›äº†ä¸€ç§ä¿®æ”¹ [PhysicsBody] 的碰撞属性的方法。"
#: doc/classes/PhysicsMaterial.xml
msgid ""
@@ -55821,14 +56054,16 @@ msgid ""
"The body's bounciness. Values range from [code]0[/code] (no bounce) to "
"[code]1[/code] (full bounciness)."
msgstr ""
-"实体的弹性。值的范围从[code]0[/code](无å弹)到[code]1[/code](完全å弹)。"
+"实体的弹性。值的范围从 [code]0[/code](无å弹)到 [code]1[/code](完全å"
+"弹)。"
#: doc/classes/PhysicsMaterial.xml
msgid ""
"The body's friction. Values range from [code]0[/code] (frictionless) to "
"[code]1[/code] (maximum friction)."
msgstr ""
-"物体的摩擦。å–值范围从[code]0[/code](无摩擦)到[code]1[/code](最大摩擦)。"
+"物体的摩擦。å–值范围从 [code]0[/code](无摩擦)到 [code]1[/code](最大摩"
+"擦)。"
#: doc/classes/PhysicsMaterial.xml
msgid ""
@@ -55856,7 +56091,7 @@ msgstr ""
#: doc/classes/PhysicsServer.xml
msgid "Creates an [Area]."
-msgstr "创建一个[Area]区域。"
+msgstr "创建一个 [Area] 区域。"
#: doc/classes/PhysicsServer.xml
msgid ""
@@ -55901,7 +56136,7 @@ msgid ""
"BodyMode] constants, for the type of body created. Additionally, the body "
"can be created in sleeping state to save processing time."
msgstr ""
-"创建物ç†ä½“ã€‚å¯¹äºŽåˆ›å»ºçš„ç‰©ä½“ç±»åž‹ï¼Œç¬¬ä¸€ä¸ªå‚æ•°å¯ä»¥æ˜¯[enum BodyMode]常é‡ä¸­çš„任何"
+"创建物ç†ä½“ã€‚å¯¹äºŽåˆ›å»ºçš„ç‰©ä½“ç±»åž‹ï¼Œç¬¬ä¸€ä¸ªå‚æ•°å¯ä»¥æ˜¯ [enum BodyMode] 常é‡ä¸­çš„任何"
"值。此外,物体å¯ä»¥åœ¨ä¼‘眠状æ€ä¸‹åˆ›å»ºï¼Œä»¥èŠ‚çœå¤„ç†æ—¶é—´ã€‚"
#: doc/classes/PhysicsServer.xml
@@ -55916,7 +56151,7 @@ msgstr ""
msgid ""
"Returns the value of a body parameter. A list of available parameters is on "
"the [enum BodyParameter] constants."
-msgstr "è¿”å›žç‰©ä½“å‚æ•°çš„值。å¯ç”¨å‚数列表ä½äºŽ[enum BodyParameter]常é‡ä¸Šã€‚"
+msgstr "è¿”å›žç‰©ä½“å‚æ•°çš„值。å¯ç”¨å‚数列表ä½äºŽ [enum BodyParameter] 常é‡ä¸Šã€‚"
#: doc/classes/PhysicsServer.xml
msgid ""
@@ -55947,7 +56182,7 @@ msgstr ""
#: doc/classes/PhysicsServer.xml
msgid "Sets the body mode, from one of the [enum BodyMode] constants."
-msgstr "从[enum BodyMode]常é‡ä¹‹ä¸€è®¾ç½®ä¸»ä½“模å¼ã€‚"
+msgstr "从 [enum BodyMode] 常é‡ä¹‹ä¸€è®¾ç½®ä¸»ä½“模å¼ã€‚"
#: doc/classes/PhysicsServer.xml
msgid ""
@@ -55957,7 +56192,7 @@ msgstr "è®¾ç½®ç‰©ä½“å‚æ•°ã€‚å¯ç”¨å‚数列表ä½äºŽ [enum BodyParameter] 常é‡
#: doc/classes/PhysicsServer.xml
msgid "Sets the body pickable with rays if [code]enabled[/code] is set."
-msgstr "如果设置了[code]enabled[/code],则设置å¯ä½¿ç”¨å…‰çº¿æ‹¾å–的物体。"
+msgstr "如果设置了 [code]enabled[/code],则设置å¯ä½¿ç”¨å…‰çº¿æ‹¾å–的物体。"
#: doc/classes/PhysicsServer.xml
msgid "Sets a body state (see [enum BodyState] constants)."
@@ -56073,12 +56308,12 @@ msgstr "设置关节的优先级值。"
#: doc/classes/PhysicsServer.xml
msgid ""
"Returns position of the joint in the local space of body a of the joint."
-msgstr "返回关节在关节物体A的局部空间中的ä½ç½®ã€‚"
+msgstr "返回关节在关节物体 A 的局部空间中的ä½ç½®ã€‚"
#: doc/classes/PhysicsServer.xml
msgid ""
"Returns position of the joint in the local space of body b of the joint."
-msgstr "返回关节在关节物体B的局部空间中的ä½ç½®ã€‚"
+msgstr "返回关节在关节物体 B 的局部空间中的ä½ç½®ã€‚"
#: doc/classes/PhysicsServer.xml
msgid "Gets a pin_joint parameter (see [enum PinJointParam] constants)."
@@ -56086,11 +56321,11 @@ msgstr "èŽ·å– pin_joint 傿•°ï¼ˆè§ [enum PinJointParam] 常é‡ï¼‰ã€‚"
#: doc/classes/PhysicsServer.xml
msgid "Sets position of the joint in the local space of body a of the joint."
-msgstr "设置关节在关节物体A的局部空间中的ä½ç½®ã€‚"
+msgstr "设置关节在关节物体 A 的局部空间中的ä½ç½®ã€‚"
#: doc/classes/PhysicsServer.xml
msgid "Sets position of the joint in the local space of body b of the joint."
-msgstr "设置关节在关节物体B的局部空间中的ä½ç½®ã€‚"
+msgstr "设置关节在关节物体 B 的局部空间中的ä½ç½®ã€‚"
#: doc/classes/PhysicsServer.xml
msgid "Sets a pin_joint parameter (see [enum PinJointParam] constants)."
@@ -56098,7 +56333,7 @@ msgstr "设置 pin_joint 傿•°ï¼ˆè§ [enum PinJointParam] 常é‡ï¼‰ã€‚"
#: doc/classes/PhysicsServer.xml
msgid "Activates or deactivates the 3D physics engine."
-msgstr "激活或åœç”¨3D物ç†å¼•擎。"
+msgstr "激活或åœç”¨ 3D 物ç†å¼•擎。"
#: doc/classes/PhysicsServer.xml
msgid ""
@@ -56120,8 +56355,8 @@ msgid ""
"body or an area. To do so, you must use [method area_set_shape] or [method "
"body_set_shape]."
msgstr ""
-"创建一个[enum ShapeType]ç±»åž‹çš„å½¢çŠ¶ã€‚ä¸æŠŠå®ƒåˆ†é…给一个体或一个区域。è¦åšåˆ°è¿™ä¸€"
-"点,你必须使用[method area_set_shape]或[method body_set_shape]。"
+"创建一个 [enum ShapeType] ç±»åž‹çš„å½¢çŠ¶ã€‚ä¸æŠŠå®ƒåˆ†é…给一个体或一个区域。è¦åšåˆ°è¿™"
+"一点,你必须使用 [method area_set_shape] 或 [method body_set_shape]。"
#: doc/classes/PhysicsServer.xml
msgid "Returns the type of shape (see [enum ShapeType] constants)."
@@ -56142,7 +56377,7 @@ msgstr ""
msgid ""
"Sets the value for a space parameter. A list of available parameters is on "
"the [enum SpaceParameter] constants."
-msgstr "è®¾ç½®ç©ºé—´å‚æ•°çš„值。å¯ç”¨å‚数列表ä½äºŽ[enum SpaceParameter]常é‡ä¸Šã€‚"
+msgstr "è®¾ç½®ç©ºé—´å‚æ•°çš„值。å¯ç”¨å‚数列表ä½äºŽ [enum SpaceParameter] 常é‡ä¸Šã€‚"
#: doc/classes/PhysicsServer.xml
msgid "The [Joint] is a [PinJoint]."
@@ -56186,7 +56421,7 @@ msgstr ""
msgid ""
"If above 0, this value is the maximum value for an impulse that this Joint "
"puts on its ends."
-msgstr "如果大于0,这个值就是这个关节对其两端施加的冲é‡çš„æœ€å¤§å€¼ã€‚"
+msgstr "如果大于 0,这个值就是这个关节对其两端施加的冲é‡çš„æœ€å¤§å€¼ã€‚"
#: doc/classes/PhysicsServer.xml
msgid "The maximum rotation across the Hinge."
@@ -56439,7 +56674,7 @@ msgid ""
"Pin joint for 3D rigid bodies. It pins 2 bodies (rigid or static) together. "
"See also [Generic6DOFJoint]."
msgstr ""
-"3Dåˆšä½“çš„é’‰å…³èŠ‚ã€‚å®ƒå°†ä¸¤ä¸ªç‰©ä½“ï¼ˆåˆšä½“æˆ–é™æ€ä½“)钉在一起。å‚阅"
+"3D åˆšä½“çš„é’‰å…³èŠ‚ã€‚å®ƒå°†ä¸¤ä¸ªç‰©ä½“ï¼ˆåˆšä½“æˆ–é™æ€ä½“)钉在一起。å¦è¯·å‚阅 "
"[Generic6DOFJoint]。"
#: doc/classes/PinJoint.xml
@@ -56458,7 +56693,7 @@ msgstr "è¢«é’‰åœ¨ä¸€èµ·çš„ç‰©ä½“ä¹‹é—´ä¿æŒå…±é€Ÿçš„力。越高,力越大。
msgid ""
"If above 0, this value is the maximum value for an impulse that this Joint "
"produces."
-msgstr "如果大于0,这个值就是此关节产生的冲é‡çš„æœ€å¤§å€¼ã€‚"
+msgstr "如果大于 0,这个值就是此关节产生的冲é‡çš„æœ€å¤§å€¼ã€‚"
#: doc/classes/PinJoint2D.xml
msgid "Pin Joint for 2D shapes."
@@ -56516,7 +56751,7 @@ msgstr "返回平é¢çš„中心。"
msgid ""
"Returns the shortest distance from the plane to the position [code]point[/"
"code]."
-msgstr "返回从平é¢åˆ°ä½ç½®[code]point[/code]的最短è·ç¦»ã€‚"
+msgstr "返回从平é¢åˆ°ä½ç½® [code]point[/code] 的最短è·ç¦»ã€‚"
#: doc/classes/Plane.xml
msgid ""
@@ -56573,7 +56808,7 @@ msgstr ""
#: doc/classes/Plane.xml
msgid ""
"Returns [code]true[/code] if [code]point[/code] is located above the plane."
-msgstr "如果[code]point[/code]ä½äºŽå¹³é¢ä¸Šæ–¹ï¼Œåˆ™è¿”回 [code]true[/code]。"
+msgstr "如果 [code]point[/code] ä½äºŽå¹³é¢ä¸Šæ–¹ï¼Œåˆ™è¿”回 [code]true[/code]。"
#: doc/classes/Plane.xml
msgid "Returns a copy of the plane, normalized."
@@ -56583,7 +56818,7 @@ msgstr "返回平é¢çš„一个标准化副本。"
msgid ""
"Returns the orthogonal projection of [code]point[/code] into a point in the "
"plane."
-msgstr "返回 [code]点[/code]在平é¢ä¸Šçš„æ­£äº¤æŠ•影。"
+msgstr "返回 [code]point[/code] 在平é¢ä¸Šçš„æ­£äº¤æŠ•影。"
#: doc/classes/Plane.xml
msgid ""
@@ -56593,9 +56828,9 @@ msgid ""
"[code]d[/code], while the [code](a, b, c)[/code] coordinates are represented "
"by the [member normal] property."
msgstr ""
-"从原点到平é¢çš„è·ç¦»ï¼Œæ²¿[member normal]æ–¹å‘。这个值通常是éžè´Ÿçš„。\n"
-"在平é¢[code]ax + by + cz = d[/code]çš„æ ‡é‡æ–¹ç¨‹ä¸­ï¼Œè¿™æ˜¯[code]d[/code],而[code]"
-"(a, b, c)[/code]åæ ‡ç”±[member normal]属性表示。"
+"从原点到平é¢çš„è·ç¦»ï¼Œæ²¿ [member normal] æ–¹å‘。这个值通常是éžè´Ÿçš„。\n"
+"åœ¨å¹³é¢ [code]ax + by + cz = d[/code] çš„æ ‡é‡æ–¹ç¨‹ä¸­ï¼Œè¿™æ˜¯ [code]d[/code],而 "
+"[code](a, b, c)[/code] åæ ‡ç”± [member normal] 属性表示。"
#: doc/classes/Plane.xml
msgid ""
@@ -56605,8 +56840,8 @@ msgid ""
"property."
msgstr ""
"å¹³é¢çš„æ³•线,必须归一化。\n"
-"在平é¢[code]ax + by + cz = d[/code]çš„æ ‡é‡æ–¹ç¨‹ä¸­ï¼Œè¿™æ˜¯å‘é‡[code](a, b, c)[/"
-"code],其中[code]d[/code]是[member d]属性。"
+"åœ¨å¹³é¢ [code]ax + by + cz = d[/code] çš„æ ‡é‡æ–¹ç¨‹ä¸­ï¼Œè¿™æ˜¯å‘é‡ [code](a, b, c)[/"
+"code],其中 [code]d[/code] 是 [member d] 属性。"
#: doc/classes/Plane.xml
msgid "The X component of the plane's [member normal] vector."
@@ -56815,12 +57050,12 @@ msgid ""
"If [code]true[/code], polygon will be inverted, containing the area outside "
"the defined points and extending to the [code]invert_border[/code]."
msgstr ""
-"如果为 [code]true[/code],则多边形将å转,包å«å®šä¹‰ç‚¹ä¹‹å¤–的区域,并扩展到"
-"[code]invert_border[/code](å转边界)."
+"如果为 [code]true[/code],则多边形将å转,包å«å®šä¹‰ç‚¹ä¹‹å¤–的区域,并扩展到 "
+"[code]invert_border[/code](å转边界)。"
#: doc/classes/Polygon2D.xml
msgid "The offset applied to each vertex."
-msgstr "应用于æ¯ä¸ªé¡¶ç‚¹çš„ä½ç½®åç§»é‡."
+msgstr "应用于æ¯ä¸ªé¡¶ç‚¹çš„ä½ç½®åç§»é‡ã€‚"
#: doc/classes/Polygon2D.xml
msgid ""
@@ -56930,11 +57165,12 @@ msgstr ""
msgid ""
"Constructs a new [PoolByteArray]. Optionally, you can pass in a generic "
"[Array] that will be converted."
-msgstr "构建新的[PoolByteArray]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„[Array],它将被转æ¢ã€‚"
+msgstr ""
+"构建新的 [PoolByteArray]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„ [Array],它将被转æ¢ã€‚"
#: doc/classes/PoolByteArray.xml
msgid "Appends a [PoolByteArray] at the end of this array."
-msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolByteArray]。"
+msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ  [PoolByteArray]。"
#: doc/classes/PoolByteArray.xml
msgid ""
@@ -57079,6 +57315,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr "改å˜ç»™å®šç´¢å¼•处的字节。"
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr "将该数组中的元素按å‡åºæŽ’列。"
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -57141,11 +57384,11 @@ msgid ""
"Constructs a new [PoolColorArray]. Optionally, you can pass in a generic "
"[Array] that will be converted."
msgstr ""
-"构建新的[PoolColorArray]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„[Array],它将被转æ¢ã€‚"
+"构建新的 [PoolColorArray]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„ [Array],它将被转æ¢ã€‚"
#: doc/classes/PoolColorArray.xml
msgid "Appends a [PoolColorArray] at the end of this array."
-msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ ä¸€ä¸ª[PoolColorArray]。"
+msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ ä¸€ä¸ª [PoolColorArray]。"
#: doc/classes/PoolColorArray.xml doc/classes/PoolIntArray.xml
msgid "Appends a value to the array."
@@ -57225,18 +57468,19 @@ msgstr ""
msgid ""
"Constructs a new [PoolIntArray]. Optionally, you can pass in a generic "
"[Array] that will be converted."
-msgstr "构建新的[PoolIntArray]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„[Array],它将被转æ¢ã€‚"
+msgstr ""
+"构建新的 [PoolIntArray]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„ [Array],它将被转æ¢ã€‚"
#: doc/classes/PoolIntArray.xml
msgid "Appends a [PoolIntArray] at the end of this array."
-msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolIntArray]。"
+msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ  [PoolIntArray]。"
#: doc/classes/PoolIntArray.xml
msgid ""
"Inserts a new int at a given position in the array. The position must be "
"valid, or at the end of the array ([code]idx == size()[/code])."
msgstr ""
-"在数组中的指定ä½ç½®æ’入一个新的int。这个ä½ç½®å¿…须是有效的,或者在数组的末端"
+"在数组中的指定ä½ç½®æ’入一个新的 int。这个ä½ç½®å¿…须是有效的,或者在数组的末端"
"([code]idx == size()[/code])。"
#: doc/classes/PoolIntArray.xml
@@ -57367,11 +57611,11 @@ msgid ""
"Constructs a new [PoolStringArray]. Optionally, you can pass in a generic "
"[Array] that will be converted."
msgstr ""
-"构建新的[PoolStringArray]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„[Array],它将被转æ¢ã€‚"
+"构建新的 [PoolStringArray]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„ [Array],它将被转æ¢ã€‚"
#: doc/classes/PoolStringArray.xml
msgid "Appends a [PoolStringArray] at the end of this array."
-msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolStringArray]。"
+msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ  [PoolStringArray]。"
#: doc/classes/PoolStringArray.xml
msgid ""
@@ -57446,15 +57690,15 @@ msgid ""
"Constructs a new [PoolVector2Array]. Optionally, you can pass in a generic "
"[Array] that will be converted."
msgstr ""
-"构建新的[PoolVector2Array]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„[Array],它将被转æ¢ã€‚"
+"构建新的 [PoolVector2Array]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„ [Array],它将被转æ¢ã€‚"
#: doc/classes/PoolVector2Array.xml
msgid "Appends a [PoolVector2Array] at the end of this array."
-msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolVector2Array]。"
+msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ  [PoolVector2Array]。"
#: doc/classes/PoolVector2Array.xml
msgid "Inserts a [Vector2] at the end."
-msgstr "在末尾æ’å…¥[Vector2]。"
+msgstr "在末尾æ’入一个 [Vector2]。"
#: doc/classes/PoolVector2Array.xml
msgid "Changes the [Vector2] at the given index."
@@ -57513,15 +57757,15 @@ msgid ""
"Constructs a new [PoolVector3Array]. Optionally, you can pass in a generic "
"[Array] that will be converted."
msgstr ""
-"构建新的[PoolVector3Array]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„[Array],它将被转æ¢ã€‚"
+"构建新的 [PoolVector3Array]。你å¯ä»¥é€‰æ‹©ä¼ å…¥ä¸€ä¸ªé€šç”¨çš„ [Array],它将被转æ¢ã€‚"
#: doc/classes/PoolVector3Array.xml
msgid "Appends a [PoolVector3Array] at the end of this array."
-msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ [PoolVector3Array]。"
+msgstr "åœ¨è¿™ä¸ªæ•°ç»„çš„æœ€åŽæ·»åŠ  [PoolVector3Array]。"
#: doc/classes/PoolVector3Array.xml
msgid "Inserts a [Vector3] at the end."
-msgstr "在末尾æ’å…¥[Vector3]。"
+msgstr "在末尾æ’入一个 [Vector3]。"
#: doc/classes/PoolVector3Array.xml
msgid "Changes the [Vector3] at the given index."
@@ -57635,11 +57879,11 @@ msgstr "PopupDialog æ˜¯å¼¹å‡ºå¯¹è¯æ¡†çš„基类,与 [WindowDialog] 一起。"
#: doc/classes/PopupDialog.xml
msgid "Sets a custom [StyleBox] for the panel of the [PopupDialog]."
-msgstr "为[PopupDialog]çš„é¢æ¿è®¾ç½®è‡ªå®šä¹‰çš„[StyleBox]。"
+msgstr "为 [PopupDialog] çš„é¢æ¿è®¾ç½®è‡ªå®šä¹‰çš„ [StyleBox]。"
#: doc/classes/PopupMenu.xml
msgid "PopupMenu displays a list of options."
-msgstr "PopupMenu(弹出èœå•)显示选项列表."
+msgstr "PopupMenu 会显示一个选项列表。"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57657,6 +57901,14 @@ msgid ""
"keystroke was registered. You can adjust the timeout duration by changing "
"[member ProjectSettings.gui/timers/incremental_search_max_interval_msec]."
msgstr ""
+"[PopupMenu] 是会显示一个选项列表的 [Control]。常è§äºŽå·¥å…·æ å’Œä¸Šä¸‹æ–‡èœå•中。\n"
+"[b]å¢žé‡æœç´¢ï¼š[/b]与 [ItemList] å’Œ [Tree] 类似,[PopupMenu] 也支æŒåœ¨èšç„¦æŽ§ä»¶æ—¶"
+"在列表中进行æœç´¢ã€‚按下与æŸä¸ªæ¡ç›®å称首字æ¯ä¸€è‡´çš„æŒ‰é”®ï¼Œå°±ä¼šé€‰ä¸­ä»¥è¯¥å­—æ¯å¼€å¤´çš„"
+"第一个æ¡ç›®ã€‚在此之åŽï¼Œè¿›è¡Œå¢žé‡æœç´¢çš„办法有两ç§ï¼š1)在超时å‰å†æ¬¡æŒ‰ä¸‹åŒä¸€ä¸ªæŒ‰"
+"键,选中以该字æ¯å¼€å¤´çš„下一个æ¡ç›®ã€‚2ï¼‰åœ¨è¶…æ—¶å‰æŒ‰ä¸‹å‰©ä½™å­—æ¯å¯¹åº”的按键,直接匹é…"
+"并选中所需的æ¡ç›®ã€‚这两个动作都会在最åŽä¸€æ¬¡æŒ‰é”®è¶…æ—¶åŽé‡ç½®å›žåˆ—表顶端。你å¯ä»¥é€š"
+"过 [member ProjectSettings.gui/timers/incremental_search_max_interval_msec] "
+"修改超时时长。"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57689,12 +57941,13 @@ msgid ""
"built-in checking behavior and must be checked/unchecked manually. See "
"[method set_item_checked] for more info on how to control it."
msgstr ""
-"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯æ£€æŸ¥é¡¹ç›®,并将指定的[ShortCut]分é…给它.å°†å¤é€‰æ¡†çš„æ ‡ç­¾è®¾ç½®ä¸º"
-"ShortCutçš„åç§°.\n"
-"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª[code]id[/code].如果没有æä¾›[code]id[/code],将从索引中创建一"
-"个.\n"
-"[b]注æ„:[/b]坿£€æŸ¥é¡¹ç›®åªæ˜¯æ˜¾ç¤ºä¸€ä¸ªæ£€æŸ¥æ ‡è®°,但没有任何内置的检查行为,必须手动"
-"æ£€æŸ¥æˆ–å–æ¶ˆæ£€æŸ¥. å‚阅 [method set_item_checked]了解更多关于如何控制它的信æ¯."
+"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯æ£€æŸ¥é¡¹ç›®,并将指定的 [ShortCut] 分é…给它。将å¤é€‰æ¡†çš„æ ‡ç­¾è®¾ç½®ä¸º "
+"ShortCut çš„å称。\n"
+"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引中创"
+"建一个。\n"
+"[b]注æ„:[/b]坿£€æŸ¥é¡¹ç›®åªæ˜¯æ˜¾ç¤ºä¸€ä¸ªæ£€æŸ¥æ ‡è®°ï¼Œä½†æ²¡æœ‰ä»»ä½•内置的检查行为,必须手"
+"åŠ¨æ£€æŸ¥æˆ–å–æ¶ˆæ£€æŸ¥ã€‚å‚阅 [method set_item_checked] 了解更多关于如何控制它的信"
+"æ¯ã€‚"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57709,14 +57962,14 @@ msgid ""
"built-in checking behavior and must be checked/unchecked manually. See "
"[method set_item_checked] for more info on how to control it."
msgstr ""
-"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯æ£€æŸ¥é¡¹ç›®ï¼Œå¸¦æœ‰æ–‡æœ¬[code]label[/code]和图标[code]texture[/"
+"æ·»åŠ ä¸€ä¸ªæ–°çš„å¯æ£€æŸ¥é¡¹ç›®ï¼Œå¸¦æœ‰æ–‡æœ¬ [code]label[/code] 和图标 [code]texture[/"
"code]。\n"
-"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª[code]id[/code],以åŠä¸€ä¸ªåŠ é€Ÿå™¨ï¼ˆ[code]accel[/code])。如果没"
-"有æä¾›[code]id[/code],将从索引中创建一个。如果没有æä¾›[code]accel[/code],那"
-"么默认的[code]0[/code]将被分é…给它。å‚阅[method get_item_accelerator]èŽ·å–æ›´å¤š"
-"关于加速器的信æ¯ã€‚\n"
+"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª [code]id[/code],以åŠä¸€ä¸ªåŠ é€Ÿå™¨ï¼ˆ[code]accel[/code])。如果"
+"没有æä¾› [code]id[/code],将从索引中创建一个。如果没有æä¾› [code]accel[/"
+"code],那么默认的 [code]0[/code] 将被分é…给它。å‚阅 [method "
+"get_item_accelerator] èŽ·å–æ›´å¤šå…³äºŽåŠ é€Ÿå™¨çš„ä¿¡æ¯ã€‚\n"
"[b]注æ„:[/b]å¯é€‰é¡¹ç›®åªæ˜¯æ˜¾ç¤ºä¸€ä¸ªå¤é€‰æ ‡è®°ï¼Œä½†æ²¡æœ‰ä»»ä½•内置的检查行为,必须手动"
-"检查/å–æ¶ˆæ£€æŸ¥ã€‚å‚阅[method set_item_checked]èŽ·å–æ›´å¤šå…³äºŽå¦‚何控制它的信æ¯ã€‚"
+"检查/å–æ¶ˆæ£€æŸ¥ã€‚å‚阅 [method set_item_checked] èŽ·å–æ›´å¤šå…³äºŽå¦‚何控制它的信æ¯ã€‚"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57729,12 +57982,12 @@ msgid ""
"built-in checking behavior and must be checked/unchecked manually. See "
"[method set_item_checked] for more info on how to control it."
msgstr ""
-"添加一个新的å¯é€‰é¡¹ç›®ï¼Œå¹¶ä¸ºå…¶åˆ†é…指定的[ShortCut]和图标[code]texture[/code]。"
-"å°†å¤é€‰æ¡†çš„æ ‡ç­¾è®¾ç½®ä¸º[ShortCut]çš„å称。\n"
-"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª[code]id[/code]。如果没有æä¾›[code]id[/code],将从索引中创建"
-"一个。\n"
+"添加一个新的å¯é€‰é¡¹ç›®ï¼Œå¹¶ä¸ºå…¶åˆ†é…指定的 [ShortCut] 和图标 [code]texture[/"
+"code]。将å¤é€‰æ¡†çš„æ ‡ç­¾è®¾ç½®ä¸º [ShortCut] çš„å称。\n"
+"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ª [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引中创"
+"建一个。\n"
"[b]注æ„:[/b]å¯é€‰é¡¹ç›®åªæ˜¯æ˜¾ç¤ºä¸€ä¸ªå¤é€‰æ ‡è®°ï¼Œä½†æ²¡æœ‰ä»»ä½•内置的检查行为,必须手动"
-"检查/å–æ¶ˆæ£€æŸ¥ã€‚å‚阅[method set_item_checked]èŽ·å–æ›´å¤šå…³äºŽå¦‚何控制它的信æ¯ã€‚"
+"检查/å–æ¶ˆæ£€æŸ¥ã€‚å‚阅 [method set_item_checked] èŽ·å–æ›´å¤šå…³äºŽå¦‚何控制它的信æ¯ã€‚"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57753,12 +58006,12 @@ msgstr ""
#: doc/classes/PopupMenu.xml
msgid "Same as [method add_icon_check_item], but uses a radio check button."
-msgstr "与[method add_icon_check_item]相åŒï¼Œä½†ä½¿ç”¨å•选按钮。"
+msgstr "与 [method add_icon_check_item] 相åŒï¼Œä½†ä½¿ç”¨å•选按钮。"
#: doc/classes/PopupMenu.xml
msgid ""
"Same as [method add_icon_check_shortcut], but uses a radio check button."
-msgstr "与[method add_icon_check_shortcut]相åŒï¼Œä½†ä½¿ç”¨ä¸€ä¸ªå•选按钮。"
+msgstr "与 [method add_icon_check_shortcut] 相åŒï¼Œä½†ä½¿ç”¨ä¸€ä¸ªå•选按钮。"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57767,9 +58020,9 @@ msgid ""
"An [code]id[/code] can optionally be provided. If no [code]id[/code] is "
"provided, one will be created from the index."
msgstr ""
-"æ·»åŠ ä¸€ä¸ªæ–°é¡¹ï¼Œå¹¶åˆ†é…æŒ‡å®šçš„[ShortCut]和图标[code]texture[/code]给它。将å¤é€‰æ¡†"
-"的标签设置为[ShortCut]çš„å称。\n"
-"å¯ä»¥é€‰æ‹©æä¾›[code]id[/code]。如果没有æä¾›[code]id[/code],将从索引中创建一"
+"æ·»åŠ ä¸€ä¸ªæ–°é¡¹ï¼Œå¹¶åˆ†é…æŒ‡å®šçš„ [ShortCut] 和图标 [code]texture[/code] 给它。将å¤"
+"选框的标签设置为 [ShortCut] çš„å称。\n"
+"å¯ä»¥é€‰æ‹©æä¾› [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引中创建一"
"个。"
#: doc/classes/PopupMenu.xml
@@ -57854,9 +58107,9 @@ msgid ""
"A [code]label[/code] can optionally be provided, which will appear at the "
"center of the separator."
msgstr ""
-"在项目之间添加一个分隔符。分隔符也å ç”¨ä¸€ä¸ªç´¢å¼•,你å¯ä»¥é€šè¿‡ä½¿ç”¨[code]id[/code]"
-"傿•°æ¥è®¾ç½®ã€‚\n"
-"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ªæ ‡ç­¾[code]label[/code],它将出现在分隔符的中心。"
+"在项目之间添加一个分隔符。分隔符也å ç”¨ä¸€ä¸ªç´¢å¼•,你å¯ä»¥é€šè¿‡ä½¿ç”¨ [code]id[/"
+"code] 傿•°æ¥è®¾ç½®ã€‚\n"
+"å¯ä»¥é€‰æ‹©æä¾›ä¸€ä¸ªæ ‡ç­¾ [code]label[/code],它将出现在分隔符的中心。"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57864,8 +58117,8 @@ msgid ""
"An [code]id[/code] can optionally be provided. If no [code]id[/code] is "
"provided, one will be created from the index."
msgstr ""
-"添加一个[ShortCut]。\n"
-"å¯ä»¥é€‰æ‹©æä¾›[code]id[/code]。如果没有æä¾›[code]id[/code],将从索引中创建一"
+"添加一个 [ShortCut]。\n"
+"å¯ä»¥é€‰æ‹©æä¾› [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引中创建一"
"个。"
#: doc/classes/PopupMenu.xml
@@ -57876,14 +58129,14 @@ msgid ""
"An [code]id[/code] can optionally be provided. If no [code]id[/code] is "
"provided, one will be created from the index."
msgstr ""
-"添加一个项目,当å•击父[PopupMenu]节点时,它将作为å­èœå•。[code]submenu[/code]"
-"傿•°æ˜¯å­èŠ‚ç‚¹[PopupMenu]çš„å称,当点击项目时显示该å­èŠ‚ç‚¹ã€‚\n"
-"å¯ä»¥é€‰æ‹©æä¾›[code]id[/code]。如果没有æä¾›[code]id[/code],将从索引中创建一"
+"添加一个项目,当å•击父 [PopupMenu] 节点时,它将作为å­èœå•。[code]submenu[/"
+"code] 傿•°æ˜¯å­èŠ‚ç‚¹ [PopupMenu] çš„å称,当点击项目时显示该å­èŠ‚ç‚¹ã€‚\n"
+"å¯ä»¥é€‰æ‹©æä¾› [code]id[/code]。如果没有æä¾› [code]id[/code],将从索引中创建一"
"个。"
#: doc/classes/PopupMenu.xml
msgid "Removes all items from the [PopupMenu]."
-msgstr "从[PopupMenu]中移除所有项目。"
+msgstr "从该 [PopupMenu] 中移除所有项目。"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57897,19 +58150,20 @@ msgid ""
"are special combinations of keys that activate the item, no matter which "
"control is focused."
msgstr ""
-"返回索引[code]idx[/code]处项目的加速项。加速器是一ç§ç‰¹æ®Šçš„æŒ‰é”®ç»„åˆï¼Œå¯ä»¥æ¿€æ´»"
-"物å“,无论哪个控制键处于焦点状æ€ã€‚"
+"返回索引 [code]idx[/code] 处项目的加速项。加速器是一ç§ç‰¹æ®Šçš„æŒ‰é”®ç»„åˆï¼Œå¯ä»¥æ¿€"
+"活物å“,无论哪个控制键处于焦点状æ€ã€‚"
#: doc/classes/PopupMenu.xml
msgid "Returns the number of items in the [PopupMenu]."
-msgstr "返回[PopupMenu]中的项目数。"
+msgstr "返回该 [PopupMenu] 中的项目数。"
#: doc/classes/PopupMenu.xml
msgid ""
"Returns the id of the item at index [code]idx[/code]. [code]id[/code] can be "
"manually assigned, while index can not."
msgstr ""
-"返回索引[code]idx[/code]处项目的id。[code]id[/code]å¯ä»¥æ‰‹åŠ¨åˆ†é…,而索引ä¸èƒ½ã€‚"
+"返回索引 [code]idx[/code] 处项目的 id。[code]id[/code] å¯ä»¥æ‰‹åŠ¨åˆ†é…,而索引ä¸"
+"能。"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57917,8 +58171,8 @@ msgid ""
"Index is automatically assigned to each item by the engine. Index can not be "
"set manually."
msgstr ""
-"è¿”å›žåŒ…å«æŒ‡å®šçš„[code]id[/code]的项的索引。索引由引擎自动分é…ç»™æ¯ä¸ªé¡¹ç›®ã€‚ä¸èƒ½æ‰‹"
-"动设置索引。"
+"è¿”å›žåŒ…å«æŒ‡å®šçš„ [code]id[/code] 的项的索引。索引由引擎自动分é…ç»™æ¯ä¸ªé¡¹ç›®ã€‚ä¸èƒ½"
+"手动设置索引。"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -57926,26 +58180,26 @@ msgid ""
"can set it with [method set_item_metadata], which provides a simple way of "
"assigning context data to items."
msgstr ""
-"返回指定项的元数æ®ï¼Œè¯¥é¡¹å¯ä»¥æ˜¯ä»»ä½•类型。您å¯ä»¥ä½¿ç”¨[method set_item_metadata]"
-"æ¥è®¾ç½®å®ƒï¼Œå®ƒæä¾›äº†ä¸€ç§å°†ä¸Šä¸‹æ–‡æ•°æ®åˆ†é…ç»™é¡¹çš„ç®€å•æ–¹æ³•。"
+"返回指定项的元数æ®ï¼Œè¯¥é¡¹å¯ä»¥æ˜¯ä»»ä½•类型。您å¯ä»¥ä½¿ç”¨ [method "
+"set_item_metadata] æ¥è®¾ç½®å®ƒï¼Œå®ƒæä¾›äº†ä¸€ç§å°†ä¸Šä¸‹æ–‡æ•°æ®åˆ†é…ç»™é¡¹çš„ç®€å•æ–¹æ³•。"
#: doc/classes/PopupMenu.xml
msgid ""
"Returns the [ShortCut] associated with the specified [code]idx[/code] item."
-msgstr "返回与指定的[code]idx[/code]项关è”çš„[ShortCut]。"
+msgstr "返回与指定的 [code]idx[/code] 项关è”çš„ [ShortCut]。"
#: doc/classes/PopupMenu.xml
msgid ""
"Returns the submenu name of the item at index [code]idx[/code]. See [method "
"add_submenu_item] for more info on how to add a submenu."
msgstr ""
-"返回在索引[code]idx[/code]处的项目的å­èœå•å。更多关于如何添加å­èœå•的信æ¯ï¼Œ"
-"请å‚阅[method add_submenu_item]。"
+"返回在索引 [code]idx[/code] 处的项目的å­èœå•å。更多关于如何添加å­èœå•的信"
+"æ¯ï¼Œè¯·å‚阅 [method add_submenu_item]。"
#: doc/classes/PopupMenu.xml
msgid ""
"Returns the tooltip associated with the specified index [code]idx[/code]."
-msgstr "返回与指定索引 [code]idx[/code]å…³è”的工具æç¤ºã€‚"
+msgstr "返回与指定索引 [code]idx[/code] å…³è”的工具æç¤ºã€‚"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -58021,7 +58275,7 @@ msgstr "将当å‰èšç„¦é¡¹ç›®è®¾ç½®ä¸ºç»™å®šçš„索引 [code]index[/code]。"
#: doc/classes/PopupMenu.xml
msgid "Hides the [PopupMenu] when the window loses focus."
-msgstr "当窗å£å¤±åŽ»ç„¦ç‚¹æ—¶éšè—[PopupMenu]。"
+msgstr "当窗å£å¤±åŽ»ç„¦ç‚¹æ—¶éšè— [PopupMenu]。"
#: doc/classes/PopupMenu.xml
msgid ""
@@ -58029,7 +58283,7 @@ msgid ""
"special combinations of keys that activate the item, no matter which control "
"is focused."
msgstr ""
-"设置索引[code]idx[/code]项的加速键。加速器是一ç§ç‰¹æ®Šçš„æŒ‰é”®ç»„åˆï¼Œå¯ä»¥æ¿€æ´»ç‰©"
+"设置索引 [code]idx[/code] 项的加速键。加速器是一ç§ç‰¹æ®Šçš„æŒ‰é”®ç»„åˆï¼Œå¯ä»¥æ¿€æ´»ç‰©"
"å“,无论哪个控制键处于焦点状æ€ã€‚"
#: doc/classes/PopupMenu.xml
@@ -58063,15 +58317,15 @@ msgstr ""
#: doc/classes/PopupMenu.xml
msgid "Sets the checkstate status of the item at index [code]idx[/code]."
-msgstr "设置项目在index [code]idx[/code]处的checkstate状æ€ã€‚"
+msgstr "è®¾ç½®åœ¨ç´¢å¼•å· [code]idx[/code] 处的项目的勾选状æ€ã€‚"
#: doc/classes/PopupMenu.xml
msgid ""
"Enables/disables the item at index [code]idx[/code]. When it is disabled, it "
"can't be selected and its action can't be invoked."
msgstr ""
-"å¯ç”¨/ç¦ç”¨ç´¢å¼•[code]idx[/code]项。当它被ç¦ç”¨æ—¶ï¼Œå°±æ— æ³•选择它,也无法调用它的æ“"
-"作。"
+"å¯ç”¨/ç¦ç”¨ç´¢å¼• [code]idx[/code] 项。当它被ç¦ç”¨æ—¶ï¼Œå°±æ— æ³•选择它,也无法调用它的"
+"æ“作。"
#: doc/classes/PopupMenu.xml
msgid "Replaces the [Texture] icon of the specified [code]idx[/code]."
@@ -62057,7 +62311,6 @@ msgstr ""
"义。"
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"This is the maximum number of shaders that can be compiled (or reconstructed "
"from cache) at the same time.\n"
@@ -62083,12 +62336,10 @@ msgstr ""
"èƒ½å¤šçš„å¼‚æ­¥ç¼–è¯‘çš„åŒæ—¶ï¼Œä¸å¯¹æ¸¸æˆçš„å“应性造æˆå½±å“,å¦åˆ™å°±ä¼šè¾œè´Ÿå¼‚步编译所带æ¥çš„"
"好处。æ¢å¥è¯è¯´ï¼Œä½ å¯èƒ½ä¼šç‰ºç‰²ä¸€ç‚¹ç‚¹çš„ FPSï¼Œæ€»æ¯”åŒæ­¥ç¼–译让整个游æˆåœæ»žè¦å¥½ã€‚\n"
"默认值比较ä¿å®ˆï¼Œæ‰€ä»¥å»ºè®®ä½ æ ¹æ®è‡ªå·±çš„目标硬件作出调整。\n"
-"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/"
-"shader_compilation_mode[/code] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„"
-"义。"
+"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/"
+"shader_compilation_mode] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„义。"
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"The default is a very conservative override for [member rendering/gles3/"
"shaders/max_simultaneous_compiles].\n"
@@ -62097,15 +62348,13 @@ msgid ""
"[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/"
"shaders/shader_compilation_mode] is [b]not[/b] [code]Synchronous[/code]."
msgstr ""
-"默认是针对 [code]rendering/gles3/shaders/max_concurrent_compiles[/code] 的覆"
+"默认是针对 [member rendering/gles3/shaders/max_simultaneous_compiles] 的覆"
"盖,å–值éžå¸¸ä¿å®ˆã€‚\n"
"æ ¹æ®ä½ æ‰€è®¾å®šä¸ºç›®æ ‡çš„特定设备,你å¯èƒ½ä¼šæƒ³è¦æé«˜è¿™ä¸ªå€¼ã€‚\n"
-"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/"
-"shader_compilation_mode[/code] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„"
-"义。"
+"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/"
+"shader_compilation_mode] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„义。"
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"The default is a very conservative override for [member rendering/gles3/"
"shaders/max_simultaneous_compiles].\n"
@@ -62114,15 +62363,13 @@ msgid ""
"[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/"
"shaders/shader_compilation_mode] is [b]not[/b] [code]Synchronous[/code]."
msgstr ""
-"默认是针对 [code]rendering/gles3/shaders/max_concurrent_compiles[/code] 的覆"
+"默认是针对 [member rendering/gles3/shaders/max_simultaneous_compiles] 的覆"
"盖,å–值éžå¸¸ä¿å®ˆã€‚\n"
"æ ¹æ®ä½ æ‰€è®¾å®šä¸ºç›®æ ‡çš„特定设备,你å¯èƒ½ä¼šæƒ³è¦æé«˜è¿™ä¸ªå€¼ã€‚\n"
-"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/"
-"shader_compilation_mode[/code] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„"
-"义。"
+"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/"
+"shader_compilation_mode] [b]ä¸ä¸º[/b] [code]Synchronous[/code] 时有æ„义。"
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"The maximum size, in megabytes, that the ubershader cache can grow up to. On "
"startup, the least recently used entries will be deleted until the total "
@@ -62132,12 +62379,10 @@ msgid ""
msgstr ""
"超级ç€è‰²å™¨ç¼“存所能增长到的最大大å°ï¼Œå•ä½ä¸ºå…†å­—节。在å¯åŠ¨æ—¶ï¼Œä¼šåˆ é™¤æœ€ä¹…æœªç”¨çš„"
"æ¡ç›®ï¼Œç›´åˆ°æ€»å¤§å°åˆ°è¾¾èŒƒå›´å†…。\n"
-"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/"
-"shader_compilation_mode[/code] 为 [code]Asynchronous + Cache[/code] 时有æ„"
-"义。"
+"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/"
+"shader_compilation_mode] 为 [code]Asynchronous + Cache[/code] 时有æ„义。"
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"An override for [member rendering/gles3/shaders/shader_cache_size_mb], so a "
"smaller maximum size can be configured for mobile platforms, where storage "
@@ -62145,14 +62390,12 @@ msgid ""
"[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/"
"shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]."
msgstr ""
-"[code]rendering/gles3/shaders/ubershader_cache_size_mb[/code] 的覆盖项,为针"
-"对移动平å°é…置更å°çš„æœ€å¤§å¤§å°ï¼Œç§»åЍ平å°çš„存储空间更有é™ã€‚\n"
-"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/"
-"shader_compilation_mode[/code] 为 [code]Asynchronous + Cache[/code] 时有æ„"
-"义。"
+"[member rendering/gles3/shaders/shader_cache_size_mb] 的覆盖项,为针对移动平"
+"å°é…置更å°çš„æœ€å¤§å¤§å°ï¼Œç§»åЍ平å°çš„存储空间更有é™ã€‚\n"
+"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/"
+"shader_compilation_mode] 为 [code]Asynchronous + Cache[/code] 时有æ„义。"
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"An override for [member rendering/gles3/shaders/shader_cache_size_mb], so a "
"smaller maximum size can be configured for web platforms, where storage "
@@ -62162,11 +62405,11 @@ msgid ""
"[b]Note:[/b] This setting is only meaningful if [member rendering/gles3/"
"shaders/shader_compilation_mode] is set to [code]Asynchronous + Cache[/code]."
msgstr ""
-"[code]rendering/gles3/shaders/ubershader_cache_size_mb[/code] 的覆盖项,为针"
-"对移动平å°é…置更å°çš„æœ€å¤§å¤§å°ï¼Œç§»åЍ平å°çš„存储空间更有é™ã€‚\n"
-"[b]注æ„:[/b]本设置仅在 [code]rendering/gles3/shaders/"
-"shader_compilation_mode[/code] 为 [code]Asynchronous + Cache[/code] 时有æ„"
-"义。"
+"[member rendering/gles3/shaders/shader_cache_size_mb] 的覆盖项,为针对移动平"
+"å°é…置更å°çš„æœ€å¤§å¤§å°ï¼Œç§»åЍ平å°çš„存储空间更有é™ã€‚\n"
+"[b]注æ„:[/b]ç›®å‰ Web å¹³å°å°šä¸æ”¯æŒç€è‰²å™¨ç¼“存。\n"
+"[b]注æ„:[/b]本设置仅在 [member rendering/gles3/shaders/"
+"shader_compilation_mode] 为 [code]Asynchronous + Cache[/code] 时有æ„义。"
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -62212,28 +62455,26 @@ msgstr ""
"ç€è‰²å™¨ä¹Ÿä¸ä¼šä½¿ç”¨å¼‚步编译。"
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"An override for [member rendering/gles3/shaders/shader_compilation_mode], so "
"asynchronous compilation can be disabled on mobile platforms.\n"
"You may want to do that since mobile GPUs generally won't support "
"ubershaders due to their complexity."
msgstr ""
-"[code]rendering/gles3/shaders/shader_compilation_mode[/code] 的覆盖项,用于为"
-"移动设备ç¦ç”¨å¼‚步编译。\n"
+"[member rendering/gles3/shaders/shader_compilation_mode] 的覆盖项,用于为移动"
+"设备ç¦ç”¨å¼‚步编译。\n"
"移动 GPU 通常ä¸ä¼šæ”¯æŒè¶…级ç€è‰²å™¨ï¼Œå› ä¸ºå…¶å¤æ‚度较高。"
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid ""
"An override for [member rendering/gles3/shaders/shader_compilation_mode], so "
"asynchronous compilation can be disabled on web platforms.\n"
"You may want to do that since certain browsers (especially on mobile "
"platforms) generally won't support ubershaders due to their complexity."
msgstr ""
-"[code]rendering/gles3/shaders/shader_compilation_mode[/code] 的覆盖项,用于为"
-"移动设备ç¦ç”¨å¼‚步编译。\n"
-"移动 GPU 通常ä¸ä¼šæ”¯æŒè¶…级ç€è‰²å™¨ï¼Œå› ä¸ºå…¶å¤æ‚度较高。"
+"[member rendering/gles3/shaders/shader_compilation_mode] 的覆盖项,用于为 "
+"Web å¹³å°ç¦ç”¨å¼‚步编译。\n"
+"æŸäº›æµè§ˆå™¨ï¼ˆå°¤å…¶åœ¨ç§»åЍ平å°ä¸Šï¼‰é€šå¸¸ä¸ä¼šæ”¯æŒè¶…级ç€è‰²å™¨ï¼Œå› ä¸ºå…¶å¤æ‚度较高。"
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -62853,9 +63094,11 @@ msgstr "阴影贴图的细分象é™å¤§å°ã€‚请å‚阅阴影映射文档。"
#: doc/classes/ProjectSettings.xml
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 ""
@@ -63640,14 +63883,14 @@ msgid ""
"Generates a pseudo-random float between [code]0.0[/code] and [code]1.0[/"
"code] (inclusive)."
msgstr ""
-"产生一个[code]0.0[/code]å’Œ[code]1.0[/code]ï¼ˆåŒ…æ‹¬ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœºæµ®ç‚¹æ•°ã€‚"
+"生æˆä¸€ä¸ª[code]0.0[/code]å’Œ[code]1.0[/code]ï¼ˆåŒ…æ‹¬ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœºæµ®ç‚¹æ•°ã€‚"
#: doc/classes/RandomNumberGenerator.xml
msgid ""
"Generates a pseudo-random float between [code]from[/code] and [code]to[/"
"code] (inclusive)."
msgstr ""
-"产生一个[code]from[/code]å’Œ[code]to[/code]ï¼ˆåŒ…æ‹¬ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœºæµ®ç‚¹æ•°ã€‚"
+"生æˆä¸€ä¸ª[code]from[/code]å’Œ[code]to[/code]ï¼ˆåŒ…æ‹¬ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœºæµ®ç‚¹æ•°ã€‚"
#: doc/classes/RandomNumberGenerator.xml
msgid ""
@@ -63656,8 +63899,8 @@ msgid ""
"specified [code]mean[/code] and a standard [code]deviation[/code]. This is "
"also called Gaussian distribution."
msgstr ""
-"产生一个[url=https://en.wikipedia.org/wiki/Normal_distribution]æ­£æ€åˆ†å¸ƒ[/url]"
-"çš„ä¼ªéšæœºæ•°ï¼Œä½¿ç”¨Box-Mullerå˜æ¢ï¼Œå…·æœ‰æŒ‡å®šçš„[code]mean[/code]和标准"
+"生æˆä¸€ä¸ª[url=https://en.wikipedia.org/wiki/Normal_distribution]æ­£æ€åˆ†å¸ƒ[/url]"
+"çš„ä¼ªéšæœºæ•°ï¼Œä½¿ç”¨ Box-Muller å˜æ¢ï¼Œå…·æœ‰æŒ‡å®šçš„ [code]mean[/code] 和标准 "
"[code]deviation[/code]。这也被称为高斯分布。"
#: doc/classes/RandomNumberGenerator.xml
@@ -63665,16 +63908,16 @@ msgid ""
"Generates a pseudo-random 32-bit unsigned integer between [code]0[/code] and "
"[code]4294967295[/code] (inclusive)."
msgstr ""
-"产生一个[code]0[/code]å’Œ[code]4294967295[/code](å«ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœº32使— ç¬¦"
-"å·æ•´æ•°ã€‚"
+"生æˆä¸€ä¸ª [code]0[/code] å’Œ [code]4294967295[/code](å«ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœº 32 "
+"使— ç¬¦å·æ•´æ•°ã€‚"
#: doc/classes/RandomNumberGenerator.xml
msgid ""
"Generates a pseudo-random 32-bit signed integer between [code]from[/code] "
"and [code]to[/code] (inclusive)."
msgstr ""
-"产生一个[code]to[/code]å’Œ[code]from[/code](å«ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœº32使œ‰ç¬¦å·æ•´"
-"数。"
+"生æˆä¸€ä¸ª [code]to[/code] å’Œ [code]from[/code](å«ç«¯ç‚¹ï¼‰ä¹‹é—´çš„ä¼ªéšæœº 32 使œ‰ç¬¦"
+"å·æ•´æ•°ã€‚"
#: doc/classes/RandomNumberGenerator.xml
msgid "Setups a time-based seed to generator."
@@ -63777,20 +64020,20 @@ msgstr "使该 [Range] åœæ­¢ä¸Žä»»ä½•å…¶ä»– Range 共享其æˆå‘˜å˜é‡ã€‚"
#: doc/classes/Range.xml
msgid ""
"If [code]true[/code], [member value] may be greater than [member max_value]."
-msgstr "如果为 [code]true[/code],[member value]å¯èƒ½å¤§äºŽ[member max_value]。"
+msgstr "如果为 [code]true[/code],[member value] å¯èƒ½å¤§äºŽ [member max_value]。"
#: doc/classes/Range.xml
msgid ""
"If [code]true[/code], [member value] may be less than [member min_value]."
-msgstr "如果为 [code]true[/code],[member value]å¯èƒ½å°äºŽ[member min_value]。"
+msgstr "如果为 [code]true[/code],[member value] å¯èƒ½å°äºŽ [member min_value]。"
#: doc/classes/Range.xml
msgid ""
"If [code]true[/code], and [code]min_value[/code] is greater than 0, "
"[code]value[/code] will be represented exponentially rather than linearly."
msgstr ""
-"如果为 [code]true[/code],并且[code]min_value[/code]大于0,[code]value[/code]"
-"将以指数方å¼è€Œä¸æ˜¯çº¿æ€§æ–¹å¼è¡¨ç¤ºã€‚"
+"如果为 [code]true[/code],并且 [code]min_value[/code] 大于 0,[code]value[/"
+"code] 将以指数方å¼è€Œä¸æ˜¯çº¿æ€§æ–¹å¼è¡¨ç¤ºã€‚"
#: doc/classes/Range.xml
msgid ""
@@ -63812,12 +64055,12 @@ msgid ""
"multiplied by [code]page[/code] over the difference between [code]min_value[/"
"code] and [code]max_value[/code]."
msgstr ""
-"页é¢å¤§å°ã€‚主è¦ç”¨äºŽ[ScrollBar]。ScrollBar的长度是它的尺寸乘以[code]page[/code]"
-"超过[code]min_value[/code]和[code]max_value[/code]之间的差值。"
+"页é¢å¤§å°ã€‚主è¦ç”¨äºŽ [ScrollBar]。ScrollBar 的长度是它的尺寸乘以 [code]page[/"
+"code] 超过 [code]min_value[/code] 和 [code]max_value[/code] 之间的差值。"
#: doc/classes/Range.xml
msgid "The value mapped between 0 and 1."
-msgstr "该值在0和1之间进行映射。"
+msgstr "该值在 0 和 1 之间进行映射。"
#: doc/classes/Range.xml
msgid ""
@@ -63833,9 +64076,9 @@ msgid ""
"[code]value[/code] will first be rounded to a multiple of [code]step[/code] "
"then rounded to the nearest integer."
msgstr ""
-"如果大于0,[code]value[/code]将总是被四èˆäº”入为[code]step[/code]çš„å€æ•°ã€‚如果"
-"[code]rounded[/code]也是[code]true[/code],[code]value[/code]将首先被四èˆäº”å…¥"
-"为[code]step[/code]çš„å€æ•°ï¼Œç„¶åŽèˆå…¥ä¸ºæœ€è¿‘的整数。"
+"如果大于 0,[code]value[/code] 将总是被四èˆäº”入为 [code]step[/code] çš„å€æ•°ã€‚"
+"如果 [code]rounded[/code] 也是 [code]true[/code],[code]value[/code] 将首先被"
+"å››èˆäº”入为 [code]step[/code] çš„å€æ•°ï¼Œç„¶åŽèˆå…¥ä¸ºæœ€è¿‘的整数。"
#: doc/classes/Range.xml
msgid "Range's current value."
@@ -63846,8 +64089,8 @@ msgid ""
"Emitted when [member min_value], [member max_value], [member page], or "
"[member step] change."
msgstr ""
-"在 [member min_value], [member max_value], [member page], 或 [member step] 改"
-"å˜æ—¶é‡Šæ”¾ä¿¡å·ã€‚"
+"在 [member min_value]ã€[member max_value]ã€[member page]ã€[member step] 改å˜"
+"时释放信å·ã€‚"
#: doc/classes/Range.xml
msgid ""
@@ -63890,12 +64133,12 @@ msgstr ""
"以便找到沿光线路径最近的对象。\n"
"RayCast å¯ä»¥å¿½ç•¥æŸäº›å¯¹è±¡ï¼Œæ–¹æ³•是通过 [code]add_exception[/code] 将它们添加到"
"例外列表中,或者通过使用碰撞层和掩ç è®¾ç½®ï¼Œè¿›è¡Œé€‚当的过滤。\n"
-"RayCast å¯ä»¥é…置为报告与 [Area]([member collide_with_areas]) å’Œ/或 "
-"[PhysicsBody]([member collide_with_bodies]) 的碰撞。\n"
+"RayCast å¯ä»¥é…置为报告与 [Area]([member collide_with_areas])和/或 "
+"[PhysicsBody]([member collide_with_bodies])的碰撞。\n"
"åªæœ‰å¯ç”¨çš„光线投射æ‰èƒ½æ£€æµ‹ç©ºé—´å¹¶æŠ¥å‘Šç¢°æ’žã€‚\n"
-"RayCast 计算æ¯ä¸ªç‰©ç†å¸§çš„交集(å‚阅 [Node]),并将结果缓存起æ¥ï¼Œä»¥ä¾¿ç¨åŽä½¿ç”¨ï¼Œ"
-"直到下一帧。如果物ç†å¸§ä¹‹é—´ï¼ˆæˆ–åŒä¸€å¸§æœŸé—´ï¼‰éœ€è¦å¤šæ¬¡æ£€æµ‹ï¼Œè¯·åœ¨è°ƒæ•´å…‰çº¿æŠ•å°„åŽä½¿"
-"用[method force_raycast_update]。"
+"RayCast 计算æ¯ä¸ªç‰©ç†å¸§çš„äº¤é›†ï¼ˆè§ [Node]),并将结果缓存起æ¥ï¼Œä»¥ä¾¿ç¨åŽä½¿ç”¨ï¼Œç›´"
+"到下一帧。如果物ç†å¸§ä¹‹é—´ï¼ˆæˆ–åŒä¸€å¸§æœŸé—´ï¼‰éœ€è¦å¤šæ¬¡æ£€æµ‹ï¼Œè¯·åœ¨è°ƒæ•´å…‰çº¿æŠ•å°„åŽä½¿ç”¨ "
+"[method force_raycast_update]。"
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid ""
@@ -63923,7 +64166,7 @@ msgid ""
msgstr ""
"更新射线的碰撞信æ¯ã€‚ä½¿ç”¨æ­¤æ–¹æ³•ç«‹å³æ›´æ–°ç¢°æ’žä¿¡æ¯ï¼Œè€Œä¸æ˜¯ç­‰å¾…下一次 "
"[code]_physics_process[/code] 调用,例如,如果光线或其父级已更改状æ€ã€‚\n"
-"[b]注æ„:[/b][code]enabled[/code]ä¸éœ€è¦æ­¤åŠŸèƒ½ã€‚"
+"[b]注æ„:[/b][code]enabled[/code] ä¸éœ€è¦æ­¤åŠŸèƒ½ã€‚"
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid ""
@@ -63949,7 +64192,7 @@ msgid ""
"[b]Note:[/b] Bit indices range from 0-19."
msgstr ""
"如果通过的ä½ç´¢å¼•被打开,则返回 [code]true[/code]。\n"
-"[b]注æ„:[/b]使Œ‡æ•°èŒƒå›´ä¸º0-19。"
+"[b]注æ„:[/b]使Œ‡æ•°èŒƒå›´ä¸º 0-19。"
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid ""
@@ -63987,8 +64230,8 @@ msgid ""
"Sets the bit index passed to the [code]value[/code] passed.\n"
"[b]Note:[/b] Bit indexes range from 0-19."
msgstr ""
-"将传递的ä½ç´¢å¼•设置为传递的[code]值[/code]。\n"
-"[b]注æ„:[/b]ä½ç´¢å¼•的范围是0-19。"
+"将传递的ä½ç´¢å¼•设置为传递的 [code]value[/code]。\n"
+"[b]注æ„:[/b]ä½ç´¢å¼•的范围是 0-19。"
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid ""
@@ -64023,9 +64266,9 @@ msgid ""
"If set to [code]Color(0.0, 0.0, 0.0)[/code] (by default), the color set in "
"[member ProjectSettings.debug/shapes/collision/shape_color] is used."
msgstr ""
-"如果在 [b]Debug[/b] èœå•中å¯ç”¨äº†å¯è§ç¢°æ’žå½¢çж [b]Visible Collision Shapes[/"
-"b],则å¯ç”¨äºŽåœ¨ç¼–辑器中和è¿è¡Œæ—¶ç»˜åˆ¶å½¢çŠ¶çš„è‡ªå®šä¹‰é¢œè‰²ã€‚å¦‚æžœ [RayCast] 与æŸç‰©ä½“å‘"
-"生碰撞,此颜色将在è¿è¡Œæ—¶çªå‡ºæ˜¾ç¤ºã€‚\n"
+"如果在[b]调试[/b]èœå•中å¯ç”¨äº†[b]显示碰撞区域[/b],则å¯ç”¨äºŽåœ¨ç¼–辑器中和è¿è¡Œæ—¶"
+"绘制形状的自定义颜色。如果 [RayCast] 与æŸç‰©ä½“å‘生碰撞,此颜色将在è¿è¡Œæ—¶çªå‡ºæ˜¾"
+"示。\n"
"如果设置为 [code]Color(0.0, 0.0, 0.0)[/code](默认),则使用 [member "
"ProjectSettings.debug/shapes/collision/shape_color] 中设置的颜色。"
@@ -64037,8 +64280,8 @@ msgid ""
"shape to be visible at run-time."
msgstr ""
"如果设置为 [code]1[/code],则将一æ¡çº¿ç”¨ä½œè°ƒè¯•形状。å¦åˆ™ï¼Œå°†ç»˜åˆ¶ä¸€ä¸ªæˆªæ–­çš„金字"
-"å¡”æ¥è¡¨ç¤º [RayCast]。需è¦åœ¨ [b]调试[/b] èœå•中å¯ç”¨å¯è§ç¢°æ’žå½¢çж [b]Visible "
-"Collision Shapes[/b],以便调试形状在è¿è¡Œæ—¶å¯è§ã€‚"
+"å¡”æ¥è¡¨ç¤º [RayCast]。需è¦åœ¨[b]调试[/b]èœå•中å¯ç”¨[b]显示碰撞区域[/b],以便调试"
+"形状在è¿è¡Œæ—¶å¯è§ã€‚"
#: doc/classes/RayCast.xml doc/classes/RayCast2D.xml
msgid "If [code]true[/code], collisions will be reported."
@@ -64068,8 +64311,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])和 "
@@ -64110,9 +64353,9 @@ msgid ""
"itself from whatever is touching its far endpoint. It's often useful for "
"characters."
msgstr ""
-"用于3D碰撞的射线形状,它å¯ä»¥è¢«è®¾ç½®æˆä¸€ä¸ª[PhysicsBody]或[Area]。一æ¡å°„çº¿å¹¶ä¸æ˜¯"
-"真正的碰撞体;然而,它试图将自己与其远端点接触的东西分开。这通常对角色很有"
-"用。"
+"用于 3D 碰撞的射线形状,它å¯ä»¥è¢«è®¾ç½®æˆä¸€ä¸ª [PhysicsBody] 或 [Area]。一æ¡å°„线"
+"并䏿˜¯çœŸæ­£çš„碰撞体;然而,它试图将自己与其远端点接触的东西分开。这通常对角色"
+"很有用。"
#: doc/classes/RayShape.xml doc/classes/RayShape2D.xml
msgid "The ray's length."
@@ -64132,8 +64375,8 @@ msgid ""
"it tries to separate itself from whatever is touching its far endpoint. It's "
"often useful for characters."
msgstr ""
-"äºŒç»´ç¢°æ’žçš„å°„çº¿å½¢çŠ¶ã€‚å°„çº¿å¹¶ä¸æ˜¯çœŸæ­£çš„碰撞体;相å,它试图将自己与接触其远端的"
-"任何东西分开。它通常对角色很有用。"
+"2D ç¢°æ’žçš„å°„çº¿å½¢çŠ¶ã€‚å°„çº¿å¹¶ä¸æ˜¯çœŸæ­£çš„碰撞体;相å,它试图将自己与接触其远端的任"
+"何东西分开。它通常对角色很有用。"
#: doc/classes/Rect2.xml
msgid "2D axis-aligned bounding box."
@@ -64152,11 +64395,11 @@ msgstr ""
#: doc/classes/Rect2.xml
msgid "Constructs a [Rect2] by position and size."
-msgstr "按ä½ç½®å’Œå¤§å°æž„造一个[Rect2]。"
+msgstr "按ä½ç½®å’Œå¤§å°æž„造一个 [Rect2]。"
#: doc/classes/Rect2.xml
msgid "Constructs a [Rect2] by x, y, width, and height."
-msgstr "通过xã€yã€å®½åº¦å’Œé«˜åº¦æž„造一个[Rect2]。"
+msgstr "通过 xã€yã€å®½åº¦å’Œé«˜åº¦æž„造一个 [Rect2]。"
#: doc/classes/Rect2.xml
msgid ""
@@ -64277,13 +64520,13 @@ msgstr "返回一个更大的 [Rect2],其中包å«è¿™ä¸ª [Rect2] å’Œ [code]b[/
#: doc/classes/RectangleShape2D.xml
msgid "Rectangle shape for 2D collisions."
-msgstr "二维碰撞的矩形。"
+msgstr "2D 碰撞的矩形。"
#: doc/classes/RectangleShape2D.xml
msgid ""
"Rectangle shape for 2D collisions. This shape is useful for modeling box-"
"like 2D objects."
-msgstr "二维碰撞的矩形。这个形状对于建模盒状2D对象很有用。"
+msgstr "2D 碰撞的矩形。这个形状对于建模盒状 2D 对象很有用。"
#: doc/classes/RectangleShape2D.xml
msgid ""
@@ -66241,8 +66484,8 @@ msgid ""
"for a body."
msgstr ""
"在物ç†å¤„ç†è¿‡ç¨‹ä¸­è¢«è°ƒç”¨ï¼Œå…许你读å–并安全地修改对象的模拟状æ€ã€‚默认情况下,它"
-"是在通常的物ç†è¡Œä¸ºä¹‹å¤–工作的,但是[member custom_integrator]属性å…许你ç¦ç”¨é»˜"
-"认行为,为一个物体施加完全自定义的åˆåŠ›ã€‚"
+"会和通常的物ç†è¡Œä¸ºä¸€èµ·ç”Ÿæ•ˆï¼Œä½†æ˜¯ä½ å¯ä»¥é€šè¿‡ [member custom_integrator] 属性ç¦"
+"用默认行为,为物体施加完全自定义的åˆåŠ›ã€‚"
#: doc/classes/RigidBody.xml
msgid ""
@@ -66283,7 +66526,7 @@ msgid ""
"position uses the rotation of the global coordinate system, but is centered "
"at the object's origin."
msgstr ""
-"对物体施加一个有å‘的冲é‡ã€‚冲釿˜¯ä¸Žæ—¶é—´æ— å…³çš„! 在æ¯ä¸€å¸§ä¸­æ–½åŠ ä¸€ä¸ªå†²é‡å°†äº§ç”Ÿä¸€"
+"对物体施加一个有å‘的冲é‡ã€‚冲釿˜¯ä¸Žæ—¶é—´æ— å…³çš„ï¼åœ¨æ¯ä¸€å¸§ä¸­æ–½åŠ ä¸€ä¸ªå†²é‡å°†äº§ç”Ÿä¸€"
"个与帧率相关的力。出于这个原因,它应该åªåœ¨æ¨¡æ‹Ÿä¸€æ¬¡æ€§å½±å“时使用。该ä½ç½®ä½¿ç”¨å…¨"
"局忠‡ç³»çš„æ—‹è½¬ï¼Œä½†ä»¥ç‰©ä½“的原点为中心。"
@@ -66526,12 +66769,12 @@ msgid ""
"[code]body[/code] the [Node], if it exists in the tree, of the other "
"[PhysicsBody] or [GridMap]."
msgstr ""
-"当与å¦ä¸€ä¸ª[PhysicsBody]或[GridMap]å‘生碰撞时触å‘。需è¦å°†[member "
-"contact_monitor]设置为 [code]true[/code],并且将[member contacts_reported]设"
-"置得足够高以检测所有的碰撞。如果[MeshLibrary]有碰撞[Shape],[GridMap]就会被检"
-"测到。\n"
-"[code]body[/code]的[Node],如果它存在于树中,则是其他[PhysicsBody]或[GridMap]"
-"的节点。"
+"当与å¦ä¸€ä¸ª [PhysicsBody] 或 [GridMap] å‘生碰撞时触å‘。需è¦å°† [member "
+"contact_monitor] 设置为 [code]true[/code],并且将 [member contacts_reported] "
+"设置得足够高以检测所有的碰撞。如果 [MeshLibrary] 有碰撞 [Shape],[GridMap] 就"
+"会被检测到。\n"
+"[code]body[/code] 的 [Node],如果它存在于树中,则是其他 [PhysicsBody] 或 "
+"[GridMap] 的节点。"
#: doc/classes/RigidBody.xml
msgid ""
@@ -66542,12 +66785,12 @@ msgid ""
"[code]body[/code] the [Node], if it exists in the tree, of the other "
"[PhysicsBody] or [GridMap]."
msgstr ""
-"当与å¦ä¸€ä¸ª[PhysicsBody]或[GridMap]çš„ç¢°æ’žç»“æŸæ—¶è§¦å‘。需è¦å°†[member "
-"contact_monitor]设置为 [code]true[/code],并且将[member contacts_reported]设"
-"置得足够高以检测到所有的碰撞。如果[MeshLibrary]有碰撞[Shape],[GridMap]就会被"
-"检测到。\n"
-"[code]body[/code]的[Node],如果它存在于树中,则是其他[PhysicsBody]或[GridMap]"
-"的节点。"
+"当与å¦ä¸€ä¸ª [PhysicsBody]或 [GridMap] çš„ç¢°æ’žç»“æŸæ—¶è§¦å‘。需è¦å°† [member "
+"contact_monitor] 设置为 [code]true[/code],并且将 [member contacts_reported] "
+"设置得足够高以检测到所有的碰撞。如果 [MeshLibrary] 有碰撞 [Shape],[GridMap] "
+"就会被检测到。\n"
+"[code]body[/code]的[Node],如果它存在于树中,则是其他 [PhysicsBody] 或 "
+"[GridMap] 的节点。"
#: doc/classes/RigidBody.xml
msgid ""
@@ -66640,35 +66883,34 @@ msgid ""
"engine or [code]emit_signal(\"sleeping_state_changed\")[/code] is used."
msgstr ""
"当物ç†å¼•擎改å˜ç‰©ä½“çš„ç¡çœ çŠ¶æ€æ—¶å‘出。\n"
-"[b]注æ„:[/b]改å˜[member sleeping]的值ä¸ä¼šè§¦å‘这个信å·ã€‚åªæœ‰å½“物ç†å¼•擎改å˜äº†"
-"ç¡çœ çŠ¶æ€æˆ–者使用了[code]emit_signal(\"sleeping_state_changed\")[/code]时,它"
-"æ‰ä¼šè¢«å‘出。"
+"[b]注æ„:[/b]æ”¹å˜ [member sleeping] 的值ä¸ä¼šè§¦å‘这个信å·ã€‚åªæœ‰å½“物ç†å¼•擎改å˜"
+"了ç¡çœ çŠ¶æ€æˆ–者使用了 [code]emit_signal(\"sleeping_state_changed\")[/code] "
+"时,它æ‰ä¼šè¢«å‘出。"
#: doc/classes/RigidBody.xml
msgid ""
"Rigid body mode. This is the \"natural\" state of a rigid body. It is "
"affected by forces, and can move, rotate, and be affected by user code."
msgstr ""
-"刚体模å¼ã€‚这是一个刚体的 \"自然 \"状æ€ã€‚它å—到力的影å“,å¯ä»¥ç§»åŠ¨ã€æ—‹è½¬ï¼Œå¹¶å—"
-"到用户代ç çš„å½±å“。"
+"刚体模å¼ã€‚这是一个刚体的“自然â€çжæ€ã€‚它å—到力的影å“,å¯ä»¥ç§»åŠ¨ã€æ—‹è½¬ï¼Œå¹¶å—到用"
+"户代ç çš„å½±å“。"
#: doc/classes/RigidBody.xml
msgid ""
"Static mode. The body behaves like a [StaticBody], and can only move by user "
"code."
-msgstr "陿­¢æ¨¡å¼ã€‚实体的行为就åƒä¸€ä¸ª[StaticBody],åªèƒ½é€šè¿‡ç”¨æˆ·ä»£ç ç§»åŠ¨ã€‚"
+msgstr "陿­¢æ¨¡å¼ã€‚该实体的行为与 [StaticBody] 类似,åªèƒ½è¢«ç”¨æˆ·ä»£ç ç§»åŠ¨ã€‚"
#: doc/classes/RigidBody.xml
msgid ""
"Character body mode. This behaves like a rigid body, but can not rotate."
-msgstr "角色模å¼ã€‚这与刚体的行为类似,但ä¸èƒ½æ—‹è½¬ã€‚"
+msgstr "角色模å¼ã€‚与刚体的行为类似,但ä¸èƒ½æ—‹è½¬ã€‚"
#: doc/classes/RigidBody.xml
msgid ""
"Kinematic body mode. The body behaves like a [KinematicBody], and can only "
"move by user code."
-msgstr ""
-"è¿åŠ¨ä½“æ¨¡å¼ã€‚这个实体的行为就åƒä¸€ä¸ª[KinematicBody],åªèƒ½é€šè¿‡ç”¨æˆ·ä»£ç æ¥ç§»åŠ¨ã€‚"
+msgstr "è¿åŠ¨ä½“æ¨¡å¼ã€‚该实体的行为与 [KinematicBody] 类似,åªèƒ½è¢«ç”¨æˆ·ä»£ç ç§»åŠ¨ã€‚"
#: doc/classes/RigidBody2D.xml
msgid "A body that is controlled by the 2D physics engine."
@@ -66706,7 +66948,7 @@ msgstr ""
"è¦è®°ä½ï¼Œç‰©ç†ç‰©ä½“在自己管ç†å˜æ¢ï¼Œå®ƒä¼šè¦†ç›–ä½ çš„å˜æ¢è®¾ç½®ã€‚所以任何直接或间接的å˜"
"æ¢ï¼ˆåŒ…括节点或其父级的缩放)将åªåœ¨ç¼–辑器中å¯è§ï¼Œå¹¶åœ¨è¿è¡Œæ—¶ç«‹å³é‡ç½®ã€‚\n"
"如果你需è¦è¦†ç›–默认的物ç†è¡Œä¸ºæˆ–者在è¿è¡Œæ—¶æ·»åŠ å˜æ¢ï¼Œä½ å¯ä»¥å†™ä¸€ä¸ªè‡ªå®šä¹‰çš„åˆåŠ›ã€‚"
-"å‚阅 [member custom_integrator]。\n"
+"è§ [member custom_integrator]。\n"
"è´¨é‡ä¸­å¿ƒæ€»æ˜¯ä½äºŽèŠ‚ç‚¹çš„åŽŸç‚¹ï¼Œè€Œä¸è€ƒè™‘ [CollisionShape2D] 中心点的å移。"
#: doc/classes/RigidBody2D.xml
@@ -66726,10 +66968,10 @@ msgid ""
"custom_integrator] allows you to disable the default behavior and write "
"custom force integration for a body."
msgstr ""
-"å…许你读å–并安全地修改对象的模拟状æ€ã€‚如果你需è¦ç›´æŽ¥æ”¹å˜ç‰©ä½“çš„"
-"[code]position[/code]或其他物ç†å±žæ€§ï¼Œè¯·ä½¿ç”¨å®ƒä»£æ›¿[method Node."
-"_physics_process]。默认情况下,它是在通常的物ç†è¡Œä¸ºä¹‹å¤–工作的,但是[member "
-"custom_integrator]å…许你ç¦ç”¨é»˜è®¤è¡Œä¸ºå¹¶ä¸ºä¸€ä¸ªç‰©ä½“编写自定义的åˆåŠ›ã€‚"
+"å…许你读å–并安全地修改对象的模拟状æ€ã€‚如果你需è¦ç›´æŽ¥æ”¹å˜ç‰©ä½“çš„ "
+"[code]position[/code] 或其他物ç†å±žæ€§ï¼Œè¯·ä½¿ç”¨å®ƒä»£æ›¿ [method Node."
+"_physics_process]。默认情况下,它是在通常的物ç†è¡Œä¸ºä¹‹å¤–工作的,但是 [member "
+"custom_integrator] å…许你ç¦ç”¨é»˜è®¤è¡Œä¸ºå¹¶ä¸ºä¸€ä¸ªç‰©ä½“编写自定义的åˆåŠ›ã€‚"
#: doc/classes/RigidBody2D.xml
msgid ""
@@ -66740,8 +66982,8 @@ msgid ""
"global coordinate system, but is centered at the object's origin."
msgstr ""
"对物体施加一个有å‘的冲é‡ã€‚冲釿˜¯ä¸Žæ—¶é—´æ— å…³çš„。æ¯ä¸€å¸§åº”用一个冲é‡ä¼šæœ‰ä¸€ä¸ªä¸Žå¸§"
-"相关的力。由于这个原因,它åªåº”该在模拟一次性冲击时使用(å¦åˆ™å°±ä½¿ç”¨\"_force "
-"\"函数)。ä½ç½®ä½¿ç”¨å…¨å±€å标系的旋转,但以物体的原点为中心。"
+"相关的力。由于这个原因,它åªåº”该在模拟一次性冲击时使用(å¦åˆ™å°±ä½¿ç”¨â€œ_forceâ€å‡½"
+"数)。ä½ç½®ä½¿ç”¨å…¨å±€å标系的旋转,但以物体的原点为中心。"
#: doc/classes/RigidBody2D.xml
msgid ""
@@ -66807,8 +67049,8 @@ msgid ""
"If [code]true[/code], the body will emit signals when it collides with "
"another RigidBody2D. See also [member contacts_reported]."
msgstr ""
-"如果为 [code]true[/code],则物体在与å¦ä¸€ä¸ªRigidBody2D碰撞时会å‘出信å·ã€‚å‚阅"
-"[member contacts_reported]。"
+"如果为 [code]true[/code],则物体在与å¦ä¸€ä¸ª RigidBody2D 碰撞时会å‘出信å·ã€‚å¦è¯·"
+"å‚阅 [member contacts_reported]。"
#: doc/classes/RigidBody2D.xml
msgid ""
@@ -66864,7 +67106,7 @@ msgid ""
"from the [b]Default Gravity[/b] value in [b]Project > Project Settings > "
"Physics > 2d[/b] and/or any additional gravity vector applied by [Area2D]s."
msgstr ""
-"乘以施加在物体上的é‡åŠ›ã€‚ç‰©ä½“çš„é‡åŠ›æ˜¯ç”±[b]项目 > 项目设置 > ç‰©ç† > 2D[/b]中的"
+"乘以施加在物体上的é‡åŠ›ã€‚ç‰©ä½“çš„é‡åŠ›æ˜¯ç”±[b]项目 > 项目设置 > ç‰©ç† > 2D[/b] 中的"
"[b]默认é‡åŠ›[/b]值和/或任何由 [Area2D] 应用的é¢å¤–é‡åŠ›å‘é‡è®¡ç®—出æ¥çš„。"
#: doc/classes/RigidBody2D.xml
@@ -66901,7 +67143,7 @@ msgid ""
"thread and runs at a different granularity. Use [method _integrate_forces] "
"as your process loop for precise control of the body state."
msgstr ""
-"该实体的线速度,å•ä½ä¸ºåƒç´ æ¯ç§’。å¯ä»¥å¶å°”使用,但是[b]ä¸è¦æ¯ä¸€å¸§éƒ½è®¾ç½®å®ƒ[/b],"
+"该实体的线速度,å•ä½ä¸ºåƒç´ æ¯ç§’。å¯ä»¥å¶å°”使用,但是[b]ä¸è¦æ¯ä¸€å¸§éƒ½åŽ»è®¾ç½®[/b],"
"因为物ç†å¯èƒ½åœ¨å¦ä¸€ä¸ªçº¿ç¨‹ä¸­è¿è¡Œï¼Œå¹¶ä¸”以ä¸åŒçš„间隔。使用 [method "
"_integrate_forces] 作为你的进程循环,以精确控制物体状æ€ã€‚"
@@ -66926,11 +67168,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 +67244,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 ""
@@ -67026,20 +67271,20 @@ msgstr ""
#: doc/classes/RigidBody2D.xml
msgid "Static mode. The body behaves like a [StaticBody2D] and does not move."
-msgstr "陿€æ¨¡å¼ã€‚物体的行为就åƒä¸€ä¸ª[StaticBody2D],ä¸ä¼šç§»åŠ¨ã€‚"
+msgstr "陿€æ¨¡å¼ã€‚该物体的行为与 [StaticBody2D] 类似,ä¸ä¼šç§»åŠ¨ã€‚"
#: doc/classes/RigidBody2D.xml
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,18 +67298,17 @@ 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."
-msgstr "Room 节点,用于在本地将对象组åˆåœ¨ä¸€èµ·ä»¥è¿›è¡Œ [Portal] 剔除。"
+msgstr "房间节点,用于在本地将对象组åˆåœ¨ä¸€èµ·ä»¥è¿›è¡Œ [Portal] 剔除。"
#: doc/classes/Room.xml
msgid ""
@@ -67205,7 +67449,7 @@ msgid ""
"before unloading a level, when transitioning from level to level, or "
"returning to a main menu."
msgstr ""
-"该方法会从 [b]portal graph[/b] æ¸…é™¤æ‰€æœ‰è½¬æ¢æ•°æ®ã€‚在å¸è½½å…³å¡ã€ä»Žå…³å¡è½¬æ¢åˆ°å…³å¡"
+"该方法会清除 [b]room graph[/b] ä¸­æ‰€æœ‰çš„è½¬æ¢æ•°æ®ã€‚在å¸è½½å…³å¡ã€ä»Žå…³å¡è½¬æ¢åˆ°å…³å¡"
"或返回主èœå•时使用此选项。"
#: doc/classes/RoomManager.xml
@@ -67305,7 +67549,7 @@ msgstr ""
"建议您仅将对象放置在希望留在这些空间内的空间中 - å³ [code]portal mode[/code]"
"是 [code]STATIC[/code] 或 [code]DYNAMIC[/code](ä¸ç©¿è¶Š Portal)。"
"[code]GLOBAL[/code] å’Œ [code]ROAMING[/code] 对象最好放置在场景树的å¦ä¸€éƒ¨åˆ†ï¼Œ"
-"以é¿å…混淆。有关portal模å¼çš„完整说明,请å‚阅 [CullInstance]。"
+"以é¿å…混淆。有关 portal 模å¼çš„完整说明,请å‚阅 [CullInstance]。"
#: doc/classes/RoomManager.xml
msgid ""
@@ -67611,8 +67855,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 +67884,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 +67964,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 +68001,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 +68202,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 +68218,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 +68560,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 +68586,7 @@ msgstr "以更高的分辨率渲染拉伸(æ’值)。"
msgid ""
"Keep the specified display resolution. No interpolation. Content may appear "
"pixelated."
-msgstr "ä¿æŒæŒ‡å®šçš„æ˜¾ç¤ºåˆ†è¾¨çŽ‡ã€‚æ²¡æœ‰æ’值。内容å¯èƒ½ä¼šå‡ºçްåƒç´ åŒ–。"
+msgstr "ä¿æŒæŒ‡å®šçš„æ˜¾ç¤ºåˆ†è¾¨çŽ‡ã€‚ä¸åšæ’值。内容å¯èƒ½ä¼šå‡ºçްåƒç´ åŒ–。"
#: doc/classes/SceneTree.xml
msgid ""
@@ -68360,13 +68604,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 +68637,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"
@@ -68421,7 +68665,6 @@ msgid ""
msgstr "通过脚本进行通用动画的轻é‡çº§å¯¹è±¡ï¼Œä½¿ç”¨ [Tweener]。"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"[SceneTreeTween] is a tween managed by the scene tree. As opposed to "
"[Tween], it does not require the instantiation of a node.\n"
@@ -68503,21 +68746,21 @@ msgstr ""
"建 [SceneTreeTween]。手动创建的 [SceneTreeTween](å³ä½¿ç”¨ [code]Tween.new()[/"
"code])是无效的,ä¸èƒ½ç”¨äºŽå¯¹å€¼è¿›è¡Œè¡¥é—´ï¼Œä½†ä½ å¯ä»¥ç”¨ [method interpolate_value] "
"æ¥æ‰‹åЍæ’值。\n"
-"[SceneTreeTween] 动画是由 [Tweener] åºåˆ—æž„æˆçš„,默认串行执行。å‘该 "
-"[SceneTreeTween] 追加 [Tweener] å³å¯åˆ›å»ºåºåˆ—。使用 [Tweener] æ¥åšåŠ¨ç”»å°±å«åšè¡¥"
-"间(Tweening)。示例补间åºåˆ—是类似这样的:\n"
+"è¡¥é—´åŠ¨ç”»æ˜¯é€šè¿‡å‘ [SceneTreeTween] 对象中添加 [Tweener] 创建的,添加的方法有 "
+"[method tween_property]ã€[method tween_interval]ã€[method tween_callback]ã€"
+"[method tween_method]:\n"
"[codeblock]\n"
"var tween = get_tree().create_tween()\n"
"tween.tween_property($Sprite, \"modulate\", Color.red, 1)\n"
"tween.tween_property($Sprite, \"scale\", Vector2(), 1)\n"
"tween.tween_callback($Sprite, \"queue_free\")\n"
"[/codeblock]\n"
-"这个åºåˆ—会让 [code]$Sprite[/code] å˜çº¢ï¼Œç„¶åŽç¼©å°ï¼Œæœ€åŽè°ƒç”¨ [method Node."
-"queue_free] æ¥ç§»é™¤ç²¾çµã€‚更多用法信æ¯è¯·å‚阅 [method tween_property]ã€[method "
-"tween_interval]ã€[method tween_callback]ã€[method tween_method] 方法。\n"
+"这个åºåˆ—会让 [code]$Sprite[/code] å˜çº¢ï¼Œç„¶åŽç¼©å°ï¼Œæœ€åŽå†è°ƒç”¨ [method Node."
+"queue_free] æ¥é‡Šæ”¾è¯¥ç²¾çµã€‚[Tweener] 默认是一个接一个执行的。这个行为å¯ä»¥é€šè¿‡ "
+"[method parallel] 和 [method set_parallel] 更改。\n"
"使用 [code]tween_*[/code] 方法创建 [Tweener] åŽï¼Œå¯ä»¥ä½¿ç”¨é“¾å¼æ–¹æ³•调用æ¥è°ƒæ•´"
"该 [Tweener] 的属性。例如,如果你想è¦åœ¨ä¸Šé¢çš„例å­ä¸­è®¾ç½®ä¸åŒçš„过渡类型,那么你"
-"å¯ä»¥ï¼š\n"
+"å¯ä»¥ä½¿ç”¨ [method set_trans]:\n"
"[codeblock]\n"
"var tween = get_tree().create_tween()\n"
"tween.tween_property($Sprite, \"modulate\", Color.red, 1).set_trans(Tween."
@@ -68526,8 +68769,9 @@ msgstr ""
"TRANS_BOUNCE)\n"
"tween.tween_callback($Sprite, \"queue_free\")\n"
"[/codeblock]\n"
-"[SceneTreeTween] 的大部分方法都å¯ä»¥ç”¨è¿™ç§æ–¹æ³•进行链å¼è°ƒç”¨ã€‚在这个示例中,我们"
-"对该 [SceneTreeTween] 进行了绑定,并设置了默认的过渡:\n"
+"[SceneTreeTween] 的大部分方法都å¯ä»¥ç”¨è¿™ç§æ–¹æ³•进行链å¼è°ƒç”¨ã€‚在下é¢çš„示例中,我"
+"们将该 [SceneTreeTween] 绑定到了执行脚本的节点,并为其 [Tweener] 设置了默认的"
+"过渡:\n"
"[codeblock]\n"
"var tween = get_tree().create_tween().bind_node(self).set_trans(Tween."
"TRANS_ELASTIC)\n"
@@ -68539,7 +68783,7 @@ msgstr ""
"[codeblock]\n"
"var tween = create_tween()\n"
"for sprite in get_children():\n"
-" tween.tween_property(sprite, \"position\", Vector2(), 1)\n"
+" tween.tween_property(sprite, \"position\", Vector2(0, 0), 1)\n"
"[/codeblock]\n"
"上é¢çš„示例中,该节点的所有å­èŠ‚ç‚¹éƒ½ä¼šä¾æ¬¡è¢«ç§»åŠ¨åˆ° (0, 0)。\n"
"一些 [Tweener] 会用到过渡和缓动。å‰è€…æŽ¥å— [enum Tween.TransitionType] 常é‡ï¼Œ"
@@ -68593,7 +68837,6 @@ msgstr ""
"[/codeblock]"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Processes the [SceneTreeTween] by the given [code]delta[/code] value, in "
"seconds. This is mostly useful for manual control when the [SceneTreeTween] "
@@ -68608,14 +68851,14 @@ msgid ""
msgstr ""
"使用给定的增é‡ç§’æ•° [code]delta[/code] 处ç†è¯¥ [SceneTreeTween]。最常è§çš„用法是"
"在该 [SceneTreeTween] æš‚åœæ—¶å¯¹å…¶è¿›è¡Œæ‰‹åŠ¨æŽ§åˆ¶ã€‚ä¹Ÿå¯ç”¨äºŽç«‹å³åœæ­¢è¯¥ "
-"[SceneTreeTween] 的动画,使用比完整长度更大的 [code]delta[/code] å³å¯ã€‚\n"
+"[SceneTreeTween] 的动画,将 [code]delta[/code] 设得比完整长度更大å³å¯ã€‚\n"
"如果该 [SceneTreeTween] ä»ç„¶æœ‰æœªå®Œæˆçš„ [Tweener],则返回 [code]true[/"
"code]。\n"
-"[b]注æ„:[/b]该 [SceneTreeTween] 在完æˆåŽä¼šå¤±æ•ˆï¼Œä½†ä½ å¯ä»¥åœ¨ step åŽè°ƒç”¨ "
-"[method stop] 将其ä¿ç•™å¹¶é‡ç½®ã€‚"
+"[b]注æ„:[/b]该 [SceneTreeTween] 完æˆåŠ¨ç”»åŽï¼Œä¼šåœ¨ä¸‹ä¸€ä¸ªå¤„ç†å¸§ä¸­å¤±æ•ˆã€‚ä½ å¯ä»¥åœ¨"
+"执行 [method custom_step] åŽè°ƒç”¨ [method stop] 将该 [SceneTreeTween] ä¿ç•™å¹¶é‡"
+"置。"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Returns the total time in seconds the [SceneTreeTween] has been animating (i."
"e. the time since it started, not counting pauses etc.). The time is "
@@ -68669,20 +68912,20 @@ msgid ""
msgstr "返回该 [SceneTreeTween] ç›®å‰æ˜¯å¦æ­£åœ¨æ‰§è¡Œï¼Œå³æœªæš‚åœä¸”未完æˆã€‚"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Returns whether the [SceneTreeTween] is valid. A valid [SceneTreeTween] is a "
"[SceneTreeTween] contained by the scene tree (i.e. the array from [method "
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
"返回该 [SceneTreeTween] æ˜¯å¦æœ‰æ•ˆã€‚有效的 [SceneTreeTween] 是由场景树包å«çš„ "
"[SceneTreeTween]ï¼ˆå³ [method SceneTree.get_processed_tweens] 返回的数组中包å«"
"这个 [SceneTreeTween])。[SceneTreeTween] 失效的情况有:补间完æˆã€è¢«é”€æ¯ã€ä½¿"
-"用 [code]Tween.new()[/code] 创建。无效的 [SceneTreeTween] ä¸èƒ½è¿½åŠ  "
-"[Tweener],因为无法进行动画。ä¸è¿‡ [method interpolate_value] 还是å¯ä»¥ä½¿ç”¨çš„。"
+"用 [code]SceneTreeTween.new()[/code] 创建。无效的 [SceneTreeTween] ä¸èƒ½è¿½åŠ  "
+"[Tweener]。但你ä»ç„¶èƒ½å¤Ÿä½¿ç”¨ [method interpolate_value]。"
#: doc/classes/SceneTreeTween.xml
msgid "Aborts all tweening operations and invalidates the [SceneTreeTween]."
@@ -68729,28 +68972,28 @@ msgstr ""
"的默认缓动类型。"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
"è¿™åªè¯¥è¡¥é—´åºåˆ—çš„é‡å¤æ¬¡æ•°ï¼Œå³ [code]set_loops(2)[/code] 会让动画执行两次。\n"
"调用这个方法时如果ä¸å¸¦å‚数,那么该 [SceneTreeTween] ä¼šæ— é™æ‰§è¡Œï¼Œç›´åˆ°è¢« "
-"[method kill] 销æ¯ã€ç»‘å®šèŠ‚ç‚¹è¢«é‡Šæ”¾ã€æˆ–者所有进行动画的对象都被释放(无法å†è¿›"
-"行任何动画)。\n"
-"[b]警告:[/b]使用无é™å¾ªçŽ¯æ—¶è¯·ä¸€å®šè¦åŠ å…¥ä¸€äº›æ—¶é•¿/延迟。0 时长的循环动画(例如"
-"å•个ä¸å¸¦å»¶è¿Ÿçš„ [CallbackTweener] 或者节点无效的 [PropertyTweener]ï¼‰å’Œæ— é™ "
-"[code]while[/code] 循环是一样的,会导致游æˆå†»ç»“。如果 [SceneTreeTween] 的生命"
-"期ä¾èµ–于æŸä¸ªèŠ‚ç‚¹ï¼Œè¯·ä¸€å®šä½¿ç”¨ [method bind_node]。"
+"[method kill] 销æ¯ã€è¯¥ [SceneTreeTween] ç»‘å®šçš„èŠ‚ç‚¹è¢«é‡Šæ”¾ã€æˆ–者所有进行动画的"
+"对象都被释放(无法å†è¿›è¡Œä»»ä½•动画)。\n"
+"[b]警告:[/b]使用无é™å¾ªçŽ¯æ—¶è¯·ä¸€å®šè¦åŠ å…¥ä¸€äº›æ—¶é•¿/延迟。为了防止游æˆå†»ç»“,0 æ—¶"
+"长的循环动画(例如å•个ä¸å¸¦å»¶è¿Ÿçš„ [CallbackTweener])会在循环若干次åŽåœæ­¢ï¼Œé€ "
+"æˆå‡ºä¹Žé¢„料的结果。如果 [SceneTreeTween] 的生命期ä¾èµ–于æŸä¸ªèŠ‚ç‚¹ï¼Œè¯·ä¸€å®šä½¿ç”¨ "
+"[method bind_node]。"
#: doc/classes/SceneTreeTween.xml
msgid ""
@@ -68834,7 +69077,6 @@ msgstr ""
"[/codeblock]"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Creates and appends an [IntervalTweener]. This method can be used to create "
"delays in the tween animation, as an alternative to using the delay in other "
@@ -68931,7 +69173,6 @@ msgstr ""
"[/codeblock]"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Creates and appends a [PropertyTweener]. This method tweens a "
"[code]property[/code] of an [code]object[/code] between an initial value and "
@@ -68965,7 +69206,7 @@ msgstr ""
"创建并追加一个 [PropertyTweener]。这个方法会将 [code]object[/code] 对象的 "
"[code]property[/code] 属性在åˆå§‹å€¼å’Œæœ€ç»ˆå€¼ [code]final_val[/code] 之间进行补"
"间,æŒç»­æ—¶é—´ä¸º [code]duration[/code] 秒。åˆå§‹å€¼é»˜è®¤ä¸ºè¯¥ [PropertyTweener] å¯"
-"动时的值。例如:\n"
+"动时该属性的值。例如:\n"
"[codeblock]\n"
"var tween = create_tween()\n"
"tween.tween_property($Sprite, \"position\", Vector2(100, 200), 1)\n"
@@ -68987,7 +69228,6 @@ msgstr ""
"[/codeblock]"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Emitted when the [SceneTreeTween] has finished all tweening. Never emitted "
"when the [SceneTreeTween] is set to infinite looping (see [method "
@@ -68998,12 +69238,11 @@ msgid ""
msgstr ""
"在该 [SceneTreeTween] å®Œæˆæ‰€æœ‰è¡¥é—´æ—¶è§¦å‘。该 [SceneTreeTween] 被设为无é™å¾ªçޝ"
"æ—¶ä¸ä¼šè§¦å‘ï¼ˆè§ [method set_loops])。\n"
-"[b]注æ„:[/b]触å‘这个信å·åŽï¼Œè¯¥ [SceneTreeTween] ä¼šè¢«ç§»é™¤ï¼ˆç½®ä¸ºæ— æ•ˆï¼‰ï¼Œä½†ä¸æ˜¯"
-"ç«‹å³å‘生的,而是在下一个处ç†å¸§ä¸­å‘生。在该信å·çš„回调中调用 [method stop] 会ä¿"
-"留该 [SceneTreeTween]。"
+"[b]注æ„:[/b]触å‘这个信å·åŽï¼Œè¯¥ [SceneTreeTween] 会在下一个处ç†å¸§ä¸­è¢«ç§»é™¤ï¼ˆç½®"
+"为无效)。在该信å·çš„回调中调用 [method stop] å¯ä»¥é˜²æ­¢è¯¥ [SceneTreeTween] 被移"
+"除。"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Emitted when a full loop is complete (see [method set_loops]), providing the "
"loop index. This signal is not emitted after the final loop, use [signal "
@@ -69013,7 +69252,6 @@ msgstr ""
"会在最åŽä¸€æ¬¡å¾ªçޝåŽè§¦å‘ï¼Œè¿™ç§æƒ…况请使用 [signal finished] 代替。"
#: doc/classes/SceneTreeTween.xml
-#, fuzzy
msgid ""
"Emitted when one step of the [SceneTreeTween] is complete, providing the "
"step index. One step is either a single [Tweener] or a group of [Tweener]s "
@@ -69693,7 +69931,7 @@ msgstr ""
#: doc/classes/Shape2D.xml
msgid "The shape's custom solver bias."
-msgstr "形状的自定义求解器å差。"
+msgstr "形状的自定义求解器å置。"
#: doc/classes/ShortCut.xml
msgid "A shortcut for binding input."
@@ -70592,13 +70830,13 @@ msgstr "å¯ç”¨æ­¤èŠ‚ç‚¹çš„å‘ˆçŽ°ã€‚å°† [member visible] 更改为 [code]true[/co
msgid ""
"Transforms [code]local_point[/code] from this node's local space to world "
"space."
-msgstr "å°† [code]local_point[/code] 从该节点的本地空间转æ¢ä¸ºä¸–界空间。"
+msgstr "å°† [code]local_point[/code] 从这个节点的局部空间转æ¢ä¸ºä¸–界空间。"
#: doc/classes/Spatial.xml
msgid ""
"Transforms [code]global_point[/code] from world space to this node's local "
"space."
-msgstr "å°† [code]global_point[/code] 从世界空间转æ¢åˆ°è¿™ä¸ªèŠ‚ç‚¹çš„æœ¬åœ°ç©ºé—´ã€‚"
+msgstr "å°† [code]global_point[/code] 从世界空间转æ¢åˆ°è¿™ä¸ªèŠ‚ç‚¹çš„å±€éƒ¨ç©ºé—´ã€‚"
#: doc/classes/Spatial.xml
msgid ""
@@ -70608,7 +70846,7 @@ msgid ""
"offset of [code](2, 0, 0)[/code] would actually add 20 ([code]2 * 10[/code]) "
"to the X coordinate."
msgstr ""
-"通过给定的åç§»é‡ [Vector3] 改å˜èŠ‚ç‚¹çš„ä½ç½®ã€‚\n"
+"通过给定的åç§»é‡ [Vector3] 改å˜è¯¥èŠ‚ç‚¹çš„ä½ç½®ã€‚\n"
"注æ„,平移 [code]offset[/code] å—节点缩放的影å“,所以如果按例如 [code]"
"(10,1,1)[/code] 进行缩放,平移 [code](2,0,0)[/code] 实际上会在 X åæ ‡ä¸Šå¢žåŠ  "
"20 ([code]2 * 10[/code])。"
@@ -70616,23 +70854,48 @@ msgstr ""
#: doc/classes/Spatial.xml
msgid ""
"Changes the node's position by the given offset [Vector3] in local space."
-msgstr "通过给定的åç§»é‡ [Vector3] 改å˜èŠ‚ç‚¹åœ¨å±€éƒ¨ç©ºé—´ä¸­çš„ä½ç½®ã€‚"
+msgstr "通过给定的局部空间åç§»é‡ [Vector3] 改å˜è¯¥èŠ‚ç‚¹çš„ä½ç½®ã€‚"
#: doc/classes/Spatial.xml
msgid "Updates the [SpatialGizmo] of this node."
-msgstr "更新该节点的 [SpatialGizmo]。"
+msgstr "更新这个节点的 [SpatialGizmo]。"
#: doc/classes/Spatial.xml
msgid ""
"The [SpatialGizmo] for this node. Used for example in [EditorSpatialGizmo] "
"as custom visualization and editing handles in Editor."
msgstr ""
-"此节点的 [SpatialGizmo]。例如在 [EditorSpatialGizmo] 中用作编辑器中的自定义å¯"
-"视化和编辑手柄。"
+"这个节点的 [SpatialGizmo]。例如在 [EditorSpatialGizmo] 中用作编辑器中的自定义"
+"å¯è§†åŒ–和编辑手柄。"
+
+#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+"å…¨å±€å˜æ¢çš„æ—‹è½¬éƒ¨åˆ†ï¼Œå•ä½ä¸ºå¼§åº¦ï¼Œä»¥ YXZ 欧拉角的形å¼è¡¨ç¤ºï¼ˆX è§’ã€Y è§’ã€Z "
+"角)。\n"
+"[b]注æ„:[/b]在数学æ„ä¹‰ä¸Šï¼Œæ—‹è½¬æ˜¯ä¸€ä¸ªçŸ©é˜µè€Œä¸æ˜¯ä¸€ä¸ªå‘é‡ã€‚这三个欧拉角是旋转矩"
+"é˜µæ¬§æ‹‰è§’å‚æ•°åŒ–çš„ä¸‰ä¸ªç‹¬ç«‹å‚æ•°ï¼Œå­˜å‚¨åœ¨ [Vector3] æ•°æ®ç»“æž„ä¸­å¹¶ä¸æ˜¯å› ä¸ºæ—‹è½¬æ˜¯ä¸€ä¸ª"
+"矢é‡ï¼Œè€Œæ˜¯å› ä¸º [Vector3] æ˜¯ä¸€ç§æ–¹ä¾¿å­˜å‚¨ 3 个浮点数的数æ®ç»“构。因此,对旋转“å‘"
+"é‡â€åº”用仿射æ“作是没有æ„义的。"
#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
-msgstr "此节点的世界空间(全局)[Transform]。"
+msgstr "è¿™ä¸ªèŠ‚ç‚¹çš„ä¸–ç•Œç©ºé—´ï¼ˆå…¨å±€ï¼‰å˜æ¢ [Transform]。"
+
+#: doc/classes/Spatial.xml
+msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr "这个节点的全局ä½ç½®ã€‚与 [code]global_transform.origin[/code] 等价。"
#: doc/classes/Spatial.xml
msgid ""
@@ -70646,7 +70909,7 @@ msgid ""
"point numbers. Therefore, applying affine operations on the rotation "
"\"vector\" is not meaningful."
msgstr ""
-"å±€éƒ¨å˜æ¢çš„æ—‹è½¬éƒ¨åˆ†ä»¥å¼§åº¦è¡¨ç¤ºï¼Œä»¥ YXZ-Euler 角的形å¼è¡¨ç¤ºï¼ˆX è§’ã€Y è§’ã€Z "
+"å±€éƒ¨å˜æ¢çš„æ—‹è½¬éƒ¨åˆ†ï¼Œå•ä½ä¸ºå¼§åº¦ï¼Œä»¥ YXZ 欧拉角的形å¼è¡¨ç¤ºï¼ˆX è§’ã€Y è§’ã€Z "
"角)。\n"
"[b]注æ„:[/b]在数学æ„ä¹‰ä¸Šï¼Œæ—‹è½¬æ˜¯ä¸€ä¸ªçŸ©é˜µè€Œä¸æ˜¯ä¸€ä¸ªå‘é‡ã€‚这三个欧拉角是旋转矩"
"é˜µæ¬§æ‹‰è§’å‚æ•°åŒ–çš„ä¸‰ä¸ªç‹¬ç«‹å‚æ•°ï¼Œå­˜å‚¨åœ¨ [Vector3] æ•°æ®ç»“æž„ä¸­å¹¶ä¸æ˜¯å› ä¸ºæ—‹è½¬æ˜¯ä¸€ä¸ª"
@@ -70667,17 +70930,17 @@ msgid ""
"transformation matrices in Godot, the scale values will either be all "
"positive or all negative."
msgstr ""
-"æœ¬åœ°å˜æ¢ä¸­çš„缩放。\n"
+"å±€éƒ¨å˜æ¢çš„缩放部分。\n"
"[b]注æ„:[/b]3D ä¸­ï¼Œå˜æ¢çŸ©é˜µæ˜¯æ— æ³•分解出正负混åˆçš„缩放的。由于 Godot 中使用å˜"
"æ¢çŸ©é˜µæ¥è¡¨ç¤ºç¼©æ”¾ï¼Œå¾—到的缩放值è¦ä¹ˆå…¨æ­£ã€è¦ä¹ˆå…¨è´Ÿã€‚"
#: doc/classes/Spatial.xml
msgid "Local space [Transform] of this node, with respect to the parent node."
-msgstr "该节点相对于父节点的局部空间 [Transform]。"
+msgstr "这个节点相对于父节点的局部空间 [Transform]。"
#: doc/classes/Spatial.xml
msgid "Local translation of this node."
-msgstr "æ­¤èŠ‚ç‚¹çš„å±€éƒ¨å˜æ¢ã€‚"
+msgstr "è¿™ä¸ªèŠ‚ç‚¹çš„å±€éƒ¨å˜æ¢ã€‚"
#: doc/classes/Spatial.xml
msgid ""
@@ -72648,16 +72911,16 @@ msgstr "ç²¾çµä¸Šä¸€ä¸ªåƒç´ å®½åº¦çš„大å°ï¼Œä»¥ 3D 缩放。"
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
"This is because opaque objects are not sorted, while transparent objects are "
"sorted from back to front (subject to priority)."
msgstr ""
-"设置精çµçš„æ¸²æŸ“优先级。优先级高的物体将被排åºåœ¨ä¼˜å…ˆçº§ä½Žçš„物体å‰é¢ã€‚\n"
-"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant ALPHA_CUT_DISABLED](默认"
-"值)时适用。\n"
+"设置该精çµçš„æ¸²æŸ“优先级。优先级高的物体将被排åºåœ¨ä¼˜å…ˆçº§ä½Žçš„物体å‰é¢ã€‚\n"
+"[b]注æ„:[/b]仅在 [member alpha_cut] 为 [constant "
+"ALPHA_CUT_DISABLED](默认值)时适用。\n"
"[b]注æ„:[/b]ä»…é€‚ç”¨äºŽé€æ˜Žç‰©ä½“的排åºã€‚è¿™ä¸ä¼šå½±å“逿˜Žç‰©ä½“相对于ä¸é€æ˜Žç‰©ä½“的排åº"
"æ–¹å¼ã€‚这是因为ä¸é€æ˜Žå¯¹è±¡ä¸è¢«æŽ’åºï¼Œè€Œé€æ˜Žå¯¹è±¡åˆ™ä»ŽåŽå¾€å‰æŽ’åºï¼ˆå–决于优先级)。"
@@ -73594,9 +73857,55 @@ 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]。"
+"æ ¼å¼åŒ–字符串,将所有的 [code]placeholder[/code] 替æ¢ä¸º [code]values[/code] 中"
+"的元素。\n"
+"[code]values[/code] å¯ä»¥æ˜¯ [Dictionary] 或 [Array]。[code]placeholder[/code] "
+"中的下划线都会事先被替æ¢ä¸ºå¯¹åº”的键。数组元素使用其索引å·ä½œä¸ºé”®ã€‚\n"
+"[codeblock]\n"
+"# 输出:Waiting for Godot 是 Samuel Beckett çš„æˆå‰§ï¼ŒGodot 引擎由此得å。\n"
+"var use_array_values = \"Waiting for {0} 是 {1} çš„æˆå‰§ï¼Œ{0} 引擎由此得"
+"å。\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# 输出:第 42 å·ç”¨æˆ·æ˜¯ Godot。\n"
+"print(\"第 {id} å·ç”¨æˆ·æ˜¯ {name}。\".format({\"id\": 42, \"name\": "
+"\"Godot\"}))\n"
+"[/codeblock]\n"
+"[code]values[/code] 为数组时还会进行一些é¢å¤–的处ç†ã€‚如果 [code]placeholder[/"
+"code] 中ä¸åŒ…å«ä¸‹åˆ’çº¿ï¼Œè¯¥æ•°ç»„ä¸­çš„å…ƒç´ ä¼šä¾æ¬¡å¯¹å‡ºçŽ°çš„å ä½ç¬¦è¿›è¡Œæ›¿æ¢ï¼›å¦‚果数组元"
+"素是一个包å«ä¸¤ä¸ªå…ƒç´ çš„æ•°ç»„,那么它就会被解释为键值对。\n"
+"[codeblock]\n"
+"# 输出:第 42 å·ç”¨æˆ·æ˜¯ Godot。\n"
+"print(\"第 {} å·ç”¨æˆ·æ˜¯ {}。\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"第 {id} å·ç”¨æˆ·æ˜¯ {name}。\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
#: doc/classes/String.xml
msgid "If the string is a valid file path, returns the base directory name."
@@ -73861,7 +74170,6 @@ msgstr ""
"[/codeblock]"
#: doc/classes/String.xml
-#, fuzzy
msgid ""
"Returns [code]true[/code] if this string contains a valid integer.\n"
"[codeblock]\n"
@@ -73874,11 +74182,11 @@ msgid ""
msgstr ""
"å¦‚æžœè¯¥å­—ç¬¦ä¸²åŒ…å«æœ‰æ•ˆçš„æ•´æ•°ï¼Œåˆ™è¿”回 [code]true[/code]\n"
"[codeblock]\n"
-"print(\"7\".is_valid_int()) # 输出“Trueâ€\n"
-"print(\"14.6\".is_valid_int()) # 输出“Falseâ€\n"
-"print(\"L\".is_valid_int()) # 输出“Falseâ€\n"
-"print(\"+3\".is_valid_int()) # 输出“Trueâ€\n"
-"print(\"-12\".is_valid_int()) # 输出“Trueâ€\n"
+"print(\"7\".is_valid_integer()) # 输出“Trueâ€\n"
+"print(\"14.6\".is_valid_integer()) # 输出“Falseâ€\n"
+"print(\"L\".is_valid_integer()) # 输出“Falseâ€\n"
+"print(\"+3\".is_valid_integer()) # 输出“Trueâ€\n"
+"print(\"-12\".is_valid_integer()) # 输出“Trueâ€\n"
"[/codeblock]"
#: doc/classes/String.xml
@@ -74414,13 +74722,16 @@ 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] 值。"
+"使用由给定的 [RID] 标识的画布项绘制这个样å¼ç›’。\n"
+"[RID] 值既å¯ä»¥é€šè¿‡å¯¹çŽ°æœ‰çš„åŸºäºŽ [CanvasItem] 节点调用 [method CanvasItem."
+"get_canvas_item] 获得,也å¯ä»¥é€šè¿‡ [method VisualServer.canvas_item_create] ç›´"
+"接在 [VisualServer] 上创建画布项获得。"
#: doc/classes/StyleBox.xml
msgid "Returns the size of this [StyleBox] without the margins."
@@ -76195,12 +76506,12 @@ msgstr "设置特定行的文本。"
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
-"如果 [code]bookmark[/code] 为 true,则为行 [code]line[/code] 设置书签。如果 "
-"[code]bookmark[/code] 为 false,则删除该书签。\n"
+"如果 [code]bookmark[/code] 为 [code]true[/code],则为行 [code]line[/code] "
+"设置书签。如果 [code]bookmark[/code] 为 [code]false[/code],则删除该书签。\n"
"书签显示在 [member breakpoint_gutter] 中。"
#: doc/classes/TextEdit.xml
@@ -76272,6 +76583,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr "为 [code]true[/code] æ—¶å³é”®å•击会显示上下文èœå•。"
#: doc/classes/TextEdit.xml
+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."
@@ -76951,7 +77266,7 @@ msgid ""
msgstr ""
"是 [Texture3D] å’Œ [TextureArray] 的基类。ä¸èƒ½ç›´æŽ¥ä½¿ç”¨ï¼Œä½†åŒ…å«è®¿é—®å’Œä½¿ç”¨ "
"[Texture3D] å’Œ [TextureArray] 的所有必è¦åŠŸèƒ½ã€‚æ•°æ®æ˜¯ä»¥æ¯å±‚为å•ä½è®¾ç½®çš„。对于 "
-"[Texture3D],层指定了深度或 Z-index,它们å¯ä»¥è¢«è§†ä¸ºä¸€å †äºŒç»´åˆ‡ç‰‡ã€‚åŒæ ·åœ°ï¼Œå¯¹"
+"[Texture3D],层指定了深度或 Z-index,它们å¯ä»¥è¢«è§†ä¸ºä¸€å † 2D åˆ‡ç‰‡ã€‚åŒæ ·åœ°ï¼Œå¯¹"
"于 [TextureArray],层指定了数组层。"
#: doc/classes/TextureLayered.xml
@@ -76998,7 +77313,7 @@ msgstr ""
msgid ""
"Sets the data for the specified layer. Data takes the form of a 2-"
"dimensional [Image] resource."
-msgstr "设置指定图层的数æ®ã€‚æ•°æ®çš„形弿˜¯äºŒç»´çš„[Image]资æºã€‚"
+msgstr "设置指定图层的数æ®ã€‚æ•°æ®çš„形弿˜¯äºŒç»´çš„ [Image] 资æºã€‚"
#: doc/classes/TextureLayered.xml
msgid "Returns a dictionary with all the data used by this texture."
@@ -78331,7 +78646,7 @@ msgstr ""
#: doc/classes/TileMap.xml
msgid "The assigned [TileSet]."
-msgstr "指定的[TileSet]图å—集。"
+msgstr "指定的 [TileSet] 图å—集。"
#: doc/classes/TileMap.xml
msgid "Emitted when a tilemap setting has changed."
@@ -78668,7 +78983,7 @@ msgstr "返回图å—çš„ [enum TileMode]。"
#: doc/classes/TileSet.xml
msgid "Returns the tile's Z index (drawing layer)."
-msgstr "返回图å—çš„Z索引,å³ç»˜åˆ¶å±‚。"
+msgstr "返回图å—çš„ Z 索引(绘制层)。"
#: doc/classes/TileSet.xml
msgid "Sets a light occluder for the tile."
@@ -78740,7 +79055,7 @@ msgstr "å¯ç”¨å›¾å—形状上的å•å‘碰撞。"
#: doc/classes/TileSet.xml
msgid "Sets a [Transform2D] on a tile's shape."
-msgstr "在图å—的形状上设置[Transform2D]。"
+msgstr "在图å—的形状上设置 [Transform2D]。"
#: doc/classes/TileSet.xml
msgid "Sets an array of shapes for the tile, enabling collision."
@@ -78756,7 +79071,7 @@ msgstr "设置图å—的纹ç†å移。"
#: doc/classes/TileSet.xml
msgid "Sets the tile's [enum TileMode]."
-msgstr "设置图å—çš„[enum TileMode]。"
+msgstr "设置图å—çš„ [enum TileMode]。"
#: doc/classes/TileSet.xml
msgid "Sets the tile's drawing index."
@@ -78993,7 +79308,7 @@ msgid ""
"[code]name[/code]. The [code]bias[/code] value is the offset from UTC in "
"minutes, since not all time zones are multiples of an hour from UTC."
msgstr ""
-"以字典的形å¼è¿”å›žå½“å‰æ—¶åŒºï¼ŒåŒ…å«çš„键为:[code]bias[/code](å倚)和 "
+"以字典的形å¼è¿”å›žå½“å‰æ—¶åŒºï¼ŒåŒ…å«çš„键为:[code]bias[/code](å置)和 "
"[code]name[/code](å称)。[code]bias[/code] 的值是从 UTC çš„åç§»é‡ï¼Œå•ä½ä¸º"
"åˆ†ï¼Œå› ä¸ºå¹¶ä¸æ˜¯æ‰€æœ‰æ—¶åŒºä¸Ž UTC 的时间差都是整数å€å°æ—¶ã€‚"
@@ -79364,7 +79679,7 @@ msgid ""
msgstr ""
"如果为 [code]true[/code],åªè¦æŒ‰ä¸‹çš„æ‰‹æŒ‡è¿›å‡ºæŒ‰é’®ï¼Œå°±ä¼šå‘出 [signal pressed] "
"å’Œ[signal released] ]ä¿¡å·ï¼Œå³ä½¿åŽ‹åŠ›å¼€å§‹äºŽæŒ‰é’®çš„æœ‰æ•ˆåŒºåŸŸä¹‹å¤–ã€‚\n"
-"[b]注æ„:[/b]è¿™æ˜¯ä¸€ç§ \"pass-by\" çš„æŒ‰åŽ‹æ¨¡å¼ ï¼Œè€Œä¸æ˜¯ \"bypass\"。"
+"[b]注æ„:[/b]这是一ç§â€œpass-byâ€çš„æŒ‰åŽ‹æ¨¡å¼ ï¼Œè€Œä¸æ˜¯â€œbypassâ€ã€‚"
#: doc/classes/TouchScreenButton.xml
msgid "The button's texture for the pressed state."
@@ -79821,7 +80136,6 @@ msgid "Control to show a tree of items."
msgstr "ä»¥æ ‘çŠ¶å½¢å¼æ˜¾ç¤ºé¡¹ç›®çš„æŽ§ä»¶ã€‚"
#: doc/classes/Tree.xml
-#, fuzzy
msgid ""
"This shows a tree of items that can be selected, expanded and collapsed. The "
"tree can have multiple columns with custom controls like text editing, "
@@ -79858,8 +80172,8 @@ msgid ""
msgstr ""
"这展示了一个å¯ä»¥é€‰æ‹©ã€å±•开和折å çš„项目树。该树å¯ä»¥æœ‰å¤šåˆ—的自定义控件,如文本"
"ç¼–è¾‘ã€æŒ‰é’®å’Œå¼¹å‡ºçª—å£ã€‚它对于结构化显示和互动很有用。\n"
-"树通过代ç å»ºç«‹ï¼Œä½¿ç”¨[TreeItem]å¯¹è±¡æ¥æž„建结构。它们有一个å•独根节点,但如果添"
-"加一个虚拟的éšè—根节点,就å¯ä»¥æ¨¡æ‹Ÿå¤šä¸ªæ ¹ã€‚\n"
+"树通过代ç å»ºç«‹ï¼Œä½¿ç”¨ [TreeItem] å¯¹è±¡æ¥æž„建结构。它们有一个å•独根节点,但如果"
+"添加一个虚拟的éšè—根节点,就å¯ä»¥æ¨¡æ‹Ÿå¤šä¸ªæ ¹ã€‚\n"
"[codeblock]\n"
"func _ready():\n"
" var tree = Tree.new()\n"
@@ -79870,9 +80184,17 @@ msgstr ""
" var subchild1 = tree.create_item(child1)\n"
" subchild1.set_text(0, \"Subchild1\")\n"
"[/codeblock]\n"
-"è¦é历一个[Tree]对象中的所有[TreeItem]对象,在通过[method get_root]获得根之"
-"åŽï¼Œä½¿ç”¨[method TreeItem.get_next]å’Œ[method TreeItem.get_children]方法。你å¯"
-"以对一个[TreeItem]使用[method Object.free]æ¥æŠŠå®ƒä»Ž[Tree]中移除。"
+"è¦é历一个 [Tree] 对象中的所有 [TreeItem] 对象,在通过 [method get_root] 获得"
+"根之åŽï¼Œä½¿ç”¨ [method TreeItem.get_next] å’Œ [method TreeItem.get_children] æ–¹"
+"法。你å¯ä»¥å¯¹ä¸€ä¸ª [TreeItem] 使用 [method Object.free] æ¥æŠŠå®ƒä»Ž [Tree] 中移"
+"除。\n"
+"[b]å¢žé‡æœç´¢ï¼š[/b]与 [ItemList] å’Œ [PopupMenu] 类似,[Tree] 也支æŒåœ¨èšç„¦æŽ§ä»¶æ—¶"
+"在列表中进行æœç´¢ã€‚按下与æŸä¸ªæ¡ç›®å称首字æ¯ä¸€è‡´çš„æŒ‰é”®ï¼Œå°±ä¼šé€‰ä¸­ä»¥è¯¥å­—æ¯å¼€å¤´çš„"
+"第一个æ¡ç›®ã€‚在此之åŽï¼Œè¿›è¡Œå¢žé‡æœç´¢çš„办法有两ç§ï¼š1)在超时å‰å†æ¬¡æŒ‰ä¸‹åŒä¸€ä¸ªæŒ‰"
+"键,选中以该字æ¯å¼€å¤´çš„下一个æ¡ç›®ã€‚2ï¼‰åœ¨è¶…æ—¶å‰æŒ‰ä¸‹å‰©ä½™å­—æ¯å¯¹åº”的按键,直接匹é…"
+"并选中所需的æ¡ç›®ã€‚这两个动作都会在最åŽä¸€æ¬¡æŒ‰é”®è¶…æ—¶åŽé‡ç½®å›žåˆ—表顶端。你å¯ä»¥é€š"
+"过 [member ProjectSettings.gui/timers/incremental_search_max_interval_msec] "
+"修改超时时长。"
#: doc/classes/Tree.xml
msgid "Clears the tree. This removes all items."
@@ -79942,7 +80264,7 @@ msgid ""
"Returns the rectangle for custom popups. Helper to create custom cell "
"controls that display a popup. See [method TreeItem.set_cell_mode]."
msgstr ""
-"返回自定义弹出窗å£çš„矩形。帮助创建显示弹出å¼çš„自定义å•元格控件。å‚阅[method "
+"返回自定义弹出窗å£çš„矩形。帮助创建显示弹出å¼çš„自定义å•å…ƒæ ¼æŽ§ä»¶ã€‚è§ [method "
"TreeItem.set_cell_mode]。"
#: doc/classes/Tree.xml
@@ -79955,10 +80277,10 @@ msgid ""
"To get the item which the returned drop section is relative to, use [method "
"get_item_at_position]."
msgstr ""
-"返回ä½äºŽ[code]position[/code]的放置部分,如果没有项目,则返回-100。\n"
-"在 \"项目上方\"ã€\"项目之上\"å’Œ \"项目下方\"的放置部分将分别返回-1ã€0或1çš„"
-"值。请å‚阅[enum DropModeFlags]以了解æ¯ä¸ªæ”¾ç½®éƒ¨åˆ†çš„æè¿°ã€‚\n"
-"è¦èŽ·å¾—è¿”å›žçš„æ”¾ç½®éƒ¨åˆ†ç›¸å¯¹é¡¹ï¼Œè¯·ä½¿ç”¨[method get_item_at_position]。"
+"返回ä½äºŽ [code]position[/code] 的放置部分,如果没有项目,则返回 -100。\n"
+"在“项目上方â€â€œé¡¹ç›®ä¹‹ä¸Šâ€å’Œâ€œé¡¹ç›®ä¸‹æ–¹â€çš„æ”¾ç½®éƒ¨åˆ†å°†åˆ†åˆ«è¿”回 -1ã€0 或 1 的值。请å‚"
+"阅 [enum DropModeFlags] 以了解æ¯ä¸ªæ”¾ç½®éƒ¨åˆ†çš„æè¿°ã€‚\n"
+"è¦èŽ·å¾—è¿”å›žçš„æ”¾ç½®éƒ¨åˆ†ç›¸å¯¹é¡¹ï¼Œè¯·ä½¿ç”¨ [method get_item_at_position]。"
#: doc/classes/Tree.xml
msgid ""
@@ -80050,7 +80372,7 @@ msgid ""
"is_selected]."
msgstr ""
"返回当å‰èŽ·å¾—ç„¦ç‚¹çš„åˆ—ï¼Œå¦‚æžœæ²¡æœ‰ç„¦ç‚¹åˆ—ï¼Œåˆ™è¿”å›ž -1。\n"
-"在[constant SELECT_SINGLE] 模å¼ä¸‹ï¼Œç„¦ç‚¹åˆ—是被选中的列。在 [constant "
+"在 [constant SELECT_SINGLE] 模å¼ä¸‹ï¼Œç„¦ç‚¹åˆ—是被选中的列。在 [constant "
"SELECT_ROW] 模å¼ä¸‹ï¼Œå¦‚果有任æ„项被选中,焦点列总是 0。在 [constant "
"SELECT_MULTI] 模å¼ä¸‹ï¼Œç„¦ç‚¹åˆ—是焦点光标下的列,但ä¸ä¸€å®šæœ‰åˆ—被选中。\n"
"è¦åˆ¤æ–­ä¸€ä¸ªé¡¹çš„æŸä¸€åˆ—æ˜¯å¦è¢«é€‰ä¸­ï¼Œè¯·ä½¿ç”¨ [method TreeItem.is_selected]。"
@@ -80075,12 +80397,12 @@ msgid ""
"will use their \"min_width\" in a similar fashion to [member Control."
"size_flags_stretch_ratio]."
msgstr ""
-"设置一个列的最å°å®½åº¦ã€‚拥有“Expandâ€æ ‡å¿—的列将以类似于 [member Control."
+"设置æŸä¸€åˆ—的最å°å®½åº¦ã€‚拥有“Expandâ€æ ‡å¿—的列将以类似于 [member Control."
"size_flags_stretch_ratio] 的方å¼ä½¿ç”¨å…¶â€œmin_widthâ€æœ€å°å®½åº¦ã€‚"
#: doc/classes/Tree.xml
msgid "Sets the title of a column."
-msgstr "设置一个列的标题。"
+msgstr "设置æŸä¸€åˆ—的标题。"
#: doc/classes/Tree.xml
msgid ""
@@ -80254,7 +80576,7 @@ msgid ""
"other flags."
msgstr ""
"ç¦ç”¨æ‰€æœ‰æ”¾ç½®éƒ¨åˆ†ï¼Œä½†ä»ç„¶å…许通过 [method get_drop_section_at_position] 检"
-"测“物å“上â€çš„æ”¾ç½®éƒ¨åˆ†ã€‚\n"
+"测“项目上â€çš„æ”¾ç½®éƒ¨åˆ†ã€‚\n"
"[b]注æ„:[/b]è¿™æ˜¯é»˜è®¤çš„æ ‡å¿—ï¼Œå½“ä¸Žå…¶ä»–æ ‡å¿—ç»“åˆæ—¶ï¼Œå®ƒæ²¡æœ‰æ•ˆæžœã€‚"
#: doc/classes/Tree.xml
@@ -80318,7 +80640,7 @@ msgid ""
"Draws the guidelines if not zero, this acts as a boolean. The guideline is a "
"horizontal line drawn at the bottom of each item."
msgstr ""
-"如果ä¸ä¸ºé›¶å°±ç»˜åˆ¶å‚考线,这作为一个布尔值。å‚考线是在æ¯ä¸ªé¡¹çš„åº•éƒ¨ç”»çš„ä¸€æ¡æ°´å¹³"
+"如果ä¸ä¸ºé›¶å°±ç»˜åˆ¶å‚考线,行为类似于布尔值。å‚考线是在æ¯ä¸ªé¡¹çš„åº•éƒ¨ç”»çš„ä¸€æ¡æ°´å¹³"
"线。"
#: doc/classes/Tree.xml
@@ -80326,8 +80648,8 @@ msgid ""
"Draws the relationship lines if not zero, this acts as a boolean. "
"Relationship lines are drawn at the start of child items to show hierarchy."
msgstr ""
-"如果ä¸ä¸ºé›¶ï¼Œåˆ™ç»˜åˆ¶å…³ç³»çº¿ï¼Œè¿™ä½œä¸ºä¸€ä¸ªå¸ƒå°”值。关系线在å­é¡¹çš„开始处绘制,以显示"
-"层次结构。"
+"如果ä¸ä¸ºé›¶å°±ç»˜åˆ¶å…³ç³»çº¿ï¼Œè¡Œä¸ºç±»ä¼¼äºŽå¸ƒå°”值。关系线在å­é¡¹çš„开始处绘制,以显示层"
+"次结构。"
#: doc/classes/Tree.xml
msgid ""
@@ -80590,19 +80912,20 @@ msgstr "返回使用 [method set_metadata] 为指定列设置的元数æ®ã€‚"
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next TreeItem in the tree or a null object if there is none."
-msgstr "返回树中的下一个 TreeItem,如果没有,则返回一个空对象。"
+"Returns the next sibling TreeItem in the tree or a null object if there is "
+"none."
+msgstr "返回树中的下一个兄弟 TreeItem,如果没有,则返回一个空对象。"
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
msgstr ""
-"返回树中下一个å¯è§çš„ TreeItem,如果没有,则返回空对象。\n"
-"如果 [code]wrap[/code] 被å¯ç”¨ï¼Œå½“在最åŽä¸€ä¸ªå¯è§å…ƒç´ ä¸Šè°ƒç”¨æ—¶ï¼Œè¯¥æ–¹æ³•将环绕到树"
+"返回树中下一个å¯è§çš„兄弟 TreeItem,如果没有,则返回空对象。\n"
+"如果å¯ç”¨äº† [code]wrap[/code],当在最åŽä¸€ä¸ªå¯è§å…ƒç´ ä¸Šè°ƒç”¨æ—¶ï¼Œè¯¥æ–¹æ³•将环绕到树"
"中的第一个å¯è§å…ƒç´ ï¼Œå¦åˆ™å®ƒå°†è¿”回 [code]null[/code]。"
#: doc/classes/TreeItem.xml
@@ -80611,19 +80934,20 @@ msgstr "返回父级 TreeItem,如果没有,则返回一个空对象。"
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous TreeItem in the tree or a null object if there is none."
-msgstr "返回树中的å‰ä¸€ä¸ª TreeItem,如果没有,则返回一个空对象。"
+"Returns the previous sibling TreeItem in the tree or a null object if there "
+"is none."
+msgstr "返回树中的å‰ä¸€ä¸ªå…„弟 TreeItem,如果没有,则返回一个空对象。"
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
msgstr ""
-"返回树中å‰ä¸€ä¸ªå¯è§çš„ TreeItem,如果没有,则返回 null 对象。\n"
-"如果 [code]wrap[/code] 被å¯ç”¨ï¼Œå½“在第一个å¯è§å…ƒç´ ä¸Šè°ƒç”¨æ—¶ï¼Œè¯¥æ–¹æ³•将环绕到树中"
+"返回树中å‰ä¸€ä¸ªå¯è§çš„兄弟 TreeItem,如果没有,则返回 null 对象。\n"
+"如果å¯ç”¨äº† [code]wrap[/code],当在第一个å¯è§å…ƒç´ ä¸Šè°ƒç”¨æ—¶ï¼Œè¯¥æ–¹æ³•将环绕到树中"
"最åŽä¸€ä¸ªå¯è§å…ƒç´ ï¼Œå¦åˆ™å®ƒå°†è¿”回 [code]null[/code]。"
#: doc/classes/TreeItem.xml
@@ -82318,7 +82642,7 @@ msgstr "[VBoxContainer] 的元素之间的垂直空间。"
#: doc/classes/Vector2.xml
msgid "Vector used for 2D math."
-msgstr "用于二维数学的å‘é‡ã€‚"
+msgstr "用于 2D 数学的å‘é‡ã€‚"
#: doc/classes/Vector2.xml
msgid ""
@@ -82928,11 +83252,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -83039,8 +83363,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -83791,13 +84115,15 @@ 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 ""
"阴影图集的分辨率(用于全å‘光和èšå…‰ï¼‰ã€‚该值将四èˆäº”入到最接近的 2 的幂。\n"
-"[b]注æ„:[/b]如果设置为 0,阴影将ä¸å¯è§ã€‚由于用户创建的视区默认值为 0,因此必"
-"须手动将此值设置为大于 0。"
+"[b]注æ„:[/b]如果设置为 [code]0[/code],点阴影和方å‘阴影[i]都[/i]å°†ä¸å¯è§ã€‚ç”±"
+"于用户创建的视区默认值为 [code]0[/code],因此必须手动将此值设置为大于 "
+"[code]0[/code](一般至少是 [code]256[/code])。"
#: doc/classes/Viewport.xml
msgid ""
@@ -83827,11 +84153,18 @@ msgstr "如果为 [code]true[/code],尺寸é‡å†™ä¹Ÿä¼šå½±å“拉伸。"
msgid ""
"If [code]true[/code], the viewport should render its background as "
"transparent."
-msgstr "如果为 [code]true[/code]ï¼Œè¯¥è§†çª—åº”ä½¿å…¶èƒŒæ™¯æ¸²æŸ“ä¸ºé€æ˜Žã€‚"
+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 ""
+"视区的渲染模å¼ã€‚\n"
+"[b]注æ„:[/b]如果设为 [constant USAGE_2D] 或 [constant "
+"USAGE_2D_NO_SAMPLING],则å¯ç”¨ [member hdr] ä¸ä¼šç”Ÿæ•ˆï¼Œå› ä¸º 2D 䏿”¯æŒ HDR。"
#: doc/classes/Viewport.xml
msgid ""
@@ -88935,8 +89268,16 @@ msgid "Sets the viewport's global transformation matrix."
msgstr "è®¾ç½®è§†çª—çš„å…¨å±€å˜æ¢çŸ©é˜µã€‚"
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
-msgstr "如果为 [code]true[/code],视窗将呈现为 hdr。"
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+"如果为 "
+"[code]true[/code],该视区会渲染至高动æ€èŒƒå›´ï¼ˆHDRï¼‰è€Œä¸æ˜¯æ ‡å‡†åЍæ€èŒƒå›´ï¼ˆSDR)。"
+"å¦è¯·å‚阅 [method viewport_set_use_32_bpc_depth]。\n"
+"[b]注æ„:[/b]仅在 GLES3 åŽç«¯å¯ç”¨ã€‚"
#: doc/classes/VisualServer.xml
msgid "If [code]true[/code], the viewport's canvas is not rendered."
@@ -89035,6 +89376,19 @@ msgstr "设置视窗的 2D/3D 模å¼ã€‚é€‰é¡¹è§ [enum ViewportUsage] 常é‡ã€‚"
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+"如果为 [code]true[/code],分é…该视区的帧缓冲时将使用完整浮点数精度(32 "
+"ä½ï¼‰è€Œä¸æ˜¯åŠæµ®ç‚¹æ•°ç²¾åº¦ï¼ˆ16 ä½ï¼‰ã€‚åªæœ‰åœ¨åŒä¸€ä¸ª [Viewport] 上通过 [method "
+"viewport_set_use_32_bpc_depth] 将 HDR 设为 [code]true[/code] 时有效。\n"
+"[b]注æ„:[/b]仅在 GLES3 åŽç«¯ä¸­å¯ç”¨ã€‚"
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
@@ -89164,7 +89518,7 @@ msgstr "由六个é¢ç»„æˆçš„纹ç†ï¼Œå¯ä»¥åœ¨ç€è‰²å™¨ä¸­ä½¿ç”¨ [code]vec3[/co
#: doc/classes/VisualServer.xml
msgid "An array of 2-dimensional textures."
-msgstr "一组二维纹ç†ã€‚"
+msgstr "二维纹ç†çš„æ•°ç»„。"
#: doc/classes/VisualServer.xml
msgid "A 3-dimensional texture with width, height, and depth."
@@ -89400,17 +89754,17 @@ msgstr "第三次拆分所å ç”¨çš„é˜´å½±å›¾é›†çš„æ¯”ä¾‹ã€‚ç¬¬å››ä¸ªæ‹†åˆ†å æ®
msgid ""
"Normal bias used to offset shadow lookup by object normal. Can be used to "
"fix self-shadowing artifacts."
-msgstr "法线å移,用于抵消物体法线的阴影查找。å¯ä»¥ç”¨æ¥ä¿®å¤è‡ªé˜´å½±çš„伪影。"
+msgstr "法线å置,用于抵消物体法线的阴影查找。å¯ä»¥ç”¨æ¥ä¿®å¤è‡ªé˜´å½±çš„伪影。"
#: doc/classes/VisualServer.xml
msgid "Bias the shadow lookup to fix self-shadowing artifacts."
-msgstr "对阴影查找进行å移,以修å¤è‡ªæˆ‘阴影的å‡è±¡ã€‚"
+msgstr "对阴影查找进行å置,以修å¤è‡ªæˆ‘阴影的å‡è±¡ã€‚"
#: doc/classes/VisualServer.xml
msgid ""
"Increases bias on further splits to fix self-shadowing that only occurs far "
"away from the camera."
-msgstr "增加对进一步分割的å差,以修å¤ä»…在远离相机的地方å‘生的自身阴影。"
+msgstr "增加对进一步分割的å置,以修å¤ä»…在远离相机的地方å‘生的自身阴影。"
#: doc/classes/VisualServer.xml
msgid "Represents the size of the [enum LightParam] enum."
@@ -89898,7 +90252,7 @@ msgid ""
"Use a specified canvas layer as the background. This can be useful for "
"instantiating a 2D scene in a 3D world."
msgstr ""
-"使用一个指定的画布层作为背景。这对在三维世界中实例化一个二维场景很有用。"
+"使用一个指定的画布层作为背景。这对在 3D 世界中实例化一个 2D 场景很有用。"
#: doc/classes/VisualServer.xml
msgid ""
@@ -93844,7 +94198,7 @@ msgid ""
"current and potential collisions. When using multi-threaded physics, access "
"is limited to [code]_physics_process(delta)[/code] in the main thread."
msgstr ""
-"直接访问世界物ç†äºŒç»´ç©ºé—´çжæ€ã€‚用于查询当å‰å’Œæ½œåœ¨çš„ç¢°æ’žã€‚ä½¿ç”¨å¤šçº¿ç¨‹ç‰©ç†æ—¶ï¼Œè®¿"
+"ç›´æŽ¥è®¿é—®ä¸–ç•Œç‰©ç† 2D 空间状æ€ã€‚用于查询当å‰å’Œæ½œåœ¨çš„ç¢°æ’žã€‚ä½¿ç”¨å¤šçº¿ç¨‹ç‰©ç†æ—¶ï¼Œè®¿"
"问仅é™äºŽä¸»çº¿ç¨‹ä¸­çš„ [code]_physics_process(delta)[/code]。"
#: doc/classes/World2D.xml
diff --git a/doc/translations/zh_TW.po b/doc/translations/zh_TW.po
index 84b16d22a6..59cd8b199b 100644
--- a/doc/translations/zh_TW.po
+++ b/doc/translations/zh_TW.po
@@ -948,7 +948,14 @@ msgid ""
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
-msgid "Like [method print], but prints only when used in debug mode."
+msgid ""
+"Like [method print], but includes the current stack frame when running with "
+"the debugger turned on.\n"
+"Output in the console would look something like this:\n"
+"[codeblock]\n"
+"Test print\n"
+" At: res://test.gd:15:_process()\n"
+"[/codeblock]"
msgstr ""
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -7798,8 +7805,8 @@ msgstr ""
#: doc/classes/ARVRController.xml
msgid ""
"The degree to which the controller vibrates. Ranges from [code]0.0[/code] to "
-"[code]1.0[/code] with precision [code].01[/code]. If changed, updates "
-"[member ARVRPositionalTracker.rumble] accordingly.\n"
+"[code]1.0[/code]. If changed, updates [member ARVRPositionalTracker.rumble] "
+"accordingly.\n"
"This is a useful property to animate if you want the controller to vibrate "
"for a limited duration."
msgstr ""
@@ -10080,7 +10087,13 @@ msgid "If [code]true[/code], audio plays when added to scene tree."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
-msgid "Bus on which this audio is playing."
+msgid ""
+"Bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer.xml
@@ -10245,7 +10258,13 @@ msgid ""
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
-msgid "The bus on which this audio is playing."
+msgid ""
+"The bus on which this audio is playing.\n"
+"[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]."
msgstr ""
#: doc/classes/AudioStreamPlayer3D.xml
@@ -11859,7 +11878,12 @@ msgstr ""
#: doc/classes/Camera.xml
msgid ""
-"If [code]true[/code], the ancestor [Viewport] is currently using this camera."
+"If [code]true[/code], the ancestor [Viewport] is currently using this "
+"camera.\n"
+"If multiple cameras are in the scene, one will always be made current. For "
+"example, if two [Camera] nodes are present in the scene and only one is "
+"current, setting one camera's [member current] to [code]false[/code] will "
+"cause the other camera to be made current."
msgstr ""
#: doc/classes/Camera.xml
@@ -12257,10 +12281,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 +19585,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 +19605,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 +19626,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
@@ -20277,7 +20311,7 @@ msgstr ""
msgid ""
"Saves the editor feature profile to a file in JSON format. It can then be "
"imported using the feature profile manager's [b]Import[/b] button or the "
-"[method load_from_file] button."
+"[method load_from_file] method."
msgstr ""
#: doc/classes/EditorFeatureProfile.xml
@@ -23669,7 +23703,7 @@ msgstr ""
#: doc/classes/Environment.xml
msgid ""
"The tonemapping mode to use. Tonemapping is the process that \"converts\" "
-"HDR values to be suitable for rendering on a LDR display. (Godot doesn't "
+"HDR values to be suitable for rendering on a SDR display. (Godot doesn't "
"support rendering on HDR displays yet.)"
msgstr ""
@@ -25506,7 +25540,7 @@ msgstr ""
#: doc/classes/Geometry.xml
msgid ""
"Given an array of [Vector2]s representing tiles, builds an atlas. The "
-"returned dictionary has two keys: [code]points[/code] is a vector of "
+"returned dictionary has two keys: [code]points[/code] is an array of "
"[Vector2] that specifies the positions of each tile, [code]size[/code] "
"contains the overall size of the whole atlas as [Vector2]."
msgstr ""
@@ -28556,13 +28590,14 @@ msgstr ""
#: doc/classes/HTTPRequest.xml
msgid ""
-"If set to a value greater than [code]0.0[/code], the HTTP request will time "
-"out after [code]timeout[/code] seconds have passed and the request is not "
-"[i]completed[/i] yet. For small HTTP requests such as REST API usage, set "
-"[member timeout] to a value greater than [code]0.0[/code] to prevent the "
-"application from getting stuck if the request fails to get a response in a "
-"timely manner. For file downloads, leave this to [code]0.0[/code] to prevent "
-"the download from failing if it takes too much time."
+"If set to a value greater than [code]0.0[/code] before the request starts, "
+"the HTTP request will time out after [code]timeout[/code] seconds have "
+"passed and the request is not [i]completed[/i] yet. For small HTTP requests "
+"such as REST API usage, set [member timeout] to a value between [code]10.0[/"
+"code] and [code]30.0[/code] to prevent the application from getting stuck if "
+"the request fails to get a response in a timely manner. For file downloads, "
+"leave this to [code]0.0[/code] to prevent the download from failing if it "
+"takes too much time."
msgstr ""
#: doc/classes/HTTPRequest.xml
@@ -29977,7 +30012,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]enabled[/i] by default. It is "
+"recommended to keep it enabled for games which don't require very reactive "
+"input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30551,10 +30589,14 @@ 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] The behavior of this event is affected by the value of [member "
+"Input.use_accumulated_input]. When set to [code]true[/code] (default), mouse/"
+"pen motion events received from the OS will be merged to emit an accumulated "
+"event only once per frame rendered at most. When set to [code]false[/code], "
+"the events will be emitted as received, which means that they can be emitted "
+"multiple times per frame rendered, allowing for precise input reporting at "
+"the expense of CPU usage.\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."
@@ -30566,6 +30608,12 @@ msgstr ""
#: doc/classes/InputEventMouseMotion.xml
msgid ""
+"Returns [code]true[/code] when using the eraser end of a stylus pen.\n"
+"[b]Note:[/b] This property is implemented on Linux, macOS and Windows."
+msgstr ""
+
+#: doc/classes/InputEventMouseMotion.xml
+msgid ""
"Represents the pressure the user puts on the pen. Ranges from [code]0.0[/"
"code] to [code]1.0[/code]."
msgstr ""
@@ -30878,6 +30926,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 ""
@@ -32597,7 +32650,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text outline. Higher priority objects will "
"be sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32613,7 +32666,7 @@ msgstr ""
msgid ""
"Sets the render priority for the text. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -32643,7 +32696,7 @@ msgstr ""
#: doc/classes/Label3D.xml
msgid ""
-"If set, text can be seen from the back as well. If not, the texture is "
+"If set, text can be seen from the back as well. If not, the text is "
"invisible when looking at it from behind."
msgstr ""
@@ -36311,7 +36364,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 +36477,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 ""
@@ -36771,7 +36832,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The cost of entering this region from another region can be controlled with "
"the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The cost of traveling distances inside this region can be controlled with "
"the [member travel_cost] multiplier."
@@ -37034,7 +37095,7 @@ msgid ""
"two regions. They must share a similar edge.\n"
"The pathfinding cost of entering this region from another region can be "
"controlled with the [member enter_cost] value.\n"
-"[b]Note[/b]: This value is not added to the path cost when the start "
+"[b]Note:[/b] This value is not added to the path cost when the start "
"position is already inside this region.\n"
"The pathfinding cost of traveling distances inside this region can be "
"controlled with the [member travel_cost] multiplier."
@@ -37152,6 +37213,52 @@ msgstr ""
msgid "Control activation of this server."
msgstr ""
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be controlled from a "
+"script."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"A [NetworkedMultiplayerPeer] implementation that can be used as a [member "
+"MultiplayerAPI.network_peer] and controlled from a script.\n"
+"Its purpose is to allow adding a new backend for the high-Level multiplayer "
+"API without needing to use GDNative."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Deliver a packet to the local [MultiplayerAPI].\n"
+"When your script receives a packet from other peers over the network "
+"(originating from the [signal packet_generated] signal on the sending peer), "
+"passing it to this method will deliver it locally."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Initialize the peer with the given [code]peer_id[/code] (must be between 1 "
+"and 2147483647)."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Set the state of the connection. See [enum NetworkedMultiplayerPeer."
+"ConnectionStatus]."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid "Set the max packet size that this peer can handle."
+msgstr ""
+
+#: doc/classes/NetworkedMultiplayerCustom.xml
+msgid ""
+"Emitted when the local [MultiplayerAPI] generates a packet.\n"
+"Your script should take this packet and send it to the requested peer over "
+"the network (which should call [method deliver_packet] with the data when "
+"it's received)."
+msgstr ""
+
#: modules/enet/doc_classes/NetworkedMultiplayerENet.xml
msgid ""
"PacketPeer implementation using the [url=http://enet.bespin.org/index."
@@ -39849,7 +39956,13 @@ msgid "See [enum ShadowDetail]."
msgstr ""
#: doc/classes/OmniLight.xml
-msgid "See [enum ShadowMode]."
+msgid ""
+"The shadow rendering mode to use for this [OmniLight]. See [enum "
+"ShadowMode].\n"
+"[b]Note:[/b] In GLES2, [constant SHADOW_CUBE] is only supported on GPUs that "
+"feature support for depth cubemaps. Old GPUs such as the Radeon HD 4000 "
+"series don't support cubemap shadows and will fall back to dual paraboloid "
+"shadows as a result."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -39861,7 +39974,8 @@ msgstr ""
#: doc/classes/OmniLight.xml
msgid ""
"Shadows are rendered to a cubemap. Slower than [constant "
-"SHADOW_DUAL_PARABOLOID], but higher-quality."
+"SHADOW_DUAL_PARABOLOID], but higher-quality. Only supported on GPUs that "
+"feature support for depth cubemaps."
msgstr ""
#: doc/classes/OmniLight.xml
@@ -45491,6 +45605,13 @@ msgstr ""
msgid "Changes the byte at the given index."
msgstr ""
+#: doc/classes/PoolByteArray.xml doc/classes/PoolColorArray.xml
+#: doc/classes/PoolIntArray.xml doc/classes/PoolRealArray.xml
+#: doc/classes/PoolStringArray.xml doc/classes/PoolVector2Array.xml
+#: doc/classes/PoolVector3Array.xml
+msgid "Sorts the elements of the array in ascending order."
+msgstr ""
+
#: doc/classes/PoolByteArray.xml
msgid ""
"Returns the slice of the [PoolByteArray] between indices (inclusive) as a "
@@ -50041,8 +50162,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
@@ -54420,7 +54541,8 @@ msgid ""
"SceneTree.get_processed_tweens] will contain this [SceneTreeTween]). A "
"[SceneTreeTween] might become invalid when it has finished tweening, is "
"killed, or when created with [code]SceneTreeTween.new()[/code]. Invalid "
-"[SceneTreeTween]s can't have [Tweener]s appended."
+"[SceneTreeTween]s can't have [Tweener]s appended. You can however still use "
+"[method interpolate_value]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -54460,15 +54582,16 @@ msgstr ""
msgid ""
"Sets the number of times the tweening sequence will be repeated, i.e. "
"[code]set_loops(2)[/code] will run the animation twice.\n"
-"Calling this method without arguments will make the [Tween] run infinitely, "
-"until either it is killed with [method kill], the [Tween]'s bound node is "
-"freed, or all the animated objects have been freed (which makes further "
-"animation impossible).\n"
+"Calling this method without arguments will make the [SceneTreeTween] run "
+"infinitely, until either it is killed with [method kill], the "
+"[SceneTreeTween]'s bound node is freed, or all the animated objects have "
+"been freed (which makes further animation impossible).\n"
"[b]Warning:[/b] Make sure to always add some duration/delay when using "
"infinite loops. To prevent the game freezing, 0-duration looped animations "
"(e.g. a single [CallbackTweener] with no delay) are stopped after a small "
-"number of loops, which may produce unexpected results. If a [Tween]'s "
-"lifetime depends on some node, always use [method bind_node]."
+"number of loops, which may produce unexpected results. If a "
+"[SceneTreeTween]'s lifetime depends on some node, always use [method "
+"bind_node]."
msgstr ""
#: doc/classes/SceneTreeTween.xml
@@ -55945,11 +56068,30 @@ msgid ""
msgstr ""
#: doc/classes/Spatial.xml
+msgid ""
+"Rotation part of the global transformation in radians, specified in terms of "
+"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
+"[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."
+msgstr ""
+
+#: doc/classes/Spatial.xml
msgid "World space (global) [Transform] of this node."
msgstr ""
#: doc/classes/Spatial.xml
msgid ""
+"Global position of this node. This is equivalent to [code]global_transform."
+"origin[/code]."
+msgstr ""
+
+#: doc/classes/Spatial.xml
+msgid ""
"Rotation part of the local transformation in radians, specified in terms of "
"YXZ-Euler angles in the format (X angle, Y angle, Z angle).\n"
"[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a "
@@ -57620,7 +57762,7 @@ msgstr ""
msgid ""
"Sets the render priority for the sprite. Higher priority objects will be "
"sorted in front of lower priority objects.\n"
-"[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant "
+"[b]Note:[/b] This only applies if [member alpha_cut] is set to [constant "
"ALPHA_CUT_DISABLED] (default value).\n"
"[b]Note:[/b] This only applies to sorting of transparent objects. This will "
"not impact how transparent objects are sorted relative to opaque objects. "
@@ -58417,7 +58559,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 +59180,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
@@ -60496,8 +60664,8 @@ msgstr ""
#: doc/classes/TextEdit.xml
msgid ""
-"Bookmarks the [code]line[/code] if [code]bookmark[/code] is true. Deletes "
-"the bookmark if [code]bookmark[/code] is false.\n"
+"Bookmarks the [code]line[/code] if [code]bookmark[/code] is [code]true[/"
+"code]. Deletes the bookmark if [code]bookmark[/code] is [code]false[/code].\n"
"Bookmarks are shown in the [member breakpoint_gutter]."
msgstr ""
@@ -60562,6 +60730,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."
@@ -64126,13 +64299,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the next visible TreeItem in the tree or a null object if there is "
-"none.\n"
+"Returns the next visible sibling TreeItem in the tree or a null object if "
+"there is none.\n"
"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]."
@@ -64144,13 +64318,14 @@ msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"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."
msgstr ""
#: doc/classes/TreeItem.xml
msgid ""
-"Returns the previous visible TreeItem in the tree or a null object if there "
-"is none.\n"
+"Returns the previous visible sibling TreeItem in the tree or a null object "
+"if there is none.\n"
"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]."
@@ -65963,11 +66138,11 @@ msgstr ""
#: doc/classes/VehicleBody.xml
msgid ""
"Accelerates the vehicle by applying an engine force. The vehicle is only "
-"speed up if the wheels that have [member VehicleWheel.use_as_traction] set "
-"to [code]true[/code] and are in contact with a surface. The [member "
-"RigidBody.mass] of the vehicle has an effect on the acceleration of the "
-"vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 "
-"range for acceleration.\n"
+"sped up if the wheels that have [member VehicleWheel.use_as_traction] set to "
+"[code]true[/code] and are in contact with a surface. The [member RigidBody."
+"mass] of the vehicle has an effect on the acceleration of the vehicle. For a "
+"vehicle with a mass set to 1000, try a value in the 25 - 50 range for "
+"acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
"you will need to add logic for this if you wish to simulate gears.\n"
"A negative value will result in the vehicle reversing."
@@ -66047,8 +66222,8 @@ msgstr ""
#: doc/classes/VehicleWheel.xml
msgid ""
-"Accelerates the wheel by applying an engine force. The wheel is only speed "
-"up if it is in contact with a surface. The [member RigidBody.mass] of the "
+"Accelerates the wheel by applying an engine force. The wheel is only sped up "
+"if it is in contact with a surface. The [member RigidBody.mass] of the "
"vehicle has an effect on the acceleration of the vehicle. For a vehicle with "
"a mass set to 1000, try a value in the 25 - 50 range for acceleration.\n"
"[b]Note:[/b] The simulation does not take the effect of gears into account, "
@@ -66655,9 +66830,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 +66862,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
@@ -71059,7 +71239,11 @@ msgid "Sets the viewport's global transformation matrix."
msgstr ""
#: doc/classes/VisualServer.xml
-msgid "If [code]true[/code], the viewport renders to hdr."
+msgid ""
+"If [code]true[/code], the viewport renders to high dynamic range (HDR) "
+"instead of standard dynamic range (SDR). See also [method "
+"viewport_set_use_32_bpc_depth].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
msgstr ""
#: doc/classes/VisualServer.xml
@@ -71144,6 +71328,15 @@ msgstr ""
#: doc/classes/VisualServer.xml
msgid ""
+"If [code]true[/code], allocates the viewport's framebuffer with full "
+"floating-point precision (32-bit) instead of half floating-point precision "
+"(16-bit). Only effective if [method viewport_set_use_32_bpc_depth] is used "
+"on the same [Viewport] to set HDR to [code]true[/code].\n"
+"[b]Note:[/b] Only available on the GLES3 backend."
+msgstr ""
+
+#: doc/classes/VisualServer.xml
+msgid ""
"If [code]true[/code], the viewport uses augmented or virtual reality "
"technologies. See [ARVRInterface]."
msgstr ""
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index 276e69e470..cc38c2352f 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -38,7 +38,7 @@
#define kOutputBus 0
#define kInputBus 1
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
OSStatus AudioDriverCoreAudio::input_device_address_cb(AudioObjectID inObjectID,
UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses,
void *inClientData) {
@@ -72,7 +72,7 @@ Error AudioDriverCoreAudio::init() {
AudioComponentDescription desc;
memset(&desc, 0, sizeof(desc));
desc.componentType = kAudioUnitType_Output;
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
desc.componentSubType = kAudioUnitSubType_HALOutput;
#else
desc.componentSubType = kAudioUnitSubType_RemoteIO;
@@ -85,7 +85,7 @@ Error AudioDriverCoreAudio::init() {
OSStatus result = AudioComponentInstanceNew(comp, &audio_unit);
ERR_FAIL_COND_V(result != noErr, FAILED);
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
AudioObjectPropertyAddress prop;
prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
prop.mScope = kAudioObjectPropertyScopeGlobal;
@@ -135,7 +135,7 @@ Error AudioDriverCoreAudio::init() {
// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
result = AudioUnitSetProperty(audio_unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, kOutputBus, &buffer_frames, sizeof(UInt32));
ERR_FAIL_COND_V(result != noErr, FAILED);
#endif
@@ -313,7 +313,7 @@ void AudioDriverCoreAudio::finish() {
ERR_PRINT("AudioUnitUninitialize failed");
}
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
AudioObjectPropertyAddress prop;
prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
prop.mScope = kAudioObjectPropertyScopeGlobal;
@@ -339,7 +339,7 @@ Error AudioDriverCoreAudio::capture_init() {
AudioComponentDescription desc;
memset(&desc, 0, sizeof(desc));
desc.componentType = kAudioUnitType_Output;
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
desc.componentSubType = kAudioUnitSubType_HALOutput;
#else
desc.componentSubType = kAudioUnitSubType_RemoteIO;
@@ -352,7 +352,7 @@ Error AudioDriverCoreAudio::capture_init() {
OSStatus result = AudioComponentInstanceNew(comp, &input_unit);
ERR_FAIL_COND_V(result != noErr, FAILED);
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
AudioObjectPropertyAddress prop;
prop.mSelector = kAudioHardwarePropertyDefaultInputDevice;
prop.mScope = kAudioObjectPropertyScopeGlobal;
@@ -370,7 +370,7 @@ Error AudioDriverCoreAudio::capture_init() {
ERR_FAIL_COND_V(result != noErr, FAILED);
UInt32 size;
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
AudioDeviceID deviceId;
size = sizeof(AudioDeviceID);
AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
@@ -447,7 +447,7 @@ void AudioDriverCoreAudio::capture_finish() {
ERR_PRINT("AudioUnitUninitialize failed");
}
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
AudioObjectPropertyAddress prop;
prop.mSelector = kAudioHardwarePropertyDefaultInputDevice;
prop.mScope = kAudioObjectPropertyScopeGlobal;
@@ -491,7 +491,7 @@ Error AudioDriverCoreAudio::capture_stop() {
return OK;
}
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
Array AudioDriverCoreAudio::_get_device_list(bool capture) {
Array list;
diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h
index f86037f092..7fac8a99ed 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.h
+++ b/drivers/coreaudio/audio_driver_coreaudio.h
@@ -28,15 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef COREAUDIO_ENABLED
-
#ifndef AUDIO_DRIVER_COREAUDIO_H
#define AUDIO_DRIVER_COREAUDIO_H
+#ifdef COREAUDIO_ENABLED
+
#include "servers/audio_server.h"
#import <AudioUnit/AudioUnit.h>
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
#import <CoreAudio/AudioHardware.h>
#endif
@@ -58,7 +58,7 @@ class AudioDriverCoreAudio : public AudioDriver {
Vector<int32_t> samples_in;
Vector<int16_t> input_buf;
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
Array _get_device_list(bool capture = false);
void _set_device(const String &device, bool capture = false);
@@ -106,7 +106,7 @@ public:
bool try_lock();
void stop();
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
virtual Array get_device_list();
virtual String get_device();
virtual void set_device(String device);
@@ -120,6 +120,6 @@ public:
~AudioDriverCoreAudio() {}
};
-#endif
+#endif // COREAUDIO_ENABLED
-#endif
+#endif // AUDIO_DRIVER_COREAUDIO_H
diff --git a/drivers/coremidi/midi_driver_coremidi.h b/drivers/coremidi/midi_driver_coremidi.h
index 0085141c6d..ac2ad99eb3 100644
--- a/drivers/coremidi/midi_driver_coremidi.h
+++ b/drivers/coremidi/midi_driver_coremidi.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef COREMIDI_ENABLED
-
#ifndef MIDI_DRIVER_COREMIDI_H
#define MIDI_DRIVER_COREMIDI_H
+#ifdef COREMIDI_ENABLED
+
#include "core/os/midi_driver.h"
#include "core/templates/vector.h"
@@ -57,5 +57,6 @@ public:
virtual ~MIDIDriverCoreMidi();
};
-#endif // MIDI_DRIVER_COREMIDI_H
#endif // COREMIDI_ENABLED
+
+#endif // MIDI_DRIVER_COREMIDI_H
diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub
index ddeec6f4c6..7e8bd22960 100644
--- a/drivers/gl_context/SCsub
+++ b/drivers/gl_context/SCsub
@@ -2,7 +2,7 @@
Import("env")
-if env["platform"] in ["haiku", "osx", "windows", "linuxbsd"]:
+if env["platform"] in ["haiku", "macos", "windows", "linuxbsd"]:
# Thirdparty source files
thirdparty_dir = "#thirdparty/glad/"
thirdparty_sources = [
diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp
index c8e6c2b476..de0181f887 100644
--- a/drivers/gles3/effects/copy_effects.cpp
+++ b/drivers/gles3/effects/copy_effects.cpp
@@ -111,6 +111,7 @@ CopyEffects::~CopyEffects() {
glDeleteVertexArrays(1, &screen_triangle_array);
glDeleteBuffers(1, &quad);
glDeleteVertexArrays(1, &quad_array);
+ copy.shader.version_free(copy.shader_version);
}
void CopyEffects::copy_to_rect(const Rect2i &p_rect) {
diff --git a/drivers/gles3/effects/copy_effects.h b/drivers/gles3/effects/copy_effects.h
index 1cf1ac9404..b863e76579 100644
--- a/drivers/gles3/effects/copy_effects.h
+++ b/drivers/gles3/effects/copy_effects.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COPY_GL_H
-#define COPY_GL_H
+#ifndef COPY_EFFECTS_GLES3_H
+#define COPY_EFFECTS_GLES3_H
#ifdef GLES3_ENABLED
@@ -70,4 +70,5 @@ public:
} //namespace GLES3
#endif // GLES3_ENABLED
-#endif // !COPY_GL_H
+
+#endif // COPY_EFFECTS_GLES3_H
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..350eb459cf
--- /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..7a0634f22b 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;
};
@@ -96,4 +93,4 @@ public:
#endif // GLES3_ENABLED
-#endif // !GI_GLES3_H
+#endif // GI_GLES3_H
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index d41c844d1d..83154acd51 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
@@ -135,7 +135,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
Transform3D screen_transform;
- screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
+ screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f));
_update_transform_to_mat4(screen_transform, state_buffer.screen_transform);
_update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
@@ -183,7 +183,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_state_buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW);
- GLuint global_buffer = material_storage->global_variables_get_uniform_buffer();
+ GLuint global_buffer = material_storage->global_shader_uniforms_get_uniform_buffer();
glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_LOCATION, global_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
@@ -815,10 +815,8 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
_bind_canvas_texture(texture, current_filter, current_repeat, r_index);
if (instance_count == 1) {
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES);
- } else if (instance_count > 1) {
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_INSTANCED);
} else {
- ERR_PRINT("Must have at least one mesh instance to draw mesh");
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_INSTANCED);
}
uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
@@ -882,7 +880,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
} else {
glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface));
}
- } else if (instance_count > 1) {
+ } else {
if (use_index_buffer) {
glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0, instance_count);
} else {
@@ -1217,7 +1215,7 @@ void RasterizerCanvasGLES3::reset_canvas() {
void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {
}
-void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) {
+void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache) {
}
void RasterizerCanvasGLES3::draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) {
@@ -1416,9 +1414,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();
@@ -1571,7 +1568,7 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage)
glBindBuffer(GL_UNIFORM_BUFFER, 0);
String global_defines;
- global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now
+ global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
global_defines += "#define MAX_LIGHTS " + itos(state.max_instances_per_batch) + "\n";
global_defines += "#define MAX_DRAW_DATA_INSTANCES " + itos(state.max_instances_per_batch) + "\n";
@@ -1611,6 +1608,8 @@ void fragment() {
RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+ memdelete_arr(state.instance_data_array);
+
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_free(state.canvas_shader_default_version);
material_storage->material_free(default_canvas_group_material);
material_storage->shader_free(default_canvas_group_shader);
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index bf13c91e1c..f920e37130 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -28,13 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RASTERIZER_CANVAS_OPENGL_H
-#define RASTERIZER_CANVAS_OPENGL_H
+#ifndef RASTERIZER_CANVAS_GLES3_H
+#define RASTERIZER_CANVAS_GLES3_H
#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,15 +203,13 @@ 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;
void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample);
void reset_canvas();
- void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache);
+ void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache);
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override;
@@ -260,9 +257,10 @@ public:
void set_time(double p_time);
static RasterizerCanvasGLES3 *get_singleton();
- RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage);
+ RasterizerCanvasGLES3();
~RasterizerCanvasGLES3();
};
#endif // GLES3_ENABLED
-#endif // RASTERIZER_CANVAS_OPENGL_H
+
+#endif // RASTERIZER_CANVAS_GLES3_H
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 78ffb42557..33303b1e38 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
@@ -68,7 +69,7 @@
#endif
#endif
-#if !defined(IPHONE_ENABLED) && !defined(JAVASCRIPT_ENABLED)
+#if !defined(IOS_ENABLED) && !defined(JAVASCRIPT_ENABLED)
// We include EGL below to get debug callback on GLES2 platforms,
// but EGL is not available on iOS.
#define CAN_DEBUG
@@ -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..97543af0d5 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -28,16 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RASTERIZER_OPENGL_H
-#define RASTERIZER_OPENGL_H
+#ifndef RASTERIZER_GLES3_H
+#define RASTERIZER_GLES3_H
#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; }
@@ -109,4 +112,4 @@ public:
#endif // GLES3_ENABLED
-#endif
+#endif // RASTERIZER_GLES3_H
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 33c7b9bf32..7207a6efbb 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -32,20 +32,18 @@
#include "core/config/project_settings.h"
#include "core/templates/sort_array.h"
#include "servers/rendering/rendering_server_default.h"
+#include "servers/rendering/rendering_server_globals.h"
#include "storage/config.h"
+#include "storage/light_storage.h"
+#include "storage/mesh_storage.h"
+#include "storage/texture_storage.h"
#ifdef GLES3_ENABLED
-uint64_t RasterizerSceneGLES3::auto_exposure_counter = 2;
-
RasterizerSceneGLES3 *RasterizerSceneGLES3::singleton = nullptr;
-RasterizerSceneGLES3 *RasterizerSceneGLES3::get_singleton() {
- return singleton;
-}
-
-RendererSceneRender::GeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_base) {
- RS::InstanceType type = storage->get_base_type(p_base);
+RenderGeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID 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();
@@ -54,176 +52,36 @@ RendererSceneRender::GeometryInstance *RasterizerSceneGLES3::geometry_instance_c
ginstance->data->base = p_base;
ginstance->data->base_type = type;
- _geometry_instance_mark_dirty(ginstance);
+ ginstance->_mark_dirty();
return ginstance;
}
-void RasterizerSceneGLES3::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->skeleton = p_skeleton;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_override = p_override;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_overlay = p_overlay;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->surface_materials = p_materials;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ERR_FAIL_COND(!ginstance);
- ginstance->mesh_instance = p_mesh_instance;
-
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->transform = p_transform;
- ginstance->mirror = p_transform.basis.determinant() < 0;
- ginstance->data->aabb = p_aabb;
- ginstance->transformed_aabb = p_transformed_aabb;
-
- Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
- // handle non uniform scale here
-
- float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
- float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
- ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
-
- ginstance->lod_model_scale = max_scale;
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->layer_mask = p_layer_mask;
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lod_bias = p_lod_bias;
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1);
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->fade_near = p_enable_near;
- ginstance->fade_near_begin = p_near_begin;
- ginstance->fade_near_end = p_near_end;
- ginstance->fade_far = p_enable_far;
- ginstance->fade_far_begin = p_far_begin;
- ginstance->fade_far_end = p_far_end;
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->parent_fade_alpha = p_alpha;
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_baked_light = p_enable;
-
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_dynamic_gi = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->shader_parameters_offset = p_offset;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->cast_double_sided_shadows = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-
uint32_t RasterizerSceneGLES3::geometry_instance_get_pair_mask() {
return (1 << RS::INSTANCE_LIGHT);
}
-void RasterizerSceneGLES3::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
+void RasterizerSceneGLES3::GeometryInstanceGLES3::pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) {
GLES3::Config *config = GLES3::Config::get_singleton();
- ginstance->omni_light_count = 0;
- ginstance->spot_light_count = 0;
- ginstance->omni_lights.clear();
- ginstance->spot_lights.clear();
+ omni_light_count = 0;
+ spot_light_count = 0;
+ omni_lights.clear();
+ spot_lights.clear();
for (uint32_t i = 0; i < p_light_instance_count; i++) {
- RS::LightType type = light_instance_get_type(p_light_instances[i]);
+ RS::LightType type = RasterizerSceneGLES3::get_singleton()->light_instance_get_type(p_light_instances[i]);
switch (type) {
case RS::LIGHT_OMNI: {
- if (ginstance->omni_light_count < (uint32_t)config->max_lights_per_object) {
- ginstance->omni_lights.push_back(p_light_instances[i]);
- ginstance->omni_light_count++;
+ if (omni_light_count < (uint32_t)config->max_lights_per_object) {
+ omni_lights.push_back(p_light_instances[i]);
+ omni_light_count++;
}
} break;
case RS::LIGHT_SPOT: {
- if (ginstance->spot_light_count < (uint32_t)config->max_lights_per_object) {
- ginstance->spot_lights.push_back(p_light_instances[i]);
- ginstance->spot_light_count++;
+ if (spot_light_count < (uint32_t)config->max_lights_per_object) {
+ spot_lights.push_back(p_light_instances[i]);
+ spot_light_count++;
}
} break;
default:
@@ -232,21 +90,7 @@ void RasterizerSceneGLES3::geometry_instance_pair_light_instances(GeometryInstan
}
}
-void RasterizerSceneGLES3::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
-}
-
-void RasterizerSceneGLES3::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
-}
-
-void RasterizerSceneGLES3::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
-}
-
-void RasterizerSceneGLES3::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-}
-
-void RasterizerSceneGLES3::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+void RasterizerSceneGLES3::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) {
GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
GeometryInstanceSurface *surf = ginstance->surface_caches;
@@ -259,24 +103,29 @@ void RasterizerSceneGLES3::geometry_instance_free(GeometryInstance *p_geometry_i
geometry_instance_alloc.free(ginstance);
}
-void RasterizerSceneGLES3::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
- GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
- if (ginstance->dirty_list_element.in_list()) {
+void RasterizerSceneGLES3::GeometryInstanceGLES3::_mark_dirty() {
+ if (dirty_list_element.in_list()) {
return;
}
//clear surface caches
- GeometryInstanceSurface *surf = ginstance->surface_caches;
+ GeometryInstanceSurface *surf = surface_caches;
while (surf) {
GeometryInstanceSurface *next = surf->next;
- geometry_instance_surface_alloc.free(surf);
+ RasterizerSceneGLES3::get_singleton()->geometry_instance_surface_alloc.free(surf);
surf = next;
}
- ginstance->surface_caches = nullptr;
+ surface_caches = nullptr;
- geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
+ RasterizerSceneGLES3::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element);
+}
+
+void RasterizerSceneGLES3::GeometryInstanceGLES3::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+}
+
+void RasterizerSceneGLES3::GeometryInstanceGLES3::set_lightmap_capture(const Color *p_sh9) {
}
void RasterizerSceneGLES3::_update_dirty_geometry_instances() {
@@ -285,16 +134,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: {
- static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ 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<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
} 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,8 +155,8 @@ void RasterizerSceneGLES3::_geometry_instance_dependency_changed(RendererStorage
}
}
-void RasterizerSceneGLES3::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
- static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+void RasterizerSceneGLES3::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
}
void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
@@ -376,7 +225,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
@@ -464,7 +313,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface(GeometryInstanceGLES3
}
}
-void RasterizerSceneGLES3::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) {
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
@@ -647,8 +496,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
while (sky) {
if (sky->radiance == 0) {
- sky->mipmap_count = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8) + 1;
-
+ sky->mipmap_count = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8) - 1;
// Left uninitialized, will attach a texture at render time
glGenFramebuffers(1, &sky->radiance_framebuffer);
@@ -675,7 +523,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1);
glGenTextures(1, &sky->raw_radiance);
glBindTexture(GL_TEXTURE_CUBE_MAP, sky->raw_radiance);
@@ -696,7 +544,8 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1);
+
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
@@ -712,13 +561,13 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
dirty_sky_list = nullptr;
}
-void RasterizerSceneGLES3::_setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
+void RasterizerSceneGLES3::_setup_sky(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
GLES3::SkyMaterialData *material = nullptr;
- Sky *sky = sky_owner.get_or_null(p_env->sky);
+ Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env));
RID sky_material;
@@ -853,22 +702,23 @@ void RasterizerSceneGLES3::_setup_sky(Environment *p_env, RID p_render_buffers,
}
if (!sky->radiance) {
+ _invalidate_sky(sky);
_update_dirty_skys();
}
}
}
-void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) {
+void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform) {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
- Sky *sky = sky_owner.get_or_null(p_env->sky);
+ Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env));
ERR_FAIL_COND(!sky);
GLES3::SkyMaterialData *material_data = nullptr;
RID sky_material;
- RS::EnvironmentBG background = p_env->background;
+ RS::EnvironmentBG background = environment_get_background(p_env);
if (sky) {
ERR_FAIL_COND(!sky);
@@ -898,18 +748,18 @@ void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_p
ERR_FAIL_COND(!shader_data);
// Camera
- CameraMatrix camera;
+ Projection camera;
- if (p_env->sky_custom_fov) {
+ if (environment_get_sky_custom_fov(p_env)) {
float near_plane = p_projection.get_z_near();
float far_plane = p_projection.get_z_far();
float aspect = p_projection.get_aspect();
- camera.set_perspective(p_env->sky_custom_fov, aspect, near_plane, far_plane);
+ camera.set_perspective(environment_get_sky_custom_fov(p_env), aspect, near_plane, far_plane);
} else {
camera = p_projection;
}
- Basis sky_transform = p_env->sky_orientation;
+ Basis sky_transform = environment_get_sky_orientation(p_env);
sky_transform.invert();
sky_transform = p_transform.basis * sky_transform;
@@ -923,17 +773,17 @@ void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_p
glDrawArrays(GL_TRIANGLES, 0, 3);
}
-void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) {
+void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform) {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
- Sky *sky = sky_owner.get_or_null(p_env->sky);
+ Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env));
ERR_FAIL_COND(!sky);
GLES3::SkyMaterialData *material_data = nullptr;
RID sky_material;
- RS::EnvironmentBG background = p_env->background;
+ RS::EnvironmentBG background = environment_get_background(p_env);
if (sky) {
ERR_FAIL_COND(!sky);
@@ -987,7 +837,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera
int max_processing_layer = sky->mipmap_count;
// Update radiance cubemap
- if (sky->reflection_dirty && (sky->processing_layer >= max_processing_layer || update_single_frame)) {
+ if (sky->reflection_dirty && (sky->processing_layer > max_processing_layer || update_single_frame)) {
static const Vector3 view_normals[6] = {
Vector3(+1, 0, 0),
Vector3(-1, 0, 0),
@@ -1005,9 +855,9 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera
Vector3(0, -1, 0)
};
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, 0.01, 10.0);
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
cm = correction * cm;
@@ -1048,6 +898,45 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera
}
}
+// Helper functions for IBL filtering
+
+Vector3 importance_sample_GGX(Vector2 xi, float roughness4) {
+ // Compute distribution direction
+ float phi = 2.0 * Math_PI * xi.x;
+ float cos_theta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y));
+ float sin_theta = sqrt(1.0 - cos_theta * cos_theta);
+
+ // Convert to spherical direction
+ Vector3 half_vector;
+ half_vector.x = sin_theta * cos(phi);
+ half_vector.y = sin_theta * sin(phi);
+ half_vector.z = cos_theta;
+
+ return half_vector;
+}
+
+float distribution_GGX(float NdotH, float roughness4) {
+ float NdotH2 = NdotH * NdotH;
+ float denom = (NdotH2 * (roughness4 - 1.0) + 1.0);
+ denom = Math_PI * denom * denom;
+
+ return roughness4 / denom;
+}
+
+float radical_inverse_vdC(uint32_t bits) {
+ 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);
+
+ return float(bits) * 2.3283064365386963e-10;
+}
+
+Vector2 hammersley(uint32_t i, uint32_t N) {
+ return Vector2(float(i) / float(N), radical_inverse_vdC(i));
+}
+
void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int p_base_layer) {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
@@ -1059,27 +948,68 @@ void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int p_base_layer) {
if (p_base_layer == 0) {
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ // Copy over base layer without filtering.
mode = CubemapFilterShaderGLES3::MODE_COPY;
-
- //Copy over base layer
}
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, sky_globals.radical_inverse_vdc_cache_tex);
int size = p_sky->radiance_size >> p_base_layer;
glViewport(0, 0, size, size);
glBindVertexArray(sky_globals.screen_triangle_array);
material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, mode);
- material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::SAMPLE_COUNT, sky_globals.ggx_samples, scene_globals.cubemap_filter_shader_version, mode);
- material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, float(p_base_layer) / (p_sky->mipmap_count - 1.0), scene_globals.cubemap_filter_shader_version, mode);
- material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_SIZE, float(size), scene_globals.cubemap_filter_shader_version, mode);
+
+ if (p_base_layer > 0) {
+ const uint32_t sample_counts[4] = { 1, sky_globals.ggx_samples / 4, sky_globals.ggx_samples / 2, sky_globals.ggx_samples };
+ uint32_t sample_count = sample_counts[MIN(3, p_base_layer)];
+
+ float roughness = float(p_base_layer) / (p_sky->mipmap_count);
+ float roughness4 = roughness * roughness;
+ roughness4 *= roughness4;
+
+ float solid_angle_texel = 4.0 * Math_PI / float(6 * size * size);
+
+ LocalVector<float> sample_directions;
+ sample_directions.resize(4 * sample_count);
+
+ uint32_t index = 0;
+ float weight = 0.0;
+ for (uint32_t i = 0; i < sample_count; i++) {
+ Vector2 xi = hammersley(i, sample_count);
+ Vector3 dir = importance_sample_GGX(xi, roughness4);
+ Vector3 light_vec = (2.0 * dir.z * dir - Vector3(0.0, 0.0, 1.0));
+
+ if (light_vec.z < 0.0) {
+ continue;
+ }
+
+ sample_directions[index * 4] = light_vec.x;
+ sample_directions[index * 4 + 1] = light_vec.y;
+ sample_directions[index * 4 + 2] = light_vec.z;
+
+ float D = distribution_GGX(dir.z, roughness4);
+ float pdf = D * dir.z / (4.0 * dir.z) + 0.0001;
+
+ float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001);
+
+ float mip_level = MAX(0.5 * log2(solid_angle_sample / solid_angle_texel) + float(MAX(1, p_base_layer - 3)), 1.0);
+
+ sample_directions[index * 4 + 3] = mip_level;
+ weight += light_vec.z;
+ index++;
+ }
+
+ glUniform4fv(material_storage->shaders.cubemap_filter_shader.version_get_uniform(CubemapFilterShaderGLES3::SAMPLE_DIRECTIONS_MIP, scene_globals.cubemap_filter_shader_version, mode), sample_count, sample_directions.ptr());
+ material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::WEIGHT, weight, scene_globals.cubemap_filter_shader_version, mode);
+ material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::SAMPLE_COUNT, index, scene_globals.cubemap_filter_shader_version, mode);
+ }
for (int i = 0; i < 6; i++) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, p_sky->radiance, p_base_layer);
#ifdef DEBUG_ENABLED
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ WARN_PRINT("Could not bind sky radiance face: " + itos(i) + ", status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status));
+ }
#endif
material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_ID, i, scene_globals.cubemap_filter_shader_version, mode);
@@ -1096,84 +1026,6 @@ Ref<Image> RasterizerSceneGLES3::sky_bake_panorama(RID p_sky, float p_energy, bo
/* ENVIRONMENT API */
-RID RasterizerSceneGLES3::environment_allocate() {
- return environment_owner.allocate_rid();
-}
-
-void RasterizerSceneGLES3::environment_initialize(RID p_rid) {
- environment_owner.initialize_rid(p_rid);
-}
-
-void RasterizerSceneGLES3::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->background = p_bg;
-}
-
-void RasterizerSceneGLES3::environment_set_sky(RID p_env, RID p_sky) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->sky = p_sky;
-}
-
-void RasterizerSceneGLES3::environment_set_sky_custom_fov(RID p_env, float p_scale) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->sky_custom_fov = p_scale;
-}
-
-void RasterizerSceneGLES3::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->sky_orientation = p_orientation;
-}
-
-void RasterizerSceneGLES3::environment_set_bg_color(RID p_env, const Color &p_color) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->bg_color = p_color;
-}
-
-void RasterizerSceneGLES3::environment_set_bg_energy(RID p_env, float p_energy) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->bg_energy = p_energy;
-}
-
-void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->canvas_max_layer = p_max_layer;
-}
-
-void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->ambient_light = p_color;
- env->ambient_source = p_ambient;
- env->ambient_light_energy = p_energy;
- env->ambient_sky_contribution = p_sky_contribution;
- env->reflection_source = p_reflection_source;
-}
-
-void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
- env->glow_enabled = p_enable;
- env->glow_levels = p_levels;
- env->glow_intensity = p_intensity;
- env->glow_strength = p_strength;
- env->glow_mix = p_mix;
- env->glow_bloom = p_bloom_threshold;
- env->glow_blend_mode = p_blend_mode;
- env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
- env->glow_hdr_bleed_scale = p_hdr_bleed_scale;
- env->glow_hdr_luminance_cap = p_hdr_luminance_cap;
- env->glow_map_strength = p_glow_map_strength;
- env->glow_map = p_glow_map;
-}
-
void RasterizerSceneGLES3::environment_glow_set_use_bicubic_upscale(bool p_enable) {
glow_bicubic_upscale = p_enable;
}
@@ -1182,35 +1034,15 @@ void RasterizerSceneGLES3::environment_glow_set_use_high_quality(bool p_enable)
glow_high_quality = p_enable;
}
-void RasterizerSceneGLES3::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->ssr_enabled = p_enable;
- env->ssr_max_steps = p_max_steps;
- env->ssr_fade_in = p_fade_int;
- env->ssr_fade_out = p_fade_out;
- env->ssr_depth_tolerance = p_depth_tolerance;
-}
-
void RasterizerSceneGLES3::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
}
-void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-}
-
void RasterizerSceneGLES3::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
}
-void RasterizerSceneGLES3::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) {
-}
void RasterizerSceneGLES3::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
}
-void RasterizerSceneGLES3::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
-}
-
void RasterizerSceneGLES3::environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) {
}
@@ -1220,49 +1052,6 @@ void RasterizerSceneGLES3::environment_set_sdfgi_frames_to_converge(RS::Environm
void RasterizerSceneGLES3::environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) {
}
-void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->exposure = p_exposure;
- env->tone_mapper = p_tone_mapper;
- if (!env->auto_exposure && p_auto_exposure) {
- env->auto_exposure_version = ++auto_exposure_counter;
- }
- env->auto_exposure = p_auto_exposure;
- env->white = p_white;
- env->min_luminance = p_min_luminance;
- env->max_luminance = p_max_luminance;
- env->auto_exp_speed = p_auto_exp_speed;
- env->auto_exp_scale = p_auto_exp_scale;
-}
-
-void RasterizerSceneGLES3::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->adjustments_enabled = p_enable;
- env->adjustments_brightness = p_brightness;
- env->adjustments_contrast = p_contrast;
- env->adjustments_saturation = p_saturation;
- env->use_1d_color_correction = p_use_1d_color_correction;
- env->color_correction = p_color_correction;
-}
-
-void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->fog_enabled = p_enable;
- env->fog_light_color = p_light_color;
- env->fog_light_energy = p_light_energy;
- env->fog_sun_scatter = p_sun_scatter;
- env->fog_density = p_density;
- env->fog_height = p_height;
- env->fog_height_density = p_height_density;
- env->fog_aerial_perspective = p_aerial_perspective;
-}
-
-void RasterizerSceneGLES3::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
-}
-
void RasterizerSceneGLES3::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) {
}
@@ -1270,27 +1059,9 @@ void RasterizerSceneGLES3::environment_set_volumetric_fog_filter_active(bool p_e
}
Ref<Image> RasterizerSceneGLES3::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Ref<Image>());
return Ref<Image>();
}
-bool RasterizerSceneGLES3::is_environment(RID p_env) const {
- return environment_owner.owns(p_env);
-}
-
-RS::EnvironmentBG RasterizerSceneGLES3::environment_get_background(RID p_env) const {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX);
- return env->background;
-}
-
-int RasterizerSceneGLES3::environment_get_canvas_max_layer(RID p_env) const {
- Environment *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->canvas_max_layer;
-}
-
RID RasterizerSceneGLES3::camera_effects_allocate() {
return RID();
}
@@ -1310,10 +1081,10 @@ void RasterizerSceneGLES3::camera_effects_set_dof_blur(RID p_camera_effects, boo
void RasterizerSceneGLES3::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) {
}
-void RasterizerSceneGLES3::shadows_quality_set(RS::ShadowQuality p_quality) {
+void RasterizerSceneGLES3::positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) {
}
-void RasterizerSceneGLES3::directional_shadow_quality_set(RS::ShadowQuality p_quality) {
+void RasterizerSceneGLES3::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) {
}
RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
@@ -1342,7 +1113,7 @@ void RasterizerSceneGLES3::light_instance_set_aabb(RID p_light_instance, const A
light_instance->aabb = p_aabb;
}
-void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
+void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
}
void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) {
@@ -1428,7 +1199,7 @@ bool RasterizerSceneGLES3::voxel_gi_needs_update(RID p_probe) const {
return false;
}
-void RasterizerSceneGLES3::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) {
+void RasterizerSceneGLES3::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) {
}
void RasterizerSceneGLES3::voxel_gi_set_quality(RS::VoxelGIQuality) {
@@ -1605,14 +1376,14 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
// Needs to be called after _setup_lights so that directional_light_count is accurate.
void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(p_flip_y);
- CameraMatrix projection = correction * p_render_data->cam_projection;
+ Projection 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;
@@ -1630,18 +1401,17 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
scene_state.ubo.time = time;
if (is_environment(p_render_data->environment)) {
- Environment *env = environment_owner.get_or_null(p_render_data->environment);
- RS::EnvironmentBG env_bg = env->background;
- RS::EnvironmentAmbientSource ambient_src = env->ambient_source;
+ RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment);
+ RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment);
- float bg_energy = env->bg_energy;
+ float bg_energy = environment_get_bg_energy(p_render_data->environment);
scene_state.ubo.ambient_light_color_energy[3] = bg_energy;
- scene_state.ubo.ambient_color_sky_mix = env->ambient_sky_contribution;
+ scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment);
//ambient
if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
- Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : env->bg_color;
+ Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
@@ -1650,42 +1420,42 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
scene_state.ubo.use_ambient_light = true;
scene_state.ubo.use_ambient_cubemap = false;
} else {
- float energy = env->ambient_light_energy;
- Color color = env->ambient_light;
+ float energy = environment_get_ambient_light_energy(p_render_data->environment);
+ Color color = environment_get_ambient_light(p_render_data->environment);
color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * energy;
scene_state.ubo.ambient_light_color_energy[2] = color.b * energy;
- Basis sky_transform = env->sky_orientation;
+ Basis sky_transform = environment_get_sky_orientation(p_render_data->environment);
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;
}
//specular
- RS::EnvironmentReflectionSource ref_src = env->reflection_source;
+ RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_render_data->environment);
if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) {
scene_state.ubo.use_reflection_cubemap = true;
} else {
scene_state.ubo.use_reflection_cubemap = false;
}
- scene_state.ubo.fog_enabled = env->fog_enabled;
- scene_state.ubo.fog_density = env->fog_density;
- scene_state.ubo.fog_height = env->fog_height;
- scene_state.ubo.fog_height_density = env->fog_height_density;
- scene_state.ubo.fog_aerial_perspective = env->fog_aerial_perspective;
+ scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment);
+ scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
+ scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
+ scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
+ scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
- Color fog_color = env->fog_light_color.srgb_to_linear();
- float fog_energy = env->fog_light_energy;
+ Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear();
+ float fog_energy = environment_get_fog_light_energy(p_render_data->environment);
scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy;
- scene_state.ubo.fog_sun_scatter = env->fog_sun_scatter;
+ scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment);
} else {
}
@@ -1880,7 +1650,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
- light_data.shadow_enabled = false;
+ light_data.shadow_opacity = 0.0;
}
// TODO, to avoid stalls, should rotate between 3 buffers based on frame index.
@@ -1902,7 +1672,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
-void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
RENDER_TIMESTAMP("Setup 3D Scene");
@@ -1967,18 +1737,16 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
// Fill Light lists here
//////////
- GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_variables_get_uniform_buffer();
+ GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_shader_uniforms_get_uniform_buffer();
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
Color clear_color;
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);
-
bool fb_cleared = false;
Size2i screen_size;
@@ -1988,10 +1756,10 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
bool use_wireframe = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME;
SceneState::TonemapUBO tonemap_ubo;
- if (env) {
- tonemap_ubo.exposure = env->exposure;
- tonemap_ubo.white = env->white;
- tonemap_ubo.tonemapper = int32_t(env->tone_mapper);
+ if (render_data.environment.is_valid()) {
+ tonemap_ubo.exposure = environment_get_exposure(render_data.environment);
+ tonemap_ubo.white = environment_get_white(render_data.environment);
+ tonemap_ubo.tonemapper = int32_t(environment_get_tone_mapper(render_data.environment));
}
if (scene_state.tonemap_buffer == 0) {
@@ -2014,25 +1782,25 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
- } else if (env) {
- RS::EnvironmentBG bg_mode = env->background;
- float bg_energy = env->bg_energy;
+ } else if (render_data.environment.is_valid()) {
+ RS::EnvironmentBG bg_mode = environment_get_background(render_data.environment);
+ float bg_energy = environment_get_bg_energy(render_data.environment);
switch (bg_mode) {
case RS::ENV_BG_CLEAR_COLOR: {
clear_color.r *= bg_energy;
clear_color.g *= bg_energy;
clear_color.b *= bg_energy;
- if (env->fog_enabled) {
+ if (environment_get_fog_enabled(render_data.environment)) {
draw_sky_fog_only = true;
GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color));
}
} break;
case RS::ENV_BG_COLOR: {
- clear_color = env->bg_color;
+ clear_color = environment_get_bg_color(render_data.environment);
clear_color.r *= bg_energy;
clear_color.g *= bg_energy;
clear_color.b *= bg_energy;
- if (env->fog_enabled) {
+ if (environment_get_fog_enabled(render_data.environment)) {
draw_sky_fog_only = true;
GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color));
}
@@ -2052,20 +1820,20 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
}
}
// setup sky if used for ambient, reflections, or background
- if (draw_sky || draw_sky_fog_only || env->reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || env->ambient_source == RS::ENV_AMBIENT_SOURCE_SKY) {
+ if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
- CameraMatrix projection = render_data.cam_projection;
+ Projection projection = render_data.cam_projection;
if (render_data.reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
projection = correction * render_data.cam_projection;
}
- _setup_sky(env, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size);
+ _setup_sky(render_data.environment, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size);
- if (env->sky.is_valid()) {
- if (env->reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || env->ambient_source == RS::ENV_AMBIENT_SOURCE_SKY || (env->reflection_source == RS::ENV_REFLECTION_SOURCE_BG && env->background == RS::ENV_BG_SKY)) {
- _update_sky_radiance(env, projection, render_data.cam_transform);
+ if (environment_get_sky(render_data.environment).is_valid()) {
+ if (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY || (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_BG && environment_get_background(render_data.environment) == RS::ENV_BG_SKY)) {
+ _update_sky_radiance(render_data.environment, projection, render_data.cam_transform);
}
} else {
// do not try to draw sky if invalid
@@ -2145,7 +1913,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS;
}
- if (!env || (env && !env->fog_enabled)) {
+ if (render_data.environment.is_null() || (render_data.environment.is_valid() && !environment_get_fog_enabled(render_data.environment))) {
spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG;
}
}
@@ -2169,7 +1937,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_DISABLED;
scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
- _draw_sky(env, render_data.cam_projection, render_data.cam_transform);
+ _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform);
}
RENDER_TIMESTAMP("Render 3D Transparent Pass");
@@ -2218,11 +1986,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
- Environment *env = environment_owner.get_or_null(p_render_data->environment);
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 2);
GLuint texture_to_bind = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_CUBEMAP_BLACK))->tex_id;
- if (env) {
- Sky *sky = sky_owner.get_or_null(env->sky);
+ if (p_render_data->environment.is_valid()) {
+ Sky *sky = sky_owner.get_or_null(environment_get_sky(p_render_data->environment));
if (sky && sky->radiance != 0) {
texture_to_bind = sky->radiance;
// base_spec_constant |= USE_RADIANCE_MAP;
@@ -2487,10 +2254,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
}
-void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
}
-void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
+void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) {
}
void RasterizerSceneGLES3::set_time(double p_time, double p_step) {
@@ -2507,7 +2274,7 @@ RID RasterizerSceneGLES3::render_buffers_create() {
return render_buffers_owner.make_rid(rb);
}
-void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
@@ -2540,7 +2307,7 @@ void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_
glGenTextures(1, &rb->depth_texture);
glBindTexture(GL_TEXTURE_2D, rb->depth_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -2621,8 +2388,8 @@ TypedArray<Image> RasterizerSceneGLES3::bake_render_uv2(RID p_base, const Vector
}
bool RasterizerSceneGLES3::free(RID p_rid) {
- if (environment_owner.owns(p_rid)) {
- environment_owner.free(p_rid);
+ if (is_environment(p_rid)) {
+ environment_free(p_rid);
} else if (sky_owner.owns(p_rid)) {
Sky *sky = sky_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!sky, false);
@@ -2657,12 +2424,12 @@ 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() {
+ singleton = this;
+
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
- storage = p_storage;
-
{
// Setup Lights
@@ -2704,7 +2471,7 @@ RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) {
{
String global_defines;
- global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now
+ global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
global_defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(config->max_renderable_lights) + "\n";
global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n";
global_defines += "\n#define MAX_FORWARD_LIGHTS " + itos(config->max_lights_per_object) + "\n";
@@ -2743,13 +2510,17 @@ void fragment() {
sky_globals.ggx_samples = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples");
String global_defines;
- global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now
+ global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_globals.max_directional_lights) + "\n";
material_storage->shaders.sky_shader.initialize(global_defines);
sky_globals.shader_default_version = material_storage->shaders.sky_shader.version_create();
material_storage->shaders.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND);
+ }
- material_storage->shaders.cubemap_filter_shader.initialize();
+ {
+ String global_defines;
+ global_defines += "\n#define MAX_SAMPLE_COUNT " + itos(sky_globals.ggx_samples) + "\n";
+ material_storage->shaders.cubemap_filter_shader.initialize(global_defines);
scene_globals.cubemap_filter_shader_version = material_storage->shaders.cubemap_filter_shader.version_create();
material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, CubemapFilterShaderGLES3::MODE_DEFAULT);
}
@@ -2819,36 +2590,6 @@ void sky() {
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
}
- // Radical inverse vdc cache texture used for cubemap filtering.
- {
- glGenTextures(1, &sky_globals.radical_inverse_vdc_cache_tex);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, sky_globals.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_RED, 512, 1, 0, GL_RED, GL_UNSIGNED_BYTE, radical_inverse);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //need this for proper sampling
-
- glBindTexture(GL_TEXTURE_2D, 0);
- }
#ifdef GLES_OVER_GL
glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS);
#endif
@@ -2870,21 +2611,23 @@ 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);
glDeleteBuffers(1, &sky_globals.directional_light_buffer);
memdelete_arr(sky_globals.directional_lights);
memdelete_arr(sky_globals.last_frame_directional_lights);
+
+ singleton = nullptr;
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 4757a3f161..a54d87a3a3 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -28,16 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RASTERIZER_SCENE_OPENGL_H
-#define RASTERIZER_SCENE_OPENGL_H
+#ifndef RASTERIZER_SCENE_GLES3_H
+#define RASTERIZER_SCENE_GLES3_H
#ifdef GLES3_ENABLED
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#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
@@ -95,18 +96,18 @@ struct RenderDataGLES3 {
Transform3D cam_transform = Transform3D();
Transform3D inv_cam_transform = Transform3D();
- CameraMatrix cam_projection = CameraMatrix();
+ Projection cam_projection = Projection();
bool cam_orthogonal = false;
// For stereo rendering
uint32_t view_count = 1;
Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS];
- CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
float z_near = 0.0;
float z_far = 0.0;
- const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr;
+ const PagedArray<RenderGeometryInstance *> *instances = nullptr;
const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr;
RID environment = RID();
@@ -125,7 +126,6 @@ struct RenderDataGLES3 {
RendererScene::RenderInfo *render_info = nullptr;
};
-class RasterizerStorageGLES3;
class RasterizerCanvasGLES3;
class RasterizerSceneGLES3 : public RendererSceneRender {
@@ -165,7 +165,7 @@ private:
float inv_spot_attenuation;
float cos_spot_angle;
float specular_amount;
- uint32_t shadow_enabled;
+ float shadow_opacity;
};
static_assert(sizeof(LightData) % 16 == 0, "LightData size must be a multiple of 16 bytes");
@@ -210,7 +210,7 @@ private:
mutable RID_Owner<LightInstance> light_instance_owner;
- struct GeometryInstanceGLES3;
+ class GeometryInstanceGLES3;
// Cached data for drawing surfaces
struct GeometryInstanceSurface {
@@ -265,33 +265,16 @@ private:
GeometryInstanceGLES3 *owner = nullptr;
};
- struct GeometryInstanceGLES3 : public GeometryInstance {
+ class GeometryInstanceGLES3 : public RenderGeometryInstanceBase {
+ public:
//used during rendering
- bool mirror = false;
- bool non_uniform_scale = false;
- float lod_bias = 0.0;
- float lod_model_scale = 1.0;
- AABB transformed_aabb; //needed for LOD
- float depth = 0;
- uint32_t flags_cache = 0;
bool store_transform_cache = true;
- int32_t shader_parameters_offset = -1;
- uint32_t layer_mask = 1;
int32_t instance_count = 0;
- RID mesh_instance;
bool can_sdfgi = false;
bool using_projectors = false;
bool using_softshadows = false;
- bool fade_near = false;
- float fade_near_begin = 0;
- float fade_near_end = 0;
- bool fade_far = false;
- float fade_far_begin = 0;
- float fade_far_end = 0;
- float force_alpha = 1.0;
- float parent_fade_alpha = 1.0;
uint32_t omni_light_count = 0;
LocalVector<RID> omni_lights;
@@ -301,35 +284,22 @@ private:
LocalVector<uint32_t> spot_light_gl_cache;
//used during setup
- uint32_t base_flags = 0;
- Transform3D transform;
GeometryInstanceSurface *surface_caches = nullptr;
SelfList<GeometryInstanceGLES3> dirty_list_element;
- struct Data {
- //data used less often goes into regular heap
- RID base;
- RS::InstanceType base_type;
-
- RID skeleton;
- Vector<RID> surface_materials;
- RID material_override;
- RID material_overlay;
- AABB aabb;
-
- bool use_dynamic_gi = false;
- bool use_baked_light = false;
- bool cast_double_sided_shadows = false;
- bool mirror = false;
- bool dirty_dependencies = false;
+ GeometryInstanceGLES3() :
+ dirty_list_element(this) {}
- RendererStorage::DependencyTracker dependency_tracker;
- };
+ virtual void _mark_dirty() override;
+ virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
+ virtual void set_lightmap_capture(const Color *p_sh9) override;
- Data *data = nullptr;
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override;
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
- GeometryInstanceGLES3() :
- dirty_list_element(this) {}
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override {}
};
enum {
@@ -345,8 +315,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;
@@ -357,8 +327,7 @@ private:
void _geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
- void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
- void _geometry_instance_update(GeometryInstance *p_geometry_instance);
+ void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
struct SceneState {
@@ -570,88 +539,8 @@ protected:
/* Environment */
- struct Environment {
- // BG
- RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR;
- RID sky;
- float sky_custom_fov = 0.0;
- Basis sky_orientation;
- Color bg_color;
- float bg_energy = 1.0;
- int canvas_max_layer = 0;
- RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG;
- Color ambient_light;
- float ambient_light_energy = 1.0;
- float ambient_sky_contribution = 1.0;
- RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
- Color ao_color;
-
- /// Tonemap
-
- RS::EnvironmentToneMapper tone_mapper;
- float exposure = 1.0;
- float white = 1.0;
- bool auto_exposure = false;
- float min_luminance = 0.2;
- float max_luminance = 8.0;
- float auto_exp_speed = 0.2;
- float auto_exp_scale = 0.5;
- uint64_t auto_exposure_version = 0;
-
- // Fog
- bool fog_enabled = false;
- Color fog_light_color = Color(0.5, 0.6, 0.7);
- float fog_light_energy = 1.0;
- float fog_sun_scatter = 0.0;
- float fog_density = 0.001;
- float fog_height = 0.0;
- float fog_height_density = 0.0; //can be negative to invert effect
- float fog_aerial_perspective = 0.0;
-
- /// Glow
- bool glow_enabled = false;
- Vector<float> glow_levels;
- float glow_intensity = 0.8;
- float glow_strength = 1.0;
- float glow_bloom = 0.0;
- float glow_mix = 0.01;
- RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT;
- float glow_hdr_bleed_threshold = 1.0;
- float glow_hdr_luminance_cap = 12.0;
- float glow_hdr_bleed_scale = 2.0;
- float glow_map_strength = 1.0;
- RID glow_map = RID();
-
- /// SSAO
- bool ssao_enabled = false;
- float ssao_radius = 1.0;
- float ssao_intensity = 2.0;
- float ssao_power = 1.5;
- float ssao_detail = 0.5;
- float ssao_horizon = 0.06;
- float ssao_sharpness = 0.98;
- float ssao_direct_light_affect = 0.0;
- float ssao_ao_channel_affect = 0.0;
-
- /// SSR
- bool ssr_enabled = false;
- int ssr_max_steps = 64;
- float ssr_fade_in = 0.15;
- float ssr_fade_out = 2.0;
- float ssr_depth_tolerance = 0.2;
-
- /// Adjustments
- bool adjustments_enabled = false;
- float adjustments_brightness = 1.0f;
- float adjustments_contrast = 1.0f;
- float adjustments_saturation = 1.0f;
- bool use_1d_color_correction = false;
- RID color_correction = RID();
- };
-
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
bool ssao_half_size = false;
- bool ssao_using_half_size = false;
float ssao_adaptive_target = 0.5;
int ssao_blur_passes = 2;
float ssao_fadeout_from = 50.0;
@@ -661,10 +550,6 @@ protected:
bool glow_high_quality = false;
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
- static uint64_t auto_exposure_counter;
-
- mutable RID_Owner<Environment, true> environment_owner;
-
/* Sky */
struct SkyGlobals {
@@ -730,45 +615,23 @@ protected:
Sky *dirty_sky_list = nullptr;
mutable RID_Owner<Sky, true> sky_owner;
- void _setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
+ void _setup_sky(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
void _invalidate_sky(Sky *p_sky);
void _update_dirty_skys();
- void _update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform);
+ void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform);
void _filter_sky_radiance(Sky *p_sky, int p_base_layer);
- void _draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform);
+ void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform);
void _free_sky_data(Sky *p_sky);
public:
- RasterizerStorageGLES3 *storage;
+ static RasterizerSceneGLES3 *get_singleton() { return singleton; }
+
RasterizerCanvasGLES3 *canvas;
- GeometryInstance *geometry_instance_create(RID p_base) override;
- void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
- void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
- void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override;
- void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override;
- void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
- void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override;
- void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
- void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
- void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
- void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
- void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
- void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
- void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
- void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
- void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
- void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
- void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
+ RenderGeometryInstance *geometry_instance_create(RID p_base) override;
+ void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
uint32_t geometry_instance_get_pair_mask() override;
- void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
- void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
- void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
- void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
- void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
-
- void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
/* SHADOW ATLAS API */
@@ -805,49 +668,24 @@ public:
/* ENVIRONMENT API */
- RID environment_allocate() override;
- void environment_initialize(RID p_rid) override;
- void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override;
- void environment_set_sky(RID p_env, RID p_sky) override;
- void environment_set_sky_custom_fov(RID p_env, float p_scale) override;
- void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override;
- void environment_set_bg_color(RID p_env, const Color &p_color) override;
- void environment_set_bg_energy(RID p_env, float p_energy) override;
- void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override;
- void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override;
-
- void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override;
void environment_glow_set_use_bicubic_upscale(bool p_enable) override;
void environment_glow_set_use_high_quality(bool p_enable) override;
- void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override;
void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override;
- void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override;
+
void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
- void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override;
- void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
- void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override;
+ void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override;
void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override;
void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override;
- void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override;
-
- void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override;
-
- void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override;
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override;
void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override;
void environment_set_volumetric_fog_filter_active(bool p_enable) override;
Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
- bool is_environment(RID p_env) const override;
- RS::EnvironmentBG environment_get_background(RID p_env) const override;
- int environment_get_canvas_max_layer(RID p_env) const override;
-
RID camera_effects_allocate() override;
void camera_effects_initialize(RID p_rid) override;
void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override;
@@ -856,13 +694,13 @@ public:
void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override;
void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
- void shadows_quality_set(RS::ShadowQuality p_quality) override;
- void directional_shadow_quality_set(RS::ShadowQuality p_quality) override;
+ void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
+ void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
RID light_instance_create(RID p_light) override;
void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
+ void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
void light_instance_mark_visible(RID p_light_instance) override;
_FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) {
@@ -901,13 +739,13 @@ public:
RID voxel_gi_instance_create(RID p_voxel_gi) override;
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override;
bool voxel_gi_needs_update(RID p_probe) const override;
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override;
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override;
void voxel_gi_set_quality(RS::VoxelGIQuality) override;
- void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
- void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override;
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+ void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override;
void set_scene_pass(uint64_t p_pass) override {
scene_pass = p_pass;
@@ -924,7 +762,7 @@ public:
}
RID render_buffers_create() override;
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
void gi_set_use_half_resolution(bool p_enable) override;
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override;
@@ -942,11 +780,10 @@ public:
void decals_set_filter(RS::DecalFilter p_filter) override;
void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
- static RasterizerSceneGLES3 *get_singleton();
- RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage);
+ RasterizerSceneGLES3();
~RasterizerSceneGLES3();
};
#endif // GLES3_ENABLED
-#endif // RASTERIZER_SCENE_OPENGL_H
+#endif // RASTERIZER_SCENE_GLES3_H
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/shader_gles3.h b/drivers/gles3/shader_gles3.h
index e1385669cd..2b72549b5b 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHADER_OPENGL_H
-#define SHADER_OPENGL_H
+#ifndef SHADER_GLES3_H
+#define SHADER_GLES3_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/os/mutex.h"
#include "core/string/string_builder.h"
#include "core/templates/hash_map.h"
@@ -248,5 +248,6 @@ public:
virtual ~ShaderGLES3();
};
-#endif // SHADER_OPENGL_H
-#endif
+#endif // GLES3_ENABLED
+
+#endif // SHADER_GLES3_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/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl
index e08a15e59d..852dccf415 100644
--- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl
+++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl
@@ -58,8 +58,8 @@ struct DrawData {
uvec4 lights;
};
-layout(std140) uniform GlobalVariableData { //ubo:1
- vec4 global_variables[MAX_GLOBAL_VARIABLES];
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
layout(std140) uniform CanvasData { //ubo:0
diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl
index ebf0c08ec4..88464876f1 100644
--- a/drivers/gles3/shaders/cubemap_filter.glsl
+++ b/drivers/gles3/shaders/cubemap_filter.glsl
@@ -29,19 +29,15 @@ uniform samplerCube source_cube; //texunit:0
/* clang-format on */
uniform int face_id;
-uniform float roughness;
-uniform float face_size;
-uniform int sample_count;
-//Todo, profile on low end hardware to see if fixed loop is faster
-#ifdef USE_FIXED_SAMPLES
-#define FIXED_SAMPLE_COUNT 32
+#ifndef MODE_DIRECT_WRITE
+uniform int sample_count;
+uniform vec4 sample_directions_mip[MAX_SAMPLE_COUNT];
+uniform float weight;
#endif
in highp vec2 uv_interp;
-uniform sampler2D radical_inverse_vdc_cache; // texunit:1
-
layout(location = 0) out vec4 frag_color;
#define M_PI 3.14159265359
@@ -93,48 +89,6 @@ vec3 texelCoordToVec(vec2 uv, int faceID) {
return normalize(result);
}
-vec3 ImportanceSampleGGX(vec2 xi, float roughness4) {
- // Compute distribution direction
- float Phi = 2.0 * M_PI * xi.x;
- float CosTheta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y));
- float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
-
- // Convert to spherical direction
- vec3 H;
- H.x = SinTheta * cos(Phi);
- H.y = SinTheta * sin(Phi);
- H.z = CosTheta;
-
- return H;
-}
-
-float DistributionGGX(float NdotH, float roughness4) {
- float NdotH2 = NdotH * NdotH;
- float denom = (NdotH2 * (roughness4 - 1.0) + 1.0);
- denom = M_PI * denom * denom;
-
- return roughness4 / denom;
-}
-
-// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
-float GGX(float NdotV, float a) {
- float k = a / 2.0;
- return NdotV / (NdotV * (1.0 - k) + k);
-}
-
-// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
-float G_Smith(float a, float nDotV, float nDotL) {
- return GGX(nDotL, a * a) * GGX(nDotV, a * a);
-}
-
-float radical_inverse_VdC(int i) {
- return texture(radical_inverse_vdc_cache, vec2(float(i) / 512.0, 0.0)).x;
-}
-
-vec2 Hammersley(int i, int N) {
- return vec2(float(i) / float(N), radical_inverse_VdC(i));
-}
-
void main() {
vec3 color = vec3(0.0);
vec2 uv = uv_interp;
@@ -145,9 +99,6 @@ void main() {
#else
vec4 sum = vec4(0.0);
- float solid_angle_texel = 4.0 * M_PI / (6.0 * face_size * face_size);
- float roughness2 = roughness * roughness;
- float roughness4 = roughness2 * roughness2;
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
mat3 T;
T[0] = normalize(cross(UpVector, N));
@@ -155,32 +106,15 @@ void main() {
T[2] = N;
for (int sample_num = 0; sample_num < sample_count; sample_num++) {
- vec2 xi = Hammersley(sample_num, sample_count);
-
- vec3 H = T * ImportanceSampleGGX(xi, roughness4);
- float NdotH = dot(N, H);
- vec3 L = (2.0 * NdotH * H - N);
-
- float NdotL = clamp(dot(N, L), 0.0, 1.0);
-
- if (NdotL > 0.0) {
- float D = DistributionGGX(NdotH, roughness4);
- float pdf = D * NdotH / (4.0 * NdotH) + 0.0001;
-
- float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001);
-
- float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(solid_angle_sample / solid_angle_texel);
-
- vec3 val = textureLod(source_cube, L, mipLevel).rgb;
- // Mix using linear
- val = srgb_to_linear(val);
-
- sum.rgb += val * NdotL;
- sum.a += NdotL;
- }
+ vec4 sample_direction_mip = sample_directions_mip[sample_num];
+ vec3 L = T * sample_direction_mip.xyz;
+ vec3 val = textureLod(source_cube, L, sample_direction_mip.w).rgb;
+ // Mix using linear
+ val = srgb_to_linear(val);
+ sum.rgb += val * sample_direction_mip.z;
}
- sum /= sum.a;
+ sum /= weight;
sum.rgb = linear_to_srgb(sum.rgb);
frag_color = vec4(sum.rgb, 1.0);
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index b3e883b566..84daf839e9 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -104,8 +104,8 @@ layout(location = 14) in highp vec4 instance_xform2;
layout(location = 15) in highp uvec4 instance_color_custom_data; // Color packed into xy, Custom data into zw.
#endif
-layout(std140) uniform GlobalVariableData { //ubo:1
- vec4 global_variables[MAX_GLOBAL_VARIABLES];
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
layout(std140) uniform SceneData { // ubo:2
@@ -399,8 +399,8 @@ uniform samplerCube radiance_map; // texunit:-2
#endif
-layout(std140) uniform GlobalVariableData { //ubo:1
- vec4 global_variables[MAX_GLOBAL_VARIABLES];
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
/* Material Uniforms */
@@ -495,7 +495,7 @@ struct LightData { //this structure needs to be as packed as possible
mediump float cone_attenuation;
mediump float cone_angle;
mediump float specular_amount;
- bool shadow_enabled;
+ mediump float shadow_opacity;
};
#ifndef DISABLE_LIGHT_OMNI
layout(std140) uniform OmniLightData { // ubo:5
@@ -686,7 +686,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif // LIGHT_ANISOTROPY_USED
// F
float cLdotH5 = SchlickFresnel(cLdotH);
- vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0);
+ // Calculate Fresnel using cheap approximate specular occlusion term from Filament:
+ // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion
+ float f90 = clamp(50.0 * f0.g, 0.0, 1.0);
+ vec3 F = f0 + (f90 - f0) * cLdotH5;
vec3 specular_brdf_NL = cNdotL * D * F * G;
@@ -751,7 +754,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
if (omni_lights[idx].size > 0.0) {
float t = omni_lights[idx].size / max(0.001, light_length);
- size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t));
}
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha,
@@ -800,7 +803,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
if (spot_lights[idx].size > 0.0) {
float t = spot_lights[idx].size / max(0.001, light_length);
- size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t));
}
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha,
@@ -1108,7 +1111,7 @@ void main() {
float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
- specular_light *= env.x * f0 + env.y;
+ specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0);
#endif
}
diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl
index 50ab38bc31..eb1befe38e 100644
--- a/drivers/gles3/shaders/sky.glsl
+++ b/drivers/gles3/shaders/sky.glsl
@@ -42,8 +42,8 @@ uniform sampler2D half_res; //texunit:-2
uniform sampler2D quarter_res; //texunit:-3
#endif
-layout(std140) uniform GlobalVariableData { //ubo:1
- vec4 global_variables[MAX_GLOBAL_VARIABLES];
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
struct DirectionalLightData {
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index f2809734a9..30b5919526 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -64,7 +64,14 @@ Config::Config() {
#else
float_texture_supported = extensions.has("GL_ARB_texture_float") || extensions.has("GL_OES_texture_float");
etc2_supported = true;
+#if defined(ANDROID_ENABLED) || defined(IPHONE_ENABLED)
+ // Some Android devices report support for S3TC but we don't expect that and don't export the textures.
+ // This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs).
+ // For good measure we do the same hack for iOS, just in case.
+ s3tc_supported = false;
+#else
s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc");
+#endif
rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc");
#endif
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index db76aa79fb..b83c83f425 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -90,4 +90,4 @@ public:
#endif // GLES3_ENABLED
-#endif // !CONFIG_GLES3_H
+#endif // CONFIG_GLES3_H
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
index 954aa11c0d..2e4bfdc15b 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -70,6 +70,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
+ light.param[RS::LIGHT_PARAM_SHADOW_OPACITY] = 1.0;
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
@@ -139,12 +140,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 +161,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 +183,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 +201,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 +221,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 +231,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 +241,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 +257,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 +266,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 +477,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..857a0261fa 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,10 +321,27 @@ 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
-#endif // !GLES3_ENABLED
+#endif // GLES3_ENABLED
-#endif // !LIGHT_STORAGE_GLES3_H
+#endif // LIGHT_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index fd50bdedbd..26441fc726 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -176,75 +176,86 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} break;
case ShaderLanguage::TYPE_IVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 2 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector2i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
}
} break;
case ShaderLanguage::TYPE_IVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
}
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector3i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
}
} break;
case ShaderLanguage::TYPE_IVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
}
+ } else {
+ Vector4i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
} break;
case ShaderLanguage::TYPE_UINT: {
@@ -271,75 +282,86 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} break;
case ShaderLanguage::TYPE_UVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 2 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector2i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
}
} break;
case ShaderLanguage::TYPE_UVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
}
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector3i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
}
} break;
case ShaderLanguage::TYPE_UVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i++) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i++) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
}
+ } else {
+ Vector4i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
} break;
case ShaderLanguage::TYPE_FLOAT: {
@@ -504,6 +526,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[1] = v.y;
gui[2] = v.z;
gui[3] = v.w;
+ } else if (value.get_type() == Variant::VECTOR4) {
+ Vector4 v = value;
+
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
} else {
Plane v = value;
@@ -660,7 +689,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[i + 15] = 1;
}
}
- } else {
+ } else if (value.get_type() == Variant::TRANSFORM3D) {
Transform3D v = value;
gui[0] = v.basis.rows[0][0];
gui[1] = v.basis.rows[1][0];
@@ -681,6 +710,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[13] = v.origin.y;
gui[14] = v.origin.z;
gui[15] = 1;
+ } else {
+ Projection v = value;
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ gui[i * 4 + j] = v.matrix[i][j];
+ }
+ }
}
} break;
default: {
@@ -937,7 +973,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
//this is a global variable, get the index to it
- GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key);
uint32_t index = 0;
if (gv) {
index = gv->buffer_index;
@@ -993,9 +1029,9 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
if (uses_global_buffer != (global_buffer_E != nullptr)) {
if (uses_global_buffer) {
- global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self);
+ global_buffer_E = material_storage->global_shader_uniforms.materials_using_buffer.push_back(self);
} else {
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
global_buffer_E = nullptr;
}
}
@@ -1006,20 +1042,20 @@ MaterialData::~MaterialData() {
if (global_buffer_E) {
//unregister global buffers
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
}
if (global_texture_E) {
//unregister global textures
for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
}
//unregister material from those using global textures
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
}
if (uniform_buffer) {
@@ -1050,7 +1086,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
if (p_texture_uniforms[i].global) {
uses_global_textures = true;
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name);
if (v) {
if (v->buffer_index >= 0) {
WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
@@ -1120,6 +1156,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_BLACK);
} break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: {
+ gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_TRANSPARENT);
+ } break;
case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_ANISO);
} break;
@@ -1222,7 +1261,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
if (E.value != global_textures_pass) {
to_delete.push_back(E.key);
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
@@ -1236,9 +1275,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
//handle registering/unregistering global textures
if (uses_global_textures != (global_texture_E != nullptr)) {
if (uses_global_textures) {
- global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self);
+ global_texture_E = material_storage->global_shader_uniforms.materials_using_texture.push_back(self);
} else {
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
global_texture_E = nullptr;
}
}
@@ -1305,22 +1344,22 @@ MaterialStorage::MaterialStorage() {
material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func;
material_data_request_func[RS::SHADER_FOG] = nullptr;
- static_assert(sizeof(GlobalVariables::Value) == 16);
+ static_assert(sizeof(GlobalShaderUniforms::Value) == 16);
- global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
- if (global_variables.buffer_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) {
- global_variables.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size);
+ global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+ if (global_shader_uniforms.buffer_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) {
+ global_shader_uniforms.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size);
WARN_PRINT("Project setting: rendering/limits/global_shader_variables/buffer_size exceeds maximum uniform buffer size of: " + itos(Config::get_singleton()->max_uniform_buffer_size));
}
- global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
- memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
- global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
- global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- glGenBuffers(1, &global_variables.buffer);
- glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalVariables::Value) * global_variables.buffer_size, nullptr, GL_DYNAMIC_DRAW);
+ global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size);
+ memset(global_shader_uniforms.buffer_values, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_usage = memnew_arr(GlobalShaderUniforms::ValueUsage, global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_dirty_regions = memnew_arr(bool, global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ glGenBuffers(1, &global_shader_uniforms.buffer);
+ glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
{
@@ -1378,6 +1417,7 @@ MaterialStorage::MaterialStorage() {
actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n";
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n";
+ actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n";
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
@@ -1457,7 +1497,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["OUTPUT_IS_SRGB"] = "true";
- actions.renames["FOG"] = "custom_fog";
+ actions.renames["FOG"] = "fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
actions.renames["BONE_INDICES"] = "bone_attrib";
@@ -1468,6 +1508,11 @@ MaterialStorage::MaterialStorage() {
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz";
+ actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
+ actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz";
+ actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz";
+
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
@@ -1613,7 +1658,7 @@ ShaderCompiler::DefaultIdentifierActions actions;
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
particles_shader.compiler.initialize(actions);
*/
@@ -1675,25 +1720,25 @@ ShaderCompiler::DefaultIdentifierActions actions;
MaterialStorage::~MaterialStorage() {
//shaders.copy.version_free(shaders.copy_version);
- memdelete_arr(global_variables.buffer_values);
- memdelete_arr(global_variables.buffer_usage);
- memdelete_arr(global_variables.buffer_dirty_regions);
- glDeleteBuffers(1, &global_variables.buffer);
+ memdelete_arr(global_shader_uniforms.buffer_values);
+ memdelete_arr(global_shader_uniforms.buffer_usage);
+ memdelete_arr(global_shader_uniforms.buffer_dirty_regions);
+ glDeleteBuffers(1, &global_shader_uniforms.buffer);
singleton = nullptr;
}
-/* GLOBAL VARIABLE API */
+/* GLOBAL SHADER UNIFORM API */
-int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
+int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) {
int32_t idx = 0;
- while (idx + p_elements <= global_variables.buffer_size) {
- if (global_variables.buffer_usage[idx].elements == 0) {
+ while (idx + p_elements <= global_shader_uniforms.buffer_size) {
+ if (global_shader_uniforms.buffer_usage[idx].elements == 0) {
bool valid = true;
for (uint32_t i = 1; i < p_elements; i++) {
- if (global_variables.buffer_usage[idx + i].elements > 0) {
+ if (global_shader_uniforms.buffer_usage[idx + i].elements > 0) {
valid = false;
- idx += i + global_variables.buffer_usage[idx + i].elements;
+ idx += i + global_shader_uniforms.buffer_usage[idx + i].elements;
break;
}
}
@@ -1704,17 +1749,17 @@ int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
return idx;
} else {
- idx += global_variables.buffer_usage[idx].elements;
+ idx += global_shader_uniforms.buffer_usage[idx].elements;
}
}
return -1;
}
-void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
+void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
bool b = p_value;
bv.x = b ? 1.0 : 0.0;
bv.y = 0.0;
@@ -1723,7 +1768,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_BVEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1731,7 +1776,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1739,7 +1784,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1747,7 +1792,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = (bvec & 8) ? 1.0 : 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_INT: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
int32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1755,7 +1800,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC2: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1763,7 +1808,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC3: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1771,7 +1816,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC4: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1779,7 +1824,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2I: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Rect2i v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1787,7 +1832,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_UINT: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
uint32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1795,7 +1840,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC2: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1803,7 +1848,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC3: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1811,7 +1856,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC4: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1819,7 +1864,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_FLOAT: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
float v = p_value;
bv.x = v;
bv.y = 0;
@@ -1827,7 +1872,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector2 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1835,7 +1880,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector3 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1843,7 +1888,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Plane v = p_value;
bv.x = v.normal.x;
bv.y = v.normal.y;
@@ -1851,14 +1896,14 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.d;
} break;
case RS::GLOBAL_VAR_TYPE_COLOR: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Color v = p_value;
bv.x = v.r;
bv.y = v.g;
bv.z = v.b;
bv.w = v.a;
- GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+ GlobalShaderUniforms::Value &bv_linear = global_shader_uniforms.buffer_values[p_index + 1];
//v = v.srgb_to_linear();
bv_linear.x = v.r;
bv_linear.y = v.g;
@@ -1867,7 +1912,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Rect2 v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1875,7 +1920,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_MAT2: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 4) {
m2.resize(4);
@@ -1892,7 +1937,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT3: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Basis v = p_value;
bv[0].x = v.rows[0][0];
bv[0].y = v.rows[1][0];
@@ -1911,7 +1956,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT4: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 16) {
@@ -1940,7 +1985,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform2D v = p_value;
bv[0].x = v.columns[0][0];
bv[0].y = v.columns[0][1];
@@ -1959,7 +2004,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform3D v = p_value;
bv[0].x = v.basis.rows[0][0];
bv[0].y = v.basis.rows[1][0];
@@ -1988,15 +2033,15 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
}
}
-void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
+void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
int32_t prev_chunk = -1;
for (int32_t i = 0; i < p_elements; i++) {
- int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ int32_t chunk = (p_index + i) / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
if (chunk != prev_chunk) {
- if (!global_variables.buffer_dirty_regions[chunk]) {
- global_variables.buffer_dirty_regions[chunk] = true;
- global_variables.buffer_dirty_region_count++;
+ if (!global_shader_uniforms.buffer_dirty_regions[chunk]) {
+ global_shader_uniforms.buffer_dirty_regions[chunk] = true;
+ global_shader_uniforms.buffer_dirty_region_count++;
}
}
@@ -2004,16 +2049,16 @@ void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_
}
}
-void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
- ERR_FAIL_COND(global_variables.variables.has(p_name));
- GlobalVariables::Variable gv;
+void MaterialStorage::global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) {
+ ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable gv;
gv.type = p_type;
gv.value = p_value;
gv.buffer_index = -1;
if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
//is texture
- global_variables.must_update_texture_materials = true; //normally there are none
+ global_shader_uniforms.must_update_texture_materials = true; //normally there are none
} else {
gv.buffer_elements = 1;
if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
@@ -2030,56 +2075,56 @@ void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVa
}
//is vector, allocate in buffer and update index
- gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+ gv.buffer_index = _global_shader_uniform_allocate(gv.buffer_elements);
ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
- global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- global_variables.must_update_buffer_materials = true; //normally there are none
+ global_shader_uniforms.must_update_buffer_materials = true; //normally there are none
}
- global_variables.variables[p_name] = gv;
+ global_shader_uniforms.variables[p_name] = gv;
}
-void MaterialStorage::global_variable_remove(const StringName &p_name) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_uniform_remove(const StringName &p_name) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return;
}
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
if (gv.buffer_index >= 0) {
- global_variables.buffer_usage[gv.buffer_index].elements = 0;
- global_variables.must_update_buffer_materials = true;
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = 0;
+ global_shader_uniforms.must_update_buffer_materials = true;
} else {
- global_variables.must_update_texture_materials = true;
+ global_shader_uniforms.must_update_texture_materials = true;
}
- global_variables.variables.erase(p_name);
+ global_shader_uniforms.variables.erase(p_name);
}
-Vector<StringName> MaterialStorage::global_variable_get_list() const {
+Vector<StringName> MaterialStorage::global_shader_uniform_get_list() const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
}
Vector<StringName> names;
- for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+ for (const KeyValue<StringName, GlobalShaderUniforms::Variable> &E : global_shader_uniforms.variables) {
names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
return names;
}
-void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
- ERR_FAIL_COND(!global_variables.variables.has(p_name));
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+void MaterialStorage::global_shader_uniform_set(const StringName &p_name, const Variant &p_value) {
+ ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.value = p_value;
if (gv.override.get_type() == Variant::NIL) {
if (gv.buffer_index >= 0) {
//buffer
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -2092,26 +2137,26 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian
}
}
-void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return; //variable may not exist
}
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.override = p_value;
if (gv.buffer_index >= 0) {
//buffer
if (gv.override.get_type() == Variant::NIL) {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
} else {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.override);
}
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -2123,35 +2168,35 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con
}
}
-Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+Variant MaterialStorage::global_shader_uniform_get(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
}
- if (!global_variables.variables.has(p_name)) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return Variant();
}
- return global_variables.variables[p_name].value;
+ return global_shader_uniforms.variables[p_name].value;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const {
- if (!global_variables.variables.has(p_name)) {
+RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type_internal(const StringName &p_name) const {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return RS::GLOBAL_VAR_TYPE_MAX;
}
- return global_variables.variables[p_name].type;
+ return global_shader_uniforms.variables[p_name].type;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
}
- return global_variable_get_type_internal(p_name);
+ return global_shader_uniform_get_type_internal(p_name);
}
-void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) {
List<PropertyInfo> settings;
ProjectSettings::get_singleton()->get_property_list(&settings);
@@ -2196,11 +2241,11 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
"samplerCube",
};
- RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+ RS::GlobalShaderUniformType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
if (global_var_type_names[i] == type) {
- gvtype = RS::GlobalVariableType(i);
+ gvtype = RS::GlobalShaderUniformType(i);
break;
}
}
@@ -2222,47 +2267,47 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
value = resource;
}
- if (global_variables.variables.has(name)) {
+ if (global_shader_uniforms.variables.has(name)) {
//has it, update it
- global_variable_set(name, value);
+ global_shader_uniform_set(name, value);
} else {
- global_variable_add(name, gvtype, value);
+ global_shader_uniform_add(name, gvtype, value);
}
}
}
}
-void MaterialStorage::global_variables_clear() {
- global_variables.variables.clear();
+void MaterialStorage::global_shader_uniforms_clear() {
+ global_shader_uniforms.variables.clear();
}
-GLuint MaterialStorage::global_variables_get_uniform_buffer() const {
- return global_variables.buffer;
+GLuint MaterialStorage::global_shader_uniforms_get_uniform_buffer() const {
+ return global_shader_uniforms.buffer;
}
-int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
- ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
- int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
+int32_t MaterialStorage::global_shader_uniforms_instance_allocate(RID p_instance) {
+ ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1);
+ int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway
ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
- global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+ global_shader_uniforms.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
return pos;
}
-void MaterialStorage::global_variables_instance_free(RID p_instance) {
- ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+void MaterialStorage::global_shader_uniforms_instance_free(RID p_instance) {
+ ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance));
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos >= 0) {
- global_variables.buffer_usage[pos].elements = 0;
+ global_shader_uniforms.buffer_usage[pos].elements = 0;
}
- global_variables.instance_buffer_pos.erase(p_instance);
+ global_shader_uniforms.instance_buffer_pos.erase(p_instance);
}
-void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
- if (!global_variables.instance_buffer_pos.has(p_instance)) {
+void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+ if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) {
return; //just not allocated, ignore
}
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos < 0) {
return; //again, not allocated, ignore
@@ -2283,11 +2328,14 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
ShaderLanguage::TYPE_VEC3, // vec3
ShaderLanguage::TYPE_IVEC3, //vec3i
ShaderLanguage::TYPE_MAX, //xform2d not supported here
+ ShaderLanguage::TYPE_VEC4, //vec4
+ ShaderLanguage::TYPE_IVEC4, //vec4i
ShaderLanguage::TYPE_VEC4, //plane
ShaderLanguage::TYPE_VEC4, //quat
ShaderLanguage::TYPE_MAX, //aabb not supported here
ShaderLanguage::TYPE_MAX, //basis not supported here
ShaderLanguage::TYPE_MAX, //xform not supported here
+ ShaderLanguage::TYPE_MAX, //projection not supported here
ShaderLanguage::TYPE_VEC4 //color
};
@@ -2297,59 +2345,59 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
pos += p_index;
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos]);
- _global_variable_mark_buffer_dirty(pos, 1);
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[pos]);
+ _global_shader_uniform_mark_buffer_dirty(pos, 1);
}
-void MaterialStorage::_update_global_variables() {
+void MaterialStorage::_update_global_shader_uniforms() {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
- if (global_variables.buffer_dirty_region_count > 0) {
- uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
+ if (global_shader_uniforms.buffer_dirty_region_count > 0) {
+ uint32_t total_regions = global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
+ if (total_regions / global_shader_uniforms.buffer_dirty_region_count <= 4) {
// 25% of regions dirty, just update all buffer
- glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, global_shader_uniforms.buffer_values, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
} else {
- uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer);
+ uint32_t region_byte_size = sizeof(GlobalShaderUniforms::Value) * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
+ glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer);
for (uint32_t i = 0; i < total_regions; i++) {
- if (global_variables.buffer_dirty_regions[i]) {
- glBufferSubData(GL_UNIFORM_BUFFER, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
- global_variables.buffer_dirty_regions[i] = false;
+ if (global_shader_uniforms.buffer_dirty_regions[i]) {
+ glBufferSubData(GL_UNIFORM_BUFFER, i * region_byte_size, region_byte_size, &global_shader_uniforms.buffer_values[i * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE]);
+ global_shader_uniforms.buffer_dirty_regions[i] = false;
}
}
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
- global_variables.buffer_dirty_region_count = 0;
+ global_shader_uniforms.buffer_dirty_region_count = 0;
}
- if (global_variables.must_update_buffer_materials) {
+ if (global_shader_uniforms.must_update_buffer_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_buffer) {
+ for (const RID &E : global_shader_uniforms.materials_using_buffer) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, true, false);
}
- global_variables.must_update_buffer_materials = false;
+ global_shader_uniforms.must_update_buffer_materials = false;
}
- if (global_variables.must_update_texture_materials) {
+ if (global_shader_uniforms.must_update_texture_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_texture) {
+ for (const RID &E : global_shader_uniforms.materials_using_texture) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, false, true);
}
- global_variables.must_update_texture_materials = false;
+ global_shader_uniforms.must_update_texture_materials = false;
}
}
@@ -2456,22 +2504,29 @@ 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);
}
}
+void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) {
+ GLES3::Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ shader->path_hint = p_path;
+}
+
String MaterialStorage::shader_get_code(RID p_shader) const {
const GLES3::Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, String());
return shader->code;
}
-void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+void MaterialStorage::shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
GLES3::Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (shader->data) {
- return shader->data->get_param_list(p_param_list);
+ return shader->data->get_shader_uniform_list(p_param_list);
}
}
@@ -2593,7 +2648,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 +2671,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 +2717,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) {
@@ -2703,19 +2758,19 @@ bool MaterialStorage::material_casts_shadows(RID p_material) {
return true; //by default everything casts shadows
}
-void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
+void MaterialStorage::material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) {
GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
if (material->shader && material->shader->data) {
material->shader->data->get_instance_param_list(r_parameters);
if (material->next_pass.is_valid()) {
- material_get_instance_shader_parameters(material->next_pass, r_parameters);
+ material_get_instance_shader_uniforms(material->next_pass, r_parameters);
}
}
}
-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);
@@ -2818,7 +2873,7 @@ void CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p
}
}
-void CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void CanvasShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -2832,7 +2887,22 @@ void CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -3040,7 +3110,7 @@ void SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_te
}
}
-void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SkyShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
RBMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -3055,7 +3125,22 @@ void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -3350,7 +3435,7 @@ void SceneShaderData::set_default_texture_param(const StringName &p_name, RID p_
}
}
-void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SceneShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
RBMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -3365,7 +3450,22 @@ void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index 09f6680bec..2ca47351a4 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"
@@ -54,7 +54,7 @@ namespace GLES3 {
struct ShaderData {
virtual void set_code(const String &p_Code) = 0;
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
virtual bool is_param_texture(const StringName &p_param) const = 0;
@@ -73,6 +73,7 @@ struct Material;
struct Shader {
ShaderData *data = nullptr;
String code;
+ String path_hint;
RS::ShaderMode mode;
HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
HashSet<Material *> owners;
@@ -125,7 +126,7 @@ struct Material {
RID next_pass;
SelfList<Material> update_element;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
Material() :
update_element(this) {}
@@ -163,7 +164,7 @@ struct CanvasShaderData : public ShaderData {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -214,7 +215,7 @@ struct SkyShaderData : public ShaderData {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -334,7 +335,7 @@ struct SceneShaderData : public ShaderData {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -364,15 +365,15 @@ struct SceneMaterialData : public MaterialData {
MaterialData *_create_scene_material_func(ShaderData *p_shader);
-/* Global variable structs */
-struct GlobalVariables {
+/* Global shader uniform structs */
+struct GlobalShaderUniforms {
enum {
BUFFER_DIRTY_REGION_SIZE = 1024
};
struct Variable {
HashSet<RID> texture_materials; // materials using this
- RS::GlobalVariableType type;
+ RS::GlobalShaderUniformType type;
Variant value;
Variant override;
int32_t buffer_index; //for vectors
@@ -428,13 +429,13 @@ private:
friend struct MaterialData;
static MaterialStorage *singleton;
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- GlobalVariables global_variables;
+ GlobalShaderUniforms global_shader_uniforms;
- int32_t _global_variable_allocate(uint32_t p_elements);
- void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
- void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+ int32_t _global_shader_uniform_allocate(uint32_t p_elements);
+ void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value);
+ void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
/* SHADER API */
@@ -453,6 +454,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 Projection &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;
@@ -465,28 +508,28 @@ public:
ShaderCompiler compiler_sky;
} shaders;
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- void _update_global_variables();
+ void _update_global_shader_uniforms();
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
- virtual void global_variable_remove(const StringName &p_name) override;
- virtual Vector<StringName> global_variable_get_list() const override;
+ virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override;
+ virtual void global_shader_uniform_remove(const StringName &p_name) override;
+ virtual Vector<StringName> global_shader_uniform_get_list() const override;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
- virtual Variant global_variable_get(const StringName &p_name) const override;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
- RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override;
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override;
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const override;
+ virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override;
+ RS::GlobalShaderUniformType global_shader_uniform_get_type_internal(const StringName &p_name) const;
- virtual void global_variables_load_settings(bool p_load_textures = true) override;
- virtual void global_variables_clear() override;
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override;
+ virtual void global_shader_uniforms_clear() override;
- virtual int32_t global_variables_instance_allocate(RID p_instance) override;
- virtual void global_variables_instance_free(RID p_instance) override;
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+ virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override;
+ virtual void global_shader_uniforms_instance_free(RID p_instance) override;
+ virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
- GLuint global_variables_get_uniform_buffer() const;
+ GLuint global_shader_uniforms_get_uniform_buffer() const;
/* SHADER API */
@@ -500,8 +543,9 @@ public:
virtual void shader_free(RID p_rid) override;
virtual void shader_set_code(RID p_shader, const String &p_code) override;
+ virtual void shader_set_path_hint(RID p_shader, const String &p_path) override;
virtual String shader_get_code(RID p_shader) const override;
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
+ virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
@@ -532,9 +576,9 @@ public:
virtual bool material_is_animated(RID p_material) override;
virtual bool material_casts_shadows(RID p_material) override;
- virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
+ virtual void material_get_instance_shader_uniforms(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);
@@ -555,4 +599,4 @@ public:
#endif // GLES3_ENABLED
-#endif // !MATERIAL_STORAGE_GLES3_H
+#endif // MATERIAL_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index 5aa82bfcc1..667ba4f5e6 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();
@@ -1345,10 +1347,10 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
_multimesh_mark_all_dirty(multimesh, false, true); //update AABB
} else if (multimesh->mesh.is_valid()) {
//if we have a mesh set, we need to re-generate the AABB from the new data
- const float *data = multimesh->data_cache.ptr();
+ 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);
}
}
@@ -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..339380b3b0 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,11 +532,15 @@ 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
#endif // GLES3_ENABLED
-#endif // !MESH_STORAGE_GLES3_H
+#endif // MESH_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h
index cf47ada5d5..84d1f94d8c 100644
--- a/drivers/gles3/storage/particles_storage.h
+++ b/drivers/gles3/storage/particles_storage.h
@@ -137,4 +137,4 @@ public:
#endif // GLES3_ENABLED
-#endif // !PARTICLES_STORAGE_GLES3_H
+#endif // PARTICLES_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 42c80da39a..543638e8ff 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -115,6 +115,17 @@ TextureStorage::TextureStorage() {
texture_2d_layered_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_CUBEMAP_BLACK], images, RS::TEXTURE_LAYERED_CUBEMAP);
}
+ { // transparent black
+ Ref<Image> image;
+ image.instantiate();
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
+ image->fill(Color(0, 0, 0, 0));
+ image->generate_mipmaps();
+
+ default_gl_textures[DEFAULT_GL_TEXTURE_TRANSPARENT] = texture_allocate();
+ texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_TRANSPARENT], image);
+ }
+
{
Ref<Image> image;
image.instantiate();
@@ -183,6 +194,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 +261,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..71f713bc9f 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -103,6 +103,7 @@ namespace GLES3 {
enum DefaultGLTexture {
DEFAULT_GL_TEXTURE_WHITE,
DEFAULT_GL_TEXTURE_BLACK,
+ DEFAULT_GL_TEXTURE_TRANSPARENT,
DEFAULT_GL_TEXTURE_NORMAL,
DEFAULT_GL_TEXTURE_ANISO,
DEFAULT_GL_TEXTURE_DEPTH,
@@ -132,6 +133,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 +376,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 +419,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) {
@@ -527,6 +547,16 @@ public:
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{};
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{};
+
+ void bind_framebuffer(GLuint framebuffer) {
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ }
+
+ void bind_framebuffer_system() {
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+ }
String get_framebuffer_error(GLenum p_status);
};
@@ -548,6 +578,6 @@ inline String TextureStorage::get_framebuffer_error(GLenum p_status) {
} // namespace GLES3
-#endif // !GLES3_ENABLED
+#endif // GLES3_ENABLED
-#endif // !TEXTURE_STORAGE_GLES3_H
+#endif // TEXTURE_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
new file mode 100644
index 0000000000..654104722b
--- /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_shader_uniforms();
+ 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..e054f2f816
--- /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/png/image_loader_png.h b/drivers/png/image_loader_png.h
index 522cc901d4..9bcfb720d3 100644
--- a/drivers/png/image_loader_png.h
+++ b/drivers/png/image_loader_png.h
@@ -45,4 +45,4 @@ public:
ImageLoaderPNG();
};
-#endif
+#endif // IMAGE_LOADER_PNG_H
diff --git a/drivers/png/png_driver_common.h b/drivers/png/png_driver_common.h
index 62302bbdbb..24546d4402 100644
--- a/drivers/png/png_driver_common.h
+++ b/drivers/png/png_driver_common.h
@@ -43,4 +43,4 @@ Error png_to_image(const uint8_t *p_source, size_t p_size, bool p_force_linear,
Error image_to_png(const Ref<Image> &p_image, Vector<uint8_t> &p_buffer);
} // namespace PNGDriverCommon
-#endif
+#endif // PNG_DRIVER_COMMON_H
diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp
index 704ddca726..275f3240d7 100644
--- a/drivers/png/resource_saver_png.cpp
+++ b/drivers/png/resource_saver_png.cpp
@@ -35,7 +35,7 @@
#include "drivers/png/png_driver_common.h"
#include "scene/resources/texture.h"
-Error ResourceSaverPNG::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceSaverPNG::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Ref<ImageTexture> texture = p_resource;
ERR_FAIL_COND_V_MSG(!texture.is_valid(), ERR_INVALID_PARAMETER, "Can't save invalid texture as PNG.");
diff --git a/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h
index 1a681faaec..260a643a1b 100644
--- a/drivers/png/resource_saver_png.h
+++ b/drivers/png/resource_saver_png.h
@@ -39,7 +39,7 @@ public:
static Error save_image(const String &p_path, const Ref<Image> &p_img);
static Vector<uint8_t> save_image_to_buffer(const Ref<Image> &p_img);
- virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
virtual bool recognize(const Ref<Resource> &p_resource) const;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
diff --git a/drivers/register_driver_types.h b/drivers/register_driver_types.h
index c008d93185..41f95b57e7 100644
--- a/drivers/register_driver_types.h
+++ b/drivers/register_driver_types.h
@@ -37,4 +37,4 @@ void unregister_core_driver_types();
void register_driver_types();
void unregister_driver_types();
-#endif
+#endif // REGISTER_DRIVER_TYPES_H
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 7e6105f033..b8b72b8d30 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;
}
@@ -511,4 +516,4 @@ DirAccessUnix::~DirAccessUnix() {
list_dir_end();
}
-#endif //posix_enabled
+#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index 69530de337..f5dca7c282 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -43,54 +43,53 @@
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);
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 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(); ///<
+ virtual void list_dir_end() override; ///<
- virtual int get_drive_count();
- virtual String get_drive(int p_drive);
- virtual int get_current_drive();
- virtual bool drives_are_shortcuts();
+ virtual int get_drive_count() override;
+ virtual String get_drive(int p_drive) override;
+ virtual int get_current_drive() override;
+ virtual bool drives_are_shortcuts() 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 make_dir(String p_dir);
+ virtual Error change_dir(String p_dir) override; ///< can be relative or absolute, return false on success
+ virtual String get_current_dir(bool p_include_drive = true) const override; ///< return current dir location
+ virtual Error make_dir(String p_dir) override;
- virtual bool file_exists(String p_file);
- virtual bool dir_exists(String p_dir);
- virtual bool is_readable(String p_dir);
- virtual bool is_writable(String p_dir);
+ virtual bool file_exists(String p_file) override;
+ virtual bool dir_exists(String p_dir) override;
+ virtual bool is_readable(String p_dir) override;
+ virtual bool is_writable(String p_dir) override;
virtual uint64_t get_modified_time(String p_file);
- virtual Error rename(String p_path, String p_new_path);
- virtual Error remove(String p_path);
+ virtual Error rename(String p_path, String p_new_path) override;
+ virtual Error remove(String p_path) override;
- virtual bool is_link(String p_file);
- virtual String read_link(String p_file);
- virtual Error create_link(String p_source, String p_target);
+ virtual bool is_link(String p_file) override;
+ virtual String read_link(String p_file) override;
+ virtual Error create_link(String p_source, String p_target) override;
- virtual uint64_t get_space_left();
+ virtual uint64_t get_space_left() override;
- virtual String get_filesystem_type() const;
+ virtual String get_filesystem_type() const override;
DirAccessUnix();
~DirAccessUnix();
};
-#endif //UNIX ENABLED
-#endif
+#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+
+#endif // DIR_ACCESS_UNIX_H
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index e0b2994b63..388ad479b9 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -333,14 +333,10 @@ 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() {
_close();
}
-#endif
+#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 4340bbbc82..297c34e454 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -49,43 +49,43 @@ class FileAccessUnix : public FileAccess {
String path;
String path_src;
- static Ref<FileAccess> create_libc();
void _close();
public:
static CloseNotificationFunc close_notification_func;
- virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual bool is_open() const; ///< true when file is open
+ 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
- virtual String get_path() const; /// returns the path for the current open file
- virtual String get_path_absolute() const; /// returns the absolute path for the current open file
+ virtual String get_path() const override; /// returns the path for the current open file
+ virtual String get_path_absolute() const override; /// returns the absolute path for the current open file
- 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
- virtual uint64_t get_length() const; ///< get size of the file
+ 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; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ 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; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
+ 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; ///< store an array of bytes
- virtual bool file_exists(const String &p_path); ///< return true if a file exists
+ virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
- virtual uint64_t _get_modified_time(const String &p_file);
- virtual uint32_t _get_unix_permissions(const String &p_file);
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
+ virtual uint64_t _get_modified_time(const String &p_file) override;
+ virtual uint32_t _get_unix_permissions(const String &p_file) override;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
FileAccessUnix() {}
virtual ~FileAccessUnix();
};
-#endif
-#endif
+#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+
+#endif // FILE_ACCESS_UNIX_H
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index 2deeb79957..0dc2efedc1 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -95,12 +95,12 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos
int s = getaddrinfo(p_hostname.utf8().get_data(), nullptr, &hints, &result);
if (s != 0) {
- ERR_PRINT("getaddrinfo failed! Cannot resolve hostname.");
+ print_verbose("getaddrinfo failed! Cannot resolve hostname.");
return;
}
if (result == nullptr || result->ai_addr == nullptr) {
- ERR_PRINT("Invalid response from getaddrinfo");
+ print_verbose("Invalid response from getaddrinfo");
if (result) {
freeaddrinfo(result);
}
diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h
index 06fcdb6e17..798d02095c 100644
--- a/drivers/unix/ip_unix.h
+++ b/drivers/unix/ip_unix.h
@@ -50,4 +50,5 @@ public:
};
#endif
+
#endif // IP_UNIX_H
diff --git a/drivers/unix/net_socket_posix.h b/drivers/unix/net_socket_posix.h
index 867513099a..5558114cb1 100644
--- a/drivers/unix/net_socket_posix.h
+++ b/drivers/unix/net_socket_posix.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NET_SOCKET_UNIX_H
-#define NET_SOCKET_UNIX_H
+#ifndef NET_SOCKET_POSIX_H
+#define NET_SOCKET_POSIX_H
#include "core/io/net_socket.h"
@@ -104,4 +104,4 @@ public:
~NetSocketPosix();
};
-#endif
+#endif // NET_SOCKET_POSIX_H
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 52a4d538e1..5bf14056ab 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -65,7 +65,7 @@
#include <time.h>
#include <unistd.h>
-#if defined(OSX_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
+#if defined(MACOS_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
// Random location for getentropy. Fitting.
#include <sys/random.h>
#define UNIX_GET_ENTROPY
@@ -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/unix/os_unix.h b/drivers/unix/os_unix.h
index a1ed4bd501..f4609a565b 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -98,6 +98,6 @@ public:
virtual ~UnixTerminalLogger();
};
-#endif
+#endif // UNIX_ENABLED
-#endif
+#endif // OS_UNIX_H
diff --git a/drivers/unix/syslog_logger.h b/drivers/unix/syslog_logger.h
index 697a96a6f9..cc6617eb25 100644
--- a/drivers/unix/syslog_logger.h
+++ b/drivers/unix/syslog_logger.h
@@ -43,6 +43,6 @@ public:
virtual ~SyslogLogger();
};
-#endif
+#endif // UNIX_ENABLED
-#endif
+#endif // SYSLOG_LOGGER_H
diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h
index 9cd3ecbe90..672adcba72 100644
--- a/drivers/unix/thread_posix.h
+++ b/drivers/unix/thread_posix.h
@@ -35,4 +35,4 @@
void init_thread_posix();
#endif
-#endif
+#endif // THREAD_POSIX_H
diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub
index b6ceb1cdea..a076c0ac54 100644
--- a/drivers/vulkan/SCsub
+++ b/drivers/vulkan/SCsub
@@ -15,11 +15,11 @@ if env["use_volk"]:
if env["platform"] == "android":
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_ANDROID_KHR"])
-elif env["platform"] == "iphone":
+elif env["platform"] == "ios":
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_IOS_MVK"])
-elif env["platform"] == "linuxbsd":
+elif env["platform"] == "linuxbsd" and env["x11"]:
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_XLIB_KHR"])
-elif env["platform"] == "osx":
+elif env["platform"] == "macos":
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_MACOS_MVK"])
elif env["platform"] == "windows":
env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_WIN32_KHR"])
@@ -40,7 +40,7 @@ elif env["platform"] == "android":
# Our current NDK version only provides old Vulkan headers,
# so we have to limit VMA.
env_thirdparty_vma.AppendUnique(CPPDEFINES=["VMA_VULKAN_VERSION=1000000"])
-elif env["platform"] == "osx" or env["platform"] == "iphone":
+elif env["platform"] == "macos" or env["platform"] == "ios":
# MoltenVK supports only Vulkan 1.1 API, limit VMA to the same version.
env_thirdparty_vma.AppendUnique(CPPDEFINES=["VMA_VULKAN_VERSION=1001000"])
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 10250bddb5..89daa2af64 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -36,6 +36,7 @@
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/templates/hashfuncs.h"
+#include "core/version.h"
#include "drivers/vulkan/vulkan_context.h"
#include "thirdparty/misc/smolv.h"
@@ -106,7 +107,7 @@ RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID
return buffer;
}
-static void update_external_dependency_for_store(VkSubpassDependency &dependency, bool is_sampled, bool is_storage, bool is_depth) {
+static void update_external_dependency_for_store(VkSubpassDependency2KHR &dependency, bool is_sampled, bool is_storage, bool is_depth) {
// Transitioning from write to read, protect the shaders that may use this next
// Allow for copies/image layout transitions
dependency.dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
@@ -1758,6 +1759,10 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
image_create_info.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
+ if (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
+ image_create_info.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+ }
+
if (p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT) {
image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
@@ -1829,6 +1834,11 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
if (p_format.usage_bits & TEXTURE_USAGE_STORAGE_ATOMIC_BIT && !(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) {
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as atomic storage image.");
}
+
+ // Validation via VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR fails if VRS attachment is not supported.
+ if (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && p_format.format != DATA_FORMAT_R8_UINT) {
+ ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as VRS attachment.");
+ }
}
//some view validation
@@ -1994,6 +2004,9 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
}
RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
if (p_data.size()) {
for (uint32_t i = 0; i < image_create_info.arrayLayers; i++) {
@@ -2123,6 +2136,9 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
texture.owner = p_with_texture;
RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
_add_dependency(id, p_with_texture);
return id;
@@ -2242,6 +2258,9 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat
}
RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
return id;
}
@@ -2367,6 +2386,9 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
texture.owner = p_with_texture;
RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
_add_dependency(id, p_with_texture);
return id;
@@ -3349,6 +3371,11 @@ bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_f
return false;
}
+ // Validation via VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR fails if VRS attachment is not supported.
+ if (p_usage & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && p_format != DATA_FORMAT_R8_UINT) {
+ return false;
+ }
+
return true;
}
@@ -3362,17 +3389,24 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; // From Section 7.1 of Vulkan API Spec v1.1.148
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | // From Section 7.1 of Vulkan API Spec v1.1.148
+ VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
VkPipelineStageFlags reading_stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
- VkSubpassDependency dependencies[2] = { { VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, default_access_mask, 0 },
- { 0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, default_access_mask, 0, 0 } };
- VkSubpassDependency &dependency_from_external = dependencies[0];
- VkSubpassDependency &dependency_to_external = dependencies[1];
+ VkSubpassDependency2KHR dependencies[2] = {
+ { VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, nullptr, VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, default_access_mask, 0, 0 },
+ { VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, nullptr, 0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, default_access_mask, 0, 0, 0 }
+ };
+ VkSubpassDependency2KHR &dependency_from_external = dependencies[0];
+ VkSubpassDependency2KHR &dependency_to_external = dependencies[1];
LocalVector<int32_t> attachment_last_pass;
attachment_last_pass.resize(p_attachments.size());
- Vector<VkAttachmentDescription> attachments;
+ // These are only used if we use multiview but we need to define them in scope.
+ const uint32_t view_mask = (1 << p_view_count) - 1;
+ const uint32_t correlation_mask = (1 << p_view_count) - 1;
+
+ Vector<VkAttachmentDescription2KHR> attachments;
Vector<int> attachment_remap;
for (int i = 0; i < p_attachments.size(); i++) {
@@ -3383,10 +3417,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
ERR_FAIL_INDEX_V(p_attachments[i].format, DATA_FORMAT_MAX, VK_NULL_HANDLE);
ERR_FAIL_INDEX_V(p_attachments[i].samples, TEXTURE_SAMPLES_MAX, VK_NULL_HANDLE);
- ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)),
- VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (color, depth, input or stencil) bit set.");
+ ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT | TEXTURE_USAGE_VRS_ATTACHMENT_BIT)),
+ VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (color, depth-stencil, input or VRS) bit set.");
- VkAttachmentDescription description = {};
+ VkAttachmentDescription2KHR description = {};
+ description.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;
+ description.pNext = nullptr;
description.flags = 0;
description.format = vulkan_formats[p_attachments[i].format];
description.samples = rasterization_sample_count[p_attachments[i].samples];
@@ -3395,83 +3431,95 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
bool is_storage = p_attachments[i].usage_flags & TEXTURE_USAGE_STORAGE_BIT;
bool is_depth = p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
- // For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write
- // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs.
- // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that
- // stage
-
- switch (is_depth ? p_initial_depth_action : p_initial_action) {
- case INITIAL_ACTION_CLEAR_REGION:
- case INITIAL_ACTION_CLEAR: {
- if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- dependency_from_external.srcStageMask |= reading_stages;
- } else {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
- dependency_from_external.srcStageMask |= reading_stages;
- }
- } break;
- case INITIAL_ACTION_KEEP: {
- if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- dependency_from_external.srcStageMask |= reading_stages;
- } else {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
- dependency_from_external.srcStageMask |= reading_stages;
- }
- } break;
- case INITIAL_ACTION_DROP: {
- if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- dependency_from_external.srcStageMask |= reading_stages;
- } else {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
- dependency_from_external.srcStageMask |= reading_stages;
- }
- } break;
- case INITIAL_ACTION_CLEAR_REGION_CONTINUE:
- case INITIAL_ACTION_CONTINUE: {
- if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- } else {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
- dependency_from_external.srcStageMask |= reading_stages;
+ // We can setup a framebuffer where we write to our VRS texture to set it up.
+ // We make the assumption here that if our texture is actually used as our VRS attachment,
+ // it is used as such for each subpass. This is fairly certain seeing the restrictions on subpasses.
+ bool is_vrs = p_attachments[i].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && i == p_passes[0].vrs_attachment;
+
+ if (is_vrs) {
+ // For VRS we only read, there is no writing to this texture
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ description.initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ } else {
+ // For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write
+ // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs.
+ // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that
+ // stage
+
+ switch (is_depth ? p_initial_depth_action : p_initial_action) {
+ case INITIAL_ACTION_CLEAR_REGION:
+ case INITIAL_ACTION_CLEAR: {
+ if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ dependency_from_external.srcStageMask |= reading_stages;
+ } else {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ dependency_from_external.srcStageMask |= reading_stages;
+ }
+ } break;
+ case INITIAL_ACTION_KEEP: {
+ if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ dependency_from_external.srcStageMask |= reading_stages;
+ } else {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ dependency_from_external.srcStageMask |= reading_stages;
+ }
+ } break;
+ case INITIAL_ACTION_DROP: {
+ if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ dependency_from_external.srcStageMask |= reading_stages;
+ } else {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ dependency_from_external.srcStageMask |= reading_stages;
+ }
+ } break;
+ case INITIAL_ACTION_CLEAR_REGION_CONTINUE:
+ case INITIAL_ACTION_CONTINUE: {
+ if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ } else {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ dependency_from_external.srcStageMask |= reading_stages;
+ }
+ } break;
+ default: {
+ ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
}
- } break;
- default: {
- ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
}
}
@@ -3485,6 +3533,10 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
if (p_passes[last_pass].depth_attachment == i) {
used_last = true;
}
+ } else if (is_vrs) {
+ if (p_passes[last_pass].vrs_attachment == i) {
+ used_last = true;
+ }
} else {
if (p_passes[last_pass].resolve_attachments.size()) {
//if using resolve attachments, check resolve attachments
@@ -3526,58 +3578,69 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
}
}
- switch (is_depth ? final_depth_action : final_action) {
- case FINAL_ACTION_READ: {
- if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false);
- } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
- description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
- update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, true);
- } else {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
- // TODO: What does this mean about the next usage (and thus appropriate dependency masks
- }
- } break;
- case FINAL_ACTION_DISCARD: {
- if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
- } else {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
- }
- } break;
- case FINAL_ACTION_CONTINUE: {
- if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
- description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
- description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- } else {
- description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
- }
+ if (is_vrs) {
+ // We don't change our VRS texture during this process
- } break;
- default: {
- ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
+ description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ // TODO do we need to update our external dependency ?
+ // update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false);
+ } else {
+ switch (is_depth ? final_depth_action : final_action) {
+ case FINAL_ACTION_READ: {
+ if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false);
+ } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
+ description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, true);
+ } else {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ // TODO: What does this mean about the next usage (and thus appropriate dependency masks
+ }
+ } break;
+ case FINAL_ACTION_DISCARD: {
+ if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ } else {
+ description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ }
+ } break;
+ case FINAL_ACTION_CONTINUE: {
+ if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
+ description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ } else {
+ description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ }
+
+ } break;
+ default: {
+ ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
+ }
}
}
@@ -3586,12 +3649,14 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
attachments.push_back(description);
}
- LocalVector<VkSubpassDescription> subpasses;
- LocalVector<LocalVector<VkAttachmentReference>> color_reference_array;
- LocalVector<LocalVector<VkAttachmentReference>> input_reference_array;
- LocalVector<LocalVector<VkAttachmentReference>> resolve_reference_array;
+ LocalVector<VkSubpassDescription2KHR> subpasses;
+ LocalVector<LocalVector<VkAttachmentReference2KHR>> color_reference_array;
+ LocalVector<LocalVector<VkAttachmentReference2KHR>> input_reference_array;
+ LocalVector<LocalVector<VkAttachmentReference2KHR>> resolve_reference_array;
LocalVector<LocalVector<uint32_t>> preserve_reference_array;
- LocalVector<VkAttachmentReference> depth_reference_array;
+ LocalVector<VkAttachmentReference2KHR> depth_reference_array;
+ LocalVector<VkAttachmentReference2KHR> vrs_reference_array;
+ LocalVector<VkFragmentShadingRateAttachmentInfoKHR> vrs_attachment_info_array;
subpasses.resize(p_passes.size());
color_reference_array.resize(p_passes.size());
@@ -3599,20 +3664,25 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
resolve_reference_array.resize(p_passes.size());
preserve_reference_array.resize(p_passes.size());
depth_reference_array.resize(p_passes.size());
+ vrs_reference_array.resize(p_passes.size());
+ vrs_attachment_info_array.resize(p_passes.size());
- LocalVector<VkSubpassDependency> subpass_dependencies;
+ LocalVector<VkSubpassDependency2KHR> subpass_dependencies;
for (int i = 0; i < p_passes.size(); i++) {
const FramebufferPass *pass = &p_passes[i];
- LocalVector<VkAttachmentReference> &color_references = color_reference_array[i];
+ LocalVector<VkAttachmentReference2KHR> &color_references = color_reference_array[i];
TextureSamples texture_samples = TEXTURE_SAMPLES_1;
bool is_multisample_first = true;
+ void *subpass_nextptr = nullptr;
for (int j = 0; j < pass->color_attachments.size(); j++) {
int32_t attachment = pass->color_attachments[j];
- VkAttachmentReference reference;
+ VkAttachmentReference2KHR reference;
+ reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
+ reference.pNext = nullptr;
if (attachment == FramebufferPass::ATTACHMENT_UNUSED) {
reference.attachment = VK_ATTACHMENT_UNUSED;
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -3631,14 +3701,17 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment_last_pass[attachment] = i;
}
+ reference.aspectMask = 0;
color_references.push_back(reference);
}
- LocalVector<VkAttachmentReference> &input_references = input_reference_array[i];
+ LocalVector<VkAttachmentReference2KHR> &input_references = input_reference_array[i];
for (int j = 0; j < pass->input_attachments.size(); j++) {
int32_t attachment = pass->input_attachments[j];
- VkAttachmentReference reference;
+ VkAttachmentReference2KHR reference;
+ reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
+ reference.pNext = nullptr;
if (attachment == FramebufferPass::ATTACHMENT_UNUSED) {
reference.attachment = VK_ATTACHMENT_UNUSED;
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -3650,10 +3723,11 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
reference.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
attachment_last_pass[attachment] = i;
}
+ reference.aspectMask = 0; // TODO we need to set this here, possibly VK_IMAGE_ASPECT_COLOR_BIT ??
input_references.push_back(reference);
}
- LocalVector<VkAttachmentReference> &resolve_references = resolve_reference_array[i];
+ LocalVector<VkAttachmentReference2KHR> &resolve_references = resolve_reference_array[i];
if (pass->resolve_attachments.size() > 0) {
ERR_FAIL_COND_V_MSG(pass->resolve_attachments.size() != pass->color_attachments.size(), VK_NULL_HANDLE, "The amount of resolve attachments (" + itos(pass->resolve_attachments.size()) + ") must match the number of color attachments (" + itos(pass->color_attachments.size()) + ").");
@@ -3661,7 +3735,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
}
for (int j = 0; j < pass->resolve_attachments.size(); j++) {
int32_t attachment = pass->resolve_attachments[j];
- VkAttachmentReference reference;
+ VkAttachmentReference2KHR reference;
+ reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
+ reference.pNext = nullptr;
if (attachment == FramebufferPass::ATTACHMENT_UNUSED) {
reference.attachment = VK_ATTACHMENT_UNUSED;
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -3676,10 +3752,13 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
attachment_last_pass[attachment] = i;
}
+ reference.aspectMask = 0;
resolve_references.push_back(reference);
}
- VkAttachmentReference &depth_stencil_reference = depth_reference_array[i];
+ VkAttachmentReference2KHR &depth_stencil_reference = depth_reference_array[i];
+ depth_stencil_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
+ depth_stencil_reference.pNext = nullptr;
if (pass->depth_attachment != FramebufferPass::ATTACHMENT_UNUSED) {
int32_t attachment = pass->depth_attachment;
@@ -3688,6 +3767,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
depth_stencil_reference.attachment = attachment_remap[attachment];
depth_stencil_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ depth_stencil_reference.aspectMask = 0;
attachment_last_pass[attachment] = i;
if (is_multisample_first) {
@@ -3702,6 +3782,32 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
depth_stencil_reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
}
+ if (context->get_vrs_capabilities().attachment_vrs_supported && pass->vrs_attachment != FramebufferPass::ATTACHMENT_UNUSED) {
+ int32_t attachment = pass->vrs_attachment;
+ ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), VK_NULL_HANDLE, "Invalid framebuffer VRS format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), VRS attachment.");
+ ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer VRS format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as VRS, but it's not a VRS attachment.");
+ ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer VRS attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
+
+ VkAttachmentReference2KHR &vrs_reference = vrs_reference_array[i];
+ vrs_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
+ vrs_reference.pNext = nullptr;
+ vrs_reference.attachment = attachment_remap[attachment];
+ vrs_reference.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+ vrs_reference.aspectMask = 0;
+
+ Size2i texel_size = context->get_vrs_capabilities().max_texel_size;
+
+ VkFragmentShadingRateAttachmentInfoKHR &vrs_attachment_info = vrs_attachment_info_array[i];
+ vrs_attachment_info.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
+ vrs_attachment_info.pNext = nullptr;
+ vrs_attachment_info.pFragmentShadingRateAttachment = &vrs_reference;
+ vrs_attachment_info.shadingRateAttachmentTexelSize = { uint32_t(texel_size.x), uint32_t(texel_size.y) };
+
+ attachment_last_pass[attachment] = i;
+
+ subpass_nextptr = &vrs_attachment_info;
+ }
+
LocalVector<uint32_t> &preserve_references = preserve_reference_array[i];
for (int j = 0; j < pass->preserve_attachments.size(); j++) {
@@ -3718,9 +3824,17 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
}
}
- VkSubpassDescription &subpass = subpasses[i];
+ VkSubpassDescription2KHR &subpass = subpasses[i];
+ subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
+ subpass.pNext = subpass_nextptr;
subpass.flags = 0;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ if (p_view_count == 1) {
+ // VUID-VkSubpassDescription2-multiview-06558: If the multiview feature is not enabled, viewMask must be 0.
+ subpass.viewMask = 0;
+ } else {
+ subpass.viewMask = view_mask;
+ }
subpass.inputAttachmentCount = input_references.size();
if (input_references.size()) {
subpass.pInputAttachments = input_references.ptr();
@@ -3757,7 +3871,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
}
if (i > 0) {
- VkSubpassDependency dependency;
+ VkSubpassDependency2KHR dependency;
+ dependency.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR;
+ dependency.pNext = nullptr;
dependency.srcSubpass = i - 1;
dependency.dstSubpass = i;
dependency.srcStageMask = 0;
@@ -3767,6 +3883,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
+ dependency.viewOffset = 0;
subpass_dependencies.push_back(dependency);
}
/*
@@ -3784,10 +3901,11 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
*/
}
- VkRenderPassCreateInfo render_pass_create_info;
- render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ VkRenderPassCreateInfo2KHR render_pass_create_info;
+ render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
render_pass_create_info.pNext = nullptr;
render_pass_create_info.flags = 0;
+
render_pass_create_info.attachmentCount = attachments.size();
render_pass_create_info.pAttachments = attachments.ptr();
render_pass_create_info.subpassCount = subpasses.size();
@@ -3804,13 +3922,21 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
render_pass_create_info.pDependencies = nullptr;
}
- // These are only used if we use multiview but we need to define them in scope.
- const uint32_t view_mask = (1 << p_view_count) - 1;
- const uint32_t correlation_mask = (1 << p_view_count) - 1;
+ if (p_view_count == 1) {
+ // VUID-VkRenderPassCreateInfo2-viewMask-03057: If the VkSubpassDescription2::viewMask member of all elements of pSubpasses is 0, correlatedViewMaskCount must be 0.
+ render_pass_create_info.correlatedViewMaskCount = 0;
+ render_pass_create_info.pCorrelatedViewMasks = nullptr;
+ } else {
+ render_pass_create_info.correlatedViewMaskCount = 1;
+ render_pass_create_info.pCorrelatedViewMasks = &correlation_mask;
+ }
+
Vector<uint32_t> view_masks;
VkRenderPassMultiviewCreateInfo render_pass_multiview_create_info;
if (p_view_count > 1) {
+ // this may no longer be needed with the new settings already including this
+
const VulkanContext::MultiviewCapabilities capabilities = context->get_multiview_capabilities();
// For now this only works with multiview!
@@ -3837,8 +3963,8 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
}
VkRenderPass render_pass;
- VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass);
- ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass failed with error " + itos(res) + ".");
+ VkResult res = context->vkCreateRenderPass2KHR(device, &render_pass_create_info, nullptr, &render_pass);
+ ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass2KHR failed with error " + itos(res) + ".");
return render_pass;
}
@@ -3857,7 +3983,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
passes.push_back(pass);
return framebuffer_format_create_multipass(p_format, passes, p_view_count);
}
-RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count) {
+RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count) {
_THREAD_SAFE_METHOD_
FramebufferFormatKey key;
@@ -3899,9 +4025,12 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
return E->get();
}
- VkSubpassDescription subpass;
+ VkSubpassDescription2KHR subpass;
+ subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
+ subpass.pNext = nullptr;
subpass.flags = 0;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.viewMask = 0;
subpass.inputAttachmentCount = 0; //unsupported for now
subpass.pInputAttachments = nullptr;
subpass.colorAttachmentCount = 0;
@@ -3911,8 +4040,8 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr;
- VkRenderPassCreateInfo render_pass_create_info;
- render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ VkRenderPassCreateInfo2KHR render_pass_create_info;
+ render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
render_pass_create_info.pNext = nullptr;
render_pass_create_info.flags = 0;
render_pass_create_info.attachmentCount = 0;
@@ -3921,11 +4050,13 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
render_pass_create_info.pSubpasses = &subpass;
render_pass_create_info.dependencyCount = 0;
render_pass_create_info.pDependencies = nullptr;
+ render_pass_create_info.correlatedViewMaskCount = 0;
+ render_pass_create_info.pCorrelatedViewMasks = nullptr;
VkRenderPass render_pass;
- VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass);
+ VkResult res = context->vkCreateRenderPass2KHR(device, &render_pass_create_info, nullptr, &render_pass);
- ERR_FAIL_COND_V_MSG(res, 0, "vkCreateRenderPass for empty fb failed with error " + itos(res) + ".");
+ ERR_FAIL_COND_V_MSG(res, 0, "vkCreateRenderPass2KHR for empty fb failed with error " + itos(res) + ".");
if (render_pass == VK_NULL_HANDLE) { //was likely invalid
return INVALID_ID;
@@ -3963,7 +4094,11 @@ RID RenderingDeviceVulkan::framebuffer_create_empty(const Size2i &p_size, Textur
framebuffer.size = p_size;
framebuffer.view_count = 1;
- return framebuffer_owner.make_rid(framebuffer);
+ RID id = framebuffer_owner.make_rid(framebuffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check, uint32_t p_view_count) {
@@ -3978,6 +4113,8 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac
if (texture && texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
pass.depth_attachment = i;
+ } else if (texture && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
+ pass.vrs_attachment = i;
} else {
pass.color_attachments.push_back(texture ? i : FramebufferPass::ATTACHMENT_UNUSED);
}
@@ -3989,7 +4126,7 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac
return framebuffer_create_multipass(p_texture_attachments, passes, p_format_check, p_view_count);
}
-RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) {
+RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) {
_THREAD_SAFE_METHOD_
Vector<AttachmentFormat> attachments;
@@ -4008,6 +4145,10 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex
size.width = texture->width;
size.height = texture->height;
size_set = true;
+ } else if (texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
+ // If this is not the first attachement we assume this is used as the VRS attachment
+ // in this case this texture will be 1/16th the size of the color attachement.
+ // So we skip the size check
} else {
ERR_FAIL_COND_V_MSG((uint32_t)size.width != texture->width || (uint32_t)size.height != texture->height, RID(),
"All textures in a framebuffer should be the same size.");
@@ -4037,6 +4178,9 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex
framebuffer.view_count = p_view_count;
RID id = framebuffer_owner.make_rid(framebuffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
for (int i = 0; i < p_texture_attachments.size(); i++) {
if (p_texture_attachments[i].is_valid()) {
@@ -4056,6 +4200,22 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_get_form
return framebuffer->format_id;
}
+bool RenderingDeviceVulkan::framebuffer_is_valid(RID p_framebuffer) const {
+ _THREAD_SAFE_METHOD_
+
+ return framebuffer_owner.owns(p_framebuffer);
+}
+
+void RenderingDeviceVulkan::framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata) {
+ _THREAD_SAFE_METHOD_
+
+ Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer);
+ ERR_FAIL_COND(!framebuffer);
+
+ framebuffer->invalidated_callback = p_callback;
+ framebuffer->invalidated_callback_userdata = p_userdata;
+}
+
/*****************/
/**** SAMPLER ****/
/*****************/
@@ -4098,7 +4258,11 @@ RID RenderingDeviceVulkan::sampler_create(const SamplerState &p_state) {
VkResult res = vkCreateSampler(device, &sampler_create_info, nullptr, &sampler);
ERR_FAIL_COND_V_MSG(res, RID(), "vkCreateSampler failed with error " + itos(res) + ".");
- return sampler_owner.make_rid(sampler);
+ RID id = sampler_owner.make_rid(sampler);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
/**********************/
@@ -4127,7 +4291,11 @@ RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Vec
_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, false);
}
- return vertex_buffer_owner.make_rid(buffer);
+ RID id = vertex_buffer_owner.make_rid(buffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
// Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated
@@ -4288,7 +4456,11 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff
_buffer_update(&index_buffer, 0, r, data_size);
_buffer_memory_barrier(index_buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, false);
}
- return index_buffer_owner.make_rid(index_buffer);
+ RID id = index_buffer_owner.make_rid(index_buffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
RID RenderingDeviceVulkan::index_array_create(RID p_index_buffer, uint32_t p_index_offset, uint32_t p_index_count) {
@@ -4556,7 +4728,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
#define SHADER_BINARY_VERSION 3
String RenderingDeviceVulkan::shader_get_binary_cache_key() const {
- return "Vulkan-SV" + itos(SHADER_BINARY_VERSION);
+ return "Vulkan-SV" + itos(SHADER_BINARY_VERSION) + "-" + String(VERSION_NUMBER) + "-" + String(VERSION_HASH);
}
struct RenderingDeviceVulkanShaderBinaryDataBinding {
@@ -4647,18 +4819,6 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed getting descriptor bindings.");
- uint32_t interface_vars_count = 0;
- result = spvReflectEnumerateInterfaceVariables(&module, &interface_vars_count, nullptr);
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating interface variables.");
-
- Vector<SpvReflectInterfaceVariable *> interface_vars;
- interface_vars.resize(interface_vars_count);
- result = spvReflectEnumerateInterfaceVariables(&module, &interface_vars_count, interface_vars.ptrw());
-
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed getting interface variables.");
-
for (uint32_t j = 0; j < binding_count; j++) {
const SpvReflectDescriptorBinding &binding = *bindings[j];
@@ -4666,6 +4826,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
bool need_array_dimensions = false;
bool need_block_size = false;
+ bool may_be_writable = false;
switch (binding.descriptor_type) {
case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER: {
@@ -4683,6 +4844,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
info.type = UNIFORM_TYPE_IMAGE;
need_array_dimensions = true;
+ may_be_writable = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {
info.type = UNIFORM_TYPE_TEXTURE_BUFFER;
@@ -4691,6 +4853,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
info.type = UNIFORM_TYPE_IMAGE_BUFFER;
need_array_dimensions = true;
+ may_be_writable = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
info.type = UNIFORM_TYPE_UNIFORM_BUFFER;
@@ -4699,6 +4862,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
info.type = UNIFORM_TYPE_STORAGE_BUFFER;
need_block_size = true;
+ may_be_writable = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: {
ERR_PRINT("Dynamic uniform buffer not supported.");
@@ -4737,17 +4901,11 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
info.length = 0;
}
- SpvReflectInterfaceVariable *interface_var = nullptr;
- for (uint32_t k = 0; k < interface_vars_count; k++) {
- if (interface_vars[k]->spirv_id == binding.spirv_id) {
- interface_var = interface_vars[k];
- break;
- }
+ if (may_be_writable) {
+ info.writable = !(binding.type_description->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE) && !(binding.block.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE);
+ } else {
+ info.writable = false;
}
- ERR_FAIL_COND_V_MSG(!interface_var, Vector<uint8_t>(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed finding interface variable.");
-
- info.writable = !(bool)(interface_var->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE);
info.binding = binding.binding;
uint32_t set = binding.set;
@@ -4771,6 +4929,10 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
ERR_FAIL_COND_V_MSG(uniform_info[set][k].length != info.length, Vector<uint8_t>(),
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different uniform size.");
+ //also, verify that it has the same writability
+ ERR_FAIL_COND_V_MSG(uniform_info[set][k].writable != info.writable, Vector<uint8_t>(),
+ "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different writability.");
+
//just append stage mask and return
uniform_info.write[set].write[k].stages |= 1 << stage;
exists = true;
@@ -5070,7 +5232,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
ERR_FAIL_COND_V(binptr[0] != 'G' || binptr[1] != 'V' || binptr[2] != 'B' || binptr[3] != 'D', RID());
uint32_t bin_version = decode_uint32(binptr + 4);
- ERR_FAIL_COND_V(bin_version > SHADER_BINARY_VERSION, RID());
+ ERR_FAIL_COND_V(bin_version != SHADER_BINARY_VERSION, RID());
uint32_t bin_data_size = decode_uint32(binptr + 8);
@@ -5395,7 +5557,11 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
ERR_FAIL_V_MSG(RID(), error_text);
}
- return shader_owner.make_rid(shader);
+ RID id = shader_owner.make_rid(shader);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
uint32_t RenderingDeviceVulkan::shader_get_vertex_input_attribute_mask(RID p_shader) {
@@ -5428,7 +5594,11 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Ve
_buffer_update(&buffer, 0, r, data_size);
_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, false);
}
- return uniform_buffer_owner.make_rid(buffer);
+ RID id = uniform_buffer_owner.make_rid(buffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, uint32_t p_usage) {
@@ -5499,7 +5669,11 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF
}
//allocate the view
- return texture_buffer_owner.make_rid(texture_buffer);
+ RID id = texture_buffer_owner.make_rid(texture_buffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
RenderingDeviceVulkan::DescriptorPool *RenderingDeviceVulkan::_descriptor_pool_allocate(const DescriptorPoolKey &p_key) {
@@ -6078,6 +6252,9 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
uniform_set.shader_id = p_shader;
RID id = uniform_set_owner.make_rid(uniform_set);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
//add dependencies
_add_dependency(id, p_shader);
for (uint32_t i = 0; i < uniform_count; i++) {
@@ -6103,7 +6280,7 @@ bool RenderingDeviceVulkan::uniform_set_is_valid(RID p_uniform_set) {
return uniform_set_owner.owns(p_uniform_set);
}
-void RenderingDeviceVulkan::uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) {
+void RenderingDeviceVulkan::uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata) {
UniformSet *us = uniform_set_owner.get_or_null(p_uniform_set);
ERR_FAIL_COND(!us);
us->invalidated_callback = p_callback;
@@ -6566,11 +6743,28 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
dynamic_state_create_info.dynamicStateCount = dynamic_states.size();
dynamic_state_create_info.pDynamicStates = dynamic_states.ptr();
+ void *graphics_pipeline_nextptr = nullptr;
+
+ VkPipelineFragmentShadingRateStateCreateInfoKHR vrs_create_info;
+ if (context->get_vrs_capabilities().attachment_vrs_supported) {
+ // If VRS is used, this defines how the different VRS types are combined.
+ // combinerOps[0] decides how we use the output of pipeline and primitive (drawcall) VRS
+ // combinerOps[1] decides how we use the output of combinerOps[0] and our attachment VRS
+
+ vrs_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR;
+ vrs_create_info.pNext = nullptr;
+ vrs_create_info.fragmentSize = { 4, 4 };
+ vrs_create_info.combinerOps[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; // We don't use pipeline/primitive VRS so this really doesn't matter
+ vrs_create_info.combinerOps[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR; // always use the outcome of attachment VRS if enabled
+
+ graphics_pipeline_nextptr = &vrs_create_info;
+ }
+
//finally, pipeline create info
VkGraphicsPipelineCreateInfo graphics_pipeline_create_info;
graphics_pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- graphics_pipeline_create_info.pNext = nullptr;
+ graphics_pipeline_create_info.pNext = graphics_pipeline_nextptr;
graphics_pipeline_create_info.flags = 0;
Vector<VkPipelineShaderStageCreateInfo> pipeline_stages = shader->pipeline_stages;
@@ -6683,6 +6877,9 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
#endif
//create ID to associate with this pipeline
RID id = render_pipeline_owner.make_rid(pipeline);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
//now add all the dependencies
_add_dependency(id, p_shader);
return id;
@@ -6735,7 +6932,7 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
if (psc.constant_id == sc.constant.constant_id) {
ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type.");
- data_ptr[i] = sc.constant.int_value;
+ data_ptr[i] = psc.int_value;
break;
}
}
@@ -6772,6 +6969,9 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi
//create ID to associate with this pipeline
RID id = compute_pipeline_owner.make_rid(pipeline);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
//now add all the dependencies
_add_dependency(id, p_shader);
return id;
@@ -6919,8 +7119,10 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu
Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]);
if (texture) {
attachments.push_back(texture->view);
- ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG);
- ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG);
+ if (!(texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) { // VRS attachment will be a different size.
+ ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG);
+ ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG);
+ }
}
}
framebuffer_create_info.attachmentCount = attachments.size();
@@ -7055,7 +7257,6 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
}
void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) {
- ERR_FAIL_COND_MSG(p_clear_color && p_clear_colors.size() != framebuffer->texture_ids.size(), "Clear color values supplied (" + itos(p_clear_colors.size()) + ") differ from the amount required for framebuffer color attachments (" + itos(framebuffer->texture_ids.size()) + ").");
Vector<VkClearAttachment> clear_attachments;
int color_index = 0;
int texture_index = 0;
@@ -7144,11 +7345,14 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
}
}
- if (p_initial_color_action == INITIAL_ACTION_CLEAR) { //check clear values
+ if (p_initial_color_action == INITIAL_ACTION_CLEAR || needs_clear_color) { //check clear values
int color_count = 0;
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
- if (!texture || !(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
+ // We only check for our VRS usage bit if this is not the first texture id.
+ // If it is the first we're likely populating our VRS texture.
+ // Bit dirty but..
+ if (!texture || (!(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !(i != 0 && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT))) {
color_count++;
}
}
@@ -7241,7 +7445,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
}
}
- if (p_initial_color_action == INITIAL_ACTION_CLEAR) { //check clear values
+ if (p_initial_color_action == INITIAL_ACTION_CLEAR || needs_clear_color) { //check clear values
int color_count = 0;
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
@@ -8549,6 +8753,11 @@ void RenderingDeviceVulkan::_free_internal(RID p_id) {
} else if (framebuffer_owner.owns(p_id)) {
Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_id);
frames[frame].framebuffers_to_dispose_of.push_back(*framebuffer);
+
+ if (framebuffer->invalidated_callback != nullptr) {
+ framebuffer->invalidated_callback(framebuffer->invalidated_callback_userdata);
+ }
+
framebuffer_owner.free(p_id);
} else if (sampler_owner.owns(p_id)) {
VkSampler *sampler = sampler_owner.get_or_null(p_id);
@@ -9009,17 +9218,6 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
{
device_capabilities.version_major = p_context->get_vulkan_major();
device_capabilities.version_minor = p_context->get_vulkan_minor();
-
- // get info about subgroups
- VulkanContext::SubgroupCapabilities subgroup_capabilities = p_context->get_subgroup_capabilities();
- device_capabilities.subgroup_size = subgroup_capabilities.size;
- device_capabilities.subgroup_in_shaders = subgroup_capabilities.supported_stages_flags_rd();
- device_capabilities.subgroup_operations = subgroup_capabilities.supported_operations_flags_rd();
-
- // get info about further features
- VulkanContext::MultiviewCapabilities multiview_capabilies = p_context->get_multiview_capabilities();
- device_capabilities.supports_multiview = multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1;
- device_capabilities.supports_fsr_half_float = p_context->get_shader_capabilities().shader_float16_is_supported && p_context->get_storage_buffer_capabilities().storage_buffer_16_bit_access_is_supported;
}
context = p_context;
@@ -9368,7 +9566,7 @@ String RenderingDeviceVulkan::get_captured_timestamp_name(uint32_t p_index) cons
return frames[frame].timestamp_result_names[p_index];
}
-uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) {
+uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) const {
switch (p_limit) {
case LIMIT_MAX_BOUND_UNIFORM_SETS:
return limits.maxBoundDescriptorSets;
@@ -9438,7 +9636,18 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) {
return limits.maxComputeWorkGroupSize[1];
case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z:
return limits.maxComputeWorkGroupSize[2];
-
+ case LIMIT_SUBGROUP_SIZE: {
+ VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
+ return subgroup_capabilities.size;
+ }
+ case LIMIT_SUBGROUP_IN_SHADERS: {
+ VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
+ return subgroup_capabilities.supported_stages_flags_rd();
+ }
+ case LIMIT_SUBGROUP_OPERATIONS: {
+ VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
+ return subgroup_capabilities.supported_operations_flags_rd();
+ }
default:
ERR_FAIL_V(0);
}
@@ -9538,6 +9747,25 @@ RenderingDevice *RenderingDeviceVulkan::create_local_device() {
return rd;
}
+bool RenderingDeviceVulkan::has_feature(const Features p_feature) const {
+ switch (p_feature) {
+ case SUPPORTS_MULTIVIEW: {
+ VulkanContext::MultiviewCapabilities multiview_capabilies = context->get_multiview_capabilities();
+ return multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1;
+ } break;
+ case SUPPORTS_FSR_HALF_FLOAT: {
+ return context->get_shader_capabilities().shader_float16_is_supported && context->get_storage_buffer_capabilities().storage_buffer_16_bit_access_is_supported;
+ } break;
+ case SUPPORTS_ATTACHMENT_VRS: {
+ VulkanContext::VRSCapabilities vrs_capabilities = context->get_vrs_capabilities();
+ return vrs_capabilities.attachment_vrs_supported;
+ } break;
+ default: {
+ return false;
+ }
+ }
+}
+
RenderingDeviceVulkan::RenderingDeviceVulkan() {
device_capabilities.device_family = DEVICE_VULKAN;
}
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index ec9e864370..d98ac1114b 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -241,6 +241,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
Vector<AttachmentFormat> attachments;
Vector<FramebufferPass> passes;
uint32_t view_count = 1;
+
bool operator<(const FramebufferFormatKey &p_key) const {
if (view_count != p_key.view_count) {
return view_count < p_key.view_count;
@@ -391,6 +392,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t storage_mask = 0;
Vector<RID> texture_ids;
+ InvalidationCallback invalidated_callback = nullptr;
+ void *invalidated_callback_userdata = nullptr;
struct Version {
VkFramebuffer framebuffer = VK_NULL_HANDLE;
@@ -746,7 +749,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
LocalVector<AttachableTexture> attachable_textures; //used for validation
Vector<Texture *> mutable_sampled_textures; //used for layout change
Vector<Texture *> mutable_storage_textures; //used for layout change
- UniformSetInvalidatedCallback invalidated_callback = nullptr;
+ InvalidationCallback invalidated_callback = nullptr;
void *invalidated_callback_userdata = nullptr;
};
@@ -1058,13 +1061,15 @@ public:
/*********************/
virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1);
- virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1);
+ virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1);
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1);
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0);
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
- virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
+ virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID);
+ virtual bool framebuffer_is_valid(RID p_framebuffer) const;
+ virtual void framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata);
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer);
@@ -1109,7 +1114,7 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);
virtual bool uniform_set_is_valid(RID p_uniform_set);
- virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata);
+ virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata);
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); //works for any buffer
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL);
@@ -1203,7 +1208,7 @@ public:
/**** Limits ****/
/****************/
- virtual uint64_t limit_get(Limit p_limit);
+ virtual uint64_t limit_get(Limit p_limit) const;
virtual void prepare_screen_for_drawing();
void initialize(VulkanContext *p_context, bool p_local_device = false);
@@ -1234,6 +1239,8 @@ public:
virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0);
+ virtual bool has_feature(const Features p_feature) const;
+
RenderingDeviceVulkan();
~RenderingDeviceVulkan();
};
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 0301f5b7fa..a9a8ce68ac 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -48,6 +48,18 @@
VulkanHooks *VulkanContext::vulkan_hooks = nullptr;
+VkResult VulkanContext::vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
+ if (fpCreateRenderPass2KHR == nullptr) {
+ fpCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)vkGetInstanceProcAddr(inst, "vkCreateRenderPass2KHR");
+ }
+
+ if (fpCreateRenderPass2KHR == nullptr) {
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ } else {
+ return (fpCreateRenderPass2KHR)(device, pCreateInfo, pAllocator, pRenderPass);
+ }
+}
+
VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
@@ -72,20 +84,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;
}
@@ -215,13 +227,13 @@ VkBool32 VulkanContext::_check_layers(uint32_t check_count, const char *const *c
Error VulkanContext::_get_preferred_validation_layers(uint32_t *count, const char *const **names) {
static const LocalVector<LocalVector<const char *>> instance_validation_layers_alt{
- // Preferred set of validation layers
+ // Preferred set of validation layers.
{ "VK_LAYER_KHRONOS_validation" },
- // Alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers
+ // Alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers.
{ "VK_LAYER_LUNARG_standard_validation" },
- // Alternative (deprecated, removed in SDK 1.1.121.1) set of validation layers
+ // Alternative (deprecated, removed in SDK 1.1.121.1) set of validation layers.
{ "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", "VK_LAYER_GOOGLE_unique_objects" }
};
@@ -269,7 +281,7 @@ typedef VkResult(VKAPI_PTR *_vkEnumerateInstanceVersion)(uint32_t *);
Error VulkanContext::_obtain_vulkan_version() {
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkApplicationInfo.html#_description
- // for Vulkan 1.0 vkEnumerateInstanceVersion is not available, including not in the loader we compile against on Android.
+ // For Vulkan 1.0 vkEnumerateInstanceVersion is not available, including not in the loader we compile against on Android.
_vkEnumerateInstanceVersion func = (_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion");
if (func != nullptr) {
uint32_t api_version;
@@ -279,15 +291,15 @@ Error VulkanContext::_obtain_vulkan_version() {
vulkan_minor = VK_API_VERSION_MINOR(api_version);
vulkan_patch = VK_API_VERSION_PATCH(api_version);
} else {
- // according to the documentation this shouldn't fail with anything except a memory allocation error
- // in which case we're in deep trouble anyway
+ // According to the documentation this shouldn't fail with anything except a memory allocation error
+ // in which case we're in deep trouble anyway.
ERR_FAIL_V(ERR_CANT_CREATE);
}
} else {
print_line("vkEnumerateInstanceVersion not available, assuming Vulkan 1.0.");
}
- // we don't go above 1.2
+ // We don't go above 1.2.
if ((vulkan_major > 1) || (vulkan_major == 1 && vulkan_minor > 2)) {
vulkan_major = 1;
vulkan_minor = 2;
@@ -303,7 +315,7 @@ Error VulkanContext::_initialize_extensions() {
enabled_extension_count = 0;
enabled_debug_utils = false;
enabled_debug_report = false;
- /* Look for instance extensions */
+ // Look for instance extensions.
VkBool32 surfaceExtFound = 0;
VkBool32 platformSurfaceExtFound = 0;
memset(extension_names, 0, sizeof(extension_names));
@@ -403,7 +415,7 @@ String VulkanContext::SubgroupCapabilities::supported_stages_desc() const {
res += ", STAGE_COMPUTE";
}
- /* these are not defined on Android GRMBL */
+ // These are not defined on Android GRMBL.
if (supportedStages & 0x00000100 /* VK_SHADER_STAGE_RAYGEN_BIT_KHR */) {
res += ", STAGE_RAYGEN_KHR";
}
@@ -429,7 +441,7 @@ String VulkanContext::SubgroupCapabilities::supported_stages_desc() const {
res += ", STAGE_MESH_NV";
}
- return res.substr(2); // remove first ", "
+ return res.substr(2); // Remove first ", "
}
uint32_t VulkanContext::SubgroupCapabilities::supported_operations_flags_rd() const {
@@ -494,19 +506,22 @@ String VulkanContext::SubgroupCapabilities::supported_operations_desc() const {
res += ", FEATURE_PARTITIONED_NV";
}
- return res.substr(2); // remove first ", "
+ return res.substr(2); // Remove first ", "
}
Error VulkanContext::_check_capabilities() {
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html
// https://www.khronos.org/blog/vulkan-subgroup-tutorial
- // for Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android.
+ // For Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android.
- // so we check if the functions are accessible by getting their function pointers and skipping if not
- // (note that the desktop loader does a better job here but the android loader doesn't)
+ // So we check if the functions are accessible by getting their function pointers and skipping if not
+ // (note that the desktop loader does a better job here but the android loader doesn't.)
- // assume not supported until proven otherwise
+ // Assume not supported until proven otherwise.
+ vrs_capabilities.pipeline_vrs_supported = false;
+ vrs_capabilities.primitive_vrs_supported = false;
+ vrs_capabilities.attachment_vrs_supported = false;
multiview_capabilities.is_supported = false;
multiview_capabilities.geometry_shader_is_supported = false;
multiview_capabilities.tessellation_shader_is_supported = false;
@@ -523,17 +538,25 @@ Error VulkanContext::_check_capabilities() {
storage_buffer_capabilities.storage_push_constant_16_is_supported = false;
storage_buffer_capabilities.storage_input_output_16 = false;
- // check for extended features
+ // Check for extended features.
PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2");
if (vkGetPhysicalDeviceFeatures2_func == nullptr) {
- // In Vulkan 1.0 might be accessible under its original extension name
+ // In Vulkan 1.0 might be accessible under its original extension name.
vkGetPhysicalDeviceFeatures2_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR");
}
if (vkGetPhysicalDeviceFeatures2_func != nullptr) {
- // check our extended features
+ // Check our extended features.
+ VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features = {
+ /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR,
+ /*pNext*/ nullptr,
+ /*pipelineFragmentShadingRate*/ false,
+ /*primitiveFragmentShadingRate*/ false,
+ /*attachmentFragmentShadingRate*/ false,
+ };
+
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {
/*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
- /*pNext*/ nullptr,
+ /*pNext*/ &vrs_features,
/*shaderFloat16*/ false,
/*shaderInt8*/ false,
};
@@ -561,6 +584,10 @@ Error VulkanContext::_check_capabilities() {
vkGetPhysicalDeviceFeatures2_func(gpu, &device_features);
+ vrs_capabilities.pipeline_vrs_supported = vrs_features.pipelineFragmentShadingRate;
+ vrs_capabilities.primitive_vrs_supported = vrs_features.primitiveFragmentShadingRate;
+ vrs_capabilities.attachment_vrs_supported = vrs_features.attachmentFragmentShadingRate;
+
multiview_capabilities.is_supported = multiview_features.multiview;
multiview_capabilities.geometry_shader_is_supported = multiview_features.multiviewGeometryShader;
multiview_capabilities.tessellation_shader_is_supported = multiview_features.multiviewTessellationShader;
@@ -574,31 +601,40 @@ Error VulkanContext::_check_capabilities() {
storage_buffer_capabilities.storage_input_output_16 = storage_feature.storageInputOutput16;
}
- // check extended properties
+ // Check extended properties.
PFN_vkGetPhysicalDeviceProperties2 device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2");
if (device_properties_func == nullptr) {
- // In Vulkan 1.0 might be accessible under its original extension name
+ // In Vulkan 1.0 might be accessible under its original extension name.
device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR");
}
if (device_properties_func != nullptr) {
+ VkPhysicalDeviceFragmentShadingRatePropertiesKHR vrsProperties;
VkPhysicalDeviceMultiviewProperties multiviewProperties;
VkPhysicalDeviceSubgroupProperties subgroupProperties;
VkPhysicalDeviceProperties2 physicalDeviceProperties;
+ void *nextptr = nullptr;
subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
- subgroupProperties.pNext = nullptr;
-
- physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ subgroupProperties.pNext = nextptr;
+ nextptr = &subgroupProperties;
if (multiview_capabilities.is_supported) {
multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
- multiviewProperties.pNext = &subgroupProperties;
+ multiviewProperties.pNext = nextptr;
- physicalDeviceProperties.pNext = &multiviewProperties;
- } else {
- physicalDeviceProperties.pNext = &subgroupProperties;
+ nextptr = &multiviewProperties;
+ }
+
+ if (vrs_capabilities.attachment_vrs_supported) {
+ vrsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;
+ vrsProperties.pNext = nextptr;
+
+ nextptr = &vrsProperties;
}
+ physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ physicalDeviceProperties.pNext = nextptr;
+
device_properties_func(gpu, &physicalDeviceProperties);
subgroup_capabilities.size = subgroupProperties.subgroupSize;
@@ -609,6 +645,28 @@ Error VulkanContext::_check_capabilities() {
// - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT
subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages;
+ if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) {
+ print_verbose("- Vulkan Variable Rate Shading supported:");
+ if (vrs_capabilities.pipeline_vrs_supported) {
+ print_verbose(" Pipeline fragment shading rate");
+ }
+ if (vrs_capabilities.primitive_vrs_supported) {
+ print_verbose(" Primitive fragment shading rate");
+ }
+ if (vrs_capabilities.attachment_vrs_supported) {
+ // TODO expose these somehow to the end user
+ vrs_capabilities.min_texel_size.x = vrsProperties.minFragmentShadingRateAttachmentTexelSize.width;
+ vrs_capabilities.min_texel_size.y = vrsProperties.minFragmentShadingRateAttachmentTexelSize.height;
+ vrs_capabilities.max_texel_size.x = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.width;
+ vrs_capabilities.max_texel_size.y = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.height;
+
+ print_verbose(String(" Attachment fragment shading rate") + String(", min texel size: (") + itos(vrs_capabilities.min_texel_size.x) + String(", ") + itos(vrs_capabilities.min_texel_size.y) + String(")") + String(", max texel size: (") + itos(vrs_capabilities.max_texel_size.x) + String(", ") + itos(vrs_capabilities.max_texel_size.y) + String(")"));
+ }
+
+ } else {
+ print_verbose("- Vulkan Variable Rate Shading not supported");
+ }
+
if (multiview_capabilities.is_supported) {
multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount;
multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex;
@@ -635,10 +693,10 @@ Error VulkanContext::_check_capabilities() {
}
Error VulkanContext::_create_instance() {
- /* obtain version */
+ // Obtain Vulkan version.
_obtain_vulkan_version();
- /* initialise extensions */
+ // Initialize extensions.
{
Error err = _initialize_extensions();
if (err != OK) {
@@ -726,8 +784,7 @@ Error VulkanContext::_create_instance() {
#endif
if (enabled_debug_utils) {
- // Setup VK_EXT_debug_utils function pointers always (we use them for
- // debug labels and names).
+ // Setup VK_EXT_debug_utils function pointers always (we use them for debug labels and names).
CreateDebugUtilsMessengerEXT =
(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT");
DestroyDebugUtilsMessengerEXT =
@@ -800,7 +857,7 @@ Error VulkanContext::_create_instance() {
}
Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
- /* Make initial call to query gpu_count, then second call for gpu info*/
+ // Make initial call to query gpu_count, then second call for gpu info.
uint32_t gpu_count = 0;
VkResult err = vkEnumeratePhysicalDevices(inst, &gpu_count, nullptr);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
@@ -836,7 +893,7 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
return ERR_CANT_CREATE;
}
- // not really needed but nice to print the correct entry
+ // Not really needed but nice to print the correct entry.
for (uint32_t i = 0; i < gpu_count; ++i) {
if (physical_devices[i] == gpu) {
device_index = i;
@@ -948,13 +1005,13 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
free(physical_devices);
- /* Look for device extensions */
+ // Look for device extensions.
uint32_t device_extension_count = 0;
VkBool32 swapchainExtFound = 0;
enabled_extension_count = 0;
memset(extension_names, 0, sizeof(extension_names));
- /* Get identifier properties */
+ // Get identifier properties.
vkGetPhysicalDeviceProperties(gpu, &gpu_props);
device_name = gpu_props.deviceName;
@@ -996,9 +1053,16 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
extension_names[enabled_extension_count++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
}
if (!strcmp(VK_KHR_MULTIVIEW_EXTENSION_NAME, device_extensions[i].extensionName)) {
- // if multiview is supported, enable it
+ // If multiview is supported, enable it.
extension_names[enabled_extension_count++] = VK_KHR_MULTIVIEW_EXTENSION_NAME;
}
+ if (!strcmp(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, device_extensions[i].extensionName)) {
+ // if shading rate image is supported, enable it
+ extension_names[enabled_extension_count++] = VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME;
+ }
+ if (!strcmp(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, device_extensions[i].extensionName)) {
+ extension_names[enabled_extension_count++] = VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME;
+ }
if (enabled_extension_count >= MAX_EXTENSIONS) {
free(device_extensions);
ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
@@ -1049,19 +1113,18 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
" extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\n"
"vkCreateInstance Failure");
- /* Call with nullptr data to get count */
+ // Call with nullptr data to get count.
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr);
ERR_FAIL_COND_V(queue_family_count == 0, ERR_CANT_CREATE);
queue_props = (VkQueueFamilyProperties *)malloc(queue_family_count * sizeof(VkQueueFamilyProperties));
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, queue_props);
-
// Query fine-grained feature support for this device.
// If app has specific feature requirements it should check supported
// features based on this query
vkGetPhysicalDeviceFeatures(gpu, &physical_device_features);
- physical_device_features.robustBufferAccess = false; //turn off robust buffer access, which can hamper performance on some hardware
+ physical_device_features.robustBufferAccess = false; // Turn off robust buffer access, which can hamper performance on some hardware.
#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
{ \
@@ -1076,7 +1139,7 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR);
GET_INSTANCE_PROC_ADDR(inst, GetSwapchainImagesKHR);
- // get info about what our vulkan driver is capable off
+ // Gets capability info for current Vulkan driver.
{
Error res = _check_capabilities();
if (res != OK) {
@@ -1110,11 +1173,23 @@ Error VulkanContext::_create_device() {
};
nextptr = &shader_features;
+ VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features;
+ if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) {
+ // insert into our chain to enable these features if they are available
+ vrs_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;
+ vrs_features.pNext = nextptr;
+ vrs_features.pipelineFragmentShadingRate = vrs_capabilities.pipeline_vrs_supported;
+ vrs_features.primitiveFragmentShadingRate = vrs_capabilities.primitive_vrs_supported;
+ vrs_features.attachmentFragmentShadingRate = vrs_capabilities.attachment_vrs_supported;
+
+ nextptr = &vrs_features;
+ }
+
VkPhysicalDeviceVulkan11Features vulkan11features;
VkPhysicalDevice16BitStorageFeaturesKHR storage_feature;
VkPhysicalDeviceMultiviewFeatures multiview_features;
if (vulkan_major > 1 || vulkan_minor >= 2) {
- // In Vulkan 1.2 and newer we use a newer struct to enable various features
+ // In Vulkan 1.2 and newer we use a newer struct to enable various features.
vulkan11features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
vulkan11features.pNext = nextptr;
@@ -1132,7 +1207,7 @@ Error VulkanContext::_create_device() {
vulkan11features.shaderDrawParameters = 0;
nextptr = &vulkan11features;
} else {
- // On Vulkan 1.0 and 1.1 we use our older structs to initialise these features
+ // On Vulkan 1.0 and 1.1 we use our older structs to initialise these features.
storage_feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;
storage_feature.pNext = nextptr;
storage_feature.storageBuffer16BitAccess = storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;
@@ -1161,7 +1236,7 @@ Error VulkanContext::_create_device() {
/*ppEnabledLayerNames*/ nullptr,
/*enabledExtensionCount*/ enabled_extension_count,
/*ppEnabledExtensionNames*/ (const char *const *)extension_names,
- /*pEnabledFeatures*/ &physical_device_features, // If specific features are required, pass them in here
+ /*pEnabledFeatures*/ &physical_device_features, // If specific features are required, pass them in here.
};
if (separate_present_queue) {
queues[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
@@ -1193,7 +1268,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) {
}
// Search for a graphics and a present queue in the array of queue
- // families, try to find one that supports both
+ // families, try to find one that supports both.
uint32_t graphicsQueueFamilyIndex = UINT32_MAX;
uint32_t presentQueueFamilyIndex = UINT32_MAX;
for (uint32_t i = 0; i < queue_family_count; i++) {
@@ -1223,7 +1298,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) {
free(supportsPresent);
- // Generate error if could not find both a graphics and a present queue
+ // Generate error if could not find both a graphics and a present queue.
ERR_FAIL_COND_V_MSG(graphicsQueueFamilyIndex == UINT32_MAX || presentQueueFamilyIndex == UINT32_MAX, ERR_CANT_CREATE,
"Could not find both graphics and present queues\n");
@@ -1279,7 +1354,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) {
color_space = surfFormats[0].colorSpace;
} else {
// These should be ordered with the ones we want to use on top and fallback modes further down
- // we want an 32bit RGBA unsigned normalised buffer or similar
+ // we want a 32bit RGBA unsigned normalised buffer or similar.
const VkFormat allowed_formats[] = {
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_R8G8B8A8_UNORM
@@ -1291,7 +1366,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) {
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "formatCount less than 1");
}
- // Find the first format that we support
+ // Find the first format that we support.
format = VK_FORMAT_UNDEFINED;
for (uint32_t af = 0; af < allowed_formats_count && format == VK_FORMAT_UNDEFINED; af++) {
for (uint32_t sf = 0; sf < formatCount && format == VK_FORMAT_UNDEFINED; sf++) {
@@ -1323,7 +1398,7 @@ Error VulkanContext::_create_semaphores() {
VkResult err;
// Create semaphores to synchronize acquiring presentable buffers before
- // rendering and waiting for drawing to be complete before presenting
+ // rendering and waiting for drawing to be complete before presenting.
VkSemaphoreCreateInfo semaphoreCreateInfo = {
/*sType*/ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
/*pNext*/ nullptr,
@@ -1331,7 +1406,7 @@ Error VulkanContext::_create_semaphores() {
};
// Create fences that we can use to throttle if we get too far
- // ahead of the image presents
+ // ahead of the image presents.
VkFenceCreateInfo fence_ci = {
/*sType*/ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
/*pNext*/ nullptr,
@@ -1351,7 +1426,7 @@ Error VulkanContext::_create_semaphores() {
}
frame_index = 0;
- // Get Memory information and properties
+ // Get Memory information and properties.
vkGetPhysicalDeviceMemoryProperties(gpu, &memory_properties);
return OK;
@@ -1426,7 +1501,7 @@ bool VulkanContext::window_is_valid_swapchain(DisplayServer::WindowID p_window)
VkRenderPass VulkanContext::window_get_render_pass(DisplayServer::WindowID p_window) {
ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE);
Window *w = &windows[p_window];
- //vulkan use of currentbuffer
+ // Vulkan use of currentbuffer.
return w->render_pass;
}
@@ -1434,7 +1509,7 @@ VkFramebuffer VulkanContext::window_get_framebuffer(DisplayServer::WindowID p_wi
ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE);
ERR_FAIL_COND_V(!buffers_prepared, VK_NULL_HANDLE);
Window *w = &windows[p_window];
- //vulkan use of currentbuffer
+ // Vulkan use of currentbuffer.
if (w->swapchain_image_resources != VK_NULL_HANDLE) {
return w->swapchain_image_resources[w->current_buffer].framebuffer;
} else {
@@ -1459,7 +1534,7 @@ Error VulkanContext::_clean_up_swap_chain(Window *window) {
}
vkDeviceWaitIdle(device);
- //this destroys images associated it seems
+ // This destroys images associated it seems.
fpDestroySwapchainKHR(device, window->swapchain, nullptr);
window->swapchain = VK_NULL_HANDLE;
vkDestroyRenderPass(device, window->render_pass, nullptr);
@@ -1485,7 +1560,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
_clean_up_swap_chain(window);
}
- // Check the surface capabilities and formats
+ // Check the surface capabilities and formats.
VkSurfaceCapabilitiesKHR surfCapabilities;
err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, window->surface, &surfCapabilities);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
@@ -1502,7 +1577,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
}
VkExtent2D swapchainExtent;
- // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
+ // Width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) {
// If the surface size is undefined, the size is set to the size
// of the images requested, which must fit within the minimum and
@@ -1522,7 +1597,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
swapchainExtent.height = surfCapabilities.maxImageExtent.height;
}
} else {
- // If the surface size is defined, the swap chain size must match
+ // If the surface size is defined, the swap chain size must match.
swapchainExtent = surfCapabilities.currentExtent;
window->width = surfCapabilities.currentExtent.width;
window->height = surfCapabilities.currentExtent.height;
@@ -1530,7 +1605,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
if (window->width == 0 || window->height == 0) {
free(presentModes);
- //likely window minimized, no swapchain created
+ // Likely window minimized, no swapchain created.
return OK;
}
// The FIFO present mode is guaranteed by the spec to be supported
@@ -1591,8 +1666,23 @@ Error VulkanContext::_update_swap_chain(Window *window) {
if (present_mode_available) {
window->presentMode = requested_present_mode;
} else {
- WARN_PRINT("Requested VSync mode is not available!");
- window->vsync_mode = DisplayServer::VSYNC_ENABLED; //Set to default
+ String present_mode_string;
+ switch (window->vsync_mode) {
+ case DisplayServer::VSYNC_MAILBOX:
+ present_mode_string = "Mailbox";
+ break;
+ case DisplayServer::VSYNC_ADAPTIVE:
+ present_mode_string = "Adaptive";
+ break;
+ case DisplayServer::VSYNC_ENABLED:
+ present_mode_string = "Enabled";
+ break;
+ case DisplayServer::VSYNC_DISABLED:
+ present_mode_string = "Disabled";
+ break;
+ }
+ WARN_PRINT(vformat("The requested V-Sync mode %s is not available. Falling back to V-Sync mode Enabled.", present_mode_string));
+ window->vsync_mode = DisplayServer::VSYNC_ENABLED; // Set to default.
}
print_verbose("Using present mode: " + String(string_VkPresentModeKHR(window->presentMode)));
@@ -1601,13 +1691,13 @@ Error VulkanContext::_update_swap_chain(Window *window) {
// Determine the number of VkImages to use in the swap chain.
// Application desires to acquire 3 images at a time for triple
- // buffering
+ // buffering.
uint32_t desiredNumOfSwapchainImages = 3;
if (desiredNumOfSwapchainImages < surfCapabilities.minImageCount) {
desiredNumOfSwapchainImages = surfCapabilities.minImageCount;
}
// If maxImageCount is 0, we can ask for as many images as we want;
- // otherwise we're limited to maxImageCount
+ // otherwise we're limited to maxImageCount.
if ((surfCapabilities.maxImageCount > 0) && (desiredNumOfSwapchainImages > surfCapabilities.maxImageCount)) {
// Application must settle for fewer images than desired:
desiredNumOfSwapchainImages = surfCapabilities.maxImageCount;
@@ -1620,7 +1710,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
preTransform = surfCapabilities.currentTransform;
}
- // Find a supported composite alpha mode - one of these is guaranteed to be set
+ // Find a supported composite alpha mode - one of these is guaranteed to be set.
VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[4] = {
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
@@ -1667,7 +1757,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
if (swapchainImageCount == 0) {
- //assign here for the first time.
+ // Assign here for the first time.
swapchainImageCount = sp_image_count;
} else {
ERR_FAIL_COND_V(swapchainImageCount != sp_image_count, ERR_BUG);
@@ -1725,7 +1815,9 @@ Error VulkanContext::_update_swap_chain(Window *window) {
/******** FRAMEBUFFER ************/
{
- const VkAttachmentDescription attachment = {
+ const VkAttachmentDescription2KHR attachment = {
+ /*sType*/ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR,
+ /*pNext*/ nullptr,
/*flags*/ 0,
/*format*/ format,
/*samples*/ VK_SAMPLE_COUNT_1_BIT,
@@ -1737,14 +1829,20 @@ Error VulkanContext::_update_swap_chain(Window *window) {
/*finalLayout*/ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
};
- const VkAttachmentReference color_reference = {
+ const VkAttachmentReference2KHR color_reference = {
+ /*sType*/ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR,
+ /*pNext*/ nullptr,
/*attachment*/ 0,
/*layout*/ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ /*aspectMask*/ 0,
};
- const VkSubpassDescription subpass = {
+ const VkSubpassDescription2KHR subpass = {
+ /*sType*/ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR,
+ /*pNext*/ nullptr,
/*flags*/ 0,
/*pipelineBindPoint*/ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ /*viewMask*/ 0,
/*inputAttachmentCount*/ 0,
/*pInputAttachments*/ nullptr,
/*colorAttachmentCount*/ 1,
@@ -1754,8 +1852,9 @@ Error VulkanContext::_update_swap_chain(Window *window) {
/*preserveAttachmentCount*/ 0,
/*pPreserveAttachments*/ nullptr,
};
- const VkRenderPassCreateInfo rp_info = {
- /*sTyp*/ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+
+ const VkRenderPassCreateInfo2KHR rp_info = {
+ /*sType*/ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR,
/*pNext*/ nullptr,
/*flags*/ 0,
/*attachmentCount*/ 1,
@@ -1764,9 +1863,11 @@ Error VulkanContext::_update_swap_chain(Window *window) {
/*pSubpasses*/ &subpass,
/*dependencyCount*/ 0,
/*pDependencies*/ nullptr,
+ /*correlatedViewMaskCount*/ 0,
+ /*pCorrelatedViewMasks*/ nullptr,
};
- err = vkCreateRenderPass(device, &rp_info, nullptr, &window->render_pass);
+ err = vkCreateRenderPass2KHR(device, &rp_info, nullptr, &window->render_pass);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
for (uint32_t i = 0; i < swapchainImageCount; i++) {
@@ -1839,7 +1940,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
}
}
- //reset current buffer
+ // Reset current buffer.
window->current_buffer = 0;
return OK;
@@ -1874,16 +1975,16 @@ void VulkanContext::append_command_buffer(VkCommandBuffer p_command_buffer) {
}
void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) {
- // ensure everything else pending is executed
+ // Ensure everything else pending is executed.
vkDeviceWaitIdle(device);
- //flush the pending setup buffer
+ // Flush the pending setup buffer.
bool setup_flushable = p_flush_setup && command_buffer_queue[0];
bool pending_flushable = p_flush_pending && command_buffer_count > 1;
if (setup_flushable) {
- //use a fence to wait for everything done
+ // Use a fence to wait for everything done.
VkSubmitInfo submit_info;
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = nullptr;
@@ -1900,7 +2001,7 @@ void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) {
}
if (pending_flushable) {
- //use a fence to wait for everything done
+ // Use a fence to wait for everything to finish.
VkSubmitInfo submit_info;
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@@ -1928,7 +2029,7 @@ Error VulkanContext::prepare_buffers() {
VkResult err;
- // Ensure no more than FRAME_LAG renderings are outstanding
+ // Ensure no more than FRAME_LAG renderings are outstanding.
vkWaitForFences(device, 1, &fences[frame_index], VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &fences[frame_index]);
@@ -1948,13 +2049,13 @@ Error VulkanContext::prepare_buffers() {
w->image_acquired_semaphores[frame_index], VK_NULL_HANDLE, &w->current_buffer);
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
- // swapchain is out of date (e.g. the window was resized) and
+ // Swapchain is out of date (e.g. the window was resized) and
// must be recreated:
print_verbose("Vulkan: Early out of date swapchain, recreating.");
- //resize_notify();
+ // resize_notify();
_update_swap_chain(w);
} else if (err == VK_SUBOPTIMAL_KHR) {
- // swapchain is not as optimal as it could be, but the platform's
+ // Swapchain is not as optimal as it could be, but the platform's
// presentation engine will still present the image correctly.
print_verbose("Vulkan: Early suboptimal swapchain.");
break;
@@ -2001,7 +2102,7 @@ Error VulkanContext::swap_buffers() {
uint32_t commands_to_submit = 0;
if (command_buffer_queue[0] == nullptr) {
- //no setup command, but commands to submit, submit from the first and skip command
+ // No setup command, but commands to submit, submit from the first and skip command.
if (command_buffer_count > 1) {
commands_ptr = command_buffer_queue.ptr() + 1;
commands_to_submit = command_buffer_count - 1;
@@ -2044,7 +2145,7 @@ Error VulkanContext::swap_buffers() {
if (separate_present_queue) {
// If we are using separate queues, change image ownership to the
// present queue before presenting, waiting for the draw complete
- // semaphore and signalling the ownership released semaphore when finished
+ // semaphore and signalling the ownership released semaphore when finished.
VkFence nullFence = VK_NULL_HANDLE;
pipe_stage_flags[0] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
submit_info.waitSemaphoreCount = 1;
@@ -2071,7 +2172,7 @@ Error VulkanContext::swap_buffers() {
}
// If we are using separate queues, we have to wait for image ownership,
- // otherwise wait for draw complete
+ // otherwise wait for draw complete.
VkPresentInfoKHR present = {
/*sType*/ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
/*pNext*/ nullptr,
@@ -2176,12 +2277,12 @@ Error VulkanContext::swap_buffers() {
frame_index %= FRAME_LAG;
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
- // swapchain is out of date (e.g. the window was resized) and
+ // Swapchain is out of date (e.g. the window was resized) and
// must be recreated:
print_verbose("Vulkan: Swapchain is out of date, recreating.");
resize_notify();
} else if (err == VK_SUBOPTIMAL_KHR) {
- // swapchain is not as optimal as it could be, but the platform's
+ // Swapchain is not as optimal as it could be, but the platform's
// presentation engine will still present the image correctly.
print_verbose("Vulkan: Swapchain is suboptimal.");
} else {
@@ -2226,7 +2327,7 @@ VkPhysicalDeviceLimits VulkanContext::get_device_limits() const {
RID VulkanContext::local_device_create() {
LocalDevice ld;
- { //create device
+ { // Create device.
VkResult err;
float queue_priorities[1] = { 0.0 };
VkDeviceQueueCreateInfo queues[2];
@@ -2247,13 +2348,13 @@ RID VulkanContext::local_device_create() {
/*ppEnabledLayerNames */ nullptr,
/*enabledExtensionCount */ enabled_extension_count,
/*ppEnabledExtensionNames */ (const char *const *)extension_names,
- /*pEnabledFeatures */ &physical_device_features, // If specific features are required, pass them in here
+ /*pEnabledFeatures */ &physical_device_features, // If specific features are required, pass them in here.
};
err = vkCreateDevice(gpu, &sdevice, nullptr, &ld.device);
ERR_FAIL_COND_V(err, RID());
}
- { //create graphics queue
+ { // Create graphics queue.
vkGetDeviceQueue(ld.device, graphics_queue_family_index, 0, &ld.queue);
}
@@ -2315,7 +2416,7 @@ void VulkanContext::command_begin_label(VkCommandBuffer p_command_buffer, String
return;
}
- CharString cs = p_label_name.utf8().get_data();
+ CharString cs = p_label_name.utf8();
VkDebugUtilsLabelEXT label;
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
label.pNext = nullptr;
@@ -2331,7 +2432,7 @@ void VulkanContext::command_insert_label(VkCommandBuffer p_command_buffer, Strin
if (!enabled_debug_utils) {
return;
}
- CharString cs = p_label_name.utf8().get_data();
+ CharString cs = p_label_name.utf8();
VkDebugUtilsLabelEXT label;
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
label.pNext = nullptr;
@@ -2385,12 +2486,12 @@ String VulkanContext::get_device_pipeline_cache_uuid() const {
}
DisplayServer::VSyncMode VulkanContext::get_vsync_mode(DisplayServer::WindowID p_window) const {
- ERR_FAIL_COND_V_MSG(!windows.has(p_window), DisplayServer::VSYNC_ENABLED, "Could not get VSync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
+ ERR_FAIL_COND_V_MSG(!windows.has(p_window), DisplayServer::VSYNC_ENABLED, "Could not get V-Sync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
return windows[p_window].vsync_mode;
}
void VulkanContext::set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode) {
- ERR_FAIL_COND_MSG(!windows.has(p_window), "Could not set VSync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
+ ERR_FAIL_COND_MSG(!windows.has(p_window), "Could not set V-Sync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
windows[p_window].vsync_mode = p_mode;
_update_swap_chain(&windows[p_window]);
}
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index e96facfacb..35e7ce7db8 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -69,6 +69,15 @@ public:
uint32_t max_instance_count;
};
+ struct VRSCapabilities {
+ bool pipeline_vrs_supported; // We can specify our fragment rate on a pipeline level
+ bool primitive_vrs_supported; // We can specify our fragment rate on each drawcall
+ bool attachment_vrs_supported; // We can provide a density map attachment on our framebuffer
+
+ Size2i min_texel_size;
+ Size2i max_texel_size;
+ };
+
struct ShaderCapabilities {
bool shader_float16_is_supported;
bool shader_int8_is_supported;
@@ -104,6 +113,7 @@ private:
uint32_t vulkan_patch = 0;
SubgroupCapabilities subgroup_capabilities;
MultiviewCapabilities multiview_capabilities;
+ VRSCapabilities vrs_capabilities;
ShaderCapabilities shader_capabilities;
StorageBufferCapabilities storage_buffer_capabilities;
@@ -206,6 +216,7 @@ private:
PFN_vkQueuePresentKHR fpQueuePresentKHR = nullptr;
PFN_vkGetRefreshCycleDurationGOOGLE fpGetRefreshCycleDurationGOOGLE = nullptr;
PFN_vkGetPastPresentationTimingGOOGLE fpGetPastPresentationTimingGOOGLE = nullptr;
+ PFN_vkCreateRenderPass2KHR fpCreateRenderPass2KHR = nullptr;
VkDebugUtilsMessengerEXT dbg_messenger = VK_NULL_HANDLE;
VkDebugReportCallbackEXT dbg_debug_report = VK_NULL_HANDLE;
@@ -256,12 +267,16 @@ protected:
Error _get_preferred_validation_layers(uint32_t *count, const char *const **names);
public:
+ // Extension calls
+ VkResult vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
+
uint32_t get_vulkan_major() const { return vulkan_major; };
uint32_t get_vulkan_minor() const { return vulkan_minor; };
- SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; };
- MultiviewCapabilities get_multiview_capabilities() const { return multiview_capabilities; };
- ShaderCapabilities get_shader_capabilities() const { return shader_capabilities; };
- StorageBufferCapabilities get_storage_buffer_capabilities() const { return storage_buffer_capabilities; };
+ const SubgroupCapabilities &get_subgroup_capabilities() const { return subgroup_capabilities; };
+ const MultiviewCapabilities &get_multiview_capabilities() const { return multiview_capabilities; };
+ const VRSCapabilities &get_vrs_capabilities() const { return vrs_capabilities; };
+ const ShaderCapabilities &get_shader_capabilities() const { return shader_capabilities; };
+ const StorageBufferCapabilities &get_storage_buffer_capabilities() const { return storage_buffer_capabilities; };
VkDevice get_device();
VkPhysicalDevice get_physical_device();
@@ -315,4 +330,4 @@ public:
virtual ~VulkanContext();
};
-#endif // VULKAN_DEVICE_H
+#endif // VULKAN_CONTEXT_H
diff --git a/drivers/vulkan/vulkan_hooks.h b/drivers/vulkan/vulkan_hooks.h
index 3f244b4d45..dec2042d0d 100644
--- a/drivers/vulkan/vulkan_hooks.h
+++ b/drivers/vulkan/vulkan_hooks.h
@@ -45,4 +45,4 @@ public:
virtual ~VulkanHooks(){};
};
-#endif
+#endif // VULKAN_HOOKS_H
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
index 89ed90e97b..9058077a1f 100644
--- a/drivers/wasapi/audio_driver_wasapi.h
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -120,4 +120,5 @@ public:
};
#endif // WASAPI_ENABLED
+
#endif // AUDIO_DRIVER_WASAPI_H
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index fbb07ddef8..c2835b3347 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -54,33 +54,33 @@ class DirAccessWindows : public DirAccess {
bool _cishidden = false;
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 String get_current_dir(bool p_include_drive = true) const override; ///< return current dir location
- 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 rename(String p_path, String p_new_path);
- virtual Error remove(String p_path);
+ virtual Error rename(String p_path, String p_new_path) override;
+ virtual Error remove(String p_path) 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; };
- uint64_t get_space_left();
+ uint64_t get_space_left() override;
- virtual String get_filesystem_type() const;
+ virtual String get_filesystem_type() const override;
DirAccessWindows();
~DirAccessWindows();
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index 5d67b6ca4f..8629bb936b 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -51,33 +51,33 @@ class FileAccessWindows : public FileAccess {
void _close();
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
+ 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
- virtual String get_path() const; /// returns the path for the current open file
- virtual String get_path_absolute() const; /// returns the absolute path for the current open file
+ virtual String get_path() const override; /// returns the path for the current open file
+ virtual String get_path_absolute() const override; /// returns the absolute path for the current open file
- 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
- virtual uint64_t get_length() const; ///< get size of the file
+ 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; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ 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; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
+ 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; ///< store an array of bytes
- virtual bool file_exists(const String &p_name); ///< return true if a file exists
+ virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
- uint64_t _get_modified_time(const String &p_file);
- virtual uint32_t _get_unix_permissions(const String &p_file);
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
+ uint64_t _get_modified_time(const String &p_file) override;
+ virtual uint32_t _get_unix_permissions(const String &p_file) override;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
FileAccessWindows() {}
virtual ~FileAccessWindows();
diff --git a/drivers/winmidi/midi_driver_winmidi.h b/drivers/winmidi/midi_driver_winmidi.h
index 6572ba0c16..e42f3df4cf 100644
--- a/drivers/winmidi/midi_driver_winmidi.h
+++ b/drivers/winmidi/midi_driver_winmidi.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef WINMIDI_ENABLED
-
#ifndef MIDI_DRIVER_WINMIDI_H
#define MIDI_DRIVER_WINMIDI_H
+#ifdef WINMIDI_ENABLED
+
#include "core/os/midi_driver.h"
#include "core/templates/vector.h"
@@ -57,5 +57,6 @@ public:
virtual ~MIDIDriverWinMidi();
};
-#endif // MIDI_DRIVER_WINMIDI_H
#endif // WINMIDI_ENABLED
+
+#endif // MIDI_DRIVER_WINMIDI_H
diff --git a/drivers/xaudio2/audio_driver_xaudio2.h b/drivers/xaudio2/audio_driver_xaudio2.h
index 9072269a0e..81432ceb8e 100644
--- a/drivers/xaudio2/audio_driver_xaudio2.h
+++ b/drivers/xaudio2/audio_driver_xaudio2.h
@@ -106,4 +106,4 @@ public:
~AudioDriverXAudio2() {}
};
-#endif
+#endif // AUDIO_DRIVER_XAUDIO2_H
diff --git a/editor/SCsub b/editor/SCsub
index a596c7d364..c217f162b4 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -76,7 +76,7 @@ if env["tools"]:
# Editor translations
to_include = (
- "ar,bg,ca,cs,de,el,eo,es_AR,es,fi,fr,gl,he,hu,id,it,ja,ko,lv,ms,nb,nl,pl,pt_BR,pt,ro,ru,sk,th,tr,uk,vi,zh_CN,zh_TW"
+ "ar,bg,ca,cs,de,el,eo,es_AR,es,fi,fr,gl,he,hu,id,it,ja,ko,lv,ms,nb,nl,pl,pt_BR,pt,ro,ru,sk,sv,th,tr,uk,vi,zh_CN,zh_TW"
).split(",")
tlist = [env.Dir("#editor/translations").abspath + "/" + f + ".po" for f in to_include]
env.Depends("#editor/editor_translations.gen.h", tlist)
@@ -113,6 +113,7 @@ if env["tools"]:
env.add_source_files(env.editor_sources, "register_exporters.gen.cpp")
SConscript("debugger/SCsub")
+ SConscript("export/SCsub")
SConscript("fileserver/SCsub")
SConscript("icons/SCsub")
SConscript("import/SCsub")
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 698390a61e..462f314471 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -720,7 +720,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
for (int i = 0; i < MOD_MAX; i++) {
String name = mods[i];
mod_checkboxes[i] = memnew(CheckBox);
- mod_checkboxes[i]->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_mod_toggled), varray(i));
+ mod_checkboxes[i]->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_mod_toggled).bind(i));
mod_checkboxes[i]->set_text(name);
mod_container->add_child(mod_checkboxes[i]);
}
@@ -1199,7 +1199,7 @@ void ActionMapEditor::use_external_search_box(LineEdit *p_searchbox) {
ActionMapEditor::ActionMapEditor() {
// Main Vbox Container
VBoxContainer *main_vbox = memnew(VBoxContainer);
- main_vbox->set_anchors_and_offsets_preset(PRESET_WIDE);
+ main_vbox->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
add_child(main_vbox);
HBoxContainer *top_hbox = memnew(HBoxContainer);
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index d8c40a97a7..1ca3c5bac0 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -209,4 +209,4 @@ public:
ActionMapEditor();
};
-#endif
+#endif // ACTION_MAP_EDITOR_H
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 391cd009f1..ab9afda803 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -654,9 +654,9 @@ void AnimationBezierTrackEdit::set_timeline(AnimationTimelineEdit *p_timeline) {
void AnimationBezierTrackEdit::set_editor(AnimationTrackEditor *p_editor) {
editor = p_editor;
- connect("clear_selection", Callable(editor, "_clear_selection"), varray(false));
- connect("select_key", Callable(editor, "_key_selected"), varray(), CONNECT_DEFERRED);
- connect("deselect_key", Callable(editor, "_key_deselected"), varray(), CONNECT_DEFERRED);
+ connect("clear_selection", Callable(editor, "_clear_selection").bind(false));
+ connect("select_key", Callable(editor, "_key_selected"), CONNECT_DEFERRED);
+ connect("deselect_key", Callable(editor, "_key_deselected"), CONNECT_DEFERRED);
}
void AnimationBezierTrackEdit::_play_position_draw() {
@@ -1593,7 +1593,7 @@ AnimationBezierTrackEdit::AnimationBezierTrackEdit() {
play_position = memnew(Control);
play_position->set_mouse_filter(MOUSE_FILTER_PASS);
add_child(play_position);
- play_position->set_anchors_and_offsets_preset(PRESET_WIDE);
+ play_position->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
play_position->connect("draw", callable_mp(this, &AnimationBezierTrackEdit::_play_position_draw));
set_focus_mode(FOCUS_CLICK);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index e612130041..83047caf98 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_scale.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "scene/animation/animation_player.h"
+#include "scene/gui/separator.h"
#include "scene/gui/view_panner.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
@@ -1577,10 +1578,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 +1629,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;
}
}
}
@@ -1890,7 +1891,7 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
play_position = memnew(Control);
play_position->set_mouse_filter(MOUSE_FILTER_PASS);
add_child(play_position);
- play_position->set_anchors_and_offsets_preset(PRESET_WIDE);
+ play_position->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
play_position->connect("draw", callable_mp(this, &AnimationTimelineEdit::_play_position_draw));
add_track = memnew(MenuButton);
@@ -2919,7 +2920,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
add_child(path_popup);
path = memnew(LineEdit);
path_popup->add_child(path);
- path->set_anchors_and_offsets_preset(PRESET_WIDE);
+ path->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
path->connect("text_submitted", callable_mp(this, &AnimationTrackEdit::_path_submitted));
}
@@ -3212,7 +3213,7 @@ AnimationTrackEdit::AnimationTrackEdit() {
play_position = memnew(Control);
play_position->set_mouse_filter(MOUSE_FILTER_PASS);
add_child(play_position);
- play_position->set_anchors_and_offsets_preset(PRESET_WIDE);
+ play_position->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
play_position->connect("draw", callable_mp(this, &AnimationTrackEdit::_play_position_draw));
set_focus_mode(FOCUS_CLICK);
set_mouse_filter(MOUSE_FILTER_PASS); // Scroll has to work too for selection.
@@ -3428,7 +3429,7 @@ void AnimationTrackEditor::set_root(Node *p_root) {
root = p_root;
if (root) {
- root->connect("tree_exiting", callable_mp(this, &AnimationTrackEditor::_root_removed), make_binds(), CONNECT_ONESHOT);
+ root->connect("tree_exiting", callable_mp(this, &AnimationTrackEditor::_root_removed), CONNECT_ONESHOT);
}
_update_tracks();
@@ -3696,7 +3697,7 @@ void AnimationTrackEditor::commit_insert_queue() {
insert_confirm_bezier->set_visible(all_bezier);
insert_confirm_reset->set_visible(reset_allowed);
- insert_confirm->get_ok_button()->set_text(TTR("Create"));
+ insert_confirm->set_ok_button_text(TTR("Create"));
insert_confirm->popup_centered();
} else {
_insert_track(reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), all_bezier && EDITOR_GET("editors/animation/default_create_bezier_tracks"));
@@ -3725,11 +3726,11 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
}
}
-void AnimationTrackEditor::_insert_track(bool p_create_reset, bool p_create_beziers) {
+void AnimationTrackEditor::_insert_track(bool p_reset_wanted, bool p_create_beziers) {
undo_redo->create_action(TTR("Anim Insert"));
Ref<Animation> reset_anim;
- if (p_create_reset) {
+ if (p_reset_wanted) {
reset_anim = _create_and_get_reset_animation();
}
@@ -3739,26 +3740,14 @@ void AnimationTrackEditor::_insert_track(bool p_create_reset, bool p_create_bezi
if (insert_data.front()->get().advance) {
advance = true;
}
- next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, p_create_reset, reset_anim, p_create_beziers);
+ next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, p_reset_wanted, reset_anim, p_create_beziers);
insert_data.pop_front();
}
undo_redo->commit_action();
if (advance) {
- float step = animation->get_step();
- if (step == 0) {
- step = 1;
- }
-
- float pos = timeline->get_play_position();
-
- pos = Math::snapped(pos + step, step);
- if (pos > animation->get_length()) {
- pos = animation->get_length();
- }
- set_anim_pos(pos);
- emit_signal(SNAME("timeline_changed"), pos, true, false);
+ _edit_menu_pressed(EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY);
}
}
@@ -4086,12 +4075,20 @@ void AnimationTrackEditor::_confirm_insert_list() {
}
TrackIndices next_tracks(animation.ptr(), reset_anim.ptr());
+ bool advance = false;
while (insert_data.size()) {
+ if (insert_data.front()->get().advance) {
+ advance = true;
+ }
next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, create_reset, reset_anim, insert_confirm_bezier->is_pressed());
insert_data.pop_front();
}
undo_redo->commit_action();
+
+ if (advance) {
+ _edit_menu_pressed(EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY);
+ }
}
PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val) {
@@ -4207,9 +4204,42 @@ static Vector<String> _get_bezier_subindices_for_type(Variant::Type p_type, bool
return subindices;
}
-AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, Ref<Animation> p_reset_anim, bool p_create_beziers) {
+AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_reset_wanted, Ref<Animation> p_reset_anim, bool p_create_beziers) {
bool created = false;
- if (p_id.track_idx < 0) {
+
+ bool create_normal_track = p_id.track_idx < 0;
+ bool create_reset_track = p_reset_wanted && track_type_is_resettable(p_id.type);
+
+ Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE;
+ if (create_normal_track || create_reset_track) {
+ if (p_id.type == Animation::TYPE_VALUE || p_id.type == Animation::TYPE_BEZIER) {
+ // Hack.
+ NodePath np;
+ animation->add_track(p_id.type);
+ animation->track_set_path(animation->get_track_count() - 1, p_id.path);
+ PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
+ animation->remove_track(animation->get_track_count() - 1); // Hack.
+
+ if (h.type == Variant::FLOAT ||
+ h.type == Variant::VECTOR2 ||
+ h.type == Variant::RECT2 ||
+ h.type == Variant::VECTOR3 ||
+ h.type == Variant::AABB ||
+ h.type == Variant::QUATERNION ||
+ h.type == Variant::COLOR ||
+ h.type == Variant::PLANE ||
+ h.type == Variant::TRANSFORM2D ||
+ h.type == Variant::TRANSFORM3D) {
+ update_mode = Animation::UPDATE_CONTINUOUS;
+ }
+
+ if (h.usage & PROPERTY_USAGE_ANIMATE_AS_TRIGGER) {
+ update_mode = Animation::UPDATE_TRIGGER;
+ }
+ }
+ }
+
+ if (create_normal_track) {
if (p_create_beziers) {
bool valid;
Vector<String> subindices = _get_bezier_subindices_for_type(p_id.value.get_type(), &valid);
@@ -4219,7 +4249,7 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
id.type = Animation::TYPE_BEZIER;
id.value = p_id.value.get(subindices[i].substr(1, subindices[i].length()));
id.path = String(p_id.path) + subindices[i];
- p_next_tracks = _confirm_insert(id, p_next_tracks, p_create_reset, p_reset_anim, false);
+ p_next_tracks = _confirm_insert(id, p_next_tracks, p_reset_wanted, p_reset_anim, false);
}
return p_next_tracks;
@@ -4227,37 +4257,6 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
}
created = true;
undo_redo->create_action(TTR("Anim Insert Track & Key"));
- Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE;
-
- if (p_id.type == Animation::TYPE_VALUE || p_id.type == Animation::TYPE_BEZIER) {
- // Wants a new track.
-
- {
- // Hack.
- NodePath np;
- animation->add_track(p_id.type);
- animation->track_set_path(animation->get_track_count() - 1, p_id.path);
- PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
- animation->remove_track(animation->get_track_count() - 1); // Hack.
-
- if (h.type == Variant::FLOAT ||
- h.type == Variant::VECTOR2 ||
- h.type == Variant::RECT2 ||
- h.type == Variant::VECTOR3 ||
- h.type == Variant::AABB ||
- h.type == Variant::QUATERNION ||
- h.type == Variant::COLOR ||
- h.type == Variant::PLANE ||
- h.type == Variant::TRANSFORM2D ||
- h.type == Variant::TRANSFORM3D) {
- update_mode = Animation::UPDATE_CONTINUOUS;
- }
-
- if (h.usage & PROPERTY_USAGE_ANIMATE_AS_TRIGGER) {
- update_mode = Animation::UPDATE_TRIGGER;
- }
- }
- }
p_id.track_idx = p_next_tracks.normal;
@@ -4320,8 +4319,7 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
}
}
- if (p_create_reset && track_type_is_resettable(p_id.type)) {
- bool create_reset_track = true;
+ if (create_reset_track) {
Animation *reset_anim = p_reset_anim.ptr();
for (int i = 0; i < reset_anim->get_track_count(); i++) {
if (reset_anim->track_get_path(i) == p_id.path) {
@@ -4332,6 +4330,9 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
if (create_reset_track) {
undo_redo->add_do_method(reset_anim, "add_track", p_id.type);
undo_redo->add_do_method(reset_anim, "track_set_path", p_next_tracks.reset, p_id.path);
+ if (p_id.type == Animation::TYPE_VALUE) {
+ undo_redo->add_do_method(reset_anim, "value_track_set_update_mode", p_next_tracks.reset, update_mode);
+ }
undo_redo->add_do_method(reset_anim, "track_insert_key", p_next_tracks.reset, 0.0f, value);
undo_redo->add_undo_method(reset_anim, "remove_track", reset_anim->get_track_count());
p_next_tracks.reset++;
@@ -4514,20 +4515,20 @@ void AnimationTrackEditor::_update_tracks() {
}
track_edit->connect("timeline_changed", callable_mp(this, &AnimationTrackEditor::_timeline_changed));
- track_edit->connect("remove_request", callable_mp(this, &AnimationTrackEditor::_track_remove_request), varray(), CONNECT_DEFERRED);
- track_edit->connect("dropped", callable_mp(this, &AnimationTrackEditor::_dropped_track), varray(), CONNECT_DEFERRED);
- track_edit->connect("insert_key", callable_mp(this, &AnimationTrackEditor::_insert_key_from_track), varray(i), CONNECT_DEFERRED);
- track_edit->connect("select_key", callable_mp(this, &AnimationTrackEditor::_key_selected), varray(i), CONNECT_DEFERRED);
- track_edit->connect("deselect_key", callable_mp(this, &AnimationTrackEditor::_key_deselected), varray(i), CONNECT_DEFERRED);
+ track_edit->connect("remove_request", callable_mp(this, &AnimationTrackEditor::_track_remove_request), CONNECT_DEFERRED);
+ track_edit->connect("dropped", callable_mp(this, &AnimationTrackEditor::_dropped_track), CONNECT_DEFERRED);
+ track_edit->connect("insert_key", callable_mp(this, &AnimationTrackEditor::_insert_key_from_track).bind(i), CONNECT_DEFERRED);
+ track_edit->connect("select_key", callable_mp(this, &AnimationTrackEditor::_key_selected).bind(i), CONNECT_DEFERRED);
+ track_edit->connect("deselect_key", callable_mp(this, &AnimationTrackEditor::_key_deselected).bind(i), CONNECT_DEFERRED);
track_edit->connect("move_selection_begin", callable_mp(this, &AnimationTrackEditor::_move_selection_begin));
track_edit->connect("move_selection", callable_mp(this, &AnimationTrackEditor::_move_selection));
track_edit->connect("move_selection_commit", callable_mp(this, &AnimationTrackEditor::_move_selection_commit));
track_edit->connect("move_selection_cancel", callable_mp(this, &AnimationTrackEditor::_move_selection_cancel));
- track_edit->connect("duplicate_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_DUPLICATE_SELECTION), CONNECT_DEFERRED);
- track_edit->connect("duplicate_transpose_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_DUPLICATE_TRANSPOSED), CONNECT_DEFERRED);
- track_edit->connect("create_reset_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_ADD_RESET_KEY), CONNECT_DEFERRED);
- track_edit->connect("delete_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_DELETE_SELECTION), CONNECT_DEFERRED);
+ track_edit->connect("duplicate_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_DUPLICATE_SELECTION), CONNECT_DEFERRED);
+ track_edit->connect("duplicate_transpose_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_DUPLICATE_TRANSPOSED), CONNECT_DEFERRED);
+ track_edit->connect("create_reset_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_ADD_RESET_KEY), CONNECT_DEFERRED);
+ track_edit->connect("delete_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_DELETE_SELECTION), CONNECT_DEFERRED);
}
}
@@ -5593,7 +5594,7 @@ void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) {
emit_signal(SNAME("timeline_changed"), pos, true, false);
}
-void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) {
+void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event, bool p_timeline_only) {
if (animation.is_null()) {
return;
}
@@ -5617,7 +5618,7 @@ void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) {
}
set_anim_pos(pos);
- emit_signal(SNAME("timeline_changed"), pos, true, false);
+ emit_signal(SNAME("timeline_changed"), pos, true, p_timeline_only);
}
void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
@@ -5965,8 +5966,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
_update_key_edit();
}
} break;
+ case EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY:
case EDIT_GOTO_NEXT_STEP: {
- goto_next_step(false);
+ goto_next_step(false, p_option == EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY);
} break;
case EDIT_GOTO_PREV_STEP: {
goto_prev_step(false);
@@ -6109,7 +6111,8 @@ float AnimationTrackEditor::snap_time(float p_value, bool p_relative) {
void AnimationTrackEditor::_show_imported_anim_warning() {
// It looks terrible on a single line but the TTR extractor doesn't support line breaks yet.
- EditorNode::get_singleton()->show_warning(TTR("This animation belongs to an imported scene, so changes to imported tracks will not be saved.\n\nTo enable the ability to add custom tracks, navigate to the scene's import settings and set\n\"Animation > Storage\" to \"Files\", enable \"Animation > Keep Custom Tracks\", then re-import.\nAlternatively, use an import preset that imports animations to separate files."),
+ EditorNode::get_singleton()->show_warning(
+ TTR("This animation belongs to an imported scene, so changes to imported tracks will not be saved.\n\nTo modify this animation, navigate to the scene's Advanced Import settings and select the animation.\nSome options, including looping, are available here. To add custom tracks, enable \"Save To File\" and\n\"Keep Custom Tracks\"."),
TTR("Warning: Editing imported animation"));
}
@@ -6241,7 +6244,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
info_message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
info_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ info_message->set_anchors_and_offsets_preset(PRESET_FULL_RECT, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
main_panel->add_child(info_message);
timeline = memnew(AnimationTimelineEdit);
@@ -6295,6 +6298,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
imported_anim_warning = memnew(Button);
imported_anim_warning->hide();
+ imported_anim_warning->set_text(TTR("Imported Scene"));
imported_anim_warning->set_tooltip(TTR("Warning: Editing imported animation"));
imported_anim_warning->connect("pressed", callable_mp(this, &AnimationTrackEditor::_show_imported_anim_warning));
bottom_hb->add_child(imported_anim_warning);
@@ -6473,8 +6477,8 @@ AnimationTrackEditor::AnimationTrackEditor() {
optimize_max_angle->set_step(0.1);
optimize_max_angle->set_value(22);
- optimize_dialog->get_ok_button()->set_text(TTR("Optimize"));
- optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_OPTIMIZE_ANIMATION_CONFIRM));
+ optimize_dialog->set_ok_button_text(TTR("Optimize"));
+ optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_OPTIMIZE_ANIMATION_CONFIRM));
//
@@ -6498,9 +6502,9 @@ AnimationTrackEditor::AnimationTrackEditor() {
cleanup_vb->add_child(cleanup_all);
cleanup_dialog->set_title(TTR("Clean-Up Animation(s) (NO UNDO!)"));
- cleanup_dialog->get_ok_button()->set_text(TTR("Clean-Up"));
+ cleanup_dialog->set_ok_button_text(TTR("Clean-Up"));
- cleanup_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_CLEAN_UP_ANIMATION_CONFIRM));
+ cleanup_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_CLEAN_UP_ANIMATION_CONFIRM));
//
scale_dialog = memnew(ConfirmationDialog);
@@ -6512,13 +6516,13 @@ AnimationTrackEditor::AnimationTrackEditor() {
scale->set_max(99999);
scale->set_step(0.001);
vbc->add_margin_child(TTR("Scale Ratio:"), scale);
- scale_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_SCALE_CONFIRM));
+ scale_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_SCALE_CONFIRM));
add_child(scale_dialog);
track_copy_dialog = memnew(ConfirmationDialog);
add_child(track_copy_dialog);
track_copy_dialog->set_title(TTR("Select Tracks to Copy"));
- track_copy_dialog->get_ok_button()->set_text(TTR("Copy"));
+ track_copy_dialog->set_ok_button_text(TTR("Copy"));
VBoxContainer *track_vbox = memnew(VBoxContainer);
track_copy_dialog->add_child(track_vbox);
@@ -6533,7 +6537,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
track_copy_select->set_v_size_flags(SIZE_EXPAND_FILL);
track_copy_select->set_hide_root(true);
track_vbox->add_child(track_copy_select);
- track_copy_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_COPY_TRACKS_CONFIRM));
+ track_copy_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_COPY_TRACKS_CONFIRM));
}
AnimationTrackEditor::~AnimationTrackEditor() {
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 55c3bd922a..cb7d3c7d96 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -33,11 +33,14 @@
#include "editor/editor_data.h"
#include "editor/editor_spin_slider.h"
-#include "editor/property_editor.h"
#include "editor/property_selector.h"
+#include "scene/3d/node_3d.h"
+#include "scene/gui/check_box.h"
#include "scene/gui/control.h"
#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/panel_container.h"
#include "scene/gui/scroll_bar.h"
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
@@ -375,8 +378,8 @@ class AnimationTrackEditor : public VBoxContainer {
reset = p_reset_anim ? p_reset_anim->get_track_count() : 0;
}
};
- TrackIndices _confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, Ref<Animation> p_reset_anim, bool p_create_beziers);
- void _insert_track(bool p_create_reset, bool p_create_beziers);
+ TrackIndices _confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_reset_wanted, Ref<Animation> p_reset_anim, bool p_create_beziers);
+ void _insert_track(bool p_reset_wanted, bool p_create_beziers);
void _root_removed();
@@ -518,6 +521,7 @@ public:
EDIT_ADD_RESET_KEY,
EDIT_DELETE_SELECTION,
EDIT_GOTO_NEXT_STEP,
+ EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY, // Next step without updating animation.
EDIT_GOTO_PREV_STEP,
EDIT_APPLY_RESET,
EDIT_OPTIMIZE_ANIMATION,
@@ -563,7 +567,7 @@ public:
void goto_prev_step(bool p_from_mouse_event);
/** If `p_from_mouse_event` is `true`, handle Shift key presses for precise snapping. */
- void goto_next_step(bool p_from_mouse_event);
+ void goto_next_step(bool p_from_mouse_event, bool p_timeline_only = false);
MenuButton *get_edit_menu();
AnimationTrackEditor();
diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp
index bea95d873e..b9e52ad7ad 100644
--- a/editor/audio_stream_preview.cpp
+++ b/editor/audio_stream_preview.cpp
@@ -153,6 +153,8 @@ void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) {
singleton->call_deferred(SNAME("_update_emit"), preview->id);
}
+ preview->preview->version++;
+
preview->playback->stop();
preview->generating.clear();
@@ -171,7 +173,7 @@ Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref<
Preview *preview = &previews[p_stream->get_instance_id()];
preview->base_stream = p_stream;
- preview->playback = preview->base_stream->instance_playback();
+ preview->playback = preview->base_stream->instantiate_playback();
preview->generating.set();
preview->id = p_stream->get_instance_id();
@@ -198,6 +200,7 @@ Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref<
if (preview->playback.is_valid()) {
preview->thread = memnew(Thread);
+ preview->thread->set_name("AudioStreamPreviewGenerator");
preview->thread->start(_preview_thread, preview);
}
diff --git a/editor/audio_stream_preview.h b/editor/audio_stream_preview.h
index 307dd93b34..0e3c8f70d2 100644
--- a/editor/audio_stream_preview.h
+++ b/editor/audio_stream_preview.h
@@ -43,8 +43,10 @@ class AudioStreamPreview : public RefCounted {
float length;
friend class AudioStreamPreviewGenerator;
+ uint64_t version = 1;
public:
+ uint64_t get_version() const { return version; }
float get_length() const;
float get_max(float p_time, float p_time_next) const;
float get_min(float p_time, float p_time_next) const;
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 272de725c8..b0eb384efc 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -332,7 +332,7 @@ void FindReplaceBar::_update_results_count() {
if (results_count_to_current > results_count) {
results_count_to_current = results_count_to_current - results_count;
- } else if (results_count_to_current == 0) {
+ } else if (results_count_to_current <= 0) {
results_count_to_current = results_count;
}
@@ -824,12 +824,15 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
if (k->is_pressed()) {
if (ED_IS_SHORTCUT("script_editor/zoom_in", p_event)) {
_zoom_in();
+ accept_event();
}
if (ED_IS_SHORTCUT("script_editor/zoom_out", p_event)) {
_zoom_out();
+ accept_event();
}
if (ED_IS_SHORTCUT("script_editor/reset_zoom", p_event)) {
_reset_zoom();
+ accept_event();
}
}
}
@@ -1042,6 +1045,8 @@ void CodeTextEditor::update_editor_settings() {
guideline_cols.append(EditorSettings::get_singleton()->get("text_editor/appearance/guidelines/line_length_guideline_soft_column"));
}
text_editor->set_line_length_guidelines(guideline_cols);
+ } else {
+ text_editor->set_line_length_guidelines(TypedArray<int>());
}
}
@@ -1594,6 +1599,10 @@ void CodeTextEditor::set_error_pos(int p_line, int p_column) {
error_column = p_column;
}
+Point2i CodeTextEditor::get_error_pos() const {
+ return Point2i(error_line, error_column);
+}
+
void CodeTextEditor::goto_error() {
if (!error->get_text().is_empty()) {
if (text_editor->get_line_count() != error_line) {
@@ -1636,30 +1645,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 +1876,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/code_editor.h b/editor/code_editor.h
index e2441cec2b..49679cc700 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -253,13 +253,14 @@ public:
void update_editor_settings();
void set_error(const String &p_error);
void set_error_pos(int p_line, int p_column);
+ Point2i get_error_pos() const;
void update_line_and_column() { _line_col_changed(); }
CodeEdit *get_text_editor() { return text_editor; }
FindReplaceBar *get_find_replace_bar() { return find_replace_bar; }
void set_find_replace_bar(FindReplaceBar *p_bar);
void remove_find_replace_bar();
virtual void apply_code() {}
- void goto_error();
+ virtual void goto_error();
void toggle_bookmark();
void goto_next_bookmark();
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 74fea03fee..6fdd9563fb 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -494,8 +494,8 @@ ConnectDialog::ConnectDialog() {
error = memnew(AcceptDialog);
add_child(error);
error->set_title(TTR("Cannot connect signal"));
- error->get_ok_button()->set_text(TTR("Close"));
- get_ok_button()->set_text(TTR("Connect"));
+ error->set_ok_button_text(TTR("Close"));
+ set_ok_button_text(TTR("Connect"));
}
ConnectDialog::~ConnectDialog() {
@@ -627,7 +627,7 @@ void ConnectionsDock::_connect(ConnectDialog::ConnectionData p_cd) {
Callable callable = p_cd.get_callable();
undo_redo->create_action(vformat(TTR("Connect '%s' to '%s'"), String(p_cd.signal), String(p_cd.method)));
- undo_redo->add_do_method(source, "connect", p_cd.signal, callable, varray(), p_cd.flags);
+ undo_redo->add_do_method(source, "connect", p_cd.signal, callable, p_cd.flags);
undo_redo->add_undo_method(source, "disconnect", p_cd.signal, callable);
undo_redo->add_do_method(this, "update_tree");
undo_redo->add_undo_method(this, "update_tree");
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index dcfde8800a..d141d1a880 100644
--- a/editor/connections_dialog.h
+++ b/editor/connections_dialog.h
@@ -97,7 +97,7 @@ public:
for (int i = 0; i < binds.size(); i++) {
argptrs[i] = &binds[i];
}
- return Callable(target, method).bind(argptrs, binds.size());
+ return Callable(target, method).bindp(argptrs, binds.size());
} else {
return Callable(target, method);
}
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 31c169a0fb..e6168f4924 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -34,6 +34,7 @@
#include "core/os/keyboard.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -57,10 +58,10 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const St
if (p_replace_mode) {
set_title(vformat(TTR("Change %s Type"), base_type));
- get_ok_button()->set_text(TTR("Change"));
+ set_ok_button_text(TTR("Change"));
} else {
set_title(vformat(TTR("Create New %s"), base_type));
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
}
_load_favorites_and_history();
@@ -378,7 +379,7 @@ void CreateDialog::_confirmed() {
}
{
- Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
if (f.is_valid()) {
f->store_line(selected_item);
@@ -655,7 +656,7 @@ void CreateDialog::_save_and_update_favorite_list() {
TreeItem *root = favorites->create_item();
{
- Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
if (f.is_valid()) {
for (int i = 0; i < favorite_list.size(); i++) {
String l = favorite_list[i];
@@ -680,7 +681,7 @@ void CreateDialog::_save_and_update_favorite_list() {
}
void CreateDialog::_load_favorites_and_history() {
- String dir = EditorSettings::get_singleton()->get_project_settings_dir();
+ String dir = EditorPaths::get_singleton()->get_project_settings_dir();
Ref<FileAccess> f = FileAccess::open(dir.plus_file("create_recent." + base_type), FileAccess::READ);
if (f.is_valid()) {
while (!f->eof_reached()) {
diff --git a/editor/create_dialog.h b/editor/create_dialog.h
index dc8618a1c0..04094108ad 100644
--- a/editor/create_dialog.h
+++ b/editor/create_dialog.h
@@ -125,4 +125,4 @@ public:
CreateDialog();
};
-#endif
+#endif // CREATE_DIALOG_H
diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.cpp b/editor/debugger/debug_adapter/debug_adapter_parser.cpp
index 0caeb90108..3c3e4faa6f 100644
--- a/editor/debugger/debug_adapter/debug_adapter_parser.cpp
+++ b/editor/debugger/debug_adapter/debug_adapter_parser.cpp
@@ -34,6 +34,7 @@
#include "editor/debugger/script_editor_debugger.h"
#include "editor/editor_node.h"
#include "editor/editor_run_native.h"
+#include "editor/export/editor_export_platform.h"
#include "editor/plugins/script_editor_plugin.h"
void DebugAdapterParser::_bind_methods() {
diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.h b/editor/debugger/debug_adapter/debug_adapter_parser.h
index f458151e17..ee32306146 100644
--- a/editor/debugger/debug_adapter/debug_adapter_parser.h
+++ b/editor/debugger/debug_adapter/debug_adapter_parser.h
@@ -93,4 +93,4 @@ public:
Dictionary ev_breakpoint(const DAP::Breakpoint &p_breakpoint, const bool &p_enabled) const;
};
-#endif
+#endif // DEBUG_ADAPTER_PARSER_H
diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp
index 92ea0f15e9..4c445eb766 100644
--- a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp
+++ b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp
@@ -37,6 +37,7 @@
#include "editor/doc_tools.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
DebugAdapterProtocol *DebugAdapterProtocol::singleton = nullptr;
diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.h b/editor/debugger/debug_adapter/debug_adapter_protocol.h
index a17e550dfc..29f577ef97 100644
--- a/editor/debugger/debug_adapter/debug_adapter_protocol.h
+++ b/editor/debugger/debug_adapter/debug_adapter_protocol.h
@@ -152,4 +152,4 @@ public:
~DebugAdapterProtocol();
};
-#endif
+#endif // DEBUG_ADAPTER_PROTOCOL_H
diff --git a/editor/debugger/debug_adapter/debug_adapter_server.cpp b/editor/debugger/debug_adapter/debug_adapter_server.cpp
index e9fc7ec913..41e6b1f308 100644
--- a/editor/debugger/debug_adapter/debug_adapter_server.cpp
+++ b/editor/debugger/debug_adapter/debug_adapter_server.cpp
@@ -33,6 +33,7 @@
#include "core/os/os.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
DebugAdapterServer::DebugAdapterServer() {
_EDITOR_DEF("network/debug_adapter/remote_port", remote_port);
diff --git a/editor/debugger/debug_adapter/debug_adapter_server.h b/editor/debugger/debug_adapter/debug_adapter_server.h
index a2b01f92c6..633739eaae 100644
--- a/editor/debugger/debug_adapter/debug_adapter_server.h
+++ b/editor/debugger/debug_adapter/debug_adapter_server.h
@@ -54,4 +54,4 @@ public:
void stop();
};
-#endif
+#endif // DEBUG_ADAPTER_SERVER_H
diff --git a/editor/debugger/debug_adapter/debug_adapter_types.h b/editor/debugger/debug_adapter/debug_adapter_types.h
index fd66905f9b..eb10184ab3 100644
--- a/editor/debugger/debug_adapter/debug_adapter_types.h
+++ b/editor/debugger/debug_adapter/debug_adapter_types.h
@@ -278,4 +278,4 @@ struct Variable {
} // namespace DAP
-#endif
+#endif // DEBUG_ADAPTER_TYPES_H
diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp
index 0e3d424a4b..58206efc20 100644
--- a/editor/debugger/editor_debugger_inspector.cpp
+++ b/editor/debugger/editor_debugger_inspector.cpp
@@ -126,25 +126,25 @@ void EditorDebuggerInspector::_object_selected(ObjectID p_object) {
}
ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) {
- EditorDebuggerRemoteObject *debugObj = nullptr;
+ EditorDebuggerRemoteObject *debug_obj = nullptr;
SceneDebuggerObject obj;
obj.deserialize(p_arr);
ERR_FAIL_COND_V(obj.id.is_null(), ObjectID());
if (remote_objects.has(obj.id)) {
- debugObj = remote_objects[obj.id];
+ debug_obj = remote_objects[obj.id];
} else {
- debugObj = memnew(EditorDebuggerRemoteObject);
- debugObj->remote_object_id = obj.id;
- debugObj->type_name = obj.class_name;
- remote_objects[obj.id] = debugObj;
- debugObj->connect("value_edited", callable_mp(this, &EditorDebuggerInspector::_object_edited));
+ debug_obj = memnew(EditorDebuggerRemoteObject);
+ debug_obj->remote_object_id = obj.id;
+ debug_obj->type_name = obj.class_name;
+ remote_objects[obj.id] = debug_obj;
+ debug_obj->connect("value_edited", callable_mp(this, &EditorDebuggerInspector::_object_edited));
}
- int old_prop_size = debugObj->prop_list.size();
+ int old_prop_size = debug_obj->prop_list.size();
- debugObj->prop_list.clear();
+ debug_obj->prop_list.clear();
int new_props_added = 0;
HashSet<String> changed;
for (int i = 0; i < obj.properties.size(); i++) {
@@ -165,12 +165,14 @@ ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) {
var = ResourceLoader::load(path);
if (pinfo.hint_string == "Script") {
- if (debugObj->get_script() != var) {
- debugObj->set_script(Ref<RefCounted>());
+ if (debug_obj->get_script() != var) {
+ debug_obj->set_script(Ref<RefCounted>());
Ref<Script> script(var);
if (!script.is_null()) {
- ScriptInstance *script_instance = script->placeholder_instance_create(debugObj);
- debugObj->set_script_and_instance(var, script_instance);
+ ScriptInstance *script_instance = script->placeholder_instance_create(debug_obj);
+ if (script_instance) {
+ debug_obj->set_script_and_instance(var, script_instance);
+ }
}
}
}
@@ -178,27 +180,27 @@ ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) {
}
//always add the property, since props may have been added or removed
- debugObj->prop_list.push_back(pinfo);
+ debug_obj->prop_list.push_back(pinfo);
- if (!debugObj->prop_values.has(pinfo.name)) {
+ if (!debug_obj->prop_values.has(pinfo.name)) {
new_props_added++;
- debugObj->prop_values[pinfo.name] = var;
+ debug_obj->prop_values[pinfo.name] = var;
} else {
- if (bool(Variant::evaluate(Variant::OP_NOT_EQUAL, debugObj->prop_values[pinfo.name], var))) {
- debugObj->prop_values[pinfo.name] = var;
+ if (bool(Variant::evaluate(Variant::OP_NOT_EQUAL, debug_obj->prop_values[pinfo.name], var))) {
+ debug_obj->prop_values[pinfo.name] = var;
changed.insert(pinfo.name);
}
}
}
- if (old_prop_size == debugObj->prop_list.size() && new_props_added == 0) {
+ if (old_prop_size == debug_obj->prop_list.size() && new_props_added == 0) {
//only some may have changed, if so, then update those, if exist
for (const String &E : changed) {
- emit_signal(SNAME("object_property_updated"), debugObj->remote_object_id, E);
+ emit_signal(SNAME("object_property_updated"), debug_obj->remote_object_id, E);
}
} else {
//full update, because props were added or removed
- debugObj->update();
+ debug_obj->update();
}
return obj.id;
}
diff --git a/editor/debugger/editor_debugger_inspector.h b/editor/debugger/editor_debugger_inspector.h
index 0e73928558..5aac4dbf11 100644
--- a/editor/debugger/editor_debugger_inspector.h
+++ b/editor/debugger/editor_debugger_inspector.h
@@ -30,6 +30,7 @@
#ifndef EDITOR_DEBUGGER_INSPECTOR_H
#define EDITOR_DEBUGGER_INSPECTOR_H
+
#include "editor/editor_inspector.h"
class EditorDebuggerRemoteObject : public Object {
diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp
index e13af59d69..472e53c0e8 100644
--- a/editor/debugger/editor_debugger_node.cpp
+++ b/editor/debugger/editor_debugger_node.cpp
@@ -92,17 +92,17 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() {
ScriptEditorDebugger *node = memnew(ScriptEditorDebugger);
int id = tabs->get_tab_count();
- node->connect("stop_requested", callable_mp(this, &EditorDebuggerNode::_debugger_wants_stop), varray(id));
- node->connect("stopped", callable_mp(this, &EditorDebuggerNode::_debugger_stopped), varray(id));
- node->connect("stack_frame_selected", callable_mp(this, &EditorDebuggerNode::_stack_frame_selected), varray(id));
- node->connect("error_selected", callable_mp(this, &EditorDebuggerNode::_error_selected), varray(id));
- node->connect("breakpoint_selected", callable_mp(this, &EditorDebuggerNode::_error_selected), varray(id));
+ node->connect("stop_requested", callable_mp(this, &EditorDebuggerNode::_debugger_wants_stop).bind(id));
+ node->connect("stopped", callable_mp(this, &EditorDebuggerNode::_debugger_stopped).bind(id));
+ node->connect("stack_frame_selected", callable_mp(this, &EditorDebuggerNode::_stack_frame_selected).bind(id));
+ node->connect("error_selected", callable_mp(this, &EditorDebuggerNode::_error_selected).bind(id));
+ node->connect("breakpoint_selected", callable_mp(this, &EditorDebuggerNode::_error_selected).bind(id));
node->connect("clear_execution", callable_mp(this, &EditorDebuggerNode::_clear_execution));
- node->connect("breaked", callable_mp(this, &EditorDebuggerNode::_breaked), varray(id));
- node->connect("remote_tree_updated", callable_mp(this, &EditorDebuggerNode::_remote_tree_updated), varray(id));
- node->connect("remote_object_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_updated), varray(id));
- node->connect("remote_object_property_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_property_updated), varray(id));
- node->connect("remote_object_requested", callable_mp(this, &EditorDebuggerNode::_remote_object_requested), varray(id));
+ node->connect("breaked", callable_mp(this, &EditorDebuggerNode::_breaked).bind(id));
+ node->connect("remote_tree_updated", callable_mp(this, &EditorDebuggerNode::_remote_tree_updated).bind(id));
+ node->connect("remote_object_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_updated).bind(id));
+ node->connect("remote_object_property_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_property_updated).bind(id));
+ node->connect("remote_object_requested", callable_mp(this, &EditorDebuggerNode::_remote_object_requested).bind(id));
node->connect("errors_cleared", callable_mp(this, &EditorDebuggerNode::_update_errors));
if (tabs->get_tab_count() > 0) {
diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h
index d50cbec291..4c9ad49ac4 100644
--- a/editor/debugger/editor_debugger_node.h
+++ b/editor/debugger/editor_debugger_node.h
@@ -205,4 +205,5 @@ public:
void add_debugger_plugin(const Ref<Script> &p_script);
void remove_debugger_plugin(const Ref<Script> &p_script);
};
+
#endif // EDITOR_DEBUGGER_NODE_H
diff --git a/editor/debugger/editor_debugger_server.h b/editor/debugger/editor_debugger_server.h
index adf9a27c71..f3805f54d8 100644
--- a/editor/debugger/editor_debugger_server.h
+++ b/editor/debugger/editor_debugger_server.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITOR_DEBUGGER_CONNECTION_H
-#define EDITOR_DEBUGGER_CONNECTION_H
+#ifndef EDITOR_DEBUGGER_SERVER_H
+#define EDITOR_DEBUGGER_SERVER_H
#include "core/debugger/remote_debugger_peer.h"
#include "core/object/ref_counted.h"
@@ -57,4 +57,4 @@ public:
virtual Ref<RemoteDebuggerPeer> take_connection() = 0;
};
-#endif // EDITOR_DEBUGGER_CONNECTION_H
+#endif // EDITOR_DEBUGGER_SERVER_H
diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp
index 023204b74a..dbd2c61d44 100644
--- a/editor/debugger/editor_debugger_tree.cpp
+++ b/editor/debugger/editor_debugger_tree.cpp
@@ -225,6 +225,39 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
updating_scene_tree = false;
}
+Variant EditorDebuggerTree::get_drag_data(const Point2 &p_point) {
+ if (get_button_id_at_position(p_point) != -1) {
+ return Variant();
+ }
+
+ TreeItem *selected = get_selected();
+ if (!selected) {
+ return Variant();
+ }
+
+ String path = selected->get_text(0);
+
+ HBoxContainer *hb = memnew(HBoxContainer);
+ TextureRect *tf = memnew(TextureRect);
+ tf->set_texture(selected->get_icon(0));
+ tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+ hb->add_child(tf);
+ Label *label = memnew(Label(path));
+ hb->add_child(label);
+ set_drag_preview(hb);
+
+ if (!selected->get_parent() || !selected->get_parent()->get_parent()) {
+ path = ".";
+ } else {
+ while (selected->get_parent()->get_parent() != get_root()) {
+ selected = selected->get_parent();
+ path = selected->get_text(0) + "/" + path;
+ }
+ }
+
+ return vformat("\"%s\"", path);
+}
+
String EditorDebuggerTree::get_selected_path() {
if (!get_selected()) {
return "";
@@ -258,7 +291,7 @@ void EditorDebuggerTree::_item_menu_id_pressed(int p_option) {
ResourceSaver::get_recognized_extensions(sd, &extensions);
file_dialog->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file_dialog->add_filter("*." + extensions[i], extensions[i].to_upper());
}
file_dialog->popup_file_dialog();
diff --git a/editor/debugger/editor_debugger_tree.h b/editor/debugger/editor_debugger_tree.h
index bba524039e..5b2df8abd5 100644
--- a/editor/debugger/editor_debugger_tree.h
+++ b/editor/debugger/editor_debugger_tree.h
@@ -65,10 +65,13 @@ protected:
void _notification(int p_what);
public:
+ virtual Variant get_drag_data(const Point2 &p_point) override;
+
String get_selected_path();
ObjectID get_selected_object();
int get_current_debugger(); // Would love to have one tree for every debugger.
void update_scene_tree(const SceneDebuggerTree *p_tree, int p_debugger);
EditorDebuggerTree();
};
+
#endif // EDITOR_DEBUGGER_TREE_H
diff --git a/editor/debugger/editor_network_profiler.h b/editor/debugger/editor_network_profiler.h
index d2e70a083d..aea7ce3eec 100644
--- a/editor/debugger/editor_network_profiler.h
+++ b/editor/debugger/editor_network_profiler.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITORNETWORKPROFILER_H
-#define EDITORNETWORKPROFILER_H
+#ifndef EDITOR_NETWORK_PROFILER_H
+#define EDITOR_NETWORK_PROFILER_H
#include "scene/debugger/scene_debugger.h"
#include "scene/gui/box_container.h"
@@ -69,4 +69,4 @@ public:
EditorNetworkProfiler();
};
-#endif //EDITORNETWORKPROFILER_H
+#endif // EDITOR_NETWORK_PROFILER_H
diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp
index 764e842539..55d025f675 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;
@@ -393,7 +393,7 @@ EditorPerformanceProfiler::EditorPerformanceProfiler() {
info_message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
info_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ info_message->set_anchors_and_offsets_preset(PRESET_FULL_RECT, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
monitor_draw->add_child(info_message);
for (int i = 0; i < Performance::MONITOR_MAX; i++) {
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_profiler.h b/editor/debugger/editor_profiler.h
index cb01a1819f..df92125258 100644
--- a/editor/debugger/editor_profiler.h
+++ b/editor/debugger/editor_profiler.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITORPROFILER_H
-#define EDITORPROFILER_H
+#ifndef EDITOR_PROFILER_H
+#define EDITOR_PROFILER_H
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
@@ -165,4 +165,4 @@ public:
EditorProfiler();
};
-#endif // EDITORPROFILER_H
+#endif // EDITOR_PROFILER_H
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index 9def646f3f..6f3dd1793c 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() {
@@ -796,7 +796,7 @@ EditorVisualProfiler::EditorVisualProfiler() {
frame_delay->set_wait_time(0.1);
frame_delay->set_one_shot(true);
add_child(frame_delay);
- frame_delay->connect("timeout", callable_mp(this, &EditorVisualProfiler::_update_frame), make_binds(false));
+ frame_delay->connect("timeout", callable_mp(this, &EditorVisualProfiler::_update_frame).bind(false));
plot_delay = memnew(Timer);
plot_delay->set_wait_time(0.1);
diff --git a/editor/debugger/editor_visual_profiler.h b/editor/debugger/editor_visual_profiler.h
index 4e5169da9e..8aa9e7b308 100644
--- a/editor/debugger/editor_visual_profiler.h
+++ b/editor/debugger/editor_visual_profiler.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITOR_FRAME_PROFILER_H
-#define EDITOR_FRAME_PROFILER_H
+#ifndef EDITOR_VISUAL_PROFILER_H
+#define EDITOR_VISUAL_PROFILER_H
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
@@ -144,4 +144,4 @@ public:
EditorVisualProfiler();
};
-#endif // EDITOR_FRAME_PROFILER_H
+#endif // EDITOR_VISUAL_PROFILER_H
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index c209c67dcb..ac2e958c5b 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -50,7 +50,6 @@
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "editor/property_editor.h"
#include "main/performance.h"
#include "scene/3d/camera_3d.h"
#include "scene/debugger/scene_debugger.h"
@@ -428,6 +427,9 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
case RemoteDebugger::MESSAGE_TYPE_LOG: {
msg_type = EditorLog::MSG_TYPE_STD;
} break;
+ case RemoteDebugger::MESSAGE_TYPE_LOG_RICH: {
+ msg_type = EditorLog::MSG_TYPE_STD_RICH;
+ } break;
case RemoteDebugger::MESSAGE_TYPE_ERROR: {
msg_type = EditorLog::MSG_TYPE_ERROR;
} break;
@@ -750,7 +752,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
const Variant *args[2] = { &cmd, &data };
Variant retval;
Callable::CallError err;
- c.call(args, 2, retval, err);
+ c.callp(args, 2, retval, err);
ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(c, args, 2, err));
ERR_FAIL_COND_MSG(retval.get_type() != Variant::BOOL, "Error calling 'capture' to callable: " + String(c) + ". Return type is not bool.");
parsed = retval;
@@ -1419,6 +1421,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());
@@ -1427,6 +1433,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;
@@ -1865,7 +1876,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
profiler = memnew(EditorProfiler);
profiler->set_name(TTR("Profiler"));
tabs->add_child(profiler);
- profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate), varray(PROFILER_SCRIPTS_SERVERS));
+ profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_SCRIPTS_SERVERS));
profiler->connect("break_request", callable_mp(this, &ScriptEditorDebugger::_profiler_seeked));
}
@@ -1873,14 +1884,14 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
visual_profiler = memnew(EditorVisualProfiler);
visual_profiler->set_name(TTR("Visual Profiler"));
tabs->add_child(visual_profiler);
- visual_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate), varray(PROFILER_VISUAL));
+ visual_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_VISUAL));
}
{ //network profiler
network_profiler = memnew(EditorNetworkProfiler);
network_profiler->set_name(TTR("Network Profiler"));
tabs->add_child(network_profiler);
- network_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate), varray(PROFILER_NETWORK));
+ network_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_NETWORK));
}
{ //monitors
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 9a1b2b5ff5..43961a7ceb 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/gui/margin_container.h"
void DependencyEditor::_searched(const String &p_path) {
@@ -58,6 +59,9 @@ void DependencyEditor::_load_pressed(Object *p_item, int p_cell, int p_button, M
search->set_title(TTR("Search Replacement For:") + " " + replacing.get_file());
+ // Set directory to closest existing directory.
+ search->set_current_dir(replacing.get_base_dir());
+
search->clear_filters();
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type(ti->get_metadata(0), &ext);
@@ -413,6 +417,45 @@ void DependencyRemoveDialog::_find_all_removed_dependencies(EditorFileSystemDire
}
}
+void DependencyRemoveDialog::_find_localization_remaps_of_removed_files(Vector<RemovedDependency> &p_removed) {
+ for (KeyValue<String, String> &files : all_remove_files) {
+ const String &path = files.key;
+
+ // Look for dependencies in the translation remaps.
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
+ Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
+
+ if (remaps.has(path)) {
+ RemovedDependency dep;
+ dep.file = TTR("Localization remap");
+ dep.file_type = "";
+ dep.dependency = path;
+ dep.dependency_folder = files.value;
+ p_removed.push_back(dep);
+ }
+
+ Array remap_keys = remaps.keys();
+ for (int j = 0; j < remap_keys.size(); j++) {
+ PackedStringArray remapped_files = remaps[remap_keys[j]];
+ for (int k = 0; k < remapped_files.size(); k++) {
+ int splitter_pos = remapped_files[k].rfind(":");
+ String res_path = remapped_files[k].substr(0, splitter_pos);
+ if (res_path == path) {
+ String locale_name = remapped_files[k].substr(splitter_pos + 1);
+
+ RemovedDependency dep;
+ dep.file = vformat(TTR("Localization remap for path '%s' and locale '%s'."), remap_keys[j], locale_name);
+ dep.file_type = "";
+ dep.dependency = path;
+ dep.dependency_folder = files.value;
+ p_removed.push_back(dep);
+ }
+ }
+ }
+ }
+ }
+}
+
void DependencyRemoveDialog::_build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed) {
owners->clear();
owners->create_item(); // root
@@ -469,6 +512,7 @@ void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector<
Vector<RemovedDependency> removed_deps;
_find_all_removed_dependencies(EditorFileSystem::get_singleton()->get_filesystem(), removed_deps);
+ _find_localization_remaps_of_removed_files(removed_deps);
removed_deps.sort();
if (removed_deps.is_empty()) {
owners->hide();
@@ -575,7 +619,7 @@ void DependencyRemoveDialog::_bind_methods() {
}
DependencyRemoveDialog::DependencyRemoveDialog() {
- get_ok_button()->set_text(TTR("Remove"));
+ set_ok_button_text(TTR("Remove"));
VBoxContainer *vb = memnew(VBoxContainer);
add_child(vb);
@@ -641,8 +685,8 @@ DependencyErrorDialog::DependencyErrorDialog() {
files->set_v_size_flags(Control::SIZE_EXPAND_FILL);
set_min_size(Size2(500, 220) * EDSCALE);
- get_ok_button()->set_text(TTR("Open Anyway"));
- get_cancel_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Open Anyway"));
+ set_cancel_button_text(TTR("Close"));
text = memnew(Label);
vb->add_child(text);
@@ -780,7 +824,7 @@ void OrphanResourcesDialog::_bind_methods() {
OrphanResourcesDialog::OrphanResourcesDialog() {
set_title(TTR("Orphan Resource Explorer"));
delete_confirm = memnew(ConfirmationDialog);
- get_ok_button()->set_text(TTR("Delete"));
+ set_ok_button_text(TTR("Delete"));
add_child(delete_confirm);
dep_edit = memnew(DependencyEditor);
add_child(dep_edit);
diff --git a/editor/dependency_editor.h b/editor/dependency_editor.h
index 96d82d58eb..6e39015ec3 100644
--- a/editor/dependency_editor.h
+++ b/editor/dependency_editor.h
@@ -119,6 +119,7 @@ class DependencyRemoveDialog : public ConfirmationDialog {
void _find_files_in_removed_folder(EditorFileSystemDirectory *efsd, const String &p_folder);
void _find_all_removed_dependencies(EditorFileSystemDirectory *efsd, Vector<RemovedDependency> &p_removed);
+ void _find_localization_remaps_of_removed_files(Vector<RemovedDependency> &p_removed);
void _build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed);
void ok_pressed() override;
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index e6cd1e0b48..a819458417 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -39,6 +39,7 @@
#include "core/object/script_language.h"
#include "core/string/translation.h"
#include "core/version.h"
+#include "editor/editor_settings.h"
#include "scene/resources/theme.h"
// Used for a hack preserving Mono properties on non-Mono builds.
@@ -178,6 +179,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];
@@ -349,8 +364,15 @@ void DocTools::generate(bool p_basic_types) {
List<PropertyInfo> properties;
List<PropertyInfo> own_properties;
- if (name == "ProjectSettings") {
- // Special case for project settings, so settings can be documented.
+
+ // Special case for editor and project settings, so they can be documented.
+ if (name == "EditorSettings") {
+ // We don't create the full blown EditorSettings (+ config file) with `create()`,
+ // instead we just make a local instance to get default values.
+ Ref<EditorSettings> edset = memnew(EditorSettings);
+ edset->get_property_list(&properties);
+ own_properties = properties;
+ } else if (name == "ProjectSettings") {
ProjectSettings::get_singleton()->get_property_list(&properties);
own_properties = properties;
} else {
@@ -388,6 +410,13 @@ void DocTools::generate(bool p_basic_types) {
bool default_value_valid = false;
Variant default_value;
+ if (name == "EditorSettings") {
+ if (E.name == "resource_local_to_scene" || E.name == "resource_name" || E.name == "resource_path" || E.name == "script") {
+ // Don't include spurious properties in the generated EditorSettings class reference.
+ continue;
+ }
+ }
+
if (name == "ProjectSettings") {
// Special case for project settings, so that settings are not taken from the current project's settings
if (E.name == "script" || !ProjectSettings::get_singleton()->is_builtin_setting(E.name)) {
@@ -410,8 +439,6 @@ void DocTools::generate(bool p_basic_types) {
}
}
- //used to track uninitialized values using valgrind
- //print_line("getting default value for " + String(name) + "." + String(E.name));
if (default_value_valid && default_value.get_type() != Variant::OBJECT) {
prop.default_value = default_value.get_construct_string().replace("\n", " ");
}
@@ -429,7 +456,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()) {
@@ -484,53 +511,7 @@ void DocTools::generate(bool p_basic_types) {
}
DocData::MethodDoc method;
-
- method.name = E.name;
-
- if (E.flags & METHOD_FLAG_VIRTUAL) {
- method.qualifiers = "virtual";
- }
-
- if (E.flags & METHOD_FLAG_CONST) {
- if (!method.qualifiers.is_empty()) {
- method.qualifiers += " ";
- }
- method.qualifiers += "const";
- }
-
- if (E.flags & METHOD_FLAG_VARARG) {
- if (!method.qualifiers.is_empty()) {
- method.qualifiers += " ";
- }
- method.qualifiers += "vararg";
- }
-
- if (E.flags & METHOD_FLAG_STATIC) {
- if (!method.qualifiers.is_empty()) {
- method.qualifiers += " ";
- }
- method.qualifiers += "static";
- }
-
- for (int i = -1; i < E.arguments.size(); i++) {
- if (i == -1) {
-#ifdef DEBUG_METHODS_ENABLED
- DocData::return_doc_from_retinfo(method, E.return_val);
-#endif
- } else {
- const PropertyInfo &arginfo = E.arguments[i];
- DocData::ArgumentDoc argument;
- DocData::argument_doc_from_arginfo(argument, arginfo);
-
- int darg_idx = i - (E.arguments.size() - E.default_arguments.size());
- if (darg_idx >= 0) {
- Variant default_arg = E.default_arguments[darg_idx];
- argument.default_value = default_arg.get_construct_string().replace("\n", " ");
- }
-
- method.arguments.push_back(argument);
- }
- }
+ DocData::method_doc_from_methodinfo(method, E, "");
Vector<Error> errs = ClassDB::get_method_error_return_values(name, E.name);
if (errs.size()) {
@@ -575,6 +556,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 +941,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 +1177,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 +1262,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 +1445,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 +1467,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/doc_tools.h b/editor/doc_tools.h
index 843cdf87a6..b3e45c6472 100644
--- a/editor/doc_tools.h
+++ b/editor/doc_tools.h
@@ -53,4 +53,4 @@ public:
Error load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size);
};
-#endif // DOC_DATA_H
+#endif // DOC_TOOLS_H
diff --git a/editor/editor_about.h b/editor/editor_about.h
index 6f05700582..971843f6d2 100644
--- a/editor/editor_about.h
+++ b/editor/editor_about.h
@@ -75,4 +75,4 @@ public:
~EditorAbout();
};
-#endif
+#endif // EDITOR_ABOUT_H
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index ef29448854..8dc8a0ab6b 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -100,8 +100,8 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
extension_guess["tga"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
extension_guess["webp"] = tree->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons"));
- extension_guess["wav"] = tree->get_theme_icon(SNAME("AudioStreamSample"), SNAME("EditorIcons"));
- extension_guess["ogg"] = tree->get_theme_icon(SNAME("AudioStreamOGGVorbis"), SNAME("EditorIcons"));
+ extension_guess["wav"] = tree->get_theme_icon(SNAME("AudioStreamWAV"), SNAME("EditorIcons"));
+ extension_guess["ogg"] = tree->get_theme_icon(SNAME("AudioStreamOggVorbis"), SNAME("EditorIcons"));
extension_guess["mp3"] = tree->get_theme_icon(SNAME("AudioStreamMP3"), SNAME("EditorIcons"));
extension_guess["scn"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
@@ -112,6 +112,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
extension_guess["glb"] = tree->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
extension_guess["gdshader"] = tree->get_theme_icon(SNAME("Shader"), SNAME("EditorIcons"));
+ extension_guess["gdshaderinc"] = tree->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
extension_guess["gd"] = tree->get_theme_icon(SNAME("GDScript"), SNAME("EditorIcons"));
if (Engine::get_singleton()->has_singleton("GodotSharp")) {
extension_guess["cs"] = tree->get_theme_icon(SNAME("CSharpScript"), SNAME("EditorIcons"));
@@ -355,7 +356,7 @@ EditorAssetInstaller::EditorAssetInstaller() {
error = memnew(AcceptDialog);
add_child(error);
- get_ok_button()->set_text(TTR("Install"));
+ set_ok_button_text(TTR("Install"));
set_title(TTR("Asset Installer"));
set_hide_on_ok(true);
diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h
index c44f4c5d22..9c88116336 100644
--- a/editor/editor_asset_installer.h
+++ b/editor/editor_asset_installer.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITORASSETINSTALLER_H
-#define EDITORASSETINSTALLER_H
+#ifndef EDITOR_ASSET_INSTALLER_H
+#define EDITOR_ASSET_INSTALLER_H
#include "scene/gui/dialogs.h"
#include "scene/gui/tree.h"
@@ -59,4 +59,4 @@ public:
EditorAssetInstaller();
};
-#endif // EDITORASSETINSTALLER_H
+#endif // EDITOR_ASSET_INSTALLER_H
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 89dc106717..b6d7bbc45f 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "filesystem_dock.h"
#include "scene/resources/font.h"
#include "servers/audio_server.h"
@@ -1007,11 +1008,11 @@ void EditorAudioBuses::_update_buses() {
bool is_master = (i == 0);
EditorAudioBus *audio_bus = memnew(EditorAudioBus(this, is_master));
bus_hb->add_child(audio_bus);
- audio_bus->connect("delete_request", callable_mp(this, &EditorAudioBuses::_delete_bus), varray(audio_bus), CONNECT_DEFERRED);
- audio_bus->connect("duplicate_request", callable_mp(this, &EditorAudioBuses::_duplicate_bus), varray(), CONNECT_DEFERRED);
- audio_bus->connect("vol_reset_request", callable_mp(this, &EditorAudioBuses::_reset_bus_volume), varray(audio_bus), CONNECT_DEFERRED);
+ audio_bus->connect("delete_request", callable_mp(this, &EditorAudioBuses::_delete_bus).bind(audio_bus), CONNECT_DEFERRED);
+ audio_bus->connect("duplicate_request", callable_mp(this, &EditorAudioBuses::_duplicate_bus), CONNECT_DEFERRED);
+ audio_bus->connect("vol_reset_request", callable_mp(this, &EditorAudioBuses::_reset_bus_volume).bind(audio_bus), CONNECT_DEFERRED);
audio_bus->connect("drop_end_request", callable_mp(this, &EditorAudioBuses::_request_drop_end));
- audio_bus->connect("dropped", callable_mp(this, &EditorAudioBuses::_drop_at_index), varray(), CONNECT_DEFERRED);
+ audio_bus->connect("dropped", callable_mp(this, &EditorAudioBuses::_drop_at_index), CONNECT_DEFERRED);
}
}
@@ -1154,7 +1155,7 @@ void EditorAudioBuses::_request_drop_end() {
bus_hb->add_child(drop_end);
drop_end->set_custom_minimum_size(Object::cast_to<Control>(bus_hb->get_child(0))->get_size());
- drop_end->connect("dropped", callable_mp(this, &EditorAudioBuses::_drop_at_index), varray(), CONNECT_DEFERRED);
+ drop_end->connect("dropped", callable_mp(this, &EditorAudioBuses::_drop_at_index), CONNECT_DEFERRED);
}
}
@@ -1174,7 +1175,7 @@ void EditorAudioBuses::_drop_at_index(int p_bus, int p_index) {
void EditorAudioBuses::_server_save() {
Ref<AudioBusLayout> state = AudioServer::get_singleton()->generate_bus_layout();
- ResourceSaver::save(edited_path, state);
+ ResourceSaver::save(state, edited_path);
}
void EditorAudioBuses::_select_layout() {
@@ -1244,7 +1245,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) {
AudioServer::get_singleton()->set_bus_layout(empty_state);
}
- Error err = ResourceSaver::save(p_string, AudioServer::get_singleton()->generate_bus_layout());
+ Error err = ResourceSaver::save(AudioServer::get_singleton()->generate_bus_layout(), p_string);
if (err != OK) {
EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), p_string));
@@ -1332,7 +1333,7 @@ EditorAudioBuses::EditorAudioBuses() {
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type("AudioBusLayout", &ext);
for (const String &E : ext) {
- file_dialog->add_filter(vformat("*.%s; %s", E, TTR("Audio Bus Layout")));
+ file_dialog->add_filter("*." + E, TTR("Audio Bus Layout"));
}
add_child(file_dialog);
file_dialog->connect("file_selected", callable_mp(this, &EditorAudioBuses::_file_dialog_callback));
@@ -1394,7 +1395,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_autoload_settings.h b/editor/editor_autoload_settings.h
index e1e0bb0a64..0eda7016d3 100644
--- a/editor/editor_autoload_settings.h
+++ b/editor/editor_autoload_settings.h
@@ -112,4 +112,4 @@ public:
~EditorAutoloadSettings();
};
-#endif
+#endif // EDITOR_AUTOLOAD_SETTINGS_H
diff --git a/editor/editor_build_profile.cpp b/editor/editor_build_profile.cpp
new file mode 100644
index 0000000000..0f0ab4a339
--- /dev/null
+++ b/editor/editor_build_profile.cpp
@@ -0,0 +1,899 @@
+/*************************************************************************/
+/* editor_build_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 "editor_build_profile.h"
+
+#include "core/io/dir_access.h"
+#include "core/io/json.h"
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_file_system.h"
+#include "editor/editor_node.h"
+#include "editor/editor_property_name_processor.h"
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+
+const char *EditorBuildProfile::build_option_identifiers[BUILD_OPTION_MAX] = {
+ // This maps to SCons build options.
+ "disable_3d",
+ "disable_2d_physics",
+ "disable_3d_physics",
+ "disable_navigation",
+ "openxr",
+ "rendering_device", // FIXME: there's no scons option to disable rendering device
+ "opengl3",
+ "vulkan",
+ "module_text_server_fb_enabled",
+ "module_text_server_adv_enabled",
+ "module_freetype_enabled",
+ "brotli",
+ "graphite",
+ "module_msdfgen_enabled"
+};
+
+const bool EditorBuildProfile::build_option_disabled_by_default[BUILD_OPTION_MAX] = {
+ // This maps to SCons build options.
+ false, // 3D
+ false, // PHYSICS_2D
+ false, // PHYSICS_3D
+ false, // NAVIGATION
+ false, // XR
+ false, // RENDERING_DEVICE
+ false, // OPENGL
+ false, // VULKAN
+ true, // TEXT_SERVER_FALLBACK
+ false, // TEXT_SERVER_COMPLEX
+ false, // DYNAMIC_FONTS
+ false, // WOFF2_FONTS
+ false, // GRPAHITE_FONTS
+ false, // MSDFGEN
+};
+
+const bool EditorBuildProfile::build_option_disable_values[BUILD_OPTION_MAX] = {
+ // This maps to SCons build options.
+ true, // 3D
+ true, // PHYSICS_2D
+ true, // PHYSICS_3D
+ true, // NAVIGATION
+ false, // XR
+ false, // RENDERING_DEVICE
+ false, // OPENGL
+ false, // VULKAN
+ false, // TEXT_SERVER_FALLBACK
+ false, // TEXT_SERVER_COMPLEX
+ false, // DYNAMIC_FONTS
+ false, // WOFF2_FONTS
+ false, // GRPAHITE_FONTS
+ false, // MSDFGEN
+};
+
+const EditorBuildProfile::BuildOptionCategory EditorBuildProfile::build_option_category[BUILD_OPTION_MAX] = {
+ BUILD_OPTION_CATEGORY_GENERAL, // 3D
+ BUILD_OPTION_CATEGORY_GENERAL, // PHYSICS_2D
+ BUILD_OPTION_CATEGORY_GENERAL, // PHYSICS_3D
+ BUILD_OPTION_CATEGORY_GENERAL, // NAVIGATION
+ BUILD_OPTION_CATEGORY_GENERAL, // XR
+ BUILD_OPTION_CATEGORY_GENERAL, // RENDERING_DEVICE
+ BUILD_OPTION_CATEGORY_GENERAL, // OPENGL
+ BUILD_OPTION_CATEGORY_GENERAL, // VULKAN
+ BUILD_OPTION_CATEGORY_TEXT_SERVER, // TEXT_SERVER_FALLBACK
+ BUILD_OPTION_CATEGORY_TEXT_SERVER, // TEXT_SERVER_COMPLEX
+ BUILD_OPTION_CATEGORY_TEXT_SERVER, // DYNAMIC_FONTS
+ BUILD_OPTION_CATEGORY_TEXT_SERVER, // WOFF2_FONTS
+ BUILD_OPTION_CATEGORY_TEXT_SERVER, // GRPAHITE_FONTS
+ BUILD_OPTION_CATEGORY_TEXT_SERVER, // MSDFGEN
+};
+
+void EditorBuildProfile::set_disable_class(const StringName &p_class, bool p_disabled) {
+ if (p_disabled) {
+ disabled_classes.insert(p_class);
+ } else {
+ disabled_classes.erase(p_class);
+ }
+}
+
+bool EditorBuildProfile::is_class_disabled(const StringName &p_class) const {
+ if (p_class == StringName()) {
+ return false;
+ }
+ return disabled_classes.has(p_class) || is_class_disabled(ClassDB::get_parent_class_nocheck(p_class));
+}
+
+void EditorBuildProfile::set_item_collapsed(const StringName &p_class, bool p_collapsed) {
+ if (p_collapsed) {
+ collapsed_classes.insert(p_class);
+ } else {
+ collapsed_classes.erase(p_class);
+ }
+}
+
+bool EditorBuildProfile::is_item_collapsed(const StringName &p_class) const {
+ return collapsed_classes.has(p_class);
+}
+
+void EditorBuildProfile::set_disable_build_option(BuildOption p_build_option, bool p_disable) {
+ ERR_FAIL_INDEX(p_build_option, BUILD_OPTION_MAX);
+ build_options_disabled[p_build_option] = p_disable;
+}
+
+void EditorBuildProfile::clear_disabled_classes() {
+ disabled_classes.clear();
+ collapsed_classes.clear();
+}
+
+bool EditorBuildProfile::is_build_option_disabled(BuildOption p_build_option) const {
+ ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, false);
+ return build_options_disabled[p_build_option];
+}
+
+bool EditorBuildProfile::get_build_option_disable_value(BuildOption p_build_option) {
+ ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, false);
+ return build_option_disable_values[p_build_option];
+}
+
+void EditorBuildProfile::set_force_detect_classes(const String &p_classes) {
+ force_detect_classes = p_classes;
+}
+
+String EditorBuildProfile::get_force_detect_classes() const {
+ return force_detect_classes;
+}
+
+String EditorBuildProfile::get_build_option_name(BuildOption p_build_option) {
+ ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, String());
+ const char *build_option_names[BUILD_OPTION_MAX] = {
+ TTRC("3D Engine"),
+ TTRC("2D Physics"),
+ TTRC("3D Physics"),
+ TTRC("Navigation"),
+ TTRC("XR"),
+ TTRC("RenderingDevice"),
+ TTRC("OpenGL"),
+ TTRC("Vulkan"),
+ TTRC("Text Server: Fallback"),
+ TTRC("Text Server: Advanced"),
+ TTRC("TTF, OTF, Type 1, WOFF1 Fonts"),
+ TTRC("WOFF2 Fonts"),
+ TTRC("SIL Graphite Fonts"),
+ TTRC("Multi-channel Signed Distance Field Font Rendering"),
+ };
+ return TTRGET(build_option_names[p_build_option]);
+}
+
+String EditorBuildProfile::get_build_option_description(BuildOption p_build_option) {
+ ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, String());
+
+ const char *build_option_descriptions[BUILD_OPTION_MAX] = {
+ TTRC("3D Nodes as well as RenderingServer access to 3D features."),
+ TTRC("2D Physics nodes and PhysicsServer2D."),
+ TTRC("3D Physics nodes and PhysicsServer3D."),
+ TTRC("Navigation, both 2D and 3D."),
+ TTRC("XR (AR and VR)."),
+ TTRC("RenderingDevice based rendering (if disabled, the OpenGL back-end is required)."),
+ TTRC("OpenGL back-end (if disabled, the RenderingDevice back-end is required)."),
+ TTRC("Vulkan back-end of RenderingDevice."),
+ TTRC("Fallback implementation of Text Server\nSupports basic text layouts."),
+ TTRC("Text Server implementation powered by ICU and HarfBuzz libraries.\nSupports complex text layouts, BiDi, and contextual OpenType font features."),
+ TTRC("TrueType, OpenType, Type 1, and WOFF1 font format support using FreeType library (if disabled, WOFF2 support is also disabled)."),
+ TTRC("WOFF2 font format support using FreeType and Brotli libraries."),
+ TTRC("SIL Graphite smart font technology support (supported by Advanced Text Server only)."),
+ TTRC("Multi-channel signed distance field font rendering support using msdfgen library (pre-rendered MSDF fonts can be used even if this option disabled)."),
+ };
+
+ return TTRGET(build_option_descriptions[p_build_option]);
+}
+
+EditorBuildProfile::BuildOptionCategory EditorBuildProfile::get_build_option_category(BuildOption p_build_option) {
+ ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, BUILD_OPTION_CATEGORY_GENERAL);
+ return build_option_category[p_build_option];
+}
+
+String EditorBuildProfile::get_build_option_category_name(BuildOptionCategory p_build_option_category) {
+ ERR_FAIL_INDEX_V(p_build_option_category, BUILD_OPTION_CATEGORY_MAX, String());
+
+ const char *build_option_subcategories[BUILD_OPTION_CATEGORY_MAX]{
+ TTRC("General Features:"),
+ TTRC("Text Rendering and Font Options:"),
+ };
+
+ return TTRGET(build_option_subcategories[p_build_option_category]);
+}
+
+Error EditorBuildProfile::save_to_file(const String &p_path) {
+ Dictionary data;
+ data["type"] = "build_profile";
+ Array dis_classes;
+ for (const StringName &E : disabled_classes) {
+ dis_classes.push_back(String(E));
+ }
+ dis_classes.sort();
+ data["disabled_classes"] = dis_classes;
+
+ Dictionary dis_build_options;
+ for (int i = 0; i < BUILD_OPTION_MAX; i++) {
+ if (build_options_disabled[i] != build_option_disabled_by_default[i]) {
+ if (build_options_disabled[i]) {
+ dis_build_options[build_option_identifiers[i]] = build_option_disable_values[i];
+ } else {
+ dis_build_options[build_option_identifiers[i]] = !build_option_disable_values[i];
+ }
+ }
+ }
+
+ data["disabled_build_options"] = dis_build_options;
+
+ if (!force_detect_classes.is_empty()) {
+ data["force_detect_classes"] = force_detect_classes;
+ }
+
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
+
+ JSON json;
+ String text = json.stringify(data, "\t");
+ f->store_string(text);
+ return OK;
+}
+
+Error EditorBuildProfile::load_from_file(const String &p_path) {
+ Error err;
+ String text = FileAccess::get_file_as_string(p_path, &err);
+ if (err != OK) {
+ return err;
+ }
+
+ JSON json;
+ err = json.parse(text);
+ if (err != OK) {
+ ERR_PRINT("Error parsing '" + p_path + "' on line " + itos(json.get_error_line()) + ": " + json.get_error_message());
+ return ERR_PARSE_ERROR;
+ }
+
+ Dictionary data = json.get_data();
+
+ if (!data.has("type") || String(data["type"]) != "build_profile") {
+ ERR_PRINT("Error parsing '" + p_path + "', it's not a build profile.");
+ return ERR_PARSE_ERROR;
+ }
+
+ disabled_classes.clear();
+
+ if (data.has("disabled_classes")) {
+ Array disabled_classes_arr = data["disabled_classes"];
+ for (int i = 0; i < disabled_classes_arr.size(); i++) {
+ disabled_classes.insert(disabled_classes_arr[i]);
+ }
+ }
+
+ for (int i = 0; i < BUILD_OPTION_MAX; i++) {
+ build_options_disabled[i] = build_option_disabled_by_default[i];
+ }
+
+ if (data.has("disabled_build_options")) {
+ Dictionary disabled_build_options_arr = data["disabled_build_options"];
+ List<Variant> keys;
+ disabled_build_options_arr.get_key_list(&keys);
+
+ for (const Variant &K : keys) {
+ String key = K;
+
+ for (int i = 0; i < BUILD_OPTION_MAX; i++) {
+ String f = build_option_identifiers[i];
+ if (f == key) {
+ build_options_disabled[i] = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (data.has("force_detect_classes")) {
+ force_detect_classes = data["force_detect_classes"];
+ }
+
+ return OK;
+}
+
+void EditorBuildProfile::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_disable_class", "class_name", "disable"), &EditorBuildProfile::set_disable_class);
+ ClassDB::bind_method(D_METHOD("is_class_disabled", "class_name"), &EditorBuildProfile::is_class_disabled);
+
+ ClassDB::bind_method(D_METHOD("set_disable_build_option", "build_option", "disable"), &EditorBuildProfile::set_disable_build_option);
+ ClassDB::bind_method(D_METHOD("is_build_option_disabled", "build_option"), &EditorBuildProfile::is_build_option_disabled);
+
+ ClassDB::bind_method(D_METHOD("get_build_option_name", "build_option"), &EditorBuildProfile::_get_build_option_name);
+
+ ClassDB::bind_method(D_METHOD("save_to_file", "path"), &EditorBuildProfile::save_to_file);
+ ClassDB::bind_method(D_METHOD("load_from_file", "path"), &EditorBuildProfile::load_from_file);
+
+ BIND_ENUM_CONSTANT(BUILD_OPTION_3D);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_2D);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_3D);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_NAVIGATION);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_XR);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_RENDERING_DEVICE);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_OPENGL);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_VULKAN);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_TEXT_SERVER_FALLBACK);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_TEXT_SERVER_ADVANCED);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_DYNAMIC_FONTS);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_WOFF2_FONTS);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_GRPAHITE_FONTS);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_MSDFGEN);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_MAX);
+
+ BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_GENERAL);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_TEXT_SERVER);
+ BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_MAX);
+}
+
+EditorBuildProfile::EditorBuildProfile() {
+ for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_MAX; i++) {
+ build_options_disabled[i] = build_option_disabled_by_default[i];
+ }
+}
+
+//////////////////////////
+
+void EditorBuildProfileManager::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ String last_file = EditorSettings::get_singleton()->get_project_metadata("build_profile", "last_file_path", "");
+ if (!last_file.is_empty()) {
+ _import_profile(last_file);
+ }
+ if (edited.is_null()) {
+ edited.instantiate();
+ _update_edited_profile();
+ }
+
+ } break;
+ }
+}
+
+void EditorBuildProfileManager::_profile_action(int p_action) {
+ last_action = Action(p_action);
+
+ switch (p_action) {
+ case ACTION_RESET: {
+ confirm_dialog->set_text("Reset the edited profile?");
+ confirm_dialog->popup_centered();
+ } break;
+ case ACTION_LOAD: {
+ import_profile->popup_file_dialog();
+ } break;
+ case ACTION_SAVE: {
+ if (!profile_path->get_text().is_empty()) {
+ Error err = edited->save_to_file(profile_path->get_text());
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(TTR("File saving failed."));
+ }
+ break;
+ }
+ [[fallthrough]];
+ }
+ case ACTION_SAVE_AS: {
+ export_profile->popup_file_dialog();
+ export_profile->set_current_file(profile_path->get_text());
+ } break;
+ case ACTION_NEW: {
+ confirm_dialog->set_text("Create a new profile?");
+ confirm_dialog->popup_centered();
+ } break;
+ case ACTION_DETECT: {
+ confirm_dialog->set_text("This will scan all files in the current project to detect used classes.");
+ confirm_dialog->popup_centered();
+ } break;
+ case ACTION_MAX: {
+ } break;
+ }
+}
+
+void EditorBuildProfileManager::_find_files(EditorFileSystemDirectory *p_dir, const HashMap<String, DetectedFile> &p_cache, HashMap<String, DetectedFile> &r_detected) {
+ if (p_dir == nullptr) {
+ return;
+ }
+
+ for (int i = 0; i < p_dir->get_file_count(); i++) {
+ String p = p_dir->get_file_path(i);
+
+ uint64_t timestamp = 0;
+ String md5;
+
+ if (p_cache.has(p)) {
+ const DetectedFile &cache = p_cache[p];
+ // Check if timestamp and MD5 match.
+ timestamp = FileAccess::get_modified_time(p);
+ bool cache_valid = true;
+ if (cache.timestamp != timestamp) {
+ md5 = FileAccess::get_md5(p);
+ if (md5 != cache.md5) {
+ cache_valid = false;
+ }
+ }
+
+ if (cache_valid) {
+ r_detected.insert(p, cache);
+ continue;
+ }
+ }
+
+ // Not cached, or cache invalid.
+
+ DetectedFile cache;
+
+ HashSet<StringName> classes;
+ ResourceLoader::get_classes_used(p, &classes);
+
+ for (const StringName &E : classes) {
+ cache.classes.push_back(E);
+ }
+
+ if (md5.is_empty()) {
+ cache.timestamp = FileAccess::get_modified_time(p);
+ cache.md5 = FileAccess::get_md5(p);
+ } else {
+ cache.timestamp = timestamp;
+ cache.md5 = md5;
+ }
+
+ r_detected.insert(p, cache);
+ }
+
+ for (int i = 0; i < p_dir->get_subdir_count(); i++) {
+ _find_files(p_dir->get_subdir(i), p_cache, r_detected);
+ }
+}
+
+void EditorBuildProfileManager::_detect_classes() {
+ HashMap<String, DetectedFile> previous_file_cache;
+
+ Ref<FileAccess> f = FileAccess::open("res://.godot/editor/used_class_cache", FileAccess::READ);
+ if (f.is_valid()) {
+ while (!f->eof_reached()) {
+ String l = f->get_line();
+ Vector<String> fields = l.split("::");
+ if (fields.size() == 4) {
+ String path = fields[0];
+ DetectedFile df;
+ df.timestamp = fields[1].to_int();
+ df.md5 = fields[2];
+ df.classes = fields[3].split(",");
+ previous_file_cache.insert(path, df);
+ }
+ }
+ f.unref();
+ }
+
+ HashMap<String, DetectedFile> updated_file_cache;
+
+ _find_files(EditorFileSystem::get_singleton()->get_filesystem(), previous_file_cache, updated_file_cache);
+
+ HashSet<StringName> used_classes;
+
+ // Find classes and update the disk cache in the process.
+ f = FileAccess::open("res://.godot/editor/used_class_cache", FileAccess::WRITE);
+
+ for (const KeyValue<String, DetectedFile> &E : updated_file_cache) {
+ String l = E.key + "::" + itos(E.value.timestamp) + "::" + E.value.md5 + "::";
+ for (int i = 0; i < E.value.classes.size(); i++) {
+ String c = E.value.classes[i];
+ if (i > 0) {
+ l += ",";
+ }
+ l += c;
+ used_classes.insert(c);
+ }
+ f->store_line(l);
+ }
+
+ f.unref();
+
+ // Add forced ones.
+
+ Vector<String> force_detect = edited->get_force_detect_classes().split(",");
+ for (int i = 0; i < force_detect.size(); i++) {
+ String c = force_detect[i].strip_edges();
+ if (c.is_empty()) {
+ continue;
+ }
+ used_classes.insert(c);
+ }
+
+ // Filter all classes to discard inherited ones.
+
+ HashSet<StringName> all_used_classes;
+
+ for (const StringName &E : used_classes) {
+ StringName c = E;
+ if (!ClassDB::class_exists(c)) {
+ // Maybe this is an old class that got replaced? try getting compat class.
+ c = ClassDB::get_compatibility_class(c);
+ if (!c) {
+ // No luck, skip.
+ continue;
+ }
+ }
+ while (c) {
+ all_used_classes.insert(c);
+ c = ClassDB::get_parent_class(c);
+ }
+ }
+
+ edited->clear_disabled_classes();
+
+ List<StringName> all_classes;
+ ClassDB::get_class_list(&all_classes);
+
+ for (const StringName &E : all_classes) {
+ if (all_used_classes.has(E)) {
+ // This class is valid, do nothing.
+ continue;
+ }
+
+ StringName p = ClassDB::get_parent_class(E);
+ if (!p || all_used_classes.has(p)) {
+ // If no parent, or if the parent is enabled, then add to disabled classes.
+ // This way we avoid disabling redundant classes.
+ edited->set_disable_class(E, true);
+ }
+ }
+}
+
+void EditorBuildProfileManager::_action_confirm() {
+ switch (last_action) {
+ case ACTION_RESET: {
+ edited.instantiate();
+ _update_edited_profile();
+ } break;
+ case ACTION_LOAD: {
+ } break;
+ case ACTION_SAVE: {
+ } break;
+ case ACTION_SAVE_AS: {
+ } break;
+ case ACTION_NEW: {
+ profile_path->set_text("");
+ edited.instantiate();
+ _update_edited_profile();
+ } break;
+ case ACTION_DETECT: {
+ _detect_classes();
+ _update_edited_profile();
+ } break;
+ case ACTION_MAX: {
+ } break;
+ }
+}
+
+void EditorBuildProfileManager::_fill_classes_from(TreeItem *p_parent, const String &p_class, const String &p_selected) {
+ TreeItem *class_item = class_list->create_item(p_parent);
+ class_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ class_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_class, "Node"));
+ String text = p_class;
+
+ bool disabled = edited->is_class_disabled(p_class);
+ if (disabled) {
+ class_item->set_custom_color(0, class_list->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
+ }
+
+ class_item->set_text(0, text);
+ class_item->set_editable(0, true);
+ class_item->set_selectable(0, true);
+ class_item->set_metadata(0, p_class);
+
+ bool collapsed = edited->is_item_collapsed(p_class);
+ class_item->set_collapsed(collapsed);
+
+ if (p_class == p_selected) {
+ class_item->select(0);
+ }
+ if (disabled) {
+ // Class disabled, do nothing else (do not show further).
+ return;
+ }
+
+ class_item->set_checked(0, true); // If it's not disabled, its checked.
+
+ List<StringName> child_classes;
+ ClassDB::get_direct_inheriters_from_class(p_class, &child_classes);
+ child_classes.sort_custom<StringName::AlphCompare>();
+
+ for (const StringName &name : child_classes) {
+ if (String(name).begins_with("Editor") || ClassDB::get_api_type(name) != ClassDB::API_CORE) {
+ continue;
+ }
+ _fill_classes_from(class_item, name, p_selected);
+ }
+}
+
+void EditorBuildProfileManager::_class_list_item_selected() {
+ if (updating_build_options) {
+ return;
+ }
+
+ TreeItem *item = class_list->get_selected();
+ if (!item) {
+ return;
+ }
+
+ Variant md = item->get_metadata(0);
+ if (md.get_type() == Variant::STRING || md.get_type() == Variant::STRING_NAME) {
+ String class_name = md;
+ String class_description;
+
+ DocTools *dd = EditorHelp::get_doc_data();
+ HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(class_name);
+ if (E) {
+ class_description = DTR(E->value.brief_description);
+ }
+
+ description_bit->set_text(class_description);
+ } else if (md.get_type() == Variant::INT) {
+ int build_option_id = md;
+ String build_option_description = EditorBuildProfile::get_build_option_description(EditorBuildProfile::BuildOption(build_option_id));
+
+ description_bit->set_text(TTRGET(build_option_description));
+ return;
+ } else {
+ return;
+ }
+}
+
+void EditorBuildProfileManager::_class_list_item_edited() {
+ if (updating_build_options) {
+ return;
+ }
+
+ TreeItem *item = class_list->get_edited();
+ if (!item) {
+ return;
+ }
+
+ bool checked = item->is_checked(0);
+
+ Variant md = item->get_metadata(0);
+ if (md.get_type() == Variant::STRING || md.get_type() == Variant::STRING_NAME) {
+ String class_selected = md;
+ edited->set_disable_class(class_selected, !checked);
+ _update_edited_profile();
+ } else if (md.get_type() == Variant::INT) {
+ int build_option_selected = md;
+ edited->set_disable_build_option(EditorBuildProfile::BuildOption(build_option_selected), !checked);
+ }
+}
+
+void EditorBuildProfileManager::_class_list_item_collapsed(Object *p_item) {
+ if (updating_build_options) {
+ return;
+ }
+
+ TreeItem *item = Object::cast_to<TreeItem>(p_item);
+ if (!item) {
+ return;
+ }
+
+ Variant md = item->get_metadata(0);
+ if (md.get_type() != Variant::STRING && md.get_type() != Variant::STRING_NAME) {
+ return;
+ }
+
+ String class_name = md;
+ bool collapsed = item->is_collapsed();
+ edited->set_item_collapsed(class_name, collapsed);
+}
+
+void EditorBuildProfileManager::_update_edited_profile() {
+ String class_selected;
+ int build_option_selected = -1;
+
+ if (class_list->get_selected()) {
+ Variant md = class_list->get_selected()->get_metadata(0);
+ if (md.get_type() == Variant::STRING || md.get_type() == Variant::STRING_NAME) {
+ class_selected = md;
+ } else if (md.get_type() == Variant::INT) {
+ build_option_selected = md;
+ }
+ }
+
+ class_list->clear();
+
+ updating_build_options = true;
+
+ TreeItem *root = class_list->create_item();
+
+ HashMap<EditorBuildProfile::BuildOptionCategory, TreeItem *> subcats;
+ for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_CATEGORY_MAX; i++) {
+ TreeItem *build_cat;
+ build_cat = class_list->create_item(root);
+
+ build_cat->set_text(0, EditorBuildProfile::get_build_option_category_name(EditorBuildProfile::BuildOptionCategory(i)));
+ subcats[EditorBuildProfile::BuildOptionCategory(i)] = build_cat;
+ }
+
+ for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_MAX; i++) {
+ TreeItem *build_option;
+ build_option = class_list->create_item(subcats[EditorBuildProfile::get_build_option_category(EditorBuildProfile::BuildOption(i))]);
+
+ build_option->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ build_option->set_text(0, EditorBuildProfile::get_build_option_name(EditorBuildProfile::BuildOption(i)));
+ build_option->set_selectable(0, true);
+ build_option->set_editable(0, true);
+ build_option->set_metadata(0, i);
+ if (!edited->is_build_option_disabled(EditorBuildProfile::BuildOption(i))) {
+ build_option->set_checked(0, true);
+ }
+
+ if (i == build_option_selected) {
+ build_option->select(0);
+ }
+ }
+
+ TreeItem *classes = class_list->create_item(root);
+ classes->set_text(0, TTR("Nodes and Classes:"));
+
+ _fill_classes_from(classes, "Node", class_selected);
+ _fill_classes_from(classes, "Resource", class_selected);
+
+ force_detect_classes->set_text(edited->get_force_detect_classes());
+
+ updating_build_options = false;
+
+ _class_list_item_selected();
+}
+
+void EditorBuildProfileManager::_force_detect_classes_changed(const String &p_text) {
+ if (updating_build_options) {
+ return;
+ }
+ edited->set_force_detect_classes(force_detect_classes->get_text());
+}
+
+void EditorBuildProfileManager::_import_profile(const String &p_path) {
+ Ref<EditorBuildProfile> profile;
+ profile.instantiate();
+ Error err = profile->load_from_file(p_path);
+ String basefile = p_path.get_file();
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("File '%s' format is invalid, import aborted."), basefile));
+ return;
+ }
+
+ profile_path->set_text(p_path);
+ EditorSettings::get_singleton()->set_project_metadata("build_profile", "last_file_path", p_path);
+
+ edited = profile;
+ _update_edited_profile();
+}
+
+void EditorBuildProfileManager::_export_profile(const String &p_path) {
+ ERR_FAIL_COND(edited.is_null());
+ Error err = edited->save_to_file(p_path);
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving profile to path: '%s'."), p_path));
+ } else {
+ profile_path->set_text(p_path);
+ EditorSettings::get_singleton()->set_project_metadata("build_profile", "last_file_path", p_path);
+ }
+}
+
+Ref<EditorBuildProfile> EditorBuildProfileManager::get_current_profile() {
+ return edited;
+}
+
+EditorBuildProfileManager *EditorBuildProfileManager::singleton = nullptr;
+
+void EditorBuildProfileManager::_bind_methods() {
+ ClassDB::bind_method("_update_selected_profile", &EditorBuildProfileManager::_update_edited_profile);
+}
+
+EditorBuildProfileManager::EditorBuildProfileManager() {
+ VBoxContainer *main_vbc = memnew(VBoxContainer);
+ add_child(main_vbc);
+
+ HBoxContainer *path_hbc = memnew(HBoxContainer);
+ profile_path = memnew(LineEdit);
+ path_hbc->add_child(profile_path);
+ profile_path->set_editable(true);
+ profile_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ profile_actions[ACTION_NEW] = memnew(Button(TTR("New")));
+ path_hbc->add_child(profile_actions[ACTION_NEW]);
+ profile_actions[ACTION_NEW]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_NEW));
+
+ profile_actions[ACTION_LOAD] = memnew(Button(TTR("Load")));
+ path_hbc->add_child(profile_actions[ACTION_LOAD]);
+ profile_actions[ACTION_LOAD]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_LOAD));
+
+ profile_actions[ACTION_SAVE] = memnew(Button(TTR("Save")));
+ path_hbc->add_child(profile_actions[ACTION_SAVE]);
+ profile_actions[ACTION_SAVE]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_SAVE));
+
+ profile_actions[ACTION_SAVE_AS] = memnew(Button(TTR("Save As")));
+ path_hbc->add_child(profile_actions[ACTION_SAVE_AS]);
+ profile_actions[ACTION_SAVE_AS]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_SAVE_AS));
+
+ main_vbc->add_margin_child(TTR("Profile:"), path_hbc);
+
+ main_vbc->add_child(memnew(HSeparator));
+
+ HBoxContainer *profiles_hbc = memnew(HBoxContainer);
+
+ profile_actions[ACTION_RESET] = memnew(Button(TTR("Reset to Defaults")));
+ profiles_hbc->add_child(profile_actions[ACTION_RESET]);
+ profile_actions[ACTION_RESET]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_RESET));
+
+ profile_actions[ACTION_DETECT] = memnew(Button(TTR("Detect from Project")));
+ profiles_hbc->add_child(profile_actions[ACTION_DETECT]);
+ profile_actions[ACTION_DETECT]->connect("pressed", callable_mp(this, &EditorBuildProfileManager::_profile_action).bind(ACTION_DETECT));
+
+ main_vbc->add_margin_child(TTR("Actions:"), profiles_hbc);
+
+ class_list = memnew(Tree);
+ class_list->set_hide_root(true);
+ class_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
+ class_list->connect("cell_selected", callable_mp(this, &EditorBuildProfileManager::_class_list_item_selected));
+ class_list->connect("item_edited", callable_mp(this, &EditorBuildProfileManager::_class_list_item_edited), CONNECT_DEFERRED);
+ class_list->connect("item_collapsed", callable_mp(this, &EditorBuildProfileManager::_class_list_item_collapsed));
+ // It will be displayed once the user creates or chooses a profile.
+ main_vbc->add_margin_child(TTR("Configure Engine Build Profile:"), class_list, true);
+
+ description_bit = memnew(EditorHelpBit);
+ description_bit->set_custom_minimum_size(Size2(0, 80) * EDSCALE);
+ main_vbc->add_margin_child(TTR("Description:"), description_bit, false);
+
+ confirm_dialog = memnew(ConfirmationDialog);
+ add_child(confirm_dialog);
+ confirm_dialog->set_title(TTR("Please Confirm:"));
+ confirm_dialog->connect("confirmed", callable_mp(this, &EditorBuildProfileManager::_action_confirm));
+
+ import_profile = memnew(EditorFileDialog);
+ add_child(import_profile);
+ import_profile->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ import_profile->add_filter("*.build", TTR("Egine Build Profile"));
+ import_profile->connect("files_selected", callable_mp(this, &EditorBuildProfileManager::_import_profile));
+ import_profile->set_title(TTR("Load Profile"));
+ import_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+
+ export_profile = memnew(EditorFileDialog);
+ add_child(export_profile);
+ export_profile->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
+ export_profile->add_filter("*.build", TTR("Egine Build Profile"));
+ export_profile->connect("file_selected", callable_mp(this, &EditorBuildProfileManager::_export_profile));
+ export_profile->set_title(TTR("Export Profile"));
+ export_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+
+ force_detect_classes = memnew(LineEdit);
+ main_vbc->add_margin_child(TTR("Forced classes on detect:"), force_detect_classes);
+ force_detect_classes->connect("text_changed", callable_mp(this, &EditorBuildProfileManager::_force_detect_classes_changed));
+
+ set_title(TTR("Edit Build Configuration Profile"));
+
+ singleton = this;
+}
diff --git a/editor/editor_build_profile.h b/editor/editor_build_profile.h
new file mode 100644
index 0000000000..606c415429
--- /dev/null
+++ b/editor/editor_build_profile.h
@@ -0,0 +1,191 @@
+/*************************************************************************/
+/* editor_build_profile.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 EDITOR_BUILD_PROFILE_H
+#define EDITOR_BUILD_PROFILE_H
+
+#include "core/io/file_access.h"
+#include "core/object/ref_counted.h"
+#include "editor/editor_help.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/tree.h"
+
+class EditorBuildProfile : public RefCounted {
+ GDCLASS(EditorBuildProfile, RefCounted);
+
+public:
+ enum BuildOption {
+ BUILD_OPTION_3D,
+ BUILD_OPTION_PHYSICS_2D,
+ BUILD_OPTION_PHYSICS_3D,
+ BUILD_OPTION_NAVIGATION,
+ BUILD_OPTION_XR,
+ BUILD_OPTION_RENDERING_DEVICE,
+ BUILD_OPTION_OPENGL,
+ BUILD_OPTION_VULKAN,
+ BUILD_OPTION_TEXT_SERVER_FALLBACK,
+ BUILD_OPTION_TEXT_SERVER_ADVANCED,
+ BUILD_OPTION_DYNAMIC_FONTS,
+ BUILD_OPTION_WOFF2_FONTS,
+ BUILD_OPTION_GRPAHITE_FONTS,
+ BUILD_OPTION_MSDFGEN,
+ BUILD_OPTION_MAX,
+ };
+
+ enum BuildOptionCategory {
+ BUILD_OPTION_CATEGORY_GENERAL,
+ BUILD_OPTION_CATEGORY_TEXT_SERVER,
+ BUILD_OPTION_CATEGORY_MAX,
+ };
+
+private:
+ HashSet<StringName> disabled_classes;
+
+ HashSet<StringName> collapsed_classes;
+
+ String force_detect_classes;
+
+ bool build_options_disabled[BUILD_OPTION_MAX] = {};
+ static const char *build_option_identifiers[BUILD_OPTION_MAX];
+ static const bool build_option_disabled_by_default[BUILD_OPTION_MAX];
+ static const bool build_option_disable_values[BUILD_OPTION_MAX];
+ static const BuildOptionCategory build_option_category[BUILD_OPTION_MAX];
+
+ String _get_build_option_name(BuildOption p_build_option) { return get_build_option_name(p_build_option); }
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_disable_class(const StringName &p_class, bool p_disabled);
+ bool is_class_disabled(const StringName &p_class) const;
+
+ void set_item_collapsed(const StringName &p_class, bool p_collapsed);
+ bool is_item_collapsed(const StringName &p_class) const;
+
+ void set_disable_build_option(BuildOption p_build_option, bool p_disable);
+ bool is_build_option_disabled(BuildOption p_build_option) const;
+
+ void set_force_detect_classes(const String &p_classes);
+ String get_force_detect_classes() const;
+
+ void clear_disabled_classes();
+
+ Error save_to_file(const String &p_path);
+ Error load_from_file(const String &p_path);
+
+ static String get_build_option_name(BuildOption p_build_option);
+ static String get_build_option_description(BuildOption p_build_option);
+ static bool get_build_option_disable_value(BuildOption p_build_option);
+ static BuildOptionCategory get_build_option_category(BuildOption p_build_option);
+
+ static String get_build_option_category_name(BuildOptionCategory p_build_option_category);
+
+ EditorBuildProfile();
+};
+
+VARIANT_ENUM_CAST(EditorBuildProfile::BuildOption)
+VARIANT_ENUM_CAST(EditorBuildProfile::BuildOptionCategory)
+
+class EditorFileSystemDirectory;
+
+class EditorBuildProfileManager : public AcceptDialog {
+ GDCLASS(EditorBuildProfileManager, AcceptDialog);
+
+ enum Action {
+ ACTION_NEW,
+ ACTION_RESET,
+ ACTION_LOAD,
+ ACTION_SAVE,
+ ACTION_SAVE_AS,
+ ACTION_DETECT,
+ ACTION_MAX
+ };
+
+ Action last_action = ACTION_NEW;
+
+ ConfirmationDialog *confirm_dialog = nullptr;
+ Button *profile_actions[ACTION_MAX];
+
+ Tree *class_list = nullptr;
+ EditorHelpBit *description_bit = nullptr;
+
+ EditorFileDialog *import_profile = nullptr;
+ EditorFileDialog *export_profile = nullptr;
+
+ LineEdit *profile_path = nullptr;
+
+ LineEdit *force_detect_classes = nullptr;
+
+ void _profile_action(int p_action);
+ void _action_confirm();
+
+ void _update_edited_profile();
+ void _fill_classes_from(TreeItem *p_parent, const String &p_class, const String &p_selected);
+
+ Ref<EditorBuildProfile> edited;
+
+ void _import_profile(const String &p_path);
+ void _export_profile(const String &p_path);
+
+ bool updating_build_options = false;
+
+ void _class_list_item_selected();
+ void _class_list_item_edited();
+ void _class_list_item_collapsed(Object *p_item);
+ void _detect_classes();
+
+ void _force_detect_classes_changed(const String &p_text);
+
+ struct DetectedFile {
+ uint32_t timestamp = 0;
+ String md5;
+ Vector<String> classes;
+ };
+
+ void _find_files(EditorFileSystemDirectory *p_dir, const HashMap<String, DetectedFile> &p_cache, HashMap<String, DetectedFile> &r_detected);
+
+ static EditorBuildProfileManager *singleton;
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ Ref<EditorBuildProfile> get_current_profile();
+
+ static EditorBuildProfileManager *get_singleton() { return singleton; }
+ EditorBuildProfileManager();
+};
+
+#endif // EDITOR_BUILD_PROFILE_H
diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp
index c1cd7f9c7b..ba1f2fd6af 100644
--- a/editor/editor_command_palette.cpp
+++ b/editor/editor_command_palette.cpp
@@ -32,6 +32,7 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/gui/control.h"
#include "scene/gui/tree.h"
@@ -199,7 +200,7 @@ void EditorCommandPalette::add_command(String p_command_name, String p_key_name,
}
Command command;
command.name = p_command_name;
- command.callable = p_action.bind(argptrs, arguments.size());
+ command.callable = p_action.bindp(argptrs, arguments.size());
command.shortcut = p_shortcut_text;
commands[p_key_name] = command;
@@ -225,7 +226,7 @@ void EditorCommandPalette::_add_command(String p_command_name, String p_key_name
void EditorCommandPalette::execute_command(String &p_command_key) {
ERR_FAIL_COND_MSG(!commands.has(p_command_key), p_command_key + " not found.");
commands[p_command_key].last_used = OS::get_singleton()->get_unix_time();
- commands[p_command_key].callable.call_deferred(nullptr, 0);
+ commands[p_command_key].callable.call_deferredp(nullptr, 0);
_save_history();
}
@@ -311,8 +312,8 @@ EditorCommandPalette::EditorCommandPalette() {
search_options = memnew(Tree);
search_options->connect("item_activated", callable_mp(this, &EditorCommandPalette::_confirmed));
- search_options->connect("item_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled), varray(false));
- search_options->connect("nothing_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled), varray(true));
+ search_options->connect("item_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled).bind(false));
+ search_options->connect("nothing_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled).bind(true));
search_options->create_item();
search_options->set_hide_root(true);
search_options->set_columns(2);
diff --git a/editor/editor_command_palette.h b/editor/editor_command_palette.h
index 124703cca4..b3e84771d0 100644
--- a/editor/editor_command_palette.h
+++ b/editor/editor_command_palette.h
@@ -101,4 +101,4 @@ public:
Ref<Shortcut> ED_SHORTCUT_AND_COMMAND(const String &p_path, const String &p_name, Key p_keycode = Key::NONE, String p_command = "");
-#endif //EDITOR_COMMAND_PALETTE_H
+#endif // EDITOR_COMMAND_PALETTE_H
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 64c234a07c..2d4945db14 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) {
@@ -1027,7 +1028,7 @@ void EditorSelection::add_node(Node *p_node) {
}
selection[p_node] = meta;
- p_node->connect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed), varray(p_node), CONNECT_ONESHOT);
+ p_node->connect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed).bind(p_node), CONNECT_ONESHOT);
}
void EditorSelection::remove_node(Node *p_node) {
diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp
index 8494991892..4071722185 100644
--- a/editor/editor_dir_dialog.cpp
+++ b/editor/editor_dir_dialog.cpp
@@ -81,15 +81,15 @@ void EditorDirDialog::reload(const String &p_path) {
void EditorDirDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload), make_binds(""));
+ EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload).bind(""));
reload();
if (!tree->is_connected("item_collapsed", callable_mp(this, &EditorDirDialog::_item_collapsed))) {
- tree->connect("item_collapsed", callable_mp(this, &EditorDirDialog::_item_collapsed), varray(), CONNECT_DEFERRED);
+ tree->connect("item_collapsed", callable_mp(this, &EditorDirDialog::_item_collapsed), CONNECT_DEFERRED);
}
if (!EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &EditorDirDialog::reload))) {
- EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload), make_binds(""));
+ EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload).bind(""));
}
} break;
@@ -211,5 +211,5 @@ EditorDirDialog::EditorDirDialog() {
mkdirerr->set_text(TTR("Could not create folder."));
add_child(mkdirerr);
- get_ok_button()->set_text(TTR("Choose"));
+ set_ok_button_text(TTR("Choose"));
}
diff --git a/editor/editor_export.h b/editor/editor_export.h
deleted file mode 100644
index 6f41736d2d..0000000000
--- a/editor/editor_export.h
+++ /dev/null
@@ -1,532 +0,0 @@
-/*************************************************************************/
-/* editor_export.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 EDITOR_EXPORT_H
-#define EDITOR_EXPORT_H
-
-#include "core/io/dir_access.h"
-#include "core/io/resource.h"
-#include "scene/gui/rich_text_label.h"
-#include "scene/main/node.h"
-#include "scene/main/timer.h"
-#include "scene/resources/texture.h"
-
-class FileAccess;
-class EditorExportPlatform;
-class EditorFileSystemDirectory;
-struct EditorProgress;
-
-class EditorExportPreset : public RefCounted {
- GDCLASS(EditorExportPreset, RefCounted);
-
-public:
- enum ExportFilter {
- EXPORT_ALL_RESOURCES,
- EXPORT_SELECTED_SCENES,
- EXPORT_SELECTED_RESOURCES,
- EXCLUDE_SELECTED_RESOURCES,
- };
-
- enum ScriptExportMode {
- MODE_SCRIPT_TEXT,
- MODE_SCRIPT_COMPILED,
- };
-
-private:
- Ref<EditorExportPlatform> platform;
- ExportFilter export_filter = EXPORT_ALL_RESOURCES;
- String include_filter;
- String exclude_filter;
- String export_path;
-
- String exporter;
- HashSet<String> selected_files;
- bool runnable = false;
-
- friend class EditorExport;
- friend class EditorExportPlatform;
-
- List<PropertyInfo> properties;
- HashMap<StringName, Variant> values;
-
- String name;
-
- String custom_features;
-
- String enc_in_filters;
- String enc_ex_filters;
- bool enc_pck = false;
- bool enc_directory = false;
-
- int script_mode = MODE_SCRIPT_COMPILED;
- String script_key;
-
-protected:
- 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:
- Ref<EditorExportPlatform> get_platform() const;
-
- bool has(const StringName &p_property) const { return values.has(p_property); }
-
- void update_files_to_export();
-
- Vector<String> get_files_to_export() const;
-
- void add_export_file(const String &p_path);
- void remove_export_file(const String &p_path);
- bool has_export_file(const String &p_path);
-
- void set_name(const String &p_name);
- String get_name() const;
-
- void set_runnable(bool p_enable);
- bool is_runnable() const;
-
- void set_export_filter(ExportFilter p_filter);
- ExportFilter get_export_filter() const;
-
- void set_include_filter(const String &p_include);
- String get_include_filter() const;
-
- void set_exclude_filter(const String &p_exclude);
- String get_exclude_filter() const;
-
- void set_custom_features(const String &p_custom_features);
- String get_custom_features() const;
-
- void set_export_path(const String &p_path);
- String get_export_path() const;
-
- void set_enc_in_filter(const String &p_filter);
- String get_enc_in_filter() const;
-
- void set_enc_ex_filter(const String &p_filter);
- String get_enc_ex_filter() const;
-
- void set_enc_pck(bool p_enabled);
- bool get_enc_pck() const;
-
- void set_enc_directory(bool p_enabled);
- bool get_enc_directory() const;
-
- void set_script_export_mode(int p_mode);
- int get_script_export_mode() const;
-
- void set_script_encryption_key(const String &p_key);
- String get_script_encryption_key() const;
-
- const List<PropertyInfo> &get_properties() const { return properties; }
-
- EditorExportPreset() {}
-};
-
-struct SharedObject {
- String path;
- Vector<String> tags;
- String target;
-
- SharedObject(const String &p_path, const Vector<String> &p_tags, const String &p_target) :
- path(p_path),
- tags(p_tags),
- target(p_target) {
- }
-
- SharedObject() {}
-};
-
-class EditorExportPlatform : public RefCounted {
- GDCLASS(EditorExportPlatform, RefCounted);
-
-public:
- typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
- typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so);
-
- enum ExportMessageType {
- EXPORT_MESSAGE_NONE,
- EXPORT_MESSAGE_INFO,
- EXPORT_MESSAGE_WARNING,
- EXPORT_MESSAGE_ERROR,
- };
-
- struct ExportMessage {
- ExportMessageType msg_type;
- String category;
- String text;
- };
-
-private:
- struct SavedData {
- uint64_t ofs = 0;
- uint64_t size = 0;
- bool encrypted = false;
- Vector<uint8_t> md5;
- CharString path_utf8;
-
- bool operator<(const SavedData &p_data) const {
- return path_utf8 < p_data.path_utf8;
- }
- };
-
- struct PackData {
- Ref<FileAccess> f;
- Vector<SavedData> file_ofs;
- EditorProgress *ep = nullptr;
- Vector<SharedObject> *so_files = nullptr;
- };
-
- struct ZipData {
- void *zip = nullptr;
- EditorProgress *ep = nullptr;
- };
-
- struct FeatureContainers {
- HashSet<String> features;
- Vector<String> features_pv;
- };
-
- Vector<ExportMessage> messages;
-
- void _export_find_resources(EditorFileSystemDirectory *p_dir, HashSet<String> &p_paths);
- void _export_find_dependencies(const String &p_path, HashSet<String> &p_paths);
-
- void gen_debug_flags(Vector<String> &r_flags, int p_flags);
- static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
- static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
-
- void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, HashSet<String> &r_list, bool exclude);
- void _edit_filter_list(HashSet<String> &r_list, const String &p_filter, bool exclude);
-
- static Error _add_shared_object(void *p_userdata, const SharedObject &p_so);
-
-protected:
- struct ExportNotifier {
- ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
- ~ExportNotifier();
- };
-
- FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug);
-
- bool exists_export_template(String template_file_name, String *err) const;
- String find_export_template(String template_file_name, String *err = nullptr) const;
- void gen_export_flags(Vector<String> &r_flags, int p_flags);
-
-public:
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) = 0;
-
- struct ExportOption {
- PropertyInfo option;
- Variant default_value;
-
- ExportOption(const PropertyInfo &p_info, const Variant &p_default) :
- option(p_info),
- default_value(p_default) {
- }
- ExportOption() {}
- };
-
- virtual Ref<EditorExportPreset> create_preset();
-
- virtual void clear_messages() { messages.clear(); }
- virtual void add_message(ExportMessageType p_type, const String &p_category, const String &p_message) {
- ExportMessage msg;
- msg.category = p_category;
- msg.text = p_message;
- msg.msg_type = p_type;
- messages.push_back(msg);
- switch (p_type) {
- case EXPORT_MESSAGE_INFO: {
- print_line(vformat("%s: %s\n", msg.category, msg.text));
- } break;
- case EXPORT_MESSAGE_WARNING: {
- WARN_PRINT(vformat("%s: %s\n", msg.category, msg.text));
- } break;
- case EXPORT_MESSAGE_ERROR: {
- ERR_PRINT(vformat("%s: %s\n", msg.category, msg.text));
- } break;
- default:
- break;
- }
- }
-
- virtual int get_message_count() const {
- return messages.size();
- }
-
- virtual ExportMessage get_message(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, messages.size(), ExportMessage());
- return messages[p_index];
- }
-
- virtual ExportMessageType get_worst_message_type() const {
- ExportMessageType worst_type = EXPORT_MESSAGE_NONE;
- for (int i = 0; i < messages.size(); i++) {
- worst_type = MAX(worst_type, messages[i].msg_type);
- }
- return worst_type;
- }
-
- virtual bool fill_log_messages(RichTextLabel *p_log, Error p_err);
-
- virtual void get_export_options(List<ExportOption> *r_options) = 0;
- virtual bool should_update_export_options() { return false; }
- virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; }
-
- virtual String get_os_name() const = 0;
- virtual String get_name() const = 0;
- virtual Ref<Texture2D> get_logo() const = 0;
-
- Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr);
-
- Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr);
- Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
-
- virtual bool poll_export() { return false; }
- virtual int get_options_count() const { return 0; }
- virtual String get_options_tooltip() const { return ""; }
- virtual Ref<ImageTexture> get_option_icon(int p_index) const;
- virtual String get_option_label(int p_device) const { return ""; }
- virtual String get_option_tooltip(int p_device) const { return ""; }
-
- enum DebugFlags {
- DEBUG_FLAG_DUMB_CLIENT = 1,
- DEBUG_FLAG_REMOTE_DEBUG = 2,
- DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST = 4,
- DEBUG_FLAG_VIEW_COLLISONS = 8,
- DEBUG_FLAG_VIEW_NAVIGATION = 16,
- };
-
- virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { return OK; }
- virtual Ref<Texture2D> get_run_icon() const { return get_logo(); }
-
- String test_etc2() const;
- virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const = 0;
-
- virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const = 0;
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) = 0;
- virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
- virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
- virtual void get_platform_features(List<String> *r_features) = 0;
- virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) = 0;
- virtual String get_debug_protocol() const { return "tcp://"; }
-
- EditorExportPlatform();
-};
-
-class EditorExportPlugin : public RefCounted {
- GDCLASS(EditorExportPlugin, RefCounted);
-
- friend class EditorExportPlatform;
-
- Ref<EditorExportPreset> export_preset;
-
- Vector<SharedObject> shared_objects;
- struct ExtraFile {
- String path;
- Vector<uint8_t> data;
- bool remap = false;
- };
- Vector<ExtraFile> extra_files;
- bool skipped = false;
-
- Vector<String> ios_frameworks;
- Vector<String> ios_embedded_frameworks;
- Vector<String> ios_project_static_libs;
- String ios_plist_content;
- String ios_linker_flags;
- Vector<String> ios_bundle_files;
- String ios_cpp_code;
-
- Vector<String> osx_plugin_files;
-
- _FORCE_INLINE_ void _clear() {
- shared_objects.clear();
- extra_files.clear();
- skipped = false;
- }
-
- _FORCE_INLINE_ void _export_end() {
- ios_frameworks.clear();
- ios_embedded_frameworks.clear();
- ios_bundle_files.clear();
- ios_plist_content = "";
- ios_linker_flags = "";
- ios_cpp_code = "";
- osx_plugin_files.clear();
- }
-
- void _export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features);
- void _export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags);
- void _export_end_script();
-
-protected:
- void set_export_preset(const Ref<EditorExportPreset> &p_preset);
- Ref<EditorExportPreset> get_export_preset() const;
-
- void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap);
- void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String());
-
- void add_ios_framework(const String &p_path);
- void add_ios_embedded_framework(const String &p_path);
- void add_ios_project_static_lib(const String &p_path);
- void add_ios_plist_content(const String &p_plist_content);
- void add_ios_linker_flags(const String &p_flags);
- void add_ios_bundle_file(const String &p_path);
- void add_ios_cpp_code(const String &p_code);
- void add_osx_plugin_file(const String &p_path);
-
- void skip();
-
- virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features);
- virtual void _export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags);
-
- static void _bind_methods();
-
- GDVIRTUAL3(_export_file, String, String, Vector<String>)
- GDVIRTUAL4(_export_begin, Vector<String>, bool, String, uint32_t)
- GDVIRTUAL0(_export_end)
-
-public:
- Vector<String> get_ios_frameworks() const;
- Vector<String> get_ios_embedded_frameworks() const;
- Vector<String> get_ios_project_static_libs() const;
- String get_ios_plist_content() const;
- String get_ios_linker_flags() const;
- Vector<String> get_ios_bundle_files() const;
- String get_ios_cpp_code() const;
- const Vector<String> &get_osx_plugin_files() const;
-
- EditorExportPlugin();
-};
-
-class EditorExport : public Node {
- GDCLASS(EditorExport, Node);
-
- Vector<Ref<EditorExportPlatform>> export_platforms;
- Vector<Ref<EditorExportPreset>> export_presets;
- Vector<Ref<EditorExportPlugin>> export_plugins;
-
- StringName _export_presets_updated;
-
- Timer *save_timer = nullptr;
- bool block_save = false;
-
- static EditorExport *singleton;
-
- void _save();
-
-protected:
- friend class EditorExportPreset;
- void save_presets();
-
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- static EditorExport *get_singleton() { return singleton; }
-
- void add_export_platform(const Ref<EditorExportPlatform> &p_platform);
- int get_export_platform_count();
- Ref<EditorExportPlatform> get_export_platform(int p_idx);
-
- void add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos = -1);
- int get_export_preset_count() const;
- Ref<EditorExportPreset> get_export_preset(int p_idx);
- void remove_export_preset(int p_idx);
-
- void add_export_plugin(const Ref<EditorExportPlugin> &p_plugin);
- void remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin);
- Vector<Ref<EditorExportPlugin>> get_export_plugins();
-
- void load_config();
- void update_export_presets();
- bool poll_export_platforms();
-
- EditorExport();
- ~EditorExport();
-};
-
-class EditorExportPlatformPC : public EditorExportPlatform {
- GDCLASS(EditorExportPlatformPC, EditorExportPlatform);
-
-private:
- Ref<ImageTexture> logo;
- String name;
- String os_name;
-
- int chmod_flags = -1;
-
-public:
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
-
- virtual void get_export_options(List<ExportOption> *r_options) override;
-
- virtual String get_name() const override;
- virtual String get_os_name() const override;
- virtual Ref<Texture2D> get_logo() const override;
-
- virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override;
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
- virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
- virtual String get_template_file_name(const String &p_target, const String &p_arch) const = 0;
-
- virtual Error prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
- virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { return OK; };
- virtual Error export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
-
- void set_extension(const String &p_extension, const String &p_feature_key = "default");
- void set_name(const String &p_name);
- void set_os_name(const String &p_name);
-
- void set_logo(const Ref<Texture2D> &p_logo);
-
- void add_platform_feature(const String &p_feature);
- virtual void get_platform_features(List<String> *r_features) override;
- virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override;
-
- int get_chmod_flags() const;
- void set_chmod_flags(int p_flags);
-
- virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
- return Error::OK;
- }
-};
-
-class EditorExportTextSceneToBinaryPlugin : public EditorExportPlugin {
- GDCLASS(EditorExportTextSceneToBinaryPlugin, EditorExportPlugin);
-
-public:
- virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) override;
- EditorExportTextSceneToBinaryPlugin();
-};
-
-#endif // EDITOR_IMPORT_EXPORT_H
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index f8fc28c31c..f0bf9fd5b3 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -34,6 +34,7 @@
#include "core/io/json.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -314,7 +315,7 @@ void EditorFeatureProfileManager::_notification(int p_what) {
current_profile = EDITOR_GET("_default_feature_profile");
if (!current_profile.is_empty()) {
current.instantiate();
- Error err = current->load_from_file(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(current_profile + ".profile"));
+ Error err = current->load_from_file(EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(current_profile + ".profile"));
if (err != OK) {
ERR_PRINT("Error loading default feature profile: " + current_profile);
current_profile = String();
@@ -323,6 +324,11 @@ void EditorFeatureProfileManager::_notification(int p_what) {
}
_update_profile_list(current_profile);
} break;
+
+ case NOTIFICATION_THEME_CHANGED: {
+ // Make sure that the icons are correctly adjusted if the theme's lightness was switched.
+ _update_selected_profile();
+ } break;
}
}
@@ -340,7 +346,7 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr
if (p_select_profile.is_empty()) { //default, keep
if (profile_list->get_selected() >= 0) {
selected_profile = profile_list->get_item_metadata(profile_list->get_selected());
- if (!FileAccess::exists(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(selected_profile + ".profile"))) {
+ if (!FileAccess::exists(EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(selected_profile + ".profile"))) {
selected_profile = String(); //does not exist
}
}
@@ -349,8 +355,8 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr
}
Vector<String> profiles;
- Ref<DirAccess> d = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
- ERR_FAIL_COND_MSG(d.is_null(), "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
+ Ref<DirAccess> d = DirAccess::open(EditorPaths::get_singleton()->get_feature_profiles_dir());
+ ERR_FAIL_COND_MSG(d.is_null(), "Cannot open directory '" + EditorPaths::get_singleton()->get_feature_profiles_dir() + "'.");
d->list_dir_begin();
while (true) {
@@ -452,8 +458,8 @@ void EditorFeatureProfileManager::_profile_action(int p_action) {
void EditorFeatureProfileManager::_erase_selected_profile() {
String selected = _get_selected_profile();
ERR_FAIL_COND(selected.is_empty());
- Ref<DirAccess> da = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
- ERR_FAIL_COND_MSG(da.is_null(), "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
+ Ref<DirAccess> da = DirAccess::open(EditorPaths::get_singleton()->get_feature_profiles_dir());
+ ERR_FAIL_COND_MSG(da.is_null(), "Cannot open directory '" + EditorPaths::get_singleton()->get_feature_profiles_dir() + "'.");
da->remove(selected + ".profile");
if (selected == current_profile) {
@@ -469,7 +475,7 @@ void EditorFeatureProfileManager::_create_new_profile() {
EditorNode::get_singleton()->show_warning(TTR("Profile must be a valid filename and must not contain '.'"));
return;
}
- String file = EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(name + ".profile");
+ String file = EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(name + ".profile");
if (FileAccess::exists(file)) {
EditorNode::get_singleton()->show_warning(TTR("Profile with this name already exists."));
return;
@@ -748,8 +754,8 @@ void EditorFeatureProfileManager::_update_selected_profile() {
} else {
//reload edited, if different from current
edited.instantiate();
- Error err = edited->load_from_file(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(profile + ".profile"));
- ERR_FAIL_COND_MSG(err != OK, "Error when loading EditorSettings from file '" + EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(profile + ".profile") + "'.");
+ Error err = edited->load_from_file(EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(profile + ".profile"));
+ ERR_FAIL_COND_MSG(err != OK, "Error when loading editor feature profile from file '" + EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(profile + ".profile") + "'.");
}
updating_features = true;
@@ -804,7 +810,7 @@ void EditorFeatureProfileManager::_import_profiles(const Vector<String> &p_paths
return;
}
- String dst_file = EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(basefile);
+ String dst_file = EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(basefile);
if (FileAccess::exists(dst_file)) {
EditorNode::get_singleton()->show_warning(vformat(TTR("Profile '%s' already exists. Remove it first before importing, import aborted."), basefile.get_basename()));
@@ -819,7 +825,7 @@ void EditorFeatureProfileManager::_import_profiles(const Vector<String> &p_paths
Error err = profile->load_from_file(p_paths[i]);
ERR_CONTINUE(err != OK);
String basefile = p_paths[i].get_file();
- String dst_file = EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(basefile);
+ String dst_file = EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(basefile);
profile->save_to_file(dst_file);
}
@@ -843,7 +849,7 @@ void EditorFeatureProfileManager::_save_and_update() {
ERR_FAIL_COND(edited_path.is_empty());
ERR_FAIL_COND(edited.is_null());
- edited->save_to_file(EditorSettings::get_singleton()->get_feature_profiles_dir().plus_file(edited_path + ".profile"));
+ edited->save_to_file(EditorPaths::get_singleton()->get_feature_profiles_dir().plus_file(edited_path + ".profile"));
if (edited == current) {
update_timer->start();
@@ -883,7 +889,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
profile_actions[PROFILE_CLEAR] = memnew(Button(TTR("Reset to Default")));
name_hbc->add_child(profile_actions[PROFILE_CLEAR]);
profile_actions[PROFILE_CLEAR]->set_disabled(true);
- profile_actions[PROFILE_CLEAR]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_CLEAR));
+ profile_actions[PROFILE_CLEAR]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_CLEAR));
main_vbc->add_margin_child(TTR("Current Profile:"), name_hbc);
@@ -897,12 +903,12 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
profile_actions[PROFILE_NEW] = memnew(Button(TTR("Create Profile")));
profiles_hbc->add_child(profile_actions[PROFILE_NEW]);
- profile_actions[PROFILE_NEW]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_NEW));
+ profile_actions[PROFILE_NEW]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_NEW));
profile_actions[PROFILE_ERASE] = memnew(Button(TTR("Remove Profile")));
profiles_hbc->add_child(profile_actions[PROFILE_ERASE]);
profile_actions[PROFILE_ERASE]->set_disabled(true);
- profile_actions[PROFILE_ERASE]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_ERASE));
+ profile_actions[PROFILE_ERASE]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_ERASE));
main_vbc->add_margin_child(TTR("Available Profiles:"), profiles_hbc);
@@ -911,18 +917,18 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
profile_actions[PROFILE_SET] = memnew(Button(TTR("Make Current")));
current_profile_hbc->add_child(profile_actions[PROFILE_SET]);
profile_actions[PROFILE_SET]->set_disabled(true);
- profile_actions[PROFILE_SET]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_SET));
+ profile_actions[PROFILE_SET]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_SET));
current_profile_hbc->add_child(memnew(VSeparator));
profile_actions[PROFILE_IMPORT] = memnew(Button(TTR("Import")));
current_profile_hbc->add_child(profile_actions[PROFILE_IMPORT]);
- profile_actions[PROFILE_IMPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_IMPORT));
+ profile_actions[PROFILE_IMPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_IMPORT));
profile_actions[PROFILE_EXPORT] = memnew(Button(TTR("Export")));
current_profile_hbc->add_child(profile_actions[PROFILE_EXPORT]);
profile_actions[PROFILE_EXPORT]->set_disabled(true);
- profile_actions[PROFILE_EXPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action), varray(PROFILE_EXPORT));
+ profile_actions[PROFILE_EXPORT]->connect("pressed", callable_mp(this, &EditorFeatureProfileManager::_profile_action).bind(PROFILE_EXPORT));
main_vbc->add_child(current_profile_hbc);
@@ -939,7 +945,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
class_list->set_hide_root(true);
class_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
class_list->connect("cell_selected", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_selected));
- class_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_edited), varray(), CONNECT_DEFERRED);
+ class_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_edited), CONNECT_DEFERRED);
class_list->connect("item_collapsed", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_collapsed));
// It will be displayed once the user creates or chooses a profile.
class_list_vbc->hide();
@@ -957,7 +963,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
property_list->set_hide_root(true);
property_list->set_hide_folding(true);
property_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
- property_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_property_item_edited), varray(), CONNECT_DEFERRED);
+ property_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_property_item_edited), CONNECT_DEFERRED);
// It will be displayed once the user creates or chooses a profile.
property_list_vbc->hide();
@@ -983,7 +989,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
add_child(new_profile_dialog);
new_profile_dialog->connect("confirmed", callable_mp(this, &EditorFeatureProfileManager::_create_new_profile));
new_profile_dialog->register_text_enter(new_profile_name);
- new_profile_dialog->get_ok_button()->set_text(TTR("Create"));
+ new_profile_dialog->set_ok_button_text(TTR("Create"));
erase_profile_dialog = memnew(ConfirmationDialog);
add_child(erase_profile_dialog);
@@ -993,7 +999,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
import_profiles = memnew(EditorFileDialog);
add_child(import_profiles);
import_profiles->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES);
- import_profiles->add_filter("*.profile; " + TTR("Godot Feature Profile"));
+ import_profiles->add_filter("*.profile", TTR("Godot Feature Profile"));
import_profiles->connect("files_selected", callable_mp(this, &EditorFeatureProfileManager::_import_profiles));
import_profiles->set_title(TTR("Import Profile(s)"));
import_profiles->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
@@ -1001,7 +1007,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
export_profile = memnew(EditorFileDialog);
add_child(export_profile);
export_profile->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- export_profile->add_filter("*.profile; " + TTR("Godot Feature Profile"));
+ export_profile->add_filter("*.profile", TTR("Godot Feature Profile"));
export_profile->connect("file_selected", callable_mp(this, &EditorFeatureProfileManager::_export_profile));
export_profile->set_title(TTR("Export Profile"));
export_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 95f72476aa..2f1134e8ef 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -227,10 +227,10 @@ void EditorFileDialog::update_dir() {
switch (mode) {
case FILE_MODE_OPEN_FILE:
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(TTR("Select Current Folder"));
+ set_ok_button_text(TTR("Select Current Folder"));
break;
case FILE_MODE_OPEN_ANY:
case FILE_MODE_SAVE_FILE:
@@ -507,7 +507,7 @@ void EditorFileDialog::_item_selected(int p_item) {
file->set_text(d["name"]);
_request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
} else if (mode == FILE_MODE_OPEN_DIR) {
- get_ok_button()->set_text(TTR("Select This Folder"));
+ set_ok_button_text(TTR("Select This Folder"));
}
get_ok_button()->set_disabled(_is_open_should_be_disabled());
@@ -540,13 +540,13 @@ void EditorFileDialog::_items_clear_selection(const Vector2 &p_pos, MouseButton
switch (mode) {
case FILE_MODE_OPEN_FILE:
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
get_ok_button()->set_disabled(!item_list->is_anything_selected());
break;
case FILE_MODE_OPEN_DIR:
get_ok_button()->set_disabled(false);
- get_ok_button()->set_text(TTR("Select Current Folder"));
+ set_ok_button_text(TTR("Select Current Folder"));
break;
case FILE_MODE_OPEN_ANY:
@@ -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);
}
@@ -976,8 +976,12 @@ void EditorFileDialog::clear_filters() {
invalidate();
}
-void EditorFileDialog::add_filter(const String &p_filter) {
- filters.push_back(p_filter);
+void EditorFileDialog::add_filter(const String &p_filter, const String &p_description) {
+ if (p_description.is_empty()) {
+ filters.push_back(p_filter);
+ } else {
+ filters.push_back(vformat("%s ; %s", p_filter, p_description));
+ }
update_filters();
invalidate();
}
@@ -1033,27 +1037,27 @@ void EditorFileDialog::set_file_mode(FileMode p_mode) {
mode = p_mode;
switch (mode) {
case FILE_MODE_OPEN_FILE:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_title(TTR("Open a File"));
can_create_dir = false;
break;
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_title(TTR("Open File(s)"));
can_create_dir = false;
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_title(TTR("Open a Directory"));
can_create_dir = true;
break;
case FILE_MODE_OPEN_ANY:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_title(TTR("Open a File or Directory"));
can_create_dir = true;
break;
case FILE_MODE_SAVE_FILE:
- get_ok_button()->set_text(TTR("Save"));
+ set_ok_button_text(TTR("Save"));
set_title(TTR("Save a File"));
can_create_dir = true;
break;
@@ -1481,7 +1485,7 @@ void EditorFileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_cancel_pressed"), &EditorFileDialog::_cancel_pressed);
ClassDB::bind_method(D_METHOD("clear_filters"), &EditorFileDialog::clear_filters);
- ClassDB::bind_method(D_METHOD("add_filter", "filter"), &EditorFileDialog::add_filter);
+ ClassDB::bind_method(D_METHOD("add_filter", "filter", "description"), &EditorFileDialog::add_filter, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_current_dir"), &EditorFileDialog::get_current_dir);
ClassDB::bind_method(D_METHOD("get_current_file"), &EditorFileDialog::get_current_file);
ClassDB::bind_method(D_METHOD("get_current_path"), &EditorFileDialog::get_current_path);
@@ -1677,7 +1681,7 @@ EditorFileDialog::EditorFileDialog() {
mode_thumbnails = memnew(Button);
mode_thumbnails->set_flat(true);
- mode_thumbnails->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode), varray(DISPLAY_THUMBNAILS));
+ mode_thumbnails->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_THUMBNAILS));
mode_thumbnails->set_toggle_mode(true);
mode_thumbnails->set_pressed(display_mode == DISPLAY_THUMBNAILS);
mode_thumbnails->set_button_group(view_mode_group);
@@ -1686,7 +1690,7 @@ EditorFileDialog::EditorFileDialog() {
mode_list = memnew(Button);
mode_list->set_flat(true);
- mode_list->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode), varray(DISPLAY_LIST));
+ mode_list->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_LIST));
mode_list->set_toggle_mode(true);
mode_list->set_pressed(display_mode == DISPLAY_LIST);
mode_list->set_button_group(view_mode_group);
@@ -1812,9 +1816,9 @@ EditorFileDialog::EditorFileDialog() {
_update_drives();
connect("confirmed", callable_mp(this, &EditorFileDialog::_action_pressed));
- item_list->connect("item_selected", callable_mp(this, &EditorFileDialog::_item_selected), varray(), CONNECT_DEFERRED);
- item_list->connect("multi_selected", callable_mp(this, &EditorFileDialog::_multi_selected), varray(), CONNECT_DEFERRED);
- item_list->connect("item_activated", callable_mp(this, &EditorFileDialog::_item_dc_selected), varray());
+ item_list->connect("item_selected", callable_mp(this, &EditorFileDialog::_item_selected), CONNECT_DEFERRED);
+ item_list->connect("multi_selected", callable_mp(this, &EditorFileDialog::_multi_selected), CONNECT_DEFERRED);
+ item_list->connect("item_activated", callable_mp(this, &EditorFileDialog::_item_dc_selected).bind());
item_list->connect("empty_clicked", callable_mp(this, &EditorFileDialog::_items_clear_selection));
dir->connect("text_submitted", callable_mp(this, &EditorFileDialog::_dir_submitted));
file->connect("text_submitted", callable_mp(this, &EditorFileDialog::_file_submitted));
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 5f2e29b690..51629f2682 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -212,7 +212,7 @@ protected:
public:
void popup_file_dialog();
void clear_filters();
- void add_filter(const String &p_filter);
+ void add_filter(const String &p_filter, const String &p_description = "");
void set_enable_multiple_selection(bool p_enable);
Vector<String> get_selected_files() const;
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index adbba98897..1a105c7fe8 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -36,9 +36,11 @@
#include "core/io/resource_importer.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
+#include "core/object/worker_thread_pool.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_settings.h"
@@ -217,7 +219,7 @@ void EditorFileSystem::_scan_filesystem() {
String project = ProjectSettings::get_singleton()->get_resource_path();
- String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
+ String fscache = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
{
Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ);
@@ -287,7 +289,7 @@ void EditorFileSystem::_scan_filesystem() {
}
}
- String update_cache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4");
+ String update_cache = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4");
if (FileAccess::exists(update_cache)) {
{
@@ -330,7 +332,7 @@ void EditorFileSystem::_scan_filesystem() {
void EditorFileSystem::_save_filesystem_cache() {
group_file_cache.clear();
- String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
+ String fscache = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::WRITE);
ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + fscache + "'. Check user write permissions.");
@@ -872,7 +874,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc
fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path);
fi->modified_time = 0;
fi->import_modified_time = 0;
- fi->import_valid = ResourceLoader::is_import_valid(path);
+ fi->import_valid = fi->type == "TextFile" ? true : ResourceLoader::is_import_valid(path);
ItemAction ia;
ia.action = ItemAction::ACTION_FILE_TEST_REIMPORT;
@@ -1023,7 +1025,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
fi->type = "TextFile";
}
fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path);
- fi->import_valid = ResourceLoader::is_import_valid(path);
+ fi->import_valid = fi->type == "TextFile" ? true : ResourceLoader::is_import_valid(path);
fi->import_group_file = ResourceLoader::get_import_group_file(path);
{
@@ -1455,7 +1457,7 @@ EditorFileSystemDirectory *EditorFileSystem::get_filesystem_path(const String &p
void EditorFileSystem::_save_late_updated_files() {
//files that already existed, and were modified, need re-scanning for dependencies upon project restart. This is done via saving this special file
- String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4");
+ String fscache = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4");
Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::WRITE);
ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + fscache + "'. Check user write permissions.");
for (const String &E : late_update_files) {
@@ -2024,7 +2026,7 @@ void EditorFileSystem::_reimport_file(const String &p_file, const HashMap<String
fs->files[cpos]->deps = _get_dependencies(p_file);
fs->files[cpos]->type = importer->get_resource_type();
fs->files[cpos]->uid = uid;
- fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file);
+ fs->files[cpos]->import_valid = fs->files[cpos]->type == "TextFile" ? true : ResourceLoader::is_import_valid(p_file);
if (ResourceUID::get_singleton()->has_id(uid)) {
ResourceUID::get_singleton()->set_id(uid, p_file);
@@ -2137,7 +2139,7 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
data.reimport_from = from;
data.reimport_files = reimport_files.ptr();
- import_threads.begin_work(i - from + 1, this, &EditorFileSystem::_reimport_thread, &data);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &EditorFileSystem::_reimport_thread, &data, i - from + 1, -1, false, vformat(TTR("Import resources of type: %s"), reimport_files[from].importer));
int current_index = from - 1;
do {
if (current_index < data.max_index) {
@@ -2145,9 +2147,9 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
pr.step(reimport_files[current_index].path.get_file(), current_index);
}
OS::get_singleton()->delay_usec(1);
- } while (!import_threads.is_done_dispatching());
+ } while (!WorkerThreadPool::get_singleton()->is_group_task_completed(group_task));
- import_threads.end_work();
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
importer->import_threaded_end();
}
@@ -2430,12 +2432,10 @@ EditorFileSystem::EditorFileSystem() {
scan_total = 0;
update_script_classes_queued.clear();
- import_threads.init();
ResourceUID::get_singleton()->clear(); //will be updated on scan
ResourceSaver::set_get_resource_id_for_path(_resource_saver_get_resource_id_for_path);
}
EditorFileSystem::~EditorFileSystem() {
- import_threads.finish();
ResourceSaver::set_get_resource_id_for_path(nullptr);
}
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index 07b1132046..f4e69b95e7 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -36,7 +36,6 @@
#include "core/os/thread_safe.h"
#include "core/templates/hash_set.h"
#include "core/templates/safe_refcount.h"
-#include "core/templates/thread_work_pool.h"
#include "scene/main/node.h"
class FileAccess;
@@ -275,8 +274,6 @@ class EditorFileSystem : public Node {
HashSet<String> group_file_cache;
- ThreadWorkPool import_threads;
-
struct ImportThreadData {
const ImportFile *reimport_files;
int reimport_from;
diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp
index 8c508494c0..c1d6e505db 100644
--- a/editor/editor_folding.cpp
+++ b/editor/editor_folding.cpp
@@ -30,9 +30,10 @@
#include "editor_folding.h"
+#include "core/io/config_file.h"
#include "core/io/file_access.h"
#include "editor/editor_inspector.h"
-#include "editor/editor_settings.h"
+#include "editor/editor_paths.h"
Vector<String> EditorFolding::_get_unfolds(const Object *p_object) {
Vector<String> sections;
@@ -55,7 +56,7 @@ void EditorFolding::save_resource_folding(const Ref<Resource> &p_resource, const
config->set_value("folding", "sections_unfolded", unfolds);
String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg";
- file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file);
+ file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file);
config->save(file);
}
@@ -73,7 +74,7 @@ void EditorFolding::load_resource_folding(Ref<Resource> p_resource, const String
config.instantiate();
String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg";
- file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file);
+ file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file);
if (config->load(file) != OK) {
return;
@@ -149,7 +150,7 @@ void EditorFolding::save_scene_folding(const Node *p_scene, const String &p_path
config->set_value("folding", "nodes_folded", nodes_folded);
String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg";
- file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file);
+ file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file);
config->save(file);
}
@@ -157,9 +158,9 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) {
Ref<ConfigFile> config;
config.instantiate();
- String path = EditorSettings::get_singleton()->get_project_settings_dir();
+ String path = EditorPaths::get_singleton()->get_project_settings_dir();
String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg";
- file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file);
+ file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file);
if (config->load(file) != OK) {
return;
@@ -213,7 +214,7 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) {
bool EditorFolding::has_folding_data(const String &p_path) {
String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg";
- file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file);
+ file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(file);
return FileAccess::exists(file);
}
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 51d4d474c5..a02051c8ee 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");
@@ -287,7 +102,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
// - macOS doesn't use font hinting.
// - Windows uses ClearType, which is in between "Light" and "Normal" hinting.
// - Linux has configurable font hinting, but most distributions including Ubuntu default to "Light".
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
font_hinting = TextServer::HINTING_NONE;
#else
font_hinting = TextServer::HINTING_LIGHT;
@@ -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_fonts.h b/editor/editor_fonts.h
index e450af00da..c8b60b0198 100644
--- a/editor/editor_fonts.h
+++ b/editor/editor_fonts.h
@@ -35,4 +35,4 @@
void editor_register_fonts(Ref<Theme> p_theme);
-#endif
+#endif // EDITOR_FONTS_H
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 36360954d9..5c3038c468 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];
@@ -1601,6 +1718,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
List<String> tag_stack;
bool code_tag = false;
+ bool codeblock_tag = false;
int pos = 0;
while (pos < bbcode.length()) {
@@ -1612,7 +1730,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
if (brk_pos > pos) {
String text = bbcode.substr(pos, brk_pos - pos);
- if (!code_tag) {
+ if (!code_tag && !codeblock_tag) {
text = text.replace("\n", "\n\n");
}
p_rt->add_text(text);
@@ -1626,7 +1744,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
if (brk_end == -1) {
String text = bbcode.substr(brk_pos, bbcode.length() - brk_pos);
- if (!code_tag) {
+ if (!code_tag && !codeblock_tag) {
text = text.replace("\n", "\n\n");
}
p_rt->add_text(text);
@@ -1650,12 +1768,20 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
if (tag != "/img") {
p_rt->pop();
if (code_tag) {
+ // Pop both color and background color.
+ p_rt->pop();
+ p_rt->pop();
+ } else if (codeblock_tag) {
+ // Pop color, cell and table.
+ p_rt->pop();
+ p_rt->pop();
p_rt->pop();
}
}
code_tag = false;
+ codeblock_tag = false;
- } else if (code_tag) {
+ } else if (code_tag || codeblock_tag) {
p_rt->add_text("[");
pos = brk_pos + 1;
@@ -1664,24 +1790,32 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
const String link_tag = tag.substr(0, tag_end);
const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" ");
+ // Use monospace font with translucent colored background color to make clickable references
+ // easier to distinguish from inline code and other text.
p_rt->push_font(doc_code_font);
p_rt->push_color(link_color);
+ p_rt->push_bgcolor(code_color * Color(1, 1, 1, 0.15));
p_rt->push_meta("@" + link_tag + " " + link_target);
p_rt->add_text(link_target + (tag.begins_with("method ") ? "()" : ""));
p_rt->pop();
p_rt->pop();
p_rt->pop();
+ p_rt->pop();
pos = brk_end + 1;
} else if (doc->class_list.has(tag)) {
// Class reference tag such as [Node2D] or [SceneTree].
+ // Use monospace font with translucent colored background color to make clickable references
+ // easier to distinguish from inline code and other text.
p_rt->push_font(doc_code_font);
p_rt->push_color(link_color);
+ p_rt->push_bgcolor(code_color * Color(1, 1, 1, 0.15));
p_rt->push_meta("#" + tag);
p_rt->add_text(tag);
p_rt->pop();
p_rt->pop();
p_rt->pop();
+ p_rt->pop();
pos = brk_end + 1;
} else if (tag == "b") {
@@ -1694,16 +1828,31 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
p_rt->push_font(doc_italic_font);
pos = brk_end + 1;
tag_stack.push_front(tag);
- } else if (tag == "code" || tag == "codeblock") {
- // Use monospace font.
+ } else if (tag == "code") {
+ // Use monospace font with translucent background color to make code easier to distinguish from other text.
p_rt->push_font(doc_code_font);
+ p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15));
p_rt->push_color(code_color);
code_tag = true;
pos = brk_end + 1;
tag_stack.push_front(tag);
+ } else if (tag == "codeblock") {
+ // Use monospace font with translucent background color to make code easier to distinguish from other text.
+ // Use a single-column table with cell row background color instead of `[bgcolor]`.
+ // This makes the background color highlight cover the entire block, rather than individual lines.
+ p_rt->push_font(doc_code_font);
+ p_rt->push_table(1);
+ p_rt->push_cell();
+ p_rt->set_cell_row_background_color(Color(0.5, 0.5, 0.5, 0.15), Color(0.5, 0.5, 0.5, 0.15));
+ p_rt->set_cell_padding(Rect2(10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE));
+ p_rt->push_color(code_color);
+ codeblock_tag = true;
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
} else if (tag == "kbd") {
- // Use keyboard font with custom color.
+ // Use keyboard font with custom color and background color.
p_rt->push_font(doc_kbd_font);
+ p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15));
p_rt->push_color(kbd_color);
code_tag = true; // Though not strictly a code tag, logic is similar.
pos = brk_end + 1;
@@ -1940,7 +2089,7 @@ EditorHelp::EditorHelp() {
class_desc->connect("finished", callable_mp(this, &EditorHelp::_class_desc_finished));
class_desc->connect("meta_clicked", callable_mp(this, &EditorHelp::_class_desc_select));
class_desc->connect("gui_input", callable_mp(this, &EditorHelp::_class_desc_input));
- class_desc->connect("resized", callable_mp(this, &EditorHelp::_class_desc_resized), varray(false));
+ class_desc->connect("resized", callable_mp(this, &EditorHelp::_class_desc_resized).bind(false));
_class_desc_resized(false);
// Added second so it opens at the bottom so it won't offset the entire widget.
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_help_search.cpp b/editor/editor_help_search.cpp
index f454ba2c41..297d1226e3 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -34,6 +34,7 @@
#include "editor/editor_feature_profile.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
void EditorHelpSearch::_update_icons() {
search_box->set_right_icon(results_tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
@@ -185,7 +186,7 @@ EditorHelpSearch::EditorHelpSearch() {
set_title(TTR("Search Help"));
get_ok_button()->set_disabled(true);
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
// Split search and results area.
VBoxContainer *vbox = memnew(VBoxContainer);
@@ -250,7 +251,7 @@ EditorHelpSearch::EditorHelpSearch() {
results_tree->set_hide_root(true);
results_tree->set_select_mode(Tree::SELECT_ROW);
results_tree->connect("item_activated", callable_mp(this, &EditorHelpSearch::_confirmed));
- results_tree->connect("item_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled), varray(false));
+ results_tree->connect("item_selected", callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled).bind(false));
vbox->add_child(results_tree, true);
}
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 2bf0cd2f20..3b37adb830 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -39,6 +39,7 @@
#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/plugins/script_editor_plugin.h"
#include "multi_node_edit.h"
#include "scene/gui/center_container.h"
#include "scene/property_utils.h"
@@ -322,7 +323,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);
@@ -410,6 +411,10 @@ StringName EditorProperty::get_edited_property() const {
return property;
}
+void EditorProperty::set_doc_path(const String &p_doc_path) {
+ doc_path = p_doc_path;
+}
+
void EditorProperty::update_property() {
GDVIRTUAL_CALL(_update_property);
}
@@ -466,6 +471,9 @@ void EditorProperty::update_revert_and_pin_status() {
bool new_can_revert = EditorPropertyRevert::can_property_revert(object, property, &current) && !is_read_only();
if (new_can_revert != can_revert || new_pinned != pinned) {
+ if (new_can_revert != can_revert) {
+ emit_signal(SNAME("property_can_revert_changed"), property, new_can_revert);
+ }
can_revert = new_can_revert;
pinned = new_pinned;
update();
@@ -549,7 +557,7 @@ void EditorProperty::_focusable_focused(int p_index) {
}
void EditorProperty::add_focusable(Control *p_control) {
- p_control->connect("focus_entered", callable_mp(this, &EditorProperty::_focusable_focused), varray(focusables.size()));
+ p_control->connect("focus_entered", callable_mp(this, &EditorProperty::_focusable_focused).bind(focusables.size()));
focusables.push_back(p_control);
}
@@ -779,6 +787,9 @@ void EditorProperty::expand_all_folding() {
void EditorProperty::collapse_all_folding() {
}
+void EditorProperty::expand_revertable() {
+}
+
void EditorProperty::set_selectable(bool p_selectable) {
selectable = p_selectable;
}
@@ -906,6 +917,10 @@ void EditorProperty::menu_option(int p_option) {
emit_signal(SNAME("property_pinned"), property, !pinned);
update();
} break;
+ case MENU_OPEN_DOCUMENTATION: {
+ ScriptEditor::get_singleton()->goto_help(doc_path);
+ EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
+ } break;
}
}
@@ -957,6 +972,7 @@ void EditorProperty::_bind_methods() {
ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "checked")));
ADD_SIGNAL(MethodInfo("property_pinned", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "pinned")));
+ ADD_SIGNAL(MethodInfo("property_can_revert_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "can_revert")));
ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "focusable_idx")));
@@ -985,20 +1001,25 @@ void EditorProperty::_update_popup() {
add_child(menu);
menu->connect("id_pressed", callable_mp(this, &EditorProperty::menu_option));
}
- menu->add_shortcut(ED_GET_SHORTCUT("property_editor/copy_property"), MENU_COPY_PROPERTY);
- menu->add_shortcut(ED_GET_SHORTCUT("property_editor/paste_property"), MENU_PASTE_PROPERTY);
- menu->add_shortcut(ED_GET_SHORTCUT("property_editor/copy_property_path"), MENU_COPY_PROPERTY_PATH);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_GET_SHORTCUT("property_editor/copy_property"), MENU_COPY_PROPERTY);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_GET_SHORTCUT("property_editor/paste_property"), MENU_PASTE_PROPERTY);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("CopyNodePath"), SNAME("EditorIcons")), ED_GET_SHORTCUT("property_editor/copy_property_path"), MENU_COPY_PROPERTY_PATH);
menu->set_item_disabled(MENU_PASTE_PROPERTY, is_read_only());
if (!pin_hidden) {
menu->add_separator();
if (can_pin) {
- menu->add_check_item(TTR("Pin value"), MENU_PIN_VALUE);
+ menu->add_icon_check_item(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")), TTR("Pin Value"), MENU_PIN_VALUE);
menu->set_item_checked(menu->get_item_index(MENU_PIN_VALUE), pinned);
- menu->set_item_tooltip(menu->get_item_index(MENU_PIN_VALUE), TTR("Pinning a value forces it to be saved even if it's equal to the default."));
} else {
- menu->add_check_item(vformat(TTR("Pin value [Disabled because '%s' is editor-only]"), property), MENU_PIN_VALUE);
+ menu->add_icon_check_item(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")), vformat(TTR("Pin Value [Disabled because '%s' is editor-only]"), property), MENU_PIN_VALUE);
menu->set_item_disabled(menu->get_item_index(MENU_PIN_VALUE), true);
}
+ menu->set_item_tooltip(menu->get_item_index(MENU_PIN_VALUE), TTR("Pinning a value forces it to be saved even if it's equal to the default."));
+ }
+
+ if (!doc_path.is_empty()) {
+ menu->add_separator();
+ menu->add_icon_item(get_theme_icon(SNAME("Help"), SNAME("EditorIcons")), TTR("Open Documentation"), MENU_OPEN_DOCUMENTATION);
}
}
@@ -1087,7 +1108,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();
}
@@ -1211,12 +1232,15 @@ void EditorInspectorSection::_notification(int p_what) {
// Get the section header font.
Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
+ Color font_color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
// Get the right direction arrow texture, if the section is foldable.
Ref<Texture2D> arrow;
+ bool folded = foldable;
if (foldable) {
if (object->editor_is_section_unfolded(section)) {
arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree"));
+ folded = false;
} else {
if (is_layout_rtl()) {
arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree"));
@@ -1260,28 +1284,71 @@ void EditorInspectorSection::_notification(int p_what) {
}
draw_rect(header_rect, c);
- // Draw header title and folding arrow.
- const int arrow_margin = 2;
- const int arrow_width = arrow.is_valid() ? arrow->get_width() : 0;
- Color color = get_theme_color(SNAME("font_color"));
- float text_width = get_size().width - Math::round(arrow_width + arrow_margin * EDSCALE) - section_indent;
- Point2 text_offset = Point2(0, font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2);
- HorizontalAlignment text_align = HORIZONTAL_ALIGNMENT_LEFT;
- if (rtl) {
- text_align = HORIZONTAL_ALIGNMENT_RIGHT;
- } else {
- text_offset.x = section_indent + Math::round(arrow_width + arrow_margin * EDSCALE);
- }
- draw_string(font, text_offset.floor(), label, text_align, text_width, font_size, color);
+ // Draw header title, folding arrow and coutn of revertable properties.
+ {
+ int separation = Math::round(2 * EDSCALE);
- if (arrow.is_valid()) {
- Point2 arrow_position = Point2(0, (header_height - arrow->get_height()) / 2);
+ int margin_start = section_indent + separation;
+ int margin_end = separation;
+
+ // - Arrow.
+ if (arrow.is_valid()) {
+ Point2 arrow_position;
+ if (rtl) {
+ arrow_position.x = get_size().width - (margin_start + arrow->get_width());
+ } else {
+ arrow_position.x = margin_start;
+ }
+ arrow_position.y = (header_height - arrow->get_height()) / 2;
+ draw_texture(arrow, arrow_position);
+ margin_start += arrow->get_width();
+ }
+
+ int available = get_size().width - (margin_start + margin_end);
+
+ // - Count of revertable properties.
+ String num_revertable_str;
+ int num_revertable_width = 0;
+ if (folded && revertable_properties.size()) {
+ int label_width = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, available, font_size, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS).x;
+
+ Ref<Font> light_font = get_theme_font(SNAME("main"), SNAME("EditorFonts"));
+ int light_font_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts"));
+ Color light_font_color = get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"));
+
+ // Can we fit the long version of the revertable count text?
+ if (revertable_properties.size() == 1) {
+ num_revertable_str = "(1 change)";
+ } else {
+ num_revertable_str = vformat("(%d changes)", revertable_properties.size());
+ }
+ num_revertable_width = light_font->get_string_size(num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, TextServer::JUSTIFICATION_NONE).x;
+ if (label_width + separation + num_revertable_width > available) {
+ // We'll have to use the short version.
+ num_revertable_str = vformat("(%d)", revertable_properties.size());
+ num_revertable_width = light_font->get_string_size(num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, TextServer::JUSTIFICATION_NONE).x;
+ }
+
+ Point2 text_offset = Point2(
+ margin_end,
+ light_font->get_ascent(light_font_size) + (header_height - light_font->get_height(light_font_size)) / 2);
+ if (!rtl) {
+ text_offset.x = get_size().width - (text_offset.x + num_revertable_width);
+ }
+ draw_string(light_font, text_offset, num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, light_font_color, TextServer::JUSTIFICATION_NONE);
+ margin_end += num_revertable_width + separation;
+ available -= num_revertable_width + separation;
+ }
+
+ // - Label.
+ Point2 text_offset = Point2(
+ margin_start,
+ font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2);
if (rtl) {
- arrow_position.x = get_size().width - section_indent - arrow->get_width() - Math::round(arrow_margin * EDSCALE);
- } else {
- arrow_position.x = section_indent + Math::round(arrow_margin * EDSCALE);
+ text_offset.x = margin_end;
}
- draw_texture(arrow, arrow_position.floor());
+ HorizontalAlignment text_align = rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT;
+ draw_string(font, text_offset, label, text_align, available, font_size, font_color, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
}
// Draw dropping highlight.
@@ -1457,6 +1524,22 @@ void EditorInspectorSection::fold() {
update();
}
+bool EditorInspectorSection::has_revertable_properties() const {
+ return !revertable_properties.is_empty();
+}
+
+void EditorInspectorSection::property_can_revert_changed(const String &p_path, bool p_can_revert) {
+ bool had_revertable_properties = has_revertable_properties();
+ if (p_can_revert) {
+ revertable_properties.insert(p_path);
+ } else {
+ revertable_properties.erase(p_path);
+ }
+ if (has_revertable_properties() != had_revertable_properties) {
+ update();
+ }
+}
+
void EditorInspectorSection::_bind_methods() {
ClassDB::bind_method(D_METHOD("setup", "section", "label", "object", "bg_color", "foldable"), &EditorInspectorSection::setup);
ClassDB::bind_method(D_METHOD("get_vbox"), &EditorInspectorSection::get_vbox);
@@ -1594,7 +1677,7 @@ void EditorInspectorArray::_panel_gui_input(Ref<InputEvent> p_event, int p_index
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == MouseButton::RIGHT) {
+ if (movable && mb->get_button_index() == MouseButton::RIGHT) {
popup_array_index_pressed = begin_array_index + p_index;
rmb_popup->set_item_disabled(OPTION_MOVE_UP, popup_array_index_pressed == 0);
rmb_popup->set_item_disabled(OPTION_MOVE_DOWN, popup_array_index_pressed == count - 1);
@@ -1623,49 +1706,118 @@ void EditorInspectorArray::_move_element(int p_element_index, int p_to_pos) {
const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] };
Variant return_value;
Callable::CallError call_error;
- move_function.call(args_p, 5, return_value, call_error);
+ move_function.callp(args_p, 5, return_value, call_error);
} else {
WARN_PRINT(vformat("Could not find a function to move arrays elements for class %s. Register a move element function using EditorData::add_move_array_element_function", object->get_class_name()));
}
} else if (mode == MODE_USE_COUNT_PROPERTY) {
ERR_FAIL_COND(p_to_pos < -1 || p_to_pos > count);
- List<PropertyInfo> object_property_list;
- object->get_property_list(&object_property_list);
- Array properties_as_array = _extract_properties_as_array(object_property_list);
- properties_as_array.resize(count);
+ if (!swap_method.is_empty()) {
+ ERR_FAIL_COND(!object->has_method(swap_method));
- // For undoing things
- undo_redo->add_undo_property(object, count_property, properties_as_array.size());
- for (int i = 0; i < (int)properties_as_array.size(); i++) {
- Dictionary d = Dictionary(properties_as_array[i]);
- Array keys = d.keys();
- for (int j = 0; j < keys.size(); j++) {
- String key = keys[j];
- undo_redo->add_undo_property(object, vformat(key, i), d[key]);
- }
- }
+ // Swap method was provided, use it.
+ if (p_element_index < 0) {
+ // Add an element at position
+ undo_redo->add_do_property(object, count_property, count + 1);
+ if (p_to_pos >= 0) {
+ for (int i = count; i > p_to_pos; i--) {
+ undo_redo->add_do_method(object, swap_method, i, i - 1);
+ }
+ for (int i = p_to_pos; i < count; i++) {
+ undo_redo->add_undo_method(object, swap_method, i, i + 1);
+ }
+ }
+ undo_redo->add_undo_property(object, count_property, count);
- if (p_element_index < 0) {
- // Add an element.
- properties_as_array.insert(p_to_pos < 0 ? properties_as_array.size() : p_to_pos, Dictionary());
- } else if (p_to_pos < 0) {
- // Delete the element.
- properties_as_array.remove_at(p_element_index);
+ } else if (p_to_pos < 0) {
+ if (count > 0) {
+ // Remove element at position
+ undo_redo->add_undo_property(object, count_property, count);
+
+ List<PropertyInfo> object_property_list;
+ object->get_property_list(&object_property_list);
+
+ for (int i = p_element_index; i < count - 1; i++) {
+ undo_redo->add_do_method(object, swap_method, i, i + 1);
+ }
+
+ for (int i = count; i > p_element_index; i--) {
+ undo_redo->add_undo_method(object, swap_method, i, i - 1);
+ }
+
+ String erase_prefix = String(array_element_prefix) + itos(p_element_index);
+
+ for (const PropertyInfo &E : object_property_list) {
+ if (E.name.begins_with(erase_prefix)) {
+ undo_redo->add_undo_property(object, E.name, object->get(E.name));
+ }
+ }
+
+ undo_redo->add_do_property(object, count_property, count - 1);
+ }
+ } else {
+ if (p_to_pos > p_element_index) {
+ p_to_pos--;
+ }
+
+ if (p_to_pos < p_element_index) {
+ for (int i = p_element_index; i > p_to_pos; i--) {
+ undo_redo->add_do_method(object, swap_method, i, i - 1);
+ }
+ for (int i = p_to_pos; i < p_element_index; i++) {
+ undo_redo->add_undo_method(object, swap_method, i, i + 1);
+ }
+ } else if (p_to_pos > p_element_index) {
+ for (int i = p_element_index; i < p_to_pos; i++) {
+ undo_redo->add_do_method(object, swap_method, i, i + 1);
+ }
+
+ for (int i = p_to_pos; i > p_element_index; i--) {
+ undo_redo->add_undo_method(object, swap_method, i, i - 1);
+ }
+ }
+ }
} else {
- // Move the element.
- properties_as_array.insert(p_to_pos, properties_as_array[p_element_index].duplicate());
- properties_as_array.remove_at(p_to_pos < p_element_index ? p_element_index + 1 : p_element_index);
- }
+ // Use standard properties.
+ List<PropertyInfo> object_property_list;
+ object->get_property_list(&object_property_list);
- // Change the array size then set the properties.
- undo_redo->add_do_property(object, count_property, properties_as_array.size());
- for (int i = 0; i < (int)properties_as_array.size(); i++) {
- Dictionary d = properties_as_array[i];
- Array keys = d.keys();
- for (int j = 0; j < keys.size(); j++) {
- String key = keys[j];
- undo_redo->add_do_property(object, vformat(key, i), d[key]);
+ Array properties_as_array = _extract_properties_as_array(object_property_list);
+ properties_as_array.resize(count);
+
+ // For undoing things
+ undo_redo->add_undo_property(object, count_property, properties_as_array.size());
+ for (int i = 0; i < (int)properties_as_array.size(); i++) {
+ Dictionary d = Dictionary(properties_as_array[i]);
+ Array keys = d.keys();
+ for (int j = 0; j < keys.size(); j++) {
+ String key = keys[j];
+ undo_redo->add_undo_property(object, vformat(key, i), d[key]);
+ }
+ }
+
+ if (p_element_index < 0) {
+ // Add an element.
+ properties_as_array.insert(p_to_pos < 0 ? properties_as_array.size() : p_to_pos, Dictionary());
+ } else if (p_to_pos < 0) {
+ // Delete the element.
+ properties_as_array.remove_at(p_element_index);
+ } else {
+ // Move the element.
+ properties_as_array.insert(p_to_pos, properties_as_array[p_element_index].duplicate());
+ properties_as_array.remove_at(p_to_pos < p_element_index ? p_element_index + 1 : p_element_index);
+ }
+
+ // Change the array size then set the properties.
+ undo_redo->add_do_property(object, count_property, properties_as_array.size());
+ for (int i = 0; i < (int)properties_as_array.size(); i++) {
+ Dictionary d = properties_as_array[i];
+ Array keys = d.keys();
+ for (int j = 0; j < keys.size(); j++) {
+ String key = keys[j];
+ undo_redo->add_do_property(object, vformat(key, i), d[key]);
+ }
}
}
}
@@ -1698,7 +1850,7 @@ void EditorInspectorArray::_clear_array() {
const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] };
Variant return_value;
Callable::CallError call_error;
- move_function.call(args_p, 5, return_value, call_error);
+ move_function.callp(args_p, 5, return_value, call_error);
} else {
WARN_PRINT(vformat("Could not find a function to move arrays elements for class %s. Register a move element function using EditorData::add_move_array_element_function", object->get_class_name()));
}
@@ -1751,7 +1903,7 @@ void EditorInspectorArray::_resize_array(int p_size) {
const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] };
Variant return_value;
Callable::CallError call_error;
- move_function.call(args_p, 5, return_value, call_error);
+ move_function.callp(args_p, 5, return_value, call_error);
} else {
WARN_PRINT(vformat("Could not find a function to move arrays elements for class %s. Register a move element function using EditorData::add_move_array_element_function", object->get_class_name()));
}
@@ -1770,7 +1922,7 @@ void EditorInspectorArray::_resize_array(int p_size) {
const Variant *args_p[] = { &args[0], &args[1], &args[2], &args[3], &args[4] };
Variant return_value;
Callable::CallError call_error;
- move_function.call(args_p, 5, return_value, call_error);
+ move_function.callp(args_p, 5, return_value, call_error);
} else {
WARN_PRINT(vformat("Could not find a function to move arrays elements for class %s. Register a move element function using EditorData::add_move_array_element_function", object->get_class_name()));
}
@@ -1905,6 +2057,20 @@ void EditorInspectorArray::_setup() {
page = CLAMP(page, 0, max_page);
}
+ Ref<Font> numbers_font;
+ int numbers_min_w = 0;
+
+ if (numbered) {
+ numbers_font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int digits_found = count;
+ String test;
+ while (digits_found) {
+ test += "8";
+ digits_found /= 10;
+ }
+ numbers_min_w = numbers_font->get_string_size(test).width;
+ }
+
for (int i = 0; i < (int)array_elements.size(); i++) {
ArrayElement &ae = array_elements[i];
@@ -1917,8 +2083,8 @@ void EditorInspectorArray::_setup() {
ae.panel->set_tooltip(vformat(TTR("Element %d: %s%d*"), i, array_element_prefix, i));
ae.panel->connect("focus_entered", callable_mp((CanvasItem *)ae.panel, &PanelContainer::update));
ae.panel->connect("focus_exited", callable_mp((CanvasItem *)ae.panel, &PanelContainer::update));
- ae.panel->connect("draw", callable_bind(callable_mp(this, &EditorInspectorArray::_panel_draw), i));
- ae.panel->connect("gui_input", callable_bind(callable_mp(this, &EditorInspectorArray::_panel_gui_input), i));
+ ae.panel->connect("draw", callable_mp(this, &EditorInspectorArray::_panel_draw).bind(i));
+ ae.panel->connect("gui_input", callable_mp(this, &EditorInspectorArray::_panel_gui_input).bind(i));
ae.panel->add_theme_style_override(SNAME("panel"), i % 2 ? odd_style : even_style);
elements_vbox->add_child(ae.panel);
@@ -1939,19 +2105,38 @@ void EditorInspectorArray::_setup() {
ae.margin->add_child(ae.hbox);
// Move button.
- ae.move_texture_rect = memnew(TextureRect);
- ae.move_texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
- ae.move_texture_rect->set_default_cursor_shape(Control::CURSOR_MOVE);
- if (is_inside_tree()) {
- ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons")));
+ if (movable) {
+ ae.move_texture_rect = memnew(TextureRect);
+ ae.move_texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+ ae.move_texture_rect->set_default_cursor_shape(Control::CURSOR_MOVE);
+
+ if (is_inside_tree()) {
+ ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons")));
+ }
+ ae.hbox->add_child(ae.move_texture_rect);
+ }
+
+ if (numbered) {
+ ae.number = memnew(Label);
+ ae.number->add_theme_font_override("font", numbers_font);
+ ae.number->set_custom_minimum_size(Size2(numbers_min_w, 0));
+ ae.number->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
+ ae.number->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
+ ae.number->set_text(itos(begin_array_index + i));
+ ae.hbox->add_child(ae.number);
}
- ae.hbox->add_child(ae.move_texture_rect);
// Right vbox.
ae.vbox = memnew(VBoxContainer);
ae.vbox->set_h_size_flags(SIZE_EXPAND_FILL);
ae.vbox->set_v_size_flags(SIZE_EXPAND_FILL);
ae.hbox->add_child(ae.vbox);
+
+ ae.erase = memnew(Button);
+ ae.erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ ae.erase->set_v_size_flags(SIZE_SHRINK_CENTER);
+ ae.erase->connect("pressed", callable_mp(this, &EditorInspectorArray::_remove_item).bind(begin_array_index + i));
+ ae.hbox->add_child(ae.erase);
}
// Hide/show the add button.
@@ -1966,7 +2151,14 @@ void EditorInspectorArray::_setup() {
}
}
+void EditorInspectorArray::_remove_item(int p_index) {
+ _move_element(p_index, -1);
+}
+
Variant EditorInspectorArray::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+ if (!movable) {
+ return Variant();
+ }
int index = p_from->get_meta("index");
Dictionary dict;
dict["type"] = "property_array_element";
@@ -1988,6 +2180,9 @@ void EditorInspectorArray::drop_data_fw(const Point2 &p_point, const Variant &p_
}
bool EditorInspectorArray::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+ if (!movable) {
+ return false;
+ }
// First, update drawing.
control_dropping->update();
@@ -2012,18 +2207,24 @@ void EditorInspectorArray::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
Color color = get_theme_color(SNAME("dark_color_1"), SNAME("Editor"));
- odd_style->set_bg_color(color.lightened(0.15));
- even_style->set_bg_color(color.darkened(0.15));
+ odd_style->set_bg_color(color.darkened(-0.08));
+ even_style->set_bg_color(color.darkened(0.08));
for (int i = 0; i < (int)array_elements.size(); i++) {
ArrayElement &ae = array_elements[i];
- ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons")));
+ if (ae.move_texture_rect) {
+ ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons")));
+ }
Size2 min_size = get_theme_stylebox(SNAME("Focus"), SNAME("EditorStyles"))->get_minimum_size();
ae.margin->add_theme_constant_override("margin_left", min_size.x / 2);
ae.margin->add_theme_constant_override("margin_top", min_size.y / 2);
ae.margin->add_theme_constant_override("margin_right", min_size.x / 2);
ae.margin->add_theme_constant_override("margin_bottom", min_size.y / 2);
+
+ if (ae.erase) {
+ ae.erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ }
}
add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
@@ -2059,23 +2260,31 @@ void EditorInspectorArray::set_undo_redo(UndoRedo *p_undo_redo) {
undo_redo = p_undo_redo;
}
-void EditorInspectorArray::setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable) {
+void EditorInspectorArray::setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable, bool p_numbered, int p_page_length, const String &p_add_item_text) {
count_property = "";
mode = MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION;
array_element_prefix = p_array_element_prefix;
page = p_page;
+ movable = p_movable;
+ page_length = p_page_length;
+ numbered = p_numbered;
EditorInspectorSection::setup(String(p_array_element_prefix) + "_array", p_label, p_object, p_bg_color, p_foldable, 0);
_setup();
}
-void EditorInspectorArray::setup_with_count_property(Object *p_object, String p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable) {
+void EditorInspectorArray::setup_with_count_property(Object *p_object, String p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable, bool p_numbered, int p_page_length, const String &p_add_item_text, const String &p_swap_method) {
count_property = p_count_property;
mode = MODE_USE_COUNT_PROPERTY;
array_element_prefix = p_array_element_prefix;
page = p_page;
+ movable = p_movable;
+ page_length = p_page_length;
+ numbered = p_numbered;
+ swap_method = p_swap_method;
+ add_button->set_text(p_add_item_text);
EditorInspectorSection::setup(String(count_property) + "_array", p_label, p_object, p_bg_color, p_foldable, 0);
_setup();
@@ -2316,7 +2525,7 @@ String EditorInspector::get_selected_path() const {
return property_selected;
}
-void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped) {
+void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped) {
for (const EditorInspectorPlugin::AddedEditor &F : ped->added_editors) {
EditorProperty *ep = Object::cast_to<EditorProperty>(F.property_editor);
current_vbox->add_child(F.property_editor);
@@ -2325,14 +2534,14 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
ep->object = object;
ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed));
ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed));
- ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), varray(), CONNECT_DEFERRED);
+ ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), CONNECT_DEFERRED);
ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value));
ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked));
ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned));
ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected));
ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed));
- ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), varray(), CONNECT_DEFERRED);
- ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), varray(), CONNECT_DEFERRED);
+ ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), CONNECT_DEFERRED);
+ ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), CONNECT_DEFERRED);
if (F.properties.size()) {
if (F.properties.size() == 1) {
@@ -2356,6 +2565,10 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
}
}
+ if (p_section) {
+ ep->connect("property_can_revert_changed", callable_mp(p_section, &EditorInspectorSection::property_can_revert_changed));
+ }
+
ep->set_read_only(read_only);
ep->update_property();
ep->_update_pin_flags();
@@ -2452,7 +2665,6 @@ void EditorInspector::update_tree() {
List<PropertyInfo> plist;
object->get_property_list(&plist, true);
- _update_script_class_properties(*object, plist);
HashMap<VBoxContainer *, HashMap<String, VBoxContainer *>> vbox_per_path;
HashMap<String, EditorInspectorArray *> editor_inspector_array_per_prefix;
@@ -2462,9 +2674,11 @@ void EditorInspector::update_tree() {
// Get the lists of editors to add the beginning.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_begin(object);
- _parse_added_editors(main_vbox, ped);
+ _parse_added_editors(main_vbox, nullptr, ped);
}
+ StringName type_name;
+
// Get the lists of editors for properties.
for (List<PropertyInfo>::Element *E_property = plist.front(); E_property; E_property = E_property->next()) {
PropertyInfo &p = E_property->get();
@@ -2535,17 +2749,24 @@ void EditorInspector::update_tree() {
category_vbox = nullptr; //reset
String type = p.name;
+ String label = p.name;
+ type_name = p.name;
// Set the category icon.
if (!ClassDB::class_exists(type) && !ScriptServer::is_global_class(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) {
// If we have a category inside a script, search for the first script with a valid icon.
Ref<Script> script = ResourceLoader::load(p.hint_string, "Script");
StringName base_type;
+ StringName name;
if (script.is_valid()) {
base_type = script->get_instance_base_type();
+ name = EditorNode::get_editor_data().script_class_get_name(script->get_path());
+ if (name != StringName() && label != name) {
+ label = name;
+ }
}
while (script.is_valid()) {
- StringName name = EditorNode::get_editor_data().script_class_get_name(script->get_path());
+ name = EditorNode::get_editor_data().script_class_get_name(script->get_path());
String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name);
if (name != StringName() && icon_path.length()) {
category->icon = ResourceLoader::load(icon_path, "Texture");
@@ -2564,28 +2785,27 @@ void EditorInspector::update_tree() {
}
// Set the category label.
- category->label = type;
+ category->label = label;
if (use_doc_hints) {
// Sets the category tooltip to show documentation.
- StringName type2 = p.name;
- if (!class_descr_cache.has(type2)) {
+ if (!class_descr_cache.has(type_name)) {
String descr;
DocTools *dd = EditorHelp::get_doc_data();
- HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(type2);
+ HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(type_name);
if (E) {
descr = DTR(E->value.brief_description);
}
- class_descr_cache[type2] = descr;
+ class_descr_cache[type_name] = descr;
}
- category->set_tooltip(p.name + "::" + (class_descr_cache[type2].is_empty() ? "" : class_descr_cache[type2]));
+ category->set_tooltip(p.name + "::" + (class_descr_cache[type_name].is_empty() ? "" : class_descr_cache[type_name]));
}
// Add editors at the start of a category.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_category(object, p.name);
- _parse_added_editors(main_vbox, ped);
+ _parse_added_editors(main_vbox, nullptr, ped);
}
continue;
@@ -2777,7 +2997,7 @@ void EditorInspector::update_tree() {
// Add editors at the start of a group.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_group(object, path);
- _parse_added_editors(section->get_vbox(), ped);
+ _parse_added_editors(section->get_vbox(), section, ped);
}
vbox_per_path[root_vbox][acc_path] = section->get_vbox();
@@ -2798,26 +3018,52 @@ void EditorInspector::update_tree() {
StringName array_element_prefix;
Color c = sscolor;
c.a /= level;
+
+ Vector<String> class_name_components = String(p.class_name).split(",");
+
+ int page_size = 5;
+ bool movable = true;
+ bool numbered = false;
+ bool foldable = use_folding;
+ String add_button_text;
+ String swap_method;
+ for (int i = (p.type == Variant::NIL ? 1 : 2); i < class_name_components.size(); i++) {
+ if (class_name_components[i].begins_with("page_size") && class_name_components[i].get_slice_count("=") == 2) {
+ page_size = class_name_components[i].get_slice("=", 1).to_int();
+ } else if (class_name_components[i].begins_with("add_button_text") && class_name_components[i].get_slice_count("=") == 2) {
+ add_button_text = class_name_components[i].get_slice("=", 1).strip_edges();
+ } else if (class_name_components[i] == "static") {
+ movable = false;
+ } else if (class_name_components[i] == "numbered") {
+ numbered = true;
+ } else if (class_name_components[i] == "unfoldable") {
+ foldable = false;
+ } else if (class_name_components[i].begins_with("swap_method") && class_name_components[i].get_slice_count("=") == 2) {
+ swap_method = class_name_components[i].get_slice("=", 1).strip_edges();
+ }
+ }
+
if (p.type == Variant::NIL) {
// Setup the array to use a method to create/move/delete elements.
- array_element_prefix = p.class_name;
+ array_element_prefix = class_name_components[0];
editor_inspector_array = memnew(EditorInspectorArray);
String array_label = path.contains("/") ? path.substr(path.rfind("/") + 1) : path;
array_label = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string, property_name_style);
int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0;
editor_inspector_array->setup_with_move_element_function(object, array_label, array_element_prefix, page, c, use_folding);
- editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request), varray(array_element_prefix));
+ editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request).bind(array_element_prefix));
editor_inspector_array->set_undo_redo(undo_redo);
} else if (p.type == Variant::INT) {
// Setup the array to use the count property and built-in functions to create/move/delete elements.
- Vector<String> class_name_components = String(p.class_name).split(",");
- if (class_name_components.size() == 2) {
+ if (class_name_components.size() >= 2) {
array_element_prefix = class_name_components[1];
editor_inspector_array = memnew(EditorInspectorArray);
int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0;
- editor_inspector_array->setup_with_count_property(object, class_name_components[0], p.name, array_element_prefix, page, c, use_folding);
- editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request), varray(array_element_prefix));
+
+ editor_inspector_array->setup_with_count_property(object, class_name_components[0], p.name, array_element_prefix, page, c, foldable, movable, numbered, page_size, add_button_text, swap_method);
+ editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request).bind(array_element_prefix));
+
editor_inspector_array->set_undo_redo(undo_redo);
}
}
@@ -2826,6 +3072,7 @@ void EditorInspector::update_tree() {
current_vbox->add_child(editor_inspector_array);
editor_inspector_array_per_prefix[array_element_prefix] = editor_inspector_array;
}
+
continue;
}
@@ -2844,28 +3091,27 @@ void EditorInspector::update_tree() {
restart_request_props.insert(p.name);
}
- String doc_hint;
+ PropertyDocInfo doc_info;
if (use_doc_hints) {
// Build the doc hint, to use as tooltip.
// Get the class name.
- StringName classname = object->get_class_name();
+ StringName classname = type_name == "" ? object->get_class_name() : type_name;
if (!object_class.is_empty()) {
classname = object_class;
}
StringName propname = property_prefix + p.name;
- String descr;
bool found = false;
// Search for the property description in the cache.
- HashMap<StringName, HashMap<StringName, String>>::Iterator E = descr_cache.find(classname);
+ HashMap<StringName, HashMap<StringName, PropertyDocInfo>>::Iterator E = doc_info_cache.find(classname);
if (E) {
- HashMap<StringName, String>::Iterator F = E->value.find(propname);
+ HashMap<StringName, PropertyDocInfo>::Iterator F = E->value.find(propname);
if (F) {
found = true;
- descr = F->value;
+ doc_info = F->value;
}
}
@@ -2873,10 +3119,11 @@ void EditorInspector::update_tree() {
// Build the property description String and add it to the cache.
DocTools *dd = EditorHelp::get_doc_data();
HashMap<String, DocData::ClassDoc>::Iterator F = dd->class_list.find(classname);
- while (F && descr.is_empty()) {
+ while (F && doc_info.description.is_empty()) {
for (int i = 0; i < F->value.properties.size(); i++) {
if (F->value.properties[i].name == propname.operator String()) {
- descr = DTR(F->value.properties[i].description);
+ doc_info.description = DTR(F->value.properties[i].description);
+ doc_info.path = "class_property:" + F->value.name + ":" + F->value.properties[i].name;
break;
}
}
@@ -2885,7 +3132,8 @@ void EditorInspector::update_tree() {
if (slices.size() == 2 && slices[0].begins_with("theme_override_")) {
for (int i = 0; i < F->value.theme_properties.size(); i++) {
if (F->value.theme_properties[i].name == slices[1]) {
- descr = DTR(F->value.theme_properties[i].description);
+ doc_info.description = DTR(F->value.theme_properties[i].description);
+ doc_info.path = "class_theme_item:" + F->value.name + ":" + F->value.theme_properties[i].name;
break;
}
}
@@ -2897,10 +3145,9 @@ void EditorInspector::update_tree() {
break;
}
}
- descr_cache[classname][propname] = descr;
- }
- doc_hint = descr;
+ doc_info_cache[classname][propname] = doc_info;
+ }
}
Vector<EditorInspectorPlugin::AddedEditor> editors;
@@ -2959,6 +3206,12 @@ void EditorInspector::update_tree() {
editor_property_map[prop].push_back(ep);
}
}
+
+ EditorInspectorSection *section = Object::cast_to<EditorInspectorSection>(current_vbox->get_parent());
+ if (section) {
+ ep->connect("property_can_revert_changed", callable_mp(section, &EditorInspectorSection::property_can_revert_changed));
+ }
+
ep->set_draw_warning(draw_warning);
ep->set_use_folding(use_folding);
ep->set_checkable(checkable);
@@ -2973,21 +3226,22 @@ void EditorInspector::update_tree() {
if (ep) {
// Eventually, set other properties/signals after the property editor got added to the tree.
bool update_all = (p.usage & PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED);
- ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed), varray(update_all));
+ ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed).bind(update_all));
ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed));
- ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), varray(), CONNECT_DEFERRED);
+ ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), CONNECT_DEFERRED);
ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value));
ep->connect("property_checked", callable_mp(this, &EditorInspector::_property_checked));
ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned));
ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected));
ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed));
- ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), varray(), CONNECT_DEFERRED);
- ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), varray(), CONNECT_DEFERRED);
- if (!doc_hint.is_empty()) {
- ep->set_tooltip(property_prefix + p.name + "::" + doc_hint);
+ ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), CONNECT_DEFERRED);
+ ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), CONNECT_DEFERRED);
+ if (!doc_info.description.is_empty()) {
+ ep->set_tooltip(property_prefix + p.name + "::" + doc_info.description);
} else {
ep->set_tooltip(property_prefix + p.name);
}
+ ep->set_doc_path(doc_info.path);
ep->update_property();
ep->_update_pin_flags();
ep->update_revert_and_pin_status();
@@ -3001,6 +3255,11 @@ void EditorInspector::update_tree() {
}
if (!hide_metadata) {
+ // Add 4px of spacing between the "Add Metadata" button and the content above it.
+ Control *spacer = memnew(Control);
+ spacer->set_custom_minimum_size(Size2(0, 4) * EDSCALE);
+ main_vbox->add_child(spacer);
+
Button *add_md = EditorInspector::create_inspector_action_button(TTR("Add Metadata"));
add_md->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
add_md->connect(SNAME("pressed"), callable_mp(this, &EditorInspector::_show_add_meta_dialog));
@@ -3010,7 +3269,7 @@ void EditorInspector::update_tree() {
// Get the lists of to add at the end.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_end(object);
- _parse_added_editors(main_vbox, ped);
+ _parse_added_editors(main_vbox, nullptr, ped);
}
}
@@ -3163,6 +3422,44 @@ void EditorInspector::expand_all_folding() {
}
}
+void EditorInspector::expand_revertable() {
+ HashSet<EditorInspectorSection *> sections_to_unfold[2];
+ for (EditorInspectorSection *E : sections) {
+ if (E->has_revertable_properties()) {
+ sections_to_unfold[0].insert(E);
+ }
+ }
+
+ // Climb up the hierachy doing double buffering with the sets.
+ int a = 0;
+ int b = 1;
+ while (sections_to_unfold[a].size()) {
+ for (EditorInspectorSection *E : sections_to_unfold[a]) {
+ E->unfold();
+
+ Node *n = E->get_parent();
+ while (n) {
+ if (Object::cast_to<EditorInspector>(n)) {
+ break;
+ }
+ if (Object::cast_to<EditorInspectorSection>(n) && !sections_to_unfold[a].has((EditorInspectorSection *)n)) {
+ sections_to_unfold[b].insert((EditorInspectorSection *)n);
+ }
+ n = n->get_parent();
+ }
+ }
+
+ sections_to_unfold[a].clear();
+ SWAP(a, b);
+ }
+
+ for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) {
+ for (EditorProperty *E : F.value) {
+ E->expand_revertable();
+ }
+ }
+}
+
void EditorInspector::set_scroll_offset(int p_offset) {
set_v_scroll(p_offset);
}
@@ -3262,14 +3559,23 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
undo_redo->add_undo_property(object, p_name, value);
}
- PropertyInfo prop_info;
- if (ClassDB::get_property_info(object->get_class_name(), p_name, &prop_info)) {
- for (const String &linked_prop : prop_info.linked_properties) {
- valid = false;
- value = object->get(linked_prop, &valid);
- if (valid) {
- undo_redo->add_undo_property(object, linked_prop, value);
- }
+ List<StringName> linked_properties;
+ ClassDB::get_linked_properties_info(object->get_class_name(), p_name, &linked_properties);
+
+ for (const StringName &linked_prop : linked_properties) {
+ valid = false;
+ Variant undo_value = object->get(linked_prop, &valid);
+ if (valid) {
+ undo_redo->add_undo_property(object, linked_prop, undo_value);
+ }
+ }
+
+ PackedStringArray linked_properties_dynamic = object->call("_get_linked_undo_properties", p_name, p_value);
+ for (int i = 0; i < linked_properties_dynamic.size(); i++) {
+ valid = false;
+ Variant undo_value = object->get(linked_properties_dynamic[i], &valid);
+ if (valid) {
+ undo_redo->add_undo_property(object, linked_properties_dynamic[i], undo_value);
}
}
@@ -3283,7 +3589,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
Variant return_value;
Callable::CallError call_error;
- callback.call(p_arguments, 4, return_value, call_error);
+ callback.callp(p_arguments, 4, return_value, call_error);
if (call_error.error != Callable::CallError::CALL_OK) {
ERR_PRINT("Invalid UndoRedo callback.");
}
@@ -3429,6 +3735,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();
@@ -3472,7 +3779,7 @@ void EditorInspector::_property_pinned(const String &p_path, bool p_pinned) {
void EditorInspector::_property_selected(const String &p_path, int p_focusable) {
property_selected = p_path;
property_focusable = p_focusable;
- //deselect the others
+ // Deselect the others.
for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) {
if (F.key == property_selected) {
continue;
@@ -3542,7 +3849,7 @@ void EditorInspector::_notification(int p_what) {
if (refresh_countdown <= 0) {
for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) {
for (EditorProperty *E : F.value) {
- if (!E->is_cache_valid()) {
+ if (E && !E->is_cache_valid()) {
E->update_property();
E->update_revert_and_pin_status();
E->update_cache();
@@ -3624,88 +3931,6 @@ void EditorInspector::_feature_profile_changed() {
update_tree();
}
-void EditorInspector::_update_script_class_properties(const Object &p_object, List<PropertyInfo> &r_list) const {
- Ref<Script> script = p_object.get_script();
- if (script.is_null()) {
- return;
- }
-
- List<Ref<Script>> classes;
-
- // NodeC -> NodeB -> NodeA
- while (script.is_valid()) {
- classes.push_front(script);
- script = script->get_base_script();
- }
-
- if (classes.is_empty()) {
- return;
- }
-
- // Script Variables -> to insert: NodeC..B..A -> bottom (insert_here)
- List<PropertyInfo>::Element *script_variables = nullptr;
- List<PropertyInfo>::Element *bottom = nullptr;
- List<PropertyInfo>::Element *insert_here = nullptr;
- for (List<PropertyInfo>::Element *E = r_list.front(); E; E = E->next()) {
- PropertyInfo &pi = E->get();
- if (pi.name != "Script Variables") {
- continue;
- }
- script_variables = E;
- bottom = r_list.insert_after(script_variables, PropertyInfo());
- insert_here = bottom;
- break;
- }
-
- HashSet<StringName> added;
- for (const Ref<Script> &s : classes) {
- String path = s->get_path();
- String name = EditorNode::get_editor_data().script_class_get_name(path);
- if (name.is_empty()) {
- if (s->is_built_in()) {
- if (s->get_name().is_empty()) {
- name = TTR("Built-in script");
- } else {
- name = vformat("%s (%s)", s->get_name(), TTR("Built-in"));
- }
- } else {
- name = path.get_file();
- }
- }
-
- List<PropertyInfo> props;
- s->get_script_property_list(&props);
-
- // Script Variables -> NodeA -> bottom (insert_here)
- List<PropertyInfo>::Element *category = r_list.insert_before(insert_here, PropertyInfo(Variant::NIL, name, PROPERTY_HINT_NONE, path, PROPERTY_USAGE_CATEGORY));
-
- // Script Variables -> NodeA -> A props... -> bottom (insert_here)
- for (List<PropertyInfo>::Element *P = props.front(); P; P = P->next()) {
- PropertyInfo &pi = P->get();
- if (added.has(pi.name)) {
- continue;
- }
- added.insert(pi.name);
-
- r_list.insert_before(insert_here, pi);
- }
-
- // Script Variables -> NodeA (insert_here) -> A props... -> bottom
- insert_here = category;
- }
-
- // NodeC -> C props... -> NodeB..C..
- if (script_variables) {
- r_list.erase(script_variables);
- List<PropertyInfo>::Element *to_delete = bottom->next();
- while (to_delete && !(to_delete->get().usage & PROPERTY_USAGE_CATEGORY)) {
- r_list.erase(to_delete);
- to_delete = bottom->next();
- }
- r_list.erase(bottom);
- }
-}
-
void EditorInspector::set_restrict_to_basic_settings(bool p_restrict) {
restrict_to_basic = p_restrict;
update_tree();
@@ -3780,7 +4005,7 @@ void EditorInspector::_show_add_meta_dialog() {
add_meta_type->add_icon_item(get_theme_icon(type, "EditorIcons"), type, i);
}
hbc->add_child(add_meta_type);
- add_meta_dialog->get_ok_button()->set_text(TTR("Add"));
+ add_meta_dialog->set_ok_button_text(TTR("Add"));
add_child(add_meta_dialog);
add_meta_dialog->register_text_enter(add_meta_name);
add_meta_dialog->connect("confirmed", callable_mp(this, &EditorInspector::_add_meta_confirm));
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index d70d06c48b..551f6f6f86 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -62,6 +62,7 @@ public:
MENU_PASTE_PROPERTY,
MENU_COPY_PROPERTY_PATH,
MENU_PIN_VALUE,
+ MENU_OPEN_DOCUMENTATION,
};
private:
@@ -71,6 +72,7 @@ private:
Object *object = nullptr;
StringName property;
String property_path;
+ String doc_path;
int property_usage;
@@ -148,6 +150,8 @@ public:
Object *get_edited_object();
StringName get_edited_property() const;
+ void set_doc_path(const String &p_doc_path);
+
virtual void update_property();
void update_revert_and_pin_status();
@@ -180,6 +184,7 @@ public:
virtual void expand_all_folding();
virtual void collapse_all_folding();
+ virtual void expand_revertable();
virtual Variant get_drag_data(const Point2 &p_point) override;
virtual void update_cache();
@@ -277,6 +282,8 @@ class EditorInspectorSection : public Container {
Timer *dropping_unfold_timer = nullptr;
bool dropping = false;
+ HashSet<StringName> revertable_properties;
+
void _test_unfold();
protected:
@@ -295,6 +302,9 @@ public:
void unfold();
void fold();
+ bool has_revertable_properties() const;
+ void property_can_revert_changed(const String &p_path, bool p_can_revert);
+
EditorInspectorSection();
~EditorInspectorSection();
};
@@ -311,6 +321,7 @@ class EditorInspectorArray : public EditorInspectorSection {
} mode;
StringName count_property;
StringName array_element_prefix;
+ String swap_method;
int count = 0;
@@ -332,6 +343,9 @@ class EditorInspectorArray : public EditorInspectorSection {
int begin_array_index = 0;
int end_array_index = 0;
+ bool movable = true;
+ bool numbered = false;
+
enum MenuOptions {
OPTION_MOVE_UP = 0,
OPTION_MOVE_DOWN,
@@ -349,7 +363,9 @@ class EditorInspectorArray : public EditorInspectorSection {
MarginContainer *margin = nullptr;
HBoxContainer *hbox = nullptr;
TextureRect *move_texture_rect = nullptr;
+ Label *number = nullptr;
VBoxContainer *vbox = nullptr;
+ Button *erase = nullptr;
};
LocalVector<ArrayElement> array_elements;
@@ -385,6 +401,8 @@ class EditorInspectorArray : public EditorInspectorSection {
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ void _remove_item(int p_index);
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -392,8 +410,8 @@ protected:
public:
void set_undo_redo(UndoRedo *p_undo_redo);
- void setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable);
- void setup_with_count_property(Object *p_object, String p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable);
+ void setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = "");
+ void setup_with_count_property(Object *p_object, String p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = "", const String &p_swap_method = "");
VBoxContainer *get_vbox(int p_index);
EditorInspectorArray();
@@ -439,7 +457,7 @@ class EditorInspector : public ScrollContainer {
VBoxContainer *main_vbox = nullptr;
- //map use to cache the instantiated editors
+ // Map used to cache the instantiated editors.
HashMap<StringName, List<EditorProperty *>> editor_property_map;
List<EditorInspectorSection *> sections;
HashSet<StringName> pending;
@@ -473,7 +491,12 @@ class EditorInspector : public ScrollContainer {
int property_focusable;
int update_scroll_request;
- HashMap<StringName, HashMap<StringName, String>> descr_cache;
+ struct PropertyDocInfo {
+ String description;
+ String path;
+ };
+
+ HashMap<StringName, HashMap<StringName, PropertyDocInfo>> doc_info_cache;
HashMap<StringName, String> class_descr_cache;
HashSet<StringName> restart_request_props;
@@ -508,12 +531,11 @@ class EditorInspector : public ScrollContainer {
void _edit_request_change(Object *p_object, const String &p_prop);
void _filter_changed(const String &p_text);
- void _parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped);
+ void _parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped);
void _vscroll_changed(double);
void _feature_profile_changed();
- void _update_script_class_properties(const Object &p_object, List<PropertyInfo> &r_list) const;
bool _is_property_disabled_by_feature_profile(const StringName &p_property);
@@ -570,6 +592,7 @@ public:
void collapse_all_folding();
void expand_all_folding();
+ void expand_revertable();
void set_scroll_offset(int p_offset);
int get_scroll_offset() const;
@@ -593,4 +616,4 @@ public:
EditorInspector();
};
-#endif // INSPECTOR_H
+#endif // EDITOR_INSPECTOR_H
diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp
index abef0dc353..cd8150d235 100644
--- a/editor/editor_locale_dialog.cpp
+++ b/editor/editor_locale_dialog.cpp
@@ -552,5 +552,5 @@ EditorLocaleDialog::EditorLocaleDialog() {
add_child(vb);
_update_tree();
- get_ok_button()->set_text(TTR("Select"));
+ set_ok_button_text(TTR("Select"));
}
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index f26f47dbc7..38cc85bb4e 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -33,8 +33,11 @@
#include "core/os/keyboard.h"
#include "core/version.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/gui/center_container.h"
+#include "scene/gui/separator.h"
#include "scene/resources/font.h"
void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) {
@@ -122,7 +125,7 @@ void EditorLog::_save_state() {
Ref<ConfigFile> config;
config.instantiate();
// Load and amend existing config if it exists.
- config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
+ config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
const String section = "editor_log";
for (const KeyValue<MessageType, LogFilter *> &E : type_filter_map) {
@@ -132,7 +135,7 @@ void EditorLog::_save_state() {
config->set_value(section, "collapse", collapse);
config->set_value(section, "show_search", search_box->is_visible());
- config->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
+ config->save(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
}
void EditorLog::_load_state() {
@@ -140,7 +143,7 @@ void EditorLog::_load_state() {
Ref<ConfigFile> config;
config.instantiate();
- config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
+ config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
// Run the below code even if config->load returns an error, since we want the defaults to be set even if the file does not exist yet.
const String section = "editor_log";
diff --git a/editor/editor_log.h b/editor/editor_log.h
index 653fba9524..003a148b9b 100644
--- a/editor/editor_log.h
+++ b/editor/editor_log.h
@@ -88,7 +88,7 @@ private:
toggle_button->add_theme_color_override("icon_color_pressed", Color(1, 1, 1, 1));
toggle_button->set_focus_mode(FOCUS_NONE);
// When toggled call the callback and pass the MessageType this button is for.
- toggle_button->connect("toggled", p_toggled_callback, varray(type));
+ toggle_button->connect("toggled", p_toggled_callback.bind(type));
}
int get_message_count() {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index b196cadcb1..e7946f56da 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -49,6 +49,7 @@
#include "main/main.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/gui/center_container.h"
+#include "scene/gui/color_picker.h"
#include "scene/gui/control.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/file_dialog.h"
@@ -75,9 +76,9 @@
#include "editor/dependency_editor.h"
#include "editor/editor_about.h"
#include "editor/editor_audio_buses.h"
+#include "editor/editor_build_profile.h"
#include "editor/editor_command_palette.h"
#include "editor/editor_data.h"
-#include "editor/editor_export.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_file_system.h"
@@ -90,6 +91,7 @@
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
#include "editor/editor_property_name_processor.h"
+#include "editor/editor_quick_open.h"
#include "editor/editor_resource_picker.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_run.h"
@@ -102,8 +104,11 @@
#include "editor/editor_themes.h"
#include "editor/editor_toaster.h"
#include "editor/editor_translation_parser.h"
-#include "editor/export_template_manager.h"
+#include "editor/export/editor_export.h"
+#include "editor/export/export_template_manager.h"
+#include "editor/export/project_export.h"
#include "editor/filesystem_dock.h"
+#include "editor/import/audio_stream_import_settings.h"
#include "editor/import/dynamic_font_import_settings.h"
#include "editor/import/editor_import_collada.h"
#include "editor/import/resource_importer_bitmask.h"
@@ -131,11 +136,12 @@
#include "editor/plugins/animation_state_machine_editor.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
#include "editor/plugins/asset_library_editor_plugin.h"
-#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/cast_2d_editor_plugin.h"
#include "editor/plugins/collision_polygon_2d_editor_plugin.h"
#include "editor/plugins/collision_shape_2d_editor_plugin.h"
#include "editor/plugins/control_editor_plugin.h"
@@ -145,7 +151,8 @@
#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/editor_resource_conversion_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,15 +171,12 @@
#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"
#include "editor/plugins/physical_bone_3d_editor_plugin.h"
#include "editor/plugins/polygon_2d_editor_plugin.h"
#include "editor/plugins/polygon_3d_editor_plugin.h"
-#include "editor/plugins/ray_cast_2d_editor_plugin.h"
-#include "editor/plugins/replication_editor_plugin.h"
#include "editor/plugins/resource_preloader_editor_plugin.h"
#include "editor/plugins/root_motion_editor_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
@@ -186,7 +190,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"
@@ -198,9 +201,7 @@
#include "editor/plugins/visual_shader_editor_plugin.h"
#include "editor/plugins/voxel_gi_editor_plugin.h"
#include "editor/progress_dialog.h"
-#include "editor/project_export.h"
#include "editor/project_settings_editor.h"
-#include "editor/quick_open.h"
#include "editor/register_exporters.h"
#include "editor/scene_tree_dock.h"
@@ -460,7 +461,7 @@ void EditorNode::shortcut_input(const Ref<InputEvent> &p_event) {
_editor_select(EDITOR_SCRIPT);
} else if (ED_IS_SHORTCUT("editor/editor_help", p_event)) {
emit_signal(SNAME("request_help_search"), "");
- } else if (ED_IS_SHORTCUT("editor/editor_assetlib", p_event) && StreamPeerSSL::is_available()) {
+ } else if (ED_IS_SHORTCUT("editor/editor_assetlib", p_event) && AssetLibraryEditorPlugin::is_available()) {
_editor_select(EDITOR_ASSETLIB);
} else if (ED_IS_SHORTCUT("editor/editor_next", p_event)) {
_editor_select_next();
@@ -513,10 +514,10 @@ void EditorNode::_update_from_settings() {
uint32_t directional_shadow_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits");
RS::get_singleton()->directional_shadow_atlas_set_size(directional_shadow_size, directional_shadow_16_bits);
- RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/shadows/soft_shadow_quality")));
- RS::get_singleton()->shadows_quality_set(shadows_quality);
- RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_quality")));
- RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality);
+ RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality")));
+ RS::get_singleton()->positional_soft_shadow_filter_set_quality(shadows_quality);
+ RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality")));
+ RS::get_singleton()->directional_soft_shadow_filter_set_quality(directional_shadow_quality);
float probe_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");
RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed);
RS::EnvironmentSDFGIFramesToConverge frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(int(GLOBAL_GET("rendering/global_illumination/sdfgi/frames_to_converge")));
@@ -553,6 +554,19 @@ void EditorNode::_update_from_settings() {
tree->set_debug_collision_contact_color(GLOBAL_GET("debug/shapes/collision/contact_color"));
tree->set_debug_navigation_color(GLOBAL_GET("debug/shapes/navigation/geometry_color"));
tree->set_debug_navigation_disabled_color(GLOBAL_GET("debug/shapes/navigation/disabled_geometry_color"));
+
+#ifdef DEBUG_ENABLED
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_edge_connection_color(GLOBAL_GET("debug/shapes/navigation/edge_connection_color"));
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_edge_color(GLOBAL_GET("debug/shapes/navigation/geometry_edge_color"));
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_face_color(GLOBAL_GET("debug/shapes/navigation/geometry_face_color"));
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_edge_disabled_color(GLOBAL_GET("debug/shapes/navigation/geometry_edge_disabled_color"));
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_face_disabled_color(GLOBAL_GET("debug/shapes/navigation/geometry_face_disabled_color"));
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_connections(GLOBAL_GET("debug/shapes/navigation/enable_edge_connections"));
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_connections_xray(GLOBAL_GET("debug/shapes/navigation/enable_edge_connections_xray"));
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_lines(GLOBAL_GET("debug/shapes/navigation/enable_edge_lines"));
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_lines_xray(GLOBAL_GET("debug/shapes/navigation/enable_edge_lines_xray"));
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_geometry_face_random_color(GLOBAL_GET("debug/shapes/navigation/enable_geometry_face_random_color"));
+#endif // DEBUG_ENABLED
}
void EditorNode::_select_default_main_screen_plugin() {
@@ -924,6 +938,7 @@ void EditorNode::_fs_changed() {
// FIXME: Move this to a cleaner location, it's hacky to do this in _fs_changed.
String export_error;
+ Error err = OK;
if (!export_defer.preset.is_empty() && !EditorFileSystem::get_singleton()->is_scanning()) {
String preset_name = export_defer.preset;
// Ensures export_project does not loop infinitely, because notifications may
@@ -941,6 +956,7 @@ void EditorNode::_fs_changed() {
if (export_preset.is_null()) {
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists("res://export_presets.cfg")) {
+ err = FAILED;
export_error = vformat(
"Invalid export preset name: %s.\nThe following presets were detected in this project's `export_presets.cfg`:\n\n",
preset_name);
@@ -949,17 +965,19 @@ void EditorNode::_fs_changed() {
export_error += vformat(" \"%s\"\n", EditorExport::get_singleton()->get_export_preset(i)->get_name());
}
} else {
+ err = FAILED;
export_error = "This project doesn't have an `export_presets.cfg` file at its root.\nCreate an export preset from the \"Project > Export\" dialog and try again.";
}
} else {
Ref<EditorExportPlatform> platform = export_preset->get_platform();
const String export_path = export_defer.path.is_empty() ? export_preset->get_export_path() : export_defer.path;
if (export_path.is_empty()) {
+ err = FAILED;
export_error = vformat("Export preset \"%s\" doesn't have a default export path, and none was specified.", preset_name);
} else if (platform.is_null()) {
+ err = FAILED;
export_error = vformat("Export preset \"%s\" doesn't have a matching platform.", preset_name);
} else {
- Error err = OK;
if (export_defer.pack_only) { // Only export .pck or .zip data pack.
if (export_path.ends_with(".zip")) {
err = platform->export_zip(export_preset, export_defer.debug, export_path);
@@ -980,17 +998,18 @@ void EditorNode::_fs_changed() {
if (err != OK) {
export_error = vformat("Project export for preset \"%s\" failed.", preset_name);
} else if (platform->get_worst_message_type() >= EditorExportPlatform::EXPORT_MESSAGE_WARNING) {
- export_error = vformat("Project export for preset \"%s\" completed with errors.", preset_name);
+ export_error = vformat("Project export for preset \"%s\" completed with warnings.", preset_name);
}
}
}
- if (!export_error.is_empty()) {
+ if (err != OK) {
ERR_PRINT(export_error);
_exit_editor(EXIT_FAILURE);
- } else {
- _exit_editor(EXIT_SUCCESS);
+ } else if (!export_error.is_empty()) {
+ WARN_PRINT(export_error);
}
+ _exit_editor(EXIT_SUCCESS);
}
}
@@ -1030,7 +1049,7 @@ void EditorNode::_sources_changed(bool p_exist) {
// Reload the global shader variables, but this time
// loading textures, as they are now properly imported.
- RenderingServer::get_singleton()->global_variables_load_settings(true);
+ RenderingServer::get_singleton()->global_shader_uniforms_load_settings(true);
// Start preview thread now that it's safe.
if (!singleton->cmdline_export_mode) {
@@ -1208,7 +1227,7 @@ void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const St
}
String path = ProjectSettings::get_singleton()->localize_path(p_path);
- Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
+ Error err = ResourceSaver::save(p_resource, path, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
if (err != OK) {
if (ResourceLoader::is_imported(p_resource->get_path())) {
@@ -1260,7 +1279,7 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String
// This serves no purpose and confused people.
continue;
}
- file->add_filter("*." + E + " ; " + E.to_upper());
+ file->add_filter("*." + E, E.to_upper());
preferred.push_back(E);
}
// Lowest priority extension.
@@ -1359,7 +1378,7 @@ void EditorNode::_get_scene_metadata(const String &p_file) {
return;
}
- String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
+ String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
Ref<ConfigFile> cf;
cf.instantiate();
@@ -1391,7 +1410,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) {
return;
}
- String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
+ String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
Ref<ConfigFile> cf;
cf.instantiate();
@@ -1431,7 +1450,7 @@ bool EditorNode::_find_and_save_resource(Ref<Resource> p_res, HashMap<Ref<Resour
if (p_res->get_path().is_resource_file()) {
if (changed || subchanged) {
- ResourceSaver::save(p_res->get_path(), p_res, flags);
+ ResourceSaver::save(p_res, p_res->get_path(), flags);
}
processed[p_res] = false; // Because it's a file.
return false;
@@ -1662,7 +1681,7 @@ int EditorNode::_save_external_resources() {
if (ps.is_valid()) {
continue; // Do not save PackedScenes, this will mess up the editor.
}
- ResourceSaver::save(res->get_path(), res, flg);
+ ResourceSaver::save(res, res->get_path(), flg);
saved++;
}
@@ -1733,7 +1752,7 @@ void EditorNode::_save_scene(String p_file, int idx) {
}
flg |= ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
- err = ResourceSaver::save(p_file, sdata, flg);
+ err = ResourceSaver::save(sdata, p_file, flg);
// This needs to be emitted before saving external resources.
emit_signal(SNAME("scene_saved"), p_file);
@@ -1795,9 +1814,16 @@ void EditorNode::restart_editor() {
_exit_editor(EXIT_SUCCESS);
List<String> args;
+
args.push_back("--path");
args.push_back(ProjectSettings::get_singleton()->get_resource_path());
+
args.push_back("-e");
+
+ if (OS::get_singleton()->is_disable_crash_handler()) {
+ args.push_back("--disable-crash-handler");
+ }
+
if (!to_reopen.is_empty()) {
args.push_back(to_reopen);
}
@@ -1933,7 +1959,7 @@ void EditorNode::_dialog_action(String p_file) {
MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true, file_export_lib_apply_xforms->is_pressed());
- Error err = ResourceSaver::save(p_file, ml);
+ Error err = ResourceSaver::save(ml, p_file);
if (err) {
show_accept(TTR("Error saving MeshLibrary!"), TTR("OK"));
return;
@@ -2178,6 +2204,8 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding"));
bool is_resource = current_obj->is_class("Resource");
bool is_node = current_obj->is_class("Node");
+ bool stay_in_script_editor_on_node_selected = bool(EDITOR_GET("text_editor/behavior/navigation/stay_in_script_editor_on_node_selected"));
+ bool skip_main_plugin = false;
String editable_warning; // None by default.
@@ -2214,6 +2242,9 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
NodeDock::get_singleton()->set_node(current_node);
SceneTreeDock::get_singleton()->set_selected(current_node);
InspectorDock::get_singleton()->update(current_node);
+ if (!inspector_only && !skip_main_plugin) {
+ skip_main_plugin = stay_in_script_editor_on_node_selected && ScriptEditor::get_singleton()->is_visible_in_tree();
+ }
} else {
NodeDock::get_singleton()->set_node(nullptr);
SceneTreeDock::get_singleton()->set_selected(nullptr);
@@ -2288,7 +2319,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
}
}
- if (main_plugin) {
+ if (main_plugin && !skip_main_plugin) {
// Special case if use of external editor is true.
Resource *current_res = Object::cast_to<Resource>(current_obj);
if (main_plugin->get_name() == "Script" && !current_obj->is_class("VisualScript") && current_res && !current_res->is_built_in() && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) {
@@ -2333,6 +2364,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 +2385,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())) {
@@ -2472,7 +2503,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions);
file->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file->add_filter("*." + extensions[i], extensions[i].to_upper());
}
Node *scene = editor_data.get_edited_scene_root();
@@ -2542,10 +2573,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (scene_root) {
String scene_filename = scene_root->get_scene_file_path();
if (p_option == FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT) {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Reload"));
+ save_confirmation->set_ok_button_text(TTR("Save & Reload"));
save_confirmation->set_text(vformat(TTR("Save changes to '%s' before reloading?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene"));
} else {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Quit"));
+ save_confirmation->set_ok_button_text(TTR("Save & Quit"));
save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene"));
}
save_confirmation->popup_centered();
@@ -2618,7 +2649,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
ResourceSaver::get_recognized_extensions(sd, &extensions);
file->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file->add_filter("*." + extensions[i], extensions[i].to_upper());
}
if (!scene->get_scene_file_path().is_empty()) {
@@ -2661,7 +2692,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case FILE_EXTERNAL_OPEN_SCENE: {
if (unsaved_cache && !p_confirmed) {
- confirmation->get_ok_button()->set_text(TTR("Open"));
+ confirmation->set_ok_button_text(TTR("Open"));
confirmation->set_text(TTR("Current scene not saved. Open anyway?"));
confirmation->popup_centered();
break;
@@ -2717,7 +2748,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
if (unsaved_cache && !p_confirmed) {
- confirmation->get_ok_button()->set_text(TTR("Reload Saved Scene"));
+ confirmation->set_ok_button_text(TTR("Reload Saved Scene"));
confirmation->set_text(
TTR("The current scene has unsaved changes.\nReload the saved scene anyway? This action cannot be undone."));
confirmation->popup_centered();
@@ -2793,9 +2824,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();
@@ -2809,6 +2837,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
}
} break;
+ case TOOLS_BUILD_PROFILE_MANAGER: {
+ build_profile_manager->popup_centered_clamped(Size2(700, 800) * EDSCALE, 0.8);
+ } break;
case RUN_USER_DATA_FOLDER: {
// Ensure_user_data_dir() to prevent the edge case: "Open User Data Folder" won't work after the project was renamed in ProjectSettingsEditor unless the project is saved.
OS::get_singleton()->ensure_user_data_dir();
@@ -2842,10 +2873,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
i = _next_unsaved_scene(true, ++i);
}
if (p_option == RELOAD_CURRENT_PROJECT) {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Reload"));
+ save_confirmation->set_ok_button_text(TTR("Save & Reload"));
save_confirmation->set_text(TTR("Save changes to the following scene(s) before reloading?") + unsaved_scenes);
} else {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Quit"));
+ save_confirmation->set_ok_button_text(TTR("Save & Quit"));
save_confirmation->set_text((p_option == FILE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes to the following scene(s) before opening Project Manager?")) + unsaved_scenes);
}
save_confirmation->popup_centered();
@@ -2907,7 +2938,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions);
file->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file->add_filter("*." + extensions[i], extensions[i].to_upper());
}
Node *scene = editor_data.get_edited_scene_root();
@@ -2994,7 +3025,7 @@ void EditorNode::_tool_menu_option(int p_idx) {
Callable callback = tool_menu->get_item_metadata(p_idx);
Callable::CallError ce;
Variant result;
- callback.call(nullptr, 0, result, ce);
+ callback.callp(nullptr, 0, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
String err = Variant::get_callable_error_text(callback, nullptr, 0, ce);
@@ -3029,7 +3060,7 @@ void EditorNode::_export_as_menu_option(int p_idx) {
Callable callback = export_as_menu->get_item_metadata(p_idx);
Callable::CallError ce;
Variant result;
- callback.call(nullptr, 0, result, ce);
+ callback.callp(nullptr, 0, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
String err = Variant::get_callable_error_text(callback, nullptr, 0, ce);
@@ -3234,7 +3265,7 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed
Button *tb = memnew(Button);
tb->set_flat(true);
tb->set_toggle_mode(true);
- tb->connect("pressed", callable_mp(singleton, &EditorNode::_editor_select), varray(singleton->main_editor_buttons.size()));
+ tb->connect("pressed", callable_mp(singleton, &EditorNode::_editor_select).bind(singleton->main_editor_buttons.size()));
tb->set_name(p_editor->get_name());
tb->set_text(p_editor->get_name());
@@ -3592,6 +3623,13 @@ void EditorNode::set_current_scene(int p_idx) {
call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // Do after everything else is done setting up.
}
+void EditorNode::setup_color_picker(ColorPicker *picker) {
+ int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode");
+ int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape");
+ picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode);
+ picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape);
+}
+
bool EditorNode::is_scene_open(const String &p_path) {
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
if (editor_data.get_scene_path(i) == p_path) {
@@ -4047,10 +4085,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;
@@ -4278,14 +4314,14 @@ Error EditorNode::export_preset(const String &p_preset, const String &p_path, bo
void EditorNode::show_accept(const String &p_text, const String &p_title) {
current_menu_option = -1;
- accept->get_ok_button()->set_text(p_title);
+ accept->set_ok_button_text(p_title);
accept->set_text(p_text);
accept->popup_centered();
}
void EditorNode::show_save_accept(const String &p_text, const String &p_title) {
current_menu_option = -1;
- save_accept->get_ok_button()->set_text(p_title);
+ save_accept->set_ok_button_text(p_title);
save_accept->set_text(p_text);
save_accept->popup_centered();
}
@@ -4339,22 +4375,22 @@ void EditorNode::_dock_make_float() {
window->set_title(dock->get_name());
Panel *p = memnew(Panel);
p->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("PanelForeground"), SNAME("EditorStyles")));
- p->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ p->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
window->add_child(p);
MarginContainer *margin = memnew(MarginContainer);
- margin->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ margin->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
margin->add_theme_constant_override("margin_right", borders.width);
margin->add_theme_constant_override("margin_top", borders.height);
margin->add_theme_constant_override("margin_left", borders.width);
margin->add_theme_constant_override("margin_bottom", borders.height);
window->add_child(margin);
- dock->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ dock->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
margin->add_child(dock);
window->set_wrap_controls(true);
window->set_size(dock_size);
window->set_position(dock_screen_pos);
window->set_transient(true);
- window->connect("close_requested", callable_mp(this, &EditorNode::_dock_floating_close_request), varray(dock));
+ window->connect("close_requested", callable_mp(this, &EditorNode::_dock_floating_close_request).bind(dock));
window->set_meta("dock_slot", dock_popup_selected_idx);
window->set_meta("dock_index", dock_index);
gui_base->add_child(window);
@@ -4575,13 +4611,13 @@ void EditorNode::_save_docks() {
Ref<ConfigFile> config;
config.instantiate();
// Load and amend existing config if it exists.
- config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
+ config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
_save_docks_to_config(config, "docks");
_save_open_scenes_to_config(config, "EditorNode");
editor_data.get_plugin_window_layout(config);
- config->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
+ config->save(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
}
void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) {
@@ -4595,8 +4631,14 @@ void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p
names += name;
}
+ String config_key = "dock_" + itos(i + 1);
+
+ if (p_layout->has_section_key(p_section, config_key)) {
+ p_layout->erase_section_key(p_section, config_key);
+ }
+
if (!names.is_empty()) {
- p_layout->set_value(p_section, "dock_" + itos(i + 1), names);
+ p_layout->set_value(p_section, config_key, names);
}
}
@@ -4639,7 +4681,7 @@ void EditorNode::_dock_split_dragged(int ofs) {
void EditorNode::_load_docks() {
Ref<ConfigFile> config;
config.instantiate();
- Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
+ Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
if (err != OK) {
// No config.
if (overridden_default_layout >= 0) {
@@ -4872,7 +4914,7 @@ bool EditorNode::has_scenes_in_session() {
}
Ref<ConfigFile> config;
config.instantiate();
- Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
+ Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
if (err != OK) {
return false;
}
@@ -4957,22 +4999,14 @@ 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;
}
bool EditorNode::immediate_confirmation_dialog(const String &p_text, const String &p_ok_text, const String &p_cancel_text) {
ConfirmationDialog *cd = memnew(ConfirmationDialog);
cd->set_text(p_text);
- cd->get_ok_button()->set_text(p_ok_text);
- cd->get_cancel_button()->set_text(p_cancel_text);
+ cd->set_ok_button_text(p_ok_text);
+ cd->set_cancel_button_text(p_cancel_text);
cd->connect("confirmed", callable_mp(singleton, &EditorNode::_immediate_dialog_confirmed));
singleton->gui_base->add_child(cd);
@@ -5034,14 +5068,14 @@ void EditorNode::_layout_menu_option(int p_id) {
case SETTINGS_LAYOUT_SAVE: {
current_menu_option = p_id;
layout_dialog->set_title(TTR("Save Layout"));
- layout_dialog->get_ok_button()->set_text(TTR("Save"));
+ layout_dialog->set_ok_button_text(TTR("Save"));
layout_dialog->popup_centered();
layout_dialog->set_name_line_enabled(true);
} break;
case SETTINGS_LAYOUT_DELETE: {
current_menu_option = p_id;
layout_dialog->set_title(TTR("Delete Layout"));
- layout_dialog->get_ok_button()->set_text(TTR("Delete"));
+ layout_dialog->set_ok_button_text(TTR("Delete"));
layout_dialog->popup_centered();
layout_dialog->set_name_line_enabled(false);
} break;
@@ -5083,7 +5117,7 @@ void EditorNode::_scene_tab_closed(int p_tab, int option) {
? saved_version != editor_data.get_undo_redo().get_version()
: editor_data.get_scene_version(p_tab) != 0;
if (unsaved) {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Close"));
+ save_confirmation->set_ok_button_text(TTR("Save & Close"));
save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), !scene->get_scene_file_path().is_empty() ? scene->get_scene_file_path() : "unsaved scene"));
save_confirmation->popup_centered();
} else {
@@ -5215,7 +5249,7 @@ void EditorNode::_scene_tab_changed(int p_tab) {
Button *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) {
Button *tb = memnew(Button);
tb->set_flat(true);
- tb->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch), varray(bottom_panel_items.size()));
+ tb->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch).bind(bottom_panel_items.size()));
tb->set_text(p_text);
tb->set_toggle_mode(true);
tb->set_focus_mode(Control::FOCUS_NONE);
@@ -5262,7 +5296,7 @@ void EditorNode::raise_bottom_panel_item(Control *p_item) {
for (int i = 0; i < bottom_panel_items.size(); i++) {
bottom_panel_items[i].button->disconnect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch));
- bottom_panel_items[i].button->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch), varray(i));
+ bottom_panel_items[i].button->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch).bind(i));
}
}
@@ -5282,7 +5316,7 @@ void EditorNode::remove_bottom_panel_item(Control *p_item) {
for (int i = 0; i < bottom_panel_items.size(); i++) {
bottom_panel_items[i].button->disconnect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch));
- bottom_panel_items[i].button->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch), varray(i));
+ bottom_panel_items[i].button->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch).bind(i));
}
}
@@ -5405,9 +5439,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);
@@ -5752,12 +5784,12 @@ void EditorNode::_feature_profile_changed() {
main_editor_buttons[EDITOR_3D]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D));
main_editor_buttons[EDITOR_SCRIPT]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT));
- if (StreamPeerSSL::is_available()) {
+ if (AssetLibraryEditorPlugin::is_available()) {
main_editor_buttons[EDITOR_ASSETLIB]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB));
}
if ((profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D) && singleton->main_editor_buttons[EDITOR_3D]->is_pressed()) ||
(profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT) && singleton->main_editor_buttons[EDITOR_SCRIPT]->is_pressed()) ||
- (StreamPeerSSL::is_available() && profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB) && singleton->main_editor_buttons[EDITOR_ASSETLIB]->is_pressed())) {
+ (AssetLibraryEditorPlugin::is_available() && profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB) && singleton->main_editor_buttons[EDITOR_ASSETLIB]->is_pressed())) {
_editor_select(EDITOR_2D);
}
} else {
@@ -5769,7 +5801,7 @@ void EditorNode::_feature_profile_changed() {
FileSystemDock::get_singleton()->set_visible(true);
main_editor_buttons[EDITOR_3D]->set_visible(true);
main_editor_buttons[EDITOR_SCRIPT]->set_visible(true);
- if (StreamPeerSSL::is_available()) {
+ if (AssetLibraryEditorPlugin::is_available()) {
main_editor_buttons[EDITOR_ASSETLIB]->set_visible(true);
}
}
@@ -5909,8 +5941,14 @@ EditorNode::EditorNode() {
RenderingServer::get_singleton()->set_debug_generate_wireframes(true);
+ AudioServer::get_singleton()->set_enable_tagging_used_audio_streams(true);
+
// No navigation server by default if in editor.
- NavigationServer3D::get_singleton()->set_active(false);
+ if (NavigationServer3D::get_singleton()->get_debug_enabled()) {
+ NavigationServer3D::get_singleton()->set_active(true);
+ } else {
+ NavigationServer3D::get_singleton()->set_active(false);
+ }
// No physics by default if in editor.
PhysicsServer3D::get_singleton()->set_active(false);
@@ -6119,8 +6157,6 @@ EditorNode::EditorNode() {
register_exporters();
- ClassDB::set_class_enabled("RootMotionView", true);
-
EDITOR_DEF("interface/editor/save_on_focus_loss", false);
EDITOR_DEF("interface/editor/show_update_spinner", false);
EDITOR_DEF("interface/editor/update_continuously", false);
@@ -6129,15 +6165,24 @@ EditorNode::EditorNode() {
EDITOR_DEF_RST("interface/inspector/default_property_name_style", EditorPropertyNameProcessor::STYLE_CAPITALIZED);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_property_name_style", PROPERTY_HINT_ENUM, "Raw,Capitalized,Localized"));
EDITOR_DEF_RST("interface/inspector/default_float_step", 0.001);
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::FLOAT, "interface/inspector/default_float_step", PROPERTY_HINT_RANGE, "0,1,0"));
+ // The lowest value is equal to the minimum float step for 32-bit floats.
+ // The step must be set manually, as changing this setting should not change the step here.
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::FLOAT, "interface/inspector/default_float_step", PROPERTY_HINT_RANGE, "0.0000001,1,0.0000001"));
EDITOR_DEF_RST("interface/inspector/disable_folding", false);
EDITOR_DEF_RST("interface/inspector/auto_unfold_foreign_scenes", true);
EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false);
EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true);
EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true);
- EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,MeshLibrary");
+
+ PackedStringArray open_in_new_inspector_defaults;
+ // Required for the script editor to work.
+ open_in_new_inspector_defaults.push_back("Script");
+ // Required for the GridMap editor to work.
+ open_in_new_inspector_defaults.push_back("MeshLibrary");
+ EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", open_in_new_inspector_defaults);
+
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));
@@ -6150,11 +6195,11 @@ EditorNode::EditorNode() {
theme_base = memnew(Control);
add_child(theme_base);
- theme_base->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ theme_base->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
gui_base = memnew(Panel);
theme_base->add_child(gui_base);
- gui_base->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ gui_base->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
theme_base->set_theme(theme);
gui_base->set_theme(theme);
@@ -6172,7 +6217,7 @@ EditorNode::EditorNode() {
main_vbox = memnew(VBoxContainer);
gui_base->add_child(main_vbox);
- main_vbox->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8);
+ main_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 8);
main_vbox->add_theme_constant_override("separation", 8 * EDSCALE);
menu_hb = memnew(HBoxContainer);
@@ -6301,7 +6346,7 @@ EditorNode::EditorNode() {
dock_slot[i]->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL);
dock_slot[i]->set_popup(dock_select_popup);
- dock_slot[i]->connect("pre_popup_pressed", callable_mp(this, &EditorNode::_dock_pre_popup), varray(i));
+ dock_slot[i]->connect("pre_popup_pressed", callable_mp(this, &EditorNode::_dock_pre_popup).bind(i));
dock_slot[i]->set_drag_to_rearrange_enabled(true);
dock_slot[i]->set_tabs_rearrange_group(1);
dock_slot[i]->connect("tab_changed", callable_mp(this, &EditorNode::_dock_tab_changed));
@@ -6349,7 +6394,7 @@ EditorNode::EditorNode() {
scene_tabs->set_drag_to_rearrange_enabled(true);
scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed));
scene_tabs->connect("tab_button_pressed", callable_mp(this, &EditorNode::_scene_tab_script_edited));
- scene_tabs->connect("tab_close_pressed", callable_mp(this, &EditorNode::_scene_tab_closed), varray(SCENE_TAB_CLOSE));
+ scene_tabs->connect("tab_close_pressed", callable_mp(this, &EditorNode::_scene_tab_closed).bind(SCENE_TAB_CLOSE));
scene_tabs->connect("tab_hovered", callable_mp(this, &EditorNode::_scene_tab_hovered));
scene_tabs->connect("mouse_exited", callable_mp(this, &EditorNode::_scene_tab_exit));
scene_tabs->connect("gui_input", callable_mp(this, &EditorNode::_scene_tab_input));
@@ -6368,7 +6413,7 @@ EditorNode::EditorNode() {
scene_tab_add->set_icon(gui_base->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
scene_tab_add->add_theme_color_override("icon_normal_color", Color(0.6f, 0.6f, 0.6f, 0.8f));
scene_tabs->add_child(scene_tab_add);
- scene_tab_add->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(FILE_NEW_SCENE));
+ scene_tab_add->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(FILE_NEW_SCENE));
scene_tab_add_ph = memnew(Control);
scene_tab_add_ph->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
@@ -6420,7 +6465,7 @@ EditorNode::EditorNode() {
prev_scene->set_icon(gui_base->get_theme_icon(SNAME("PrevScene"), SNAME("EditorIcons")));
prev_scene->set_tooltip(TTR("Go to previously opened scene."));
prev_scene->set_disabled(true);
- prev_scene->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(FILE_OPEN_PREV));
+ prev_scene->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(FILE_OPEN_PREV));
gui_base->add_child(prev_scene);
prev_scene->set_position(Point2(3, 24));
prev_scene->hide();
@@ -6431,7 +6476,7 @@ EditorNode::EditorNode() {
save_accept = memnew(AcceptDialog);
gui_base->add_child(save_accept);
- save_accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), make_binds((int)MenuOptions::FILE_SAVE_AS_SCENE));
+ save_accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind((int)MenuOptions::FILE_SAVE_AS_SCENE));
project_export = memnew(ProjectExportDialog);
gui_base->add_child(project_export);
@@ -6451,6 +6496,9 @@ EditorNode::EditorNode() {
scene_import_settings = memnew(SceneImportSettings);
gui_base->add_child(scene_import_settings);
+ audio_stream_import_settings = memnew(AudioStreamImportSettings);
+ gui_base->add_child(audio_stream_import_settings);
+
fontdata_import_settings = memnew(DynamicFontImportSettings);
gui_base->add_child(fontdata_import_settings);
@@ -6459,6 +6507,10 @@ EditorNode::EditorNode() {
feature_profile_manager = memnew(EditorFeatureProfileManager);
gui_base->add_child(feature_profile_manager);
+
+ build_profile_manager = memnew(EditorBuildProfileManager);
+ gui_base->add_child(build_profile_manager);
+
about = memnew(EditorAbout);
gui_base->add_child(about);
feature_profile_manager->connect("current_feature_profile_changed", callable_mp(this, &EditorNode::_feature_profile_changed));
@@ -6551,6 +6603,10 @@ EditorNode::EditorNode() {
p->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE);
p->add_item(TTR("Open User Data Folder"), RUN_USER_DATA_FOLDER);
+ p->add_separator();
+ p->add_item(TTR("Customize Engine Build Configuration..."), TOOLS_BUILD_PROFILE_MANAGER);
+ p->add_separator();
+
plugin_config_dialog = memnew(PluginConfigDialog);
plugin_config_dialog->connect("plugin_ready", callable_mp(this, &EditorNode::_on_plugin_ready));
gui_base->add_child(plugin_config_dialog);
@@ -6663,7 +6719,7 @@ EditorNode::EditorNode() {
play_button->set_toggle_mode(true);
play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
play_button->set_focus_mode(Control::FOCUS_NONE);
- play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY));
+ play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY));
play_button->set_tooltip(TTR("Play the project."));
ED_SHORTCUT_AND_COMMAND("editor/play", TTR("Play"), Key::F5);
@@ -6688,7 +6744,7 @@ EditorNode::EditorNode() {
play_hb->add_child(stop_button);
stop_button->set_focus_mode(Control::FOCUS_NONE);
stop_button->set_icon(gui_base->get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
- stop_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_STOP));
+ stop_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_STOP));
stop_button->set_tooltip(TTR("Stop the scene."));
stop_button->set_disabled(true);
@@ -6706,7 +6762,7 @@ EditorNode::EditorNode() {
play_scene_button->set_toggle_mode(true);
play_scene_button->set_focus_mode(Control::FOCUS_NONE);
play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons")));
- play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_SCENE));
+ play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_SCENE));
play_scene_button->set_tooltip(TTR("Play the edited scene."));
ED_SHORTCUT_AND_COMMAND("editor/play_scene", TTR("Play Scene"), Key::F6);
@@ -6719,7 +6775,7 @@ EditorNode::EditorNode() {
play_custom_scene_button->set_toggle_mode(true);
play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE);
play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons")));
- play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_CUSTOM_SCENE));
+ play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_CUSTOM_SCENE));
play_custom_scene_button->set_tooltip(TTR("Play custom scene"));
ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F5);
@@ -6733,15 +6789,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);
@@ -6788,8 +6841,8 @@ EditorNode::EditorNode() {
video_restart_dialog = memnew(ConfirmationDialog);
video_restart_dialog->set_text(TTR("Changing the video driver requires restarting the editor."));
- video_restart_dialog->get_ok_button()->set_text(TTR("Save & Restart"));
- video_restart_dialog->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SET_RENDERING_DRIVER_SAVE_AND_RESTART));
+ video_restart_dialog->set_ok_button_text(TTR("Save & Restart"));
+ video_restart_dialog->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(SET_RENDERING_DRIVER_SAVE_AND_RESTART));
gui_base->add_child(video_restart_dialog);
progress_hb = memnew(BackgroundProgress);
@@ -6822,6 +6875,7 @@ EditorNode::EditorNode() {
filesystem_dock->connect("inherit", callable_mp(this, &EditorNode::_inherit_request));
filesystem_dock->connect("instance", callable_mp(this, &EditorNode::_instantiate_request));
filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_docks));
+ get_project_settings()->connect_filesystem_dock_signals(filesystem_dock);
// Scene: Top left.
dock_slot[DOCK_SLOT_LEFT_UR]->add_child(SceneTreeDock::get_singleton());
@@ -6957,9 +7011,9 @@ EditorNode::EditorNode() {
custom_build_manage_templates = memnew(ConfirmationDialog);
custom_build_manage_templates->set_text(TTR("Android build template is missing, please install relevant templates."));
- custom_build_manage_templates->get_ok_button()->set_text(TTR("Manage Templates"));
- custom_build_manage_templates->add_button(TTR("Install from file"))->connect("pressed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE));
- custom_build_manage_templates->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_MANAGE_EXPORT_TEMPLATES));
+ custom_build_manage_templates->set_ok_button_text(TTR("Manage Templates"));
+ custom_build_manage_templates->add_button(TTR("Install from file"))->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE));
+ custom_build_manage_templates->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(SETTINGS_MANAGE_EXPORT_TEMPLATES));
gui_base->add_child(custom_build_manage_templates);
file_android_build_source = memnew(EditorFileDialog);
@@ -6972,14 +7026,14 @@ EditorNode::EditorNode() {
install_android_build_template = memnew(ConfirmationDialog);
install_android_build_template->set_text(TTR("This will set up your project for custom Android builds by installing the source template to \"res://android/build\".\nYou can then apply modifications and build your own custom APK on export (adding modules, changing the AndroidManifest.xml, etc.).\nNote that in order to make custom builds instead of using pre-built APKs, the \"Use Custom Build\" option should be enabled in the Android export preset."));
- install_android_build_template->get_ok_button()->set_text(TTR("Install"));
+ install_android_build_template->set_ok_button_text(TTR("Install"));
install_android_build_template->connect("confirmed", callable_mp(this, &EditorNode::_menu_confirm_current));
gui_base->add_child(install_android_build_template);
remove_android_build_template = memnew(ConfirmationDialog);
remove_android_build_template->set_text(TTR("The Android build template is already installed in this project and it won't be overwritten.\nRemove the \"res://android/build\" directory manually before attempting this operation again."));
- remove_android_build_template->get_ok_button()->set_text(TTR("Show in File Manager"));
- remove_android_build_template->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(FILE_EXPLORE_ANDROID_BUILD_TEMPLATES));
+ remove_android_build_template->set_ok_button_text(TTR("Show in File Manager"));
+ remove_android_build_template->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(FILE_EXPLORE_ANDROID_BUILD_TEMPLATES));
gui_base->add_child(remove_android_build_template);
file_templates = memnew(EditorFileDialog);
@@ -6989,7 +7043,7 @@ EditorNode::EditorNode() {
file_templates->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
file_templates->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
file_templates->clear_filters();
- file_templates->add_filter("*.tpz ; " + TTR("Template Package"));
+ file_templates->add_filter("*.tpz", TTR("Template Package"));
file = memnew(EditorFileDialog);
gui_base->add_child(file);
@@ -7053,7 +7107,7 @@ EditorNode::EditorNode() {
disk_changed->connect("confirmed", callable_mp(this, &EditorNode::_reload_modified_scenes));
disk_changed->connect("confirmed", callable_mp(this, &EditorNode::_reload_project_settings));
- disk_changed->get_ok_button()->set_text(TTR("Reload"));
+ disk_changed->set_ok_button_text(TTR("Reload"));
disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave");
disk_changed->connect("custom_action", callable_mp(this, &EditorNode::_resave_scenes));
@@ -7071,15 +7125,11 @@ 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.
-#ifndef JAVASCRIPT_ENABLED
- if (StreamPeerSSL::is_available()) {
+ 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).");
}
-#endif
// Add interface before adding plugins.
@@ -7088,64 +7138,64 @@ EditorNode::EditorNode() {
// More visually meaningful to have this later.
raise_bottom_panel_item(AnimationPlayerEditor::get_singleton());
- add_editor_plugin(memnew(ReplicationEditorPlugin));
add_editor_plugin(VersionControlEditorPlugin::get_singleton());
- add_editor_plugin(memnew(ShaderEditorPlugin));
- add_editor_plugin(memnew(ShaderFileEditorPlugin));
+ // This list is alphabetized, and plugins that depend on Node2D are in their own section below.
+ add_editor_plugin(memnew(AnimationTreeEditorPlugin));
+ add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor)));
+ add_editor_plugin(memnew(AudioStreamRandomizerEditorPlugin));
+ add_editor_plugin(memnew(BitMapEditorPlugin));
+ add_editor_plugin(memnew(BoneMapEditorPlugin));
add_editor_plugin(memnew(Camera3DEditorPlugin));
- add_editor_plugin(memnew(ThemeEditorPlugin));
- add_editor_plugin(memnew(MultiMeshEditorPlugin));
+ add_editor_plugin(memnew(ControlEditorPlugin));
+ add_editor_plugin(memnew(CPUParticles3DEditorPlugin));
+ add_editor_plugin(memnew(CurveEditorPlugin));
+ add_editor_plugin(memnew(FontEditorPlugin));
+ add_editor_plugin(memnew(GPUParticles3DEditorPlugin));
+ add_editor_plugin(memnew(GPUParticlesCollisionSDF3DEditorPlugin));
+ add_editor_plugin(memnew(GradientEditorPlugin));
+ add_editor_plugin(memnew(GradientTexture2DEditorPlugin));
+ add_editor_plugin(memnew(InputEventEditorPlugin));
+ add_editor_plugin(memnew(LightmapGIEditorPlugin));
+ add_editor_plugin(memnew(MaterialEditorPlugin));
+ add_editor_plugin(memnew(MeshEditorPlugin));
add_editor_plugin(memnew(MeshInstance3DEditorPlugin));
- add_editor_plugin(memnew(AnimationTreeEditorPlugin));
add_editor_plugin(memnew(MeshLibraryEditorPlugin));
- add_editor_plugin(memnew(StyleBoxEditorPlugin));
- add_editor_plugin(memnew(Sprite2DEditorPlugin));
- add_editor_plugin(memnew(Skeleton2DEditorPlugin));
- add_editor_plugin(memnew(GPUParticles2DEditorPlugin));
- add_editor_plugin(memnew(GPUParticles3DEditorPlugin));
- add_editor_plugin(memnew(CPUParticles2DEditorPlugin));
- add_editor_plugin(memnew(CPUParticles3DEditorPlugin));
- add_editor_plugin(memnew(ResourcePreloaderEditorPlugin));
+ add_editor_plugin(memnew(MultiMeshEditorPlugin));
+ add_editor_plugin(memnew(OccluderInstance3DEditorPlugin));
+ add_editor_plugin(memnew(Path3DEditorPlugin));
+ add_editor_plugin(memnew(PhysicalBone3DEditorPlugin));
add_editor_plugin(memnew(Polygon3DEditorPlugin));
- add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin));
- add_editor_plugin(memnew(TilesEditorPlugin));
+ add_editor_plugin(memnew(ResourcePreloaderEditorPlugin));
+ add_editor_plugin(memnew(ShaderEditorPlugin));
+ add_editor_plugin(memnew(ShaderFileEditorPlugin));
+ add_editor_plugin(memnew(Skeleton3DEditorPlugin));
+ add_editor_plugin(memnew(SkeletonIK3DEditorPlugin));
add_editor_plugin(memnew(SpriteFramesEditorPlugin));
+ add_editor_plugin(memnew(StyleBoxEditorPlugin));
+ add_editor_plugin(memnew(SubViewportPreviewEditorPlugin));
+ add_editor_plugin(memnew(Texture3DEditorPlugin));
+ add_editor_plugin(memnew(TextureEditorPlugin));
+ add_editor_plugin(memnew(TextureLayeredEditorPlugin));
add_editor_plugin(memnew(TextureRegionEditorPlugin));
+ add_editor_plugin(memnew(ThemeEditorPlugin));
add_editor_plugin(memnew(VoxelGIEditorPlugin));
- add_editor_plugin(memnew(LightmapGIEditorPlugin));
- add_editor_plugin(memnew(OccluderInstance3DEditorPlugin));
- add_editor_plugin(memnew(Path2DEditorPlugin));
- add_editor_plugin(memnew(Path3DEditorPlugin));
- add_editor_plugin(memnew(Line2DEditorPlugin));
- add_editor_plugin(memnew(Polygon2DEditorPlugin));
+
+ // 2D
+ add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin));
+ add_editor_plugin(memnew(CollisionShape2DEditorPlugin));
+ add_editor_plugin(memnew(CPUParticles2DEditorPlugin));
+ add_editor_plugin(memnew(GPUParticles2DEditorPlugin));
add_editor_plugin(memnew(LightOccluder2DEditorPlugin));
+ add_editor_plugin(memnew(Line2DEditorPlugin));
add_editor_plugin(memnew(NavigationPolygonEditorPlugin));
- add_editor_plugin(memnew(GradientEditorPlugin));
- 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));
- add_editor_plugin(memnew(AudioStreamEditorPlugin));
- add_editor_plugin(memnew(AudioStreamRandomizerEditorPlugin));
- add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor)));
- add_editor_plugin(memnew(Skeleton3DEditorPlugin));
- add_editor_plugin(memnew(SkeletonIK3DEditorPlugin));
- add_editor_plugin(memnew(PhysicalBone3DEditorPlugin));
- add_editor_plugin(memnew(MeshEditorPlugin));
- add_editor_plugin(memnew(MaterialEditorPlugin));
- 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(Path2DEditorPlugin));
+ add_editor_plugin(memnew(Polygon2DEditorPlugin));
+ add_editor_plugin(memnew(Cast2DEditorPlugin));
+ add_editor_plugin(memnew(Skeleton2DEditorPlugin));
+ add_editor_plugin(memnew(Sprite2DEditorPlugin));
+ add_editor_plugin(memnew(TilesEditorPlugin));
for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) {
add_editor_plugin(EditorPlugins::create(i));
@@ -7203,6 +7253,7 @@ EditorNode::EditorNode() {
vshader_convert.instantiate();
resource_conversion_plugins.push_back(vshader_convert);
}
+
update_spinner_step_msec = OS::get_singleton()->get_ticks_msec();
update_spinner_step_frame = Engine::get_singleton()->get_frames_drawn();
@@ -7232,7 +7283,7 @@ EditorNode::EditorNode() {
set_process(true);
open_imported = memnew(ConfirmationDialog);
- open_imported->get_ok_button()->set_text(TTR("Open Anyway"));
+ open_imported->set_ok_button_text(TTR("Open Anyway"));
new_inherited_button = open_imported->add_button(TTR("New Inherited"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "inherit");
open_imported->connect("confirmed", callable_mp(this, &EditorNode::_open_imported));
open_imported->connect("custom_action", callable_mp(this, &EditorNode::_inherit_imported));
@@ -7273,8 +7324,8 @@ EditorNode::EditorNode() {
pick_main_scene = memnew(ConfirmationDialog);
gui_base->add_child(pick_main_scene);
- pick_main_scene->get_ok_button()->set_text(TTR("Select"));
- pick_main_scene->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_PICK_MAIN_SCENE));
+ pick_main_scene->set_ok_button_text(TTR("Select"));
+ pick_main_scene->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(SETTINGS_PICK_MAIN_SCENE));
select_current_scene_button = pick_main_scene->add_button(TTR("Select Current"), true, "select_current");
pick_main_scene->connect("custom_action", callable_mp(this, &EditorNode::_pick_main_scene_custom_action));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index c327a73ce9..0201e84eaf 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -32,12 +32,11 @@
#define EDITOR_NODE_H
#include "core/templates/safe_refcount.h"
-#include "editor/editor_export.h"
#include "editor/editor_folding.h"
#include "editor/editor_native_shader_source_visualizer.h"
#include "editor/editor_run.h"
+#include "editor/export/editor_export.h"
#include "editor/inspector_dock.h"
-#include "editor/property_editor.h"
typedef void (*EditorNodeInitCallback)();
typedef void (*EditorPluginInitializeCallback)();
@@ -48,6 +47,7 @@ class AudioStreamPreviewGenerator;
class BackgroundProgress;
class Button;
class CenterContainer;
+class ColorPicker;
class ConfirmationDialog;
class Control;
class DependencyEditor;
@@ -67,6 +67,7 @@ class EditorPlugin;
class EditorPluginList;
class EditorQuickOpen;
class EditorResourcePreview;
+class EditorResourceConversionPlugin;
class EditorRun;
class EditorRunNative;
class EditorSettingsDialog;
@@ -88,6 +89,7 @@ class ProjectExportDialog;
class ProjectSettingsEditor;
class RunSettingsDialog;
class SceneImportSettings;
+class AudioStreamImportSettings;
class ScriptCreateDialog;
class SubViewport;
class TabBar;
@@ -95,6 +97,7 @@ class TabContainer;
class TextureProgressBar;
class VSplitContainer;
class Window;
+class EditorBuildProfileManager;
class EditorNode : public Node {
GDCLASS(EditorNode, Node);
@@ -163,6 +166,7 @@ private:
EDIT_REDO,
EDIT_RELOAD_SAVED_SCENE,
TOOLS_ORPHAN_RESOURCES,
+ TOOLS_BUILD_PROFILE_MANAGER,
TOOLS_CUSTOM,
RESOURCE_SAVE,
RESOURCE_SAVE_AS,
@@ -173,7 +177,6 @@ private:
RUN_PLAY_CUSTOM_SCENE,
RUN_SETTINGS,
RUN_USER_DATA_FOLDER,
- RUN_WRITE_MOVIE,
RELOAD_CURRENT_PROJECT,
RUN_PROJECT_MANAGER,
RUN_VCS_METADATA,
@@ -378,6 +381,7 @@ private:
EditorFileDialog *file = nullptr;
ExportTemplateManager *export_template_manager = nullptr;
EditorFeatureProfileManager *feature_profile_manager = nullptr;
+ EditorBuildProfileManager *build_profile_manager = nullptr;
EditorFileDialog *file_templates = nullptr;
EditorFileDialog *file_export_lib = nullptr;
EditorFileDialog *file_script = nullptr;
@@ -469,6 +473,7 @@ private:
DynamicFontImportSettings *fontdata_import_settings = nullptr;
SceneImportSettings *scene_import_settings = nullptr;
+ AudioStreamImportSettings *audio_stream_import_settings = nullptr;
String import_reload_fn;
@@ -669,7 +674,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);
@@ -785,6 +789,8 @@ public:
void set_current_version(uint64_t p_version);
void set_current_scene(int p_idx);
+ void setup_color_picker(ColorPicker *picker);
+
void request_instance_scene(const String &p_path);
void request_instantiate_scenes(const Vector<String> &p_files);
diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp
index 6453db3b0b..dc77b5fea9 100644
--- a/editor/editor_path.cpp
+++ b/editor/editor_path.cpp
@@ -198,7 +198,7 @@ EditorPath::EditorPath(EditorSelectionHistory *p_history) {
history = p_history;
MarginContainer *main_mc = memnew(MarginContainer);
- main_mc->set_anchors_and_offsets_preset(PRESET_WIDE);
+ main_mc->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
main_mc->add_theme_constant_override("margin_left", 4 * EDSCALE);
main_mc->add_theme_constant_override("margin_right", 6 * EDSCALE);
add_child(main_mc);
diff --git a/editor/editor_paths.cpp b/editor/editor_paths.cpp
index a5c2fe093c..b6364e1ab7 100644
--- a/editor/editor_paths.cpp
+++ b/editor/editor_paths.cpp
@@ -66,6 +66,30 @@ String EditorPaths::get_self_contained_file() const {
return self_contained_file;
}
+String EditorPaths::get_export_templates_dir() const {
+ return get_data_dir().plus_file(export_templates_folder);
+}
+
+String EditorPaths::get_project_settings_dir() const {
+ return get_project_data_dir().plus_file("editor");
+}
+
+String EditorPaths::get_text_editor_themes_dir() const {
+ return get_config_dir().plus_file(text_editor_themes_folder);
+}
+
+String EditorPaths::get_script_templates_dir() const {
+ return get_config_dir().plus_file(script_templates_folder);
+}
+
+String EditorPaths::get_project_script_templates_dir() const {
+ return ProjectSettings::get_singleton()->get("editor/script/templates_search_path");
+}
+
+String EditorPaths::get_feature_profiles_dir() const {
+ return get_config_dir().plus_file(feature_profiles_folder);
+}
+
void EditorPaths::create() {
ERR_FAIL_COND(singleton != nullptr);
memnew(EditorPaths());
@@ -82,6 +106,8 @@ void EditorPaths::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cache_dir"), &EditorPaths::get_cache_dir);
ClassDB::bind_method(D_METHOD("is_self_contained"), &EditorPaths::is_self_contained);
ClassDB::bind_method(D_METHOD("get_self_contained_file"), &EditorPaths::get_self_contained_file);
+
+ ClassDB::bind_method(D_METHOD("get_project_settings_dir"), &EditorPaths::get_project_settings_dir);
}
EditorPaths::EditorPaths() {
@@ -153,8 +179,8 @@ EditorPaths::EditorPaths() {
}
}
- if (!dir->dir_exists("templates")) {
- dir->make_dir("templates");
+ if (!dir->dir_exists(export_templates_folder)) {
+ dir->make_dir(export_templates_folder);
}
}
@@ -168,14 +194,14 @@ EditorPaths::EditorPaths() {
}
}
- if (!dir->dir_exists("text_editor_themes")) {
- dir->make_dir("text_editor_themes");
+ if (!dir->dir_exists(text_editor_themes_folder)) {
+ dir->make_dir(text_editor_themes_folder);
}
- if (!dir->dir_exists("script_templates")) {
- dir->make_dir("script_templates");
+ if (!dir->dir_exists(script_templates_folder)) {
+ dir->make_dir(script_templates_folder);
}
- if (!dir->dir_exists("feature_profiles")) {
- dir->make_dir("feature_profiles");
+ if (!dir->dir_exists(feature_profiles_folder)) {
+ dir->make_dir(feature_profiles_folder);
}
}
@@ -192,7 +218,6 @@ EditorPaths::EditorPaths() {
// Validate or create project-specific editor data dir,
// including shader cache subdir.
-
if (Engine::get_singleton()->is_project_manager_hint() || Main::is_cmdline_tool()) {
// Nothing to create, use shared editor data dir for shader cache.
Engine::get_singleton()->set_shader_cache_path(data_dir);
diff --git a/editor/editor_paths.h b/editor/editor_paths.h
index 7d863a7c6c..9cff1063c5 100644
--- a/editor/editor_paths.h
+++ b/editor/editor_paths.h
@@ -45,6 +45,10 @@ class EditorPaths : public Object {
String project_data_dir; // Project-specific data (metadata, shader cache, etc.).
bool self_contained = false; // Self-contained means everything goes to `editor_data` dir.
String self_contained_file; // Self-contained file with configuration.
+ String export_templates_folder = "export_templates";
+ String text_editor_themes_folder = "text_editor_themes";
+ String script_templates_folder = "script_templates";
+ String feature_profiles_folder = "feature_profiles";
static EditorPaths *singleton;
@@ -58,6 +62,12 @@ public:
String get_config_dir() const;
String get_cache_dir() const;
String get_project_data_dir() const;
+ String get_export_templates_dir() const;
+ String get_project_settings_dir() const;
+ String get_text_editor_themes_dir() const;
+ String get_script_templates_dir() const;
+ String get_project_script_templates_dir() const;
+ String get_feature_profiles_dir() const;
bool is_self_contained() const;
String get_self_contained_file() const;
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 639846861b..566c22f5a9 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -31,11 +31,11 @@
#include "editor_plugin.h"
#include "editor/editor_command_palette.h"
-#include "editor/editor_export.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_settings.h"
+#include "editor/export/editor_export.h"
#include "editor/filesystem_dock.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
@@ -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_plugin.h b/editor/editor_plugin.h
index c666b4639d..84c63d1021 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -346,4 +346,4 @@ public:
}
};
-#endif
+#endif // EDITOR_PLUGIN_H
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index 3a0b875b8c..5a010a66c1 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "scene/gui/margin_container.h"
+#include "scene/gui/tree.h"
void EditorPluginSettings::_notification(int p_what) {
switch (p_what) {
diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h
index 4903a02c4d..9c619066f2 100644
--- a/editor/editor_plugin_settings.h
+++ b/editor/editor_plugin_settings.h
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITORPLUGINSETTINGS_H
-#define EDITORPLUGINSETTINGS_H
+#ifndef EDITOR_PLUGIN_SETTINGS_H
+#define EDITOR_PLUGIN_SETTINGS_H
#include "core/object/undo_redo.h"
#include "editor/editor_data.h"
#include "editor/plugin_config_dialog.h"
-#include "property_editor.h"
-#include "scene/gui/dialogs.h"
+
+class Tree;
class EditorPluginSettings : public VBoxContainer {
GDCLASS(EditorPluginSettings, VBoxContainer);
@@ -65,4 +65,4 @@ public:
EditorPluginSettings();
};
-#endif // EDITORPLUGINSETTINGS_H
+#endif // EDITOR_PLUGIN_SETTINGS_H
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index aff328bba7..5e66d436fc 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -133,6 +133,11 @@ void EditorPropertyMultilineText::_text_changed() {
void EditorPropertyMultilineText::_open_big_text() {
if (!big_text_dialog) {
big_text = memnew(TextEdit);
+ if (expression) {
+ big_text->set_syntax_highlighter(text->get_syntax_highlighter());
+ big_text->add_theme_font_override("font", get_theme_font(SNAME("expression"), SNAME("EditorFonts")));
+ big_text->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("expression_size"), SNAME("EditorFonts")));
+ }
big_text->connect("text_changed", callable_mp(this, &EditorPropertyMultilineText::_big_text_changed));
big_text->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY);
big_text_dialog = memnew(AcceptDialog);
@@ -162,12 +167,24 @@ void EditorPropertyMultilineText::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
Ref<Texture2D> df = get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons"));
open_big_text->set_icon(df);
- Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
- int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
- text->set_custom_minimum_size(Vector2(0, font->get_height(font_size) * 6));
- text->add_theme_font_override("font", get_theme_font("expression", "EditorFonts"));
- text->add_theme_font_size_override("font_size", get_theme_font_size("expression_size", "EditorFonts"));
+ Ref<Font> font;
+ int font_size;
+ if (expression) {
+ font = get_theme_font(SNAME("expression"), SNAME("EditorFonts"));
+ font_size = get_theme_font_size(SNAME("expression_size"), SNAME("EditorFonts"));
+
+ text->add_theme_font_override("font", font);
+ text->add_theme_font_size_override("font_size", font_size);
+ if (big_text) {
+ big_text->add_theme_font_override("font", font);
+ big_text->add_theme_font_size_override("font_size", font_size);
+ }
+ } else {
+ font = get_theme_font(SNAME("font"), SNAME("TextEdit"));
+ font_size = get_theme_font_size(SNAME("font_size"), SNAME("TextEdit"));
+ }
+ text->set_custom_minimum_size(Vector2(0, font->get_height(font_size) * 6));
} break;
}
}
@@ -490,13 +507,55 @@ void EditorPropertyPath::_path_focus_exited() {
_path_selected(path->get_text());
}
+void EditorPropertyPath::_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+ const Dictionary drag_data = p_data;
+ if (!drag_data.has("type")) {
+ return;
+ }
+ if (String(drag_data["type"]) != "files") {
+ return;
+ }
+ const Vector<String> filesPaths = drag_data["files"];
+ if (filesPaths.size() == 0) {
+ return;
+ }
+
+ emit_changed(get_edited_property(), filesPaths[0]);
+ update_property();
+}
+
+bool EditorPropertyPath::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+ const Dictionary drag_data = p_data;
+ if (!drag_data.has("type")) {
+ return false;
+ }
+ if (String(drag_data["type"]) != "files") {
+ return false;
+ }
+ const Vector<String> filesPaths = drag_data["files"];
+ if (filesPaths.size() == 0) {
+ return false;
+ }
+
+ for (const String &extension : extensions) {
+ if (filesPaths[0].ends_with(extension.substr(1, extension.size() - 1))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void EditorPropertyPath::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw", "position", "data", "from"), &EditorPropertyPath::_can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw", "position", "data", "from"), &EditorPropertyPath::_drop_data_fw);
}
EditorPropertyPath::EditorPropertyPath() {
HBoxContainer *path_hb = memnew(HBoxContainer);
add_child(path_hb);
path = memnew(LineEdit);
+ path->set_drag_forwarding(this);
path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
path_hb->add_child(path);
path->connect("text_submitted", callable_mp(this, &EditorPropertyPath::_path_selected));
@@ -774,7 +833,7 @@ void EditorPropertyFlags::setup(const Vector<String> &p_options) {
CheckBox *cb = memnew(CheckBox);
cb->set_text(option);
cb->set_clip_text(true);
- cb->connect("pressed", callable_mp(this, &EditorPropertyFlags::_flag_toggled), varray(i));
+ cb->connect("pressed", callable_mp(this, &EditorPropertyFlags::_flag_toggled).bind(i));
add_focusable(cb);
vbox->add_child(cb);
flags.push_back(cb);
@@ -836,7 +895,7 @@ EditorPropertyLayersGrid::EditorPropertyLayersGrid() {
rename_dialog->add_child(rename_dialog_vb);
rename_dialog_text = memnew(LineEdit);
rename_dialog_vb->add_margin_child(TTR("Name:"), rename_dialog_text);
- rename_dialog->get_ok_button()->set_text(TTR("Rename"));
+ rename_dialog->set_ok_button_text(TTR("Rename"));
add_child(rename_dialog);
rename_dialog->register_text_enter(rename_dialog_text);
rename_dialog->connect("confirmed", callable_mp(this, &EditorPropertyLayersGrid::_rename_operation_confirm));
@@ -1236,7 +1295,7 @@ EditorPropertyLayers::EditorPropertyLayers() {
add_child(layers);
layers->set_hide_on_checkable_item_selection(false);
layers->connect("id_pressed", callable_mp(this, &EditorPropertyLayers::_menu_pressed));
- layers->connect("popup_hide", callable_mp((BaseButton *)button, &BaseButton::set_pressed), varray(false));
+ layers->connect("popup_hide", callable_mp((BaseButton *)button, &BaseButton::set_pressed).bind(false));
EditorNode::get_singleton()->connect("project_settings_changed", callable_mp(this, &EditorPropertyLayers::_refresh_names));
}
@@ -1304,7 +1363,7 @@ void EditorPropertyObjectID::update_property() {
ObjectID id = get_edited_object()->get(get_edited_property());
if (id.is_valid()) {
- edit->set_text(type + " ID: " + itos(id));
+ edit->set_text(type + " ID: " + uitos(id));
edit->set_disabled(false);
edit->set_icon(EditorNode::get_singleton()->get_class_icon(type));
} else {
@@ -1328,6 +1387,54 @@ EditorPropertyObjectID::EditorPropertyObjectID() {
edit->connect("pressed", callable_mp(this, &EditorPropertyObjectID::_edit_pressed));
}
+///////////////////// SIGNAL /////////////////////////
+
+void EditorPropertySignal::_edit_pressed() {
+ Signal signal = get_edited_object()->get(get_edited_property());
+ emit_signal(SNAME("object_id_selected"), get_edited_property(), signal.get_object_id());
+}
+
+void EditorPropertySignal::update_property() {
+ String type = base_type;
+
+ Signal signal = get_edited_object()->get(get_edited_property());
+
+ edit->set_text("Signal: " + signal.get_name());
+ edit->set_disabled(false);
+ edit->set_icon(get_theme_icon(SNAME("Signals"), SNAME("EditorIcons")));
+}
+
+void EditorPropertySignal::_bind_methods() {
+}
+
+EditorPropertySignal::EditorPropertySignal() {
+ edit = memnew(Button);
+ add_child(edit);
+ add_focusable(edit);
+ edit->connect("pressed", callable_mp(this, &EditorPropertySignal::_edit_pressed));
+}
+
+///////////////////// CALLABLE /////////////////////////
+
+void EditorPropertyCallable::update_property() {
+ String type = base_type;
+
+ Callable callable = get_edited_object()->get(get_edited_property());
+
+ edit->set_text("Callable");
+ edit->set_disabled(true);
+ edit->set_icon(get_theme_icon(SNAME("Callable"), SNAME("EditorIcons")));
+}
+
+void EditorPropertyCallable::_bind_methods() {
+}
+
+EditorPropertyCallable::EditorPropertyCallable() {
+ edit = memnew(Button);
+ add_child(edit);
+ add_focusable(edit);
+}
+
///////////////////// FLOAT /////////////////////////
void EditorPropertyFloat::_set_read_only(bool p_read_only) {
@@ -1532,6 +1639,11 @@ void EditorPropertyEasing::_spin_value_changed(double p_value) {
// which can cause crashes and other issues.
p_value = CLAMP(p_value, -1'000'000, 1'000'000);
+ if (positive_only) {
+ // Force a positive or zero value if a negative value was manually entered by double-clicking.
+ p_value = MAX(0.0, p_value);
+ }
+
emit_changed(get_edited_property(), p_value);
_spin_focus_exited();
}
@@ -1543,9 +1655,9 @@ void EditorPropertyEasing::_spin_focus_exited() {
easing_draw->update();
}
-void EditorPropertyEasing::setup(bool p_full, bool p_flip) {
+void EditorPropertyEasing::setup(bool p_positive_only, bool p_flip) {
flip = p_flip;
- full = p_full;
+ positive_only = p_positive_only;
}
void EditorPropertyEasing::_notification(int p_what) {
@@ -1553,13 +1665,13 @@ void EditorPropertyEasing::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_ENTER_TREE: {
preset->clear();
- preset->add_icon_item(get_theme_icon(SNAME("CurveConstant"), SNAME("EditorIcons")), "Zero", EASING_ZERO);
preset->add_icon_item(get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons")), "Linear", EASING_LINEAR);
- preset->add_icon_item(get_theme_icon(SNAME("CurveIn"), SNAME("EditorIcons")), "In", EASING_IN);
- preset->add_icon_item(get_theme_icon(SNAME("CurveOut"), SNAME("EditorIcons")), "Out", EASING_OUT);
- if (full) {
- preset->add_icon_item(get_theme_icon(SNAME("CurveInOut"), SNAME("EditorIcons")), "In-Out", EASING_IN_OUT);
- preset->add_icon_item(get_theme_icon(SNAME("CurveOutIn"), SNAME("EditorIcons")), "Out-In", EASING_OUT_IN);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveIn"), SNAME("EditorIcons")), "Ease In", EASING_IN);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveOut"), SNAME("EditorIcons")), "Ease Out", EASING_OUT);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveConstant"), SNAME("EditorIcons")), "Zero", EASING_ZERO);
+ if (!positive_only) {
+ preset->add_icon_item(get_theme_icon(SNAME("CurveInOut"), SNAME("EditorIcons")), "Ease In-Out", EASING_IN_OUT);
+ preset->add_icon_item(get_theme_icon(SNAME("CurveOutIn"), SNAME("EditorIcons")), "Ease Out-In", EASING_OUT_IN);
}
easing_draw->set_custom_minimum_size(Size2(0, get_theme_font(SNAME("font"), SNAME("Label"))->get_height(get_theme_font_size(SNAME("font_size"), SNAME("Label"))) * 2));
} break;
@@ -1707,7 +1819,7 @@ EditorPropertyVector2::EditorPropertyVector2(bool p_force_wide) {
spin[i]->set_label(desc[i]);
bc->add_child(spin[i]);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector2::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector2::_value_changed).bind(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
@@ -1817,7 +1929,7 @@ EditorPropertyRect2::EditorPropertyRect2(bool p_force_wide) {
}
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2::_value_changed).bind(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
@@ -1989,7 +2101,7 @@ EditorPropertyVector3::EditorPropertyVector3(bool p_force_wide) {
spin[i]->set_label(desc[i]);
bc->add_child(spin[i]);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector3::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector3::_value_changed).bind(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
@@ -2120,7 +2232,7 @@ EditorPropertyVector2i::EditorPropertyVector2i(bool p_force_wide) {
spin[i]->set_label(desc[i]);
bc->add_child(spin[i]);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector2i::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector2i::_value_changed).bind(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
@@ -2230,7 +2342,7 @@ EditorPropertyRect2i::EditorPropertyRect2i(bool p_force_wide) {
}
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2i::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyRect2i::_value_changed).bind(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
@@ -2372,7 +2484,7 @@ EditorPropertyVector3i::EditorPropertyVector3i(bool p_force_wide) {
spin[i]->set_label(desc[i]);
bc->add_child(spin[i]);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector3i::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector3i::_value_changed).bind(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
@@ -2473,7 +2585,7 @@ EditorPropertyPlane::EditorPropertyPlane(bool p_force_wide) {
spin[i]->set_label(desc[i]);
bc->add_child(spin[i]);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyPlane::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyPlane::_value_changed).bind(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
@@ -2565,7 +2677,187 @@ EditorPropertyQuaternion::EditorPropertyQuaternion() {
spin[i]->set_label(desc[i]);
bc->add_child(spin[i]);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyQuaternion::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyQuaternion::_value_changed).bind(desc[i]));
+ if (horizontal) {
+ spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
+ }
+ }
+
+ if (!horizontal) {
+ set_label_reference(spin[0]); //show text and buttons around this
+ }
+}
+///////////////////// VECTOR4 /////////////////////////
+
+void EditorPropertyVector4::_set_read_only(bool p_read_only) {
+ for (int i = 0; i < 4; i++) {
+ spin[i]->set_read_only(p_read_only);
+ }
+};
+
+void EditorPropertyVector4::_value_changed(double val, const String &p_name) {
+ if (setting) {
+ return;
+ }
+
+ Vector4 p;
+ p.x = spin[0]->get_value();
+ p.y = spin[1]->get_value();
+ p.z = spin[2]->get_value();
+ p.w = spin[3]->get_value();
+ emit_changed(get_edited_property(), p, p_name);
+}
+
+void EditorPropertyVector4::update_property() {
+ Vector4 val = get_edited_object()->get(get_edited_property());
+ setting = true;
+ spin[0]->set_value(val.x);
+ spin[1]->set_value(val.y);
+ spin[2]->set_value(val.z);
+ spin[3]->set_value(val.w);
+ setting = false;
+}
+
+void EditorPropertyVector4::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ const Color *colors = _get_property_colors();
+ for (int i = 0; i < 4; i++) {
+ spin[i]->add_theme_color_override("label_color", colors[i]);
+ }
+ } break;
+ }
+}
+
+void EditorPropertyVector4::_bind_methods() {
+}
+
+void EditorPropertyVector4::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
+ for (int i = 0; i < 4; i++) {
+ spin[i]->set_min(p_min);
+ spin[i]->set_max(p_max);
+ spin[i]->set_step(p_step);
+ spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
+ // Vector4 is inherently unitless, however someone may want to use it as
+ // a generic way to store 4 values, so we'll still respect the suffix.
+ spin[i]->set_suffix(p_suffix);
+ }
+}
+
+EditorPropertyVector4::EditorPropertyVector4() {
+ bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
+
+ BoxContainer *bc;
+
+ if (horizontal) {
+ bc = memnew(HBoxContainer);
+ add_child(bc);
+ set_bottom_editor(bc);
+ } else {
+ bc = memnew(VBoxContainer);
+ add_child(bc);
+ }
+
+ static const char *desc[4] = { "x", "y", "z", "w" };
+ for (int i = 0; i < 4; i++) {
+ spin[i] = memnew(EditorSpinSlider);
+ spin[i]->set_flat(true);
+ spin[i]->set_label(desc[i]);
+ bc->add_child(spin[i]);
+ add_focusable(spin[i]);
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector4::_value_changed).bind(desc[i]));
+ if (horizontal) {
+ spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
+ }
+ }
+
+ if (!horizontal) {
+ set_label_reference(spin[0]); //show text and buttons around this
+ }
+}
+
+///////////////////// VECTOR4I /////////////////////////
+
+void EditorPropertyVector4i::_set_read_only(bool p_read_only) {
+ for (int i = 0; i < 4; i++) {
+ spin[i]->set_read_only(p_read_only);
+ }
+};
+
+void EditorPropertyVector4i::_value_changed(double val, const String &p_name) {
+ if (setting) {
+ return;
+ }
+
+ Vector4i p;
+ p.x = spin[0]->get_value();
+ p.y = spin[1]->get_value();
+ p.z = spin[2]->get_value();
+ p.w = spin[3]->get_value();
+ emit_changed(get_edited_property(), p, p_name);
+}
+
+void EditorPropertyVector4i::update_property() {
+ Vector4i val = get_edited_object()->get(get_edited_property());
+ setting = true;
+ spin[0]->set_value(val.x);
+ spin[1]->set_value(val.y);
+ spin[2]->set_value(val.z);
+ spin[3]->set_value(val.w);
+ setting = false;
+}
+
+void EditorPropertyVector4i::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ const Color *colors = _get_property_colors();
+ for (int i = 0; i < 4; i++) {
+ spin[i]->add_theme_color_override("label_color", colors[i]);
+ }
+ } break;
+ }
+}
+
+void EditorPropertyVector4i::_bind_methods() {
+}
+
+void EditorPropertyVector4i::setup(double p_min, double p_max, bool p_no_slider, const String &p_suffix) {
+ for (int i = 0; i < 4; i++) {
+ spin[i]->set_min(p_min);
+ spin[i]->set_max(p_max);
+ spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
+ spin[i]->set_suffix(p_suffix);
+ }
+}
+
+EditorPropertyVector4i::EditorPropertyVector4i() {
+ bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
+
+ BoxContainer *bc;
+
+ if (horizontal) {
+ bc = memnew(HBoxContainer);
+ add_child(bc);
+ set_bottom_editor(bc);
+ } else {
+ bc = memnew(VBoxContainer);
+ add_child(bc);
+ }
+
+ static const char *desc[4] = { "x", "y", "z", "w" };
+ for (int i = 0; i < 4; i++) {
+ spin[i] = memnew(EditorSpinSlider);
+ spin[i]->set_flat(true);
+ spin[i]->set_label(desc[i]);
+ bc->add_child(spin[i]);
+ add_focusable(spin[i]);
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector4i::_value_changed).bind(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
@@ -2654,7 +2946,7 @@ EditorPropertyAABB::EditorPropertyAABB() {
g->add_child(spin[i]);
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyAABB::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyAABB::_value_changed).bind(desc[i]));
}
set_bottom_editor(g);
}
@@ -2745,7 +3037,7 @@ EditorPropertyTransform2D::EditorPropertyTransform2D(bool p_include_origin) {
}
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform2D::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform2D::_value_changed).bind(desc[i]));
}
set_bottom_editor(g);
}
@@ -2835,7 +3127,7 @@ EditorPropertyBasis::EditorPropertyBasis() {
g->add_child(spin[i]);
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyBasis::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyBasis::_value_changed).bind(desc[i]));
}
set_bottom_editor(g);
}
@@ -2933,11 +3225,116 @@ EditorPropertyTransform3D::EditorPropertyTransform3D() {
g->add_child(spin[i]);
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
add_focusable(spin[i]);
- spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform3D::_value_changed), varray(desc[i]));
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform3D::_value_changed).bind(desc[i]));
}
set_bottom_editor(g);
}
+///////////////////// PROJECTION /////////////////////////
+
+void EditorPropertyProjection::_set_read_only(bool p_read_only) {
+ for (int i = 0; i < 12; i++) {
+ spin[i]->set_read_only(p_read_only);
+ }
+};
+
+void EditorPropertyProjection::_value_changed(double val, const String &p_name) {
+ if (setting) {
+ return;
+ }
+
+ Projection p;
+ p.matrix[0][0] = spin[0]->get_value();
+ p.matrix[0][1] = spin[1]->get_value();
+ p.matrix[0][2] = spin[2]->get_value();
+ p.matrix[0][3] = spin[3]->get_value();
+ p.matrix[1][0] = spin[4]->get_value();
+ p.matrix[1][1] = spin[5]->get_value();
+ p.matrix[1][2] = spin[6]->get_value();
+ p.matrix[1][3] = spin[7]->get_value();
+ p.matrix[2][0] = spin[8]->get_value();
+ p.matrix[2][1] = spin[9]->get_value();
+ p.matrix[2][2] = spin[10]->get_value();
+ p.matrix[2][3] = spin[11]->get_value();
+ p.matrix[3][0] = spin[12]->get_value();
+ p.matrix[3][1] = spin[13]->get_value();
+ p.matrix[3][2] = spin[14]->get_value();
+ p.matrix[3][3] = spin[15]->get_value();
+
+ emit_changed(get_edited_property(), p, p_name);
+}
+
+void EditorPropertyProjection::update_property() {
+ update_using_transform(get_edited_object()->get(get_edited_property()));
+}
+
+void EditorPropertyProjection::update_using_transform(Projection p_transform) {
+ setting = true;
+ spin[0]->set_value(p_transform.matrix[0][0]);
+ spin[1]->set_value(p_transform.matrix[0][1]);
+ spin[2]->set_value(p_transform.matrix[0][2]);
+ spin[3]->set_value(p_transform.matrix[0][3]);
+ spin[4]->set_value(p_transform.matrix[1][0]);
+ spin[5]->set_value(p_transform.matrix[1][1]);
+ spin[6]->set_value(p_transform.matrix[1][2]);
+ spin[7]->set_value(p_transform.matrix[1][3]);
+ spin[8]->set_value(p_transform.matrix[2][0]);
+ spin[9]->set_value(p_transform.matrix[2][1]);
+ spin[10]->set_value(p_transform.matrix[2][2]);
+ spin[11]->set_value(p_transform.matrix[2][3]);
+ spin[12]->set_value(p_transform.matrix[3][0]);
+ spin[13]->set_value(p_transform.matrix[3][1]);
+ spin[14]->set_value(p_transform.matrix[3][2]);
+ spin[15]->set_value(p_transform.matrix[3][3]);
+ setting = false;
+}
+
+void EditorPropertyProjection::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ const Color *colors = _get_property_colors();
+ for (int i = 0; i < 16; i++) {
+ spin[i]->add_theme_color_override("label_color", colors[i % 4]);
+ }
+ } break;
+ }
+}
+
+void EditorPropertyProjection::_bind_methods() {
+}
+
+void EditorPropertyProjection::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
+ for (int i = 0; i < 16; i++) {
+ spin[i]->set_min(p_min);
+ spin[i]->set_max(p_max);
+ spin[i]->set_step(p_step);
+ spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
+ if (i % 4 == 3) {
+ spin[i]->set_suffix(p_suffix);
+ }
+ }
+}
+
+EditorPropertyProjection::EditorPropertyProjection() {
+ GridContainer *g = memnew(GridContainer);
+ g->set_columns(4);
+ add_child(g);
+
+ static const char *desc[16] = { "xx", "xy", "xz", "xw", "yx", "yy", "yz", "yw", "zx", "zy", "zz", "zw", "wx", "wy", "wz", "ww" };
+ for (int i = 0; i < 16; i++) {
+ spin[i] = memnew(EditorSpinSlider);
+ spin[i]->set_label(desc[i]);
+ spin[i]->set_flat(true);
+ g->add_child(spin[i]);
+ spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
+ add_focusable(spin[i]);
+ spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyProjection::_value_changed).bind(desc[i]));
+ }
+ set_bottom_editor(g);
+}
////////////// COLOR PICKER //////////////////////
void EditorPropertyColor::_set_read_only(bool p_read_only) {
@@ -2959,19 +3356,6 @@ 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);
- }
-
- int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape");
- picker->get_picker()->set_picker_shape((ColorPicker::PickerShapeType)picker_shape);
-}
-
void EditorPropertyColor::_picker_opening() {
last_color = picker->get_pick_color();
}
@@ -3016,7 +3400,7 @@ EditorPropertyColor::EditorPropertyColor() {
picker->set_flat(true);
picker->connect("color_changed", callable_mp(this, &EditorPropertyColor::_color_changed));
picker->connect("popup_closed", callable_mp(this, &EditorPropertyColor::_popup_closed));
- picker->connect("picker_created", callable_mp(this, &EditorPropertyColor::_picker_created));
+ picker->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(picker->get_picker()));
picker->get_popup()->connect("about_to_popup", callable_mp(this, &EditorPropertyColor::_picker_opening));
}
@@ -3127,7 +3511,25 @@ 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);
+
+ if (valid_types.is_empty()) {
+ // No type requirements specified so any type is valid.
+ return true;
+ }
+
+ for (const StringName &E : valid_types) {
+ if (dropped_node->is_class(E)) {
+ return true;
+ }
+ }
+
+ return false;
}
void EditorPropertyNodePath::update_property() {
@@ -3222,8 +3624,8 @@ EditorPropertyNodePath::EditorPropertyNodePath() {
void EditorPropertyRID::update_property() {
RID rid = get_edited_object()->get(get_edited_property());
if (rid.is_valid()) {
- int id = rid.get_id();
- label->set_text("RID: " + itos(id));
+ uint64_t id = rid.get_id();
+ label->set_text("RID: " + uitos(id));
} else {
label->set_text(TTR("Invalid RID"));
}
@@ -3265,7 +3667,10 @@ void EditorPropertyResource::_resource_selected(const Ref<Resource> &p_resource,
void EditorPropertyResource::_resource_changed(const Ref<Resource> &p_resource) {
// Make visual script the correct type.
Ref<Script> s = p_resource;
+ bool is_script = false;
if (get_edited_object() && s.is_valid()) {
+ is_script = true;
+ InspectorDock::get_singleton()->store_script_properties(get_edited_object());
s->call("set_instance_base_type", get_edited_object()->get_class());
}
@@ -3291,6 +3696,11 @@ void EditorPropertyResource::_resource_changed(const Ref<Resource> &p_resource)
emit_changed(get_edited_property(), p_resource);
update_property();
+ if (is_script) {
+ // Restore properties if script was changed.
+ InspectorDock::get_singleton()->apply_script_properties(get_edited_object());
+ }
+
// Automatically suggest setting up the path for a ViewportTexture.
if (vpt.is_valid() && vpt->get_viewport_path_in_scene().is_empty()) {
if (!scene_tree) {
@@ -3461,6 +3871,9 @@ void EditorPropertyResource::setup(Object *p_object, const String &p_path, const
shader_picker->set_edited_material(Object::cast_to<ShaderMaterial>(p_object));
resource_picker = shader_picker;
connect(SNAME("ready"), callable_mp(this, &EditorPropertyResource::_update_preferred_shader));
+ } else if (p_base_type == "AudioStream") {
+ EditorAudioStreamPicker *astream_picker = memnew(EditorAudioStreamPicker);
+ resource_picker = astream_picker;
} else {
resource_picker = memnew(EditorResourcePicker);
}
@@ -3569,6 +3982,12 @@ void EditorPropertyResource::expand_all_folding() {
}
}
+void EditorPropertyResource::expand_revertable() {
+ if (sub_inspector) {
+ sub_inspector->expand_revertable();
+ }
+}
+
void EditorPropertyResource::set_use_sub_inspector(bool p_enable) {
use_sub_inspector = p_enable;
}
@@ -3750,20 +4169,20 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
case Variant::FLOAT: {
if (p_hint == PROPERTY_HINT_EXP_EASING) {
EditorPropertyEasing *editor = memnew(EditorPropertyEasing);
- bool full = true;
+ bool positive_only = false;
bool flip = false;
- Vector<String> hints = p_hint_text.split(",");
+ const Vector<String> hints = p_hint_text.split(",");
for (int i = 0; i < hints.size(); i++) {
- String h = hints[i].strip_edges();
- if (h == "attenuation") {
+ const String hint = hints[i].strip_edges();
+ if (hint == "attenuation") {
flip = true;
}
- if (h == "inout") {
- full = true;
+ if (hint == "positive_only") {
+ positive_only = true;
}
}
- editor->setup(full, flip);
+ editor->setup(positive_only, flip);
return editor;
} else {
@@ -3898,6 +4317,20 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
return editor;
} break;
+ case Variant::VECTOR4: {
+ EditorPropertyVector4 *editor = memnew(EditorPropertyVector4);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
+
+ } break;
+ case Variant::VECTOR4I: {
+ EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
+ editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix);
+ return editor;
+
+ } break;
case Variant::TRANSFORM2D: {
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
@@ -3935,6 +4368,13 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
return editor;
} break;
+ case Variant::PROJECTION: {
+ EditorPropertyProjection *editor = memnew(EditorPropertyProjection);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
+ editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
+ return editor;
+
+ } break;
// misc types
case Variant::COLOR: {
@@ -3986,11 +4426,11 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
editor->setup(p_object, p_path, p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource");
if (p_hint == PROPERTY_HINT_RESOURCE_TYPE) {
- String open_in_new = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector");
- for (int i = 0; i < open_in_new.get_slice_count(","); i++) {
- String type = open_in_new.get_slicec(',', i).strip_edges();
+ const PackedStringArray open_in_new_inspector = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector");
+
+ for (const String &type : open_in_new_inspector) {
for (int j = 0; j < p_hint_text.get_slice_count(","); j++) {
- String inherits = p_hint_text.get_slicec(',', j);
+ const String inherits = p_hint_text.get_slicec(',', j);
if (ClassDB::is_parent_class(inherits, type)) {
editor->set_use_sub_inspector(false);
}
@@ -4002,6 +4442,14 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
}
} break;
+ case Variant::CALLABLE: {
+ EditorPropertyCallable *editor = memnew(EditorPropertyCallable);
+ return editor;
+ } break;
+ case Variant::SIGNAL: {
+ EditorPropertySignal *editor = memnew(EditorPropertySignal);
+ return editor;
+ } break;
case Variant::DICTIONARY: {
if (p_hint == PROPERTY_HINT_LOCALIZABLE_STRING) {
EditorPropertyLocalizableString *editor = memnew(EditorPropertyLocalizableString);
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 7cd6ea4f6b..5c73a53184 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -142,6 +142,8 @@ class EditorPropertyPath : public EditorProperty {
void _path_selected(const String &p_path);
void _path_pressed();
void _path_focus_exited();
+ void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+ bool _can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
protected:
virtual void _set_read_only(bool p_read_only) override;
@@ -389,6 +391,33 @@ public:
EditorPropertyObjectID();
};
+class EditorPropertySignal : public EditorProperty {
+ GDCLASS(EditorPropertySignal, EditorProperty);
+ Button *edit = nullptr;
+ String base_type;
+ void _edit_pressed();
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual void update_property() override;
+ EditorPropertySignal();
+};
+
+class EditorPropertyCallable : public EditorProperty {
+ GDCLASS(EditorPropertyCallable, EditorProperty);
+ Button *edit = nullptr;
+ String base_type;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual void update_property() override;
+ EditorPropertyCallable();
+};
+
class EditorPropertyFloat : public EditorProperty {
GDCLASS(EditorPropertyFloat, EditorProperty);
EditorSpinSlider *spin = nullptr;
@@ -416,6 +445,7 @@ class EditorPropertyEasing : public EditorProperty {
bool dragging = false;
bool full = false;
bool flip = false;
+ bool positive_only = false;
enum {
EASING_ZERO,
@@ -444,7 +474,7 @@ protected:
public:
virtual void update_property() override;
- void setup(bool p_full, bool p_flip);
+ void setup(bool p_positive_only, bool p_flip);
EditorPropertyEasing();
};
@@ -609,6 +639,40 @@ public:
EditorPropertyQuaternion();
};
+class EditorPropertyVector4 : public EditorProperty {
+ GDCLASS(EditorPropertyVector4, EditorProperty);
+ EditorSpinSlider *spin[4];
+ bool setting = false;
+ void _value_changed(double p_val, const String &p_name);
+
+protected:
+ virtual void _set_read_only(bool p_read_only) override;
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ virtual void update_property() override;
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
+ EditorPropertyVector4();
+};
+
+class EditorPropertyVector4i : public EditorProperty {
+ GDCLASS(EditorPropertyVector4i, EditorProperty);
+ EditorSpinSlider *spin[4];
+ bool setting = false;
+ void _value_changed(double p_val, const String &p_name);
+
+protected:
+ virtual void _set_read_only(bool p_read_only) override;
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ virtual void update_property() override;
+ void setup(double p_min, double p_max, bool p_no_slider, const String &p_suffix = String());
+ EditorPropertyVector4i();
+};
+
class EditorPropertyAABB : public EditorProperty {
GDCLASS(EditorPropertyAABB, EditorProperty);
EditorSpinSlider *spin[6];
@@ -678,6 +742,24 @@ public:
EditorPropertyTransform3D();
};
+class EditorPropertyProjection : public EditorProperty {
+ GDCLASS(EditorPropertyProjection, EditorProperty);
+ EditorSpinSlider *spin[16];
+ bool setting = false;
+ void _value_changed(double p_val, const String &p_name);
+
+protected:
+ virtual void _set_read_only(bool p_read_only) override;
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ virtual void update_property() override;
+ virtual void update_using_transform(Projection p_transform);
+ void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
+ EditorPropertyProjection();
+};
+
class EditorPropertyColor : public EditorProperty {
GDCLASS(EditorPropertyColor, EditorProperty);
ColorPickerButton *picker = nullptr;
@@ -777,6 +859,7 @@ public:
void collapse_all_folding() override;
void expand_all_folding() override;
+ void expand_revertable() override;
void set_use_sub_inspector(bool p_enable);
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index f1a3fe0c57..9a83082d1e 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -211,7 +211,14 @@ void EditorPropertyArray::update_property() {
String array_type_name = Variant::get_type_name(array_type);
if (array_type == Variant::ARRAY && subtype != Variant::NIL) {
- array_type_name = vformat("%s[%s]", array_type_name, Variant::get_type_name(subtype));
+ String type_name;
+ if (subtype == Variant::OBJECT && subtype_hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ type_name = subtype_hint_string;
+ } else {
+ type_name = Variant::get_type_name(subtype);
+ }
+
+ array_type_name = vformat("%s[%s]", array_type_name, type_name);
}
if (array.get_type() == Variant::NIL) {
@@ -322,7 +329,7 @@ void EditorPropertyArray::update_property() {
reorder_button->set_icon(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons")));
reorder_button->set_default_cursor_shape(Control::CURSOR_MOVE);
reorder_button->connect("gui_input", callable_mp(this, &EditorPropertyArray::_reorder_button_gui_input));
- reorder_button->connect("button_down", callable_mp(this, &EditorPropertyArray::_reorder_button_down), varray(i + offset));
+ reorder_button->connect("button_down", callable_mp(this, &EditorPropertyArray::_reorder_button_down).bind(i + offset));
reorder_button->connect("button_up", callable_mp(this, &EditorPropertyArray::_reorder_button_up));
hbox->add_child(reorder_button);
@@ -359,11 +366,11 @@ void EditorPropertyArray::update_property() {
Button *edit = memnew(Button);
edit->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
hbox->add_child(edit);
- edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_change_type), varray(edit, i + offset));
+ edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_change_type).bind(edit, i + offset));
} else {
Button *remove = memnew(Button);
remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
- remove->connect("pressed", callable_mp(this, &EditorPropertyArray::_remove_pressed), varray(i + offset));
+ remove->connect("pressed", callable_mp(this, &EditorPropertyArray::_remove_pressed).bind(i + offset));
hbox->add_child(remove);
}
@@ -942,6 +949,18 @@ void EditorPropertyDictionary::update_property() {
prop = editor;
} break;
+ case Variant::VECTOR4: {
+ EditorPropertyVector4 *editor = memnew(EditorPropertyVector4);
+ editor->setup(-100000, 100000, default_float_step, true);
+ prop = editor;
+
+ } break;
+ case Variant::VECTOR4I: {
+ EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i);
+ editor->setup(-100000, 100000, true);
+ prop = editor;
+
+ } break;
case Variant::TRANSFORM2D: {
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
editor->setup(-100000, 100000, default_float_step, true);
@@ -978,6 +997,12 @@ void EditorPropertyDictionary::update_property() {
prop = editor;
} break;
+ case Variant::PROJECTION: {
+ EditorPropertyProjection *editor = memnew(EditorPropertyProjection);
+ editor->setup(-100000, 100000, default_float_step, true);
+ prop = editor;
+
+ } break;
// Miscellaneous types.
case Variant::COLOR: {
@@ -1111,7 +1136,7 @@ void EditorPropertyDictionary::update_property() {
Button *edit = memnew(Button);
edit->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
hbox->add_child(edit);
- edit->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_change_type), varray(edit, change_index));
+ edit->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_change_type).bind(edit, change_index));
prop->update_property();
@@ -1350,7 +1375,7 @@ void EditorPropertyLocalizableString::update_property() {
Button *edit = memnew(Button);
edit->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
hbox->add_child(edit);
- edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_remove_item), varray(edit, remove_index));
+ edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_remove_item).bind(edit, remove_index));
prop->update_property();
}
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index 44623149d0..82aeebe14a 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -81,10 +81,7 @@ class EditorPropertyArray : public EditorProperty {
GDCLASS(EditorPropertyArray, EditorProperty);
PopupMenu *change_type = nullptr;
- bool updating = false;
- bool dropping = false;
- Ref<EditorPropertyArrayObject> object;
int page_length = 20;
int page_index = 0;
int changing_type_index;
@@ -106,29 +103,35 @@ class EditorPropertyArray : public EditorProperty {
Button *reorder_selected_button = nullptr;
void _page_changed(int p_page);
- void _length_changed(double p_page);
- void _add_element();
- void _edit_pressed();
- void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
- void _change_type(Object *p_button, int p_index);
- void _change_type_menu(int p_index);
-
- void _object_id_selected(const StringName &p_property, ObjectID p_id);
- void _remove_pressed(int p_index);
-
- void _button_draw();
- bool _is_drop_valid(const Dictionary &p_drag_data) const;
- bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
- void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
void _reorder_button_gui_input(const Ref<InputEvent> &p_event);
void _reorder_button_down(int p_index);
void _reorder_button_up();
protected:
+ Ref<EditorPropertyArrayObject> object;
+
+ bool updating = false;
+ bool dropping = false;
+
static void _bind_methods();
void _notification(int p_what);
+ virtual void _add_element();
+ virtual void _length_changed(double p_page);
+ virtual void _edit_pressed();
+ virtual void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
+ virtual void _change_type(Object *p_button, int p_index);
+ virtual void _change_type_menu(int p_index);
+
+ virtual void _object_id_selected(const StringName &p_property, ObjectID p_id);
+ virtual void _remove_pressed(int p_index);
+
+ virtual void _button_draw();
+ virtual bool _is_drop_valid(const Dictionary &p_drag_data) const;
+ virtual bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ virtual void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+
public:
void setup(Variant::Type p_array_type, const String &p_hint_string = "");
virtual void update_property() override;
diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp
index 09d2992e07..6c713de94a 100644
--- a/editor/editor_property_name_processor.cpp
+++ b/editor/editor_property_name_processor.cpp
@@ -114,6 +114,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["bidi"] = "BiDi";
capitalize_string_remaps["bp"] = "BP";
capitalize_string_remaps["bpc"] = "BPC";
+ capitalize_string_remaps["bpm"] = "BPM";
capitalize_string_remaps["bptc"] = "BPTC";
capitalize_string_remaps["bvh"] = "BVH";
capitalize_string_remaps["ca"] = "CA";
diff --git a/editor/quick_open.cpp b/editor/editor_quick_open.cpp
index 4938699fc4..539cb7cd8a 100644
--- a/editor/quick_open.cpp
+++ b/editor/editor_quick_open.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* quick_open.cpp */
+/* editor_quick_open.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "quick_open.h"
+#include "editor_quick_open.h"
#include "core/os/keyboard.h"
@@ -263,6 +263,6 @@ EditorQuickOpen::EditorQuickOpen() {
search_options->add_theme_constant_override("draw_guides", 1);
vbc->add_margin_child(TTR("Matches:"), search_options, true);
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_hide_on_ok(false);
}
diff --git a/editor/quick_open.h b/editor/editor_quick_open.h
index 843ef47711..e41a8c7e75 100644
--- a/editor/quick_open.h
+++ b/editor/editor_quick_open.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* quick_open.h */
+/* editor_quick_open.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 4d53ddb344..e5c1836205 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -30,14 +30,16 @@
#include "editor_resource_picker.h"
+#include "editor/audio_stream_preview.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
+#include "editor/editor_quick_open.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/filesystem_dock.h"
+#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
-#include "editor/quick_open.h"
#include "editor/scene_tree_dock.h"
HashMap<StringName, List<StringName>> EditorResourcePicker::allowed_types_cache;
@@ -47,32 +49,37 @@ void EditorResourcePicker::clear_caches() {
}
void EditorResourcePicker::_update_resource() {
- preview_rect->set_texture(Ref<Texture2D>());
- assign_button->set_custom_minimum_size(Size2(1, 1));
+ String resource_path;
+ if (edited_resource.is_valid() && edited_resource->get_path().is_resource_file()) {
+ resource_path = edited_resource->get_path() + "\n";
+ }
- if (edited_resource == Ref<Resource>()) {
- assign_button->set_icon(Ref<Texture2D>());
- assign_button->set_text(TTR("[empty]"));
- assign_button->set_tooltip("");
- } else {
- assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object"));
+ if (preview_rect) {
+ preview_rect->set_texture(Ref<Texture2D>());
- if (!edited_resource->get_name().is_empty()) {
- assign_button->set_text(edited_resource->get_name());
- } else if (edited_resource->get_path().is_resource_file()) {
- assign_button->set_text(edited_resource->get_path().get_file());
+ assign_button->set_custom_minimum_size(assign_button_min_size);
+
+ if (edited_resource == Ref<Resource>()) {
+ assign_button->set_icon(Ref<Texture2D>());
+ assign_button->set_text(TTR("[empty]"));
+ assign_button->set_tooltip("");
} else {
- assign_button->set_text(edited_resource->get_class());
- }
+ assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object"));
- String resource_path;
- if (edited_resource->get_path().is_resource_file()) {
- resource_path = edited_resource->get_path() + "\n";
+ if (!edited_resource->get_name().is_empty()) {
+ assign_button->set_text(edited_resource->get_name());
+ } else if (edited_resource->get_path().is_resource_file()) {
+ assign_button->set_text(edited_resource->get_path().get_file());
+ } else {
+ assign_button->set_text(edited_resource->get_class());
+ }
+ assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class());
+
+ // Preview will override the above, so called at the end.
+ EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id());
}
+ } else if (edited_resource.is_valid()) {
assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class());
-
- // Preview will override the above, so called at the end.
- EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id());
}
}
@@ -81,28 +88,30 @@ void EditorResourcePicker::_update_resource_preview(const String &p_path, const
return;
}
- Ref<Script> script = edited_resource;
- if (script.is_valid()) {
- assign_button->set_text(script->get_path().get_file());
- return;
- }
+ if (preview_rect) {
+ Ref<Script> script = edited_resource;
+ if (script.is_valid()) {
+ assign_button->set_text(script->get_path().get_file());
+ return;
+ }
- if (p_preview.is_valid()) {
- preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox(SNAME("normal"))->get_default_margin(SIDE_LEFT) + get_theme_constant(SNAME("h_separation"), SNAME("Button")));
+ if (p_preview.is_valid()) {
+ preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox(SNAME("normal"))->get_default_margin(SIDE_LEFT) + get_theme_constant(SNAME("h_separation"), SNAME("Button")));
- // Resource-specific stretching.
- if (Ref<GradientTexture1D>(edited_resource).is_valid() || Ref<Gradient>(edited_resource).is_valid()) {
- preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE);
- assign_button->set_custom_minimum_size(Size2(1, 1));
- } else {
- preview_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size *= EDSCALE;
- assign_button->set_custom_minimum_size(Size2(1, thumbnail_size));
- }
+ // Resource-specific stretching.
+ if (Ref<GradientTexture1D>(edited_resource).is_valid() || Ref<Gradient>(edited_resource).is_valid()) {
+ preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE);
+ assign_button->set_custom_minimum_size(assign_button_min_size);
+ } else {
+ preview_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size *= EDSCALE;
+ assign_button->set_custom_minimum_size(Size2(MIN(1, assign_button_min_size.x), MIN(thumbnail_size, assign_button_min_size.y)));
+ }
- preview_rect->set_texture(p_preview);
- assign_button->set_text("");
+ preview_rect->set_texture(p_preview);
+ assign_button->set_text("");
+ }
}
}
@@ -175,6 +184,21 @@ void EditorResourcePicker::_update_menu_items() {
edit_menu->add_icon_item(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), TTR("Edit"), OBJ_MENU_EDIT);
edit_menu->add_icon_item(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), TTR("Clear"), OBJ_MENU_CLEAR);
edit_menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
+
+ // Check whether the resource has subresources.
+ List<PropertyInfo> property_list;
+ edited_resource->get_property_list(&property_list);
+ bool has_subresources = false;
+ for (PropertyInfo &p : property_list) {
+ if ((p.type == Variant::OBJECT) && (p.hint == PROPERTY_HINT_RESOURCE_TYPE) && (p.name != "script")) {
+ has_subresources = true;
+ break;
+ }
+ }
+ if (has_subresources) {
+ edit_menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Make Unique (Recursive)"), OBJ_MENU_MAKE_UNIQUE_RECURSIVE);
+ }
+
edit_menu->add_icon_item(get_theme_icon(SNAME("Save"), SNAME("EditorIcons")), TTR("Save"), OBJ_MENU_SAVE);
if (edited_resource->get_path().is_resource_file()) {
@@ -254,7 +278,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
file_dialog->clear_filters();
for (const String &E : valid_extensions) {
- file_dialog->add_filter("*." + E + " ; " + E.to_upper());
+ file_dialog->add_filter("*." + E, E.to_upper());
}
file_dialog->popup_file_dialog();
@@ -288,28 +312,22 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
return;
}
- List<PropertyInfo> property_list;
- edited_resource->get_property_list(&property_list);
- List<Pair<String, Variant>> propvalues;
- for (const PropertyInfo &pi : property_list) {
- Pair<String, Variant> p;
- if (pi.usage & PROPERTY_USAGE_STORAGE) {
- p.first = pi.name;
- p.second = edited_resource->get(pi.name);
- }
+ Ref<Resource> unique_resource = edited_resource->duplicate();
+ ERR_FAIL_COND(unique_resource.is_null());
- propvalues.push_back(p);
+ edited_resource = unique_resource;
+ emit_signal(SNAME("resource_changed"), edited_resource);
+ _update_resource();
+ } break;
+
+ case OBJ_MENU_MAKE_UNIQUE_RECURSIVE: {
+ if (edited_resource.is_null()) {
+ return;
}
- String orig_type = edited_resource->get_class();
- Object *inst = ClassDB::instantiate(orig_type);
- Ref<Resource> unique_resource = Ref<Resource>(Object::cast_to<Resource>(inst));
+ Ref<Resource> unique_resource = edited_resource->duplicate(true);
ERR_FAIL_COND(unique_resource.is_null());
- for (const Pair<String, Variant> &p : propvalues) {
- unique_resource->set(p.first, p.second);
- }
-
edited_resource = unique_resource;
emit_signal(SNAME("resource_changed"), edited_resource);
_update_resource();
@@ -534,8 +552,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 +691,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;
}
@@ -875,10 +881,10 @@ void EditorResourcePicker::_ensure_resource_menu() {
edit_menu = memnew(PopupMenu);
add_child(edit_menu);
edit_menu->connect("id_pressed", callable_mp(this, &EditorResourcePicker::_edit_menu_cbk));
- edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed), varray(false));
+ edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed).bind(false));
}
-EditorResourcePicker::EditorResourcePicker() {
+EditorResourcePicker::EditorResourcePicker(bool p_hide_assign_button_controls) {
assign_button = memnew(Button);
assign_button->set_flat(true);
assign_button->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -889,13 +895,15 @@ EditorResourcePicker::EditorResourcePicker() {
assign_button->connect("draw", callable_mp(this, &EditorResourcePicker::_button_draw));
assign_button->connect("gui_input", callable_mp(this, &EditorResourcePicker::_button_input));
- preview_rect = memnew(TextureRect);
- preview_rect->set_ignore_texture_size(true);
- preview_rect->set_anchors_and_offsets_preset(PRESET_WIDE);
- preview_rect->set_offset(SIDE_TOP, 1);
- preview_rect->set_offset(SIDE_BOTTOM, -1);
- preview_rect->set_offset(SIDE_RIGHT, -1);
- assign_button->add_child(preview_rect);
+ if (!p_hide_assign_button_controls) {
+ preview_rect = memnew(TextureRect);
+ preview_rect->set_ignore_texture_size(true);
+ preview_rect->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
+ preview_rect->set_offset(SIDE_TOP, 1);
+ preview_rect->set_offset(SIDE_BOTTOM, -1);
+ preview_rect->set_offset(SIDE_RIGHT, -1);
+ assign_button->add_child(preview_rect);
+ }
edit_button = memnew(Button);
edit_button->set_flat(true);
@@ -1005,3 +1013,176 @@ void EditorShaderPicker::set_preferred_mode(int p_mode) {
EditorShaderPicker::EditorShaderPicker() {
}
+
+//////////////
+
+void EditorAudioStreamPicker::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY:
+ case NOTIFICATION_THEME_CHANGED: {
+ _update_resource();
+ } break;
+ case NOTIFICATION_INTERNAL_PROCESS: {
+ Ref<AudioStream> audio_stream = get_edited_resource();
+ if (audio_stream.is_valid()) {
+ if (audio_stream->get_length() > 0) {
+ Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(audio_stream);
+ if (preview.is_valid()) {
+ if (preview->get_version() != last_preview_version) {
+ stream_preview_rect->update();
+ last_preview_version = preview->get_version();
+ }
+ }
+ }
+
+ uint64_t tagged_frame = audio_stream->get_tagged_frame();
+ uint64_t diff_frames = AudioServer::get_singleton()->get_mixed_frames() - tagged_frame;
+ uint64_t diff_msec = diff_frames * 1000 / AudioServer::get_singleton()->get_mix_rate();
+
+ if (diff_msec < 300) {
+ uint32_t count = audio_stream->get_tagged_frame_count();
+
+ bool differ = false;
+
+ if (count != tagged_frame_offset_count) {
+ differ = true;
+ }
+ float offsets[MAX_TAGGED_FRAMES];
+
+ for (uint32_t i = 0; i < MIN(count, uint32_t(MAX_TAGGED_FRAMES)); i++) {
+ offsets[i] = audio_stream->get_tagged_frame_offset(i);
+ if (offsets[i] != tagged_frame_offsets[i]) {
+ differ = true;
+ }
+ }
+
+ if (differ) {
+ tagged_frame_offset_count = count;
+ for (uint32_t i = 0; i < count; i++) {
+ tagged_frame_offsets[i] = offsets[i];
+ }
+ }
+
+ stream_preview_rect->update();
+ } else {
+ if (tagged_frame_offset_count != 0) {
+ stream_preview_rect->update();
+ }
+ tagged_frame_offset_count = 0;
+ }
+ }
+ } break;
+ }
+}
+
+void EditorAudioStreamPicker::_update_resource() {
+ EditorResourcePicker::_update_resource();
+
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Ref<AudioStream> audio_stream = get_edited_resource();
+ if (audio_stream.is_valid() && audio_stream->get_length() > 0.0) {
+ set_assign_button_min_size(Size2(1, font->get_height(font_size) * 3));
+ } else {
+ set_assign_button_min_size(Size2(1, font->get_height(font_size) * 1.5));
+ }
+
+ stream_preview_rect->update();
+}
+
+void EditorAudioStreamPicker::_preview_draw() {
+ Ref<AudioStream> audio_stream = get_edited_resource();
+ if (!audio_stream.is_valid()) {
+ get_assign_button()->set_text(TTR("[empty]"));
+ return;
+ }
+
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+
+ get_assign_button()->set_text("");
+
+ Size2i size = stream_preview_rect->get_size();
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+
+ Rect2 rect(Point2(), size);
+
+ if (audio_stream->get_length() > 0) {
+ rect.size.height *= 0.5;
+
+ stream_preview_rect->draw_rect(rect, Color(0, 0, 0, 1));
+
+ Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(audio_stream);
+ float preview_len = preview->get_length();
+
+ Vector<Vector2> lines;
+ lines.resize(size.width * 2);
+
+ for (int i = 0; i < size.width; i++) {
+ float ofs = i * preview_len / size.width;
+ float ofs_n = (i + 1) * preview_len / size.width;
+ float max = preview->get_max(ofs, ofs_n) * 0.5 + 0.5;
+ float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5;
+
+ int idx = i;
+ lines.write[idx * 2 + 0] = Vector2(i + 1, rect.position.y + min * rect.size.y);
+ lines.write[idx * 2 + 1] = Vector2(i + 1, rect.position.y + max * rect.size.y);
+ }
+
+ Vector<Color> color;
+ color.push_back(get_theme_color(SNAME("contrast_color_2"), SNAME("Editor")));
+
+ RS::get_singleton()->canvas_item_add_multiline(stream_preview_rect->get_canvas_item(), lines, color);
+
+ if (tagged_frame_offset_count) {
+ Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+
+ for (uint32_t i = 0; i < tagged_frame_offset_count; i++) {
+ int x = CLAMP(tagged_frame_offsets[i] * size.width / preview_len, 0, size.width);
+ if (x == 0) {
+ continue; // Because some may always return 0, ignore offset 0.
+ }
+ stream_preview_rect->draw_rect(Rect2i(x, 0, 2, rect.size.height), accent);
+ }
+ }
+ rect.position.y += rect.size.height;
+ }
+
+ Ref<Texture2D> icon;
+ Color icon_modulate(1, 1, 1, 1);
+
+ if (tagged_frame_offset_count > 0) {
+ icon = get_theme_icon(SNAME("Play"), SNAME("EditorIcons"));
+ if ((OS::get_singleton()->get_ticks_msec() % 500) > 250) {
+ icon_modulate = Color(1, 0.5, 0.5, 1); // get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ }
+ } else {
+ icon = EditorNode::get_singleton()->get_object_icon(audio_stream.operator->(), "Object");
+ }
+ String text;
+ if (!audio_stream->get_name().is_empty()) {
+ text = audio_stream->get_name();
+ } else if (audio_stream->get_path().is_resource_file()) {
+ text = audio_stream->get_path().get_file();
+ } else {
+ text = audio_stream->get_class().replace_first("AudioStream", "");
+ }
+
+ stream_preview_rect->draw_texture(icon, Point2i(EDSCALE * 2, rect.position.y + (rect.size.height - icon->get_height()) / 2), icon_modulate);
+ stream_preview_rect->draw_string(font, Point2i(EDSCALE * 2 + icon->get_width(), rect.position.y + font->get_ascent(font_size) + (rect.size.height - font->get_height(font_size)) / 2), text, HORIZONTAL_ALIGNMENT_CENTER, size.width - 4 * EDSCALE - icon->get_width());
+}
+
+EditorAudioStreamPicker::EditorAudioStreamPicker() :
+ EditorResourcePicker(true) {
+ stream_preview_rect = memnew(Control);
+
+ stream_preview_rect->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
+ stream_preview_rect->set_offset(SIDE_TOP, 1);
+ stream_preview_rect->set_offset(SIDE_BOTTOM, -1);
+ stream_preview_rect->set_offset(SIDE_RIGHT, -1);
+ stream_preview_rect->set_mouse_filter(MOUSE_FILTER_IGNORE);
+ stream_preview_rect->connect("draw", callable_mp(this, &EditorAudioStreamPicker::_preview_draw));
+
+ get_assign_button()->add_child(stream_preview_rect);
+ get_assign_button()->move_child(stream_preview_rect, 0);
+ set_process_internal(true);
+}
diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h
index 8e26e1f4c0..3a4d5985bd 100644
--- a/editor/editor_resource_picker.h
+++ b/editor/editor_resource_picker.h
@@ -58,12 +58,15 @@ class EditorResourcePicker : public HBoxContainer {
EditorFileDialog *file_dialog = nullptr;
EditorQuickOpen *quick_open = nullptr;
+ Size2i assign_button_min_size = Size2i(1, 1);
+
enum MenuOption {
OBJ_MENU_LOAD,
OBJ_MENU_QUICKLOAD,
OBJ_MENU_EDIT,
OBJ_MENU_CLEAR,
OBJ_MENU_MAKE_UNIQUE,
+ OBJ_MENU_MAKE_UNIQUE_RECURSIVE,
OBJ_MENU_SAVE,
OBJ_MENU_COPY,
OBJ_MENU_PASTE,
@@ -75,7 +78,6 @@ class EditorResourcePicker : public HBoxContainer {
PopupMenu *edit_menu = nullptr;
- void _update_resource();
void _update_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj);
void _resource_selected();
@@ -100,9 +102,17 @@ class EditorResourcePicker : public HBoxContainer {
void _ensure_resource_menu();
protected:
+ virtual void _update_resource();
+
+ Button *get_assign_button() { return assign_button; }
static void _bind_methods();
void _notification(int p_what);
+ void set_assign_button_min_size(const Size2i &p_size) {
+ assign_button_min_size = p_size;
+ assign_button->set_custom_minimum_size(assign_button_min_size);
+ }
+
GDVIRTUAL1(_set_create_options, Object *)
GDVIRTUAL1R(bool, _handle_menu_selected, int)
@@ -126,7 +136,7 @@ public:
virtual void set_create_options(Object *p_menu_node);
virtual bool handle_menu_selected(int p_which);
- EditorResourcePicker();
+ EditorResourcePicker(bool p_hide_assign_button_controls = false);
};
class EditorScriptPicker : public EditorResourcePicker {
@@ -173,4 +183,26 @@ public:
EditorShaderPicker();
};
+class EditorAudioStreamPicker : public EditorResourcePicker {
+ GDCLASS(EditorAudioStreamPicker, EditorResourcePicker);
+
+ uint64_t last_preview_version = 0;
+ Control *stream_preview_rect = nullptr;
+
+ enum {
+ MAX_TAGGED_FRAMES = 8
+ };
+ float tagged_frame_offsets[MAX_TAGGED_FRAMES];
+ uint32_t tagged_frame_offset_count = 0;
+
+ void _preview_draw();
+ virtual void _update_resource() override;
+
+protected:
+ void _notification(int p_what);
+
+public:
+ EditorAudioStreamPicker();
+};
+
#endif // EDITOR_RESOURCE_PICKER_H
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index dffb378408..c0ea2b743e 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;
@@ -195,9 +195,9 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
if (r_texture.is_valid()) {
//wow it generated a preview... save cache
bool has_small_texture = r_small_texture.is_valid();
- ResourceSaver::save(cache_base + ".png", r_texture);
+ ResourceSaver::save(r_texture, cache_base + ".png");
if (has_small_texture) {
- ResourceSaver::save(cache_base + "_small.png", r_small_texture);
+ ResourceSaver::save(r_small_texture, cache_base + "_small.png");
}
Ref<FileAccess> f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE);
ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + cache_base + ".txt'. Check user write permissions.");
@@ -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_resource_preview.h b/editor/editor_resource_preview.h
index 820e22bdc8..0413477d88 100644
--- a/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITORRESOURCEPREVIEW_H
-#define EDITORRESOURCEPREVIEW_H
+#ifndef EDITOR_RESOURCE_PREVIEW_H
+#define EDITOR_RESOURCE_PREVIEW_H
#include "core/os/semaphore.h"
#include "core/os/thread.h"
@@ -124,4 +124,4 @@ public:
~EditorResourcePreview();
};
-#endif // EDITORRESOURCEPREVIEW_H
+#endif // EDITOR_RESOURCE_PREVIEW_H
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index ba49c6dc5f..6ce8625daa 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -55,7 +55,7 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
args.push_back("--remote-debug");
args.push_back(EditorDebuggerNode::get_singleton()->get_server_uri());
- args.push_back("--allow_focus_steal_pid");
+ args.push_back("--editor-pid");
args.push_back(itos(OS::get_singleton()->get_process_id()));
bool debug_collisions = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_collisons", false);
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index 6ce9e5fa6f..d8b738be17 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -30,9 +30,10 @@
#include "editor_run_native.h"
-#include "editor/editor_export.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "editor/export/editor_export_platform.h"
void EditorRunNative::_notification(int p_what) {
switch (p_what) {
@@ -49,12 +50,10 @@ 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));
+ mb->get_popup()->connect("id_pressed", callable_mp(this, &EditorRunNative::run_native).bind(i));
+ mb->connect("pressed", callable_mp(this, &EditorRunNative::run_native).bind(-1, i));
mb->set_icon(small_icon);
add_child(mb);
menus[i] = mb;
diff --git a/editor/editor_scale.h b/editor/editor_scale.h
index 918fde15fb..02e9b997f6 100644
--- a/editor/editor_scale.h
+++ b/editor/editor_scale.h
@@ -35,4 +35,5 @@ void editor_set_scale(float p_scale);
float editor_get_scale();
#define EDSCALE (editor_get_scale())
+
#endif // EDITOR_SCALE_H
diff --git a/editor/editor_sectioned_inspector.h b/editor/editor_sectioned_inspector.h
index babd11eb69..758efae31e 100644
--- a/editor/editor_sectioned_inspector.h
+++ b/editor/editor_sectioned_inspector.h
@@ -76,4 +76,5 @@ public:
SectionedInspector();
~SectionedInspector();
};
+
#endif // EDITOR_SECTIONED_INSPECTOR_H
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index ad9c547693..80e77a1125 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -414,7 +414,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("interface/editor/code_font_custom_opentype_features", "");
_initial_set("interface/editor/code_font_custom_variations", "");
_initial_set("interface/editor/font_antialiased", true);
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (None),None,Light,Normal")
#else
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (Light),None,Light,Normal")
@@ -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")
@@ -543,6 +544,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/behavior/navigation/smooth_scrolling", true);
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/behavior/navigation/v_scroll_speed", 80, "1,10000,1")
_initial_set("text_editor/behavior/navigation/drag_and_drop_selection", true);
+ _initial_set("text_editor/behavior/navigation/stay_in_script_editor_on_node_selected", true);
// Behavior: Indent
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/behavior/indent/type", 0, "Tabs,Spaces")
@@ -683,7 +685,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Visual editors
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/minimap_opacity", 0.85, "0.0,1.0,0.01")
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/lines_curvature", 0.5, "0.0,1.0,0.01")
- EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/visual_editors/visualshader/port_preview_size", 160, "100,400,0.01")
+ EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/visual_editors/visual_shader/port_preview_size", 160, "100,400,0.01")
/* Run */
@@ -763,6 +765,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));
@@ -864,7 +867,6 @@ void EditorSettings::create() {
}
singleton->save_changed_setting = true;
- singleton->config_file_path = config_file_path;
print_verbose("EditorSettings: Load OK!");
@@ -889,8 +891,8 @@ fail:
}
singleton = Ref<EditorSettings>(memnew(EditorSettings));
+ singleton->set_path(config_file_path, true);
singleton->save_changed_setting = true;
- singleton->config_file_path = config_file_path;
singleton->_load_defaults(extra_config);
singleton->setup_language();
singleton->setup_network();
@@ -950,15 +952,10 @@ void EditorSettings::save() {
return;
}
- if (singleton->config_file_path.is_empty()) {
- ERR_PRINT("Cannot save EditorSettings config, no valid path");
- return;
- }
-
- Error err = ResourceSaver::save(singleton->config_file_path, singleton);
+ Error err = ResourceSaver::save(singleton);
if (err != OK) {
- ERR_PRINT("Error saving editor settings to " + singleton->config_file_path);
+ ERR_PRINT("Error saving editor settings to " + singleton->get_path());
} else {
singleton->changed_settings.clear();
print_verbose("EditorSettings: Save OK!");
@@ -1054,6 +1051,8 @@ void EditorSettings::set_initial_value(const StringName &p_setting, const Varian
}
Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default, bool p_restart_if_changed) {
+ ERR_FAIL_NULL_V_MSG(EditorSettings::get_singleton(), p_default, "EditorSettings not instantiated yet.");
+
Variant ret = p_default;
if (EditorSettings::get_singleton()->has_setting(p_setting)) {
ret = EditorSettings::get_singleton()->get(p_setting);
@@ -1070,7 +1069,7 @@ Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default, bool p_re
}
Variant _EDITOR_GET(const String &p_setting) {
- ERR_FAIL_COND_V(!EditorSettings::get_singleton()->has_setting(p_setting), Variant());
+ ERR_FAIL_COND_V(!EditorSettings::get_singleton() || !EditorSettings::get_singleton()->has_setting(p_setting), Variant());
return EditorSettings::get_singleton()->get(p_setting);
}
@@ -1100,38 +1099,11 @@ void EditorSettings::add_property_hint(const PropertyInfo &p_hint) {
hints[p_hint.name] = p_hint;
}
-// Editor data and config directories
-// EditorPaths::create() is responsible for the creation of these directories.
-
-String EditorSettings::get_templates_dir() const {
- return EditorPaths::get_singleton()->get_data_dir().plus_file("templates");
-}
-
-String EditorSettings::get_project_settings_dir() const {
- return EditorPaths::get_singleton()->get_project_data_dir().plus_file("editor");
-}
-
-String EditorSettings::get_text_editor_themes_dir() const {
- return EditorPaths::get_singleton()->get_config_dir().plus_file("text_editor_themes");
-}
-
-String EditorSettings::get_script_templates_dir() const {
- return EditorPaths::get_singleton()->get_config_dir().plus_file("script_templates");
-}
-
-String EditorSettings::get_project_script_templates_dir() const {
- return ProjectSettings::get_singleton()->get("editor/script/templates_search_path");
-}
-
-String EditorSettings::get_feature_profiles_dir() const {
- return EditorPaths::get_singleton()->get_config_dir().plus_file("feature_profiles");
-}
-
// Metadata
void EditorSettings::set_project_metadata(const String &p_section, const String &p_key, Variant p_data) {
Ref<ConfigFile> cf = memnew(ConfigFile);
- String path = get_project_settings_dir().plus_file("project_metadata.cfg");
+ String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("project_metadata.cfg");
Error err;
err = cf->load(path);
ERR_FAIL_COND_MSG(err != OK && err != ERR_FILE_NOT_FOUND, "Cannot load editor settings from file '" + path + "'.");
@@ -1142,7 +1114,7 @@ void EditorSettings::set_project_metadata(const String &p_section, const String
Variant EditorSettings::get_project_metadata(const String &p_section, const String &p_key, Variant p_default) const {
Ref<ConfigFile> cf = memnew(ConfigFile);
- String path = get_project_settings_dir().plus_file("project_metadata.cfg");
+ String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("project_metadata.cfg");
Error err = cf->load(path);
if (err != OK) {
return p_default;
@@ -1156,7 +1128,7 @@ void EditorSettings::set_favorites(const Vector<String> &p_favorites) {
if (Engine::get_singleton()->is_project_manager_hint()) {
favorites_file = EditorPaths::get_singleton()->get_config_dir().plus_file("favorite_dirs");
} else {
- favorites_file = get_project_settings_dir().plus_file("favorites");
+ favorites_file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("favorites");
}
Ref<FileAccess> f = FileAccess::open(favorites_file, FileAccess::WRITE);
if (f.is_valid()) {
@@ -1176,7 +1148,7 @@ void EditorSettings::set_recent_dirs(const Vector<String> &p_recent_dirs) {
if (Engine::get_singleton()->is_project_manager_hint()) {
recent_dirs_file = EditorPaths::get_singleton()->get_config_dir().plus_file("recent_dirs");
} else {
- recent_dirs_file = get_project_settings_dir().plus_file("recent_dirs");
+ recent_dirs_file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("recent_dirs");
}
Ref<FileAccess> f = FileAccess::open(recent_dirs_file, FileAccess::WRITE);
if (f.is_valid()) {
@@ -1197,8 +1169,8 @@ void EditorSettings::load_favorites_and_recent_dirs() {
favorites_file = EditorPaths::get_singleton()->get_config_dir().plus_file("favorite_dirs");
recent_dirs_file = EditorPaths::get_singleton()->get_config_dir().plus_file("recent_dirs");
} else {
- favorites_file = get_project_settings_dir().plus_file("favorites");
- recent_dirs_file = get_project_settings_dir().plus_file("recent_dirs");
+ favorites_file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("favorites");
+ recent_dirs_file = EditorPaths::get_singleton()->get_project_settings_dir().plus_file("recent_dirs");
}
Ref<FileAccess> f = FileAccess::open(favorites_file, FileAccess::READ);
if (f.is_valid()) {
@@ -1230,7 +1202,7 @@ bool EditorSettings::is_dark_theme() {
void EditorSettings::list_text_editor_themes() {
String themes = "Default,Godot 2,Custom";
- Ref<DirAccess> d = DirAccess::open(get_text_editor_themes_dir());
+ Ref<DirAccess> d = DirAccess::open(EditorPaths::get_singleton()->get_text_editor_themes_dir());
if (d.is_valid()) {
List<String> custom_themes;
d->list_dir_begin();
@@ -1261,7 +1233,7 @@ void EditorSettings::load_text_editor_theme() {
return; // sorry for "Settings changed" console spam
}
- String theme_path = get_text_editor_themes_dir().plus_file(p_file + ".tet");
+ String theme_path = EditorPaths::get_singleton()->get_text_editor_themes_dir().plus_file(p_file + ".tet");
Ref<ConfigFile> cf = memnew(ConfigFile);
Error err = cf->load(theme_path);
@@ -1296,9 +1268,9 @@ bool EditorSettings::import_text_editor_theme(String p_file) {
return false;
}
- Ref<DirAccess> d = DirAccess::open(get_text_editor_themes_dir());
+ Ref<DirAccess> d = DirAccess::open(EditorPaths::get_singleton()->get_text_editor_themes_dir());
if (d.is_valid()) {
- d->copy(p_file, get_text_editor_themes_dir().plus_file(p_file.get_file()));
+ d->copy(p_file, EditorPaths::get_singleton()->get_text_editor_themes_dir().plus_file(p_file.get_file()));
return true;
}
}
@@ -1311,7 +1283,7 @@ bool EditorSettings::save_text_editor_theme() {
if (_is_default_text_editor_theme(p_file.get_file().to_lower())) {
return false;
}
- String theme_path = get_text_editor_themes_dir().plus_file(p_file + ".tet");
+ String theme_path = EditorPaths::get_singleton()->get_text_editor_themes_dir().plus_file(p_file + ".tet");
return _save_text_editor_theme(theme_path);
}
@@ -1328,7 +1300,7 @@ bool EditorSettings::save_text_editor_theme_as(String p_file) {
list_text_editor_themes();
String theme_name = p_file.substr(0, p_file.length() - 4).get_file();
- if (p_file.get_base_dir() == get_text_editor_themes_dir()) {
+ if (p_file.get_base_dir() == EditorPaths::get_singleton()->get_text_editor_themes_dir()) {
_initial_set("text_editor/theme/color_theme", theme_name);
load_text_editor_theme();
}
@@ -1344,7 +1316,7 @@ bool EditorSettings::is_default_text_editor_theme() {
Vector<String> EditorSettings::get_script_templates(const String &p_extension, const String &p_custom_path) {
Vector<String> templates;
- String template_dir = get_script_templates_dir();
+ String template_dir = EditorPaths::get_singleton()->get_script_templates_dir();
if (!p_custom_path.is_empty()) {
template_dir = p_custom_path;
}
@@ -1368,7 +1340,7 @@ String EditorSettings::get_editor_layouts_config() const {
}
float EditorSettings::get_auto_display_scale() const {
-#if defined(OSX_ENABLED) || defined(ANDROID_ENABLED)
+#if defined(MACOS_ENABLED) || defined(ANDROID_ENABLED)
return DisplayServer::get_singleton()->screen_get_max_scale();
#else
const int screen = DisplayServer::get_singleton()->window_get_current_screen();
@@ -1452,9 +1424,7 @@ void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) {
}
Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path) {
- if (!EditorSettings::get_singleton()) {
- return nullptr;
- }
+ ERR_FAIL_NULL_V_MSG(EditorSettings::get_singleton(), nullptr, "EditorSettings not instantiated yet.");
Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
@@ -1464,6 +1434,8 @@ Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path) {
}
void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_keycode) {
+ ERR_FAIL_NULL_MSG(EditorSettings::get_singleton(), "EditorSettings not instantiated yet.");
+
Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE with invalid shortcut: " + p_path + ".");
@@ -1474,6 +1446,8 @@ void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_k
}
void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, const PackedInt32Array &p_keycodes) {
+ ERR_FAIL_NULL_MSG(EditorSettings::get_singleton(), "EditorSettings not instantiated yet.");
+
Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE_ARRAY with invalid shortcut: " + p_path + ".");
@@ -1487,7 +1461,7 @@ void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, c
for (int i = 0; i < p_keycodes.size(); i++) {
Key keycode = (Key)p_keycodes[i];
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
// Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
if (keycode == Key::KEY_DELETE) {
keycode = KeyModifierMask::CMD | Key::BACKSPACE;
@@ -1517,7 +1491,7 @@ Ref<Shortcut> ED_SHORTCUT_ARRAY(const String &p_path, const String &p_name, cons
for (int i = 0; i < p_keycodes.size(); i++) {
Key keycode = (Key)p_keycodes[i];
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
// Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
if (keycode == Key::KEY_DELETE) {
keycode = KeyModifierMask::CMD | Key::BACKSPACE;
@@ -1651,8 +1625,6 @@ void EditorSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert);
ClassDB::bind_method(D_METHOD("add_property_info", "info"), &EditorSettings::_add_property_info_bind);
- ClassDB::bind_method(D_METHOD("get_project_settings_dir"), &EditorSettings::get_project_settings_dir);
-
ClassDB::bind_method(D_METHOD("set_project_metadata", "section", "key", "data"), &EditorSettings::set_project_metadata);
ClassDB::bind_method(D_METHOD("get_project_metadata", "section", "key", "default"), &EditorSettings::get_project_metadata, DEFVAL(Variant()));
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 43f90f9258..5faeec88c8 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -88,8 +88,6 @@ private:
mutable HashMap<String, Ref<Shortcut>> shortcuts;
HashMap<String, List<Ref<InputEvent>>> builtin_action_overrides;
- String config_file_path;
-
Vector<String> favorites;
Vector<String> recent_dirs;
@@ -150,14 +148,6 @@ public:
void set_resource_clipboard(const Ref<Resource> &p_resource) { clipboard = p_resource; }
Ref<Resource> get_resource_clipboard() const { return clipboard; }
- String get_data_dir() const;
- String get_templates_dir() const;
- String get_project_settings_dir() const;
- String get_text_editor_themes_dir() const;
- String get_script_templates_dir() const;
- String get_project_script_templates_dir() const;
- String get_feature_profiles_dir() const;
-
void set_project_metadata(const String &p_section, const String &p_key, Variant p_data);
Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default) const;
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index 3eb7d7ffbd..08ff63551f 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -772,7 +772,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
timer->set_one_shot(true);
add_child(timer);
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &EditorSettingsDialog::_settings_changed));
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
}
EditorSettingsDialog::~EditorSettingsDialog() {
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index f23f0cf758..20e9d7a3df 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -37,7 +37,7 @@
String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const {
if (grabber->is_visible()) {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
Key key = Key::META;
#else
Key key = Key::CTRL;
@@ -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);
@@ -649,7 +652,7 @@ void EditorSpinSlider::_ensure_input_popup() {
value_input = memnew(LineEdit);
value_input_popup->add_child(value_input);
value_input_popup->set_wrap_controls(true);
- value_input->set_anchors_and_offsets_preset(PRESET_WIDE);
+ value_input->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
value_input->connect("text_submitted", callable_mp(this, &EditorSpinSlider::_value_input_submitted));
value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited));
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 10412eac41..a3086a2ccf 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
@@ -280,6 +277,14 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
exceptions.insert("StatusWarning");
exceptions.insert("OverbrightIndicator");
exceptions.insert("GuiMiniCheckerboard");
+
+ // Prevents Code Editor icons from changing
+ exceptions.insert("GuiTab");
+ exceptions.insert("GuiSpace");
+ exceptions.insert("CodeFoldedRightArrow");
+ exceptions.insert("CodeFoldDownArrow");
+ exceptions.insert("TextEditorPlay");
+ exceptions.insert("Breakpoint");
}
// These ones should be converted even if we are using a dark theme.
@@ -636,6 +641,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Add a highlight line at the top of the selected tab.
style_tab_selected->set_border_width_all(0);
+ style_tab_selected->set_default_margin(SIDE_LEFT, widget_default_margin.x - border_width);
style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE));
// Make the highlight line prominent, but not too prominent as to not be distracting.
Color tab_highlight = dark_color_2.lerp(accent_color, 0.75);
@@ -648,6 +654,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// We can't prevent them with both rounded corners and non-zero border width, though
style_tab_selected->set_expand_margin_size(SIDE_BOTTOM, corner_width > 0 ? corner_width : border_width);
+ // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel.
+ style_tab_selected->set_expand_margin_size(SIDE_LEFT, -border_width);
+
style_tab_selected->set_default_margin(SIDE_LEFT, widget_default_margin.x + 2 * EDSCALE);
style_tab_selected->set_default_margin(SIDE_RIGHT, widget_default_margin.x + 2 * EDSCALE);
style_tab_selected->set_default_margin(SIDE_BOTTOM, widget_default_margin.y);
@@ -825,6 +834,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("pressed", "CheckButton", style_menu);
theme->set_stylebox("disabled", "CheckButton", style_menu);
theme->set_stylebox("hover", "CheckButton", style_menu);
+ theme->set_stylebox("hover_pressed", "CheckButton", style_menu);
theme->set_icon("on", "CheckButton", theme->get_icon(SNAME("GuiToggleOn"), SNAME("EditorIcons")));
theme->set_icon("on_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabled"), SNAME("EditorIcons")));
@@ -862,6 +872,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("pressed", "CheckBox", sb_checkbox);
theme->set_stylebox("disabled", "CheckBox", sb_checkbox);
theme->set_stylebox("hover", "CheckBox", sb_checkbox);
+ theme->set_stylebox("hover_pressed", "CheckBox", sb_checkbox);
theme->set_icon("checked", "CheckBox", theme->get_icon(SNAME("GuiChecked"), SNAME("EditorIcons")));
theme->set_icon("unchecked", "CheckBox", theme->get_icon(SNAME("GuiUnchecked"), SNAME("EditorIcons")));
theme->set_icon("radio_checked", "CheckBox", theme->get_icon(SNAME("GuiRadioChecked"), SNAME("EditorIcons")));
@@ -890,17 +901,16 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("panel", "PopupDialog", style_popup);
// PopupMenu
- const int popup_menu_margin_size = default_margin_size * 1.5 * EDSCALE;
Ref<StyleBoxFlat> style_popup_menu = style_popup->duplicate();
// Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn
// on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted,
// and it looks weird. 1px solves this.
- style_popup_menu->set_default_margin(SIDE_LEFT, 1 * EDSCALE);
- style_popup_menu->set_default_margin(SIDE_TOP, popup_menu_margin_size);
- style_popup_menu->set_default_margin(SIDE_RIGHT, 1 * EDSCALE);
- style_popup_menu->set_default_margin(SIDE_BOTTOM, popup_menu_margin_size);
+ style_popup_menu->set_default_margin(SIDE_LEFT, EDSCALE);
+ style_popup_menu->set_default_margin(SIDE_TOP, 2 * EDSCALE);
+ style_popup_menu->set_default_margin(SIDE_RIGHT, EDSCALE);
+ style_popup_menu->set_default_margin(SIDE_BOTTOM, 2 * EDSCALE);
// Always display a border for PopupMenus so they can be distinguished from their background.
- style_popup_menu->set_border_width_all(1 * EDSCALE);
+ style_popup_menu->set_border_width_all(EDSCALE);
style_popup_menu->set_border_color(dark_color_2);
theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
@@ -934,12 +944,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Force the v_separation to be even so that the spacing on top and bottom is even.
// If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided.
- // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example)
- int vsep_base = extra_spacing + default_margin_size + 2;
- int force_even_vsep = vsep_base + (vsep_base % 2);
+ // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example).
+ const int vsep_base = extra_spacing + default_margin_size + 6;
+ const int force_even_vsep = vsep_base + (vsep_base % 2);
theme->set_constant("v_separation", "PopupMenu", force_even_vsep * EDSCALE);
- theme->set_constant("item_start_padding", "PopupMenu", popup_menu_margin_size * EDSCALE);
- theme->set_constant("item_end_padding", "PopupMenu", popup_menu_margin_size * EDSCALE);
+ theme->set_constant("item_start_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE);
+ theme->set_constant("item_end_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE);
// Sub-inspectors
for (int i = 0; i < 16; i++) {
@@ -1655,6 +1665,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_dictionary_add_item->set_expand_margin_size(SIDE_RIGHT, 4 * EDSCALE);
theme->set_stylebox("DictionaryAddItem", "EditorStyles", style_dictionary_add_item);
+ Ref<StyleBoxEmpty> vshader_label_style = make_empty_stylebox(2, 1, 2, 1);
+ theme->set_stylebox("label_style", "VShaderEditor", vshader_label_style);
+
// adaptive script theme constants
// for comments and elements with lower relevance
const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5);
@@ -1662,19 +1675,16 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const float mono_value = mono_color.r;
const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07);
const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14);
- const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.7);
-
- // editor main color
- const Color main_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0.02, 0.5, 1.0);
+ const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27);
- const Color symbol_color = Color(0.34, 0.57, 1.0).lerp(mono_color, dark_theme ? 0.5 : 0.3);
- const Color keyword_color = Color(1.0, 0.44, 0.52);
- const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.8, 0.4, 0.6);
- const Color basetype_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0.0, 0.76, 0.38);
- const Color type_color = basetype_color.lerp(mono_color, dark_theme ? 0.4 : 0.3);
- const Color usertype_color = basetype_color.lerp(mono_color, dark_theme ? 0.7 : 0.5);
- const Color comment_color = dim_color;
- const Color string_color = (dark_theme ? Color(1.0, 0.85, 0.26) : Color(1.0, 0.82, 0.09)).lerp(mono_color, dark_theme ? 0.5 : 0.3);
+ const Color symbol_color = dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61);
+ const Color keyword_color = dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51);
+ const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8);
+ const Color base_type_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2);
+ const Color engine_type_color = dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4);
+ const Color user_type_color = dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4);
+ const Color comment_color = dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5);
+ const Color string_color = dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0);
// Use the brightest background color on a light theme (which generally uses a negative contrast rate).
const Color te_background_color = dark_theme ? background_color : dark_color_3;
@@ -1683,27 +1693,28 @@ 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;
- const Color safe_line_number_color = dim_color * Color(1, 1.2, 1, 1.5);
+ const Color safe_line_number_color = dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75);
const Color caret_color = mono_color;
const Color caret_background_color = mono_color.inverted();
const Color text_selected_color = dark_color_3;
- const Color brace_mismatch_color = error_color;
+ const Color brace_mismatch_color = dark_theme ? error_color : Color(1, 0.08, 0, 1);
const Color current_line_color = alpha1;
const Color line_length_guideline_color = dark_theme ? base_color : background_color;
const Color word_highlighted_color = alpha1;
- const Color number_color = basetype_color.lerp(mono_color, dark_theme ? 0.5 : 0.3);
- const Color function_color = main_color;
- const Color member_variable_color = main_color.lerp(mono_color, 0.6);
+ const Color number_color = dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1);
+ const Color function_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1);
+ const Color member_variable_color = dark_theme ? Color(0.34, 0.7, 1.0).lerp(mono_color, 0.6) : Color(0, 0.4, 0.68, 1);
const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3);
const Color bookmark_color = Color(0.08, 0.49, 0.98);
- const Color breakpoint_color = error_color;
+ const Color breakpoint_color = dark_theme ? error_color : Color(1, 0.27, 0.2, 1);
const Color executing_line_color = Color(0.98, 0.89, 0.27);
const Color code_folding_color = alpha3;
const Color search_result_color = alpha1;
- const Color search_result_border_color = Color(0.41, 0.61, 0.91, 0.38);
+ const Color search_result_border_color = dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38);
EditorSettings *setting = EditorSettings::get_singleton();
String text_editor_color_theme = setting->get("text_editor/theme/color_theme");
@@ -1711,9 +1722,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true);
setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true);
setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/base_type_color", basetype_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", type_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/user_type_color", usertype_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true);
setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true);
setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true);
setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true);
@@ -1721,6 +1732,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);
@@ -1750,22 +1762,27 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Now theme is loaded, apply it to CodeEdit.
theme->set_font("font", "CodeEdit", theme->get_font(SNAME("source"), SNAME("EditorFonts")));
theme->set_font_size("font_size", "CodeEdit", theme->get_font_size(SNAME("source_size"), SNAME("EditorFonts")));
+
Ref<StyleBoxFlat> code_edit_stylebox = make_flat_stylebox(EDITOR_GET("text_editor/theme/highlighting/background_color"), widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y, corner_radius);
theme->set_stylebox("normal", "CodeEdit", code_edit_stylebox);
theme->set_stylebox("read_only", "CodeEdit", code_edit_stylebox);
theme->set_stylebox("focus", "CodeEdit", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
+
theme->set_icon("tab", "CodeEdit", theme->get_icon(SNAME("GuiTab"), SNAME("EditorIcons")));
theme->set_icon("space", "CodeEdit", theme->get_icon(SNAME("GuiSpace"), SNAME("EditorIcons")));
- theme->set_icon("folded", "CodeEdit", theme->get_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")));
- theme->set_icon("can_fold", "CodeEdit", theme->get_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")));
- theme->set_icon("executing_line", "CodeEdit", theme->get_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ theme->set_icon("folded", "CodeEdit", theme->get_icon(SNAME("CodeFoldedRightArrow"), SNAME("EditorIcons")));
+ theme->set_icon("can_fold", "CodeEdit", theme->get_icon(SNAME("CodeFoldDownArrow"), SNAME("EditorIcons")));
+ theme->set_icon("executing_line", "CodeEdit", theme->get_icon(SNAME("TextEditorPlay"), SNAME("EditorIcons")));
theme->set_icon("breakpoint", "CodeEdit", theme->get_icon(SNAME("Breakpoint"), SNAME("EditorIcons")));
+
theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
+
theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0));
theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color"));
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/editor_themes.h b/editor/editor_themes.h
index 642558d774..95184b9d4a 100644
--- a/editor/editor_themes.h
+++ b/editor/editor_themes.h
@@ -40,4 +40,4 @@ Ref<Theme> create_custom_theme(Ref<Theme> p_theme = nullptr);
Ref<ImageTexture> create_unscaled_default_project_icon();
-#endif
+#endif // EDITOR_THEMES_H
diff --git a/editor/editor_toaster.cpp b/editor/editor_toaster.cpp
index 4986bccc35..050cde6069 100644
--- a/editor/editor_toaster.cpp
+++ b/editor/editor_toaster.cpp
@@ -356,7 +356,7 @@ Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_
break;
}
panel->set_modulate(Color(1, 1, 1, 0));
- panel->connect("draw", callable_bind(callable_mp(this, &EditorToaster::_draw_progress), panel));
+ panel->connect("draw", callable_mp(this, &EditorToaster::_draw_progress).bind(panel));
// Horizontal container.
HBoxContainer *hbox_container = memnew(HBoxContainer);
@@ -372,8 +372,8 @@ Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_
Button *close_button = memnew(Button);
close_button->set_flat(true);
close_button->set_icon(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- close_button->connect("pressed", callable_bind(callable_mp(this, &EditorToaster::close), panel));
- close_button->connect("theme_changed", callable_bind(callable_mp(this, &EditorToaster::_close_button_theme_changed), close_button));
+ close_button->connect("pressed", callable_mp(this, &EditorToaster::close).bind(panel));
+ close_button->connect("theme_changed", callable_mp(this, &EditorToaster::_close_button_theme_changed).bind(close_button));
hbox_container->add_child(close_button);
}
@@ -522,7 +522,7 @@ EditorToaster::EditorToaster() {
main_button->set_modulate(Color(0.5, 0.5, 0.5));
main_button->set_disabled(true);
main_button->set_flat(true);
- main_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled), varray(true));
+ main_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled).bind(true));
main_button->connect("pressed", callable_mp(this, &EditorToaster::_repop_old));
main_button->connect("draw", callable_mp(this, &EditorToaster::_draw_button));
add_child(main_button);
@@ -536,7 +536,7 @@ EditorToaster::EditorToaster() {
disable_notifications_button = memnew(Button);
disable_notifications_button->set_tooltip(TTR("Silence the notifications."));
disable_notifications_button->set_flat(true);
- disable_notifications_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled), varray(false));
+ disable_notifications_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled).bind(false));
disable_notifications_panel->add_child(disable_notifications_button);
// Other
diff --git a/editor/editor_vcs_interface.h b/editor/editor_vcs_interface.h
index 487625e84c..6a6fca7eba 100644
--- a/editor/editor_vcs_interface.h
+++ b/editor/editor_vcs_interface.h
@@ -85,4 +85,4 @@ public:
virtual ~EditorVCSInterface();
};
-#endif // !EDITOR_VCS_INTERFACE_H
+#endif // EDITOR_VCS_INTERFACE_H
diff --git a/editor/export/SCsub b/editor/export/SCsub
new file mode 100644
index 0000000000..359d04e5df
--- /dev/null
+++ b/editor/export/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.editor_sources, "*.cpp")
diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp
new file mode 100644
index 0000000000..31f408eedb
--- /dev/null
+++ b/editor/export/editor_export.cpp
@@ -0,0 +1,355 @@
+/*************************************************************************/
+/* editor_export.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 "editor_export.h"
+
+#include "core/config/project_settings.h"
+#include "core/io/config_file.h"
+
+EditorExport *EditorExport::singleton = nullptr;
+
+void EditorExport::_save() {
+ Ref<ConfigFile> config;
+ config.instantiate();
+ for (int i = 0; i < export_presets.size(); i++) {
+ Ref<EditorExportPreset> preset = export_presets[i];
+ String section = "preset." + itos(i);
+
+ config->set_value(section, "name", preset->get_name());
+ config->set_value(section, "platform", preset->get_platform()->get_name());
+ config->set_value(section, "runnable", preset->is_runnable());
+ config->set_value(section, "custom_features", preset->get_custom_features());
+
+ bool save_files = false;
+ switch (preset->get_export_filter()) {
+ case EditorExportPreset::EXPORT_ALL_RESOURCES: {
+ config->set_value(section, "export_filter", "all_resources");
+ } break;
+ case EditorExportPreset::EXPORT_SELECTED_SCENES: {
+ config->set_value(section, "export_filter", "scenes");
+ save_files = true;
+ } break;
+ case EditorExportPreset::EXPORT_SELECTED_RESOURCES: {
+ config->set_value(section, "export_filter", "resources");
+ save_files = true;
+ } break;
+ case EditorExportPreset::EXCLUDE_SELECTED_RESOURCES: {
+ config->set_value(section, "export_filter", "exclude");
+ save_files = true;
+ } break;
+ }
+
+ if (save_files) {
+ Vector<String> export_files = preset->get_files_to_export();
+ config->set_value(section, "export_files", export_files);
+ }
+ config->set_value(section, "include_filter", preset->get_include_filter());
+ config->set_value(section, "exclude_filter", preset->get_exclude_filter());
+ config->set_value(section, "export_path", preset->get_export_path());
+ config->set_value(section, "encryption_include_filters", preset->get_enc_in_filter());
+ config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter());
+ config->set_value(section, "encrypt_pck", preset->get_enc_pck());
+ config->set_value(section, "encrypt_directory", preset->get_enc_directory());
+ config->set_value(section, "script_export_mode", preset->get_script_export_mode());
+ config->set_value(section, "script_encryption_key", preset->get_script_encryption_key());
+
+ String option_section = "preset." + itos(i) + ".options";
+
+ for (const PropertyInfo &E : preset->get_properties()) {
+ config->set_value(option_section, E.name, preset->get(E.name));
+ }
+ }
+
+ config->save("res://export_presets.cfg");
+}
+
+void EditorExport::save_presets() {
+ if (block_save) {
+ return;
+ }
+ save_timer->start();
+}
+
+void EditorExport::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("export_presets_updated"));
+}
+
+void EditorExport::add_export_platform(const Ref<EditorExportPlatform> &p_platform) {
+ export_platforms.push_back(p_platform);
+}
+
+int EditorExport::get_export_platform_count() {
+ return export_platforms.size();
+}
+
+Ref<EditorExportPlatform> EditorExport::get_export_platform(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx, export_platforms.size(), Ref<EditorExportPlatform>());
+
+ return export_platforms[p_idx];
+}
+
+void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos) {
+ if (p_at_pos < 0) {
+ export_presets.push_back(p_preset);
+ } else {
+ export_presets.insert(p_at_pos, p_preset);
+ }
+}
+
+String EditorExportPlatform::test_etc2() const {
+ const bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
+
+ if (!etc2_supported) {
+ return TTR("Target platform requires 'ETC2' texture compression. Enable 'Import Etc 2' in Project Settings.");
+ }
+
+ return String();
+}
+
+int EditorExport::get_export_preset_count() const {
+ return export_presets.size();
+}
+
+Ref<EditorExportPreset> EditorExport::get_export_preset(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx, export_presets.size(), Ref<EditorExportPreset>());
+ return export_presets[p_idx];
+}
+
+void EditorExport::remove_export_preset(int p_idx) {
+ export_presets.remove_at(p_idx);
+ save_presets();
+}
+
+void EditorExport::add_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
+ if (!export_plugins.has(p_plugin)) {
+ export_plugins.push_back(p_plugin);
+ }
+}
+
+void EditorExport::remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
+ export_plugins.erase(p_plugin);
+}
+
+Vector<Ref<EditorExportPlugin>> EditorExport::get_export_plugins() {
+ return export_plugins;
+}
+
+void EditorExport::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ load_config();
+ } break;
+
+ case NOTIFICATION_PROCESS: {
+ update_export_presets();
+ } break;
+ }
+}
+
+void EditorExport::load_config() {
+ Ref<ConfigFile> config;
+ config.instantiate();
+ Error err = config->load("res://export_presets.cfg");
+ if (err != OK) {
+ return;
+ }
+
+ block_save = true;
+
+ int index = 0;
+ while (true) {
+ String section = "preset." + itos(index);
+ if (!config->has_section(section)) {
+ break;
+ }
+
+ String platform = config->get_value(section, "platform");
+
+ Ref<EditorExportPreset> preset;
+
+ for (int i = 0; i < export_platforms.size(); i++) {
+ if (export_platforms[i]->get_name() == platform) {
+ preset = export_platforms.write[i]->create_preset();
+ break;
+ }
+ }
+
+ if (!preset.is_valid()) {
+ index++;
+ ERR_CONTINUE(!preset.is_valid());
+ }
+
+ preset->set_name(config->get_value(section, "name"));
+ preset->set_runnable(config->get_value(section, "runnable"));
+
+ if (config->has_section_key(section, "custom_features")) {
+ preset->set_custom_features(config->get_value(section, "custom_features"));
+ }
+
+ String export_filter = config->get_value(section, "export_filter");
+
+ bool get_files = false;
+
+ if (export_filter == "all_resources") {
+ preset->set_export_filter(EditorExportPreset::EXPORT_ALL_RESOURCES);
+ } else if (export_filter == "scenes") {
+ preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_SCENES);
+ get_files = true;
+ } else if (export_filter == "resources") {
+ preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_RESOURCES);
+ get_files = true;
+ } else if (export_filter == "exclude") {
+ preset->set_export_filter(EditorExportPreset::EXCLUDE_SELECTED_RESOURCES);
+ get_files = true;
+ }
+
+ if (get_files) {
+ Vector<String> files = config->get_value(section, "export_files");
+
+ for (int i = 0; i < files.size(); i++) {
+ if (!FileAccess::exists(files[i])) {
+ preset->remove_export_file(files[i]);
+ } else {
+ preset->add_export_file(files[i]);
+ }
+ }
+ }
+
+ preset->set_include_filter(config->get_value(section, "include_filter"));
+ preset->set_exclude_filter(config->get_value(section, "exclude_filter"));
+ preset->set_export_path(config->get_value(section, "export_path", ""));
+
+ if (config->has_section_key(section, "encrypt_pck")) {
+ preset->set_enc_pck(config->get_value(section, "encrypt_pck"));
+ }
+ if (config->has_section_key(section, "encrypt_directory")) {
+ preset->set_enc_directory(config->get_value(section, "encrypt_directory"));
+ }
+ if (config->has_section_key(section, "encryption_include_filters")) {
+ preset->set_enc_in_filter(config->get_value(section, "encryption_include_filters"));
+ }
+ if (config->has_section_key(section, "encryption_exclude_filters")) {
+ preset->set_enc_ex_filter(config->get_value(section, "encryption_exclude_filters"));
+ }
+ if (config->has_section_key(section, "script_export_mode")) {
+ preset->set_script_export_mode(config->get_value(section, "script_export_mode"));
+ }
+ if (config->has_section_key(section, "script_encryption_key")) {
+ preset->set_script_encryption_key(config->get_value(section, "script_encryption_key"));
+ }
+
+ String option_section = "preset." + itos(index) + ".options";
+
+ List<String> options;
+
+ config->get_section_keys(option_section, &options);
+
+ for (const String &E : options) {
+ Variant value = config->get_value(option_section, E);
+
+ preset->set(E, value);
+ }
+
+ add_export_preset(preset);
+ index++;
+ }
+
+ block_save = false;
+}
+
+void EditorExport::update_export_presets() {
+ HashMap<StringName, List<EditorExportPlatform::ExportOption>> platform_options;
+
+ for (int i = 0; i < export_platforms.size(); i++) {
+ Ref<EditorExportPlatform> platform = export_platforms[i];
+
+ if (platform->should_update_export_options()) {
+ List<EditorExportPlatform::ExportOption> options;
+ platform->get_export_options(&options);
+
+ platform_options[platform->get_name()] = options;
+ }
+ }
+
+ bool export_presets_updated = false;
+ for (int i = 0; i < export_presets.size(); i++) {
+ Ref<EditorExportPreset> preset = export_presets[i];
+ if (platform_options.has(preset->get_platform()->get_name())) {
+ export_presets_updated = true;
+
+ List<EditorExportPlatform::ExportOption> options = platform_options[preset->get_platform()->get_name()];
+
+ // Copy the previous preset values
+ HashMap<StringName, Variant> previous_values = preset->values;
+
+ // Clear the preset properties and values prior to reloading
+ preset->properties.clear();
+ preset->values.clear();
+
+ for (const EditorExportPlatform::ExportOption &E : options) {
+ preset->properties.push_back(E.option);
+
+ StringName option_name = E.option.name;
+ preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E.default_value;
+ }
+ }
+ }
+
+ if (export_presets_updated) {
+ emit_signal(_export_presets_updated);
+ }
+}
+
+bool EditorExport::poll_export_platforms() {
+ bool changed = false;
+ for (int i = 0; i < export_platforms.size(); i++) {
+ if (export_platforms.write[i]->poll_export()) {
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+EditorExport::EditorExport() {
+ save_timer = memnew(Timer);
+ add_child(save_timer);
+ save_timer->set_wait_time(0.8);
+ save_timer->set_one_shot(true);
+ save_timer->connect("timeout", callable_mp(this, &EditorExport::_save));
+
+ _export_presets_updated = "export_presets_updated";
+
+ singleton = this;
+ set_process(true);
+}
+
+EditorExport::~EditorExport() {
+}
diff --git a/editor/export/editor_export.h b/editor/export/editor_export.h
new file mode 100644
index 0000000000..13c3c34cea
--- /dev/null
+++ b/editor/export/editor_export.h
@@ -0,0 +1,84 @@
+/*************************************************************************/
+/* editor_export.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 EDITOR_EXPORT_H
+#define EDITOR_EXPORT_H
+
+#include "editor_export_platform.h"
+#include "editor_export_plugin.h"
+
+class EditorExport : public Node {
+ GDCLASS(EditorExport, Node);
+
+ Vector<Ref<EditorExportPlatform>> export_platforms;
+ Vector<Ref<EditorExportPreset>> export_presets;
+ Vector<Ref<EditorExportPlugin>> export_plugins;
+
+ StringName _export_presets_updated;
+
+ Timer *save_timer = nullptr;
+ bool block_save = false;
+
+ static EditorExport *singleton;
+
+ void _save();
+
+protected:
+ friend class EditorExportPreset;
+ void save_presets();
+
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ static EditorExport *get_singleton() { return singleton; }
+
+ void add_export_platform(const Ref<EditorExportPlatform> &p_platform);
+ int get_export_platform_count();
+ Ref<EditorExportPlatform> get_export_platform(int p_idx);
+
+ void add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos = -1);
+ int get_export_preset_count() const;
+ Ref<EditorExportPreset> get_export_preset(int p_idx);
+ void remove_export_preset(int p_idx);
+
+ void add_export_plugin(const Ref<EditorExportPlugin> &p_plugin);
+ void remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin);
+ Vector<Ref<EditorExportPlugin>> get_export_plugins();
+
+ void load_config();
+ void update_export_presets();
+ bool poll_export_platforms();
+
+ EditorExport();
+ ~EditorExport();
+};
+
+#endif // EDITOR_EXPORT_H
diff --git a/editor/editor_export.cpp b/editor/export/editor_export_platform.cpp
index bb9d930cf5..34b407779e 100644
--- a/editor/editor_export.cpp
+++ b/editor/export/editor_export_platform.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* editor_export.cpp */
+/* editor_export_platform.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,20 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "editor_export.h"
+#include "editor_export_platform.h"
#include "core/config/project_settings.h"
#include "core/crypto/crypto_core.h"
#include "core/extension/native_extension.h"
-#include "core/io/config_file.h"
-#include "core/io/dir_access.h"
-#include "core/io/file_access.h"
#include "core/io/file_access_encrypted.h"
#include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
-#include "core/io/resource_loader.h"
-#include "core/io/resource_saver.h"
#include "core/io/zip_io.h"
-#include "core/object/script_language.h"
#include "core/version.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
@@ -49,7 +43,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/plugins/script_editor_plugin.h"
-#include "scene/resources/resource_format_text.h"
+#include "editor_export_plugin.h"
static int _get_pad(int p_alignment, int p_n) {
int rest = p_n % p_alignment;
@@ -63,196 +57,6 @@ static int _get_pad(int p_alignment, int p_n) {
#define PCK_PADDING 16
-bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) {
- if (values.has(p_name)) {
- values[p_name] = p_value;
- EditorExport::singleton->save_presets();
- return true;
- }
-
- return false;
-}
-
-bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const {
- if (values.has(p_name)) {
- r_ret = values[p_name];
- return true;
- }
-
- return false;
-}
-
-void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const PropertyInfo &E : properties) {
- if (platform->get_export_option_visibility(E.name, values)) {
- p_list->push_back(E);
- }
- }
-}
-
-Ref<EditorExportPlatform> EditorExportPreset::get_platform() const {
- return platform;
-}
-
-void EditorExportPreset::update_files_to_export() {
- Vector<String> to_remove;
- for (const String &E : selected_files) {
- if (!FileAccess::exists(E)) {
- to_remove.push_back(E);
- }
- }
- for (int i = 0; i < to_remove.size(); ++i) {
- selected_files.erase(to_remove[i]);
- }
-}
-
-Vector<String> EditorExportPreset::get_files_to_export() const {
- Vector<String> files;
- for (const String &E : selected_files) {
- files.push_back(E);
- }
- return files;
-}
-
-void EditorExportPreset::set_name(const String &p_name) {
- name = p_name;
- EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_name() const {
- return name;
-}
-
-void EditorExportPreset::set_runnable(bool p_enable) {
- runnable = p_enable;
- EditorExport::singleton->save_presets();
-}
-
-bool EditorExportPreset::is_runnable() const {
- return runnable;
-}
-
-void EditorExportPreset::set_export_filter(ExportFilter p_filter) {
- export_filter = p_filter;
- EditorExport::singleton->save_presets();
-}
-
-EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const {
- return export_filter;
-}
-
-void EditorExportPreset::set_include_filter(const String &p_include) {
- include_filter = p_include;
- EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_include_filter() const {
- return include_filter;
-}
-
-void EditorExportPreset::set_export_path(const String &p_path) {
- export_path = p_path;
- /* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path,
- * this should be removed. */
- if (export_path.is_absolute_path()) {
- String res_path = OS::get_singleton()->get_resource_dir();
- export_path = res_path.path_to_file(export_path);
- }
- EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_export_path() const {
- return export_path;
-}
-
-void EditorExportPreset::set_exclude_filter(const String &p_exclude) {
- exclude_filter = p_exclude;
- EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_exclude_filter() const {
- return exclude_filter;
-}
-
-void EditorExportPreset::add_export_file(const String &p_path) {
- selected_files.insert(p_path);
- EditorExport::singleton->save_presets();
-}
-
-void EditorExportPreset::remove_export_file(const String &p_path) {
- selected_files.erase(p_path);
- EditorExport::singleton->save_presets();
-}
-
-bool EditorExportPreset::has_export_file(const String &p_path) {
- return selected_files.has(p_path);
-}
-
-void EditorExportPreset::set_custom_features(const String &p_custom_features) {
- custom_features = p_custom_features;
- EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_custom_features() const {
- return custom_features;
-}
-
-void EditorExportPreset::set_enc_in_filter(const String &p_filter) {
- enc_in_filters = p_filter;
- EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_enc_in_filter() const {
- return enc_in_filters;
-}
-
-void EditorExportPreset::set_enc_ex_filter(const String &p_filter) {
- enc_ex_filters = p_filter;
- EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_enc_ex_filter() const {
- return enc_ex_filters;
-}
-
-void EditorExportPreset::set_enc_pck(bool p_enabled) {
- enc_pck = p_enabled;
- EditorExport::singleton->save_presets();
-}
-
-bool EditorExportPreset::get_enc_pck() const {
- return enc_pck;
-}
-
-void EditorExportPreset::set_enc_directory(bool p_enabled) {
- enc_directory = p_enabled;
- EditorExport::singleton->save_presets();
-}
-
-bool EditorExportPreset::get_enc_directory() const {
- return enc_directory;
-}
-
-void EditorExportPreset::set_script_export_mode(int p_mode) {
- script_mode = p_mode;
- EditorExport::singleton->save_presets();
-}
-
-int EditorExportPreset::get_script_export_mode() const {
- return script_mode;
-}
-
-void EditorExportPreset::set_script_encryption_key(const String &p_key) {
- script_key = p_key;
- EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_script_encryption_key() const {
- return script_key;
-}
-
-///////////////////////////////////
-
bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) {
bool has_messages = false;
@@ -267,7 +71,7 @@ bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err)
if (get_worst_message_type() >= EditorExportPlatform::EXPORT_MESSAGE_WARNING) {
p_log->add_image(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")), 16 * EDSCALE, 16 * EDSCALE, Color(1.0, 1.0, 1.0), INLINE_ALIGNMENT_CENTER);
p_log->add_text(" ");
- p_log->add_text(TTR("Completed with errors."));
+ p_log->add_text(TTR("Completed with warnings."));
has_messages = true;
} else {
p_log->add_image(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons")), 16 * EDSCALE, 16 * EDSCALE, Color(1.0, 1.0, 1.0), INLINE_ALIGNMENT_CENTER);
@@ -491,7 +295,7 @@ Ref<ImageTexture> EditorExportPlatform::get_option_icon(int p_index) const {
String EditorExportPlatform::find_export_template(String template_file_name, String *err) const {
String current_version = VERSION_FULL_CONFIG;
- String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(current_version).plus_file(template_file_name);
+ String template_path = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(current_version).plus_file(template_file_name);
if (FileAccess::exists(template_path)) {
return template_path;
@@ -625,139 +429,7 @@ void EditorExportPlatform::_edit_filter_list(HashSet<String> &r_list, const Stri
_edit_files_with_filter(da, filters, r_list, exclude);
}
-void EditorExportPlugin::set_export_preset(const Ref<EditorExportPreset> &p_preset) {
- if (p_preset.is_valid()) {
- export_preset = p_preset;
- }
-}
-
-Ref<EditorExportPreset> EditorExportPlugin::get_export_preset() const {
- return export_preset;
-}
-
-void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap) {
- ExtraFile ef;
- ef.data = p_file;
- ef.path = p_path;
- ef.remap = p_remap;
- extra_files.push_back(ef);
-}
-
-void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &p_tags, const String &p_target) {
- shared_objects.push_back(SharedObject(p_path, p_tags, p_target));
-}
-
-void EditorExportPlugin::add_ios_framework(const String &p_path) {
- ios_frameworks.push_back(p_path);
-}
-
-void EditorExportPlugin::add_ios_embedded_framework(const String &p_path) {
- ios_embedded_frameworks.push_back(p_path);
-}
-
-Vector<String> EditorExportPlugin::get_ios_frameworks() const {
- return ios_frameworks;
-}
-
-Vector<String> EditorExportPlugin::get_ios_embedded_frameworks() const {
- return ios_embedded_frameworks;
-}
-
-void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) {
- ios_plist_content += p_plist_content + "\n";
-}
-
-String EditorExportPlugin::get_ios_plist_content() const {
- return ios_plist_content;
-}
-
-void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) {
- if (ios_linker_flags.length() > 0) {
- ios_linker_flags += ' ';
- }
- ios_linker_flags += p_flags;
-}
-
-String EditorExportPlugin::get_ios_linker_flags() const {
- return ios_linker_flags;
-}
-
-void EditorExportPlugin::add_ios_bundle_file(const String &p_path) {
- ios_bundle_files.push_back(p_path);
-}
-
-Vector<String> EditorExportPlugin::get_ios_bundle_files() const {
- return ios_bundle_files;
-}
-
-void EditorExportPlugin::add_ios_cpp_code(const String &p_code) {
- ios_cpp_code += p_code;
-}
-
-String EditorExportPlugin::get_ios_cpp_code() const {
- return ios_cpp_code;
-}
-
-void EditorExportPlugin::add_osx_plugin_file(const String &p_path) {
- osx_plugin_files.push_back(p_path);
-}
-
-const Vector<String> &EditorExportPlugin::get_osx_plugin_files() const {
- return osx_plugin_files;
-}
-
-void EditorExportPlugin::add_ios_project_static_lib(const String &p_path) {
- ios_project_static_libs.push_back(p_path);
-}
-
-Vector<String> EditorExportPlugin::get_ios_project_static_libs() const {
- return ios_project_static_libs;
-}
-
-void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features) {
- GDVIRTUAL_CALL(_export_file, p_path, p_type, p_features);
-}
-
-void EditorExportPlugin::_export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
- GDVIRTUAL_CALL(_export_begin, p_features, p_debug, p_path, p_flags);
-}
-
-void EditorExportPlugin::_export_end_script() {
- GDVIRTUAL_CALL(_export_end);
-}
-
-void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
-}
-
-void EditorExportPlugin::_export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
-}
-
-void EditorExportPlugin::skip() {
- skipped = true;
-}
-
-void EditorExportPlugin::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags", "target"), &EditorExportPlugin::add_shared_object);
- ClassDB::bind_method(D_METHOD("add_ios_project_static_lib", "path"), &EditorExportPlugin::add_ios_project_static_lib);
- ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file);
- ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework);
- ClassDB::bind_method(D_METHOD("add_ios_embedded_framework", "path"), &EditorExportPlugin::add_ios_embedded_framework);
- ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content);
- ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags);
- ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file);
- ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code);
- ClassDB::bind_method(D_METHOD("add_osx_plugin_file", "path"), &EditorExportPlugin::add_osx_plugin_file);
- ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip);
-
- GDVIRTUAL_BIND(_export_file, "path", "type", "features");
- GDVIRTUAL_BIND(_export_begin, "features", "is_debug", "path", "flags");
- GDVIRTUAL_BIND(_export_end);
-}
-
-EditorExportPlugin::EditorExportPlugin() {
-}
-
-EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug) {
+EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug) const {
Ref<EditorExportPlatform> platform = p_preset->get_platform();
List<String> feature_list;
platform->get_platform_features(&feature_list);
@@ -1504,573 +1176,3 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags
EditorExportPlatform::EditorExportPlatform() {
}
-
-////
-
-EditorExport *EditorExport::singleton = nullptr;
-
-void EditorExport::_save() {
- Ref<ConfigFile> config;
- config.instantiate();
- for (int i = 0; i < export_presets.size(); i++) {
- Ref<EditorExportPreset> preset = export_presets[i];
- String section = "preset." + itos(i);
-
- config->set_value(section, "name", preset->get_name());
- config->set_value(section, "platform", preset->get_platform()->get_name());
- config->set_value(section, "runnable", preset->is_runnable());
- config->set_value(section, "custom_features", preset->get_custom_features());
-
- bool save_files = false;
- switch (preset->get_export_filter()) {
- case EditorExportPreset::EXPORT_ALL_RESOURCES: {
- config->set_value(section, "export_filter", "all_resources");
- } break;
- case EditorExportPreset::EXPORT_SELECTED_SCENES: {
- config->set_value(section, "export_filter", "scenes");
- save_files = true;
- } break;
- case EditorExportPreset::EXPORT_SELECTED_RESOURCES: {
- config->set_value(section, "export_filter", "resources");
- save_files = true;
- } break;
- case EditorExportPreset::EXCLUDE_SELECTED_RESOURCES: {
- config->set_value(section, "export_filter", "exclude");
- save_files = true;
- } break;
- }
-
- if (save_files) {
- Vector<String> export_files = preset->get_files_to_export();
- config->set_value(section, "export_files", export_files);
- }
- config->set_value(section, "include_filter", preset->get_include_filter());
- config->set_value(section, "exclude_filter", preset->get_exclude_filter());
- config->set_value(section, "export_path", preset->get_export_path());
- config->set_value(section, "encryption_include_filters", preset->get_enc_in_filter());
- config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter());
- config->set_value(section, "encrypt_pck", preset->get_enc_pck());
- config->set_value(section, "encrypt_directory", preset->get_enc_directory());
- config->set_value(section, "script_export_mode", preset->get_script_export_mode());
- config->set_value(section, "script_encryption_key", preset->get_script_encryption_key());
-
- String option_section = "preset." + itos(i) + ".options";
-
- for (const PropertyInfo &E : preset->get_properties()) {
- config->set_value(option_section, E.name, preset->get(E.name));
- }
- }
-
- config->save("res://export_presets.cfg");
-}
-
-void EditorExport::save_presets() {
- if (block_save) {
- return;
- }
- save_timer->start();
-}
-
-void EditorExport::_bind_methods() {
- ADD_SIGNAL(MethodInfo("export_presets_updated"));
-}
-
-void EditorExport::add_export_platform(const Ref<EditorExportPlatform> &p_platform) {
- export_platforms.push_back(p_platform);
-}
-
-int EditorExport::get_export_platform_count() {
- return export_platforms.size();
-}
-
-Ref<EditorExportPlatform> EditorExport::get_export_platform(int p_idx) {
- ERR_FAIL_INDEX_V(p_idx, export_platforms.size(), Ref<EditorExportPlatform>());
-
- return export_platforms[p_idx];
-}
-
-void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos) {
- if (p_at_pos < 0) {
- export_presets.push_back(p_preset);
- } else {
- export_presets.insert(p_at_pos, p_preset);
- }
-}
-
-String EditorExportPlatform::test_etc2() const {
- const bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
-
- if (!etc2_supported) {
- return TTR("Target platform requires 'ETC2' texture compression. Enable 'Import Etc 2' in Project Settings.");
- }
-
- return String();
-}
-
-int EditorExport::get_export_preset_count() const {
- return export_presets.size();
-}
-
-Ref<EditorExportPreset> EditorExport::get_export_preset(int p_idx) {
- ERR_FAIL_INDEX_V(p_idx, export_presets.size(), Ref<EditorExportPreset>());
- return export_presets[p_idx];
-}
-
-void EditorExport::remove_export_preset(int p_idx) {
- export_presets.remove_at(p_idx);
- save_presets();
-}
-
-void EditorExport::add_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
- if (!export_plugins.has(p_plugin)) {
- export_plugins.push_back(p_plugin);
- }
-}
-
-void EditorExport::remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
- export_plugins.erase(p_plugin);
-}
-
-Vector<Ref<EditorExportPlugin>> EditorExport::get_export_plugins() {
- return export_plugins;
-}
-
-void EditorExport::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- load_config();
- } break;
-
- case NOTIFICATION_PROCESS: {
- update_export_presets();
- } break;
- }
-}
-
-void EditorExport::load_config() {
- Ref<ConfigFile> config;
- config.instantiate();
- Error err = config->load("res://export_presets.cfg");
- if (err != OK) {
- return;
- }
-
- block_save = true;
-
- int index = 0;
- while (true) {
- String section = "preset." + itos(index);
- if (!config->has_section(section)) {
- break;
- }
-
- String platform = config->get_value(section, "platform");
-
- Ref<EditorExportPreset> preset;
-
- for (int i = 0; i < export_platforms.size(); i++) {
- if (export_platforms[i]->get_name() == platform) {
- preset = export_platforms.write[i]->create_preset();
- break;
- }
- }
-
- if (!preset.is_valid()) {
- index++;
- ERR_CONTINUE(!preset.is_valid());
- }
-
- preset->set_name(config->get_value(section, "name"));
- preset->set_runnable(config->get_value(section, "runnable"));
-
- if (config->has_section_key(section, "custom_features")) {
- preset->set_custom_features(config->get_value(section, "custom_features"));
- }
-
- String export_filter = config->get_value(section, "export_filter");
-
- bool get_files = false;
-
- if (export_filter == "all_resources") {
- preset->set_export_filter(EditorExportPreset::EXPORT_ALL_RESOURCES);
- } else if (export_filter == "scenes") {
- preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_SCENES);
- get_files = true;
- } else if (export_filter == "resources") {
- preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_RESOURCES);
- get_files = true;
- } else if (export_filter == "exclude") {
- preset->set_export_filter(EditorExportPreset::EXCLUDE_SELECTED_RESOURCES);
- get_files = true;
- }
-
- if (get_files) {
- Vector<String> files = config->get_value(section, "export_files");
-
- for (int i = 0; i < files.size(); i++) {
- if (!FileAccess::exists(files[i])) {
- preset->remove_export_file(files[i]);
- } else {
- preset->add_export_file(files[i]);
- }
- }
- }
-
- preset->set_include_filter(config->get_value(section, "include_filter"));
- preset->set_exclude_filter(config->get_value(section, "exclude_filter"));
- preset->set_export_path(config->get_value(section, "export_path", ""));
-
- if (config->has_section_key(section, "encrypt_pck")) {
- preset->set_enc_pck(config->get_value(section, "encrypt_pck"));
- }
- if (config->has_section_key(section, "encrypt_directory")) {
- preset->set_enc_directory(config->get_value(section, "encrypt_directory"));
- }
- if (config->has_section_key(section, "encryption_include_filters")) {
- preset->set_enc_in_filter(config->get_value(section, "encryption_include_filters"));
- }
- if (config->has_section_key(section, "encryption_exclude_filters")) {
- preset->set_enc_ex_filter(config->get_value(section, "encryption_exclude_filters"));
- }
- if (config->has_section_key(section, "script_export_mode")) {
- preset->set_script_export_mode(config->get_value(section, "script_export_mode"));
- }
- if (config->has_section_key(section, "script_encryption_key")) {
- preset->set_script_encryption_key(config->get_value(section, "script_encryption_key"));
- }
-
- String option_section = "preset." + itos(index) + ".options";
-
- List<String> options;
-
- config->get_section_keys(option_section, &options);
-
- for (const String &E : options) {
- Variant value = config->get_value(option_section, E);
-
- preset->set(E, value);
- }
-
- add_export_preset(preset);
- index++;
- }
-
- block_save = false;
-}
-
-void EditorExport::update_export_presets() {
- HashMap<StringName, List<EditorExportPlatform::ExportOption>> platform_options;
-
- for (int i = 0; i < export_platforms.size(); i++) {
- Ref<EditorExportPlatform> platform = export_platforms[i];
-
- if (platform->should_update_export_options()) {
- List<EditorExportPlatform::ExportOption> options;
- platform->get_export_options(&options);
-
- platform_options[platform->get_name()] = options;
- }
- }
-
- bool export_presets_updated = false;
- for (int i = 0; i < export_presets.size(); i++) {
- Ref<EditorExportPreset> preset = export_presets[i];
- if (platform_options.has(preset->get_platform()->get_name())) {
- export_presets_updated = true;
-
- List<EditorExportPlatform::ExportOption> options = platform_options[preset->get_platform()->get_name()];
-
- // Copy the previous preset values
- HashMap<StringName, Variant> previous_values = preset->values;
-
- // Clear the preset properties and values prior to reloading
- preset->properties.clear();
- preset->values.clear();
-
- for (const EditorExportPlatform::ExportOption &E : options) {
- preset->properties.push_back(E.option);
-
- StringName option_name = E.option.name;
- preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E.default_value;
- }
- }
- }
-
- if (export_presets_updated) {
- emit_signal(_export_presets_updated);
- }
-}
-
-bool EditorExport::poll_export_platforms() {
- bool changed = false;
- for (int i = 0; i < export_platforms.size(); i++) {
- if (export_platforms.write[i]->poll_export()) {
- changed = true;
- }
- }
-
- return changed;
-}
-
-EditorExport::EditorExport() {
- save_timer = memnew(Timer);
- add_child(save_timer);
- save_timer->set_wait_time(0.8);
- save_timer->set_one_shot(true);
- save_timer->connect("timeout", callable_mp(this, &EditorExport::_save));
-
- _export_presets_updated = "export_presets_updated";
-
- singleton = this;
- set_process(true);
-}
-
-EditorExport::~EditorExport() {
-}
-
-//////////
-
-void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
- if (p_preset->get("texture_format/s3tc")) {
- r_features->push_back("s3tc");
- }
- if (p_preset->get("texture_format/etc")) {
- r_features->push_back("etc");
- }
- if (p_preset->get("texture_format/etc2")) {
- r_features->push_back("etc2");
- }
-
- if (p_preset->get("binary_format/64_bits")) {
- r_features->push_back("64");
- } else {
- r_features->push_back("32");
- }
-}
-
-void EditorExportPlatformPC::get_export_options(List<ExportOption> *r_options) {
- String ext_filter = (get_os_name() == "Windows") ? "*.exe" : "";
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, ext_filter), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, ext_filter), ""));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "debug/export_console_script", PROPERTY_HINT_ENUM, "No,Debug Only,Debug and Release"), 1));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/64_bits"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/embed_pck"), false));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/bptc"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/no_bptc_fallbacks"), true));
-}
-
-String EditorExportPlatformPC::get_name() const {
- return name;
-}
-
-String EditorExportPlatformPC::get_os_name() const {
- return os_name;
-}
-
-Ref<Texture2D> EditorExportPlatformPC::get_logo() const {
- return logo;
-}
-
-bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
- String err;
- bool valid = false;
-
- // Look for export templates (first official, and if defined custom templates).
-
- bool use64 = p_preset->get("binary_format/64_bits");
- bool dvalid = exists_export_template(get_template_file_name("debug", use64 ? "64" : "32"), &err);
- bool rvalid = exists_export_template(get_template_file_name("release", use64 ? "64" : "32"), &err);
-
- if (p_preset->get("custom_template/debug") != "") {
- dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
- if (!dvalid) {
- err += TTR("Custom debug template not found.") + "\n";
- }
- }
- if (p_preset->get("custom_template/release") != "") {
- rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
- if (!rvalid) {
- err += TTR("Custom release template not found.") + "\n";
- }
- }
-
- valid = dvalid || rvalid;
- r_missing_templates = !valid;
-
- if (!err.is_empty()) {
- r_error = err;
- }
- return valid;
-}
-
-Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
- ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
-
- Error err = prepare_template(p_preset, p_debug, p_path, p_flags);
- if (err == OK) {
- err = modify_template(p_preset, p_debug, p_path, p_flags);
- }
- if (err == OK) {
- err = export_project_data(p_preset, p_debug, p_path, p_flags);
- }
-
- return err;
-}
-
-Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
- if (!DirAccess::exists(p_path.get_base_dir())) {
- add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("The given export path doesn't exist."));
- return ERR_FILE_BAD_PATH;
- }
-
- String custom_debug = p_preset->get("custom_template/debug");
- String custom_release = p_preset->get("custom_template/release");
-
- String template_path = p_debug ? custom_debug : custom_release;
-
- template_path = template_path.strip_edges();
-
- if (template_path.is_empty()) {
- template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", p_preset->get("binary_format/64_bits") ? "64" : "32"));
- }
-
- if (!template_path.is_empty() && !FileAccess::exists(template_path)) {
- add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), vformat(TTR("Template file not found: \"%s\"."), template_path));
- return ERR_FILE_NOT_FOUND;
- }
-
- Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->make_dir_recursive(p_path.get_base_dir());
- Error err = da->copy(template_path, p_path, get_chmod_flags());
- if (err != OK) {
- add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("Failed to copy export template."));
- }
-
- return err;
-}
-
-Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
- String pck_path;
- if (p_preset->get("binary_format/embed_pck")) {
- pck_path = p_path;
- } else {
- pck_path = p_path.get_basename() + ".pck";
- }
-
- Vector<SharedObject> so_files;
-
- int64_t embedded_pos;
- int64_t embedded_size;
- Error err = save_pack(p_preset, p_debug, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size);
- if (err == OK && p_preset->get("binary_format/embed_pck")) {
- if (embedded_size >= 0x100000000 && !p_preset->get("binary_format/64_bits")) {
- add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."));
- return ERR_INVALID_PARAMETER;
- }
-
- err = fixup_embedded_pck(p_path, embedded_pos, embedded_size);
- }
-
- if (err == OK && !so_files.is_empty()) {
- // If shared object files, copy them.
- Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- for (int i = 0; i < so_files.size() && err == OK; i++) {
- String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path);
- String target_path;
- if (so_files[i].target.is_empty()) {
- target_path = p_path.get_base_dir().plus_file(src_path.get_file());
- } else {
- target_path = p_path.get_base_dir().plus_file(so_files[i].target).plus_file(src_path.get_file());
- }
-
- if (da->dir_exists(src_path)) {
- err = da->make_dir_recursive(target_path);
- if (err == OK) {
- err = da->copy_dir(src_path, target_path, -1, true);
- }
- } else {
- err = da->copy(src_path, target_path);
- if (err == OK) {
- err = sign_shared_object(p_preset, p_debug, target_path);
- }
- }
- }
- }
-
- return err;
-}
-
-Error EditorExportPlatformPC::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
- return OK;
-}
-
-void EditorExportPlatformPC::set_name(const String &p_name) {
- name = p_name;
-}
-
-void EditorExportPlatformPC::set_os_name(const String &p_name) {
- os_name = p_name;
-}
-
-void EditorExportPlatformPC::set_logo(const Ref<Texture2D> &p_logo) {
- logo = p_logo;
-}
-
-void EditorExportPlatformPC::get_platform_features(List<String> *r_features) {
- r_features->push_back("pc"); //all pcs support "pc"
- r_features->push_back("s3tc"); //all pcs support "s3tc" compression
- r_features->push_back(get_os_name().to_lower()); //OS name is a feature
-}
-
-void EditorExportPlatformPC::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) {
- if (p_features.has("bptc")) {
- if (p_preset->has("texture_format/no_bptc_fallbacks")) {
- p_features.erase("s3tc");
- }
- }
-}
-
-int EditorExportPlatformPC::get_chmod_flags() const {
- return chmod_flags;
-}
-
-void EditorExportPlatformPC::set_chmod_flags(int p_flags) {
- chmod_flags = p_flags;
-}
-
-///////////////////////
-
-void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
- String extension = p_path.get_extension().to_lower();
- if (extension != "tres" && extension != "tscn") {
- return;
- }
-
- bool convert = GLOBAL_GET("editor/export/convert_text_resources_to_binary");
- if (!convert) {
- return;
- }
- String tmp_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpfile.res");
- Error err = ResourceFormatLoaderText::convert_file_to_binary(p_path, tmp_path);
- if (err != OK) {
- DirAccess::remove_file_or_error(tmp_path);
- ERR_FAIL();
- }
- Vector<uint8_t> data = FileAccess::get_file_as_array(tmp_path);
- if (data.size() == 0) {
- DirAccess::remove_file_or_error(tmp_path);
- ERR_FAIL();
- }
- DirAccess::remove_file_or_error(tmp_path);
- add_file(p_path + ".converted.res", data, true);
-}
-
-EditorExportTextSceneToBinaryPlugin::EditorExportTextSceneToBinaryPlugin() {
- GLOBAL_DEF("editor/export/convert_text_resources_to_binary", false);
-}
diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h
new file mode 100644
index 0000000000..832a0cf846
--- /dev/null
+++ b/editor/export/editor_export_platform.h
@@ -0,0 +1,221 @@
+/*************************************************************************/
+/* editor_export_platform.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 EDITOR_EXPORT_PLATFORM_H
+#define EDITOR_EXPORT_PLATFORM_H
+
+class EditorFileSystemDirectory;
+struct EditorProgress;
+
+#include "core/io/dir_access.h"
+#include "editor_export_preset.h"
+#include "editor_export_shared_object.h"
+#include "scene/gui/rich_text_label.h"
+#include "scene/main/node.h"
+
+class EditorExportPlatform : public RefCounted {
+ GDCLASS(EditorExportPlatform, RefCounted);
+
+public:
+ typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
+ typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so);
+
+ enum ExportMessageType {
+ EXPORT_MESSAGE_NONE,
+ EXPORT_MESSAGE_INFO,
+ EXPORT_MESSAGE_WARNING,
+ EXPORT_MESSAGE_ERROR,
+ };
+
+ struct ExportMessage {
+ ExportMessageType msg_type;
+ String category;
+ String text;
+ };
+
+private:
+ struct SavedData {
+ uint64_t ofs = 0;
+ uint64_t size = 0;
+ bool encrypted = false;
+ Vector<uint8_t> md5;
+ CharString path_utf8;
+
+ bool operator<(const SavedData &p_data) const {
+ return path_utf8 < p_data.path_utf8;
+ }
+ };
+
+ struct PackData {
+ Ref<FileAccess> f;
+ Vector<SavedData> file_ofs;
+ EditorProgress *ep = nullptr;
+ Vector<SharedObject> *so_files = nullptr;
+ };
+
+ struct ZipData {
+ void *zip = nullptr;
+ EditorProgress *ep = nullptr;
+ };
+
+ struct FeatureContainers {
+ HashSet<String> features;
+ Vector<String> features_pv;
+ };
+
+ Vector<ExportMessage> messages;
+
+ void _export_find_resources(EditorFileSystemDirectory *p_dir, HashSet<String> &p_paths);
+ void _export_find_dependencies(const String &p_path, HashSet<String> &p_paths);
+
+ void gen_debug_flags(Vector<String> &r_flags, int p_flags);
+ static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
+ static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
+
+ void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, HashSet<String> &r_list, bool exclude);
+ void _edit_filter_list(HashSet<String> &r_list, const String &p_filter, bool exclude);
+
+ static Error _add_shared_object(void *p_userdata, const SharedObject &p_so);
+
+protected:
+ struct ExportNotifier {
+ ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
+ ~ExportNotifier();
+ };
+
+ FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug) const;
+
+ bool exists_export_template(String template_file_name, String *err) const;
+ String find_export_template(String template_file_name, String *err = nullptr) const;
+ void gen_export_flags(Vector<String> &r_flags, int p_flags);
+
+public:
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const = 0;
+
+ struct ExportOption {
+ PropertyInfo option;
+ Variant default_value;
+
+ ExportOption(const PropertyInfo &p_info, const Variant &p_default) :
+ option(p_info),
+ default_value(p_default) {
+ }
+ ExportOption() {}
+ };
+
+ virtual Ref<EditorExportPreset> create_preset();
+
+ virtual void clear_messages() { messages.clear(); }
+ virtual void add_message(ExportMessageType p_type, const String &p_category, const String &p_message) {
+ ExportMessage msg;
+ msg.category = p_category;
+ msg.text = p_message;
+ msg.msg_type = p_type;
+ messages.push_back(msg);
+ switch (p_type) {
+ case EXPORT_MESSAGE_INFO: {
+ print_line(vformat("%s: %s\n", msg.category, msg.text));
+ } break;
+ case EXPORT_MESSAGE_WARNING: {
+ WARN_PRINT(vformat("%s: %s\n", msg.category, msg.text));
+ } break;
+ case EXPORT_MESSAGE_ERROR: {
+ ERR_PRINT(vformat("%s: %s\n", msg.category, msg.text));
+ } break;
+ default:
+ break;
+ }
+ }
+
+ virtual int get_message_count() const {
+ return messages.size();
+ }
+
+ virtual ExportMessage get_message(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, messages.size(), ExportMessage());
+ return messages[p_index];
+ }
+
+ virtual ExportMessageType get_worst_message_type() const {
+ ExportMessageType worst_type = EXPORT_MESSAGE_NONE;
+ for (int i = 0; i < messages.size(); i++) {
+ worst_type = MAX(worst_type, messages[i].msg_type);
+ }
+ return worst_type;
+ }
+
+ virtual bool fill_log_messages(RichTextLabel *p_log, Error p_err);
+
+ virtual void get_export_options(List<ExportOption> *r_options) = 0;
+ virtual bool should_update_export_options() { return false; }
+ virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; }
+
+ virtual String get_os_name() const = 0;
+ virtual String get_name() const = 0;
+ virtual Ref<Texture2D> get_logo() const = 0;
+
+ Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr);
+
+ Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr);
+ Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
+
+ virtual bool poll_export() { return false; }
+ virtual int get_options_count() const { return 0; }
+ virtual String get_options_tooltip() const { return ""; }
+ virtual Ref<ImageTexture> get_option_icon(int p_index) const;
+ virtual String get_option_label(int p_device) const { return ""; }
+ virtual String get_option_tooltip(int p_device) const { return ""; }
+
+ enum DebugFlags {
+ DEBUG_FLAG_DUMB_CLIENT = 1,
+ DEBUG_FLAG_REMOTE_DEBUG = 2,
+ DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST = 4,
+ DEBUG_FLAG_VIEW_COLLISONS = 8,
+ DEBUG_FLAG_VIEW_NAVIGATION = 16,
+ };
+
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { return OK; }
+ virtual Ref<Texture2D> get_run_icon() const { return get_logo(); }
+
+ String test_etc2() const;
+ virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const = 0;
+
+ virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const = 0;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) = 0;
+ virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
+ virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
+ virtual void get_platform_features(List<String> *r_features) const = 0;
+ virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) = 0;
+ virtual String get_debug_protocol() const { return "tcp://"; }
+
+ EditorExportPlatform();
+};
+
+#endif // EDITOR_EXPORT_PLATFORM_H
diff --git a/editor/export/editor_export_platform_pc.cpp b/editor/export/editor_export_platform_pc.cpp
new file mode 100644
index 0000000000..5e0044f2ae
--- /dev/null
+++ b/editor/export/editor_export_platform_pc.cpp
@@ -0,0 +1,242 @@
+/*************************************************************************/
+/* editor_export_platform_pc.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 "editor_export_platform_pc.h"
+
+#include "core/config/project_settings.h"
+
+void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
+ if (p_preset->get("texture_format/s3tc")) {
+ r_features->push_back("s3tc");
+ }
+ if (p_preset->get("texture_format/etc")) {
+ r_features->push_back("etc");
+ }
+ if (p_preset->get("texture_format/etc2")) {
+ r_features->push_back("etc2");
+ }
+ // PC platforms only have one architecture per export, since
+ // we export a single executable instead of a bundle.
+ r_features->push_back(p_preset->get("binary_format/architecture"));
+}
+
+void EditorExportPlatformPC::get_export_options(List<ExportOption> *r_options) {
+ String ext_filter = (get_os_name() == "Windows") ? "*.exe" : "";
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, ext_filter), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, ext_filter), ""));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "debug/export_console_script", PROPERTY_HINT_ENUM, "No,Debug Only,Debug and Release"), 1));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/embed_pck"), false));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/bptc"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/no_bptc_fallbacks"), true));
+}
+
+String EditorExportPlatformPC::get_name() const {
+ return name;
+}
+
+String EditorExportPlatformPC::get_os_name() const {
+ return os_name;
+}
+
+Ref<Texture2D> EditorExportPlatformPC::get_logo() const {
+ return logo;
+}
+
+bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
+ String err;
+ bool valid = false;
+
+ // Look for export templates (first official, and if defined custom templates).
+ String arch = p_preset->get("binary_format/architecture");
+ bool dvalid = exists_export_template(get_template_file_name("debug", arch), &err);
+ bool rvalid = exists_export_template(get_template_file_name("release", arch), &err);
+
+ if (p_preset->get("custom_template/debug") != "") {
+ dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+ if (!dvalid) {
+ err += TTR("Custom debug template not found.") + "\n";
+ }
+ }
+ if (p_preset->get("custom_template/release") != "") {
+ rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+ if (!rvalid) {
+ err += TTR("Custom release template not found.") + "\n";
+ }
+ }
+
+ valid = dvalid || rvalid;
+ r_missing_templates = !valid;
+
+ if (!err.is_empty()) {
+ r_error = err;
+ }
+ return valid;
+}
+
+Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
+
+ Error err = prepare_template(p_preset, p_debug, p_path, p_flags);
+ if (err == OK) {
+ err = modify_template(p_preset, p_debug, p_path, p_flags);
+ }
+ if (err == OK) {
+ err = export_project_data(p_preset, p_debug, p_path, p_flags);
+ }
+
+ return err;
+}
+
+Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ if (!DirAccess::exists(p_path.get_base_dir())) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("The given export path doesn't exist."));
+ return ERR_FILE_BAD_PATH;
+ }
+
+ String custom_debug = p_preset->get("custom_template/debug");
+ String custom_release = p_preset->get("custom_template/release");
+
+ String template_path = p_debug ? custom_debug : custom_release;
+
+ template_path = template_path.strip_edges();
+
+ if (template_path.is_empty()) {
+ template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", p_preset->get("binary_format/architecture")));
+ }
+
+ if (!template_path.is_empty() && !FileAccess::exists(template_path)) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), vformat(TTR("Template file not found: \"%s\"."), template_path));
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->make_dir_recursive(p_path.get_base_dir());
+ Error err = da->copy(template_path, p_path, get_chmod_flags());
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("Failed to copy export template."));
+ }
+
+ return err;
+}
+
+Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ String pck_path;
+ if (p_preset->get("binary_format/embed_pck")) {
+ pck_path = p_path;
+ } else {
+ pck_path = p_path.get_basename() + ".pck";
+ }
+
+ Vector<SharedObject> so_files;
+
+ int64_t embedded_pos;
+ int64_t embedded_size;
+ Error err = save_pack(p_preset, p_debug, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size);
+ if (err == OK && p_preset->get("binary_format/embed_pck")) {
+ if (embedded_size >= 0x100000000 && String(p_preset->get("binary_format/architecture")).contains("32")) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."));
+ return ERR_INVALID_PARAMETER;
+ }
+
+ err = fixup_embedded_pck(p_path, embedded_pos, embedded_size);
+ }
+
+ if (err == OK && !so_files.is_empty()) {
+ // If shared object files, copy them.
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ for (int i = 0; i < so_files.size() && err == OK; i++) {
+ String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path);
+ String target_path;
+ if (so_files[i].target.is_empty()) {
+ target_path = p_path.get_base_dir().plus_file(src_path.get_file());
+ } else {
+ target_path = p_path.get_base_dir().plus_file(so_files[i].target).plus_file(src_path.get_file());
+ }
+
+ if (da->dir_exists(src_path)) {
+ err = da->make_dir_recursive(target_path);
+ if (err == OK) {
+ err = da->copy_dir(src_path, target_path, -1, true);
+ }
+ } else {
+ err = da->copy(src_path, target_path);
+ if (err == OK) {
+ err = sign_shared_object(p_preset, p_debug, target_path);
+ }
+ }
+ }
+ }
+
+ return err;
+}
+
+Error EditorExportPlatformPC::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
+ return OK;
+}
+
+void EditorExportPlatformPC::set_name(const String &p_name) {
+ name = p_name;
+}
+
+void EditorExportPlatformPC::set_os_name(const String &p_name) {
+ os_name = p_name;
+}
+
+void EditorExportPlatformPC::set_logo(const Ref<Texture2D> &p_logo) {
+ logo = p_logo;
+}
+
+void EditorExportPlatformPC::get_platform_features(List<String> *r_features) const {
+ r_features->push_back("pc"); //all pcs support "pc"
+ r_features->push_back("s3tc"); //all pcs support "s3tc" compression
+ r_features->push_back(get_os_name().to_lower()); //OS name is a feature
+}
+
+void EditorExportPlatformPC::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) {
+ if (p_features.has("bptc")) {
+ if (p_preset->has("texture_format/no_bptc_fallbacks")) {
+ p_features.erase("s3tc");
+ }
+ }
+}
+
+int EditorExportPlatformPC::get_chmod_flags() const {
+ return chmod_flags;
+}
+
+void EditorExportPlatformPC::set_chmod_flags(int p_flags) {
+ chmod_flags = p_flags;
+}
diff --git a/editor/export/editor_export_platform_pc.h b/editor/export/editor_export_platform_pc.h
new file mode 100644
index 0000000000..bdb86e924a
--- /dev/null
+++ b/editor/export/editor_export_platform_pc.h
@@ -0,0 +1,82 @@
+/*************************************************************************/
+/* editor_export_platform_pc.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 EDITOR_EXPORT_PLATFORM_PC_H
+#define EDITOR_EXPORT_PLATFORM_PC_H
+
+#include "editor_export_platform.h"
+
+class EditorExportPlatformPC : public EditorExportPlatform {
+ GDCLASS(EditorExportPlatformPC, EditorExportPlatform);
+
+private:
+ Ref<ImageTexture> logo;
+ String name;
+ String os_name;
+
+ int chmod_flags = -1;
+
+public:
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
+
+ virtual void get_export_options(List<ExportOption> *r_options) override;
+
+ virtual String get_name() const override;
+ virtual String get_os_name() const override;
+ virtual Ref<Texture2D> get_logo() const override;
+
+ virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
+ virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
+ virtual String get_template_file_name(const String &p_target, const String &p_arch) const = 0;
+
+ virtual Error prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
+ virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { return OK; };
+ virtual Error export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
+
+ void set_extension(const String &p_extension, const String &p_feature_key = "default");
+ void set_name(const String &p_name);
+ void set_os_name(const String &p_name);
+
+ void set_logo(const Ref<Texture2D> &p_logo);
+
+ void add_platform_feature(const String &p_feature);
+ virtual void get_platform_features(List<String> *r_features) const override;
+ virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override;
+
+ int get_chmod_flags() const;
+ void set_chmod_flags(int p_flags);
+
+ virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
+ return Error::OK;
+ }
+};
+
+#endif // EDITOR_EXPORT_PLATFORM_PC_H
diff --git a/editor/export/editor_export_plugin.cpp b/editor/export/editor_export_plugin.cpp
new file mode 100644
index 0000000000..cf3a9b0810
--- /dev/null
+++ b/editor/export/editor_export_plugin.cpp
@@ -0,0 +1,201 @@
+/*************************************************************************/
+/* editor_export_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 "editor_export_plugin.h"
+
+#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
+#include "editor/editor_paths.h"
+#include "editor/export/editor_export_platform.h"
+#include "scene/resources/resource_format_text.h"
+
+void EditorExportPlugin::set_export_preset(const Ref<EditorExportPreset> &p_preset) {
+ if (p_preset.is_valid()) {
+ export_preset = p_preset;
+ }
+}
+
+Ref<EditorExportPreset> EditorExportPlugin::get_export_preset() const {
+ return export_preset;
+}
+
+void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap) {
+ ExtraFile ef;
+ ef.data = p_file;
+ ef.path = p_path;
+ ef.remap = p_remap;
+ extra_files.push_back(ef);
+}
+
+void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &p_tags, const String &p_target) {
+ shared_objects.push_back(SharedObject(p_path, p_tags, p_target));
+}
+
+void EditorExportPlugin::add_ios_framework(const String &p_path) {
+ ios_frameworks.push_back(p_path);
+}
+
+void EditorExportPlugin::add_ios_embedded_framework(const String &p_path) {
+ ios_embedded_frameworks.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_frameworks() const {
+ return ios_frameworks;
+}
+
+Vector<String> EditorExportPlugin::get_ios_embedded_frameworks() const {
+ return ios_embedded_frameworks;
+}
+
+void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) {
+ ios_plist_content += p_plist_content + "\n";
+}
+
+String EditorExportPlugin::get_ios_plist_content() const {
+ return ios_plist_content;
+}
+
+void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) {
+ if (ios_linker_flags.length() > 0) {
+ ios_linker_flags += ' ';
+ }
+ ios_linker_flags += p_flags;
+}
+
+String EditorExportPlugin::get_ios_linker_flags() const {
+ return ios_linker_flags;
+}
+
+void EditorExportPlugin::add_ios_bundle_file(const String &p_path) {
+ ios_bundle_files.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_bundle_files() const {
+ return ios_bundle_files;
+}
+
+void EditorExportPlugin::add_ios_cpp_code(const String &p_code) {
+ ios_cpp_code += p_code;
+}
+
+String EditorExportPlugin::get_ios_cpp_code() const {
+ return ios_cpp_code;
+}
+
+void EditorExportPlugin::add_macos_plugin_file(const String &p_path) {
+ macos_plugin_files.push_back(p_path);
+}
+
+const Vector<String> &EditorExportPlugin::get_macos_plugin_files() const {
+ return macos_plugin_files;
+}
+
+void EditorExportPlugin::add_ios_project_static_lib(const String &p_path) {
+ ios_project_static_libs.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_project_static_libs() const {
+ return ios_project_static_libs;
+}
+
+void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features) {
+ GDVIRTUAL_CALL(_export_file, p_path, p_type, p_features);
+}
+
+void EditorExportPlugin::_export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
+ GDVIRTUAL_CALL(_export_begin, p_features, p_debug, p_path, p_flags);
+}
+
+void EditorExportPlugin::_export_end_script() {
+ GDVIRTUAL_CALL(_export_end);
+}
+
+void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
+}
+
+void EditorExportPlugin::_export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
+}
+
+void EditorExportPlugin::skip() {
+ skipped = true;
+}
+
+void EditorExportPlugin::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags", "target"), &EditorExportPlugin::add_shared_object);
+ ClassDB::bind_method(D_METHOD("add_ios_project_static_lib", "path"), &EditorExportPlugin::add_ios_project_static_lib);
+ ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file);
+ ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework);
+ ClassDB::bind_method(D_METHOD("add_ios_embedded_framework", "path"), &EditorExportPlugin::add_ios_embedded_framework);
+ ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content);
+ ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags);
+ ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file);
+ ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code);
+ ClassDB::bind_method(D_METHOD("add_macos_plugin_file", "path"), &EditorExportPlugin::add_macos_plugin_file);
+ ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip);
+
+ GDVIRTUAL_BIND(_export_file, "path", "type", "features");
+ GDVIRTUAL_BIND(_export_begin, "features", "is_debug", "path", "flags");
+ GDVIRTUAL_BIND(_export_end);
+}
+
+EditorExportPlugin::EditorExportPlugin() {
+}
+
+///////////////////////
+
+void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
+ String extension = p_path.get_extension().to_lower();
+ if (extension != "tres" && extension != "tscn") {
+ return;
+ }
+
+ bool convert = GLOBAL_GET("editor/export/convert_text_resources_to_binary");
+ if (!convert) {
+ return;
+ }
+ String tmp_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpfile.res");
+ Error err = ResourceFormatLoaderText::convert_file_to_binary(p_path, tmp_path);
+ if (err != OK) {
+ DirAccess::remove_file_or_error(tmp_path);
+ ERR_FAIL();
+ }
+ Vector<uint8_t> data = FileAccess::get_file_as_array(tmp_path);
+ if (data.size() == 0) {
+ DirAccess::remove_file_or_error(tmp_path);
+ ERR_FAIL();
+ }
+ DirAccess::remove_file_or_error(tmp_path);
+ add_file(p_path + ".converted.res", data, true);
+}
+
+EditorExportTextSceneToBinaryPlugin::EditorExportTextSceneToBinaryPlugin() {
+ GLOBAL_DEF("editor/export/convert_text_resources_to_binary", false);
+}
diff --git a/editor/export/editor_export_plugin.h b/editor/export/editor_export_plugin.h
new file mode 100644
index 0000000000..04ebc1dfed
--- /dev/null
+++ b/editor/export/editor_export_plugin.h
@@ -0,0 +1,132 @@
+/*************************************************************************/
+/* editor_export_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 EDITOR_EXPORT_PLUGIN_H
+#define EDITOR_EXPORT_PLUGIN_H
+
+#include "core/extension/native_extension.h"
+#include "editor_export_preset.h"
+#include "editor_export_shared_object.h"
+
+class EditorExportPlugin : public RefCounted {
+ GDCLASS(EditorExportPlugin, RefCounted);
+
+ friend class EditorExportPlatform;
+
+ Ref<EditorExportPreset> export_preset;
+
+ Vector<SharedObject> shared_objects;
+ struct ExtraFile {
+ String path;
+ Vector<uint8_t> data;
+ bool remap = false;
+ };
+ Vector<ExtraFile> extra_files;
+ bool skipped = false;
+
+ Vector<String> ios_frameworks;
+ Vector<String> ios_embedded_frameworks;
+ Vector<String> ios_project_static_libs;
+ String ios_plist_content;
+ String ios_linker_flags;
+ Vector<String> ios_bundle_files;
+ String ios_cpp_code;
+
+ Vector<String> macos_plugin_files;
+
+ _FORCE_INLINE_ void _clear() {
+ shared_objects.clear();
+ extra_files.clear();
+ skipped = false;
+ }
+
+ _FORCE_INLINE_ void _export_end() {
+ ios_frameworks.clear();
+ ios_embedded_frameworks.clear();
+ ios_bundle_files.clear();
+ ios_plist_content = "";
+ ios_linker_flags = "";
+ ios_cpp_code = "";
+ macos_plugin_files.clear();
+ }
+
+ void _export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features);
+ void _export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags);
+ void _export_end_script();
+
+protected:
+ void set_export_preset(const Ref<EditorExportPreset> &p_preset);
+ Ref<EditorExportPreset> get_export_preset() const;
+
+ void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap);
+ void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String());
+
+ void add_ios_framework(const String &p_path);
+ void add_ios_embedded_framework(const String &p_path);
+ void add_ios_project_static_lib(const String &p_path);
+ void add_ios_plist_content(const String &p_plist_content);
+ void add_ios_linker_flags(const String &p_flags);
+ void add_ios_bundle_file(const String &p_path);
+ void add_ios_cpp_code(const String &p_code);
+ void add_macos_plugin_file(const String &p_path);
+
+ void skip();
+
+ virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features);
+ virtual void _export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags);
+
+ static void _bind_methods();
+
+ GDVIRTUAL3(_export_file, String, String, Vector<String>)
+ GDVIRTUAL4(_export_begin, Vector<String>, bool, String, uint32_t)
+ GDVIRTUAL0(_export_end)
+
+public:
+ Vector<String> get_ios_frameworks() const;
+ Vector<String> get_ios_embedded_frameworks() const;
+ Vector<String> get_ios_project_static_libs() const;
+ String get_ios_plist_content() const;
+ String get_ios_linker_flags() const;
+ Vector<String> get_ios_bundle_files() const;
+ String get_ios_cpp_code() const;
+ const Vector<String> &get_macos_plugin_files() const;
+
+ EditorExportPlugin();
+};
+
+class EditorExportTextSceneToBinaryPlugin : public EditorExportPlugin {
+ GDCLASS(EditorExportTextSceneToBinaryPlugin, EditorExportPlugin);
+
+public:
+ virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) override;
+ EditorExportTextSceneToBinaryPlugin();
+};
+
+#endif // EDITOR_EXPORT_PLUGIN_H
diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp
new file mode 100644
index 0000000000..cdf69e727d
--- /dev/null
+++ b/editor/export/editor_export_preset.cpp
@@ -0,0 +1,221 @@
+/*************************************************************************/
+/* editor_export_preset.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 "editor_export.h"
+
+bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) {
+ if (values.has(p_name)) {
+ values[p_name] = p_value;
+ EditorExport::singleton->save_presets();
+ return true;
+ }
+
+ return false;
+}
+
+bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const {
+ if (values.has(p_name)) {
+ r_ret = values[p_name];
+ return true;
+ }
+
+ return false;
+}
+
+void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const {
+ for (const PropertyInfo &E : properties) {
+ if (platform->get_export_option_visibility(E.name, values)) {
+ p_list->push_back(E);
+ }
+ }
+}
+
+Ref<EditorExportPlatform> EditorExportPreset::get_platform() const {
+ return platform;
+}
+
+void EditorExportPreset::update_files_to_export() {
+ Vector<String> to_remove;
+ for (const String &E : selected_files) {
+ if (!FileAccess::exists(E)) {
+ to_remove.push_back(E);
+ }
+ }
+ for (int i = 0; i < to_remove.size(); ++i) {
+ selected_files.erase(to_remove[i]);
+ }
+}
+
+Vector<String> EditorExportPreset::get_files_to_export() const {
+ Vector<String> files;
+ for (const String &E : selected_files) {
+ files.push_back(E);
+ }
+ return files;
+}
+
+void EditorExportPreset::set_name(const String &p_name) {
+ name = p_name;
+ EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_name() const {
+ return name;
+}
+
+void EditorExportPreset::set_runnable(bool p_enable) {
+ runnable = p_enable;
+ EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::is_runnable() const {
+ return runnable;
+}
+
+void EditorExportPreset::set_export_filter(ExportFilter p_filter) {
+ export_filter = p_filter;
+ EditorExport::singleton->save_presets();
+}
+
+EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const {
+ return export_filter;
+}
+
+void EditorExportPreset::set_include_filter(const String &p_include) {
+ include_filter = p_include;
+ EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_include_filter() const {
+ return include_filter;
+}
+
+void EditorExportPreset::set_export_path(const String &p_path) {
+ export_path = p_path;
+ /* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path,
+ * this should be removed. */
+ if (export_path.is_absolute_path()) {
+ String res_path = OS::get_singleton()->get_resource_dir();
+ export_path = res_path.path_to_file(export_path);
+ }
+ EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_export_path() const {
+ return export_path;
+}
+
+void EditorExportPreset::set_exclude_filter(const String &p_exclude) {
+ exclude_filter = p_exclude;
+ EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_exclude_filter() const {
+ return exclude_filter;
+}
+
+void EditorExportPreset::add_export_file(const String &p_path) {
+ selected_files.insert(p_path);
+ EditorExport::singleton->save_presets();
+}
+
+void EditorExportPreset::remove_export_file(const String &p_path) {
+ selected_files.erase(p_path);
+ EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::has_export_file(const String &p_path) {
+ return selected_files.has(p_path);
+}
+
+void EditorExportPreset::set_custom_features(const String &p_custom_features) {
+ custom_features = p_custom_features;
+ EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_custom_features() const {
+ return custom_features;
+}
+
+void EditorExportPreset::set_enc_in_filter(const String &p_filter) {
+ enc_in_filters = p_filter;
+ EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_enc_in_filter() const {
+ return enc_in_filters;
+}
+
+void EditorExportPreset::set_enc_ex_filter(const String &p_filter) {
+ enc_ex_filters = p_filter;
+ EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_enc_ex_filter() const {
+ return enc_ex_filters;
+}
+
+void EditorExportPreset::set_enc_pck(bool p_enabled) {
+ enc_pck = p_enabled;
+ EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::get_enc_pck() const {
+ return enc_pck;
+}
+
+void EditorExportPreset::set_enc_directory(bool p_enabled) {
+ enc_directory = p_enabled;
+ EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::get_enc_directory() const {
+ return enc_directory;
+}
+
+void EditorExportPreset::set_script_export_mode(int p_mode) {
+ script_mode = p_mode;
+ EditorExport::singleton->save_presets();
+}
+
+int EditorExportPreset::get_script_export_mode() const {
+ return script_mode;
+}
+
+void EditorExportPreset::set_script_encryption_key(const String &p_key) {
+ script_key = p_key;
+ EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_script_encryption_key() const {
+ return script_key;
+}
+
+EditorExportPreset::EditorExportPreset() {}
diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h
new file mode 100644
index 0000000000..00109396b0
--- /dev/null
+++ b/editor/export/editor_export_preset.h
@@ -0,0 +1,145 @@
+/*************************************************************************/
+/* editor_export_preset.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 EDITOR_EXPORT_PRESET_H
+#define EDITOR_EXPORT_PRESET_H
+
+class EditorExportPlatform;
+
+#include "core/object/ref_counted.h"
+
+class EditorExportPreset : public RefCounted {
+ GDCLASS(EditorExportPreset, RefCounted);
+
+public:
+ enum ExportFilter {
+ EXPORT_ALL_RESOURCES,
+ EXPORT_SELECTED_SCENES,
+ EXPORT_SELECTED_RESOURCES,
+ EXCLUDE_SELECTED_RESOURCES,
+ };
+
+ enum ScriptExportMode {
+ MODE_SCRIPT_TEXT,
+ MODE_SCRIPT_COMPILED,
+ };
+
+private:
+ Ref<EditorExportPlatform> platform;
+ ExportFilter export_filter = EXPORT_ALL_RESOURCES;
+ String include_filter;
+ String exclude_filter;
+ String export_path;
+
+ String exporter;
+ HashSet<String> selected_files;
+ bool runnable = false;
+
+ friend class EditorExport;
+ friend class EditorExportPlatform;
+
+ List<PropertyInfo> properties;
+ HashMap<StringName, Variant> values;
+
+ String name;
+
+ String custom_features;
+
+ String enc_in_filters;
+ String enc_ex_filters;
+ bool enc_pck = false;
+ bool enc_directory = false;
+
+ int script_mode = MODE_SCRIPT_COMPILED;
+ String script_key;
+
+protected:
+ 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:
+ Ref<EditorExportPlatform> get_platform() const;
+
+ bool has(const StringName &p_property) const { return values.has(p_property); }
+
+ void update_files_to_export();
+
+ Vector<String> get_files_to_export() const;
+
+ void add_export_file(const String &p_path);
+ void remove_export_file(const String &p_path);
+ bool has_export_file(const String &p_path);
+
+ void set_name(const String &p_name);
+ String get_name() const;
+
+ void set_runnable(bool p_enable);
+ bool is_runnable() const;
+
+ void set_export_filter(ExportFilter p_filter);
+ ExportFilter get_export_filter() const;
+
+ void set_include_filter(const String &p_include);
+ String get_include_filter() const;
+
+ void set_exclude_filter(const String &p_exclude);
+ String get_exclude_filter() const;
+
+ void set_custom_features(const String &p_custom_features);
+ String get_custom_features() const;
+
+ void set_export_path(const String &p_path);
+ String get_export_path() const;
+
+ void set_enc_in_filter(const String &p_filter);
+ String get_enc_in_filter() const;
+
+ void set_enc_ex_filter(const String &p_filter);
+ String get_enc_ex_filter() const;
+
+ void set_enc_pck(bool p_enabled);
+ bool get_enc_pck() const;
+
+ void set_enc_directory(bool p_enabled);
+ bool get_enc_directory() const;
+
+ void set_script_export_mode(int p_mode);
+ int get_script_export_mode() const;
+
+ void set_script_encryption_key(const String &p_key);
+ String get_script_encryption_key() const;
+
+ const List<PropertyInfo> &get_properties() const { return properties; }
+
+ EditorExportPreset();
+};
+
+#endif // EDITOR_EXPORT_PRESET_H
diff --git a/editor/export/editor_export_shared_object.h b/editor/export/editor_export_shared_object.h
new file mode 100644
index 0000000000..558f403ca1
--- /dev/null
+++ b/editor/export/editor_export_shared_object.h
@@ -0,0 +1,51 @@
+/*************************************************************************/
+/* editor_export_shared_object.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 EDITOR_EXPORT_SHARED_OBJECT_H
+#define EDITOR_EXPORT_SHARED_OBJECT_H
+
+#include "core/string/ustring.h"
+#include "core/templates/vector.h"
+
+struct SharedObject {
+ String path;
+ Vector<String> tags;
+ String target;
+
+ SharedObject(const String &p_path, const Vector<String> &p_tags, const String &p_target) :
+ path(p_path),
+ tags(p_tags),
+ target(p_target) {
+ }
+
+ SharedObject() {}
+};
+
+#endif // EDITOR_EXPORT_SHARED_OBJECT_H
diff --git a/editor/export_template_manager.cpp b/editor/export/export_template_manager.cpp
index 4ca2e1fdbf..a7d9d7f068 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export/export_template_manager.cpp
@@ -30,23 +30,24 @@
#include "export_template_manager.h"
-#include "core/input/input.h"
#include "core/io/dir_access.h"
#include "core/io/json.h"
#include "core/io/zip_io.h"
-#include "core/os/keyboard.h"
-#include "core/templates/rb_set.h"
#include "core/version.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
-#include "progress_dialog.h"
-#include "scene/gui/link_button.h"
+#include "editor/editor_settings.h"
+#include "editor/progress_dialog.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/tree.h"
+#include "scene/main/http_request.h"
void ExportTemplateManager::_update_template_status() {
// Fetch installed templates from the file system.
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
+ const String &templates_dir = EditorPaths::get_singleton()->get_export_templates_dir();
Error err = da->change_dir(templates_dir);
ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir + "'.");
@@ -439,7 +440,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
}
Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version);
+ String template_path = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(version);
Error err = d->make_dir_recursive(template_path);
if (err != OK) {
EditorNode::get_singleton()->show_warning(TTR("Error creating path for extracting templates:") + "\n" + template_path);
@@ -538,7 +539,7 @@ void ExportTemplateManager::_uninstall_template(const String &p_version) {
void ExportTemplateManager::_uninstall_template_confirmed() {
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
+ const String &templates_dir = EditorPaths::get_singleton()->get_export_templates_dir();
Error err = da->change_dir(templates_dir);
ERR_FAIL_COND_MSG(err != OK, "Could not access templates directory at '" + templates_dir + "'.");
@@ -616,7 +617,7 @@ void ExportTemplateManager::_installed_table_button_cbk(Object *p_item, int p_co
}
void ExportTemplateManager::_open_template_folder(const String &p_version) {
- const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
+ const String &templates_dir = EditorPaths::get_singleton()->get_export_templates_dir();
OS::get_singleton()->shell_open("file://" + templates_dir.plus_file(p_version));
}
@@ -640,12 +641,12 @@ void ExportTemplateManager::_hide_dialog() {
}
bool ExportTemplateManager::can_install_android_template() {
- const String templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
+ const String templates_dir = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(VERSION_FULL_CONFIG);
return FileAccess::exists(templates_dir.plus_file("android_source.zip"));
}
Error ExportTemplateManager::install_android_template() {
- const String &templates_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
+ const String &templates_path = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(VERSION_FULL_CONFIG);
const String &source_zip = templates_path.plus_file("android_source.zip");
ERR_FAIL_COND_V(!FileAccess::exists(source_zip), ERR_CANT_OPEN);
return install_android_template_from_file(source_zip);
@@ -810,7 +811,7 @@ void ExportTemplateManager::_bind_methods() {
ExportTemplateManager::ExportTemplateManager() {
set_title(TTR("Export Template Manager"));
set_hide_on_ok(false);
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
// Downloadable export templates are only available for stable and official alpha/beta/RC builds
// (which always have a number following their status, e.g. "alpha1").
@@ -869,13 +870,13 @@ ExportTemplateManager::ExportTemplateManager() {
current_open_button->set_text(TTR("Open Folder"));
current_open_button->set_tooltip(TTR("Open the folder containing installed templates for the current version."));
current_installed_hb->add_child(current_open_button);
- current_open_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_open_template_folder), varray(VERSION_FULL_CONFIG));
+ current_open_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_open_template_folder).bind(VERSION_FULL_CONFIG));
current_uninstall_button = memnew(Button);
current_uninstall_button->set_text(TTR("Uninstall"));
current_uninstall_button->set_tooltip(TTR("Uninstall templates for the current version."));
current_installed_hb->add_child(current_uninstall_button);
- current_uninstall_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_uninstall_template), varray(VERSION_FULL_CONFIG));
+ current_uninstall_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_uninstall_template).bind(VERSION_FULL_CONFIG));
main_vb->add_child(memnew(HSeparator));
@@ -990,8 +991,8 @@ ExportTemplateManager::ExportTemplateManager() {
install_file_dialog->set_title(TTR("Select Template File"));
install_file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM);
install_file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE);
- install_file_dialog->add_filter("*.tpz ; " + TTR("Godot Export Templates"));
- install_file_dialog->connect("file_selected", callable_mp(this, &ExportTemplateManager::_install_file_selected), varray(false));
+ install_file_dialog->add_filter("*.tpz", TTR("Godot Export Templates"));
+ install_file_dialog->connect("file_selected", callable_mp(this, &ExportTemplateManager::_install_file_selected).bind(false));
add_child(install_file_dialog);
hide_dialog_accept = memnew(AcceptDialog);
diff --git a/editor/export_template_manager.h b/editor/export/export_template_manager.h
index 3494e11d5e..f01da15832 100644
--- a/editor/export_template_manager.h
+++ b/editor/export/export_template_manager.h
@@ -31,15 +31,15 @@
#ifndef EXPORT_TEMPLATE_MANAGER_H
#define EXPORT_TEMPLATE_MANAGER_H
-#include "editor/editor_settings.h"
#include "scene/gui/dialogs.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/progress_bar.h"
-#include "scene/gui/scroll_container.h"
-#include "scene/main/http_request.h"
class ExportTemplateVersion;
+class FileDialog;
+class HTTPRequest;
+class MenuButton;
+class OptionButton;
+class ProgressBar;
+class Tree;
class ExportTemplateManager : public AcceptDialog {
GDCLASS(ExportTemplateManager, AcceptDialog);
diff --git a/editor/project_export.cpp b/editor/export/project_export.cpp
index 030337a4bc..cb82cefbbb 100644
--- a/editor/project_export.cpp
+++ b/editor/export/project_export.cpp
@@ -31,23 +31,16 @@
#include "project_export.h"
#include "core/config/project_settings.h"
-#include "core/io/dir_access.h"
-#include "core/io/file_access.h"
-#include "core/io/image_loader.h"
-#include "core/io/resource_loader.h"
-#include "core/io/resource_saver.h"
-#include "core/os/os.h"
-#include "core/string/optimized_translation.h"
-#include "core/version_generated.gen.h"
+#include "core/version.h"
#include "editor/editor_file_dialog.h"
+#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
+#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
-#include "editor/editor_settings.h"
-#include "scene/gui/box_container.h"
-#include "scene/gui/margin_container.h"
-#include "scene/gui/scroll_container.h"
-#include "scene/gui/tab_container.h"
-#include "servers/display_server.h"
+#include "editor/export/editor_export.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/link_button.h"
+#include "scene/gui/tree.h"
void ProjectExportDialog::_theme_changed() {
duplicate_preset->set_icon(presets->get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")));
@@ -366,16 +359,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) {
@@ -891,7 +885,7 @@ void ProjectExportDialog::_export_project() {
List<String> extension_list = platform->get_binary_extensions(current);
for (int i = 0; i < extension_list.size(); i++) {
// TRANSLATORS: This is the name of a project export file format. %s will be replaced by the platform name.
- export_project->add_filter(vformat("*.%s; %s", extension_list[i], vformat(TTR("%s Export"), platform->get_name())));
+ export_project->add_filter("*." + extension_list[i], vformat(TTR("%s Export"), platform->get_name()));
}
if (!current->get_export_path().is_empty()) {
@@ -1194,13 +1188,13 @@ ProjectExportDialog::ProjectExportDialog() {
delete_confirm = memnew(ConfirmationDialog);
add_child(delete_confirm);
- delete_confirm->get_ok_button()->set_text(TTR("Delete"));
+ delete_confirm->set_ok_button_text(TTR("Delete"));
delete_confirm->connect("confirmed", callable_mp(this, &ProjectExportDialog::_delete_preset_confirm));
// Export buttons, dialogs and errors.
- get_cancel_button()->set_text(TTR("Close"));
- get_ok_button()->set_text(TTR("Export PCK/ZIP..."));
+ set_cancel_button_text(TTR("Close"));
+ set_ok_button_text(TTR("Export PCK/ZIP..."));
export_button = add_button(TTR("Export Project..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export");
export_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_project));
// Disable initially before we select a valid preset
@@ -1221,8 +1215,8 @@ ProjectExportDialog::ProjectExportDialog() {
export_all_button->set_disabled(true);
export_pck_zip = memnew(EditorFileDialog);
- export_pck_zip->add_filter("*.zip ; " + TTR("ZIP File"));
- export_pck_zip->add_filter("*.pck ; " + TTR("Godot Project Pack"));
+ export_pck_zip->add_filter("*.zip", TTR("ZIP File"));
+ export_pck_zip->add_filter("*.pck", TTR("Godot Project Pack"));
export_pck_zip->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
export_pck_zip->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
add_child(export_pck_zip);
diff --git a/editor/project_export.h b/editor/export/project_export.h
index 6b10642495..96dd765a2c 100644
--- a/editor/project_export.h
+++ b/editor/export/project_export.h
@@ -28,31 +28,25 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PROJECT_EXPORT_SETTINGS_H
-#define PROJECT_EXPORT_SETTINGS_H
-
-#include "core/io/dir_access.h"
-#include "core/os/thread.h"
-#include "editor/editor_export.h"
-#include "editor/editor_file_system.h"
-#include "editor/editor_inspector.h"
-#include "editor/editor_properties.h"
-#include "scene/gui/button.h"
-#include "scene/gui/check_button.h"
-#include "scene/gui/control.h"
+#ifndef PROJECT_EXPORT_H
+#define PROJECT_EXPORT_H
+
#include "scene/gui/dialogs.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/label.h"
-#include "scene/gui/link_button.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/rich_text_label.h"
-#include "scene/gui/slider.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/tree.h"
-#include "scene/main/timer.h"
+class CheckBox;
+class CheckButton;
+class EditorExportPreset;
class EditorFileDialog;
+class EditorFileSystemDirectory;
+class EditorInspector;
+class EditorPropertyPath;
+class ItemList;
+class MenuButton;
+class OptionButton;
+class RichTextLabel;
+class TabContainer;
+class Tree;
+class TreeItem;
class ProjectExportDialog : public ConfirmationDialog {
GDCLASS(ProjectExportDialog, ConfirmationDialog);
@@ -183,4 +177,4 @@ public:
~ProjectExportDialog();
};
-#endif // PROJECT_EXPORT_SETTINGS_H
+#endif // PROJECT_EXPORT_H
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 2d6ec0c63a..b823db68f0 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -381,7 +381,7 @@ void FileSystemDock::_notification(int p_what) {
file_list_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_list_rmb_option));
tree_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_tree_rmb_option));
- current_path->connect("text_submitted", callable_mp(this, &FileSystemDock::_navigate_to_path), make_binds(false));
+ current_path->connect("text_submitted", callable_mp(this, &FileSystemDock::_navigate_to_path).bind(false));
always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"));
@@ -985,7 +985,9 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit
}
}
- if (ResourceLoader::get_resource_type(fpath) == "PackedScene") {
+ String resource_type = ResourceLoader::get_resource_type(fpath);
+
+ if (resource_type == "PackedScene") {
bool is_imported = false;
{
@@ -1005,7 +1007,7 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit
} else {
EditorNode::get_singleton()->open_request(fpath);
}
- } else if (ResourceLoader::get_resource_type(fpath) == "AnimationLibrary") {
+ } else if (resource_type == "AnimationLibrary") {
bool is_imported = false;
{
@@ -1025,6 +1027,25 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit
} else {
EditorNode::get_singleton()->open_request(fpath);
}
+ } else if (ResourceLoader::is_imported(fpath)) {
+ // If the importer has advanced settings, show them.
+ int order;
+ bool can_threads;
+ String name;
+ Error err = ResourceFormatImporter::get_singleton()->get_import_order_threads_and_importer(fpath, order, can_threads, name);
+ bool used_advanced_settings = false;
+ if (err == OK) {
+ Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(name);
+ if (importer.is_valid() && importer->has_advanced_options()) {
+ importer->show_advanced_options(fpath);
+ used_advanced_settings = true;
+ }
+ }
+
+ if (!used_advanced_settings) {
+ EditorNode::get_singleton()->load_resource(fpath);
+ }
+
} else {
EditorNode::get_singleton()->load_resource(fpath);
}
@@ -1510,14 +1531,13 @@ void FileSystemDock::_folder_removed(String p_folder) {
void FileSystemDock::_rename_operation_confirm() {
String new_name = rename_dialog_text->get_text().strip_edges();
- String old_name = tree->get_selected()->get_text(0);
if (new_name.length() == 0) {
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
return;
} else if (new_name.contains("/") || new_name.contains("\\") || new_name.contains(":")) {
EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
return;
- } else if (to_rename.is_file && old_name.get_extension() != new_name.get_extension()) {
+ } else if (to_rename.is_file && to_rename.path.get_extension() != new_name.get_extension()) {
if (!EditorFileSystem::get_singleton()->get_valid_extensions().find(new_name.get_extension())) {
EditorNode::get_singleton()->show_warning(TTR("This file extension is not recognized by the editor.\nIf you want to rename it anyway, use your operating system's file manager.\nAfter renaming to an unknown extension, the file won't be shown in the editor anymore."));
return;
@@ -2034,6 +2054,10 @@ void FileSystemDock::_resource_created() {
make_shader_dialog->config(fpath.plus_file("new_shader"), false, false, 1);
make_shader_dialog->popup_centered();
return;
+ } else if (type_name == "ShaderInclude") {
+ make_shader_dialog->config(fpath.plus_file("new_shader_include"), false, false, 2);
+ make_shader_dialog->popup_centered();
+ return;
}
Variant c = new_resource_dialog->instance_selected();
@@ -3054,7 +3078,7 @@ FileSystemDock::FileSystemDock() {
tree_search_box = memnew(LineEdit);
tree_search_box->set_h_size_flags(SIZE_EXPAND_FILL);
tree_search_box->set_placeholder(TTR("Filter Files"));
- tree_search_box->connect("text_changed", callable_mp(this, &FileSystemDock::_search_changed), varray(tree_search_box));
+ tree_search_box->connect("text_changed", callable_mp(this, &FileSystemDock::_search_changed).bind(tree_search_box));
toolbar2_hbc->add_child(tree_search_box);
tree_button_sort = _create_file_menu_button();
@@ -3099,7 +3123,7 @@ FileSystemDock::FileSystemDock() {
file_list_search_box = memnew(LineEdit);
file_list_search_box->set_h_size_flags(SIZE_EXPAND_FILL);
file_list_search_box->set_placeholder(TTR("Filter Files"));
- file_list_search_box->connect("text_changed", callable_mp(this, &FileSystemDock::_search_changed), varray(file_list_search_box));
+ file_list_search_box->connect("text_changed", callable_mp(this, &FileSystemDock::_search_changed).bind(file_list_search_box));
path_hb->add_child(file_list_search_box);
file_list_button_sort = _create_file_menu_button();
@@ -3145,9 +3169,9 @@ FileSystemDock::FileSystemDock() {
add_child(remove_dialog);
move_dialog = memnew(EditorDirDialog);
- move_dialog->get_ok_button()->set_text(TTR("Move"));
+ move_dialog->set_ok_button_text(TTR("Move"));
add_child(move_dialog);
- move_dialog->connect("dir_selected", callable_mp(this, &FileSystemDock::_move_operation_confirm), make_binds(false));
+ move_dialog->connect("dir_selected", callable_mp(this, &FileSystemDock::_move_operation_confirm).bind(false));
rename_dialog = memnew(ConfirmationDialog);
VBoxContainer *rename_dialog_vb = memnew(VBoxContainer);
@@ -3155,13 +3179,13 @@ FileSystemDock::FileSystemDock() {
rename_dialog_text = memnew(LineEdit);
rename_dialog_vb->add_margin_child(TTR("Name:"), rename_dialog_text);
- rename_dialog->get_ok_button()->set_text(TTR("Rename"));
+ rename_dialog->set_ok_button_text(TTR("Rename"));
add_child(rename_dialog);
rename_dialog->register_text_enter(rename_dialog_text);
rename_dialog->connect("confirmed", callable_mp(this, &FileSystemDock::_rename_operation_confirm));
overwrite_dialog = memnew(ConfirmationDialog);
- overwrite_dialog->get_ok_button()->set_text(TTR("Overwrite"));
+ overwrite_dialog->set_ok_button_text(TTR("Overwrite"));
add_child(overwrite_dialog);
overwrite_dialog->connect("confirmed", callable_mp(this, &FileSystemDock::_move_with_overwrite));
@@ -3171,7 +3195,7 @@ FileSystemDock::FileSystemDock() {
duplicate_dialog_text = memnew(LineEdit);
duplicate_dialog_vb->add_margin_child(TTR("Name:"), duplicate_dialog_text);
- duplicate_dialog->get_ok_button()->set_text(TTR("Duplicate"));
+ duplicate_dialog->set_ok_button_text(TTR("Duplicate"));
add_child(duplicate_dialog);
duplicate_dialog->register_text_enter(duplicate_dialog_text);
duplicate_dialog->connect("confirmed", callable_mp(this, &FileSystemDock::_duplicate_operation_confirm));
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index f73e076ac0..c38b3f8a47 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -342,4 +342,4 @@ public:
~FileSystemDock();
};
-#endif // SCENES_DOCK_H
+#endif // FILESYSTEM_DOCK_H
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/groups_editor.cpp b/editor/groups_editor.cpp
index 5dc81f623d..f16097f109 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -432,7 +432,7 @@ GroupDialog::GroupDialog() {
VBoxContainer *vbc = memnew(VBoxContainer);
add_child(vbc);
- vbc->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ vbc->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
HBoxContainer *hbc = memnew(HBoxContainer);
vbc->add_child(hbc);
@@ -473,7 +473,7 @@ GroupDialog::GroupDialog() {
add_group_button = memnew(Button);
add_group_button->set_text(TTR("Add"));
chbc->add_child(add_group_button);
- add_group_button->connect("pressed", callable_mp(this, &GroupDialog::_add_group_pressed), varray(String()));
+ add_group_button->connect("pressed", callable_mp(this, &GroupDialog::_add_group_pressed).bind(String()));
VBoxContainer *vbc_add = memnew(VBoxContainer);
hbc->add_child(vbc_add);
@@ -562,13 +562,13 @@ GroupDialog::GroupDialog() {
group_empty->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
group_empty->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
nodes_to_remove->add_child(group_empty);
- group_empty->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ group_empty->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
set_title(TTR("Group Editor"));
error = memnew(ConfirmationDialog);
add_child(error);
- error->get_ok_button()->set_text(TTR("Close"));
+ error->set_ok_button_text(TTR("Close"));
_add_group_text_changed("");
}
@@ -737,7 +737,7 @@ GroupsEditor::GroupsEditor() {
add = memnew(Button);
add->set_text(TTR("Add"));
hbc->add_child(add);
- add->connect("pressed", callable_mp(this, &GroupsEditor::_add_group), varray(String()));
+ add->connect("pressed", callable_mp(this, &GroupsEditor::_add_group).bind(String()));
tree = memnew(Tree);
tree->set_hide_root(true);
diff --git a/editor/groups_editor.h b/editor/groups_editor.h
index 75cbfd01a4..fec8913e31 100644
--- a/editor/groups_editor.h
+++ b/editor/groups_editor.h
@@ -144,4 +144,4 @@ public:
~GroupsEditor();
};
-#endif
+#endif // GROUPS_EDITOR_H
diff --git a/editor/icons/AudioStream.svg b/editor/icons/AudioStream.svg
new file mode 100644
index 0000000000..5d92dc25a5
--- /dev/null
+++ b/editor/icons/AudioStream.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff5f5f"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#5fff97"/></linearGradient><path d="m12 2a-1 1 0 0 1 1 1-1 1 0 0 1 -1 1c-4.4301 0-8 3.5699-8 8a-1 1 0 0 1 -1 1-1 1 0 0 1 -1-1c0-5.511 4.489-10 10-10zm0 4a-1 1 0 0 1 1 1-1 1 0 0 1 -1 1c-2.221 0-4 1.779-4 4a-1 1 0 0 1 -1 1-1 1 0 0 1 -1-1c0-3.3018 2.6981-6 6-6zm0 4a-2 2 0 0 1 2 2-2 2 0 0 1 -2 2-2 2 0 0 1 -2-2-2 2 0 0 1 2-2z" fill="url(#a)"/></svg>
diff --git a/editor/icons/AudioStreamGenerator.svg b/editor/icons/AudioStreamGenerator.svg
new file mode 100644
index 0000000000..55b0fb9d92
--- /dev/null
+++ b/editor/icons/AudioStreamGenerator.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff5f5f"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#5fff97"/></linearGradient><path d="m14 9-3 5-3-12-3 7-3-2" fill="none" stroke="url(#a)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></svg>
diff --git a/editor/icons/AudioStreamMicrophone.svg b/editor/icons/AudioStreamMicrophone.svg
new file mode 100644
index 0000000000..51009e9d53
--- /dev/null
+++ b/editor/icons/AudioStreamMicrophone.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff5f5f"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#5fff97"/></linearGradient><path d="m7 1c-1.108 0-2 .892-2 2h2v1h-2v2h2v1h-2c0 1.108.892 2 2 2v4l-2 2h6l-2-2v-4c1.108 0 2-.892 2-2h-2v-1h2v-2h-2v-1h2c0-1.108-.892-2-2-2z" fill="url(#a)"/></svg>
diff --git a/editor/icons/AudioStreamOGGVorbis.svg b/editor/icons/AudioStreamOggVorbis.svg
index 2e54de9faa..2e54de9faa 100644
--- a/editor/icons/AudioStreamOGGVorbis.svg
+++ b/editor/icons/AudioStreamOggVorbis.svg
diff --git a/editor/icons/AudioStreamRandomizer.svg b/editor/icons/AudioStreamRandomizer.svg
new file mode 100644
index 0000000000..1696dff795
--- /dev/null
+++ b/editor/icons/AudioStreamRandomizer.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1" y2="15"><stop offset="0" stop-color="#ff5f5f"/><stop offset=".5" stop-color="#e1da5b"/><stop offset="1" stop-color="#5fff97"/></linearGradient><path d="m7.9999997 1c6.6837543 0 7.0000003.3165085 7.0000003 7.0057779 0 6.6877711-.286255 6.9755641-6.9367525 6.9938021-3.0191555.008313-4.4456225-.105997-5.1863245-.415726-1.570375-.65669-1.876923-1.727949-1.876923-6.5780761 0-6.6892694.316247-7.0057779 6.9999997-7.0057779zm3.5299143 1.7638478c-1.5662016 0-2.4379256 1.7724432-1.475213 2.9973439.738933.9401693 2.041543 1.025967 2.876923.1899002 1.183646-1.1846229.303279-3.1872441-1.40171-3.1872441zm-3.5760682 3.2710739c-1.5661974 0-2.4379268 1.7707341-1.4752138 2.9956331.7389365.9401892 2.0415435 1.0276772 2.8769233.191611 1.1836457-1.1846231.3032798-3.1872441-1.4017095-3.1872441zm-3.5538458 3.4729499c-.958537.031867-1.875214.7423284-1.875214 1.8493884 0 1.564955 2.248443 2.516522 3.249573 1.375494.7905175-.900982.8551191-1.664857.208547-2.487522-.416627-.5300879-1.007786-.7565128-1.582906-.7373604z" fill="url(#a)"/></svg>
diff --git a/editor/icons/AudioStreamSample.svg b/editor/icons/AudioStreamWAV.svg
index 2e54de9faa..2e54de9faa 100644
--- a/editor/icons/AudioStreamSample.svg
+++ b/editor/icons/AudioStreamWAV.svg
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/CodeFoldDownArrow.svg b/editor/icons/CodeFoldDownArrow.svg
new file mode 100644
index 0000000000..0024a1256b
--- /dev/null
+++ b/editor/icons/CodeFoldDownArrow.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path d="m3 5 3 3 3-3" fill="none" stroke="#fff" stroke-width="2"/></svg>
diff --git a/editor/icons/CodeFoldedRightArrow.svg b/editor/icons/CodeFoldedRightArrow.svg
new file mode 100644
index 0000000000..f2a4bd44e0
--- /dev/null
+++ b/editor/icons/CodeFoldedRightArrow.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path d="m4 9 3-3-3-3" fill="none" stroke="#fff" stroke-width="2"/></svg>
diff --git a/editor/icons/ControlAlignWide.svg b/editor/icons/ControlAlignFullRect.svg
index 0099e04896..0099e04896 100644
--- a/editor/icons/ControlAlignWide.svg
+++ b/editor/icons/ControlAlignFullRect.svg
diff --git a/editor/icons/CopyNodePath.svg b/editor/icons/CopyNodePath.svg
index 1adec4ade3..12d03843e0 100644
--- a/editor/icons/CopyNodePath.svg
+++ b/editor/icons/CopyNodePath.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)"><circle cx="3" cy="1048.4"/><path d="m2 1c-.55226.0001-.99994.4477-1 1v12c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-8l-5-5zm1 2h6v3c0 .554.44599 1 1 1h3v6h-10zm3 5-2 4h2l2-4zm4 0-2 4h2l2-4z" fill-opacity=".78431" transform="translate(0 1036.4)"/></g></svg>
+<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)"><circle cx="3" cy="1048.4"/><path d="m2 1c-.55226.0001-.99994.4477-1 1v12c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-8l-5-5zm1 2h6v3c0 .554.44599 1 1 1h3v6h-10zm3 5-2 4h2l2-4zm4 0-2 4h2l2-4z" transform="translate(0 1036.4)"/></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..c014299783
--- /dev/null
+++ b/editor/icons/FontFile.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.5 7.5h-1a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5h-.5V9a1 1 0 0 1-1 1v1H8V9.854A1 1 0 0 1 7.5 9V7.5zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" style="fill:#e0e0e0;fill-opacity:1"/><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..39917bcba9
--- /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="M5.975 11 7.21 7.5H5.916a.478.478 0 0 0-.113.016.837.837 0 0 0-.127.043c-.044.018-.089.04-.133.066l-.043.027V9a1 1 0 0 1-1 1v1h1.475zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" style="fill:#e0e0e0;fill-opacity:1"/><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/LabelSettings.svg b/editor/icons/LabelSettings.svg
new file mode 100644
index 0000000000..4dc3b9e86e
--- /dev/null
+++ b/editor/icons/LabelSettings.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M6 3a1 1 0 0 0-.707.293l-4 4a1 1 0 0 0 0 1.414l4 4A1 1 0 0 0 6 13h2.076a3.766 3.766 0 0 1-.058-.496c-.003-.058-.006-.115-.006-.174a2.606 2.606 0 0 1 .05-.508 3.212 3.212 0 0 1 .133-.496 5.104 5.104 0 0 1 .451-.982 8.303 8.303 0 0 1 .422-.656 14.41 14.41 0 0 1 .489-.667c.172-.223.351-.45.535-.68.163-.203.327-.408.492-.618a27.639 27.639 0 0 0 .732-.977 16.04 16.04 0 0 0 .465-.697c.075-.12.147-.242.219-.365a12.399 12.399 0 0 0 .684 1.062 27.555 27.555 0 0 0 .73.977c.165.21.331.415.494.619a43.298 43.298 0 0 1 .787 1.013c.082.111.16.222.237.332L15 9.79V4a1 1 0 0 0-1-1H6zM5 7a1 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" style="fill:#8eef97;fill-opacity:1"/><path d="M9.184 13A2.99 2.99 0 0 0 12 15a2.99 2.99 0 0 0 2.816-2z" fill="#ff4596"/><path d="M9.23 11c-.136.326-.23.656-.23 1 0 .352.072.686.184 1h5.632c.112-.314.184-.648.184-1 0-.344-.094-.674-.23-1H9.23z" fill="#8045ff"/><path d="M10.564 9c-.552.69-1.058 1.342-1.334 2h5.54c-.276-.658-.782-1.31-1.335-2Z" fill="#45d7ff"/><path d="M12 7c-.43.746-.945 1.387-1.435 2h2.87c-.49-.613-1.005-1.254-1.435-2Z" fill="#45ffa2"/></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/icons/NodeWarnings2.svg b/editor/icons/NodeWarnings2.svg
new file mode 100644
index 0000000000..e0385c28d1
--- /dev/null
+++ b/editor/icons/NodeWarnings2.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.0292969 2.0019531a1.0001 1.0001 0 0 0 -.8867188.484375l-6 9.9999999a1.0001 1.0001 0 0 0 .8574219 1.513672h12a1.0001 1.0001 0 0 0 .857422-1.513672l-2.326172-3.876953c-.89392-.5083134-1.507327-1.4610509-1.529297-2.5488281l-2.1445311-3.5742188a1.0001 1.0001 0 0 0 -.828125-.484375zm-1.0292969 2.9980469h2v5h-2zm0 6h2v2h-2z" fill="#ffdd65"/><g fill="#f95252"><path d="m14 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z"/><path d="m15.447266 4.6210938c-.430501.2402237-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062z"/></g></svg>
diff --git a/editor/icons/NodeWarnings3.svg b/editor/icons/NodeWarnings3.svg
new file mode 100644
index 0000000000..53c0e70034
--- /dev/null
+++ b/editor/icons/NodeWarnings3.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.0292969 2.0019531a1.0001 1.0001 0 0 0 -.8867188.484375l-6 9.9999999a1.0001 1.0001 0 0 0 .8574219 1.513672h12a1.0001 1.0001 0 0 0 .982422-1.171875c-.308689.108606-.638692.171875-.982422.171875-1.645008 0-3-1.354992-3-3a1.0001 1.0001 0 0 0 0-.0019531c.002071-.7569921.302544-1.4803618.818359-2.0332031-.464296-.5178712-.798903-1.1662278-.816406-1.9042969l-2.1445311-3.5742188a1.0001 1.0001 0 0 0 -.828125-.484375zm-1.0292969 2.9980469h2v5h-2zm6.095703 4.7636719c-.02286.0837076-.095296.1479891-.095703.2363281v.001953c.001004.551209.418791.97816.964844.996094l-.712891-1.1875001c-.051505-.0169949-.103183-.0337067-.15625-.046875zm-6.095703 1.2363281h2v2h-2z" fill="#ffdd65"/><path d="m14 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm1.447266 4.6210938c-.430501.2402237-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062zm0 4c-.430501.2402236-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062z" fill="#f95252" stroke-dashoffset="16.5" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></svg>
diff --git a/editor/icons/NodeWarnings4Plus.svg b/editor/icons/NodeWarnings4Plus.svg
new file mode 100644
index 0000000000..64c0a0671d
--- /dev/null
+++ b/editor/icons/NodeWarnings4Plus.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.0292969 2.0019531a1.0001 1.0001 0 0 0 -.8867188.484375l-6 9.9999999a1.0001 1.0001 0 0 0 .8574219 1.513672h9a1.0001 1.0001 0 0 0 0-.001953c.002025-.740254.278882-1.453739.773438-2.001953-.478045-.532242-.773438-1.231924-.773438-1.996094a1.0001 1.0001 0 0 0 0-.0019531c.002071-.7569921.302544-1.4803618.818359-2.0332031-.464296-.5178713-.798903-1.1662278-.816406-1.9042969l-2.1445311-3.5742188a1.0001 1.0001 0 0 0 -.828125-.484375zm-1.0292969 2.9980469h2v5h-2zm6.095703 4.7636719c-.02286.0837076-.095296.1479891-.095703.2363281v.001953c.001004.551209.418791.97816.964844.996094l-.712891-1.1875001c-.051505-.0169949-.103183-.0337067-.15625-.046875zm-6.095703 1.2363281h2v2h-2zm6.095703 2.763672c-.02286.083707-.095296.147988-.095703.236328h1c-.326848 0-.598793-.160518-.904297-.236328z" fill="#ffdd65"/><g fill="#f95252" stroke-dashoffset="16.5" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m14 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z"/><path d="m15.447266 8.6210938c-.430501.2402236-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062z"/><path d="m15.447266 4.6210938c-.430501.2402237-.923653.3789062-1.447266.3789062-.522676 0-1.015355-.1375274-1.445312-.3769531a2 2 0 0 0 -.554688 1.3769531 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.3789062z"/><path d="m15.447266 12.621094c-.430501.240224-.923653.378906-1.447266.378906-.522676 0-1.015355-.137527-1.445312-.376953a2 2 0 0 0 -.554688 1.376953 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.552734-1.378906z"/></g></svg>
diff --git a/editor/icons/ShapeCast3D.svg b/editor/icons/ShapeCast3D.svg
new file mode 100644
index 0000000000..c9f24a59b4
--- /dev/null
+++ b/editor/icons/ShapeCast3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f"><path d="m7 1v9h-3l4 5 4-5h-3v-9z"/><circle cx="7.990566" cy="4.8202" r="4.009434"/></g></svg>
diff --git a/editor/icons/SystemFont.svg b/editor/icons/SystemFont.svg
new file mode 100644
index 0000000000..a6f62d56d3
--- /dev/null
+++ b/editor/icons/SystemFont.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path style="fill:#e0e0e0;fill-opacity:1;stroke-width:.714755" d="m5.787 1-.402 1.613c-.352.265-.71.122-1.012-.111l-.904-.541L2.46 2.973l.853 1.425c-.058.438-.412.586-.79.635-.343.065-.674.216-1.024.213V6.72c.367 0 .715.157 1.074.224.371.032.716.243.727.65l-.84 1.4 1.008 1.01c.443-.266.895-.53 1.33-.802.349-.044.675.139.674.506l.314 1.258c.459-.059 1.099.115 1.45-.082.117-.475.242-.954.35-1.428A.67.67 0 0 1 8 9.195V7.5H6.5a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5H4v-4h5.75c-.005-.22.107-.434.254-.625l.543-.902L9.535 1.96l-1.426.853c-.437-.058-.588-.412-.636-.79L7.217 1h-1.43z"/><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/TextEditorPlay.svg b/editor/icons/TextEditorPlay.svg
new file mode 100644
index 0000000000..5a1d195530
--- /dev/null
+++ b/editor/icons/TextEditorPlay.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1048.4v-8l7 4z" fill="#e0e0e0" fill-rule="evenodd" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/icons/TorusMesh.svg b/editor/icons/TorusMesh.svg
new file mode 100644
index 0000000000..2ed973d3cf
--- /dev/null
+++ b/editor/icons/TorusMesh.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="8" cy="7.5" fill="none" rx="6" ry="3.5" stroke="#ffca5f" stroke-linecap="square" stroke-linejoin="round" stroke-width="2"/></svg>
diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp
new file mode 100644
index 0000000000..f3709efab6
--- /dev/null
+++ b/editor/import/audio_stream_import_settings.cpp
@@ -0,0 +1,650 @@
+/*************************************************************************/
+/* audio_stream_import_settings.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 "audio_stream_import_settings.h"
+#include "editor/audio_stream_preview.h"
+#include "editor/editor_file_system.h"
+#include "editor/editor_scale.h"
+
+AudioStreamImportSettings *AudioStreamImportSettings::singleton = nullptr;
+
+void AudioStreamImportSettings::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ AudioStreamPreviewGenerator::get_singleton()->connect("preview_updated", callable_mp(this, &AudioStreamImportSettings::_preview_changed));
+ connect("confirmed", callable_mp(this, &AudioStreamImportSettings::_reimport));
+ } break;
+
+ case NOTIFICATION_THEME_CHANGED:
+ case NOTIFICATION_ENTER_TREE: {
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ _stop_button->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
+ _preview->set_color(get_theme_color(SNAME("dark_color_2"), SNAME("Editor")));
+ color_rect->set_color(get_theme_color(SNAME("dark_color_1"), SNAME("Editor")));
+ _current_label->add_theme_font_override("font", get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
+ _current_label->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
+ _duration_label->add_theme_font_override("font", get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
+ _duration_label->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
+
+ zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons")));
+ zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons")));
+ zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons")));
+
+ _indicator->update();
+ _preview->update();
+ } break;
+
+ case NOTIFICATION_PROCESS: {
+ _current = _player->get_playback_position();
+ _indicator->update();
+ } break;
+
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible()) {
+ _stop();
+ }
+ } break;
+ }
+}
+
+void AudioStreamImportSettings::_draw_preview() {
+ Rect2 rect = _preview->get_rect();
+ Size2 size = rect.size;
+
+ Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream);
+ float preview_offset = zoom_bar->get_value();
+ float preview_len = zoom_bar->get_page();
+
+ Ref<Font> beat_font = get_theme_font(SNAME("main"), SNAME("EditorFonts"));
+ int main_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts"));
+ Vector<Vector2> lines;
+ lines.resize(size.width * 2);
+ Color color_active = get_theme_color(SNAME("contrast_color_2"), SNAME("Editor"));
+ Color color_inactive = color_active;
+ color_inactive.a *= 0.5;
+ Vector<Color> color;
+ color.resize(lines.size());
+
+ float inactive_from = 1e20;
+ float beat_size = 0;
+ int last_beat = 0;
+ if (stream->get_bpm() > 0) {
+ beat_size = 60 / float(stream->get_bpm());
+ int y_ofs = beat_font->get_height(main_size) + 4 * EDSCALE;
+ rect.position.y += y_ofs;
+ rect.size.y -= y_ofs;
+
+ if (stream->get_beat_count() > 0) {
+ last_beat = stream->get_beat_count();
+ inactive_from = last_beat * beat_size;
+ }
+ }
+
+ for (int i = 0; i < size.width; i++) {
+ float ofs = preview_offset + i * preview_len / size.width;
+ float ofs_n = preview_offset + (i + 1) * preview_len / size.width;
+ float max = preview->get_max(ofs, ofs_n) * 0.5 + 0.5;
+ float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5;
+
+ int idx = i;
+ lines.write[idx * 2 + 0] = Vector2(i + 1, rect.position.y + min * rect.size.y);
+ lines.write[idx * 2 + 1] = Vector2(i + 1, rect.position.y + max * rect.size.y);
+
+ Color c = ofs > inactive_from ? color_inactive : color_active;
+
+ color.write[idx * 2 + 0] = c;
+ color.write[idx * 2 + 1] = c;
+ }
+
+ RS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, color);
+
+ if (beat_size) {
+ Color beat_color = Color(1, 1, 1, 1);
+ Color final_beat_color = beat_color;
+ Color bar_color = beat_color;
+ beat_color.a *= 0.4;
+ bar_color.a *= 0.6;
+
+ int prev_beat = 0; // Do not draw beat zero
+ Color color_bg = color_active;
+ color_bg.a *= 0.2;
+ _preview->draw_rect(Rect2(0, 0, rect.size.width, rect.position.y), color_bg);
+ int bar_beats = stream->get_bar_beats();
+
+ int last_text_end_x = 0;
+ for (int i = 0; i < size.width; i++) {
+ float ofs = preview_offset + i * preview_len / size.width;
+ int beat = int(ofs / beat_size);
+ if (beat != prev_beat) {
+ String text = itos(beat);
+ int text_w = beat_font->get_string_size(text).width;
+ if (i - text_w / 2 > last_text_end_x + 2 * EDSCALE) {
+ int x_ofs = i - text_w / 2;
+ _preview->draw_string(beat_font, Point2(x_ofs, 2 * EDSCALE + beat_font->get_ascent(main_size)), text, HORIZONTAL_ALIGNMENT_LEFT, rect.size.width - x_ofs, Font::DEFAULT_FONT_SIZE, color_active);
+ last_text_end_x = i + text_w / 2;
+ }
+
+ if (beat == last_beat) {
+ _preview->draw_rect(Rect2i(i, rect.position.y, 2, rect.size.height), final_beat_color);
+ // Darken subsequent beats
+ beat_color.a *= 0.3;
+ color_active.a *= 0.3;
+ } else {
+ _preview->draw_rect(Rect2i(i, rect.position.y, 1, rect.size.height), (beat % bar_beats) == 0 ? bar_color : beat_color);
+ }
+ prev_beat = beat;
+ }
+ }
+ }
+}
+
+void AudioStreamImportSettings::_preview_changed(ObjectID p_which) {
+ if (stream.is_valid() && stream->get_instance_id() == p_which) {
+ _preview->update();
+ }
+}
+
+void AudioStreamImportSettings::_preview_zoom_in() {
+ if (!stream.is_valid()) {
+ return;
+ }
+ float page_size = zoom_bar->get_page();
+ zoom_bar->set_page(page_size * 0.5);
+ zoom_bar->set_value(zoom_bar->get_value() + page_size * 0.25);
+
+ _preview->update();
+ _indicator->update();
+}
+
+void AudioStreamImportSettings::_preview_zoom_out() {
+ if (!stream.is_valid()) {
+ return;
+ }
+ float page_size = zoom_bar->get_page();
+ zoom_bar->set_page(MIN(zoom_bar->get_max(), page_size * 2.0));
+ zoom_bar->set_value(zoom_bar->get_value() - page_size * 0.5);
+
+ _preview->update();
+ _indicator->update();
+}
+
+void AudioStreamImportSettings::_preview_zoom_reset() {
+ if (!stream.is_valid()) {
+ return;
+ }
+ zoom_bar->set_max(stream->get_length());
+ zoom_bar->set_page(zoom_bar->get_max());
+ zoom_bar->set_value(0);
+ _preview->update();
+ _indicator->update();
+}
+
+void AudioStreamImportSettings::_preview_zoom_offset_changed(double) {
+ _preview->update();
+ _indicator->update();
+}
+
+void AudioStreamImportSettings::_audio_changed() {
+ if (!is_visible()) {
+ return;
+ }
+ _preview->update();
+ _indicator->update();
+ color_rect->update();
+}
+
+void AudioStreamImportSettings::_play() {
+ if (_player->is_playing()) {
+ // '_pausing' variable indicates that we want to pause the audio player, not stop it. See '_on_finished()'.
+ _pausing = true;
+ _player->stop();
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ set_process(false);
+ } else {
+ _player->play(_current);
+ _play_button->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons")));
+ set_process(true);
+ }
+}
+
+void AudioStreamImportSettings::_stop() {
+ _player->stop();
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ _current = 0;
+ _indicator->update();
+ set_process(false);
+}
+
+void AudioStreamImportSettings::_on_finished() {
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ if (!_pausing) {
+ _current = 0;
+ _indicator->update();
+ } else {
+ _pausing = false;
+ }
+ set_process(false);
+}
+
+void AudioStreamImportSettings::_draw_indicator() {
+ if (!stream.is_valid()) {
+ return;
+ }
+
+ Rect2 rect = _preview->get_rect();
+
+ Ref<Font> beat_font = get_theme_font(SNAME("main"), SNAME("EditorFonts"));
+ int main_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts"));
+
+ if (stream->get_bpm() > 0) {
+ int y_ofs = beat_font->get_height(main_size) + 4 * EDSCALE;
+ rect.position.y += y_ofs;
+ rect.size.height -= y_ofs;
+ }
+
+ float ofs_x = (_current - zoom_bar->get_value()) * rect.size.width / zoom_bar->get_page();
+ if (ofs_x < 0 || ofs_x >= rect.size.width) {
+ return;
+ }
+
+ const Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ _indicator->draw_line(Point2(ofs_x, rect.position.y), Point2(ofs_x, rect.position.y + rect.size.height), color, Math::round(2 * EDSCALE));
+ _indicator->draw_texture(
+ get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons")),
+ Point2(ofs_x - get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons"))->get_width() * 0.5, rect.position.y),
+ color);
+
+ if (stream->get_bpm() > 0 && _hovering_beat != -1) {
+ // Draw hovered beat.
+ float preview_offset = zoom_bar->get_value();
+ float preview_len = zoom_bar->get_page();
+ float beat_size = 60 / float(stream->get_bpm());
+ int prev_beat = 0;
+ int last_text_end_x = 0;
+ for (int i = 0; i < rect.size.width; i++) {
+ float ofs = preview_offset + i * preview_len / rect.size.width;
+ int beat = int(ofs / beat_size);
+ if (beat != prev_beat) {
+ String text = itos(beat);
+ int text_w = beat_font->get_string_size(text).width;
+ if (i - text_w / 2 > last_text_end_x + 2 * EDSCALE && beat == _hovering_beat) {
+ int x_ofs = i - text_w / 2;
+ _indicator->draw_string(beat_font, Point2(x_ofs, 2 * EDSCALE + beat_font->get_ascent(main_size)), text, HORIZONTAL_ALIGNMENT_LEFT, rect.size.width - x_ofs, Font::DEFAULT_FONT_SIZE, color);
+ last_text_end_x = i + text_w / 2;
+ break;
+ }
+ prev_beat = beat;
+ }
+ }
+ }
+
+ _current_label->set_text(String::num(_current, 2).pad_decimals(2) + " /");
+}
+
+void AudioStreamImportSettings::_on_indicator_mouse_exited() {
+ _hovering_beat = -1;
+ _indicator->update();
+}
+
+void AudioStreamImportSettings::_on_input_indicator(Ref<InputEvent> p_event) {
+ const Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
+ if (stream->get_bpm() > 0) {
+ int main_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts"));
+ Ref<Font> beat_font = get_theme_font(SNAME("main"), SNAME("EditorFonts"));
+ int y_ofs = beat_font->get_height(main_size) + 4 * EDSCALE;
+ if ((!_dragging && mb->get_position().y < y_ofs) || _beat_len_dragging) {
+ if (mb->is_pressed()) {
+ _set_beat_len_to(mb->get_position().x);
+ _beat_len_dragging = true;
+ } else {
+ _beat_len_dragging = false;
+ }
+ return;
+ }
+ }
+
+ if (mb->is_pressed()) {
+ _seek_to(mb->get_position().x);
+ }
+ _dragging = mb->is_pressed();
+ }
+
+ const Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ if (_dragging) {
+ _seek_to(mm->get_position().x);
+ }
+ if (_beat_len_dragging) {
+ _set_beat_len_to(mm->get_position().x);
+ }
+ if (stream->get_bpm() > 0) {
+ int main_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts"));
+ Ref<Font> beat_font = get_theme_font(SNAME("main"), SNAME("EditorFonts"));
+ int y_ofs = beat_font->get_height(main_size) + 4 * EDSCALE;
+ if (mm->get_position().y < y_ofs) {
+ int new_hovering_beat = _get_beat_at_pos(mm->get_position().x);
+ if (new_hovering_beat != _hovering_beat) {
+ _hovering_beat = new_hovering_beat;
+ _indicator->update();
+ }
+ } else if (_hovering_beat != -1) {
+ _hovering_beat = -1;
+ _indicator->update();
+ }
+ }
+ }
+}
+
+int AudioStreamImportSettings::_get_beat_at_pos(real_t p_x) {
+ float ofs_sec = zoom_bar->get_value() + p_x * zoom_bar->get_page() / _preview->get_size().width;
+ ofs_sec = CLAMP(ofs_sec, 0, stream->get_length());
+ float beat_size = 60 / float(stream->get_bpm());
+ int beat = int(ofs_sec / beat_size + 0.5);
+
+ if (beat * beat_size > stream->get_length() + 0.001) { // Stream may end few audio frames before but may still want to use full loop.
+ beat--;
+ }
+ return beat;
+}
+
+void AudioStreamImportSettings::_set_beat_len_to(real_t p_x) {
+ int beat = _get_beat_at_pos(p_x);
+ if (beat < 1) {
+ beat = 1; // Because 0 is disable.
+ }
+ updating_settings = true;
+ beats_enabled->set_pressed(true);
+ beats_edit->set_value(beat);
+ updating_settings = false;
+ _settings_changed();
+}
+
+void AudioStreamImportSettings::_seek_to(real_t p_x) {
+ _current = zoom_bar->get_value() + p_x / _preview->get_rect().size.x * zoom_bar->get_page();
+ _current = CLAMP(_current, 0, stream->get_length());
+ _player->seek(_current);
+ _indicator->update();
+}
+
+void AudioStreamImportSettings::edit(const String &p_path, const String &p_importer, const Ref<AudioStream> &p_stream) {
+ if (!stream.is_null()) {
+ stream->disconnect("changed", callable_mp(this, &AudioStreamImportSettings::_audio_changed));
+ }
+
+ importer = p_importer;
+ path = p_path;
+
+ stream = p_stream;
+ _player->set_stream(stream);
+ _current = 0;
+ String text = String::num(stream->get_length(), 2).pad_decimals(2) + "s";
+ _duration_label->set_text(text);
+
+ if (!stream.is_null()) {
+ stream->connect("changed", callable_mp(this, &AudioStreamImportSettings::_audio_changed));
+ _preview->update();
+ _indicator->update();
+ color_rect->update();
+ } else {
+ hide();
+ }
+ params.clear();
+
+ if (stream.is_valid()) {
+ Ref<ConfigFile> config_file;
+ config_file.instantiate();
+ Error err = config_file->load(p_path + ".import");
+ updating_settings = true;
+ if (err == OK) {
+ double bpm = config_file->get_value("params", "bpm", 0);
+ int beats = config_file->get_value("params", "beat_count", 0);
+ bpm_edit->set_value(bpm > 0 ? bpm : 120);
+ bpm_enabled->set_pressed(bpm > 0);
+ beats_edit->set_value(beats);
+ beats_enabled->set_pressed(beats > 0);
+ loop->set_pressed(config_file->get_value("params", "loop", false));
+ loop_offset->set_value(config_file->get_value("params", "loop_offset", 0));
+ bar_beats_edit->set_value(config_file->get_value("params", "bar_beats", 4));
+
+ List<String> keys;
+ config_file->get_section_keys("params", &keys);
+ for (const String &K : keys) {
+ params[K] = config_file->get_value("params", K);
+ }
+ } else {
+ bpm_edit->set_value(false);
+ bpm_enabled->set_pressed(false);
+ beats_edit->set_value(0);
+ beats_enabled->set_pressed(false);
+ bar_beats_edit->set_value(4);
+ loop->set_pressed(false);
+ loop_offset->set_value(0);
+ }
+
+ _preview_zoom_reset();
+ updating_settings = false;
+ _settings_changed();
+
+ set_title(vformat(TTR("Audio Stream Importer: %s"), p_path.get_file()));
+ popup_centered();
+ }
+}
+
+void AudioStreamImportSettings::_settings_changed() {
+ if (updating_settings) {
+ return;
+ }
+
+ updating_settings = true;
+ stream->call("set_loop", loop->is_pressed());
+ stream->call("set_loop_offset", loop_offset->get_value());
+ if (bpm_enabled->is_pressed()) {
+ stream->call("set_bpm", bpm_edit->get_value());
+ beats_enabled->show();
+ beats_edit->show();
+ bar_beats_label->show();
+ bar_beats_edit->show();
+ double bpm = bpm_edit->get_value();
+ if (bpm > 0) {
+ float beat_size = 60 / float(bpm);
+ int beat_max = int((stream->get_length() + 0.001) / beat_size);
+ int current_beat = beats_edit->get_value();
+ beats_edit->set_max(beat_max);
+ if (current_beat > beat_max) {
+ beats_edit->set_value(beat_max);
+ stream->call("set_beat_count", beat_max);
+ }
+ }
+ stream->call("set_bar_beats", bar_beats_edit->get_value());
+ } else {
+ stream->call("set_bpm", 0);
+ stream->call("set_bar_beats", 4);
+ beats_enabled->hide();
+ beats_edit->hide();
+ bar_beats_label->hide();
+ bar_beats_edit->hide();
+ }
+ if (bpm_enabled->is_pressed() && beats_enabled->is_pressed()) {
+ stream->call("set_beat_count", beats_edit->get_value());
+ } else {
+ stream->call("set_beat_count", 0);
+ }
+
+ updating_settings = false;
+
+ _preview->update();
+ _indicator->update();
+ color_rect->update();
+}
+
+void AudioStreamImportSettings::_reimport() {
+ params["loop"] = loop->is_pressed();
+ params["loop_offset"] = loop_offset->get_value();
+ params["bpm"] = bpm_enabled->is_pressed() ? double(bpm_edit->get_value()) : double(0);
+ params["beat_count"] = (bpm_enabled->is_pressed() && beats_enabled->is_pressed()) ? int(beats_edit->get_value()) : int(0);
+ params["bar_beats"] = (bpm_enabled->is_pressed()) ? int(bar_beats_edit->get_value()) : int(4);
+
+ EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(path, importer, params);
+}
+
+AudioStreamImportSettings::AudioStreamImportSettings() {
+ get_ok_button()->set_text(TTR("Reimport"));
+ get_cancel_button()->set_text(TTR("Close"));
+
+ VBoxContainer *main_vbox = memnew(VBoxContainer);
+ add_child(main_vbox);
+
+ HBoxContainer *loop_hb = memnew(HBoxContainer);
+ loop_hb->add_theme_constant_override("separation", 4 * EDSCALE);
+ loop = memnew(CheckBox);
+ loop->set_text(TTR("Enable"));
+ loop->set_tooltip(TTR("Enable looping."));
+ loop->connect("toggled", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1));
+ loop_hb->add_child(loop);
+ loop_hb->add_spacer();
+ loop_hb->add_child(memnew(Label(TTR("Offset:"))));
+ loop_offset = memnew(SpinBox);
+ loop_offset->set_max(10000);
+ loop_offset->set_step(0.001);
+ loop_offset->set_suffix("sec");
+ loop_offset->set_tooltip(TTR("Loop offset (from beginning). Note that if BPM is set, this setting will be ignored."));
+ loop_offset->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1));
+ loop_hb->add_child(loop_offset);
+ main_vbox->add_margin_child(TTR("Loop:"), loop_hb);
+
+ HBoxContainer *interactive_hb = memnew(HBoxContainer);
+ interactive_hb->add_theme_constant_override("separation", 4 * EDSCALE);
+ bpm_enabled = memnew(CheckBox);
+ bpm_enabled->set_text((TTR("BPM:")));
+ bpm_enabled->connect("toggled", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1));
+ interactive_hb->add_child(bpm_enabled);
+ bpm_edit = memnew(SpinBox);
+ bpm_edit->set_max(400);
+ bpm_edit->set_step(0.01);
+ bpm_edit->set_tooltip(TTR("Configure the Beats Per Measure (tempo) used for the interactive streams.\nThis is required in order to configure beat information."));
+ bpm_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1));
+ interactive_hb->add_child(bpm_edit);
+ interactive_hb->add_spacer();
+ bar_beats_label = memnew(Label(TTR("Beats/Bar:")));
+ interactive_hb->add_child(bar_beats_label);
+ bar_beats_edit = memnew(SpinBox);
+ bar_beats_edit->set_tooltip(TTR("Configure the Beats Per Bar. This used for music-aware transitions between AudioStreams."));
+ bar_beats_edit->set_min(2);
+ bar_beats_edit->set_max(32);
+ bar_beats_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1));
+ interactive_hb->add_child(bar_beats_edit);
+ interactive_hb->add_spacer();
+ beats_enabled = memnew(CheckBox);
+ beats_enabled->set_text(TTR("Length (in beats):"));
+ beats_enabled->connect("toggled", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1));
+ interactive_hb->add_child(beats_enabled);
+ beats_edit = memnew(SpinBox);
+ beats_edit->set_tooltip(TTR("Configure the amount of Beats used for music-aware looping. If zero, it will be autodetected from the length.\nIt is recommended to set this value (either manually or by clicking on a beat number in the preview) to ensure looping works properly."));
+ beats_edit->set_max(99999);
+ beats_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1));
+ interactive_hb->add_child(beats_edit);
+ main_vbox->add_margin_child(TTR("Music Playback:"), interactive_hb);
+
+ color_rect = memnew(ColorRect);
+ main_vbox->add_margin_child(TTR("Preview:"), color_rect);
+
+ color_rect->set_custom_minimum_size(Size2(600, 200) * EDSCALE);
+ color_rect->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+ _player = memnew(AudioStreamPlayer);
+ _player->connect("finished", callable_mp(this, &AudioStreamImportSettings::_on_finished));
+ color_rect->add_child(_player);
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 0);
+ color_rect->add_child(vbox);
+ vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+ _preview = memnew(ColorRect);
+ _preview->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ _preview->connect("draw", callable_mp(this, &AudioStreamImportSettings::_draw_preview));
+ _preview->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ vbox->add_child(_preview);
+
+ HBoxContainer *zoom_hbox = memnew(HBoxContainer);
+ zoom_bar = memnew(HScrollBar);
+ zoom_in = memnew(Button);
+ zoom_in->set_flat(true);
+ zoom_reset = memnew(Button);
+ zoom_reset->set_flat(true);
+ zoom_out = memnew(Button);
+ zoom_out->set_flat(true);
+ zoom_hbox->add_child(zoom_bar);
+ zoom_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ zoom_bar->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ zoom_hbox->add_child(zoom_out);
+ zoom_hbox->add_child(zoom_reset);
+ zoom_hbox->add_child(zoom_in);
+ zoom_in->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_preview_zoom_in));
+ zoom_reset->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_preview_zoom_reset));
+ zoom_out->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_preview_zoom_out));
+ zoom_bar->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_preview_zoom_offset_changed));
+ vbox->add_child(zoom_hbox);
+
+ _indicator = memnew(Control);
+ _indicator->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+ _indicator->connect("draw", callable_mp(this, &AudioStreamImportSettings::_draw_indicator));
+ _indicator->connect("gui_input", callable_mp(this, &AudioStreamImportSettings::_on_input_indicator));
+ _indicator->connect("mouse_exited", callable_mp(this, &AudioStreamImportSettings::_on_indicator_mouse_exited));
+ _preview->add_child(_indicator);
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ hbox->add_theme_constant_override("separation", 0);
+ vbox->add_child(hbox);
+
+ _play_button = memnew(Button);
+ _play_button->set_flat(true);
+ hbox->add_child(_play_button);
+ _play_button->set_focus_mode(Control::FOCUS_NONE);
+ _play_button->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_play));
+
+ _stop_button = memnew(Button);
+ _stop_button->set_flat(true);
+ hbox->add_child(_stop_button);
+ _stop_button->set_focus_mode(Control::FOCUS_NONE);
+ _stop_button->connect("pressed", callable_mp(this, &AudioStreamImportSettings::_stop));
+
+ _current_label = memnew(Label);
+ _current_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
+ _current_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ _current_label->set_modulate(Color(1, 1, 1, 0.5));
+ hbox->add_child(_current_label);
+
+ _duration_label = memnew(Label);
+ hbox->add_child(_duration_label);
+
+ singleton = this;
+}
diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/import/audio_stream_import_settings.h
index 0d927bddd5..5e399237ca 100644
--- a/editor/plugins/audio_stream_editor_plugin.h
+++ b/editor/import/audio_stream_import_settings.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* audio_stream_editor_plugin.h */
+/* audio_stream_import_settings.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,17 +28,27 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIO_STREAM_EDITOR_PLUGIN_H
-#define AUDIO_STREAM_EDITOR_PLUGIN_H
+#ifndef AUDIO_STREAM_IMPORT_SETTINGS_H
+#define AUDIO_STREAM_IMPORT_SETTINGS_H
#include "editor/editor_plugin.h"
#include "scene/audio/audio_stream_player.h"
#include "scene/gui/color_rect.h"
+#include "scene/gui/spin_box.h"
#include "scene/resources/texture.h"
-class AudioStreamEditor : public ColorRect {
- GDCLASS(AudioStreamEditor, ColorRect);
+class AudioStreamImportSettings : public ConfirmationDialog {
+ GDCLASS(AudioStreamImportSettings, ConfirmationDialog);
+ CheckBox *bpm_enabled = nullptr;
+ SpinBox *bpm_edit = nullptr;
+ CheckBox *beats_enabled = nullptr;
+ SpinBox *beats_edit = nullptr;
+ Label *bar_beats_label = nullptr;
+ SpinBox *bar_beats_edit = nullptr;
+ CheckBox *loop = nullptr;
+ SpinBox *loop_offset = nullptr;
+ ColorRect *color_rect = nullptr;
Ref<AudioStream> stream;
AudioStreamPlayer *_player = nullptr;
ColorRect *_preview = nullptr;
@@ -46,18 +56,42 @@ class AudioStreamEditor : public ColorRect {
Label *_current_label = nullptr;
Label *_duration_label = nullptr;
+ HScrollBar *zoom_bar = nullptr;
+ Button *zoom_in = nullptr;
+ Button *zoom_reset = nullptr;
+ Button *zoom_out = nullptr;
+
Button *_play_button = nullptr;
Button *_stop_button = nullptr;
+ bool updating_settings = false;
+
float _current = 0;
bool _dragging = false;
+ bool _beat_len_dragging = false;
bool _pausing = false;
+ int _hovering_beat = -1;
+
+ HashMap<StringName, Variant> params;
+ String importer;
+ String path;
void _audio_changed();
+ static AudioStreamImportSettings *singleton;
+
+ void _settings_changed();
+
+ void _reimport();
+
protected:
void _notification(int p_what);
void _preview_changed(ObjectID p_which);
+ void _preview_zoom_in();
+ void _preview_zoom_out();
+ void _preview_zoom_reset();
+ void _preview_zoom_offset_changed(double);
+
void _play();
void _stop();
void _on_finished();
@@ -65,27 +99,16 @@ protected:
void _draw_indicator();
void _on_input_indicator(Ref<InputEvent> p_event);
void _seek_to(real_t p_x);
- static void _bind_methods();
+ void _set_beat_len_to(real_t p_x);
+ void _on_indicator_mouse_exited();
+ int _get_beat_at_pos(real_t p_x);
public:
- void edit(Ref<AudioStream> p_stream);
- AudioStreamEditor();
-};
+ void edit(const String &p_path, const String &p_importer, const Ref<AudioStream> &p_stream);
-class AudioStreamEditorPlugin : public EditorPlugin {
- GDCLASS(AudioStreamEditorPlugin, EditorPlugin);
+ static AudioStreamImportSettings *get_singleton() { return singleton; }
- AudioStreamEditor *audio_editor = nullptr;
-
-public:
- virtual String get_name() const override { return "Audio"; }
- 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;
-
- AudioStreamEditorPlugin();
- ~AudioStreamEditorPlugin();
+ AudioStreamImportSettings();
};
-#endif // AUDIO_STREAM_EDITOR_PLUGIN_H
+#endif // AUDIO_STREAM_IMPORT_SETTINGS_H
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index f7fe334828..043681aa87 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,69 +939,62 @@ 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;
inspector_vars->edit(nullptr);
+ inspector_text->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 +1013,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 +1072,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 +1106,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 +1116,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 +1168,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 +1177,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 +1205,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 +1253,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 +1308,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,106 +1359,11 @@ 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();
import_settings_data->owner = this;
- get_ok_button()->set_text(TTR("Reimport"));
- get_cancel_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Reimport"));
+ set_cancel_button_text(TTR("Close"));
}
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/editor_import_collada.h b/editor/import/editor_import_collada.h
index e45db47440..a75b0a903f 100644
--- a/editor/import/editor_import_collada.h
+++ b/editor/import/editor_import_collada.h
@@ -44,4 +44,4 @@ public:
EditorSceneFormatImporterCollada();
};
-#endif
+#endif // EDITOR_IMPORT_COLLADA_H
diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h
index 44fbd41962..4548513b6f 100644
--- a/editor/import/editor_import_plugin.h
+++ b/editor/import/editor_import_plugin.h
@@ -68,4 +68,4 @@ public:
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, Variant *r_metadata = nullptr) override;
};
-#endif //EDITOR_IMPORT_PLUGIN_H
+#endif // EDITOR_IMPORT_PLUGIN_H
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..69c0a047e4
--- /dev/null
+++ b/editor/import/post_import_plugin_skeleton_renamer.cpp
@@ -0,0 +1,190 @@
+/*************************************************************************/
+/* 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));
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/unique_node/make_unique"), true));
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::STRING, "retarget/bone_renamer/unique_node/skeleton_name"), "GeneralSkeleton"));
+ }
+}
+
+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);
+ }
+ }
+
+ // Make unique skeleton.
+ if (bool(p_options["retarget/bone_renamer/unique_node/make_unique"])) {
+ String unique_name = String(p_options["retarget/bone_renamer/unique_node/skeleton_name"]);
+ ERR_FAIL_COND_MSG(unique_name == String(), "Skeleton unique name cannot be empty.");
+
+ 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 track_len = anim->get_track_count();
+ for (int i = 0; i < track_len; i++) {
+ String track_path = String(anim->track_get_path(i).get_concatenated_names());
+ Node *orig_node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
+ Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
+ while (node) {
+ Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (track_skeleton && track_skeleton == skeleton) {
+ if (node == orig_node) {
+ if (anim->track_get_path(i).get_subname_count() > 0) {
+ anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name + String(":") + anim->track_get_path(i).get_concatenated_subnames());
+ } else {
+ anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name);
+ }
+ } else {
+ if (anim->track_get_path(i).get_subname_count() > 0) {
+ anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name + "/" + node->get_path_to(orig_node) + String(":") + anim->track_get_path(i).get_concatenated_subnames());
+ } else {
+ anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name + "/" + node->get_path_to(orig_node));
+ }
+ }
+ break;
+ }
+ node = node->get_parent();
+ }
+ }
+ }
+ }
+ skeleton->set_name(unique_name);
+ skeleton->set_unique_name_in_owner(true);
+ }
+ }
+}
+
+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/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp
new file mode 100644
index 0000000000..4f00bd120a
--- /dev/null
+++ b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp
@@ -0,0 +1,489 @@
+/*************************************************************************/
+/* post_import_plugin_skeleton_rest_fixer.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_rest_fixer.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 PostImportPluginSkeletonRestFixer::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/rest_fixer/normalize_position_tracks"), true));
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/overwrite_axis"), true));
+
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/fix_silhouette/enable"), false));
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "retarget/rest_fixer/fix_silhouette/threshold"), 15));
+
+ // TODO: PostImportPlugin need to be implemented such as validate_option(PropertyInfo &property, const Dictionary &p_options).
+ // get_internal_option_visibility() is not sufficient because it can only retrieve options implemented in the core and can only read option values.
+ // r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::ARRAY, "retarget/rest_fixer/filter", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::STRING_NAME, PROPERTY_HINT_ENUM, "Hips,Spine,Chest")), Array()));
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::ARRAY, "retarget/rest_fixer/fix_silhouette/filter", PROPERTY_HINT_ARRAY_TYPE, "StringName"), Array()));
+ }
+}
+
+void PostImportPluginSkeletonRestFixer::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) {
+ return;
+ }
+ BoneMap *bone_map = Object::cast_to<BoneMap>(map);
+ Ref<SkeletonProfile> profile = bone_map->get_profile();
+ if (!profile.is_valid()) {
+ return;
+ }
+ Skeleton3D *src_skeleton = Object::cast_to<Skeleton3D>(p_node);
+ if (!src_skeleton) {
+ return;
+ }
+ bool is_renamed = bool(p_options["retarget/bone_renamer/rename_bones"]);
+ Array filter = p_options["retarget/rest_fixer/fix_silhouette/filter"];
+ bool is_rest_changed = false;
+
+ // Build profile skeleton.
+ Skeleton3D *prof_skeleton = memnew(Skeleton3D);
+ {
+ int prof_bone_len = profile->get_bone_size();
+ // Add single bones.
+ for (int i = 0; i < prof_bone_len; i++) {
+ prof_skeleton->add_bone(profile->get_bone_name(i));
+ prof_skeleton->set_bone_rest(i, profile->get_reference_pose(i));
+ }
+ // Set parents.
+ for (int i = 0; i < prof_bone_len; i++) {
+ int parent = profile->find_bone(profile->get_bone_parent(i));
+ if (parent >= 0) {
+ prof_skeleton->set_bone_parent(i, parent);
+ }
+ }
+ }
+
+ // Set motion scale to Skeleton if normalize position tracks.
+ if (bool(p_options["retarget/rest_fixer/normalize_position_tracks"])) {
+ int src_bone_idx = src_skeleton->find_bone(profile->get_scale_base_bone());
+ if (src_bone_idx >= 0) {
+ real_t motion_scale = abs(src_skeleton->get_bone_global_rest(src_bone_idx).origin.y);
+ if (motion_scale > 0) {
+ src_skeleton->set_motion_scale(motion_scale);
+ }
+ }
+
+ 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 track_len = anim->get_track_count();
+ for (int i = 0; i < track_len; i++) {
+ if (anim->track_get_path(i).get_subname_count() != 1 || anim->track_get_type(i) != Animation::TYPE_POSITION_3D) {
+ continue;
+ }
+
+ if (anim->track_is_compressed(i)) {
+ continue; // Shouldn't occur in internal_process().
+ }
+
+ 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) {
+ if (track_skeleton && track_skeleton == src_skeleton) {
+ real_t mlt = 1 / src_skeleton->get_motion_scale();
+ int key_len = anim->track_get_key_count(i);
+ for (int j = 0; j < key_len; j++) {
+ Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j));
+ anim->track_set_key_value(i, j, pos * mlt);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Complement Rotation track for compatibility between different rests.
+ {
+ 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 track_len = anim->get_track_count();
+
+ // Detect does the animation have skeleton's TRS track.
+ String track_path;
+ bool found_skeleton = false;
+ for (int i = 0; i < track_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;
+ }
+ 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 == src_skeleton) {
+ found_skeleton = true;
+ break;
+ }
+ }
+ }
+
+ if (found_skeleton) {
+ // Search and insert rot track if it doesn't exist.
+ for (int prof_idx = 0; prof_idx < prof_skeleton->get_bone_count(); prof_idx++) {
+ String bone_name = is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx)));
+ if (bone_name == String()) {
+ continue;
+ }
+ int src_idx = src_skeleton->find_bone(bone_name);
+ if (src_idx == -1) {
+ continue;
+ }
+ String insert_path = track_path + ":" + bone_name;
+ int rot_track = anim->find_track(insert_path, Animation::TYPE_ROTATION_3D);
+ if (rot_track == -1) {
+ int track = anim->add_track(Animation::TYPE_ROTATION_3D);
+ anim->track_set_path(track, insert_path);
+ anim->rotation_track_insert_key(track, 0, src_skeleton->get_bone_rest(src_idx).basis.get_rotation_quaternion());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Fix silhouette.
+ Vector<Transform3D> silhouette_diff; // Transform values to be ignored when overwrite axis.
+ silhouette_diff.resize(src_skeleton->get_bone_count());
+ Transform3D *silhouette_diff_w = silhouette_diff.ptrw();
+ if (bool(p_options["retarget/rest_fixer/fix_silhouette/enable"])) {
+ LocalVector<Transform3D> old_skeleton_global_rest;
+ for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
+ old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i));
+ }
+
+ Vector<int> bones_to_process = prof_skeleton->get_parentless_bones();
+ while (bones_to_process.size() > 0) {
+ int prof_idx = bones_to_process[0];
+ bones_to_process.erase(prof_idx);
+ Vector<int> prof_children = prof_skeleton->get_bone_children(prof_idx);
+ for (int i = 0; i < prof_children.size(); i++) {
+ bones_to_process.push_back(prof_children[i]);
+ }
+
+ // Calc virtual/looking direction with origins.
+ bool is_filtered = false;
+ for (int i = 0; i < filter.size(); i++) {
+ if (String(filter[i]) == prof_skeleton->get_bone_name(prof_idx)) {
+ is_filtered = true;
+ break;
+ }
+ }
+ if (is_filtered) {
+ continue;
+ }
+
+ int src_idx = src_skeleton->find_bone(is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx))));
+ if (src_idx < 0 || profile->get_tail_direction(prof_idx) == SkeletonProfile::TAIL_DIRECTION_END) {
+ continue;
+ }
+ Vector3 prof_tail;
+ Vector3 src_tail;
+ if (profile->get_tail_direction(prof_idx) == SkeletonProfile::TAIL_DIRECTION_AVERAGE_CHILDREN) {
+ PackedInt32Array prof_bone_children = prof_skeleton->get_bone_children(prof_idx);
+ int children_size = prof_bone_children.size();
+ if (children_size == 0) {
+ continue;
+ }
+ bool exist_all_children = true;
+ for (int i = 0; i < children_size; i++) {
+ int prof_child_idx = prof_bone_children[i];
+ int src_child_idx = src_skeleton->find_bone(is_renamed ? prof_skeleton->get_bone_name(prof_child_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_child_idx))));
+ if (src_child_idx < 0) {
+ exist_all_children = false;
+ break;
+ }
+ prof_tail = prof_tail + prof_skeleton->get_bone_global_rest(prof_child_idx).origin;
+ src_tail = src_tail + src_skeleton->get_bone_global_rest(src_child_idx).origin;
+ }
+ if (!exist_all_children) {
+ continue;
+ }
+ prof_tail = prof_tail / children_size;
+ src_tail = src_tail / children_size;
+ }
+ if (profile->get_tail_direction(prof_idx) == SkeletonProfile::TAIL_DIRECTION_SPECIFIC_CHILD) {
+ int prof_tail_idx = prof_skeleton->find_bone(profile->get_bone_tail(prof_idx));
+ if (prof_tail_idx < 0) {
+ continue;
+ }
+ int src_tail_idx = src_skeleton->find_bone(is_renamed ? prof_skeleton->get_bone_name(prof_tail_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_tail_idx))));
+ if (src_tail_idx < 0) {
+ continue;
+ }
+ prof_tail = prof_skeleton->get_bone_global_rest(prof_tail_idx).origin;
+ src_tail = src_skeleton->get_bone_global_rest(src_tail_idx).origin;
+ }
+
+ Vector3 prof_head = prof_skeleton->get_bone_global_rest(prof_idx).origin;
+ Vector3 src_head = src_skeleton->get_bone_global_rest(src_idx).origin;
+
+ Vector3 prof_dir = prof_tail - prof_head;
+ Vector3 src_dir = src_tail - src_head;
+
+ // Rotate rest.
+ if (Math::abs(Math::rad2deg(src_dir.angle_to(prof_dir))) > float(p_options["retarget/rest_fixer/fix_silhouette/threshold"])) {
+ // Get rotation difference.
+ Vector3 up_vec; // Need to rotate other than roll axis.
+ switch (Vector3(abs(src_dir.x), abs(src_dir.y), abs(src_dir.z)).min_axis_index()) {
+ case Vector3::AXIS_X: {
+ up_vec = Vector3(1, 0, 0);
+ } break;
+ case Vector3::AXIS_Y: {
+ up_vec = Vector3(0, 1, 0);
+ } break;
+ case Vector3::AXIS_Z: {
+ up_vec = Vector3(0, 0, 1);
+ } break;
+ }
+ Basis src_b;
+ src_b = src_b.looking_at(src_dir, up_vec);
+ Basis prof_b;
+ prof_b = src_b.looking_at(prof_dir, up_vec);
+ if (prof_b.is_equal_approx(Basis())) {
+ continue; // May not need to rotate.
+ }
+ Basis diff_b = prof_b * src_b.inverse();
+
+ // Apply rotation difference as global transform to skeleton.
+ Basis src_pg;
+ int src_parent = src_skeleton->get_bone_parent(src_idx);
+ if (src_parent >= 0) {
+ src_pg = src_skeleton->get_bone_global_rest(src_parent).basis;
+ }
+ Transform3D fixed_rest = Transform3D(src_pg.inverse() * diff_b * src_pg * src_skeleton->get_bone_rest(src_idx).basis, src_skeleton->get_bone_rest(src_idx).origin);
+ src_skeleton->set_bone_rest(src_idx, fixed_rest);
+ }
+ }
+
+ // For skin modification in overwrite rest.
+ for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
+ silhouette_diff_w[i] = old_skeleton_global_rest[i] * src_skeleton->get_bone_global_rest(i).inverse();
+ }
+
+ is_rest_changed = true;
+ }
+
+ // Overwrite axis.
+ if (bool(p_options["retarget/rest_fixer/overwrite_axis"])) {
+ LocalVector<Transform3D> old_skeleton_rest;
+ LocalVector<Transform3D> old_skeleton_global_rest;
+ for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
+ old_skeleton_rest.push_back(src_skeleton->get_bone_rest(i));
+ old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i));
+ }
+
+ Vector<Basis> diffs;
+ diffs.resize(src_skeleton->get_bone_count());
+ Basis *diffs_w = diffs.ptrw();
+
+ Vector<int> bones_to_process = src_skeleton->get_parentless_bones();
+ while (bones_to_process.size() > 0) {
+ int src_idx = bones_to_process[0];
+ bones_to_process.erase(src_idx);
+ Vector<int> src_children = src_skeleton->get_bone_children(src_idx);
+ for (int i = 0; i < src_children.size(); i++) {
+ bones_to_process.push_back(src_children[i]);
+ }
+
+ Basis tgt_rot;
+ StringName src_bone_name = is_renamed ? StringName(src_skeleton->get_bone_name(src_idx)) : bone_map->find_profile_bone_name(src_skeleton->get_bone_name(src_idx));
+ if (src_bone_name != StringName()) {
+ Basis src_pg;
+ int src_parent_idx = src_skeleton->get_bone_parent(src_idx);
+ if (src_parent_idx >= 0) {
+ src_pg = src_skeleton->get_bone_global_rest(src_parent_idx).basis;
+ }
+
+ int prof_idx = profile->find_bone(src_bone_name);
+ if (prof_idx >= 0) {
+ tgt_rot = src_pg.inverse() * prof_skeleton->get_bone_global_rest(prof_idx).basis; // Mapped bone uses reference pose.
+ }
+ /*
+ // If there is rest-relative animation, this logic may be work fine, but currently not so...
+ } else {
+ // tgt_rot = src_pg.inverse() * old_skeleton_global_rest[src_idx].basis; // Non-Mapped bone keeps global rest.
+ }
+ */
+ }
+
+ if (src_skeleton->get_bone_parent(src_idx) >= 0) {
+ diffs_w[src_idx] = tgt_rot.inverse() * diffs[src_skeleton->get_bone_parent(src_idx)] * src_skeleton->get_bone_rest(src_idx).basis;
+ } else {
+ diffs_w[src_idx] = tgt_rot.inverse() * src_skeleton->get_bone_rest(src_idx).basis;
+ }
+
+ Basis diff;
+ if (src_skeleton->get_bone_parent(src_idx) >= 0) {
+ diff = diffs[src_skeleton->get_bone_parent(src_idx)];
+ }
+ src_skeleton->set_bone_rest(src_idx, Transform3D(tgt_rot, diff.xform(src_skeleton->get_bone_rest(src_idx).origin)));
+ }
+
+ // Fix 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 == src_skeleton) {
+ int skin_len = skin->get_bind_count();
+ for (int i = 0; i < skin_len; i++) {
+ StringName bn = skin->get_bind_name(i);
+ int bone_idx = src_skeleton->find_bone(bn);
+ if (bone_idx >= 0) {
+ Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx);
+ skin->set_bind_pose(i, new_rest.inverse());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Fix animation.
+ {
+ 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 track_len = anim->get_track_count();
+ for (int i = 0; i < track_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;
+ }
+
+ if (anim->track_is_compressed(i)) {
+ continue; // Shouldn't occur in internal_process().
+ }
+
+ 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 == src_skeleton) {
+ StringName bn = anim->track_get_path(i).get_subname(0);
+ if (bn) {
+ int bone_idx = src_skeleton->find_bone(bn);
+
+ Transform3D old_rest = old_skeleton_rest[bone_idx];
+ Transform3D new_rest = src_skeleton->get_bone_rest(bone_idx);
+ Transform3D old_pg;
+ Transform3D new_pg;
+ int parent_idx = src_skeleton->get_bone_parent(bone_idx);
+ if (parent_idx >= 0) {
+ old_pg = old_skeleton_global_rest[parent_idx];
+ new_pg = src_skeleton->get_bone_global_rest(parent_idx);
+ }
+
+ int key_len = anim->track_get_key_count(i);
+ if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) {
+ Quaternion old_rest_q = old_rest.basis.get_rotation_quaternion();
+ Quaternion new_rest_q = new_rest.basis.get_rotation_quaternion();
+ Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion();
+ Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion();
+ for (int j = 0; j < key_len; j++) {
+ Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j));
+ anim->track_set_key_value(i, j, new_pg_q.inverse() * old_pg_q * qt * old_rest_q.inverse() * old_pg_q.inverse() * new_pg_q * new_rest_q);
+ }
+ } else if (anim->track_get_type(i) == Animation::TYPE_SCALE_3D) {
+ Basis old_rest_b = old_rest.basis;
+ Basis new_rest_b = new_rest.basis;
+ Basis old_pg_b = old_pg.basis;
+ Basis new_pg_b = new_pg.basis;
+ for (int j = 0; j < key_len; j++) {
+ Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j)));
+ anim->track_set_key_value(i, j, (new_pg_b.inverse() * old_pg_b * sc * old_rest_b.inverse() * old_pg_b.inverse() * new_pg_b * new_rest_b).get_scale());
+ }
+ } else {
+ Vector3 old_rest_o = old_rest.origin;
+ Vector3 new_rest_o = new_rest.origin;
+ Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion();
+ Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion();
+ for (int j = 0; j < key_len; j++) {
+ Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
+ anim->track_set_key_value(i, j, new_pg_q.xform_inv(old_pg_q.xform(ps - old_rest_o)) + new_rest_o);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ is_rest_changed = true;
+ }
+
+ // Init skeleton pose to new rest.
+ if (is_rest_changed) {
+ for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
+ Transform3D fixed_rest = src_skeleton->get_bone_rest(i);
+ src_skeleton->set_bone_pose_position(i, fixed_rest.origin);
+ src_skeleton->set_bone_pose_rotation(i, fixed_rest.basis.get_rotation_quaternion());
+ src_skeleton->set_bone_pose_scale(i, fixed_rest.basis.get_scale());
+ }
+ }
+
+ memdelete(prof_skeleton);
+ }
+}
+
+PostImportPluginSkeletonRestFixer::PostImportPluginSkeletonRestFixer() {
+}
diff --git a/editor/import/post_import_plugin_skeleton_rest_fixer.h b/editor/import/post_import_plugin_skeleton_rest_fixer.h
new file mode 100644
index 0000000000..11e9d08e88
--- /dev/null
+++ b/editor/import/post_import_plugin_skeleton_rest_fixer.h
@@ -0,0 +1,46 @@
+/*************************************************************************/
+/* post_import_plugin_skeleton_rest_fixer.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_REST_FIXER_H
+#define POST_IMPORT_PLUGIN_SKELETON_REST_FIXER_H
+
+#include "resource_importer_scene.h"
+
+class PostImportPluginSkeletonRestFixer : public EditorScenePostImportPlugin {
+ GDCLASS(PostImportPluginSkeletonRestFixer, 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;
+
+ PostImportPluginSkeletonRestFixer();
+};
+
+#endif // POST_IMPORT_PLUGIN_SKELETON_REST_FIXER_H
diff --git a/editor/import/post_import_plugin_skeleton_track_organizer.cpp b/editor/import/post_import_plugin_skeleton_track_organizer.cpp
new file mode 100644
index 0000000000..01186f47fe
--- /dev/null
+++ b/editor/import/post_import_plugin_skeleton_track_organizer.cpp
@@ -0,0 +1,127 @@
+/*************************************************************************/
+/* post_import_plugin_skeleton_track_organizer.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_track_organizer.h"
+
+#include "editor/import/scene_import_settings.h"
+#include "scene/3d/skeleton_3d.h"
+#include "scene/animation/animation_player.h"
+#include "scene/resources/bone_map.h"
+
+void PostImportPluginSkeletonTrackOrganizer::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/remove_tracks/except_bone_transform"), false));
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/unimportant_positions"), true));
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/unmapped_bones"), false));
+ }
+}
+
+void PostImportPluginSkeletonTrackOrganizer::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) {
+ return;
+ }
+ BoneMap *bone_map = Object::cast_to<BoneMap>(map);
+ Ref<SkeletonProfile> profile = bone_map->get_profile();
+ if (!profile.is_valid()) {
+ return;
+ }
+ Skeleton3D *src_skeleton = Object::cast_to<Skeleton3D>(p_node);
+ if (!src_skeleton) {
+ return;
+ }
+ bool remove_except_bone = bool(p_options["retarget/remove_tracks/except_bone_transform"]);
+ bool remove_positions = bool(p_options["retarget/remove_tracks/unimportant_positions"]);
+ bool remove_unmapped_bones = bool(p_options["retarget/remove_tracks/unmapped_bones"]);
+
+ if (!remove_positions && !remove_unmapped_bones) {
+ return;
+ }
+
+ 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 track_len = anim->get_track_count();
+ Vector<int> remove_indices;
+ for (int i = 0; i < track_len; i++) {
+ 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) {
+ if (remove_except_bone) {
+ remove_indices.push_back(i);
+ }
+ continue;
+ }
+ Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (track_skeleton && track_skeleton == src_skeleton) {
+ 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)) {
+ if (remove_except_bone) {
+ remove_indices.push_back(i);
+ }
+ continue;
+ }
+ StringName bn = anim->track_get_path(i).get_subname(0);
+ if (bn) {
+ int prof_idx = profile->find_bone(bone_map->find_profile_bone_name(bn));
+ if (remove_unmapped_bones && prof_idx < 0) {
+ remove_indices.push_back(i);
+ continue;
+ }
+ if (remove_positions && anim->track_get_type(i) == Animation::TYPE_POSITION_3D && prof_idx >= 0) {
+ StringName prof_bn = profile->get_bone_name(prof_idx);
+ if (prof_bn == profile->get_root_bone() || prof_bn == profile->get_scale_base_bone()) {
+ continue;
+ }
+ remove_indices.push_back(i);
+ }
+ }
+ }
+ if (remove_except_bone) {
+ remove_indices.push_back(i);
+ }
+ }
+
+ remove_indices.reverse();
+ for (int i = 0; i < remove_indices.size(); i++) {
+ anim->remove_track(remove_indices[i]);
+ }
+ }
+ }
+ }
+}
+
+PostImportPluginSkeletonTrackOrganizer::PostImportPluginSkeletonTrackOrganizer() {
+}
diff --git a/editor/import/post_import_plugin_skeleton_track_organizer.h b/editor/import/post_import_plugin_skeleton_track_organizer.h
new file mode 100644
index 0000000000..1830861430
--- /dev/null
+++ b/editor/import/post_import_plugin_skeleton_track_organizer.h
@@ -0,0 +1,46 @@
+/*************************************************************************/
+/* post_import_plugin_skeleton_track_organizer.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_TRACK_ORGANIZER_H
+#define POST_IMPORT_PLUGIN_SKELETON_TRACK_ORGANIZER_H
+
+#include "resource_importer_scene.h"
+
+class PostImportPluginSkeletonTrackOrganizer : public EditorScenePostImportPlugin {
+ GDCLASS(PostImportPluginSkeletonTrackOrganizer, 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;
+
+ PostImportPluginSkeletonTrackOrganizer();
+};
+
+#endif // POST_IMPORT_PLUGIN_SKELETON_TRACK_ORGANIZER_H
diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp
index 966719dc48..c03962b8a4 100644
--- a/editor/import/resource_importer_bitmask.cpp
+++ b/editor/import/resource_importer_bitmask.cpp
@@ -103,7 +103,7 @@ Error ResourceImporterBitMap::import(const String &p_source_file, const String &
}
}
- return ResourceSaver::save(p_save_path + ".res", bitmap);
+ return ResourceSaver::save(bitmap, p_save_path + ".res");
}
ResourceImporterBitMap::ResourceImporterBitMap() {
diff --git a/editor/import/resource_importer_bitmask.h b/editor/import/resource_importer_bitmask.h
index 8682ab80a3..e791788d50 100644
--- a/editor/import/resource_importer_bitmask.h
+++ b/editor/import/resource_importer_bitmask.h
@@ -53,4 +53,5 @@ public:
ResourceImporterBitMap();
~ResourceImporterBitMap();
};
+
#endif // RESOURCE_IMPORTER_BITMASK_H
diff --git a/editor/import/resource_importer_bmfont.cpp b/editor/import/resource_importer_bmfont.cpp
index 8a40b113b9..14b5638755 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,25 +60,31 @@ 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;
}
print_verbose("Saving to: " + p_save_path + ".fontdata");
- err = ResourceSaver::save(p_save_path + ".fontdata", font, flg);
+ err = ResourceSaver::save(font, p_save_path + ".fontdata", flg);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save font to file \"" + p_save_path + ".res\".");
print_verbose("Done saving to: " + p_save_path + ".fontdata");
return OK;
diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp
index 0b3622e3c0..8b429e74d1 100644
--- a/editor/import/resource_importer_csv_translation.cpp
+++ b/editor/import/resource_importer_csv_translation.cpp
@@ -131,7 +131,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const
String save_path = p_source_file.get_basename() + "." + translations[i]->get_locale() + ".translation";
- ResourceSaver::save(save_path, xlt);
+ ResourceSaver::save(xlt, save_path);
if (r_gen_files) {
r_gen_files->push_back(save_path);
}
diff --git a/editor/import/resource_importer_csv_translation.h b/editor/import/resource_importer_csv_translation.h
index 306aafa843..2ed121c5e8 100644
--- a/editor/import/resource_importer_csv_translation.h
+++ b/editor/import/resource_importer_csv_translation.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RESOURCEIMPORTERCSVTRANSLATION_H
-#define RESOURCEIMPORTERCSVTRANSLATION_H
+#ifndef RESOURCE_IMPORTER_CSV_TRANSLATION_H
+#define RESOURCE_IMPORTER_CSV_TRANSLATION_H
#include "core/io/resource_importer.h"
@@ -54,4 +54,4 @@ public:
ResourceImporterCSVTranslation();
};
-#endif // RESOURCEIMPORTERCSVTRANSLATION_H
+#endif // RESOURCE_IMPORTER_CSV_TRANSLATION_H
diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp
index a92b0fe280..32fd94b093 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,111 +168,58 @@ 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;
}
print_verbose("Saving to: " + p_save_path + ".fontdata");
- Error err = ResourceSaver::save(p_save_path + ".fontdata", font, flg);
+ Error err = ResourceSaver::save(font, p_save_path + ".fontdata", flg);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save font to file \"" + p_save_path + ".res\".");
print_verbose("Done saving to: " + p_save_path + ".fontdata");
return OK;
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..374cbe7ce2 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,16 +150,16 @@ 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;
}
print_verbose("Saving to: " + p_save_path + ".fontdata");
- err = ResourceSaver::save(p_save_path + ".fontdata", font, flg);
+ err = ResourceSaver::save(font, p_save_path + ".fontdata", flg);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save font to file \"" + p_save_path + ".res\".");
print_verbose("Done saving to: " + p_save_path + ".fontdata");
return OK;
diff --git a/editor/import/resource_importer_imagefont.h b/editor/import/resource_importer_imagefont.h
index f46bc8c19b..e163f873da 100644
--- a/editor/import/resource_importer_imagefont.h
+++ b/editor/import/resource_importer_imagefont.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RESOURCE_IMPORTER_IMAGE_FONT_H
-#define RESOURCE_IMPORTER_IMAGE_FONT_H
+#ifndef RESOURCE_IMPORTER_IMAGEFONT_H
+#define RESOURCE_IMPORTER_IMAGEFONT_H
#include "core/io/resource_importer.h"
#include "scene/resources/font.h"
@@ -55,4 +55,4 @@ public:
ResourceImporterImageFont();
};
-#endif // RESOURCE_IMPORTER_IMAGE_FONT_H
+#endif // RESOURCE_IMPORTER_IMAGEFONT_H
diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp
index bacd09592e..2e6de95a46 100644
--- a/editor/import/resource_importer_layered_texture.cpp
+++ b/editor/import/resource_importer_layered_texture.cpp
@@ -367,7 +367,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
for (int j = 0; j < hslices; j++) {
int x = slice_w * j;
int y = slice_h * i;
- Ref<Image> slice = image->get_rect(Rect2(x, y, slice_w, slice_h));
+ Ref<Image> slice = image->get_rect(Rect2i(x, y, slice_w, slice_h));
ERR_CONTINUE(slice.is_null() || slice->is_empty());
if (slice->get_width() != slice_w || slice->get_height() != slice_h) {
slice->resize(slice_w, slice_h);
@@ -391,7 +391,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
texture_import->bptc_ldr = bptc_ldr;
texture_import->mipmaps = mipmaps;
texture_import->used_channels = used_channels;
- _check_compress_ctex(texture_import);
+ _check_compress_ctex(p_source_file, texture_import);
if (r_metadata) {
Dictionary metadata;
metadata["vram_texture"] = compress_mode == COMPRESS_VRAM_COMPRESSED;
@@ -472,7 +472,7 @@ ResourceImporterLayeredTexture::ResourceImporterLayeredTexture() {
ResourceImporterLayeredTexture::~ResourceImporterLayeredTexture() {
}
-void ResourceImporterLayeredTexture::_check_compress_ctex(Ref<LayeredTextureImport> r_texture_import) {
+void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source_file, Ref<LayeredTextureImport> r_texture_import) {
String extension = get_save_extension();
ERR_FAIL_NULL(r_texture_import->csource);
if (r_texture_import->compress_mode != COMPRESS_VRAM_COMPRESSED) {
@@ -542,5 +542,5 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(Ref<LayeredTextureImpo
}
return;
}
- EditorNode::add_io_error(TTR("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correctly on PC."));
+ EditorNode::add_io_error(vformat(TTR("%s: No suitable PC VRAM compression algorithm enabled in Project Settings (S3TC or BPTC). This texture may not display correctly on desktop platforms."), p_source_file));
}
diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h
index 5a29010c3b..e292390fb3 100644
--- a/editor/import/resource_importer_layered_texture.h
+++ b/editor/import/resource_importer_layered_texture.h
@@ -87,7 +87,7 @@ protected:
static ResourceImporterLayeredTexture *singleton;
public:
- void _check_compress_ctex(Ref<LayeredTextureImport> r_texture_import);
+ void _check_compress_ctex(const String &p_source_file, Ref<LayeredTextureImport> r_texture_import);
static ResourceImporterLayeredTexture *get_singleton() { return singleton; }
virtual String get_importer_name() const override;
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 6fbfecfdfa..d1c4e1f8dd 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -519,7 +519,7 @@ Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_s
String save_path = p_save_path + ".mesh";
- err = ResourceSaver::save(save_path, meshes.front()->get());
+ err = ResourceSaver::save(meshes.front()->get(), save_path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save Mesh to file '" + save_path + "'.");
diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h
index 3da9f02adb..4dfac90fa1 100644
--- a/editor/import/resource_importer_obj.h
+++ b/editor/import/resource_importer_obj.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RESOURCEIMPORTEROBJ_H
-#define RESOURCEIMPORTEROBJ_H
+#ifndef RESOURCE_IMPORTER_OBJ_H
+#define RESOURCE_IMPORTER_OBJ_H
#include "resource_importer_scene.h"
@@ -69,4 +69,4 @@ public:
ResourceImporterOBJ();
};
-#endif // RESOURCEIMPORTEROBJ_H
+#endif // RESOURCE_IMPORTER_OBJ_H
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 171ef5bf4c..3c0de61d24 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);
}
@@ -742,6 +743,163 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, HashMap<R
return p_node;
}
+Node *ResourceImporterScene::_pre_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps) {
+ // children first
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ Node *r = _pre_fix_animations(p_node->get_child(i), p_root, p_node_data, p_animation_data, p_animation_fps);
+ if (!r) {
+ i--; //was erased
+ }
+ }
+
+ String import_id = p_node->get_meta("import_id", "PATH:" + p_root->get_path_to(p_node));
+
+ Dictionary node_settings;
+ if (p_node_data.has(import_id)) {
+ node_settings = p_node_data[import_id];
+ }
+
+ {
+ //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;
+ }
+ }
+ }
+
+ if (Object::cast_to<AnimationPlayer>(p_node)) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
+
+ Array animation_clips;
+ {
+ int clip_count = node_settings["clips/amount"];
+
+ for (int i = 0; i < clip_count; i++) {
+ String name = node_settings["clip_" + itos(i + 1) + "/name"];
+ int from_frame = node_settings["clip_" + itos(i + 1) + "/start_frame"];
+ int end_frame = node_settings["clip_" + itos(i + 1) + "/end_frame"];
+ Animation::LoopMode loop_mode = static_cast<Animation::LoopMode>((int)node_settings["clip_" + itos(i + 1) + "/loop_mode"]);
+ bool save_to_file = node_settings["clip_" + itos(i + 1) + "/save_to_file/enabled"];
+ bool save_to_path = node_settings["clip_" + itos(i + 1) + "/save_to_file/path"];
+ bool save_to_file_keep_custom = node_settings["clip_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"];
+
+ animation_clips.push_back(name);
+ animation_clips.push_back(from_frame / p_animation_fps);
+ animation_clips.push_back(end_frame / p_animation_fps);
+ animation_clips.push_back(loop_mode);
+ animation_clips.push_back(save_to_file);
+ animation_clips.push_back(save_to_path);
+ animation_clips.push_back(save_to_file_keep_custom);
+ }
+ }
+
+ if (animation_clips.size()) {
+ _create_clips(ap, animation_clips, true);
+ } else {
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ AnimationImportTracks import_tracks_mode[TRACK_CHANNEL_MAX] = {
+ AnimationImportTracks(int(node_settings["import_tracks/position"])),
+ AnimationImportTracks(int(node_settings["import_tracks/rotation"])),
+ AnimationImportTracks(int(node_settings["import_tracks/scale"]))
+ };
+ if (anims.size() > 1 && (import_tracks_mode[0] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[1] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[2] != ANIMATION_IMPORT_TRACKS_IF_PRESENT)) {
+ _optimize_track_usage(ap, import_tracks_mode);
+ }
+ }
+ }
+
+ return p_node;
+}
+
+Node *ResourceImporterScene::_post_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps) {
+ // children first
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ Node *r = _post_fix_animations(p_node->get_child(i), p_root, p_node_data, p_animation_data, p_animation_fps);
+ if (!r) {
+ i--; //was erased
+ }
+ }
+
+ String import_id = p_node->get_meta("import_id", "PATH:" + p_root->get_path_to(p_node));
+
+ Dictionary node_settings;
+ if (p_node_data.has(import_id)) {
+ node_settings = p_node_data[import_id];
+ }
+
+ {
+ //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;
+ }
+ }
+ }
+
+ if (Object::cast_to<AnimationPlayer>(p_node)) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
+
+ bool use_optimizer = node_settings["optimizer/enabled"];
+ float anim_optimizer_linerr = node_settings["optimizer/max_linear_error"];
+ float anim_optimizer_angerr = node_settings["optimizer/max_angular_error"];
+ float anim_optimizer_maxang = node_settings["optimizer/max_angle"];
+
+ if (use_optimizer) {
+ _optimize_animations(ap, anim_optimizer_linerr, anim_optimizer_angerr, anim_optimizer_maxang);
+ }
+
+ bool use_compression = node_settings["compression/enabled"];
+ int anim_compression_page_size = node_settings["compression/page_size"];
+
+ if (use_compression) {
+ _compress_animations(ap, anim_compression_page_size);
+ }
+
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for (const StringName &name : anims) {
+ Ref<Animation> anim = ap->get_animation(name);
+ if (p_animation_data.has(name)) {
+ Dictionary anim_settings = p_animation_data[name];
+ {
+ //fill with default values
+ List<ImportOption> iopts;
+ get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION, &iopts);
+ for (const ImportOption &F : iopts) {
+ if (!anim_settings.has(F.option.name)) {
+ anim_settings[F.option.name] = F.default_value;
+ }
+ }
+ }
+
+ anim->set_loop_mode(static_cast<Animation::LoopMode>((int)anim_settings["settings/loop_mode"]));
+ bool save = anim_settings["save_to_file/enabled"];
+ String path = anim_settings["save_to_file/path"];
+ bool keep_custom = anim_settings["save_to_file/keep_custom_tracks"];
+
+ Ref<Animation> saved_anim = _save_animation_to_file(anim, save, path, keep_custom);
+
+ if (saved_anim != anim) {
+ Ref<AnimationLibrary> al = ap->get_animation_library(ap->find_animation_library(anim));
+ al->add_animation(name, saved_anim); //replace
+ }
+ }
+ }
+ }
+
+ return p_node;
+}
+
Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) {
// children first
for (int i = 0; i < p_node->get_child_count(); i++) {
@@ -766,6 +924,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 +964,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 +988,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,100 +1165,10 @@ 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);
}
- bool use_optimizer = node_settings["optimizer/enabled"];
- float anim_optimizer_linerr = node_settings["optimizer/max_linear_error"];
- float anim_optimizer_angerr = node_settings["optimizer/max_angular_error"];
- float anim_optimizer_maxang = node_settings["optimizer/max_angle"];
-
- if (use_optimizer) {
- _optimize_animations(ap, anim_optimizer_linerr, anim_optimizer_angerr, anim_optimizer_maxang);
- }
-
- Array animation_clips;
- {
- int clip_count = node_settings["clips/amount"];
-
- for (int i = 0; i < clip_count; i++) {
- String name = node_settings["clip_" + itos(i + 1) + "/name"];
- int from_frame = node_settings["clip_" + itos(i + 1) + "/start_frame"];
- int end_frame = node_settings["clip_" + itos(i + 1) + "/end_frame"];
- Animation::LoopMode loop_mode = static_cast<Animation::LoopMode>((int)node_settings["clip_" + itos(i + 1) + "/loop_mode"]);
- bool save_to_file = node_settings["clip_" + itos(i + 1) + "/save_to_file/enabled"];
- bool save_to_path = node_settings["clip_" + itos(i + 1) + "/save_to_file/path"];
- bool save_to_file_keep_custom = node_settings["clip_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"];
-
- animation_clips.push_back(name);
- animation_clips.push_back(from_frame / p_animation_fps);
- animation_clips.push_back(end_frame / p_animation_fps);
- animation_clips.push_back(loop_mode);
- animation_clips.push_back(save_to_file);
- animation_clips.push_back(save_to_path);
- animation_clips.push_back(save_to_file_keep_custom);
- }
- }
-
- if (animation_clips.size()) {
- _create_clips(ap, animation_clips, true);
- } else {
- List<StringName> anims;
- ap->get_animation_list(&anims);
- for (const StringName &name : anims) {
- Ref<Animation> anim = ap->get_animation(name);
- if (p_animation_data.has(name)) {
- Dictionary anim_settings = p_animation_data[name];
- {
- //fill with default values
- List<ImportOption> iopts;
- get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION, &iopts);
- for (const ImportOption &F : iopts) {
- if (!anim_settings.has(F.option.name)) {
- anim_settings[F.option.name] = F.default_value;
- }
- }
- }
-
- anim->set_loop_mode(static_cast<Animation::LoopMode>((int)anim_settings["settings/loop_mode"]));
- bool save = anim_settings["save_to_file/enabled"];
- String path = anim_settings["save_to_file/path"];
- bool keep_custom = anim_settings["save_to_file/keep_custom_tracks"];
-
- Ref<Animation> saved_anim = _save_animation_to_file(anim, save, path, keep_custom);
-
- if (saved_anim != anim) {
- Ref<AnimationLibrary> al = ap->get_animation_library(ap->find_animation_library(anim));
- al->add_animation(name, saved_anim); //replace
- }
- }
- }
-
- AnimationImportTracks import_tracks_mode[TRACK_CHANNEL_MAX] = {
- AnimationImportTracks(int(node_settings["import_tracks/position"])),
- AnimationImportTracks(int(node_settings["import_tracks/rotation"])),
- AnimationImportTracks(int(node_settings["import_tracks/scale"]))
- };
-
- if (anims.size() > 1 && (import_tracks_mode[0] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[1] != ANIMATION_IMPORT_TRACKS_IF_PRESENT || import_tracks_mode[2] != ANIMATION_IMPORT_TRACKS_IF_PRESENT)) {
- _optimize_track_usage(ap, import_tracks_mode);
- }
- }
-
if (post_importer_plugins.size()) {
List<StringName> anims;
ap->get_animation_list(&anims);
@@ -1084,13 +1193,6 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
}
}
}
-
- bool use_compression = node_settings["compression/enabled"];
- int anim_compression_page_size = node_settings["compression/page_size"];
-
- if (use_compression) {
- _compress_animations(ap, anim_compression_page_size);
- }
}
return p_node;
@@ -1122,7 +1224,7 @@ Ref<Animation> ResourceImporterScene::_save_animation_to_file(Ref<Animation> ani
}
}
anim->set_path(p_save_to_path, true); // Set path to save externally.
- Error err = ResourceSaver::save(p_save_to_path, anim, ResourceSaver::FLAG_CHANGE_PATH);
+ Error err = ResourceSaver::save(anim, p_save_to_path, ResourceSaver::FLAG_CHANGE_PATH);
ERR_FAIL_COND_V_MSG(err != OK, anim, "Saving of animation failed: " + p_save_to_path);
return anim;
}
@@ -1385,6 +1487,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 +1605,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 +1646,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 +1736,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"];
@@ -1718,7 +1842,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m
}
mesh = src_mesh_node->get_mesh()->get_mesh(existing);
- ResourceSaver::save(save_to_file, mesh); //override
+ ResourceSaver::save(mesh, save_to_file); //override
mesh->set_path(save_to_file, true); //takeover existing, if needed
@@ -1921,7 +2045,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 +2070,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;
}
@@ -2043,7 +2172,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
post_importer_plugins.write[i]->pre_process(scene, p_options);
}
+ _pre_fix_animations(scene, scene, node_data, animation_data, fps);
_post_fix_node(scene, scene, collision_map, occluder_arrays, scanned_meshes, node_data, material_data, animation_data, fps);
+ _post_fix_animations(scene, scene, node_data, animation_data, fps);
String root_type = p_options["nodes/root_type"];
root_type = root_type.split(" ")[0]; // full root_type is "ClassName (filename.gd)" for a script global class.
@@ -2179,14 +2310,14 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
}
print_verbose("Saving animation to: " + p_save_path + ".scn");
- err = ResourceSaver::save(p_save_path + ".res", library); //do not take over, let the changed files reload themselves
+ err = ResourceSaver::save(library, p_save_path + ".res"); //do not take over, let the changed files reload themselves
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save animation to file '" + p_save_path + ".res'.");
} else {
Ref<PackedScene> packer = memnew(PackedScene);
packer->pack(scene);
print_verbose("Saving scene to: " + p_save_path + ".scn");
- err = ResourceSaver::save(p_save_path + ".scn", packer); //do not take over, let the changed files reload themselves
+ err = ResourceSaver::save(packer, p_save_path + ".scn"); //do not take over, let the changed files reload themselves
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'.");
}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 16cf3d651d..b336931476 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RESOURCEIMPORTERSCENE_H
-#define RESOURCEIMPORTERSCENE_H
+#ifndef RESOURCE_IMPORTER_SCENE_H
+#define RESOURCE_IMPORTER_SCENE_H
#include "core/error/error_macros.h"
#include "core/io/resource_importer.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
};
@@ -272,14 +274,16 @@ public:
virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; }
Node *_pre_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames);
+ Node *_pre_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps);
Node *_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps);
+ Node *_post_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps);
Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks);
void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all);
void _optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle);
void _compress_animations(AnimationPlayer *anim, int p_page_size_kb);
- Node *pre_import(const String &p_source_file);
+ 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;
@@ -477,4 +481,4 @@ Transform3D ResourceImporterScene::get_collision_shapes_transform(const M &p_opt
return transform;
}
-#endif // RESOURCEIMPORTERSCENE_H
+#endif // RESOURCE_IMPORTER_SCENE_H
diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp
index 64839bf199..d3079141e0 100644
--- a/editor/import/resource_importer_shader_file.cpp
+++ b/editor/import/resource_importer_shader_file.cpp
@@ -109,7 +109,7 @@ Error ResourceImporterShaderFile::import(const String &p_source_file, const Stri
}
}
- ResourceSaver::save(p_save_path + ".res", shader_file);
+ ResourceSaver::save(shader_file, p_save_path + ".res");
return OK;
}
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index deb3047864..0eed6184c0 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -597,7 +597,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
}
if (!ok_on_pc) {
- EditorNode::add_io_error(TTR("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correctly on PC."));
+ EditorNode::add_io_error(vformat(TTR("%s: No suitable desktop VRAM compression algorithm enabled in Project Settings (S3TC or BPTC). This texture may not display correctly on desktop platforms."), p_source_file));
}
} else {
//import normally
diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h
index 7def2d4f77..496ad3bf70 100644
--- a/editor/import/resource_importer_texture.h
+++ b/editor/import/resource_importer_texture.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RESOURCEIMPORTTEXTURE_H
-#define RESOURCEIMPORTTEXTURE_H
+#ifndef RESOURCE_IMPORTER_TEXTURE_H
+#define RESOURCE_IMPORTER_TEXTURE_H
#include "core/io/file_access.h"
#include "core/io/image.h"
@@ -109,4 +109,4 @@ public:
~ResourceImporterTexture();
};
-#endif // RESOURCEIMPORTTEXTURE_H
+#endif // RESOURCE_IMPORTER_TEXTURE_H
diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp
index e5fe99890e..bae1b903c6 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(ImageTexture::create_from_image(broken), p_save_path + ".tex");
return OK;
}
@@ -218,7 +212,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file
EditorAtlasPacker::Chart chart;
- Rect2 used_rect = Rect2(Vector2(), image->get_size());
+ Rect2i used_rect = Rect2i(Vector2i(), image->get_size());
if (trim_alpha_border_from_region) {
// Clip a region from the image.
used_rect = image->get_used_rect();
@@ -226,9 +220,9 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file
pack_data.region = used_rect;
chart.vertices.push_back(used_rect.position);
- chart.vertices.push_back(used_rect.position + Vector2(used_rect.size.x, 0));
- chart.vertices.push_back(used_rect.position + Vector2(used_rect.size.x, used_rect.size.y));
- chart.vertices.push_back(used_rect.position + Vector2(0, used_rect.size.y));
+ chart.vertices.push_back(used_rect.position + Vector2i(used_rect.size.x, 0));
+ chart.vertices.push_back(used_rect.position + Vector2i(used_rect.size.x, used_rect.size.y));
+ chart.vertices.push_back(used_rect.position + Vector2i(0, used_rect.size.y));
EditorAtlasPacker::Chart::Face f;
f.vertex[0] = 0;
f.vertex[1] = 1;
@@ -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;
}
@@ -394,7 +386,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file
}
String save_path = p_base_paths[E.key] + ".res";
- ResourceSaver::save(save_path, texture);
+ ResourceSaver::save(texture, save_path);
idx++;
}
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index 362940dc17..a1e00f7d30 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -33,7 +33,7 @@
#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/io/resource_saver.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.h"
const float TRIM_DB_LIMIT = -50;
const int TRIM_FADE_OUT_FRAMES = 500;
@@ -55,7 +55,7 @@ String ResourceImporterWAV::get_save_extension() const {
}
String ResourceImporterWAV::get_resource_type() const {
- return "AudioStreamSample";
+ return "AudioStreamWAV";
}
bool ResourceImporterWAV::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
@@ -86,7 +86,7 @@ void ResourceImporterWAV::get_import_options(const String &p_path, List<ImportOp
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "force/max_rate_hz", PROPERTY_HINT_RANGE, "11025,192000,1,exp"), 44100));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/trim"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/normalize"), false));
- // Keep the `edit/loop_mode` enum in sync with AudioStreamSample::LoopMode (note: +1 offset due to "Detect From WAV").
+ // Keep the `edit/loop_mode` enum in sync with AudioStreamWAV::LoopMode (note: +1 offset due to "Detect From WAV").
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_mode", PROPERTY_HINT_ENUM, "Detect From WAV,Disabled,Forward,Ping-Pong,Backward", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_begin"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_end"), -1));
@@ -130,7 +130,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
int format_bits = 0;
int format_channels = 0;
- AudioStreamSample::LoopMode loop_mode = AudioStreamSample::LOOP_DISABLED;
+ AudioStreamWAV::LoopMode loop_mode = AudioStreamWAV::LOOP_DISABLED;
uint16_t compression_code = 1;
bool format_found = false;
bool data_found = false;
@@ -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();
+ }
}
}
@@ -268,11 +282,11 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
int loop_type = file->get_32();
if (loop_type == 0x00 || loop_type == 0x01 || loop_type == 0x02) {
if (loop_type == 0x00) {
- loop_mode = AudioStreamSample::LOOP_FORWARD;
+ loop_mode = AudioStreamWAV::LOOP_FORWARD;
} else if (loop_type == 0x01) {
- loop_mode = AudioStreamSample::LOOP_PINGPONG;
+ loop_mode = AudioStreamWAV::LOOP_PINGPONG;
} else if (loop_type == 0x02) {
- loop_mode = AudioStreamSample::LOOP_BACKWARD;
+ loop_mode = AudioStreamWAV::LOOP_BACKWARD;
}
loop_begin = file->get_32();
loop_end = file->get_32();
@@ -372,7 +386,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
bool trim = p_options["edit/trim"];
- if (trim && (loop_mode != AudioStreamSample::LOOP_DISABLED) && format_channels > 0) {
+ if (trim && (loop_mode != AudioStreamWAV::LOOP_DISABLED) && format_channels > 0) {
int first = 0;
int last = (frames / format_channels) - 1;
bool found = false;
@@ -417,7 +431,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
}
if (import_loop_mode >= 2) {
- loop_mode = (AudioStreamSample::LoopMode)(import_loop_mode - 1);
+ loop_mode = (AudioStreamWAV::LoopMode)(import_loop_mode - 1);
loop_begin = p_options["edit/loop_begin"];
loop_end = p_options["edit/loop_end"];
// Wrap around to max frames, so `-1` can be used to select the end, etc.
@@ -449,10 +463,10 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
}
Vector<uint8_t> dst_data;
- AudioStreamSample::Format dst_format;
+ AudioStreamWAV::Format dst_format;
if (compression == 1) {
- dst_format = AudioStreamSample::FORMAT_IMA_ADPCM;
+ dst_format = AudioStreamWAV::FORMAT_IMA_ADPCM;
if (format_channels == 1) {
_compress_ima_adpcm(data, dst_data);
} else {
@@ -489,7 +503,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
}
} else {
- dst_format = is16 ? AudioStreamSample::FORMAT_16_BITS : AudioStreamSample::FORMAT_8_BITS;
+ dst_format = is16 ? AudioStreamWAV::FORMAT_16_BITS : AudioStreamWAV::FORMAT_8_BITS;
dst_data.resize(data.size() * (is16 ? 2 : 1));
{
uint8_t *w = dst_data.ptrw();
@@ -507,7 +521,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
}
}
- Ref<AudioStreamSample> sample;
+ Ref<AudioStreamWAV> sample;
sample.instantiate();
sample->set_data(dst_data);
sample->set_format(dst_format);
@@ -517,7 +531,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
sample->set_loop_end(loop_end);
sample->set_stereo(format_channels == 2);
- ResourceSaver::save(p_save_path + ".sample", sample);
+ ResourceSaver::save(sample, p_save_path + ".sample");
return OK;
}
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 99d1658405..6c12464b5a 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/importer_mesh.h"
@@ -135,6 +136,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 +149,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 +167,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 +344,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;
}
@@ -496,7 +503,7 @@ void SceneImportSettings::_update_camera() {
Transform3D xf;
xf.basis = Basis(Vector3(1, 0, 0), rot_x) * Basis(Vector3(0, 1, 0), rot_y);
xf.origin = center;
- xf.translate(0, 0, camera_size);
+ xf.translate_local(0, 0, camera_size);
camera->set_transform(xf);
}
@@ -536,12 +543,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 +588,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 +611,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 +627,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 +674,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;
@@ -1041,7 +1060,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
}
external_paths->set_title(TTR("Extract Materials to Resource Files"));
- external_paths->get_ok_button()->set_text(TTR("Extract"));
+ external_paths->set_ok_button_text(TTR("Extract"));
} break;
case ACTION_CHOOSE_MESH_SAVE_PATHS: {
for (const KeyValue<String, MeshData> &E : mesh_map) {
@@ -1094,7 +1113,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
}
external_paths->set_title(TTR("Set paths to save meshes as resource files on Reimport"));
- external_paths->get_ok_button()->set_text(TTR("Set Paths"));
+ external_paths->set_ok_button_text(TTR("Set Paths"));
} break;
case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: {
for (const KeyValue<String, AnimationData> &E : animation_map) {
@@ -1140,7 +1159,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
}
external_paths->set_title(TTR("Set paths to save animations as resource files on Reimport"));
- external_paths->get_ok_button()->set_text(TTR("Set Paths"));
+ external_paths->set_ok_button_text(TTR("Set Paths"));
} break;
}
@@ -1166,7 +1185,7 @@ void SceneImportSettings::_save_dir_confirm() {
ERR_CONTINUE(!material_map.has(id));
MaterialData &md = material_map[id];
- Error err = ResourceSaver::save(path, md.material);
+ Error err = ResourceSaver::save(md.material, path);
if (err != OK) {
EditorNode::get_singleton()->add_io_error(TTR("Can't make material external to file, write error:") + "\n\t" + path);
continue;
@@ -1329,8 +1348,8 @@ SceneImportSettings::SceneImportSettings() {
scene_import_settings_data = memnew(SceneImportSettingsData);
- get_ok_button()->set_text(TTR("Reimport"));
- get_cancel_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Reimport"));
+ set_cancel_button_text(TTR("Close"));
external_paths = memnew(ConfirmationDialog);
add_child(external_paths);
@@ -1364,8 +1383,8 @@ SceneImportSettings::SceneImportSettings() {
item_save_path = memnew(EditorFileDialog);
item_save_path->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- item_save_path->add_filter("*.tres; " + TTR("Text Resource"));
- item_save_path->add_filter("*.res; " + TTR("Binary Resource"));
+ item_save_path->add_filter("*.tres", TTR("Text Resource"));
+ item_save_path->add_filter("*.res", TTR("Binary Resource"));
add_child(item_save_path);
item_save_path->connect("file_selected", callable_mp(this, &SceneImportSettings::_save_path_changed));
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/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp
index 9d96822aef..a70f5225e9 100644
--- a/editor/import_defaults_editor.cpp
+++ b/editor/import_defaults_editor.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_autoload_settings.h"
#include "editor/editor_plugin_settings.h"
#include "editor/editor_sectioned_inspector.h"
+#include "editor/editor_settings.h"
#include "editor/localization_editor.h"
#include "editor/shader_globals_editor.h"
#include "scene/gui/center_container.h"
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 6bb71ff491..087ef48b56 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -34,6 +34,7 @@
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
class ImportDockParameters : public Object {
GDCLASS(ImportDockParameters, Object);
@@ -671,7 +672,7 @@ ImportDock::ImportDock() {
advanced->connect("pressed", callable_mp(this, &ImportDock::_advanced_options));
reimport_confirm = memnew(ConfirmationDialog);
- reimport_confirm->get_ok_button()->set_text(TTR("Save Scenes, Re-Import, and Restart"));
+ reimport_confirm->set_ok_button_text(TTR("Save Scenes, Re-Import, and Restart"));
content->add_child(reimport_confirm);
reimport_confirm->connect("confirmed", callable_mp(this, &ImportDock::_reimport_and_restart));
diff --git a/editor/import_dock.h b/editor/import_dock.h
index 7f4aa1ddb3..3098c6e815 100644
--- a/editor/import_dock.h
+++ b/editor/import_dock.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef IMPORTDOCK_H
-#define IMPORTDOCK_H
+#ifndef IMPORT_DOCK_H
+#define IMPORT_DOCK_H
#include "core/io/config_file.h"
#include "core/io/resource_importer.h"
@@ -105,4 +105,4 @@ public:
~ImportDock();
};
-#endif // IMPORTDOCK_H
+#endif // IMPORT_DOCK_H
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index ad92911810..79d94246ad 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -33,6 +33,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/plugins/script_editor_plugin.h"
InspectorDock *InspectorDock::singleton = nullptr;
@@ -64,6 +65,9 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) {
case COLLAPSE_ALL: {
_menu_collapseall();
} break;
+ case EXPAND_REVERTABLE: {
+ _menu_expand_revertable();
+ } break;
case RESOURCE_SAVE: {
_save_resource(false);
@@ -219,12 +223,12 @@ void InspectorDock::_load_resource(const String &p_type) {
load_resource_dialog->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- load_resource_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ load_resource_dialog->add_filter("*." + extensions[i], extensions[i].to_upper());
}
const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false);
for (int i = 0; i < textfile_ext.size(); i++) {
- load_resource_dialog->add_filter("*." + textfile_ext[i] + " ; " + textfile_ext[i].to_upper());
+ load_resource_dialog->add_filter("*." + textfile_ext[i], textfile_ext[i].to_upper());
}
load_resource_dialog->popup_file_dialog();
@@ -400,6 +404,10 @@ void InspectorDock::_menu_expandall() {
inspector->expand_all_folding();
}
+void InspectorDock::_menu_expand_revertable() {
+ inspector->expand_revertable();
+}
+
void InspectorDock::_warning_pressed() {
warning_dialog->popup_centered();
}
@@ -453,6 +461,9 @@ void InspectorDock::_bind_methods() {
ClassDB::bind_method("edit_resource", &InspectorDock::edit_resource);
+ ClassDB::bind_method("store_script_properties", &InspectorDock::store_script_properties);
+ ClassDB::bind_method("apply_script_properties", &InspectorDock::apply_script_properties);
+
ADD_SIGNAL(MethodInfo("request_help"));
}
@@ -515,6 +526,8 @@ void InspectorDock::update(Object *p_object) {
p->clear();
p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/expand_all", TTR("Expand All")), EXPAND_ALL);
p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All")), COLLAPSE_ALL);
+ // Calling it 'revertable' internally, because that's what the implementation is based on, but labeling it as 'non-default' because that's more user friendly, even if not 100% accurate.
+ p->add_shortcut(ED_SHORTCUT("property_editor/expand_revertable", TTR("Expand Non-Default")), EXPAND_REVERTABLE);
p->add_separator(TTR("Property Name Style"));
p->add_radio_check_item(TTR("Raw"), PROPERTY_NAME_STYLE_RAW);
@@ -565,6 +578,31 @@ EditorPropertyNameProcessor::Style InspectorDock::get_property_name_style() cons
return property_name_style;
}
+void InspectorDock::store_script_properties(Object *p_object) {
+ ERR_FAIL_NULL(p_object);
+ ScriptInstance *si = p_object->get_script_instance();
+ if (!si) {
+ return;
+ }
+ si->get_property_state(stored_properties);
+}
+
+void InspectorDock::apply_script_properties(Object *p_object) {
+ ERR_FAIL_NULL(p_object);
+ ScriptInstance *si = p_object->get_script_instance();
+ if (!si) {
+ return;
+ }
+
+ for (const Pair<StringName, Variant> &E : stored_properties) {
+ Variant current;
+ if (si->get(E.first, current) && current.get_type() == E.second.get_type()) {
+ si->set(E.first, E.second);
+ }
+ }
+ stored_properties.clear();
+}
+
InspectorDock::InspectorDock(EditorData &p_editor_data) {
singleton = this;
set_name("Inspector");
@@ -645,7 +683,7 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) {
open_docs_button->set_tooltip(TTR("Open documentation for this object."));
open_docs_button->set_shortcut(ED_SHORTCUT("property_editor/open_help", TTR("Open Documentation")));
subresource_hb->add_child(open_docs_button);
- open_docs_button->connect("pressed", callable_mp(this, &InspectorDock::_menu_option), varray(OBJECT_REQUEST_HELP));
+ open_docs_button->connect("pressed", callable_mp(this, &InspectorDock::_menu_option).bind(OBJECT_REQUEST_HELP));
new_resource_dialog = memnew(CreateDialog);
EditorNode::get_singleton()->get_gui_base()->add_child(new_resource_dialog);
diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h
index 1f2d8afb7d..e32410151f 100644
--- a/editor/inspector_dock.h
+++ b/editor/inspector_dock.h
@@ -61,6 +61,7 @@ class InspectorDock : public VBoxContainer {
COLLAPSE_ALL,
EXPAND_ALL,
+ EXPAND_REVERTABLE,
// Matches `EditorPropertyNameProcessor::Style`.
PROPERTY_NAME_STYLE_RAW,
@@ -100,6 +101,7 @@ class InspectorDock : public VBoxContainer {
Tree *unique_resources_list_tree = nullptr;
EditorPropertyNameProcessor::Style property_name_style;
+ List<Pair<StringName, Variant>> stored_properties;
void _prepare_menu();
void _menu_option(int p_option);
@@ -123,6 +125,7 @@ class InspectorDock : public VBoxContainer {
void _edit_back();
void _menu_collapseall();
void _menu_expandall();
+ void _menu_expand_revertable();
void _select_history(int p_idx);
void _prepare_history();
@@ -149,8 +152,11 @@ public:
EditorPropertyNameProcessor::Style get_property_name_style() const;
+ void store_script_properties(Object *p_object);
+ void apply_script_properties(Object *p_object);
+
InspectorDock(EditorData &p_editor_data);
~InspectorDock();
};
-#endif
+#endif // INSPECTOR_DOCK_H
diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp
index 0325f4bd5c..e8fb80eb57 100644
--- a/editor/localization_editor.cpp
+++ b/editor/localization_editor.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_translation_parser.h"
+#include "editor/filesystem_dock.h"
#include "editor/pot_generator.h"
#include "scene/gui/control.h"
@@ -379,6 +380,95 @@ void LocalizationEditor::_update_pot_file_extensions() {
}
}
+void LocalizationEditor::connect_filesystem_dock_signals(FileSystemDock *p_fs_dock) {
+ p_fs_dock->connect("files_moved", callable_mp(this, &LocalizationEditor::_filesystem_files_moved));
+ p_fs_dock->connect("file_removed", callable_mp(this, &LocalizationEditor::_filesystem_file_removed));
+}
+
+void LocalizationEditor::_filesystem_files_moved(const String &p_old_file, const String &p_new_file) {
+ // Update remaps if the moved file is a part of them.
+ Dictionary remaps;
+ bool remaps_changed = false;
+
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
+ remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
+ }
+
+ // Check for the keys.
+ if (remaps.has(p_old_file)) {
+ PackedStringArray remapped_files = remaps[p_old_file];
+ remaps.erase(p_old_file);
+ remaps[p_new_file] = remapped_files;
+ remaps_changed = true;
+ print_verbose(vformat("Changed remap key \"%s\" to \"%s\" due to a moved file.", p_old_file, p_new_file));
+ }
+
+ // Check for the Array elements of the values.
+ Array remap_keys = remaps.keys();
+ for (int i = 0; i < remap_keys.size(); i++) {
+ PackedStringArray remapped_files = remaps[remap_keys[i]];
+ bool remapped_files_updated = false;
+
+ for (int j = 0; j < remapped_files.size(); j++) {
+ int splitter_pos = remapped_files[j].rfind(":");
+ String res_path = remapped_files[j].substr(0, splitter_pos);
+
+ if (res_path == p_old_file) {
+ String locale_name = remapped_files[j].substr(splitter_pos + 1);
+ // Replace the element at that index.
+ remapped_files.insert(j, p_new_file + ":" + locale_name);
+ remapped_files.remove_at(j + 1);
+ remaps_changed = true;
+ remapped_files_updated = true;
+ print_verbose(vformat("Changed remap value \"%s\" to \"%s\" of key \"%s\" due to a moved file.", res_path + ":" + locale_name, remapped_files[j], remap_keys[i]));
+ }
+ }
+
+ if (remapped_files_updated) {
+ remaps[remap_keys[i]] = remapped_files;
+ }
+ }
+
+ if (remaps_changed) {
+ ProjectSettings::get_singleton()->set_setting("internationalization/locale/translation_remaps", remaps);
+ update_translations();
+ emit_signal("localization_changed");
+ }
+}
+
+void LocalizationEditor::_filesystem_file_removed(const String &p_file) {
+ // Check if the remaps are affected.
+ Dictionary remaps;
+
+ if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
+ remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
+ }
+
+ bool remaps_changed = remaps.has(p_file);
+
+ if (!remaps_changed) {
+ Array remap_keys = remaps.keys();
+ for (int i = 0; i < remap_keys.size() && !remaps_changed; i++) {
+ PackedStringArray remapped_files = remaps[remap_keys[i]];
+ for (int j = 0; j < remapped_files.size() && !remaps_changed; j++) {
+ int splitter_pos = remapped_files[j].rfind(":");
+ String res_path = remapped_files[j].substr(0, splitter_pos);
+ remaps_changed = p_file == res_path;
+ if (remaps_changed) {
+ print_verbose(vformat("Remap value \"%s\" of key \"%s\" has been removed from the file system.", remapped_files[j], remap_keys[i]));
+ }
+ }
+ }
+ } else {
+ print_verbose(vformat("Remap key \"%s\" has been removed from the file system.", p_file));
+ }
+
+ if (remaps_changed) {
+ update_translations();
+ emit_signal("localization_changed");
+ }
+}
+
void LocalizationEditor::update_translations() {
if (updating_translations) {
return;
@@ -432,6 +522,13 @@ void LocalizationEditor::update_translations() {
t->set_tooltip(0, keys[i]);
t->set_metadata(0, keys[i]);
t->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0, false, TTR("Remove"));
+
+ // Display that it has been removed if this is the case.
+ if (!FileAccess::exists(keys[i])) {
+ t->set_text(0, t->get_text(0) + vformat(" (%s)", TTR("Removed")));
+ t->set_tooltip(0, vformat(TTR("%s cannot be found."), t->get_tooltip(0)));
+ }
+
if (keys[i] == remap_selected) {
t->select(0);
translation_res_option_add_button->set_disabled(false);
@@ -454,6 +551,12 @@ void LocalizationEditor::update_translations() {
t2->set_editable(1, true);
t2->set_metadata(1, path);
t2->set_tooltip(1, locale);
+
+ // Display that it has been removed if this is the case.
+ if (!FileAccess::exists(path)) {
+ t2->set_text(0, t2->get_text(0) + vformat(" (%s)", TTR("Removed")));
+ t2->set_tooltip(0, vformat(TTR("%s cannot be found."), t2->get_tooltip(0)));
+ }
}
}
}
diff --git a/editor/localization_editor.h b/editor/localization_editor.h
index 4b41a90cc2..10ccdfdc13 100644
--- a/editor/localization_editor.h
+++ b/editor/localization_editor.h
@@ -36,6 +36,7 @@
#include "scene/gui/tree.h"
class EditorFileDialog;
+class FileSystemDock;
class LocalizationEditor : public VBoxContainer {
GDCLASS(LocalizationEditor, VBoxContainer);
@@ -81,6 +82,9 @@ class LocalizationEditor : public VBoxContainer {
void _pot_generate(const String &p_file);
void _update_pot_file_extensions();
+ void _filesystem_files_moved(const String &p_old_file, const String &p_new_file);
+ void _filesystem_file_removed(const String &p_file);
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -88,6 +92,7 @@ protected:
public:
void add_translation(const String &p_translation);
void update_translations();
+ void connect_filesystem_dock_signals(FileSystemDock *p_fs_dock);
LocalizationEditor();
};
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index 77e4905341..6d323572e6 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -81,8 +81,8 @@ void PluginConfigDialog::_on_confirmed() {
template_content = templates[0].content;
}
Ref<Script> script = ScriptServer::get_language(lang_idx)->make_template(template_content, class_name, "EditorPlugin");
- script->set_path(script_path);
- ResourceSaver::save(script_path, script);
+ script->set_path(script_path, true);
+ ResourceSaver::save(script);
emit_signal(SNAME("plugin_ready"), script.ptr(), active_edit->is_pressed() ? _to_absolute_plugin_path(_get_subfolder()) : "");
} else {
@@ -200,7 +200,7 @@ void PluginConfigDialog::config(const String &p_config_path) {
_on_required_text_changed("");
get_ok_button()->set_disabled(!_edit_mode);
- get_ok_button()->set_text(_edit_mode ? TTR("Update") : TTR("Create"));
+ set_ok_button_text(_edit_mode ? TTR("Update") : TTR("Create"));
}
void PluginConfigDialog::_bind_methods() {
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index ad6d8e6379..a7d7c0145a 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -35,6 +35,8 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "scene/gui/separator.h"
bool AbstractPolygon2DEditor::Vertex::operator==(const AbstractPolygon2DEditor::Vertex &p_vertex) const {
return polygon == p_vertex.polygon && vertex == p_vertex.vertex;
@@ -292,9 +294,9 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
_commit_action();
return true;
} else {
- pre_move_edit = vertices;
edited_point = PosVertex(insert.polygon, insert.vertex + 1, xform.affine_inverse().xform(insert.pos));
vertices.insert(edited_point.vertex, edited_point.pos);
+ pre_move_edit = vertices;
selected_point = Vertex(edited_point.polygon, edited_point.vertex);
edge_point = PosVertex();
@@ -565,7 +567,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));
}
}
@@ -716,24 +718,24 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(bool p_wip_destructive) {
button_create = memnew(Button);
button_create->set_flat(true);
add_child(button_create);
- button_create->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_CREATE));
+ button_create->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option).bind(MODE_CREATE));
button_create->set_toggle_mode(true);
button_edit = memnew(Button);
button_edit->set_flat(true);
add_child(button_edit);
- button_edit->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_EDIT));
+ button_edit->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option).bind(MODE_EDIT));
button_edit->set_toggle_mode(true);
button_delete = memnew(Button);
button_delete->set_flat(true);
add_child(button_delete);
- button_delete->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_DELETE));
+ button_delete->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option).bind(MODE_DELETE));
button_delete->set_toggle_mode(true);
create_resource = memnew(ConfirmationDialog);
add_child(create_resource);
- create_resource->get_ok_button()->set_text(TTR("Create"));
+ create_resource->set_ok_button_text(TTR("Create"));
}
void AbstractPolygon2DEditorPlugin::edit(Object *p_object) {
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index 2e4dcab203..32d97c65a9 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -34,6 +34,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/animation/animation_blend_tree.h"
StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const {
@@ -215,7 +216,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 +225,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 +241,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 +298,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));
}
}
@@ -314,6 +315,8 @@ void AnimationNodeBlendSpace1DEditor::_update_space() {
max_value->set_value(blend_space->get_max_space());
min_value->set_value(blend_space->get_min_space());
+ sync->set_pressed(blend_space->is_using_sync());
+
label_value->set_text(blend_space->get_value_label());
snap_value->set_value(blend_space->get_snap());
@@ -329,13 +332,15 @@ void AnimationNodeBlendSpace1DEditor::_config_changed(double) {
}
updating = true;
- undo_redo->create_action(TTR("Change BlendSpace1D Limits"));
+ undo_redo->create_action(TTR("Change BlendSpace1D Config"));
undo_redo->add_do_method(blend_space.ptr(), "set_max_space", max_value->get_value());
undo_redo->add_undo_method(blend_space.ptr(), "set_max_space", blend_space->get_max_space());
undo_redo->add_do_method(blend_space.ptr(), "set_min_space", min_value->get_value());
undo_redo->add_undo_method(blend_space.ptr(), "set_min_space", blend_space->get_min_space());
undo_redo->add_do_method(blend_space.ptr(), "set_snap", snap_value->get_value());
undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap());
+ undo_redo->add_do_method(blend_space.ptr(), "set_use_sync", sync->is_pressed());
+ undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync());
undo_redo->add_do_method(this, "_update_space");
undo_redo->add_undo_method(this, "_update_space");
undo_redo->commit_action();
@@ -608,7 +613,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
top_hb->add_child(tool_blend);
tool_blend->set_pressed(true);
tool_blend->set_tooltip(TTR("Set the blending position within the space"));
- tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(3));
+ tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(3));
tool_select = memnew(Button);
tool_select->set_flat(true);
@@ -616,7 +621,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
tool_select->set_button_group(bg);
top_hb->add_child(tool_select);
tool_select->set_tooltip(TTR("Select and move points, create points with RMB."));
- tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(0));
+ tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(0));
tool_create = memnew(Button);
tool_create->set_flat(true);
@@ -624,7 +629,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
tool_create->set_button_group(bg);
top_hb->add_child(tool_create);
tool_create->set_tooltip(TTR("Create points."));
- tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(1));
+ tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(1));
tool_erase_sep = memnew(VSeparator);
top_hb->add_child(tool_erase_sep);
@@ -650,6 +655,12 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
snap_value->set_step(0.01);
snap_value->set_max(1000);
+ top_hb->add_child(memnew(VSeparator));
+ top_hb->add_child(memnew(Label(TTR("Sync:"))));
+ sync = memnew(CheckBox);
+ top_hb->add_child(sync);
+ sync->connect("toggled", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed));
+
edit_hb = memnew(HBoxContainer);
top_hb->add_child(edit_hb);
edit_hb->add_child(memnew(VSeparator));
@@ -665,7 +676,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
open_editor = memnew(Button);
edit_hb->add_child(open_editor);
open_editor->set_text(TTR("Open Editor"));
- open_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_open_editor), varray(), CONNECT_DEFERRED);
+ open_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_open_editor), CONNECT_DEFERRED);
edit_hb->hide();
open_editor->hide();
diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h
index 2f7dee65fc..9b06f3248f 100644
--- a/editor/plugins/animation_blend_space_1d_editor.h
+++ b/editor/plugins/animation_blend_space_1d_editor.h
@@ -33,11 +33,11 @@
#include "editor/editor_plugin.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
-#include "editor/property_editor.h"
#include "scene/animation/animation_blend_space_1d.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
#include "scene/gui/popup.h"
+#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
@@ -61,6 +61,8 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
SpinBox *max_value = nullptr;
SpinBox *min_value = nullptr;
+ CheckBox *sync = nullptr;
+
HBoxContainer *edit_hb = nullptr;
SpinBox *edit_value = nullptr;
Button *open_editor = nullptr;
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index 86addde87b..dc764725dd 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/menu_button.h"
@@ -407,22 +408,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 +436,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 +450,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 +479,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 +534,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 +565,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));
}
}
@@ -595,6 +596,7 @@ void AnimationNodeBlendSpace2DEditor::_update_space() {
auto_triangles->set_pressed(blend_space->get_auto_triangles());
+ sync->set_pressed(blend_space->is_using_sync());
interpolation->select(blend_space->get_blend_mode());
max_x_value->set_value(blend_space->get_max_space().x);
@@ -620,13 +622,15 @@ void AnimationNodeBlendSpace2DEditor::_config_changed(double) {
}
updating = true;
- undo_redo->create_action(TTR("Change BlendSpace2D Limits"));
+ undo_redo->create_action(TTR("Change BlendSpace2D Config"));
undo_redo->add_do_method(blend_space.ptr(), "set_max_space", Vector2(max_x_value->get_value(), max_y_value->get_value()));
undo_redo->add_undo_method(blend_space.ptr(), "set_max_space", blend_space->get_max_space());
undo_redo->add_do_method(blend_space.ptr(), "set_min_space", Vector2(min_x_value->get_value(), min_y_value->get_value()));
undo_redo->add_undo_method(blend_space.ptr(), "set_min_space", blend_space->get_min_space());
undo_redo->add_do_method(blend_space.ptr(), "set_snap", Vector2(snap_x->get_value(), snap_y->get_value()));
undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap());
+ undo_redo->add_do_method(blend_space.ptr(), "set_use_sync", sync->is_pressed());
+ undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync());
undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected());
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode());
undo_redo->add_do_method(this, "_update_space");
@@ -829,7 +833,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
top_hb->add_child(tool_blend);
tool_blend->set_pressed(true);
tool_blend->set_tooltip(TTR("Set the blending position within the space"));
- tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(3));
+ tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(3));
tool_select = memnew(Button);
tool_select->set_flat(true);
@@ -837,7 +841,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
tool_select->set_button_group(bg);
top_hb->add_child(tool_select);
tool_select->set_tooltip(TTR("Select and move points, create points with RMB."));
- tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(0));
+ tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(0));
tool_create = memnew(Button);
tool_create->set_flat(true);
@@ -845,7 +849,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
tool_create->set_button_group(bg);
top_hb->add_child(tool_create);
tool_create->set_tooltip(TTR("Create points."));
- tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(1));
+ tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(1));
tool_triangle = memnew(Button);
tool_triangle->set_flat(true);
@@ -853,7 +857,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
tool_triangle->set_button_group(bg);
top_hb->add_child(tool_triangle);
tool_triangle->set_tooltip(TTR("Create triangles by connecting points."));
- tool_triangle->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(2));
+ tool_triangle->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(2));
tool_erase_sep = memnew(VSeparator);
top_hb->add_child(tool_erase_sep);
@@ -899,6 +903,13 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
top_hb->add_child(memnew(VSeparator));
+ top_hb->add_child(memnew(Label(TTR("Sync:"))));
+ sync = memnew(CheckBox);
+ top_hb->add_child(sync);
+ sync->connect("toggled", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_config_changed));
+
+ top_hb->add_child(memnew(VSeparator));
+
top_hb->add_child(memnew(Label(TTR("Blend:"))));
interpolation = memnew(OptionButton);
top_hb->add_child(interpolation);
@@ -923,7 +934,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
open_editor = memnew(Button);
edit_hb->add_child(open_editor);
open_editor->set_text(TTR("Open Editor"));
- open_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_open_editor), varray(), CONNECT_DEFERRED);
+ open_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_open_editor), CONNECT_DEFERRED);
edit_hb->hide();
open_editor->hide();
diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h
index db54e84254..26471df051 100644
--- a/editor/plugins/animation_blend_space_2d_editor.h
+++ b/editor/plugins/animation_blend_space_2d_editor.h
@@ -33,11 +33,11 @@
#include "editor/editor_plugin.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
-#include "editor/property_editor.h"
#include "scene/animation/animation_blend_space_2d.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
#include "scene/gui/popup.h"
+#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
@@ -55,6 +55,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
Button *snap = nullptr;
SpinBox *snap_x = nullptr;
SpinBox *snap_y = nullptr;
+ CheckBox *sync = nullptr;
OptionButton *interpolation = nullptr;
Button *auto_triangles = nullptr;
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index 5e703cf814..79be2d04b3 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/panel.h"
@@ -147,11 +148,11 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
name->set_expand_to_text_length_enabled(true);
node->add_child(name);
node->set_slot(0, false, 0, Color(), true, 0, get_theme_color(SNAME("font_color"), SNAME("Label")));
- name->connect("text_submitted", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed), varray(agnode), CONNECT_DEFERRED);
- name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out), varray(name, agnode), CONNECT_DEFERRED);
+ name->connect("text_submitted", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed).bind(agnode), CONNECT_DEFERRED);
+ name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out).bind(name, agnode), CONNECT_DEFERRED);
base = 1;
node->set_show_close_button(true);
- node->connect("close_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_request), varray(E), CONNECT_DEFERRED);
+ node->connect("close_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_request).bind(E), CONNECT_DEFERRED);
}
for (int i = 0; i < agnode->get_input_count(); i++) {
@@ -179,7 +180,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
}
}
- node->connect("dragged", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_dragged), varray(E));
+ node->connect("dragged", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_dragged).bind(E));
if (AnimationTreeEditor::get_singleton()->can_edit(agnode)) {
node->add_child(memnew(HSeparator));
@@ -187,7 +188,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
open_in_editor->set_text(TTR("Open Editor"));
open_in_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
node->add_child(open_in_editor);
- open_in_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_open_in_editor), varray(E), CONNECT_DEFERRED);
+ open_in_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_open_in_editor).bind(E), CONNECT_DEFERRED);
open_in_editor->set_h_size_flags(SIZE_SHRINK_CENTER);
}
@@ -197,7 +198,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
edit_filters->set_text(TTR("Edit Filters"));
edit_filters->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons")));
node->add_child(edit_filters);
- edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters), varray(E), CONNECT_DEFERRED);
+ edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters).bind(E), CONNECT_DEFERRED);
edit_filters->set_h_size_flags(SIZE_SHRINK_CENTER);
}
@@ -236,7 +237,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
animations[E] = pb;
node->add_child(pb);
- mb->get_popup()->connect("index_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_anim_selected), varray(options, E), CONNECT_DEFERRED);
+ mb->get_popup()->connect("index_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_anim_selected).bind(options, E), CONNECT_DEFERRED);
}
Ref<StyleBoxFlat> sb = node->get_theme_stylebox(SNAME("frame"), SNAME("GraphNode"));
@@ -961,8 +962,8 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() {
graph->add_valid_right_disconnect_type(0);
graph->add_valid_left_disconnect_type(0);
graph->set_v_size_flags(SIZE_EXPAND_FILL);
- graph->connect("connection_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_connection_request), varray(), CONNECT_DEFERRED);
- graph->connect("disconnection_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_disconnection_request), varray(), CONNECT_DEFERRED);
+ graph->connect("connection_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_connection_request), CONNECT_DEFERRED);
+ graph->connect("disconnection_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_disconnection_request), CONNECT_DEFERRED);
graph->connect("node_selected", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_selected));
graph->connect("scroll_offset_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_scroll_changed));
graph->connect("delete_nodes_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_nodes_request));
@@ -983,7 +984,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() {
add_node->set_text(TTR("Add Node..."));
graph->get_zoom_hbox()->move_child(add_node, 0);
add_node->get_popup()->connect("id_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_add_node));
- add_node->connect("about_to_popup", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu), varray(false));
+ add_node->connect("about_to_popup", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu).bind(false));
add_options.push_back(AddOption("Animation", "AnimationNodeAnimation"));
add_options.push_back(AddOption("OneShot", "AnimationNodeOneShot", 2));
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h
index b5bf91a1da..18199676b8 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.h
+++ b/editor/plugins/animation_blend_tree_editor_plugin.h
@@ -33,7 +33,6 @@
#include "editor/editor_plugin.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
-#include "editor/property_editor.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
diff --git a/editor/plugins/animation_library_editor.h b/editor/plugins/animation_library_editor.h
index bf89508321..6e214860b8 100644
--- a/editor/plugins/animation_library_editor.h
+++ b/editor/plugins/animation_library_editor.h
@@ -116,4 +116,4 @@ public:
AnimationLibraryEditor();
};
-#endif // ANIMATIONPLAYERLIBRARYEDITOR_H
+#endif // ANIMATION_LIBRARY_EDITOR_H
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index e5ca5d66e8..ebd7525bb8 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -132,10 +132,10 @@ void AnimationPlayerEditor::_notification(int p_what) {
Size2 icon_size = autoplay_img->get_size();
autoplay_reset_img.instantiate();
autoplay_reset_img->create(icon_size.x * 2, icon_size.y, false, autoplay_img->get_format());
- 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_img->blit_rect(autoplay_img, Rect2i(Point2i(), icon_size), Point2i());
+ autoplay_reset_img->blit_rect(reset_img, Rect2i(Point2i(), icon_size), Point2i(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")));
@@ -1426,19 +1426,19 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() {
// Render every past/future step with the capture shader.
RS::get_singleton()->canvas_item_set_material(onion.capture.canvas_item, onion.capture.material->get_rid());
- onion.capture.material->set_shader_param("bkg_color", GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
- onion.capture.material->set_shader_param("differences_only", onion.differences_only);
- onion.capture.material->set_shader_param("present", onion.differences_only ? RS::get_singleton()->viewport_get_texture(present_rid) : RID());
+ onion.capture.material->set_shader_uniform("bkg_color", GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
+ onion.capture.material->set_shader_uniform("differences_only", onion.differences_only);
+ onion.capture.material->set_shader_uniform("present", onion.differences_only ? RS::get_singleton()->viewport_get_texture(present_rid) : RID());
int step_off_a = onion.past ? -onion.steps : 0;
int step_off_b = onion.future ? onion.steps : 0;
int cidx = 0;
- onion.capture.material->set_shader_param("dir_color", onion.force_white_modulate ? Color(1, 1, 1) : Color(EDITOR_GET("editors/animation/onion_layers_past_color")));
+ onion.capture.material->set_shader_uniform("dir_color", onion.force_white_modulate ? Color(1, 1, 1) : Color(EDITOR_GET("editors/animation/onion_layers_past_color")));
for (int step_off = step_off_a; step_off <= step_off_b; step_off++) {
if (step_off == 0) {
// Skip present step and switch to the color of future.
if (!onion.force_white_modulate) {
- onion.capture.material->set_shader_param("dir_color", EDITOR_GET("editors/animation/onion_layers_future_color"));
+ onion.capture.material->set_shader_uniform("dir_color", EDITOR_GET("editors/animation/onion_layers_future_color"));
}
continue;
}
@@ -1633,7 +1633,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
onion_toggle->set_flat(true);
onion_toggle->set_toggle_mode(true);
onion_toggle->set_tooltip(TTR("Enable Onion Skinning"));
- onion_toggle->connect("pressed", callable_mp(this, &AnimationPlayerEditor::_onion_skinning_menu), varray(ONION_SKINNING_ENABLE));
+ onion_toggle->connect("pressed", callable_mp(this, &AnimationPlayerEditor::_onion_skinning_menu).bind(ONION_SKINNING_ENABLE));
hb->add_child(onion_toggle);
onion_skinning = memnew(MenuButton);
@@ -1688,7 +1688,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
name_dialog->register_text_enter(name);
error_dialog = memnew(ConfirmationDialog);
- error_dialog->get_ok_button()->set_text(TTR("Close"));
+ error_dialog->set_ok_button_text(TTR("Close"));
error_dialog->set_title(TTR("Error!"));
add_child(error_dialog);
@@ -1696,7 +1696,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
blend_editor.dialog = memnew(AcceptDialog);
add_child(blend_editor.dialog);
- blend_editor.dialog->get_ok_button()->set_text(TTR("Close"));
+ blend_editor.dialog->set_ok_button_text(TTR("Close"));
blend_editor.dialog->set_hide_on_ok(true);
VBoxContainer *blend_vb = memnew(VBoxContainer);
blend_editor.dialog->add_child(blend_vb);
@@ -1720,7 +1720,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
animation->connect("item_selected", callable_mp(this, &AnimationPlayerEditor::_animation_selected));
- frame->connect("value_changed", callable_mp(this, &AnimationPlayerEditor::_seek_value_changed), make_binds(true, false));
+ frame->connect("value_changed", callable_mp(this, &AnimationPlayerEditor::_seek_value_changed).bind(true, false));
scale->connect("text_submitted", callable_mp(this, &AnimationPlayerEditor::_scale_changed));
last_active = false;
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 00cc5a6ca0..473450b292 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/menu_button.h"
@@ -1018,7 +1019,7 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) {
anim->set_animation(animations_to_add[p_index]);
- String base_name = animations_to_add[p_index];
+ String base_name = animations_to_add[p_index].validate_node_name();
int base = 1;
String name = base_name;
while (state_machine->has_node(name)) {
@@ -1224,7 +1225,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 +1380,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;
@@ -1899,7 +1900,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
tool_select->set_button_group(bg);
tool_select->set_pressed(true);
tool_select->set_tooltip(TTR("Select and move nodes.\nRMB: Add node at position clicked.\nShift+LMB+Drag: Connects the selected node with another node or creates a new node if you select an area without nodes."));
- tool_select->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED);
+ tool_select->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED);
tool_create = memnew(Button);
tool_create->set_flat(true);
@@ -1907,7 +1908,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
tool_create->set_toggle_mode(true);
tool_create->set_button_group(bg);
tool_create->set_tooltip(TTR("Create new nodes."));
- tool_create->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED);
+ tool_create->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED);
tool_connect = memnew(Button);
tool_connect->set_flat(true);
@@ -1915,7 +1916,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
tool_connect->set_toggle_mode(true);
tool_connect->set_button_group(bg);
tool_connect->set_tooltip(TTR("Connect nodes."));
- tool_connect->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED);
+ tool_connect->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED);
tool_erase_hb = memnew(HBoxContainer);
top_hb->add_child(tool_erase_hb);
@@ -1938,7 +1939,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
tool_erase = memnew(Button);
tool_erase->set_flat(true);
tool_erase->set_tooltip(TTR("Remove selected node or transition."));
- tool_erase->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected), varray(false));
+ tool_erase->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected).bind(false));
tool_erase->set_disabled(true);
tool_erase_hb->add_child(tool_erase);
@@ -1969,7 +1970,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
state_machine_play_pos = memnew(Control);
state_machine_draw->add_child(state_machine_play_pos);
state_machine_play_pos->set_mouse_filter(MOUSE_FILTER_PASS); //pass all to parent
- state_machine_play_pos->set_anchors_and_offsets_preset(PRESET_WIDE);
+ state_machine_play_pos->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
state_machine_play_pos->connect("draw", callable_mp(this, &AnimationNodeStateMachineEditor::_state_machine_pos_draw));
v_scroll = memnew(VScrollBar);
@@ -2022,7 +2023,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
add_child(name_edit_popup);
name_edit = memnew(LineEdit);
name_edit_popup->add_child(name_edit);
- name_edit->set_anchors_and_offsets_preset(PRESET_WIDE);
+ name_edit->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
name_edit->connect("text_submitted", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited));
name_edit->connect("focus_exited", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited_focus_out));
diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h
index ea16abd64c..165940e639 100644
--- a/editor/plugins/animation_state_machine_editor.h
+++ b/editor/plugins/animation_state_machine_editor.h
@@ -33,7 +33,6 @@
#include "editor/editor_plugin.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
-#include "editor/property_editor.h"
#include "scene/animation/animation_node_state_machine.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index 7ea6906d72..bce4c9de8e 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -86,7 +86,7 @@ void AnimationTreeEditor::_update_path() {
b->set_button_group(group);
b->set_pressed(true);
b->set_focus_mode(FOCUS_NONE);
- b->connect("pressed", callable_mp(this, &AnimationTreeEditor::_path_button_pressed), varray(-1));
+ b->connect("pressed", callable_mp(this, &AnimationTreeEditor::_path_button_pressed).bind(-1));
path_hb->add_child(b);
for (int i = 0; i < button_path.size(); i++) {
b = memnew(Button);
@@ -96,7 +96,7 @@ void AnimationTreeEditor::_update_path() {
path_hb->add_child(b);
b->set_pressed(true);
b->set_focus_mode(FOCUS_NONE);
- b->connect("pressed", callable_mp(this, &AnimationTreeEditor::_path_button_pressed), varray(i));
+ b->connect("pressed", callable_mp(this, &AnimationTreeEditor::_path_button_pressed).bind(i));
}
}
diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h
index ab4ef5a001..a33d97f62f 100644
--- a/editor/plugins/animation_tree_editor_plugin.h
+++ b/editor/plugins/animation_tree_editor_plugin.h
@@ -32,7 +32,6 @@
#define ANIMATION_TREE_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "editor/property_editor.h"
#include "scene/animation/animation_tree.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 249b3a6d6a..8ee162d085 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -32,6 +32,7 @@
#include "core/input/input.h"
#include "core/io/json.h"
+#include "core/io/stream_peer_ssl.h"
#include "core/os/keyboard.h"
#include "core/version.h"
#include "editor/editor_file_dialog.h"
@@ -160,18 +161,13 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const
Ref<Image> overlay = previews->get_theme_icon(SNAME("PlayOverlay"), SNAME("EditorIcons"))->get_image();
Ref<Image> thumbnail = p_image->get_image();
thumbnail = thumbnail->duplicate();
- Point2 overlay_pos = Point2((thumbnail->get_width() - overlay->get_width()) / 2, (thumbnail->get_height() - overlay->get_height()) / 2);
+ Point2i overlay_pos = Point2i((thumbnail->get_width() - overlay->get_width()) / 2, (thumbnail->get_height() - overlay->get_height()) / 2);
// 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 {
@@ -257,7 +253,7 @@ void EditorAssetLibraryItemDescription::add_preview(int p_id, bool p_video, cons
preview.button = memnew(Button);
preview.button->set_icon(previews->get_theme_icon(SNAME("ThumbnailWait"), SNAME("EditorIcons")));
preview.button->set_toggle_mode(true);
- preview.button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDescription::_preview_click), varray(p_id));
+ preview.button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDescription::_preview_click).bind(p_id));
preview_hb->add_child(preview.button);
if (!p_video) {
preview.image = previews->get_theme_icon(SNAME("ThumbnailWait"), SNAME("EditorIcons"));
@@ -290,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);
@@ -308,8 +307,8 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
preview_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
previews->add_child(preview_hb);
- get_ok_button()->set_text(TTR("Download"));
- get_cancel_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Download"));
+ set_cancel_button_text(TTR("Close"));
}
///////////////////////////////////////////////////////////////////////////////////
@@ -620,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);
@@ -782,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;
@@ -886,7 +887,7 @@ void EditorAssetLibrary::_request_image(ObjectID p_for, String p_image_url, Imag
iq.queue_id = ++last_queue_id;
iq.active = false;
- iq.request->connect("request_completed", callable_mp(this, &EditorAssetLibrary::_image_request_completed), varray(iq.queue_id));
+ iq.request->connect("request_completed", callable_mp(this, &EditorAssetLibrary::_image_request_completed).bind(iq.queue_id));
image_queue[iq.queue_id] = iq;
@@ -1005,7 +1006,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int
Button *first = memnew(Button);
first->set_text(TTR("First", "Pagination"));
if (p_page != 0) {
- first->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(0));
+ first->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(0));
} else {
first->set_disabled(true);
first->set_focus_mode(Control::FOCUS_NONE);
@@ -1015,7 +1016,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int
Button *prev = memnew(Button);
prev->set_text(TTR("Previous", "Pagination"));
if (p_page > 0) {
- prev->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(p_page - 1));
+ prev->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(p_page - 1));
} else {
prev->set_disabled(true);
prev->set_focus_mode(Control::FOCUS_NONE);
@@ -1036,7 +1037,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int
Button *current = memnew(Button);
// Add padding to make page number buttons easier to click.
current->set_text(vformat(" %d ", i + 1));
- current->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(i));
+ current->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(i));
hbc->add_child(current);
}
@@ -1045,7 +1046,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int
Button *next = memnew(Button);
next->set_text(TTR("Next", "Pagination"));
if (p_page < p_page_count - 1) {
- next->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(p_page + 1));
+ next->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(p_page + 1));
} else {
next->set_disabled(true);
next->set_focus_mode(Control::FOCUS_NONE);
@@ -1056,7 +1057,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int
Button *last = memnew(Button);
last->set_text(TTR("Last", "Pagination"));
if (p_page != p_page_count - 1) {
- last->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(p_page_count - 1));
+ last->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search).bind(p_page_count - 1));
} else {
last->set_disabled(true);
last->set_focus_mode(Control::FOCUS_NONE);
@@ -1209,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);
@@ -1292,14 +1293,14 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
EditorAssetLibraryItemDownload *download_item = _get_asset_in_progress(description->get_asset_id());
if (download_item) {
if (download_item->can_install()) {
- description->get_ok_button()->set_text(TTR("Install"));
+ description->set_ok_button_text(TTR("Install"));
description->get_ok_button()->set_disabled(false);
} else {
- description->get_ok_button()->set_text(TTR("Downloading..."));
+ description->set_ok_button_text(TTR("Downloading..."));
description->get_ok_button()->set_disabled(true);
}
} else {
- description->get_ok_button()->set_text(TTR("Download"));
+ description->set_ok_button_text(TTR("Download"));
description->get_ok_button()->set_disabled(false);
}
@@ -1375,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() {
@@ -1538,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);
@@ -1578,7 +1584,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
asset_open = memnew(EditorFileDialog);
asset_open->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- asset_open->add_filter("*.zip ; " + TTR("Assets ZIP File"));
+ asset_open->add_filter("*.zip", TTR("Assets ZIP File"));
asset_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
add_child(asset_open);
asset_open->connect("file_selected", callable_mp(this, &EditorAssetLibrary::_asset_file_selected));
@@ -1588,6 +1594,16 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
///////
+bool AssetLibraryEditorPlugin::is_available() {
+#ifdef JAVASCRIPT_ENABLED
+ // Asset Library can't work on Web editor for now as most assets are sourced
+ // directly from GitHub which does not set CORS.
+ return false;
+#else
+ return StreamPeerSSL::is_available();
+#endif
+}
+
void AssetLibraryEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
addon_library->show();
@@ -1600,7 +1616,7 @@ AssetLibraryEditorPlugin::AssetLibraryEditorPlugin() {
addon_library = memnew(EditorAssetLibrary);
addon_library->set_v_size_flags(Control::SIZE_EXPAND_FILL);
EditorNode::get_singleton()->get_main_control()->add_child(addon_library);
- addon_library->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ addon_library->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
addon_library->hide();
}
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index e09700b646..070d25e29f 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);
};
@@ -322,6 +323,8 @@ class AssetLibraryEditorPlugin : public EditorPlugin {
EditorAssetLibrary *addon_library = nullptr;
public:
+ static bool is_available();
+
virtual String get_name() const override { return "AssetLib"; }
bool has_main_screen() const override { return true; }
virtual void edit(Object *p_object) override {}
@@ -335,4 +338,4 @@ public:
~AssetLibraryEditorPlugin();
};
-#endif // EDITORASSETLIBRARY_H
+#endif // ASSET_LIBRARY_EDITOR_PLUGIN_H
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
deleted file mode 100644
index a60e49ca9d..0000000000
--- a/editor/plugins/audio_stream_editor_plugin.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/*************************************************************************/
-/* audio_stream_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 "audio_stream_editor_plugin.h"
-
-#include "core/config/project_settings.h"
-#include "core/io/resource_loader.h"
-#include "core/os/keyboard.h"
-#include "editor/audio_stream_preview.h"
-#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
-#include "editor/editor_settings.h"
-
-void AudioStreamEditor::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_READY: {
- AudioStreamPreviewGenerator::get_singleton()->connect("preview_updated", callable_mp(this, &AudioStreamEditor::_preview_changed));
- } break;
-
- case NOTIFICATION_THEME_CHANGED:
- case NOTIFICATION_ENTER_TREE: {
- _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
- _stop_button->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
- _preview->set_color(get_theme_color(SNAME("dark_color_2"), SNAME("Editor")));
- set_color(get_theme_color(SNAME("dark_color_1"), SNAME("Editor")));
-
- _indicator->update();
- _preview->update();
- } break;
-
- case NOTIFICATION_PROCESS: {
- _current = _player->get_playback_position();
- _indicator->update();
- } break;
-
- case NOTIFICATION_VISIBILITY_CHANGED: {
- if (!is_visible_in_tree()) {
- _stop();
- }
- } break;
- }
-}
-
-void AudioStreamEditor::_draw_preview() {
- Rect2 rect = _preview->get_rect();
- Size2 size = get_size();
-
- Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream);
- float preview_len = preview->get_length();
-
- Vector<Vector2> lines;
- lines.resize(size.width * 2);
-
- for (int i = 0; i < size.width; i++) {
- float ofs = i * preview_len / size.width;
- float ofs_n = (i + 1) * preview_len / size.width;
- float max = preview->get_max(ofs, ofs_n) * 0.5 + 0.5;
- float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5;
-
- int idx = i;
- lines.write[idx * 2 + 0] = Vector2(i + 1, rect.position.y + min * rect.size.y);
- lines.write[idx * 2 + 1] = Vector2(i + 1, rect.position.y + max * rect.size.y);
- }
-
- Vector<Color> color;
- color.push_back(get_theme_color(SNAME("contrast_color_2"), SNAME("Editor")));
-
- RS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, color);
-}
-
-void AudioStreamEditor::_preview_changed(ObjectID p_which) {
- if (stream.is_valid() && stream->get_instance_id() == p_which) {
- _preview->update();
- }
-}
-
-void AudioStreamEditor::_audio_changed() {
- if (!is_visible()) {
- return;
- }
- update();
-}
-
-void AudioStreamEditor::_play() {
- if (_player->is_playing()) {
- // '_pausing' variable indicates that we want to pause the audio player, not stop it. See '_on_finished()'.
- _pausing = true;
- _player->stop();
- _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
- set_process(false);
- } else {
- _player->play(_current);
- _play_button->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons")));
- set_process(true);
- }
-}
-
-void AudioStreamEditor::_stop() {
- _player->stop();
- _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
- _current = 0;
- _indicator->update();
- set_process(false);
-}
-
-void AudioStreamEditor::_on_finished() {
- _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
- if (!_pausing) {
- _current = 0;
- _indicator->update();
- } else {
- _pausing = false;
- }
- set_process(false);
-}
-
-void AudioStreamEditor::_draw_indicator() {
- if (!stream.is_valid()) {
- return;
- }
-
- Rect2 rect = _preview->get_rect();
- float len = stream->get_length();
- float ofs_x = _current / len * rect.size.width;
- const Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
- _indicator->draw_line(Point2(ofs_x, 0), Point2(ofs_x, rect.size.height), color, Math::round(2 * EDSCALE));
- _indicator->draw_texture(
- get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons")),
- Point2(ofs_x - get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons"))->get_width() * 0.5, 0),
- color);
-
- _current_label->set_text(String::num(_current, 2).pad_decimals(2) + " /");
-}
-
-void AudioStreamEditor::_on_input_indicator(Ref<InputEvent> p_event) {
- const Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
- if (mb->is_pressed()) {
- _seek_to(mb->get_position().x);
- }
- _dragging = mb->is_pressed();
- }
-
- const Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid()) {
- if (_dragging) {
- _seek_to(mm->get_position().x);
- }
- }
-}
-
-void AudioStreamEditor::_seek_to(real_t p_x) {
- _current = p_x / _preview->get_rect().size.x * stream->get_length();
- _current = CLAMP(_current, 0, stream->get_length());
- _player->seek(_current);
- _indicator->update();
-}
-
-void AudioStreamEditor::edit(Ref<AudioStream> p_stream) {
- if (!stream.is_null()) {
- stream->disconnect("changed", callable_mp(this, &AudioStreamEditor::_audio_changed));
- }
-
- stream = p_stream;
- _player->set_stream(stream);
- _current = 0;
- String text = String::num(stream->get_length(), 2).pad_decimals(2) + "s";
- _duration_label->set_text(text);
-
- if (!stream.is_null()) {
- stream->connect("changed", callable_mp(this, &AudioStreamEditor::_audio_changed));
- update();
- } else {
- hide();
- }
-}
-
-void AudioStreamEditor::_bind_methods() {
-}
-
-AudioStreamEditor::AudioStreamEditor() {
- set_custom_minimum_size(Size2(1, 100) * EDSCALE);
-
- _player = memnew(AudioStreamPlayer);
- _player->connect("finished", callable_mp(this, &AudioStreamEditor::_on_finished));
- add_child(_player);
-
- VBoxContainer *vbox = memnew(VBoxContainer);
- vbox->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_MINSIZE, 0);
- add_child(vbox);
-
- _preview = memnew(ColorRect);
- _preview->set_v_size_flags(SIZE_EXPAND_FILL);
- _preview->connect("draw", callable_mp(this, &AudioStreamEditor::_draw_preview));
- vbox->add_child(_preview);
-
- _indicator = memnew(Control);
- _indicator->set_anchors_and_offsets_preset(PRESET_WIDE);
- _indicator->connect("draw", callable_mp(this, &AudioStreamEditor::_draw_indicator));
- _indicator->connect("gui_input", callable_mp(this, &AudioStreamEditor::_on_input_indicator));
- _preview->add_child(_indicator);
-
- HBoxContainer *hbox = memnew(HBoxContainer);
- hbox->add_theme_constant_override("separation", 0);
- vbox->add_child(hbox);
-
- _play_button = memnew(Button);
- _play_button->set_flat(true);
- hbox->add_child(_play_button);
- _play_button->set_focus_mode(Control::FOCUS_NONE);
- _play_button->connect("pressed", callable_mp(this, &AudioStreamEditor::_play));
- _play_button->set_shortcut(ED_SHORTCUT("inspector/audio_preview_play_pause", TTR("Audio Preview Play/Pause"), Key::SPACE));
-
- _stop_button = memnew(Button);
- _stop_button->set_flat(true);
- hbox->add_child(_stop_button);
- _stop_button->set_focus_mode(Control::FOCUS_NONE);
- _stop_button->connect("pressed", callable_mp(this, &AudioStreamEditor::_stop));
-
- _current_label = memnew(Label);
- _current_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
- _current_label->set_h_size_flags(SIZE_EXPAND_FILL);
- _current_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
- _current_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
- _current_label->set_modulate(Color(1, 1, 1, 0.5));
- hbox->add_child(_current_label);
-
- _duration_label = memnew(Label);
- _duration_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
- _duration_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
- hbox->add_child(_duration_label);
-}
-
-void AudioStreamEditorPlugin::edit(Object *p_object) {
- AudioStream *s = Object::cast_to<AudioStream>(p_object);
- if (!s) {
- return;
- }
-
- audio_editor->edit(Ref<AudioStream>(s));
-}
-
-bool AudioStreamEditorPlugin::handles(Object *p_object) const {
- return p_object->is_class("AudioStream");
-}
-
-void AudioStreamEditorPlugin::make_visible(bool p_visible) {
- audio_editor->set_visible(p_visible);
-}
-
-AudioStreamEditorPlugin::AudioStreamEditorPlugin() {
- audio_editor = memnew(AudioStreamEditor);
- add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM, audio_editor);
- audio_editor->hide();
-}
-
-AudioStreamEditorPlugin::~AudioStreamEditorPlugin() {
-}
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/bit_map_editor_plugin.h b/editor/plugins/bit_map_editor_plugin.h
index c883e5542f..b045f8c751 100644
--- a/editor/plugins/bit_map_editor_plugin.h
+++ b/editor/plugins/bit_map_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BIT_MAP_PREVIEW_EDITOR_PLUGIN_H
-#define BIT_MAP_PREVIEW_EDITOR_PLUGIN_H
+#ifndef BIT_MAP_EDITOR_PLUGIN_H
+#define BIT_MAP_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/resources/bit_map.h"
@@ -61,4 +61,4 @@ public:
BitMapEditorPlugin();
};
-#endif // BIT_MAP_PREVIEW_EDITOR_PLUGIN_H
+#endif // BIT_MAP_EDITOR_PLUGIN_H
diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp
new file mode 100644
index 0000000000..70775c1ee2
--- /dev/null
+++ b/editor/plugins/bone_map_editor_plugin.cpp
@@ -0,0 +1,499 @@
+/*************************************************************************/
+/* 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/post_import_plugin_skeleton_rest_fixer.h"
+#include "editor/import/post_import_plugin_skeleton_track_organizer.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_MISSING: {
+ circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/missing"));
+ } break;
+ case BONE_MAP_STATE_ERROR: {
+ circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/error"));
+ } break;
+ default: {
+ } break;
+ }
+}
+
+bool BoneMapperButton::is_require() const {
+ return require;
+}
+
+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_require, bool p_selected) {
+ profile_bone_name = p_profile_bone_name;
+ require = p_require;
+ selected = p_selected;
+}
+
+BoneMapperButton::~BoneMapperButton() {
+}
+
+void BoneMapperItem::create_editor() {
+ skeleton_bone_selector = memnew(EditorPropertyTextEnum);
+ skeleton_bone_selector->setup(skeleton_bone_names, false, true);
+ 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), profile->is_require(i), current_bone_idx == i));
+ mb->connect("pressed", callable_mp(this, &BoneMapper::set_current_bone_idx).bind(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;
+ 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 pbn = bone_mapper_buttons[i]->get_profile_bone_name();
+ StringName sbn = bone_map->get_skeleton_bone_name(pbn);
+ int bone_idx = skeleton->find_bone(sbn);
+ if (bone_idx >= 0) {
+ if (bone_map->get_skeleton_bone_name_count(sbn) == 1) {
+ Ref<SkeletonProfile> prof = bone_map->get_profile();
+
+ StringName parent_name = prof->get_bone_parent(prof->find_bone(pbn));
+ Vector<int> prof_parent_bones;
+ while (parent_name != StringName()) {
+ prof_parent_bones.push_back(skeleton->find_bone(bone_map->get_skeleton_bone_name(parent_name)));
+ if (prof->find_bone(parent_name) == -1) {
+ break;
+ }
+ parent_name = prof->get_bone_parent(prof->find_bone(parent_name));
+ }
+
+ int parent_id = skeleton->get_bone_parent(bone_idx);
+ Vector<int> skel_parent_bones;
+ while (parent_id >= 0) {
+ skel_parent_bones.push_back(parent_id);
+ parent_id = skeleton->get_bone_parent(parent_id);
+ }
+
+ bool is_broken = false;
+ for (int j = 0; j < prof_parent_bones.size(); j++) {
+ if (prof_parent_bones[j] != -1 && !skel_parent_bones.has(prof_parent_bones[j])) {
+ is_broken = true;
+ }
+ }
+
+ if (is_broken) {
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_ERROR);
+ } else {
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_SET);
+ }
+ } else {
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_ERROR);
+ }
+ } else {
+ if (bone_mapper_buttons[i]->is_require()) {
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_MISSING);
+ } 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() {
+ skeleton = nullptr;
+ // Hackey... but it may be the easist way to get a selected object from "ImporterScene".
+ SceneImportSettings *si = SceneImportSettings::get_singleton();
+ if (!si) {
+ return;
+ }
+ if (!si->is_visible()) {
+ 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: {
+ if (bone_mapper) {
+ remove_child(bone_mapper);
+ bone_mapper->queue_delete();
+ }
+ skeleton = nullptr;
+ } break;
+ }
+}
+
+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/unset", Color(0.3, 0.3, 0.3));
+ EDITOR_DEF("editors/bone_mapper/handle_colors/set", Color(0.1, 0.6, 0.25));
+ EDITOR_DEF("editors/bone_mapper/handle_colors/missing", Color(0.8, 0.2, 0.8));
+ EDITOR_DEF("editors/bone_mapper/handle_colors/error", Color(0.8, 0.2, 0.2));
+
+ Ref<EditorInspectorPluginBoneMap> inspector_plugin;
+ inspector_plugin.instantiate();
+ add_inspector_plugin(inspector_plugin);
+
+ Ref<PostImportPluginSkeletonTrackOrganizer> post_import_plugin_track_organizer;
+ post_import_plugin_track_organizer.instantiate();
+ add_scene_post_import_plugin(post_import_plugin_track_organizer);
+
+ Ref<PostImportPluginSkeletonRenamer> post_import_plugin_renamer;
+ post_import_plugin_renamer.instantiate();
+ add_scene_post_import_plugin(post_import_plugin_renamer);
+
+ Ref<PostImportPluginSkeletonRestFixer> post_import_plugin_rest_fixer;
+ post_import_plugin_rest_fixer.instantiate();
+ add_scene_post_import_plugin(post_import_plugin_rest_fixer);
+}
diff --git a/editor/plugins/bone_map_editor_plugin.h b/editor/plugins/bone_map_editor_plugin.h
new file mode 100644
index 0000000000..339547ea10
--- /dev/null
+++ b/editor/plugins/bone_map_editor_plugin.h
@@ -0,0 +1,180 @@
+/*************************************************************************/
+/* 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_PLUGIN_H
+#define BONE_MAP_EDITOR_PLUGIN_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_MISSING,
+ BONE_MAP_STATE_ERROR
+ };
+
+private:
+ StringName profile_bone_name;
+ bool selected = false;
+ bool require = 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);
+
+ bool is_require() const;
+
+ BoneMapperButton(const StringName p_profile_bone_name, bool p_require, 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_PLUGIN_H
diff --git a/editor/plugins/camera_3d_editor_plugin.h b/editor/plugins/camera_3d_editor_plugin.h
index a8164f9b85..a969b31976 100644
--- a/editor/plugins/camera_3d_editor_plugin.h
+++ b/editor/plugins/camera_3d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CAMERA_EDITOR_PLUGIN_H
-#define CAMERA_EDITOR_PLUGIN_H
+#ifndef CAMERA_3D_EDITOR_PLUGIN_H
+#define CAMERA_3D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/3d/camera_3d.h"
@@ -68,4 +68,4 @@ public:
~Camera3DEditorPlugin();
};
-#endif // CAMERA_EDITOR_PLUGIN_H
+#endif // CAMERA_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index dea4aaded7..ac85eb5e1b 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -50,8 +50,10 @@
#include "scene/2d/skeleton_2d.h"
#include "scene/2d/sprite_2d.h"
#include "scene/2d/touch_screen_button.h"
+#include "scene/gui/flow_container.h"
#include "scene/gui/grid_container.h"
#include "scene/gui/nine_patch_rect.h"
+#include "scene/gui/separator.h"
#include "scene/gui/subviewport_container.h"
#include "scene/gui/view_panner.h"
#include "scene/main/canvas_layer.h"
@@ -813,9 +815,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()) {
@@ -1193,7 +1203,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
}
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -1361,14 +1371,14 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
drag_selection[0]->get_name(),
drag_selection[0]->_edit_get_pivot().x,
drag_selection[0]->_edit_get_pivot().y));
- drag_type = DRAG_NONE;
+ _reset_drag();
return true;
}
// Cancel a drag
if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection);
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -1444,14 +1454,14 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
_insert_animation_keys(false, true, false, true);
}
- drag_type = DRAG_NONE;
+ _reset_drag();
return true;
}
// Cancel a drag
if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection);
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -1606,14 +1616,14 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
_commit_canvas_item_state(
drag_selection,
vformat(TTR("Move CanvasItem \"%s\" Anchor"), drag_selection[0]->get_name()));
- drag_type = DRAG_NONE;
+ _reset_drag();
return true;
}
// Cancel a drag
if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection);
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -1812,7 +1822,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -1822,7 +1832,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
_restore_canvas_item_state(drag_selection);
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -1951,7 +1961,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
_insert_animation_keys(false, false, true, true);
}
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -1959,7 +1969,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
// Cancel a drag
if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) {
_restore_canvas_item_state(drag_selection);
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -2084,7 +2094,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -2094,7 +2104,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
_restore_canvas_item_state(drag_selection, true);
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -2201,7 +2211,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
drag_selection[0]->_edit_get_position().y),
true);
}
- drag_type = DRAG_NONE;
+ _reset_drag();
}
viewport->update();
return true;
@@ -2273,7 +2283,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
}
selection_menu_additive_selection = b->is_shift_pressed();
- selection_menu->set_position(get_screen_position() + b->get_position());
+ selection_menu->set_position(viewport->get_screen_transform().xform(b->get_position()));
selection_menu->reset_size();
selection_menu->popup();
return true;
@@ -2352,7 +2362,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
if (drag_type == DRAG_QUEUED) {
if (b.is_valid() && !b->is_pressed()) {
- drag_type = DRAG_NONE;
+ _reset_drag();
return true;
}
if (m.is_valid()) {
@@ -2403,14 +2413,14 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
}
}
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
if (b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::RIGHT) {
// Cancel box selection
- drag_type = DRAG_NONE;
+ _reset_drag();
viewport->update();
return true;
}
@@ -2669,7 +2679,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 +2751,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));
}
}
@@ -2782,10 +2794,10 @@ void CanvasItemEditor::_draw_rulers() {
if (grid_snap_active || _is_grid_visible()) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (snap_relative && selection.size() > 0) {
- ruler_transform.translate(_get_encompassing_rect_from_list(selection).position);
+ ruler_transform.translate_local(_get_encompassing_rect_from_list(selection).position);
ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
} else {
- ruler_transform.translate(grid_offset);
+ ruler_transform.translate_local(grid_offset);
ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
}
while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) {
@@ -2962,13 +2974,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 +3000,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 +3029,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 +3065,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 +3625,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 +3646,67 @@ void CanvasItemEditor::_draw_hover() {
}
}
+void CanvasItemEditor::_draw_transform_message() {
+ if (drag_type == DRAG_NONE || 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 +3818,7 @@ void CanvasItemEditor::_draw_viewport() {
_draw_smart_snapping();
_draw_focus();
_draw_hover();
+ _draw_transform_message();
}
void CanvasItemEditor::update_viewport() {
@@ -3779,7 +3863,7 @@ void CanvasItemEditor::_update_editor_settings() {
key_auto_insert_button->add_theme_color_override("icon_pressed_color", key_auto_color.lerp(Color(1, 0, 0), 0.55));
animation_menu->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
- context_menu_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles")));
+ context_menu_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles")));
panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/2d_editor_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning")));
pan_speed = int(EditorSettings::get_singleton()->get("editors/panning/2d_editor_pan_speed"));
@@ -3899,7 +3983,7 @@ void CanvasItemEditor::_notification(int p_what) {
void CanvasItemEditor::_selection_changed() {
if (!selected_from_canvas) {
- drag_type = DRAG_NONE;
+ _reset_drag();
}
selected_from_canvas = false;
}
@@ -3907,7 +3991,7 @@ void CanvasItemEditor::_selection_changed() {
void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
Array selection = editor_selection->get_selected_nodes();
if (selection.size() != 1 || Object::cast_to<Node>(selection[0]) != p_canvas_item) {
- drag_type = DRAG_NONE;
+ _reset_drag();
// Clear the selection
editor_selection->clear(); //_clear_canvas_items();
@@ -4153,13 +4237,13 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
Control *ctrl = Object::cast_to<Control>(canvas_item);
if (key_pos) {
- te->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), p_on_existing);
+ te->insert_node_value_key(ctrl, "position", ctrl->get_position(), p_on_existing);
}
if (key_rot) {
- te->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation(), p_on_existing);
+ te->insert_node_value_key(ctrl, "rotation", ctrl->get_rotation(), p_on_existing);
}
if (key_scale) {
- te->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), p_on_existing);
+ te->insert_node_value_key(ctrl, "size", ctrl->get_size(), p_on_existing);
}
}
}
@@ -4619,6 +4703,11 @@ void CanvasItemEditor::_focus_selection(int p_op) {
}
}
+void CanvasItemEditor::_reset_drag() {
+ drag_type = DRAG_NONE;
+ drag_selection.clear();
+}
+
void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_override_camera_button", "game_running"), &CanvasItemEditor::_update_override_camera_button);
ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data);
@@ -4839,11 +4928,11 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) {
ERR_FAIL_COND(!p_control);
- hbc_context_menu->add_child(p_control);
+ context_menu_hbox->add_child(p_control);
}
void CanvasItemEditor::remove_control_from_menu_panel(Control *p_control) {
- hbc_context_menu->remove_child(p_control);
+ context_menu_hbox->remove_child(p_control);
}
void CanvasItemEditor::add_control_to_left_panel(Control *p_control) {
@@ -4889,12 +4978,17 @@ CanvasItemEditor::CanvasItemEditor() {
SceneTreeDock::get_singleton()->connect("node_created", callable_mp(this, &CanvasItemEditor::_node_created));
SceneTreeDock::get_singleton()->connect("add_node_used", callable_mp(this, &CanvasItemEditor::_reset_create_position));
- EditorNode::get_singleton()->call_deferred(SNAME("connect"), "play_pressed", Callable(this, "_update_override_camera_button"), make_binds(true));
- EditorNode::get_singleton()->call_deferred(SNAME("connect"), "stop_pressed", Callable(this, "_update_override_camera_button"), make_binds(false));
+ EditorNode::get_singleton()->call_deferred(SNAME("connect"), "play_pressed", Callable(this, "_update_override_camera_button").bind(true));
+ EditorNode::get_singleton()->call_deferred(SNAME("connect"), "stop_pressed", Callable(this, "_update_override_camera_button").bind(false));
+
+ // A fluid container for all toolbars.
+ HFlowContainer *main_flow = memnew(HFlowContainer);
+ add_child(main_flow);
- hb = memnew(HBoxContainer);
- add_child(hb);
- hb->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ // Main toolbars.
+ HBoxContainer *main_menu_hbox = memnew(HBoxContainer);
+ main_menu_hbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+ main_flow->add_child(main_menu_hbox);
bottom_split = memnew(VSplitContainer);
add_child(bottom_split);
@@ -4919,7 +5013,7 @@ CanvasItemEditor::CanvasItemEditor() {
SubViewportContainer *scene_tree = memnew(SubViewportContainer);
viewport_scrollable->add_child(scene_tree);
scene_tree->set_stretch(true);
- scene_tree->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ scene_tree->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
scene_tree->add_child(EditorNode::get_singleton()->get_scene_root());
controls_vb = memnew(VBoxContainer);
@@ -4949,7 +5043,7 @@ CanvasItemEditor::CanvasItemEditor() {
viewport = memnew(CanvasItemEditorViewport(this));
viewport_scrollable->add_child(viewport);
viewport->set_mouse_filter(MOUSE_FILTER_PASS);
- viewport->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ viewport->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
viewport->set_clip_contents(true);
viewport->set_focus_mode(FOCUS_ALL);
viewport->connect("draw", callable_mp(this, &CanvasItemEditor::_draw_viewport));
@@ -4972,87 +5066,87 @@ CanvasItemEditor::CanvasItemEditor() {
// This prevents the first button's hover/pressed effect from "touching" the panel's border,
// which looks ugly.
Control *margin_left = memnew(Control);
- hb->add_child(margin_left);
+ main_menu_hbox->add_child(margin_left);
margin_left->set_custom_minimum_size(Size2(2, 0) * EDSCALE);
select_button = memnew(Button);
select_button->set_flat(true);
- hb->add_child(select_button);
+ main_menu_hbox->add_child(select_button);
select_button->set_toggle_mode(true);
- select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SELECT));
+ select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_SELECT));
select_button->set_pressed(true);
select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), Key::Q));
select_button->set_shortcut_context(this);
select_button->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("RMB: Add node at position clicked."));
- hb->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
move_button = memnew(Button);
move_button->set_flat(true);
- hb->add_child(move_button);
+ main_menu_hbox->add_child(move_button);
move_button->set_toggle_mode(true);
- move_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_MOVE));
+ move_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_MOVE));
move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), Key::W));
move_button->set_shortcut_context(this);
move_button->set_tooltip(TTR("Move Mode"));
rotate_button = memnew(Button);
rotate_button->set_flat(true);
- hb->add_child(rotate_button);
+ main_menu_hbox->add_child(rotate_button);
rotate_button->set_toggle_mode(true);
- rotate_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_ROTATE));
+ rotate_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_ROTATE));
rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), Key::E));
rotate_button->set_shortcut_context(this);
rotate_button->set_tooltip(TTR("Rotate Mode"));
scale_button = memnew(Button);
scale_button->set_flat(true);
- hb->add_child(scale_button);
+ main_menu_hbox->add_child(scale_button);
scale_button->set_toggle_mode(true);
- scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SCALE));
+ scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_SCALE));
scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), Key::S));
scale_button->set_shortcut_context(this);
scale_button->set_tooltip(TTR("Shift: Scale proportionally."));
- hb->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
list_select_button = memnew(Button);
list_select_button->set_flat(true);
- hb->add_child(list_select_button);
+ main_menu_hbox->add_child(list_select_button);
list_select_button->set_toggle_mode(true);
- list_select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_LIST_SELECT));
+ list_select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_LIST_SELECT));
list_select_button->set_tooltip(TTR("Show list of selectable nodes at position clicked."));
pivot_button = memnew(Button);
pivot_button->set_flat(true);
- hb->add_child(pivot_button);
+ main_menu_hbox->add_child(pivot_button);
pivot_button->set_toggle_mode(true);
- pivot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_EDIT_PIVOT));
+ pivot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_EDIT_PIVOT));
pivot_button->set_tooltip(TTR("Click to change object's rotation pivot."));
pan_button = memnew(Button);
pan_button->set_flat(true);
- hb->add_child(pan_button);
+ main_menu_hbox->add_child(pan_button);
pan_button->set_toggle_mode(true);
- pan_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_PAN));
+ pan_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_PAN));
pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), Key::G));
pan_button->set_shortcut_context(this);
pan_button->set_tooltip(TTR("You can also use Pan View shortcut (Space by default) to pan in any mode."));
ruler_button = memnew(Button);
ruler_button->set_flat(true);
- hb->add_child(ruler_button);
+ main_menu_hbox->add_child(ruler_button);
ruler_button->set_toggle_mode(true);
- ruler_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_RULER));
+ ruler_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_RULER));
ruler_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/ruler_mode", TTR("Ruler Mode"), Key::R));
ruler_button->set_shortcut_context(this);
ruler_button->set_tooltip(TTR("Ruler Mode"));
- hb->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
smart_snap_button = memnew(Button);
smart_snap_button->set_flat(true);
- hb->add_child(smart_snap_button);
+ main_menu_hbox->add_child(smart_snap_button);
smart_snap_button->set_toggle_mode(true);
smart_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_smart_snap));
smart_snap_button->set_tooltip(TTR("Toggle smart snapping."));
@@ -5061,7 +5155,7 @@ CanvasItemEditor::CanvasItemEditor() {
grid_snap_button = memnew(Button);
grid_snap_button->set_flat(true);
- hb->add_child(grid_snap_button);
+ main_menu_hbox->add_child(grid_snap_button);
grid_snap_button->set_toggle_mode(true);
grid_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_grid_snap));
grid_snap_button->set_tooltip(TTR("Toggle grid snapping."));
@@ -5070,7 +5164,7 @@ CanvasItemEditor::CanvasItemEditor() {
snap_config_menu = memnew(MenuButton);
snap_config_menu->set_shortcut_context(this);
- hb->add_child(snap_config_menu);
+ main_menu_hbox->add_child(snap_config_menu);
snap_config_menu->set_h_size_flags(SIZE_SHRINK_END);
snap_config_menu->set_tooltip(TTR("Snapping Options"));
snap_config_menu->set_switch_on_hover(true);
@@ -5099,46 +5193,46 @@ CanvasItemEditor::CanvasItemEditor() {
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to Other Nodes")), SNAP_USE_OTHER_NODES);
smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTR("Snap to Guides")), SNAP_USE_GUIDES);
- hb->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
lock_button = memnew(Button);
lock_button->set_flat(true);
- hb->add_child(lock_button);
+ main_menu_hbox->add_child(lock_button);
- lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(LOCK_SELECTED));
+ lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(LOCK_SELECTED));
lock_button->set_tooltip(TTR("Lock selected node, preventing selection and movement."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L));
unlock_button = memnew(Button);
unlock_button->set_flat(true);
- hb->add_child(unlock_button);
- unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNLOCK_SELECTED));
+ main_menu_hbox->add_child(unlock_button);
+ unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(UNLOCK_SELECTED));
unlock_button->set_tooltip(TTR("Unlock selected node, allowing selection and movement."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L));
group_button = memnew(Button);
group_button->set_flat(true);
- hb->add_child(group_button);
- group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(GROUP_SELECTED));
- group_button->set_tooltip(TTR("Makes sure the object's children are not selectable."));
+ main_menu_hbox->add_child(group_button);
+ group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(GROUP_SELECTED));
+ group_button->set_tooltip(TTR("Make selected node's children not selectable."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G));
ungroup_button = memnew(Button);
ungroup_button->set_flat(true);
- hb->add_child(ungroup_button);
- ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNGROUP_SELECTED));
- ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected."));
+ main_menu_hbox->add_child(ungroup_button);
+ ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(UNGROUP_SELECTED));
+ ungroup_button->set_tooltip(TTR("Make selected node's children selectable."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G));
- hb->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
skeleton_menu = memnew(MenuButton);
skeleton_menu->set_shortcut_context(this);
- hb->add_child(skeleton_menu);
+ main_menu_hbox->add_child(skeleton_menu);
skeleton_menu->set_tooltip(TTR("Skeleton Options"));
skeleton_menu->set_switch_on_hover(true);
@@ -5149,24 +5243,24 @@ CanvasItemEditor::CanvasItemEditor() {
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bone2D Node(s) from Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::B), SKELETON_MAKE_BONES);
p->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback));
- hb->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
override_camera_button = memnew(Button);
override_camera_button->set_flat(true);
- hb->add_child(override_camera_button);
+ main_menu_hbox->add_child(override_camera_button);
override_camera_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_override_camera));
override_camera_button->set_toggle_mode(true);
override_camera_button->set_disabled(true);
_update_override_camera_button(false);
- hb->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
view_menu = memnew(MenuButton);
// TRANSLATORS: Noun, name of the 2D/3D View menus.
view_menu->set_text(TTR("View"));
view_menu->set_switch_on_hover(true);
view_menu->set_shortcut_context(this);
- hb->add_child(view_menu);
+ main_menu_hbox->add_child(view_menu);
view_menu->get_popup()->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback));
p = view_menu->get_popup();
@@ -5199,16 +5293,17 @@ CanvasItemEditor::CanvasItemEditor() {
p->add_separator();
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::P), PREVIEW_CANVAS_SCALE);
- hb->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
- context_menu_container = memnew(PanelContainer);
- hbc_context_menu = memnew(HBoxContainer);
- context_menu_container->add_child(hbc_context_menu);
- hb->add_child(context_menu_container);
+ // Contextual toolbars.
+ context_menu_panel = memnew(PanelContainer);
+ context_menu_hbox = memnew(HBoxContainer);
+ context_menu_panel->add_child(context_menu_hbox);
+ main_flow->add_child(context_menu_panel);
// Animation controls.
animation_hb = memnew(HBoxContainer);
- hbc_context_menu->add_child(animation_hb);
+ context_menu_hbox->add_child(animation_hb);
animation_hb->add_child(memnew(VSeparator));
animation_hb->hide();
@@ -5217,7 +5312,7 @@ CanvasItemEditor::CanvasItemEditor() {
key_loc_button->set_toggle_mode(true);
key_loc_button->set_pressed(true);
key_loc_button->set_focus_mode(FOCUS_NONE);
- key_loc_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_POS));
+ key_loc_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_POS));
key_loc_button->set_tooltip(TTR("Translation mask for inserting keys."));
animation_hb->add_child(key_loc_button);
@@ -5226,7 +5321,7 @@ CanvasItemEditor::CanvasItemEditor() {
key_rot_button->set_toggle_mode(true);
key_rot_button->set_pressed(true);
key_rot_button->set_focus_mode(FOCUS_NONE);
- key_rot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_ROT));
+ key_rot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_ROT));
key_rot_button->set_tooltip(TTR("Rotation mask for inserting keys."));
animation_hb->add_child(key_rot_button);
@@ -5234,14 +5329,14 @@ CanvasItemEditor::CanvasItemEditor() {
key_scale_button->set_flat(true);
key_scale_button->set_toggle_mode(true);
key_scale_button->set_focus_mode(FOCUS_NONE);
- key_scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_SCALE));
+ key_scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_SCALE));
key_scale_button->set_tooltip(TTR("Scale mask for inserting keys."));
animation_hb->add_child(key_scale_button);
key_insert_button = memnew(Button);
key_insert_button->set_flat(true);
key_insert_button->set_focus_mode(FOCUS_NONE);
- key_insert_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_KEY));
+ key_insert_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_KEY));
key_insert_button->set_tooltip(TTR("Insert keys (based on mask)."));
key_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key", TTR("Insert Key"), Key::INSERT));
key_insert_button->set_shortcut_context(this);
@@ -5282,7 +5377,7 @@ CanvasItemEditor::CanvasItemEditor() {
add_child(selection_menu);
selection_menu->set_min_size(Vector2(100, 0));
selection_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_selection_result_pressed));
- selection_menu->connect("popup_hide", callable_mp(this, &CanvasItemEditor::_selection_menu_hide));
+ selection_menu->connect("popup_hide", callable_mp(this, &CanvasItemEditor::_selection_menu_hide), CONNECT_DEFERRED);
add_node_menu = memnew(PopupMenu);
add_child(add_node_menu);
@@ -5338,7 +5433,7 @@ CanvasItemEditorPlugin::CanvasItemEditorPlugin() {
canvas_item_editor = memnew(CanvasItemEditor);
canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
EditorNode::get_singleton()->get_main_control()->add_child(canvas_item_editor);
- canvas_item_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ canvas_item_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
canvas_item_editor->hide();
}
@@ -5821,7 +5916,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(CanvasItemEditor *p_canvas_it
CheckBox *check = memnew(CheckBox);
btn_group->add_child(check);
check->set_text(texture_node_types[i]);
- check->connect("button_down", callable_mp(this, &CanvasItemEditorViewport::_on_select_type), varray(check));
+ check->connect("button_down", callable_mp(this, &CanvasItemEditorViewport::_on_select_type).bind(check));
check->set_button_group(button_group);
}
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index c20a054800..04fd819dec 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -188,11 +188,10 @@ private:
HScrollBar *h_scroll = nullptr;
VScrollBar *v_scroll = nullptr;
- HBoxContainer *hb = nullptr;
// Used for secondary menu items which are displayed depending on the currently selected node
// (such as MeshInstance's "Mesh" menu).
- PanelContainer *context_menu_container = nullptr;
- HBoxContainer *hbc_context_menu = nullptr;
+ PanelContainer *context_menu_panel = nullptr;
+ HBoxContainer *context_menu_hbox = nullptr;
Transform2D transform;
GridVisibility grid_visibility = GRID_VISIBILITY_SHOW_WHEN_SNAPPING;
@@ -215,8 +214,8 @@ private:
int primary_grid_steps = 8;
int grid_step_multiplier = 0;
- real_t snap_rotation_step = 0.0;
- real_t snap_rotation_offset = Math::deg2rad(15.0);
+ real_t snap_rotation_step = Math::deg2rad(15.0);
+ real_t snap_rotation_offset = 0.0;
real_t snap_scale_step = 0.1f;
bool smart_snap_active = false;
bool grid_snap_active = false;
@@ -347,6 +346,7 @@ private:
bool is_hovering_v_guide = false;
bool updating_value_dialog = false;
+ Transform2D original_transform;
Point2 box_selecting_to;
@@ -433,6 +433,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();
@@ -453,8 +454,8 @@ private:
void _update_cursor();
void _selection_changed();
-
void _focus_selection(int p_op);
+ void _reset_drag();
SnapTarget snap_target[2];
Transform2D snap_transform;
@@ -501,8 +502,6 @@ protected:
static void _bind_methods();
- HBoxContainer *get_panel_hb() { return hb; }
-
static CanvasItemEditor *singleton;
public:
@@ -631,4 +630,4 @@ public:
~CanvasItemEditorViewport();
};
-#endif //CANVAS_ITEM_EDITOR_PLUGIN_H
+#endif // CANVAS_ITEM_EDITOR_PLUGIN_H
diff --git a/editor/plugins/ray_cast_2d_editor_plugin.cpp b/editor/plugins/cast_2d_editor_plugin.cpp
index 6f247a37ef..18c38e7ab8 100644
--- a/editor/plugins/ray_cast_2d_editor_plugin.cpp
+++ b/editor/plugins/cast_2d_editor_plugin.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* ray_cast_2d_editor_plugin.cpp */
+/* cast_2d_editor_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,30 +28,32 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "ray_cast_2d_editor_plugin.h"
+#include "cast_2d_editor_plugin.h"
#include "canvas_item_editor_plugin.h"
#include "editor/editor_node.h"
+#include "scene/2d/ray_cast_2d.h"
+#include "scene/2d/shape_cast_2d.h"
-void RayCast2DEditor::_notification(int p_what) {
+void Cast2DEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- get_tree()->connect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed));
+ get_tree()->connect("node_removed", callable_mp(this, &Cast2DEditor::_node_removed));
} break;
case NOTIFICATION_EXIT_TREE: {
- get_tree()->disconnect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed));
+ get_tree()->disconnect("node_removed", callable_mp(this, &Cast2DEditor::_node_removed));
} break;
}
}
-void RayCast2DEditor::_node_removed(Node *p_node) {
+void Cast2DEditor::_node_removed(Node *p_node) {
if (p_node == node) {
node = nullptr;
}
}
-bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
+bool Cast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
if (!node || !node->is_visible_in_tree()) {
return false;
}
@@ -60,10 +62,12 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
+ Vector2 target_position = node->get("target_position");
+
if (mb->is_pressed()) {
- if (xform.xform(node->get_target_position()).distance_to(mb->get_position()) < 8) {
+ if (xform.xform(target_position).distance_to(mb->get_position()) < 8) {
pressed = true;
- original_target_position = node->get_target_position();
+ original_target_position = target_position;
return true;
} else {
@@ -73,9 +77,9 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
}
} else if (pressed) {
undo_redo->create_action(TTR("Set target_position"));
- undo_redo->add_do_method(node, "set_target_position", node->get_target_position());
+ undo_redo->add_do_property(node, "target_position", target_position);
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
- undo_redo->add_undo_method(node, "set_target_position", original_target_position);
+ undo_redo->add_undo_property(node, "target_position", original_target_position);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
undo_redo->commit_action();
@@ -90,7 +94,7 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
Vector2 point = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()));
point = node->get_global_transform().affine_inverse().xform(point);
- node->set_target_position(point);
+ node->set("target_position", point);
canvas_item_editor->update_viewport();
node->notify_property_list_changed();
@@ -100,7 +104,7 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
return false;
}
-void RayCast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
+void Cast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
if (!node || !node->is_visible_in_tree()) {
return;
}
@@ -108,16 +112,16 @@ void RayCast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
- p_overlay->draw_texture(handle, gt.xform(node->get_target_position()) - handle->get_size() / 2);
+ p_overlay->draw_texture(handle, gt.xform((Vector2)node->get("target_position")) - handle->get_size() / 2);
}
-void RayCast2DEditor::edit(Node *p_node) {
+void Cast2DEditor::edit(Node2D *p_node) {
if (!canvas_item_editor) {
canvas_item_editor = CanvasItemEditor::get_singleton();
}
- if (p_node) {
- node = Object::cast_to<RayCast2D>(p_node);
+ if (Object::cast_to<RayCast2D>(p_node) || Object::cast_to<ShapeCast2D>(p_node)) {
+ node = p_node;
} else {
node = nullptr;
}
@@ -125,27 +129,27 @@ void RayCast2DEditor::edit(Node *p_node) {
canvas_item_editor->update_viewport();
}
-RayCast2DEditor::RayCast2DEditor() {
+Cast2DEditor::Cast2DEditor() {
undo_redo = EditorNode::get_singleton()->get_undo_redo();
}
///////////////////////
-void RayCast2DEditorPlugin::edit(Object *p_object) {
- ray_cast_2d_editor->edit(Object::cast_to<RayCast2D>(p_object));
+void Cast2DEditorPlugin::edit(Object *p_object) {
+ cast_2d_editor->edit(Object::cast_to<Node2D>(p_object));
}
-bool RayCast2DEditorPlugin::handles(Object *p_object) const {
- return Object::cast_to<RayCast2D>(p_object) != nullptr;
+bool Cast2DEditorPlugin::handles(Object *p_object) const {
+ return Object::cast_to<RayCast2D>(p_object) != nullptr || Object::cast_to<ShapeCast2D>(p_object) != nullptr;
}
-void RayCast2DEditorPlugin::make_visible(bool p_visible) {
+void Cast2DEditorPlugin::make_visible(bool p_visible) {
if (!p_visible) {
edit(nullptr);
}
}
-RayCast2DEditorPlugin::RayCast2DEditorPlugin() {
- ray_cast_2d_editor = memnew(RayCast2DEditor);
- EditorNode::get_singleton()->get_gui_base()->add_child(ray_cast_2d_editor);
+Cast2DEditorPlugin::Cast2DEditorPlugin() {
+ cast_2d_editor = memnew(Cast2DEditor);
+ EditorNode::get_singleton()->get_gui_base()->add_child(cast_2d_editor);
}
diff --git a/editor/plugins/ray_cast_2d_editor_plugin.h b/editor/plugins/cast_2d_editor_plugin.h
index 74628da0e4..d9c0cc4a06 100644
--- a/editor/plugins/ray_cast_2d_editor_plugin.h
+++ b/editor/plugins/cast_2d_editor_plugin.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* ray_cast_2d_editor_plugin.h */
+/* cast_2d_editor_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,20 +28,20 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RAY_CAST_2D_EDITOR_PLUGIN_H
-#define RAY_CAST_2D_EDITOR_PLUGIN_H
+#ifndef CAST_2D_EDITOR_PLUGIN_H
+#define CAST_2D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "scene/2d/ray_cast_2d.h"
+#include "scene/2d/node_2d.h"
class CanvasItemEditor;
-class RayCast2DEditor : public Control {
- GDCLASS(RayCast2DEditor, Control);
+class Cast2DEditor : public Control {
+ GDCLASS(Cast2DEditor, Control);
UndoRedo *undo_redo = nullptr;
CanvasItemEditor *canvas_item_editor = nullptr;
- RayCast2D *node;
+ Node2D *node;
bool pressed = false;
Point2 original_target_position;
@@ -53,27 +53,27 @@ protected:
public:
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
void forward_canvas_draw_over_viewport(Control *p_overlay);
- void edit(Node *p_node);
+ void edit(Node2D *p_node);
- RayCast2DEditor();
+ Cast2DEditor();
};
-class RayCast2DEditorPlugin : public EditorPlugin {
- GDCLASS(RayCast2DEditorPlugin, EditorPlugin);
+class Cast2DEditorPlugin : public EditorPlugin {
+ GDCLASS(Cast2DEditorPlugin, EditorPlugin);
- RayCast2DEditor *ray_cast_2d_editor = nullptr;
+ Cast2DEditor *cast_2d_editor = nullptr;
public:
- virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return ray_cast_2d_editor->forward_canvas_gui_input(p_event); }
- virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { ray_cast_2d_editor->forward_canvas_draw_over_viewport(p_overlay); }
+ virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return cast_2d_editor->forward_canvas_gui_input(p_event); }
+ virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { cast_2d_editor->forward_canvas_draw_over_viewport(p_overlay); }
- virtual String get_name() const override { return "RayCast2D"; }
+ virtual String get_name() const override { return "Cast2D"; }
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 visible) override;
- RayCast2DEditorPlugin();
+ Cast2DEditorPlugin();
};
-#endif // RAY_CAST_2D_EDITOR_PLUGIN_H
+#endif // CAST_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
index da9e9f339f..f7de05ddd1 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.h
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -112,4 +112,4 @@ public:
~CollisionShape2DEditorPlugin();
};
-#endif //COLLISION_SHAPE_2D_EDITOR_PLUGIN_H
+#endif // COLLISION_SHAPE_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp
index 3adaf8f601..2756e45cf4 100644
--- a/editor/plugins/control_editor_plugin.cpp
+++ b/editor/plugins/control_editor_plugin.cpp
@@ -31,7 +31,9 @@
#include "control_editor_plugin.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "scene/gui/separator.h"
void ControlPositioningWarning::_update_warning() {
if (!control_node) {
@@ -173,7 +175,7 @@ void EditorPropertyAnchorsPreset::setup(const Vector<String> &p_options) {
Vector<String> split_after;
split_after.append("Custom");
- split_after.append("PresetWide");
+ split_after.append("PresetFullRect");
split_after.append("PresetBottomLeft");
split_after.append("PresetCenter");
@@ -181,24 +183,18 @@ void EditorPropertyAnchorsPreset::setup(const Vector<String> &p_options) {
Vector<String> text_split = p_options[i].split(":");
int64_t current_val = text_split[1].to_int();
- String humanized_name = text_split[0];
- if (humanized_name.begins_with("Preset")) {
- if (humanized_name == "PresetWide") {
- humanized_name = "Full Rect";
- } else {
- humanized_name = humanized_name.trim_prefix("Preset");
- humanized_name = humanized_name.capitalize();
- }
-
- String icon_name = text_split[0].trim_prefix("Preset");
- icon_name = "ControlAlign" + icon_name;
+ String option_name = text_split[0];
+ if (option_name.begins_with("Preset")) {
+ String preset_name = option_name.trim_prefix("Preset");
+ String humanized_name = preset_name.capitalize();
+ String icon_name = "ControlAlign" + preset_name;
options->add_icon_item(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(icon_name, "EditorIcons"), humanized_name);
} else {
- options->add_item(humanized_name);
+ options->add_item(option_name);
}
options->set_item_metadata(j, current_val);
- if (split_after.has(text_split[0])) {
+ if (split_after.has(option_name)) {
options->add_separator();
j++;
}
@@ -479,7 +475,7 @@ void ControlEditorToolbar::_set_anchors_and_offsets_preset(Control::LayoutPreset
case PRESET_BOTTOM_WIDE:
case PRESET_VCENTER_WIDE:
case PRESET_HCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
undo_redo->add_do_method(control, "set_offsets_preset", p_preset, Control::PRESET_MODE_MINSIZE);
break;
}
@@ -689,8 +685,8 @@ void ControlEditorToolbar::_popup_callback(int p_op) {
case ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE: {
_set_anchors_and_offsets_preset(PRESET_HCENTER_WIDE);
} break;
- case ANCHORS_AND_OFFSETS_PRESET_WIDE: {
- _set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ case ANCHORS_AND_OFFSETS_PRESET_FULL_RECT: {
+ _set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
} break;
case ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO: {
_set_anchors_and_offsets_to_keep_ratio();
@@ -741,8 +737,8 @@ void ControlEditorToolbar::_popup_callback(int p_op) {
case ANCHORS_PRESET_HCENTER_WIDE: {
_set_anchors_preset(PRESET_HCENTER_WIDE);
} break;
- case ANCHORS_PRESET_WIDE: {
- _set_anchors_preset(Control::PRESET_WIDE);
+ case ANCHORS_PRESET_FULL_RECT: {
+ _set_anchors_preset(Control::PRESET_FULL_RECT);
} break;
case CONTAINERS_H_PRESET_FILL: {
@@ -840,7 +836,7 @@ void ControlEditorToolbar::_notification(int p_what) {
p->add_icon_item(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")), TTR("VCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE);
p->add_icon_item(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")), TTR("HCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE);
p->add_separator();
- p->add_icon_item(get_theme_icon(SNAME("ControlAlignWide"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_AND_OFFSETS_PRESET_WIDE);
+ p->add_icon_item(get_theme_icon(SNAME("ControlAlignFullRect"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_AND_OFFSETS_PRESET_FULL_RECT);
p->add_icon_item(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")), TTR("Keep Current Ratio"), ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO);
p->set_item_tooltip(19, TTR("Adjust anchors and offsets to match the current rect size."));
@@ -867,7 +863,7 @@ void ControlEditorToolbar::_notification(int p_what) {
anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignVCenterWide"), SNAME("EditorIcons")), TTR("VCenter Wide"), ANCHORS_PRESET_VCENTER_WIDE);
anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignHCenterWide"), SNAME("EditorIcons")), TTR("HCenter Wide"), ANCHORS_PRESET_HCENTER_WIDE);
anchors_popup->add_separator();
- anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignWide"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_PRESET_WIDE);
+ anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignFullRect"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_PRESET_FULL_RECT);
anchor_mode_button->set_icon(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")));
diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h
index 96451f7dcf..11389bc095 100644
--- a/editor/plugins/control_editor_plugin.h
+++ b/editor/plugins/control_editor_plugin.h
@@ -147,7 +147,7 @@ class ControlEditorToolbar : public HBoxContainer {
ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE,
ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE,
ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE,
- ANCHORS_AND_OFFSETS_PRESET_WIDE,
+ ANCHORS_AND_OFFSETS_PRESET_FULL_RECT,
ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO,
@@ -166,7 +166,7 @@ class ControlEditorToolbar : public HBoxContainer {
ANCHORS_PRESET_BOTTOM_WIDE,
ANCHORS_PRESET_VCENTER_WIDE,
ANCHORS_PRESET_HCENTER_WIDE,
- ANCHORS_PRESET_WIDE,
+ ANCHORS_PRESET_FULL_RECT,
// Offsets Presets are not currently in use.
OFFSETS_PRESET_TOP_LEFT,
@@ -184,7 +184,7 @@ class ControlEditorToolbar : public HBoxContainer {
OFFSETS_PRESET_BOTTOM_WIDE,
OFFSETS_PRESET_VCENTER_WIDE,
OFFSETS_PRESET_HCENTER_WIDE,
- OFFSETS_PRESET_WIDE,
+ OFFSETS_PRESET_FULL_RECT,
CONTAINERS_H_PRESET_FILL,
CONTAINERS_H_PRESET_FILL_EXPAND,
@@ -247,4 +247,4 @@ public:
ControlEditorPlugin();
};
-#endif //CONTROL_EDITOR_PLUGIN_H
+#endif // CONTROL_EDITOR_PLUGIN_H
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
index 79025041d3..a7c3c32120 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
@@ -257,7 +257,7 @@ CPUParticles2DEditorPlugin::CPUParticles2DEditorPlugin() {
List<String> ext;
ImageLoader::get_recognized_extensions(&ext);
for (const String &E : ext) {
- file->add_filter("*." + E + "; " + E.to_upper());
+ file->add_filter("*." + E, E.to_upper());
}
file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
toolbar->add_child(file);
diff --git a/editor/plugins/cpu_particles_3d_editor_plugin.h b/editor/plugins/cpu_particles_3d_editor_plugin.h
index 70f2da4b2d..f38349985c 100644
--- a/editor/plugins/cpu_particles_3d_editor_plugin.h
+++ b/editor/plugins/cpu_particles_3d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CPU_PARTICLES_EDITOR_PLUGIN_H
-#define CPU_PARTICLES_EDITOR_PLUGIN_H
+#ifndef CPU_PARTICLES_3D_EDITOR_PLUGIN_H
+#define CPU_PARTICLES_3D_EDITOR_PLUGIN_H
#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
#include "scene/3d/cpu_particles_3d.h"
@@ -78,4 +78,4 @@ public:
~CPUParticles3DEditorPlugin();
};
-#endif // CPU_PARTICLES_EDITOR_PLUGIN_H
+#endif // CPU_PARTICLES_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 6d1a86765a..8aeab684e3 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -36,6 +36,7 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
CurveEditor::CurveEditor() {
_selected_point = -1;
@@ -542,11 +543,11 @@ void CurveEditor::update_view_transform() {
const Vector2 scale = view_size / world_rect.size;
Transform2D world_trans;
- world_trans.translate(-world_rect.position - Vector2(0, world_rect.size.y));
+ world_trans.translate_local(-world_rect.position - Vector2(0, world_rect.size.y));
world_trans.scale(Vector2(scale.x, -scale.y));
Transform2D view_trans;
- view_trans.translate(view_margin);
+ view_trans.translate_local(view_margin);
_world_to_view = view_trans * world_trans;
}
@@ -751,12 +752,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 +842,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/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp
index 5c90d70982..c572b5b7fe 100644
--- a/editor/plugins/debugger_editor_plugin.cpp
+++ b/editor/plugins/debugger_editor_plugin.cpp
@@ -35,6 +35,7 @@
#include "editor/debugger/editor_debugger_server.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/fileserver/editor_file_server.h"
#include "editor/plugins/script_editor_plugin.h"
#include "scene/gui/menu_button.h"
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index bb0cfcba25..0196214ceb 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>();
@@ -323,7 +307,7 @@ Ref<Texture2D> EditorMaterialPreviewPlugin::generate(const Ref<Resource> &p_from
if (material->get_shader_mode() == Shader::MODE_SPATIAL) {
RS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid());
- RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT);
+ RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Object::CONNECT_ONESHOT);
preview_done.wait();
@@ -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() {
@@ -622,7 +599,7 @@ Ref<Texture2D> EditorAudioStreamPreviewPlugin::generate(const Ref<Resource> &p_f
uint8_t *imgdata = img.ptrw();
uint8_t *imgw = imgdata;
- Ref<AudioStreamPlayback> playback = stream->instance_playback();
+ Ref<AudioStreamPlayback> playback = stream->instantiate_playback();
ERR_FAIL_COND_V(playback.is_null(), Ref<Texture2D>());
real_t len_s = stream->get_length();
@@ -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() {
@@ -727,7 +702,7 @@ Ref<Texture2D> EditorMeshPreviewPlugin::generate(const Ref<Resource> &p_from, co
xform.origin.z -= rot_aabb.size.z * 2;
RS::get_singleton()->instance_set_transform(mesh_instance, xform);
- RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT);
+ RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_generate_frame_started), Object::CONNECT_ONESHOT);
preview_done.wait();
@@ -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,20 +801,18 @@ 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);
+ RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Object::CONNECT_ONESHOT);
preview_done.wait();
@@ -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/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h
index f548683b70..163cfe79f9 100644
--- a/editor/plugins/editor_preview_plugins.h
+++ b/editor/plugins/editor_preview_plugins.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITORPREVIEWPLUGINS_H
-#define EDITORPREVIEWPLUGINS_H
+#ifndef EDITOR_PREVIEW_PLUGINS_H
+#define EDITOR_PREVIEW_PLUGINS_H
#include "core/templates/safe_refcount.h"
#include "editor/editor_resource_preview.h"
@@ -193,4 +193,5 @@ public:
EditorGradientPreviewPlugin();
};
-#endif // EDITORPREVIEWPLUGINS_H
+
+#endif // EDITOR_PREVIEW_PLUGINS_H
diff --git a/editor/plugins/editor_resource_conversion_plugin.cpp b/editor/plugins/editor_resource_conversion_plugin.cpp
new file mode 100644
index 0000000000..91394dbac7
--- /dev/null
+++ b/editor/plugins/editor_resource_conversion_plugin.cpp
@@ -0,0 +1,64 @@
+/*************************************************************************/
+/* editor_resource_conversion_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 "editor_resource_conversion_plugin.h"
+
+void EditorResourceConversionPlugin::_bind_methods() {
+ GDVIRTUAL_BIND(_converts_to);
+ GDVIRTUAL_BIND(_handles, "resource");
+ GDVIRTUAL_BIND(_convert, "resource");
+}
+
+String EditorResourceConversionPlugin::converts_to() const {
+ String ret;
+ if (GDVIRTUAL_CALL(_converts_to, ret)) {
+ return ret;
+ }
+
+ return "";
+}
+
+bool EditorResourceConversionPlugin::handles(const Ref<Resource> &p_resource) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_handles, p_resource, ret)) {
+ return ret;
+ }
+
+ return false;
+}
+
+Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) const {
+ Ref<Resource> ret;
+ if (GDVIRTUAL_CALL(_convert, p_resource, ret)) {
+ return ret;
+ }
+
+ return Ref<Resource>();
+}
diff --git a/editor/plugins/editor_resource_conversion_plugin.h b/editor/plugins/editor_resource_conversion_plugin.h
new file mode 100644
index 0000000000..34b0837383
--- /dev/null
+++ b/editor/plugins/editor_resource_conversion_plugin.h
@@ -0,0 +1,54 @@
+/*************************************************************************/
+/* editor_resource_conversion_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 EDITOR_RESOURCE_CONVERSION_PLUGIN_H
+#define EDITOR_RESOURCE_CONVERSION_PLUGIN_H
+
+#include "core/io/resource.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+
+class EditorResourceConversionPlugin : public RefCounted {
+ GDCLASS(EditorResourceConversionPlugin, RefCounted);
+
+protected:
+ static void _bind_methods();
+
+ GDVIRTUAL0RC(String, _converts_to)
+ GDVIRTUAL1RC(bool, _handles, Ref<Resource>)
+ GDVIRTUAL1RC(Ref<Resource>, _convert, Ref<Resource>)
+
+public:
+ virtual String converts_to() const;
+ virtual bool handles(const Ref<Resource> &p_resource) const;
+ virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const;
+};
+
+#endif // EDITOR_RESOURCE_CONVERSION_PLUGIN_H
diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp
new file mode 100644
index 0000000000..cadb974345
--- /dev/null
+++ b/editor/plugins/font_config_plugin.cpp
@@ -0,0 +1,1057 @@
+/*************************************************************************/
+/* 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).bind(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).bind(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"));
+
+ // Draw font preview.
+ bool prev_ok = true;
+ if (prev_font.is_valid()) {
+ if (prev_font->get_font_name().is_empty()) {
+ prev_ok = false;
+ } else {
+ String name;
+ if (prev_font->get_font_style_name().is_empty()) {
+ name = prev_font->get_font_name();
+ } else {
+ name = vformat("%s (%s)", prev_font->get_font_name(), prev_font->get_font_style_name());
+ }
+ if (prev_font->is_class("FontVariation")) {
+ name += " " + TTR(" - Variation");
+ }
+ 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);
+
+ String sample;
+ static const String sample_base = U"12漢字ԱբΑαÐбΑα×בابÜÜ’Þ€Þआআਆઆଆஆఆಆആආà¸à¸´àºàº´à¼€á€€á‚ áƒí•œê¸€áˆ€áŽ£áášáš áœ€áœ á€á áž€á  á¤á¥Ab😀";
+ for (int i = 0; i < sample_base.length(); i++) {
+ if (prev_font->has_char(sample_base[i])) {
+ sample += sample_base[i];
+ }
+ }
+ if (sample.is_empty()) {
+ sample = prev_font->get_supported_chars().substr(0, 6);
+ }
+ if (sample.is_empty()) {
+ prev_ok = false;
+ } else {
+ prev_font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + prev_font->get_height(25 * EDSCALE)), sample, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, 25 * EDSCALE, text_color);
+ }
+ }
+ }
+ if (!prev_ok) {
+ text_color.a *= 0.5;
+ font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), TTR("Unable to preview font"), HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_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) {
+ prev_font = p_f;
+ update();
+}
+
+FontPreview::FontPreview() {
+}
+
+/*************************************************************************/
+/* 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;
+}
+
+/*************************************************************************/
+/* EditorPropertyFontNamesArray */
+/*************************************************************************/
+
+void EditorPropertyFontNamesArray::_add_element() {
+ 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 EditorPropertyFontNamesArray::_add_font(int p_option) {
+ if (updating) {
+ return;
+ }
+
+ Variant array = object->get_array();
+ int previous_size = array.call("size");
+
+ array.call("resize", previous_size + 1);
+ array.set(previous_size, menu->get_item_text(p_option));
+
+ emit_changed(get_edited_property(), array, "", false);
+ object->set_array(array);
+ update_property();
+}
+
+EditorPropertyFontNamesArray::EditorPropertyFontNamesArray() {
+ menu = memnew(PopupMenu);
+ menu->add_item("Sans-Serif", 0);
+ menu->add_item("Serif", 1);
+ menu->add_item("Monospace", 2);
+ menu->add_item("Fantasy", 3);
+ menu->add_item("Cursive", 4);
+
+ menu->add_separator();
+
+ if (OS::get_singleton()) {
+ Vector<String> fonts = OS::get_singleton()->get_system_fonts();
+ for (int i = 0; i < fonts.size(); i++) {
+ menu->add_item(fonts[i], i + 6);
+ }
+ }
+ add_child(menu);
+ menu->connect("id_pressed", callable_mp(this, &EditorPropertyFontNamesArray::_add_font));
+}
+
+/*************************************************************************/
+/* EditorInspectorPluginSystemFont */
+/*************************************************************************/
+
+bool EditorInspectorPluginSystemFont::can_handle(Object *p_object) {
+ return Object::cast_to<SystemFont>(p_object) != nullptr;
+}
+
+bool EditorInspectorPluginSystemFont::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 == "font_names") {
+ EditorPropertyFontNamesArray *editor = memnew(EditorPropertyFontNamesArray);
+ editor->setup(p_type, p_hint_text);
+ add_property_editor(p_path, editor);
+ return true;
+ }
+ return false;
+}
+
+/*************************************************************************/
+/* FontEditorPlugin */
+/*************************************************************************/
+
+FontEditorPlugin::FontEditorPlugin() {
+ Ref<EditorInspectorPluginFontVariation> fc_plugin;
+ fc_plugin.instantiate();
+ EditorInspector::add_inspector_plugin(fc_plugin);
+
+ Ref<EditorInspectorPluginSystemFont> fs_plugin;
+ fs_plugin.instantiate();
+ EditorInspector::add_inspector_plugin(fs_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..3eaa2fdc17
--- /dev/null
+++ b/editor/plugins/font_config_plugin.h
@@ -0,0 +1,288 @@
+/*************************************************************************/
+/* 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 FONT_CONFIG_PLUGIN_H
+#define FONT_CONFIG_PLUGIN_H
+
+#include "core/io/marshalls.h"
+#include "editor/editor_plugin.h"
+#include "editor/editor_properties.h"
+#include "editor/editor_properties_array_dict.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();
+
+ Ref<Font> prev_font;
+
+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 EditorPropertyFontNamesArray : public EditorPropertyArray {
+ GDCLASS(EditorPropertyFontNamesArray, EditorPropertyArray);
+
+ PopupMenu *menu = nullptr;
+
+protected:
+ virtual void _add_element() override;
+
+ void _add_font(int p_option);
+ static void _bind_methods(){};
+
+public:
+ EditorPropertyFontNamesArray();
+};
+
+/*************************************************************************/
+
+class EditorInspectorPluginSystemFont : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginSystemFont, 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 FontEditorPlugin : public EditorPlugin {
+ GDCLASS(FontEditorPlugin, EditorPlugin);
+
+public:
+ FontEditorPlugin();
+
+ virtual String get_name() const override { return "Font"; }
+};
+
+#endif // FONT_CONFIG_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/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h
index b91a17d9e5..b5eca46ad3 100644
--- a/editor/plugins/gdextension_export_plugin.h
+++ b/editor/plugins/gdextension_export_plugin.h
@@ -31,7 +31,7 @@
#ifndef GDEXTENSION_EXPORT_PLUGIN_H
#define GDEXTENSION_EXPORT_PLUGIN_H
-#include "editor/editor_export.h"
+#include "editor/export/editor_export.h"
class GDExtensionExportPlugin : public EditorExportPlugin {
protected:
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index 72caa15e9c..8e6687c836 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);
@@ -391,7 +380,7 @@ GPUParticles2DEditorPlugin::GPUParticles2DEditorPlugin() {
List<String> ext;
ImageLoader::get_recognized_extensions(&ext);
for (const String &E : ext) {
- file->add_filter("*." + E + "; " + E.to_upper());
+ file->add_filter("*." + E, E.to_upper());
}
file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
toolbar->add_child(file);
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h
index 75f68617d1..bf49a82166 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PARTICLES_2D_EDITOR_PLUGIN_H
-#define PARTICLES_2D_EDITOR_PLUGIN_H
+#ifndef GPU_PARTICLES_2D_EDITOR_PLUGIN_H
+#define GPU_PARTICLES_2D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/2d/collision_polygon_2d.h"
@@ -97,4 +97,4 @@ public:
~GPUParticles2DEditorPlugin();
};
-#endif // PARTICLES_2D_EDITOR_PLUGIN_H
+#endif // GPU_PARTICLES_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index fa971679e6..6750f1aa9c 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -215,7 +215,7 @@ GPUParticles3DEditorBase::GPUParticles3DEditorBase() {
emission_fill->add_item(TTR("Volume"));
emd_vb->add_margin_child(TTR("Emission Source:"), emission_fill);
- emission_dialog->get_ok_button()->set_text(TTR("Create"));
+ emission_dialog->set_ok_button_text(TTR("Create"));
emission_dialog->connect("confirmed", callable_mp(this, &GPUParticles3DEditorBase::_generate_emission_points));
emission_tree_dialog = memnew(SceneTreeDialog);
@@ -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/gpu_particles_3d_editor_plugin.h b/editor/plugins/gpu_particles_3d_editor_plugin.h
index 6ba6d102ef..17bdfa6e3f 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PARTICLES_EDITOR_PLUGIN_H
-#define PARTICLES_EDITOR_PLUGIN_H
+#ifndef GPU_PARTICLES_3D_EDITOR_PLUGIN_H
+#define GPU_PARTICLES_3D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/3d/gpu_particles_3d.h"
@@ -114,4 +114,4 @@ public:
~GPUParticles3DEditorPlugin();
};
-#endif // PARTICLES_EDITOR_PLUGIN_H
+#endif // GPU_PARTICLES_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp
index 643a470425..b54cb515e4 100644
--- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp
@@ -140,7 +140,7 @@ void GPUParticlesCollisionSDF3DEditorPlugin::_sdf_save_path_and_bake(const Strin
if (col_sdf) {
Ref<Image> bake_img = col_sdf->bake();
if (bake_img.is_null()) {
- EditorNode::get_singleton()->show_warning(TTR("Bake Error."));
+ EditorNode::get_singleton()->show_warning(TTR("No faces detected during GPUParticlesCollisionSDF3D bake.\nCheck whether there are visible meshes matching the bake mask within its extents."));
return;
}
diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp
index 1386f03662..542aee879b 100644
--- a/editor/plugins/gradient_editor_plugin.cpp
+++ b/editor/plugins/gradient_editor_plugin.cpp
@@ -33,6 +33,7 @@
#include "canvas_item_editor_plugin.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "node_3d_editor_plugin.h"
Size2 GradientEditor::get_minimum_size() const {
@@ -85,6 +86,7 @@ void GradientEditor::reverse_gradient() {
}
GradientEditor::GradientEditor() {
+ GradientEdit::get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(GradientEdit::get_picker()));
editing = false;
}
diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
index e97c611e96..df45d6c290 100644
--- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp
+++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
@@ -117,17 +117,15 @@ void GradientTexture2DEditorRect::_notification(int p_what) {
const Ref<Texture2D> fill_to_icon = get_theme_icon(SNAME("EditorPathSharpHandle"), SNAME("EditorIcons"));
handle_size = fill_from_icon->get_size();
- const int MAX_HEIGHT = 250 * EDSCALE;
Size2 rect_size = get_size();
// Get the size and position to draw the texture and handles at.
- size = Size2(texture->get_width() * MAX_HEIGHT / texture->get_height(), MAX_HEIGHT);
+ size = Size2(texture->get_width() * rect_size.height / texture->get_height(), rect_size.height);
if (size.width > rect_size.width) {
size.width = rect_size.width;
- size.height = texture->get_height() * rect_size.width / texture->get_width();
+ size.height = texture->get_height() * size.width / texture->get_width();
}
- offset = Point2(Math::round((rect_size.width - size.width) / 2), 0) + handle_size / 2;
- set_custom_minimum_size(Size2(0, size.height));
+ offset = ((rect_size - size + handle_size) / 2).round();
size -= handle_size;
checkerboard->set_rect(Rect2(offset, size));
@@ -183,6 +181,8 @@ GradientTexture2DEditorRect::GradientTexture2DEditorRect() {
checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
checkerboard->set_draw_behind_parent(true);
add_child(checkerboard);
+
+ set_custom_minimum_size(Size2(0, 250 * EDSCALE));
}
///////////////////////
diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.h b/editor/plugins/gradient_texture_2d_editor_plugin.h
index 4ce64ce1dc..93c49b1e6f 100644
--- a/editor/plugins/gradient_texture_2d_editor_plugin.h
+++ b/editor/plugins/gradient_texture_2d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GRADIENT_TEXTURE_2D_EDITOR
-#define GRADIENT_TEXTURE_2D_EDITOR
+#ifndef GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H
+#define GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "editor/editor_spin_slider.h"
@@ -109,4 +109,4 @@ public:
GradientTexture2DEditorPlugin();
};
-#endif
+#endif // GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/lightmap_gi_editor_plugin.cpp b/editor/plugins/lightmap_gi_editor_plugin.cpp
index aef97f059a..8413c5e875 100644
--- a/editor/plugins/lightmap_gi_editor_plugin.cpp
+++ b/editor/plugins/lightmap_gi_editor_plugin.cpp
@@ -138,7 +138,7 @@ LightmapGIEditorPlugin::LightmapGIEditorPlugin() {
file_dialog = memnew(EditorFileDialog);
file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- file_dialog->add_filter("*.lmbake ; " + TTR("LightMap Bake"));
+ file_dialog->add_filter("*.lmbake", TTR("LightMap Bake"));
file_dialog->set_title(TTR("Select lightmap bake file:"));
file_dialog->connect("file_selected", callable_mp(this, &LightmapGIEditorPlugin::_bake_select_file));
bake->add_child(file_dialog);
diff --git a/editor/plugins/lightmap_gi_editor_plugin.h b/editor/plugins/lightmap_gi_editor_plugin.h
index 1202efe8fc..a06f97fc94 100644
--- a/editor/plugins/lightmap_gi_editor_plugin.h
+++ b/editor/plugins/lightmap_gi_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BAKED_LIGHTMAP_EDITOR_PLUGIN_H
-#define BAKED_LIGHTMAP_EDITOR_PLUGIN_H
+#ifndef LIGHTMAP_GI_EDITOR_PLUGIN_H
+#define LIGHTMAP_GI_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/3d/lightmap_gi.h"
@@ -67,4 +67,4 @@ public:
~LightmapGIEditorPlugin();
};
-#endif
+#endif // LIGHTMAP_GI_EDITOR_PLUGIN_H
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index eb004568d0..1b4d98fc3f 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -32,6 +32,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/gui/subviewport_container.h"
#include "scene/resources/fog_material.h"
#include "scene/resources/particles_material.h"
@@ -130,7 +131,7 @@ MaterialEditor::MaterialEditor() {
layout_2d = memnew(HBoxContainer);
layout_2d->set_alignment(BoxContainer::ALIGNMENT_CENTER);
add_child(layout_2d);
- layout_2d->set_anchors_and_offsets_preset(PRESET_WIDE);
+ layout_2d->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
rect_instance = memnew(ColorRect);
layout_2d->add_child(rect_instance);
@@ -143,7 +144,7 @@ MaterialEditor::MaterialEditor() {
vc = memnew(SubViewportContainer);
vc->set_stretch(true);
add_child(vc);
- vc->set_anchors_and_offsets_preset(PRESET_WIDE);
+ vc->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
viewport = memnew(SubViewport);
Ref<World3D> world_3d;
world_3d.instantiate();
@@ -155,7 +156,9 @@ MaterialEditor::MaterialEditor() {
camera = memnew(Camera3D);
camera->set_transform(Transform3D(Basis(), Vector3(0, 0, 3)));
- camera->set_perspective(45, 0.1, 10);
+ // Use low field of view so the sphere/box is fully encompassed within the preview,
+ // without much distortion.
+ camera->set_perspective(20, 0.1, 10);
camera->make_current();
viewport->add_child(camera);
@@ -177,8 +180,8 @@ MaterialEditor::MaterialEditor() {
Transform3D box_xform;
box_xform.basis.rotate(Vector3(1, 0, 0), Math::deg2rad(25.0));
box_xform.basis = box_xform.basis * Basis().rotated(Vector3(0, 1, 0), Math::deg2rad(-25.0));
- box_xform.basis.scale(Vector3(0.8, 0.8, 0.8));
- box_xform.origin.y = 0.2;
+ box_xform.basis.scale(Vector3(0.7, 0.7, 0.7));
+ box_xform.origin.y = 0.05;
box_instance->set_transform(box_xform);
sphere_mesh.instantiate();
@@ -190,7 +193,7 @@ MaterialEditor::MaterialEditor() {
layout_3d = memnew(HBoxContainer);
add_child(layout_3d);
- layout_3d->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2);
+ layout_3d->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 2);
VBoxContainer *vb_shape = memnew(VBoxContainer);
layout_3d->add_child(vb_shape);
@@ -199,13 +202,13 @@ MaterialEditor::MaterialEditor() {
sphere_switch->set_toggle_mode(true);
sphere_switch->set_pressed(true);
vb_shape->add_child(sphere_switch);
- sphere_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed), varray(sphere_switch));
+ sphere_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed).bind(sphere_switch));
box_switch = memnew(TextureButton);
box_switch->set_toggle_mode(true);
box_switch->set_pressed(false);
vb_shape->add_child(box_switch);
- box_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed), varray(box_switch));
+ box_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed).bind(box_switch));
layout_3d->add_spacer();
@@ -215,12 +218,12 @@ MaterialEditor::MaterialEditor() {
light_1_switch = memnew(TextureButton);
light_1_switch->set_toggle_mode(true);
vb_light->add_child(light_1_switch);
- light_1_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed), varray(light_1_switch));
+ light_1_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed).bind(light_1_switch));
light_2_switch = memnew(TextureButton);
light_2_switch->set_toggle_mode(true);
vb_light->add_child(light_2_switch);
- light_2_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed), varray(light_2_switch));
+ light_2_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed).bind(light_2_switch));
first_enter = true;
@@ -337,17 +340,17 @@ Ref<Resource> StandardMaterial3DConversionPlugin::convert(const Ref<Resource> &p
smat->set_shader(shader);
List<PropertyInfo> params;
- RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+ RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), &params);
for (const PropertyInfo &E : params) {
// Texture parameter has to be treated specially since StandardMaterial3D saved it
// as RID but ShaderMaterial needs Texture itself
Ref<Texture2D> texture = mat->get_texture_by_name(E.name);
if (texture.is_valid()) {
- smat->set_shader_param(E.name, texture);
+ smat->set_shader_uniform(E.name, texture);
} else {
Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
- smat->set_shader_param(E.name, value);
+ smat->set_shader_uniform(E.name, value);
}
}
@@ -383,17 +386,17 @@ Ref<Resource> ORMMaterial3DConversionPlugin::convert(const Ref<Resource> &p_reso
smat->set_shader(shader);
List<PropertyInfo> params;
- RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+ RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), &params);
for (const PropertyInfo &E : params) {
// Texture parameter has to be treated specially since ORMMaterial3D saved it
// as RID but ShaderMaterial needs Texture itself
Ref<Texture2D> texture = mat->get_texture_by_name(E.name);
if (texture.is_valid()) {
- smat->set_shader_param(E.name, texture);
+ smat->set_shader_uniform(E.name, texture);
} else {
Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
- smat->set_shader_param(E.name, value);
+ smat->set_shader_uniform(E.name, value);
}
}
@@ -429,11 +432,11 @@ Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_
smat->set_shader(shader);
List<PropertyInfo> params;
- RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+ RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), &params);
for (const PropertyInfo &E : params) {
Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
- smat->set_shader_param(E.name, value);
+ smat->set_shader_uniform(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
@@ -468,11 +471,11 @@ Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p
smat->set_shader(shader);
List<PropertyInfo> params;
- RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+ RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), &params);
for (const PropertyInfo &E : params) {
Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
- smat->set_shader_param(E.name, value);
+ smat->set_shader_uniform(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
@@ -507,11 +510,11 @@ Ref<Resource> ProceduralSkyMaterialConversionPlugin::convert(const Ref<Resource>
smat->set_shader(shader);
List<PropertyInfo> params;
- RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+ RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), &params);
for (const PropertyInfo &E : params) {
Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
- smat->set_shader_param(E.name, value);
+ smat->set_shader_uniform(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
@@ -546,11 +549,11 @@ Ref<Resource> PanoramaSkyMaterialConversionPlugin::convert(const Ref<Resource> &
smat->set_shader(shader);
List<PropertyInfo> params;
- RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+ RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), &params);
for (const PropertyInfo &E : params) {
Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
- smat->set_shader_param(E.name, value);
+ smat->set_shader_uniform(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
@@ -585,11 +588,11 @@ Ref<Resource> PhysicalSkyMaterialConversionPlugin::convert(const Ref<Resource> &
smat->set_shader(shader);
List<PropertyInfo> params;
- RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+ RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), &params);
for (const PropertyInfo &E : params) {
Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
- smat->set_shader_param(E.name, value);
+ smat->set_shader_uniform(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
@@ -624,11 +627,11 @@ Ref<Resource> FogMaterialConversionPlugin::convert(const Ref<Resource> &p_resour
smat->set_shader(shader);
List<PropertyInfo> params;
- RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+ RS::get_singleton()->shader_get_shader_uniform_list(mat->get_shader_rid(), &params);
for (const PropertyInfo &E : params) {
Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
- smat->set_shader_param(E.name, value);
+ smat->set_shader_uniform(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
index 9c6247d59b..fc3da5fd9f 100644
--- a/editor/plugins/material_editor_plugin.h
+++ b/editor/plugins/material_editor_plugin.h
@@ -32,7 +32,7 @@
#define MATERIAL_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "editor/property_editor.h"
+#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index 7029768479..31c9f1e387 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -137,7 +137,7 @@ MeshEditor::MeshEditor() {
HBoxContainer *hb = memnew(HBoxContainer);
add_child(hb);
- hb->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2);
+ hb->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 2);
hb->add_spacer();
@@ -147,12 +147,12 @@ MeshEditor::MeshEditor() {
light_1_switch = memnew(TextureButton);
light_1_switch->set_toggle_mode(true);
vb_light->add_child(light_1_switch);
- light_1_switch->connect("pressed", callable_mp(this, &MeshEditor::_button_pressed), varray(light_1_switch));
+ light_1_switch->connect("pressed", callable_mp(this, &MeshEditor::_button_pressed).bind(light_1_switch));
light_2_switch = memnew(TextureButton);
light_2_switch->set_toggle_mode(true);
vb_light->add_child(light_2_switch);
- light_2_switch->connect("pressed", callable_mp(this, &MeshEditor::_button_pressed), varray(light_2_switch));
+ light_2_switch->connect("pressed", callable_mp(this, &MeshEditor::_button_pressed).bind(light_2_switch));
first_enter = true;
diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h
index 3554b3c1e9..fb61f03485 100644
--- a/editor/plugins/mesh_editor_plugin.h
+++ b/editor/plugins/mesh_editor_plugin.h
@@ -87,4 +87,4 @@ public:
MeshEditorPlugin();
};
-#endif
+#endif // MESH_EDITOR_PLUGIN_H
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index d1f858315c..5fb885ad1f 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -519,7 +519,7 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
outline_dialog = memnew(ConfirmationDialog);
outline_dialog->set_title(TTR("Create Outline Mesh"));
- outline_dialog->get_ok_button()->set_text(TTR("Create"));
+ outline_dialog->set_ok_button_text(TTR("Create"));
VBoxContainer *outline_dialog_vbc = memnew(VBoxContainer);
outline_dialog->add_child(outline_dialog_vbc);
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h
index 36d8eacd98..7968176744 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.h
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef MESH_INSTANCE_EDITOR_PLUGIN_H
-#define MESH_INSTANCE_EDITOR_PLUGIN_H
+#ifndef MESH_INSTANCE_3D_EDITOR_PLUGIN_H
+#define MESH_INSTANCE_3D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/3d/mesh_instance_3d.h"
@@ -97,4 +97,4 @@ public:
~MeshInstance3DEditorPlugin();
};
-#endif // MESH_EDITOR_PLUGIN_H
+#endif // MESH_INSTANCE_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 914ccb54c1..319f6ee9de 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -263,7 +263,7 @@ MeshLibraryEditor::MeshLibraryEditor() {
file->clear_filters();
file->set_title(TTR("Import Scene"));
for (int i = 0; i < extensions.size(); i++) {
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file->add_filter("*." + extensions[i], extensions[i].to_upper());
}
add_child(file);
file->connect("file_selected", callable_mp(this, &MeshLibraryEditor::_import_scene_cbk));
@@ -288,9 +288,9 @@ MeshLibraryEditor::MeshLibraryEditor() {
cd_remove->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_remove_confirm));
cd_update = memnew(ConfirmationDialog);
add_child(cd_update);
- cd_update->get_ok_button()->set_text(TTR("Apply without Transforms"));
- cd_update->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(false));
- cd_update->add_button(TTR("Apply with Transforms"))->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(true));
+ cd_update->set_ok_button_text(TTR("Apply without Transforms"));
+ cd_update->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm).bind(false));
+ cd_update->add_button(TTR("Apply with Transforms"))->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm).bind(true));
}
void MeshLibraryEditorPlugin::edit(Object *p_node) {
diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index 0fab3aed0d..fc4dc5bc2f 100644
--- a/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
@@ -291,7 +291,7 @@ MultiMeshEditor::MultiMeshEditor() {
Button *b = memnew(Button);
hbc->add_child(b);
b->set_text("..");
- b->connect("pressed", callable_mp(this, &MultiMeshEditor::_browse), make_binds(false));
+ b->connect("pressed", callable_mp(this, &MultiMeshEditor::_browse).bind(false));
vbc->add_margin_child(TTR("Target Surface:"), hbc);
@@ -303,7 +303,7 @@ MultiMeshEditor::MultiMeshEditor() {
hbc->add_child(b);
b->set_text("..");
vbc->add_margin_child(TTR("Source Mesh:"), hbc);
- b->connect("pressed", callable_mp(this, &MultiMeshEditor::_browse), make_binds(true));
+ b->connect("pressed", callable_mp(this, &MultiMeshEditor::_browse).bind(true));
populate_axis = memnew(OptionButton);
populate_axis->add_item(TTR("X-Axis"));
@@ -347,7 +347,7 @@ MultiMeshEditor::MultiMeshEditor() {
populate_amount->set_value(128);
vbc->add_margin_child(TTR("Amount:"), populate_amount);
- populate_dialog->get_ok_button()->set_text(TTR("Populate"));
+ populate_dialog->set_ok_button_text(TTR("Populate"));
populate_dialog->get_ok_button()->connect("pressed", callable_mp(this, &MultiMeshEditor::_populate));
std = memnew(SceneTreeDialog);
diff --git a/editor/plugins/navigation_polygon_editor_plugin.h b/editor/plugins/navigation_polygon_editor_plugin.h
index 7550b75fa3..239da88ba2 100644
--- a/editor/plugins/navigation_polygon_editor_plugin.h
+++ b/editor/plugins/navigation_polygon_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NAVIGATIONPOLYGONEDITORPLUGIN_H
-#define NAVIGATIONPOLYGONEDITORPLUGIN_H
+#ifndef NAVIGATION_POLYGON_EDITOR_PLUGIN_H
+#define NAVIGATION_POLYGON_EDITOR_PLUGIN_H
#include "editor/plugins/abstract_polygon_2d_editor.h"
#include "scene/2d/navigation_region_2d.h"
@@ -67,4 +67,4 @@ public:
NavigationPolygonEditorPlugin();
};
-#endif // NAVIGATIONPOLYGONEDITORPLUGIN_H
+#endif // NAVIGATION_POLYGON_EDITOR_PLUGIN_H
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 64aeb9f2a8..0070226d40 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -57,6 +57,7 @@
#include "scene/3d/position_3d.h"
#include "scene/3d/ray_cast_3d.h"
#include "scene/3d/reflection_probe.h"
+#include "scene/3d/shape_cast_3d.h"
#include "scene/3d/soft_dynamic_body_3d.h"
#include "scene/3d/spring_arm_3d.h"
#include "scene/3d/sprite_3d.h"
@@ -74,6 +75,7 @@
#include "scene/resources/sphere_shape_3d.h"
#include "scene/resources/surface_tool.h"
#include "scene/resources/world_boundary_shape_3d.h"
+#include "servers/navigation_server_3d.h"
#define HANDLE_HALF_SIZE 9.5
@@ -245,6 +247,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) {
@@ -2539,6 +2542,44 @@ void RayCast3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
/////
+ShapeCast3DGizmoPlugin::ShapeCast3DGizmoPlugin() {
+ const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
+ create_material("shape_material", gizmo_color);
+ const float gizmo_value = gizmo_color.get_v();
+ const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
+ create_material("shape_material_disabled", gizmo_color_disabled);
+}
+
+bool ShapeCast3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
+ return Object::cast_to<ShapeCast3D>(p_spatial) != nullptr;
+}
+
+String ShapeCast3DGizmoPlugin::get_gizmo_name() const {
+ return "ShapeCast3D";
+}
+
+int ShapeCast3DGizmoPlugin::get_priority() const {
+ return -1;
+}
+
+void ShapeCast3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
+ ShapeCast3D *shapecast = Object::cast_to<ShapeCast3D>(p_gizmo->get_spatial_node());
+
+ p_gizmo->clear();
+
+ const Ref<StandardMaterial3D> material = shapecast->is_enabled() ? shapecast->get_debug_material() : get_material("shape_material_disabled");
+
+ p_gizmo->add_lines(shapecast->get_debug_line_vertices(), material);
+
+ if (shapecast->get_shape().is_valid()) {
+ p_gizmo->add_lines(shapecast->get_debug_shape_vertices(), material);
+ }
+
+ p_gizmo->add_collision_segments(shapecast->get_debug_line_vertices());
+}
+
+/////
+
void SpringArm3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
SpringArm3D *spring_arm = Object::cast_to<SpringArm3D>(p_gizmo->get_spatial_node());
@@ -4798,10 +4839,6 @@ void CollisionPolygon3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
////
NavigationRegion3DGizmoPlugin::NavigationRegion3DGizmoPlugin() {
- create_material("navigation_edge_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge", Color(0.5, 1, 1)));
- create_material("navigation_edge_material_disabled", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge_disabled", Color(0.7, 0.7, 0.7)));
- create_material("navigation_solid_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid", Color(0.5, 1, 1, 0.4)));
- create_material("navigation_solid_material_disabled", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid_disabled", Color(0.7, 0.7, 0.7, 0.4)));
}
bool NavigationRegion3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
@@ -4817,24 +4854,19 @@ int NavigationRegion3DGizmoPlugin::get_priority() const {
}
void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
- NavigationRegion3D *navmesh = Object::cast_to<NavigationRegion3D>(p_gizmo->get_spatial_node());
-
- Ref<Material> edge_material = get_material("navigation_edge_material", p_gizmo);
- Ref<Material> edge_material_disabled = get_material("navigation_edge_material_disabled", p_gizmo);
- Ref<Material> solid_material = get_material("navigation_solid_material", p_gizmo);
- Ref<Material> solid_material_disabled = get_material("navigation_solid_material_disabled", p_gizmo);
+ NavigationRegion3D *navigationregion = Object::cast_to<NavigationRegion3D>(p_gizmo->get_spatial_node());
p_gizmo->clear();
- Ref<NavigationMesh> navmeshie = navmesh->get_navigation_mesh();
- if (navmeshie.is_null()) {
+ Ref<NavigationMesh> navigationmesh = navigationregion->get_navigation_mesh();
+ if (navigationmesh.is_null()) {
return;
}
- Vector<Vector3> vertices = navmeshie->get_vertices();
+ Vector<Vector3> vertices = navigationmesh->get_vertices();
const Vector3 *vr = vertices.ptr();
List<Face3> faces;
- for (int i = 0; i < navmeshie->get_polygon_count(); i++) {
- Vector<int> p = navmeshie->get_polygon(i);
+ for (int i = 0; i < navigationmesh->get_polygon_count(); i++) {
+ Vector<int> p = navigationmesh->get_polygon(i);
for (int j = 2; j < p.size(); j++) {
Face3 f;
@@ -4891,17 +4923,90 @@ void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<TriangleMesh> tmesh = memnew(TriangleMesh);
tmesh->create(tmeshfaces);
- if (lines.size()) {
- p_gizmo->add_lines(lines, navmesh->is_enabled() ? edge_material : edge_material_disabled);
- }
p_gizmo->add_collision_triangles(tmesh);
- Ref<ArrayMesh> m = memnew(ArrayMesh);
- Array a;
- a.resize(Mesh::ARRAY_MAX);
- a[0] = tmeshfaces;
- m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a);
- m->surface_set_material(0, navmesh->is_enabled() ? solid_material : solid_material_disabled);
- p_gizmo->add_mesh(m);
+
+ Ref<ArrayMesh> debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
+ int polygon_count = navigationmesh->get_polygon_count();
+
+ // build geometry face surface
+ Vector<Vector3> face_vertex_array;
+ face_vertex_array.resize(polygon_count * 3);
+
+ for (int i = 0; i < polygon_count; i++) {
+ Vector<int> polygon = navigationmesh->get_polygon(i);
+
+ face_vertex_array.push_back(vertices[polygon[0]]);
+ face_vertex_array.push_back(vertices[polygon[1]]);
+ face_vertex_array.push_back(vertices[polygon[2]]);
+ }
+
+ Array face_mesh_array;
+ face_mesh_array.resize(Mesh::ARRAY_MAX);
+ face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array;
+
+ // if enabled add vertex colors to colorize each face individually
+ bool enabled_geometry_face_random_color = NavigationServer3D::get_singleton()->get_debug_navigation_enable_geometry_face_random_color();
+ if (enabled_geometry_face_random_color) {
+ Color debug_navigation_geometry_face_color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color();
+ Color polygon_color = debug_navigation_geometry_face_color;
+
+ Vector<Color> face_color_array;
+ face_color_array.resize(polygon_count * 3);
+
+ for (int i = 0; i < polygon_count; i++) {
+ polygon_color = debug_navigation_geometry_face_color * (Color(Math::randf(), Math::randf(), Math::randf()));
+
+ Vector<int> polygon = navigationmesh->get_polygon(i);
+
+ face_color_array.push_back(polygon_color);
+ face_color_array.push_back(polygon_color);
+ face_color_array.push_back(polygon_color);
+ }
+ face_mesh_array[Mesh::ARRAY_COLOR] = face_color_array;
+ }
+
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array);
+ Ref<StandardMaterial3D> debug_geometry_face_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_material();
+ debug_mesh->surface_set_material(0, debug_geometry_face_material);
+
+ // if enabled build geometry edge line surface
+ bool enabled_edge_lines = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines();
+
+ if (enabled_edge_lines) {
+ Vector<Vector3> line_vertex_array;
+ line_vertex_array.resize(polygon_count * 6);
+
+ for (int i = 0; i < polygon_count; i++) {
+ Vector<int> polygon = navigationmesh->get_polygon(i);
+
+ line_vertex_array.push_back(vertices[polygon[0]]);
+ line_vertex_array.push_back(vertices[polygon[1]]);
+ line_vertex_array.push_back(vertices[polygon[1]]);
+ line_vertex_array.push_back(vertices[polygon[2]]);
+ line_vertex_array.push_back(vertices[polygon[2]]);
+ line_vertex_array.push_back(vertices[polygon[0]]);
+ }
+
+ Array line_mesh_array;
+ line_mesh_array.resize(Mesh::ARRAY_MAX);
+ line_mesh_array[Mesh::ARRAY_VERTEX] = line_vertex_array;
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, line_mesh_array);
+ Ref<StandardMaterial3D> debug_geometry_edge_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_material();
+ debug_mesh->surface_set_material(1, debug_geometry_edge_material);
+ }
+
+ if (!navigationregion->is_enabled()) {
+ if (debug_mesh.is_valid()) {
+ if (debug_mesh->get_surface_count() > 0) {
+ debug_mesh->surface_set_material(0, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_disabled_material());
+ }
+ if (debug_mesh->get_surface_count() > 1) {
+ debug_mesh->surface_set_material(1, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_disabled_material());
+ }
+ }
+ }
+
+ p_gizmo->add_mesh(debug_mesh);
p_gizmo->add_collision_segments(lines);
}
@@ -5043,8 +5148,8 @@ Basis JointGizmosDrawer::look_body_toward_z(const Transform3D &p_joint_transform
void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform3D &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse) {
if (p_limit_lower == p_limit_upper) {
- r_points.push_back(p_offset.translated(Vector3()).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(0.5, 0, 0))).origin);
+ r_points.push_back(p_offset.translated_local(Vector3()).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(0.5, 0, 0))).origin);
} else {
if (p_limit_lower > p_limit_upper) {
@@ -5086,20 +5191,20 @@ void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const
}
if (i == points - 1) {
- r_points.push_back(p_offset.translated(to).origin);
- r_points.push_back(p_offset.translated(Vector3()).origin);
+ r_points.push_back(p_offset.translated_local(to).origin);
+ r_points.push_back(p_offset.translated_local(Vector3()).origin);
}
if (i == 0) {
- r_points.push_back(p_offset.translated(from).origin);
- r_points.push_back(p_offset.translated(Vector3()).origin);
+ r_points.push_back(p_offset.translated_local(from).origin);
+ r_points.push_back(p_offset.translated_local(Vector3()).origin);
}
- r_points.push_back(p_offset.translated(from).origin);
- r_points.push_back(p_offset.translated(to).origin);
+ r_points.push_back(p_offset.translated_local(from).origin);
+ r_points.push_back(p_offset.translated_local(to).origin);
}
- r_points.push_back(p_offset.translated(Vector3(0, p_radius * 1.5, 0)).origin);
- r_points.push_back(p_offset.translated(Vector3()).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(0, p_radius * 1.5, 0)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3()).origin);
}
}
@@ -5115,17 +5220,17 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba
Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, a.x, a.y))).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, b.x, b.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(d, a.x, a.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(d, b.x, b.y))).origin);
if (i % 90 == 0) {
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, a.x, a.y))).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3())).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(d, a.x, a.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3())).origin);
}
}
- r_points.push_back(p_offset.translated(p_base.xform(Vector3())).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(1, 0, 0))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3())).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(1, 0, 0))).origin);
/// Twist
float ts = Math::rad2deg(p_twist);
@@ -5139,8 +5244,8 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba
Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w * c;
Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w * cn;
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(c, a.x, a.y))).origin);
- r_points.push_back(p_offset.translated(p_base.xform(Vector3(cn, b.x, b.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(c, a.x, a.y))).origin);
+ r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(cn, b.x, b.y))).origin);
}
}
@@ -5324,17 +5429,17 @@ void Joint3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
void Joint3DGizmoPlugin::CreatePinJointGizmo(const Transform3D &p_offset, Vector<Vector3> &r_cursor_points) {
float cs = 0.25;
- r_cursor_points.push_back(p_offset.translated(Vector3(+cs, 0, 0)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(-cs, 0, 0)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(0, +cs, 0)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(0, -cs, 0)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, +cs)).origin);
- r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, -cs)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(+cs, 0, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(-cs, 0, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(0, +cs, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(0, -cs, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(0, 0, +cs)).origin);
+ r_cursor_points.push_back(p_offset.translated_local(Vector3(0, 0, -cs)).origin);
}
void Joint3DGizmoPlugin::CreateHingeJointGizmo(const Transform3D &p_offset, const Transform3D &p_trs_joint, const Transform3D &p_trs_body_a, const Transform3D &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
- r_common_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin);
- r_common_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin);
+ r_common_points.push_back(p_offset.translated_local(Vector3(0, 0, 0.5)).origin);
+ r_common_points.push_back(p_offset.translated_local(Vector3(0, 0, -0.5)).origin);
if (!p_use_limit) {
p_limit_upper = -1;
@@ -5367,34 +5472,34 @@ void Joint3DGizmoPlugin::CreateSliderJointGizmo(const Transform3D &p_offset, con
p_linear_limit_upper = -p_linear_limit_upper;
float cs = 0.25;
- r_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin);
- r_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(0, 0, 0.5)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(0, 0, -0.5)).origin);
if (p_linear_limit_lower >= p_linear_limit_upper) {
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, 0, 0)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, 0, 0)).origin);
-
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
-
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, -cs)).origin);
- r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, 0, 0)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, 0, 0)).origin);
+
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
+
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
} else {
- r_points.push_back(p_offset.translated(Vector3(+cs * 2, 0, 0)).origin);
- r_points.push_back(p_offset.translated(Vector3(-cs * 2, 0, 0)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(+cs * 2, 0, 0)).origin);
+ r_points.push_back(p_offset.translated_local(Vector3(-cs * 2, 0, 0)).origin);
}
if (r_body_a_points) {
@@ -5517,13 +5622,13 @@ void Joint3DGizmoPlugin::CreateGeneric6DOFJointGizmo(
break;
}
-#define ADD_VTX(x, y, z) \
- { \
- Vector3 v; \
- v[a1] = (x); \
- v[a2] = (y); \
- v[a3] = (z); \
- r_points.push_back(p_offset.translated(v).origin); \
+#define ADD_VTX(x, y, z) \
+ { \
+ Vector3 v; \
+ v[a1] = (x); \
+ v[a2] = (y); \
+ v[a3] = (z); \
+ r_points.push_back(p_offset.translated_local(v).origin); \
}
if (enable_lin && lll >= lul) {
diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index a0d7715347..739bf1b929 100644
--- a/editor/plugins/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -373,6 +373,18 @@ public:
RayCast3DGizmoPlugin();
};
+class ShapeCast3DGizmoPlugin : public EditorNode3DGizmoPlugin {
+ GDCLASS(ShapeCast3DGizmoPlugin, EditorNode3DGizmoPlugin);
+
+public:
+ bool has_gizmo(Node3D *p_spatial) override;
+ String get_gizmo_name() const override;
+ int get_priority() const override;
+ void redraw(EditorNode3DGizmo *p_gizmo) override;
+
+ ShapeCast3DGizmoPlugin();
+};
+
class SpringArm3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(SpringArm3DGizmoPlugin, EditorNode3DGizmoPlugin);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 815d0a2425..005d5fc951 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -33,8 +33,8 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/input/input_map.h"
-#include "core/math/camera_matrix.h"
#include "core/math/math_funcs.h"
+#include "core/math/projection.h"
#include "core/os/keyboard.h"
#include "core/templates/sort_array.h"
#include "editor/debugger/editor_debugger_node.h"
@@ -52,6 +52,7 @@
#include "scene/3d/visual_instance_3d.h"
#include "scene/3d/world_environment.h"
#include "scene/gui/center_container.h"
+#include "scene/gui/flow_container.h"
#include "scene/gui/subviewport_container.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/surface_tool.h"
@@ -145,7 +146,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);
@@ -355,14 +356,14 @@ void Node3DEditorViewport::_update_camera(real_t p_interp_delta) {
Transform3D Node3DEditorViewport::to_camera_transform(const Cursor &p_cursor) const {
Transform3D camera_transform;
- camera_transform.translate(p_cursor.pos);
+ camera_transform.translate_local(p_cursor.pos);
camera_transform.basis.rotate(Vector3(1, 0, 0), -p_cursor.x_rot);
camera_transform.basis.rotate(Vector3(0, 1, 0), -p_cursor.y_rot);
if (orthogonal) {
- camera_transform.translate(0, 0, (get_zfar() - get_znear()) / 2.0);
+ camera_transform.translate_local(0, 0, (get_zfar() - get_znear()) / 2.0);
} else {
- camera_transform.translate(0, 0, p_cursor.distance);
+ camera_transform.translate_local(0, 0, p_cursor.distance);
}
return camera_transform;
@@ -514,7 +515,7 @@ void Node3DEditorViewport::_select_clicked(bool p_allow_locked) {
}
}
-ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) {
+ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const {
Vector3 ray = _get_ray(p_pos);
Vector3 pos = _get_ray_pos(p_pos);
Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink();
@@ -641,7 +642,7 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, Vector<_RayRe
}
Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) {
- CameraMatrix cm;
+ Projection cm;
if (orthogonal) {
cm.set_orthogonal(camera->get_size(), get_size().aspect(), get_znear() + p_vector3.z, get_zfar());
} else {
@@ -650,10 +651,10 @@ Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) {
Vector2 screen_he = cm.get_viewport_half_extents();
Transform3D camera_transform;
- camera_transform.translate(cursor.pos);
+ camera_transform.translate_local(cursor.pos);
camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
- camera_transform.translate(0, 0, cursor.distance);
+ camera_transform.translate_local(0, 0, cursor.distance);
return camera_transform.xform(Vector3(((p_vector3.x / get_size().width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (p_vector3.y / get_size().height)) * 2.0 - 1.0) * screen_he.y, -(get_znear() + p_vector3.z)));
}
@@ -1259,7 +1260,9 @@ void Node3DEditorViewport::_surface_mouse_enter() {
}
void Node3DEditorViewport::_surface_mouse_exit() {
- _remove_preview();
+ _remove_preview_node();
+ _reset_preview_material();
+ _remove_preview_material();
}
void Node3DEditorViewport::_surface_focus_enter() {
@@ -2099,7 +2102,7 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const
Transform3D camera_transform;
- camera_transform.translate(cursor.pos);
+ camera_transform.translate_local(cursor.pos);
camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
const bool invert_x_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_x_axis");
@@ -2109,7 +2112,7 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const
(invert_y_axis ? -1 : 1) * p_relative.y * pan_speed,
0);
translation *= cursor.distance / DISTANCE_DEFAULT;
- camera_transform.translate(translation);
+ camera_transform.translate_local(translation);
cursor.pos = camera_transform.origin;
}
@@ -2379,19 +2382,19 @@ void Node3DEditorPlugin::edited_scene_changed() {
void Node3DEditorViewport::_project_settings_changed() {
//update shadow atlas if changed
- int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/size");
- bool shadowmap_16_bits = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/16_bits");
- int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_0_subdiv");
- int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_1_subdiv");
- int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_2_subdiv");
- int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/shadows/shadow_atlas/quadrant_3_subdiv");
-
- viewport->set_shadow_atlas_size(shadowmap_size);
- viewport->set_shadow_atlas_16_bits(shadowmap_16_bits);
- viewport->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0));
- viewport->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1));
- viewport->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
- viewport->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
+ int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_size");
+ bool shadowmap_16_bits = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_16_bits");
+ int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv");
+ int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv");
+ int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv");
+ int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv");
+
+ viewport->set_positional_shadow_atlas_size(shadowmap_size);
+ viewport->set_positional_shadow_atlas_16_bits(shadowmap_16_bits);
+ viewport->set_positional_shadow_atlas_quadrant_subdiv(0, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q0));
+ viewport->set_positional_shadow_atlas_quadrant_subdiv(1, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q1));
+ viewport->set_positional_shadow_atlas_quadrant_subdiv(2, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q2));
+ viewport->set_positional_shadow_atlas_quadrant_subdiv(3, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q3));
_update_shrink();
@@ -2422,8 +2425,8 @@ void Node3DEditorViewport::_project_settings_changed() {
const float fsr_sharpness = GLOBAL_GET("rendering/scaling_3d/fsr_sharpness");
viewport->set_fsr_sharpness(fsr_sharpness);
- const float fsr_mipmap_bias = GLOBAL_GET("rendering/scaling_3d/fsr_mipmap_bias");
- viewport->set_fsr_mipmap_bias(fsr_mipmap_bias);
+ const float texture_mipmap_bias = GLOBAL_GET("rendering/textures/default_filters/texture_mipmap_bias");
+ viewport->set_texture_mipmap_bias(texture_mipmap_bias);
}
void Node3DEditorViewport::_notification(int p_what) {
@@ -2519,14 +2522,14 @@ void Node3DEditorViewport::_notification(int p_what) {
const Vector3 offset(0.005, 0.005, 0.005);
Basis aabb_s;
aabb_s.scale(se->aabb.size + offset);
- t.translate(se->aabb.position - offset / 2);
+ t.translate_local(se->aabb.position - offset / 2);
t.basis = t.basis * aabb_s;
}
{
const Vector3 offset(0.01, 0.01, 0.01);
Basis aabb_s;
aabb_s.scale(se->aabb.size + offset);
- t_offset.translate(se->aabb.position - offset / 2);
+ t_offset.translate_local(se->aabb.position - offset / 2);
t_offset.basis = t_offset.basis * aabb_s;
}
@@ -2702,6 +2705,13 @@ void Node3DEditorViewport::_notification(int p_what) {
cinema_label->add_theme_style_override("normal", gui_base->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
locked_label->add_theme_style_override("normal", gui_base->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles")));
} break;
+
+ case NOTIFICATION_DRAG_END: {
+ // Clear preview material when dropped outside applicable object.
+ if (spatial_editor->get_preview_material().is_valid() && !is_drag_successful()) {
+ _remove_preview_material();
+ }
+ } break;
}
}
@@ -2725,7 +2735,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 +3262,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 +3271,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 +3280,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 +3289,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 +3298,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 +3306,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 +3318,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() {
@@ -3784,7 +3803,7 @@ Node *Node3DEditorViewport::_sanitize_preview_node(Node *p_node) const {
return p_node;
}
-void Node3DEditorViewport::_create_preview(const Vector<String> &files) const {
+void Node3DEditorViewport::_create_preview_node(const Vector<String> &files) const {
for (int i = 0; i < files.size(); i++) {
String path = files[i];
Ref<Resource> res = ResourceLoader::load(path);
@@ -3811,7 +3830,7 @@ void Node3DEditorViewport::_create_preview(const Vector<String> &files) const {
*preview_bounds = _calculate_spatial_bounds(preview_node);
}
-void Node3DEditorViewport::_remove_preview() {
+void Node3DEditorViewport::_remove_preview_node() {
if (preview_node->get_parent()) {
for (int i = preview_node->get_child_count() - 1; i >= 0; i--) {
Node *node = preview_node->get_child(i);
@@ -3822,6 +3841,106 @@ void Node3DEditorViewport::_remove_preview() {
}
}
+bool Node3DEditorViewport::_apply_preview_material(ObjectID p_target, const Point2 &p_point) const {
+ _reset_preview_material();
+
+ if (p_target.is_null()) {
+ return false;
+ }
+
+ spatial_editor->set_preview_material_target(p_target);
+
+ Object *target_inst = ObjectDB::get_instance(p_target);
+
+ bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL);
+
+ MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(target_inst);
+ if (is_ctrl && mesh_instance) {
+ Ref<Mesh> mesh = mesh_instance->get_mesh();
+ int surface_count = mesh->get_surface_count();
+
+ Vector3 world_ray = _get_ray(p_point);
+ Vector3 world_pos = _get_ray_pos(p_point);
+
+ int closest_surface = -1;
+ float closest_dist = 1e20;
+
+ Transform3D gt = mesh_instance->get_global_transform();
+
+ Transform3D ai = gt.affine_inverse();
+ Vector3 xform_ray = ai.basis.xform(world_ray).normalized();
+ Vector3 xform_pos = ai.xform(world_pos);
+
+ for (int surface = 0; surface < surface_count; surface++) {
+ Ref<TriangleMesh> surface_mesh = mesh->generate_surface_triangle_mesh(surface);
+
+ Vector3 rpos, rnorm;
+ if (surface_mesh->intersect_ray(xform_pos, xform_ray, rpos, rnorm)) {
+ Vector3 hitpos = gt.xform(rpos);
+
+ const real_t dist = world_pos.distance_to(hitpos);
+
+ if (dist < 0) {
+ continue;
+ }
+
+ if (dist < closest_dist) {
+ closest_surface = surface;
+ closest_dist = dist;
+ }
+ }
+ }
+
+ if (closest_surface == -1) {
+ return false;
+ }
+
+ if (spatial_editor->get_preview_material() != mesh_instance->get_surface_override_material(closest_surface)) {
+ spatial_editor->set_preview_material_surface(closest_surface);
+ spatial_editor->set_preview_reset_material(mesh_instance->get_surface_override_material(closest_surface));
+ mesh_instance->set_surface_override_material(closest_surface, spatial_editor->get_preview_material());
+ }
+
+ return true;
+ }
+
+ GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(target_inst);
+ if (geometry_instance && spatial_editor->get_preview_material() != geometry_instance->get_material_override()) {
+ spatial_editor->set_preview_reset_material(geometry_instance->get_material_override());
+ geometry_instance->set_material_override(spatial_editor->get_preview_material());
+ return true;
+ }
+
+ return false;
+}
+
+void Node3DEditorViewport::_reset_preview_material() const {
+ ObjectID last_target = spatial_editor->get_preview_material_target();
+ if (last_target.is_null()) {
+ return;
+ }
+ Object *last_target_inst = ObjectDB::get_instance(last_target);
+
+ MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(last_target_inst);
+ GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(last_target_inst);
+ if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) {
+ mesh_instance->set_surface_override_material(spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material());
+ spatial_editor->set_preview_material_surface(-1);
+ } else if (geometry_instance) {
+ geometry_instance->set_material_override(spatial_editor->get_preview_reset_material());
+ }
+}
+
+void Node3DEditorViewport::_remove_preview_material() {
+ preview_material_label->hide();
+ preview_material_label_desc->hide();
+
+ spatial_editor->set_preview_material(Ref<Material>());
+ spatial_editor->set_preview_reset_material(Ref<Material>());
+ spatial_editor->set_preview_material_target(ObjectID());
+ spatial_editor->set_preview_material_surface(-1);
+}
+
bool Node3DEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {
if (p_desired_node->get_scene_file_path() == p_target_scene_path) {
return true;
@@ -3920,7 +4039,26 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
}
void Node3DEditorViewport::_perform_drop_data() {
- _remove_preview();
+ if (spatial_editor->get_preview_material_target().is_valid()) {
+ GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target()));
+ MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target()));
+ if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) {
+ editor_data->get_undo_redo().create_action(vformat(TTR("Set Surface %d Override Material"), spatial_editor->get_preview_material_surface()));
+ editor_data->get_undo_redo().add_do_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_material());
+ editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material());
+ editor_data->get_undo_redo().commit_action();
+ } else if (geometry_instance) {
+ editor_data->get_undo_redo().create_action(TTR("Set Material Override"));
+ editor_data->get_undo_redo().add_do_method(geometry_instance, "set_material_override", spatial_editor->get_preview_material());
+ editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_material_override", spatial_editor->get_preview_reset_material());
+ editor_data->get_undo_redo().commit_action();
+ }
+
+ _remove_preview_material();
+ return;
+ }
+
+ _remove_preview_node();
Vector<String> error_files;
@@ -3958,7 +4096,7 @@ void Node3DEditorViewport::_perform_drop_data() {
bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
bool can_instantiate = false;
- if (!preview_node->is_inside_tree()) {
+ if (!preview_node->is_inside_tree() && spatial_editor->get_preview_material().is_null()) {
Dictionary d = p_data;
if (d.has("type") && (String(d["type"]) == "files")) {
Vector<String> files = d["files"];
@@ -3967,40 +4105,78 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions);
List<String> mesh_extensions;
ResourceLoader::get_recognized_extensions_for_type("Mesh", &mesh_extensions);
+ List<String> material_extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Material", &material_extensions);
+ List<String> texture_extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Texture", &texture_extensions);
for (int i = 0; i < files.size(); i++) {
// Check if dragged files with mesh or scene extension can be created at least once.
- if (mesh_extensions.find(files[i].get_extension()) || scene_extensions.find(files[i].get_extension())) {
+ if (mesh_extensions.find(files[i].get_extension()) ||
+ scene_extensions.find(files[i].get_extension()) ||
+ material_extensions.find(files[i].get_extension()) ||
+ texture_extensions.find(files[i].get_extension())) {
Ref<Resource> res = ResourceLoader::load(files[i]);
if (res.is_null()) {
continue;
}
Ref<PackedScene> scn = res;
+ Ref<Material> mat = res;
+ Ref<Texture2D> tex = res;
if (scn.is_valid()) {
Node *instantiated_scene = scn->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
if (!instantiated_scene) {
continue;
}
memdelete(instantiated_scene);
+ } else if (mat.is_valid()) {
+ Ref<BaseMaterial3D> base_mat = res;
+ Ref<ShaderMaterial> shader_mat = res;
+
+ if (base_mat.is_null() && !shader_mat.is_null()) {
+ break;
+ }
+
+ spatial_editor->set_preview_material(mat);
+ break;
+ } else if (tex.is_valid()) {
+ Ref<StandardMaterial3D> new_mat = memnew(StandardMaterial3D);
+ new_mat->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, tex);
+
+ spatial_editor->set_preview_material(new_mat);
+ break;
+ } else {
+ continue;
}
can_instantiate = true;
break;
}
}
if (can_instantiate) {
- _create_preview(files);
+ _create_preview_node(files);
}
}
} else {
- can_instantiate = true;
+ if (preview_node->is_inside_tree()) {
+ can_instantiate = true;
+ }
}
if (can_instantiate) {
Transform3D global_transform = Transform3D(Basis(), _get_instance_position(p_point));
preview_node->set_global_transform(global_transform);
+ return true;
}
- return can_instantiate;
+ if (spatial_editor->get_preview_material().is_valid()) {
+ preview_material_label->show();
+ preview_material_label_desc->show();
+
+ ObjectID new_preview_material_target = _select_ray(p_point);
+ return _apply_preview_material(new_preview_material_target, p_point);
+ }
+
+ return false;
}
void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
@@ -4038,7 +4214,7 @@ void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_
} else {
accept->set_text(TTR("Cannot drag and drop into multiple selected nodes."));
accept->popup_centered();
- _remove_preview();
+ _remove_preview_node();
return;
}
@@ -4440,7 +4616,7 @@ void Node3DEditorViewport::register_shortcut_action(const String &p_path, const
Ref<Shortcut> sc = ED_SHORTCUT(p_path, p_name, p_keycode);
shortcut_changed_callback(sc, p_path);
// Connect to the change event on the shortcut so the input binding can be updated.
- sc->connect("changed", callable_mp(this, &Node3DEditorViewport::shortcut_changed_callback), varray(sc, p_path));
+ sc->connect("changed", callable_mp(this, &Node3DEditorViewport::shortcut_changed_callback).bind(sc, p_path));
}
// Update the action in the InputMap to the provided shortcut events.
@@ -4485,7 +4661,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
subviewport_container = c;
c->set_stretch(true);
add_child(c);
- c->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ c->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
viewport = memnew(SubViewport);
viewport->set_disable_input(true);
@@ -4493,7 +4669,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
surface = memnew(Control);
surface->set_drag_forwarding(this);
add_child(surface);
- surface->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ surface->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
surface->set_clip_contents(true);
camera = memnew(Camera3D);
camera->set_disable_gizmos(true);
@@ -4514,6 +4690,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 +4714,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);
@@ -4687,12 +4865,29 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
zoom_limit_label->hide();
surface->add_child(zoom_limit_label);
+ preview_material_label = memnew(Label);
+ preview_material_label->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT);
+ preview_material_label->set_offset(Side::SIDE_TOP, -70 * EDSCALE);
+ preview_material_label->set_text(TTR("Overriding material..."));
+ preview_material_label->add_theme_color_override("font_color", Color(1, 1, 1, 1));
+ preview_material_label->hide();
+ surface->add_child(preview_material_label);
+
+ preview_material_label_desc = memnew(Label);
+ preview_material_label_desc->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT);
+ preview_material_label_desc->set_offset(Side::SIDE_TOP, -50 * EDSCALE);
+ preview_material_label_desc->set_text(TTR("Drag and drop to override the material of any geometry node.\nHold Ctrl when dropping to override a specific surface."));
+ preview_material_label_desc->add_theme_color_override("font_color", Color(0.8, 0.8, 0.8, 1));
+ preview_material_label_desc->add_theme_constant_override("line_spacing", 0);
+ preview_material_label_desc->hide();
+ surface->add_child(preview_material_label_desc);
+
frame_time_gradient = memnew(Gradient);
// The color is set when the theme changes.
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 +5383,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 +5403,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 +6192,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);
}
@@ -6208,7 +6408,7 @@ void fragment() {
Ref<ShaderMaterial> rotate_mat = memnew(ShaderMaterial);
rotate_mat->set_render_priority(Material::RENDER_PRIORITY_MAX);
rotate_mat->set_shader(rotate_shader);
- rotate_mat->set_shader_param("albedo", col);
+ rotate_mat->set_shader_uniform("albedo", col);
rotate_gizmo_color[i] = rotate_mat;
Array arrays = surftool->commit_to_arrays();
@@ -6216,7 +6416,7 @@ void fragment() {
rotate_gizmo[i]->surface_set_material(0, rotate_mat);
Ref<ShaderMaterial> rotate_mat_hl = rotate_mat->duplicate();
- rotate_mat_hl->set_shader_param("albedo", albedo);
+ rotate_mat_hl->set_shader_uniform("albedo", albedo);
rotate_gizmo_color_hl[i] = rotate_mat_hl;
if (i == 2) { // Rotation white outline
@@ -6257,7 +6457,7 @@ void fragment() {
)");
border_mat->set_shader(border_shader);
- border_mat->set_shader_param("albedo", Color(0.75, 0.75, 0.75, col.a / 3.0));
+ border_mat->set_shader_uniform("albedo", Color(0.75, 0.75, 0.75, col.a / 3.0));
rotate_gizmo[3] = Ref<ArrayMesh>(memnew(ArrayMesh));
rotate_gizmo[3]->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arrays);
@@ -6510,8 +6710,8 @@ void Node3DEditor::_init_grid() {
fade_size = CLAMP(fade_size, min_fade_size, max_fade_size);
real_t grid_fade_size = (grid_size - primary_grid_steps) * fade_size;
- grid_mat[c]->set_shader_param("grid_size", grid_fade_size);
- grid_mat[c]->set_shader_param("orthogonal", orthogonal);
+ grid_mat[c]->set_shader_uniform("grid_size", grid_fade_size);
+ grid_mat[c]->set_shader_uniform("orthogonal", orthogonal);
// Cache these so we don't have to re-access memory.
Vector<Vector3> &ref_grid = grid_points[c];
@@ -6603,6 +6803,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);
}
}
@@ -6621,7 +6822,7 @@ void Node3DEditor::_finish_grid() {
}
void Node3DEditor::update_grid() {
- const Camera3D::Projection current_projection = viewports[0]->camera->get_projection();
+ const Camera3D::ProjectionType current_projection = viewports[0]->camera->get_projection();
if (current_projection != grid_camera_last_update_perspective) {
grid_init_draw = false; // redraw
@@ -6966,7 +7167,7 @@ void Node3DEditor::_update_theme() {
environ_sky_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor"))));
environ_ground_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor"))));
- context_menu_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles")));
+ context_menu_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles")));
}
void Node3DEditor::_notification(int p_what) {
@@ -6981,8 +7182,8 @@ void Node3DEditor::_notification(int p_what) {
SceneTreeDock::get_singleton()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_selection_changed));
- EditorNode::get_singleton()->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false));
- EditorNode::get_singleton()->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(true));
+ EditorNode::get_singleton()->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button).bind(false));
+ EditorNode::get_singleton()->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button).bind(true));
_update_preview_environment();
@@ -7055,11 +7256,11 @@ Vector<int> Node3DEditor::get_subgizmo_selection() {
}
void Node3DEditor::add_control_to_menu_panel(Control *p_control) {
- hbc_context_menu->add_child(p_control);
+ context_menu_hbox->add_child(p_control);
}
void Node3DEditor::remove_control_from_menu_panel(Control *p_control) {
- hbc_context_menu->remove_child(p_control);
+ context_menu_hbox->remove_child(p_control);
}
void Node3DEditor::set_can_preview(Camera3D *p_preview) {
@@ -7216,7 +7417,7 @@ void Node3DEditor::_toggle_maximize_view(Object *p_viewport) {
if (!maximized) {
for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) {
if (i == (uint32_t)index) {
- viewports[i]->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ viewports[i]->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
} else {
viewports[i]->hide();
}
@@ -7296,6 +7497,7 @@ void Node3DEditor::_register_all_gizmos() {
add_gizmo_plugin(Ref<Label3DGizmoPlugin>(memnew(Label3DGizmoPlugin)));
add_gizmo_plugin(Ref<Position3DGizmoPlugin>(memnew(Position3DGizmoPlugin)));
add_gizmo_plugin(Ref<RayCast3DGizmoPlugin>(memnew(RayCast3DGizmoPlugin)));
+ add_gizmo_plugin(Ref<ShapeCast3DGizmoPlugin>(memnew(ShapeCast3DGizmoPlugin)));
add_gizmo_plugin(Ref<SpringArm3DGizmoPlugin>(memnew(SpringArm3DGizmoPlugin)));
add_gizmo_plugin(Ref<VehicleWheel3DGizmoPlugin>(memnew(VehicleWheel3DGizmoPlugin)));
add_gizmo_plugin(Ref<VisibleOnScreenNotifier3DGizmoPlugin>(memnew(VisibleOnScreenNotifier3DGizmoPlugin)));
@@ -7357,9 +7559,9 @@ void Node3DEditor::_sun_direction_draw() {
sun_direction->draw_rect(Rect2(Vector2(), sun_direction->get_size()), Color(1, 1, 1, 1));
Vector3 z_axis = preview_sun->get_transform().basis.get_column(Vector3::AXIS_Z);
z_axis = get_editor_viewport(0)->camera->get_camera_transform().basis.xform_inv(z_axis);
- sun_direction_material->set_shader_param("sun_direction", Vector3(z_axis.x, -z_axis.y, z_axis.z));
+ sun_direction_material->set_shader_uniform("sun_direction", Vector3(z_axis.x, -z_axis.y, z_axis.z));
Color color = sun_color->get_pick_color() * sun_energy->get_value();
- sun_direction_material->set_shader_param("sun_color", Vector3(color.r, color.g, color.b));
+ sun_direction_material->set_shader_uniform("sun_color", Vector3(color.r, color.g, color.b));
}
void Node3DEditor::_preview_settings_changed() {
@@ -7512,163 +7714,155 @@ Node3DEditor::Node3DEditor() {
camera_override_viewport_id = 0;
- hbc_menu = memnew(HBoxContainer);
- vbc->add_child(hbc_menu);
+ // A fluid container for all toolbars.
+ HFlowContainer *main_flow = memnew(HFlowContainer);
+ vbc->add_child(main_flow);
+
+ // Main toolbars.
+ HBoxContainer *main_menu_hbox = memnew(HBoxContainer);
+ main_flow->add_child(main_menu_hbox);
- Vector<Variant> button_binds;
- button_binds.resize(1);
String sct;
// Add some margin to the left for better aesthetics.
// This prevents the first button's hover/pressed effect from "touching" the panel's border,
// which looks ugly.
Control *margin_left = memnew(Control);
- hbc_menu->add_child(margin_left);
+ main_menu_hbox->add_child(margin_left);
margin_left->set_custom_minimum_size(Size2(2, 0) * EDSCALE);
tool_button[TOOL_MODE_SELECT] = memnew(Button);
- hbc_menu->add_child(tool_button[TOOL_MODE_SELECT]);
+ main_menu_hbox->add_child(tool_button[TOOL_MODE_SELECT]);
tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true);
tool_button[TOOL_MODE_SELECT]->set_flat(true);
tool_button[TOOL_MODE_SELECT]->set_pressed(true);
- button_binds.write[0] = MENU_TOOL_SELECT;
- tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
+ tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SELECT));
tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), Key::Q));
tool_button[TOOL_MODE_SELECT]->set_shortcut_context(this);
tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
- hbc_menu->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
tool_button[TOOL_MODE_MOVE] = memnew(Button);
- hbc_menu->add_child(tool_button[TOOL_MODE_MOVE]);
+ main_menu_hbox->add_child(tool_button[TOOL_MODE_MOVE]);
tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true);
tool_button[TOOL_MODE_MOVE]->set_flat(true);
- button_binds.write[0] = MENU_TOOL_MOVE;
- tool_button[TOOL_MODE_MOVE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
+
+ tool_button[TOOL_MODE_MOVE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_MOVE));
tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), Key::W));
tool_button[TOOL_MODE_MOVE]->set_shortcut_context(this);
tool_button[TOOL_MODE_ROTATE] = memnew(Button);
- hbc_menu->add_child(tool_button[TOOL_MODE_ROTATE]);
+ main_menu_hbox->add_child(tool_button[TOOL_MODE_ROTATE]);
tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true);
tool_button[TOOL_MODE_ROTATE]->set_flat(true);
- button_binds.write[0] = MENU_TOOL_ROTATE;
- tool_button[TOOL_MODE_ROTATE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
+ tool_button[TOOL_MODE_ROTATE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_ROTATE));
tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), Key::E));
tool_button[TOOL_MODE_ROTATE]->set_shortcut_context(this);
tool_button[TOOL_MODE_SCALE] = memnew(Button);
- hbc_menu->add_child(tool_button[TOOL_MODE_SCALE]);
+ main_menu_hbox->add_child(tool_button[TOOL_MODE_SCALE]);
tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true);
tool_button[TOOL_MODE_SCALE]->set_flat(true);
- button_binds.write[0] = MENU_TOOL_SCALE;
- tool_button[TOOL_MODE_SCALE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
+ tool_button[TOOL_MODE_SCALE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SCALE));
tool_button[TOOL_MODE_SCALE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_scale", TTR("Scale Mode"), Key::R));
tool_button[TOOL_MODE_SCALE]->set_shortcut_context(this);
- hbc_menu->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
tool_button[TOOL_MODE_LIST_SELECT] = memnew(Button);
- hbc_menu->add_child(tool_button[TOOL_MODE_LIST_SELECT]);
+ main_menu_hbox->add_child(tool_button[TOOL_MODE_LIST_SELECT]);
tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true);
tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true);
- button_binds.write[0] = MENU_TOOL_LIST_SELECT;
- tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
+ tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_LIST_SELECT));
tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show list of selectable nodes at position clicked."));
tool_button[TOOL_LOCK_SELECTED] = memnew(Button);
- hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]);
+ main_menu_hbox->add_child(tool_button[TOOL_LOCK_SELECTED]);
tool_button[TOOL_LOCK_SELECTED]->set_flat(true);
- button_binds.write[0] = MENU_LOCK_SELECTED;
- tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
+ tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_LOCK_SELECTED));
tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock selected node, preventing selection and movement."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L));
tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button);
- hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]);
+ main_menu_hbox->add_child(tool_button[TOOL_UNLOCK_SELECTED]);
tool_button[TOOL_UNLOCK_SELECTED]->set_flat(true);
- button_binds.write[0] = MENU_UNLOCK_SELECTED;
- tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
+ tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNLOCK_SELECTED));
tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock selected node, allowing selection and movement."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L));
tool_button[TOOL_GROUP_SELECTED] = memnew(Button);
- hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]);
+ main_menu_hbox->add_child(tool_button[TOOL_GROUP_SELECTED]);
tool_button[TOOL_GROUP_SELECTED]->set_flat(true);
- button_binds.write[0] = MENU_GROUP_SELECTED;
- tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
- tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable."));
+ tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_GROUP_SELECTED));
+ tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Make selected node's children not selectable."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G));
tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button);
- hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]);
+ main_menu_hbox->add_child(tool_button[TOOL_UNGROUP_SELECTED]);
tool_button[TOOL_UNGROUP_SELECTED]->set_flat(true);
- button_binds.write[0] = MENU_UNGROUP_SELECTED;
- tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
- tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Restores the object's children's ability to be selected."));
+ tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNGROUP_SELECTED));
+ tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Make selected node's children selectable."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G));
- hbc_menu->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
tool_option_button[TOOL_OPT_LOCAL_COORDS] = memnew(Button);
- hbc_menu->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]);
+ main_menu_hbox->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]);
tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_toggle_mode(true);
tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_flat(true);
- button_binds.write[0] = MENU_TOOL_LOCAL_COORDS;
- tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds);
+ tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled).bind(MENU_TOOL_LOCAL_COORDS));
tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Use Local Space"), Key::T));
tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut_context(this);
tool_option_button[TOOL_OPT_USE_SNAP] = memnew(Button);
- hbc_menu->add_child(tool_option_button[TOOL_OPT_USE_SNAP]);
+ main_menu_hbox->add_child(tool_option_button[TOOL_OPT_USE_SNAP]);
tool_option_button[TOOL_OPT_USE_SNAP]->set_toggle_mode(true);
tool_option_button[TOOL_OPT_USE_SNAP]->set_flat(true);
- button_binds.write[0] = MENU_TOOL_USE_SNAP;
- tool_option_button[TOOL_OPT_USE_SNAP]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds);
+ tool_option_button[TOOL_OPT_USE_SNAP]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled).bind(MENU_TOOL_USE_SNAP));
tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut(ED_SHORTCUT("spatial_editor/snap", TTR("Use Snap"), Key::Y));
tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut_context(this);
- hbc_menu->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(Button);
- hbc_menu->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]);
+ main_menu_hbox->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]);
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_toggle_mode(true);
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_flat(true);
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_disabled(true);
- button_binds.write[0] = MENU_TOOL_OVERRIDE_CAMERA;
- tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds);
+ tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled).bind(MENU_TOOL_OVERRIDE_CAMERA));
_update_camera_override_button(false);
- hbc_menu->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
sun_button = memnew(Button);
sun_button->set_tooltip(TTR("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled."));
sun_button->set_toggle_mode(true);
sun_button->set_flat(true);
- sun_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), varray(), CONNECT_DEFERRED);
+ sun_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED);
sun_button->set_disabled(true);
- hbc_menu->add_child(sun_button);
+ main_menu_hbox->add_child(sun_button);
environ_button = memnew(Button);
environ_button->set_tooltip(TTR("Toggle preview environment.\nIf a WorldEnvironment node is added to the scene, preview environment is disabled."));
environ_button->set_toggle_mode(true);
environ_button->set_flat(true);
- environ_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), varray(), CONNECT_DEFERRED);
+ environ_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED);
environ_button->set_disabled(true);
- hbc_menu->add_child(environ_button);
+ main_menu_hbox->add_child(environ_button);
sun_environ_settings = memnew(Button);
sun_environ_settings->set_tooltip(TTR("Edit Sun and Environment settings."));
sun_environ_settings->set_flat(true);
sun_environ_settings->connect("pressed", callable_mp(this, &Node3DEditor::_sun_environ_settings_pressed));
- hbc_menu->add_child(sun_environ_settings);
+ main_menu_hbox->add_child(sun_environ_settings);
- hbc_menu->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
// Drag and drop support;
preview_node = memnew(Node3D);
@@ -7702,7 +7896,7 @@ Node3DEditor::Node3DEditor() {
transform_menu->set_text(TTR("Transform"));
transform_menu->set_switch_on_hover(true);
transform_menu->set_shortcut_context(this);
- hbc_menu->add_child(transform_menu);
+ main_menu_hbox->add_child(transform_menu);
p = transform_menu->get_popup();
p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap Object to Floor"), Key::PAGEDOWN), MENU_SNAP_TO_FLOOR);
@@ -7718,14 +7912,14 @@ Node3DEditor::Node3DEditor() {
view_menu->set_text(TTR("View"));
view_menu->set_switch_on_hover(true);
view_menu->set_shortcut_context(this);
- hbc_menu->add_child(view_menu);
+ main_menu_hbox->add_child(view_menu);
- hbc_menu->add_child(memnew(VSeparator));
+ main_menu_hbox->add_child(memnew(VSeparator));
- context_menu_container = memnew(PanelContainer);
- hbc_context_menu = memnew(HBoxContainer);
- context_menu_container->add_child(hbc_context_menu);
- hbc_menu->add_child(context_menu_container);
+ context_menu_panel = memnew(PanelContainer);
+ context_menu_hbox = memnew(HBoxContainer);
+ context_menu_panel->add_child(context_menu_hbox);
+ main_flow->add_child(context_menu_panel);
// Get the view menu popup and have it stay open when a checkable item is selected
p = view_menu->get_popup();
@@ -7843,7 +8037,7 @@ Node3DEditor::Node3DEditor() {
settings_vbc->add_margin_child(TTR("View Z-Far:"), settings_zfar);
for (uint32_t i = 0; i < VIEWPORTS_COUNT; ++i) {
- settings_dialog->connect("confirmed", callable_mp(viewports[i], &Node3DEditorViewport::_view_settings_confirmed), varray(0.0));
+ settings_dialog->connect("confirmed", callable_mp(viewports[i], &Node3DEditorViewport::_view_settings_confirmed).bind(0.0));
}
/* XFORM DIALOG */
@@ -7968,8 +8162,8 @@ void fragment() {
)");
sun_direction_material.instantiate();
sun_direction_material->set_shader(sun_direction_shader);
- sun_direction_material->set_shader_param("sun_direction", Vector3(0, 0, 1));
- sun_direction_material->set_shader_param("sun_color", Vector3(1, 1, 1));
+ sun_direction_material->set_shader_uniform("sun_direction", Vector3(0, 0, 1));
+ sun_direction_material->set_shader_uniform("sun_color", Vector3(1, 1, 1));
sun_direction->set_material(sun_direction_material);
HBoxContainer *sun_angle_hbox = memnew(HBoxContainer);
@@ -8005,6 +8199,7 @@ void fragment() {
sun_color->set_edit_alpha(false);
sun_vb->add_margin_child(TTR("Sun Color"), sun_color);
sun_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ sun_color->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(sun_color->get_picker()));
sun_energy = memnew(EditorSpinSlider);
sun_vb->add_margin_child(TTR("Sun Energy"), sun_energy);
@@ -8020,7 +8215,7 @@ void fragment() {
sun_add_to_scene = memnew(Button);
sun_add_to_scene->set_text(TTR("Add Sun to Scene"));
sun_add_to_scene->set_tooltip(TTR("Adds a DirectionalLight3D node matching the preview sun settings to the current scene.\nHold Shift while clicking to also add the preview environment to the current scene."));
- sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene), varray(false));
+ sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene).bind(false));
sun_vb->add_spacer();
sun_vb->add_child(sun_add_to_scene);
@@ -8050,10 +8245,12 @@ void fragment() {
environ_sky_color = memnew(ColorPickerButton);
environ_sky_color->set_edit_alpha(false);
environ_sky_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ environ_sky_color->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(environ_sky_color->get_picker()));
environ_vb->add_margin_child(TTR("Sky Color"), environ_sky_color);
environ_ground_color = memnew(ColorPickerButton);
environ_ground_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
environ_ground_color->set_edit_alpha(false);
+ environ_ground_color->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(environ_ground_color->get_picker()));
environ_vb->add_margin_child(TTR("Ground Color"), environ_ground_color);
environ_energy = memnew(EditorSpinSlider);
environ_energy->connect("value_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
@@ -8065,29 +8262,29 @@ void fragment() {
environ_ao_button = memnew(Button);
environ_ao_button->set_text(TTR("AO"));
environ_ao_button->set_toggle_mode(true);
- environ_ao_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ environ_ao_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), CONNECT_DEFERRED);
fx_vb->add_child(environ_ao_button);
environ_glow_button = memnew(Button);
environ_glow_button->set_text(TTR("Glow"));
environ_glow_button->set_toggle_mode(true);
- environ_glow_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ environ_glow_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), CONNECT_DEFERRED);
fx_vb->add_child(environ_glow_button);
environ_tonemap_button = memnew(Button);
environ_tonemap_button->set_text(TTR("Tonemap"));
environ_tonemap_button->set_toggle_mode(true);
- environ_tonemap_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ environ_tonemap_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), CONNECT_DEFERRED);
fx_vb->add_child(environ_tonemap_button);
environ_gi_button = memnew(Button);
environ_gi_button->set_text(TTR("GI"));
environ_gi_button->set_toggle_mode(true);
- environ_gi_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ environ_gi_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), CONNECT_DEFERRED);
fx_vb->add_child(environ_gi_button);
environ_vb->add_margin_child(TTR("Post Process"), fx_vb);
environ_add_to_scene = memnew(Button);
environ_add_to_scene->set_text(TTR("Add Environment to Scene"));
environ_add_to_scene->set_tooltip(TTR("Adds a WorldEnvironment node matching the preview environment settings to the current scene.\nHold Shift while clicking to also add the preview sun to the current scene."));
- environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene), varray(false));
+ environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene).bind(false));
environ_vb->add_spacer();
environ_vb->add_child(environ_add_to_scene);
@@ -8114,7 +8311,6 @@ void fragment() {
_preview_settings_changed();
}
}
-
Node3DEditor::~Node3DEditor() {
memdelete(preview_node);
}
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 8a602be08b..4469271a38 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -227,6 +227,9 @@ private:
Label *locked_label = nullptr;
Label *zoom_limit_label = nullptr;
+ Label *preview_material_label = nullptr;
+ Label *preview_material_label_desc = nullptr;
+
VBoxContainer *top_right_vbox = nullptr;
ViewportRotationControl *rotation_control = nullptr;
Gradient *frame_time_gradient = nullptr;
@@ -244,7 +247,7 @@ private:
void _compute_edit(const Point2 &p_point);
void _clear_selected();
void _select_clicked(bool p_allow_locked);
- ObjectID _select_ray(const Point2 &p_pos);
+ ObjectID _select_ray(const Point2 &p_pos) const;
void _find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked);
Vector3 _get_ray_pos(const Vector2 &p_pos) const;
Vector3 _get_ray(const Vector2 &p_pos) const;
@@ -272,6 +275,7 @@ private:
float get_fov() const;
ObjectID clicked;
+ ObjectID material_target;
Vector<_RayResult> selection_results;
bool clicked_wants_append = false;
bool selection_in_progress = false;
@@ -399,8 +403,11 @@ private:
Node *_sanitize_preview_node(Node *p_node) const;
- void _create_preview(const Vector<String> &files) const;
- void _remove_preview();
+ void _create_preview_node(const Vector<String> &files) const;
+ void _remove_preview_node();
+ bool _apply_preview_material(ObjectID p_target, const Point2 &p_point) const;
+ void _reset_preview_material() const;
+ void _remove_preview_material();
bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
bool _create_instance(Node *parent, String &path, const Point2 &p_point);
void _perform_drop_data();
@@ -560,7 +567,7 @@ private:
bool grid_enable[3]; //should be always visible if true
bool grid_enabled = false;
bool grid_init_draw = false;
- Camera3D::Projection grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;
+ Camera3D::ProjectionType grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;
Vector3 grid_camera_last_update_position = Vector3();
Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3], axis_gizmo[3];
@@ -593,6 +600,11 @@ private:
Node3D *preview_node = nullptr;
AABB preview_bounds;
+ Ref<Material> preview_material;
+ Ref<Material> preview_reset_material;
+ ObjectID preview_material_target;
+ int preview_material_surface = -1;
+
struct Gizmo {
bool visible = false;
real_t scale = 0;
@@ -664,11 +676,10 @@ private:
void _menu_gizmo_toggled(int p_option);
void _update_camera_override_button(bool p_game_running);
void _update_camera_override_viewport(Object *p_viewport);
- HBoxContainer *hbc_menu = nullptr;
// Used for secondary menu items which are displayed depending on the currently selected node
// (such as MeshInstance's "Mesh" menu).
- PanelContainer *context_menu_container = nullptr;
- HBoxContainer *hbc_context_menu = nullptr;
+ PanelContainer *context_menu_panel = nullptr;
+ HBoxContainer *context_menu_hbox = nullptr;
void _generate_selection_boxes();
UndoRedo *undo_redo = nullptr;
@@ -851,6 +862,15 @@ public:
void set_can_preview(Camera3D *p_preview);
+ void set_preview_material(Ref<Material> p_material) { preview_material = p_material; }
+ Ref<Material> get_preview_material() { return preview_material; }
+ void set_preview_reset_material(Ref<Material> p_material) { preview_reset_material = p_material; }
+ Ref<Material> get_preview_reset_material() const { return preview_reset_material; }
+ void set_preview_material_target(ObjectID p_object_id) { preview_material_target = p_object_id; }
+ ObjectID get_preview_material_target() const { return preview_material_target; }
+ void set_preview_material_surface(int p_surface) { preview_material_surface = p_surface; }
+ int get_preview_material_surface() const { return preview_material_surface; }
+
Node3DEditorViewport *get_editor_viewport(int p_idx) {
ERR_FAIL_INDEX_V(p_idx, static_cast<int>(VIEWPORTS_COUNT), nullptr);
return viewports[p_idx];
diff --git a/editor/plugins/occluder_instance_3d_editor_plugin.cpp b/editor/plugins/occluder_instance_3d_editor_plugin.cpp
index d5fc51aea4..365f74d7a3 100644
--- a/editor/plugins/occluder_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/occluder_instance_3d_editor_plugin.cpp
@@ -113,7 +113,7 @@ OccluderInstance3DEditorPlugin::OccluderInstance3DEditorPlugin() {
file_dialog = memnew(EditorFileDialog);
file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- file_dialog->add_filter("*.occ ; Occluder3D");
+ file_dialog->add_filter("*.occ", "Occluder3D");
file_dialog->set_title(TTR("Select occluder bake file:"));
file_dialog->connect("file_selected", callable_mp(this, &OccluderInstance3DEditorPlugin::_bake_select_file));
bake->add_child(file_dialog);
diff --git a/editor/plugins/occluder_instance_3d_editor_plugin.h b/editor/plugins/occluder_instance_3d_editor_plugin.h
index 360b7297cf..e8d98927f4 100644
--- a/editor/plugins/occluder_instance_3d_editor_plugin.h
+++ b/editor/plugins/occluder_instance_3d_editor_plugin.h
@@ -63,4 +63,4 @@ public:
~OccluderInstance3DEditorPlugin();
};
-#endif
+#endif // OCCLUDER_INSTANCE_3D_EDITOR_PLUGIN_H
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/ot_features_plugin.h b/editor/plugins/ot_features_plugin.h
deleted file mode 100644
index 6639148080..0000000000
--- a/editor/plugins/ot_features_plugin.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*************************************************************************/
-/* ot_features_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 "editor/editor_plugin.h"
-#include "editor/editor_properties.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();
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- virtual void update_property() override;
- OpenTypeFeaturesEditor();
-};
-
-/*************************************************************************/
-
-class OpenTypeFeaturesAdd : public Button {
- GDCLASS(OpenTypeFeaturesAdd, Button);
-
- Object *edited_object = nullptr;
- PopupMenu *menu = nullptr;
- PopupMenu *menu_ss = nullptr;
- PopupMenu *menu_cv = nullptr;
- PopupMenu *menu_cu = nullptr;
-
- void _add_feature(int p_option);
- void _features_menu();
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- void setup(Object *p_object);
-
- OpenTypeFeaturesAdd();
-};
-
-/*************************************************************************/
-
-class EditorInspectorPluginOpenTypeFeatures : public EditorInspectorPlugin {
- GDCLASS(EditorInspectorPluginOpenTypeFeatures, 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 OpenTypeFeaturesEditorPlugin : public EditorPlugin {
- GDCLASS(OpenTypeFeaturesEditorPlugin, EditorPlugin);
-
-public:
- OpenTypeFeaturesEditorPlugin();
-
- virtual String get_name() const override { return "OpenTypeFeatures"; }
-};
-
-#endif // OT_FEATURES_PLUGIN_H
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index 9e666ef70a..fd331c4127 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -537,7 +537,7 @@ Path2DEditor::Path2DEditor() {
curve_edit->set_toggle_mode(true);
curve_edit->set_focus_mode(Control::FOCUS_NONE);
curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point"));
- curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT));
+ curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_EDIT));
base_hb->add_child(curve_edit);
curve_edit_curve = memnew(Button);
@@ -545,7 +545,7 @@ Path2DEditor::Path2DEditor() {
curve_edit_curve->set_toggle_mode(true);
curve_edit_curve->set_focus_mode(Control::FOCUS_NONE);
curve_edit_curve->set_tooltip(TTR("Select Control Points (Shift+Drag)"));
- curve_edit_curve->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT_CURVE));
+ curve_edit_curve->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_EDIT_CURVE));
base_hb->add_child(curve_edit_curve);
curve_create = memnew(Button);
@@ -553,7 +553,7 @@ Path2DEditor::Path2DEditor() {
curve_create->set_toggle_mode(true);
curve_create->set_focus_mode(Control::FOCUS_NONE);
curve_create->set_tooltip(TTR("Add Point (in empty space)"));
- curve_create->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_CREATE));
+ curve_create->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_CREATE));
base_hb->add_child(curve_create);
curve_del = memnew(Button);
@@ -561,14 +561,14 @@ Path2DEditor::Path2DEditor() {
curve_del->set_toggle_mode(true);
curve_del->set_focus_mode(Control::FOCUS_NONE);
curve_del->set_tooltip(TTR("Delete Point"));
- curve_del->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_DELETE));
+ curve_del->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_DELETE));
base_hb->add_child(curve_del);
curve_close = memnew(Button);
curve_close->set_flat(true);
curve_close->set_focus_mode(Control::FOCUS_NONE);
curve_close->set_tooltip(TTR("Close Curve"));
- curve_close->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(ACTION_CLOSE));
+ curve_close->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(ACTION_CLOSE));
base_hb->add_child(curve_close);
PopupMenu *menu;
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index 36f559b2ae..65b15a6001 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -34,6 +34,7 @@
#include "core/math/geometry_3d.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
#include "node_3d_editor_plugin.h"
#include "scene/resources/curve.h"
@@ -557,9 +558,9 @@ void Path3DEditorPlugin::_update_theme() {
void Path3DEditorPlugin::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- curve_create->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed), make_binds(0));
- curve_edit->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed), make_binds(1));
- curve_del->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed), make_binds(2));
+ curve_create->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed).bind(0));
+ curve_edit->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed).bind(1));
+ curve_del->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed).bind(2));
curve_close->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_close_curve));
_update_theme();
diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h
index ee31fcf43d..53e4e2efa8 100644
--- a/editor/plugins/path_3d_editor_plugin.h
+++ b/editor/plugins/path_3d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PATH_EDITOR_PLUGIN_H
-#define PATH_EDITOR_PLUGIN_H
+#ifndef PATH_3D_EDITOR_PLUGIN_H
+#define PATH_3D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "editor/plugins/node_3d_editor_gizmos.h"
@@ -118,4 +118,4 @@ public:
~Path3DEditorPlugin();
};
-#endif // PATH_EDITOR_PLUGIN_H
+#endif // PATH_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.h b/editor/plugins/physical_bone_3d_editor_plugin.h
index 93e722a432..f15eab7991 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.h
+++ b/editor/plugins/physical_bone_3d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PHYSICAL_BONE_PLUGIN_H
-#define PHYSICAL_BONE_PLUGIN_H
+#ifndef PHYSICAL_BONE_3D_EDITOR_PLUGIN_H
+#define PHYSICAL_BONE_3D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/3d/physics_body_3d.h"
@@ -76,4 +76,4 @@ public:
PhysicalBone3DEditorPlugin();
};
-#endif
+#endif // PHYSICAL_BONE_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index a682bb455c..4f46c99a04 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -192,7 +192,7 @@ void Polygon2DEditor::_update_bone_list() {
cb->set_pressed(true);
}
- cb->connect("pressed", callable_mp(this, &Polygon2DEditor::_bone_paint_selected), varray(i));
+ cb->connect("pressed", callable_mp(this, &Polygon2DEditor::_bone_paint_selected).bind(i));
}
uv_edit_draw->update();
@@ -1238,7 +1238,7 @@ Polygon2DEditor::Polygon2DEditor() {
button_uv->set_flat(true);
add_child(button_uv);
button_uv->set_tooltip(TTR("Open Polygon 2D UV editor."));
- button_uv->connect("pressed", callable_mp(this, &Polygon2DEditor::_menu_option), varray(MODE_EDIT_UV));
+ button_uv->connect("pressed", callable_mp(this, &Polygon2DEditor::_menu_option).bind(MODE_EDIT_UV));
uv_mode = UV_MODE_EDIT_POINT;
uv_edit = memnew(AcceptDialog);
@@ -1276,10 +1276,10 @@ Polygon2DEditor::Polygon2DEditor() {
uv_edit_mode[2]->set_button_group(uv_edit_group);
uv_edit_mode[3]->set_button_group(uv_edit_group);
- uv_edit_mode[0]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(0));
- uv_edit_mode[1]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(1));
- uv_edit_mode[2]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(2));
- uv_edit_mode[3]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(3));
+ uv_edit_mode[0]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(0));
+ uv_edit_mode[1]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(1));
+ uv_edit_mode[2]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(2));
+ uv_edit_mode[3]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(3));
uv_mode_hb->add_child(memnew(VSeparator));
@@ -1289,7 +1289,7 @@ Polygon2DEditor::Polygon2DEditor() {
uv_button[i]->set_flat(true);
uv_button[i]->set_toggle_mode(true);
uv_mode_hb->add_child(uv_button[i]);
- uv_button[i]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_mode), varray(i));
+ uv_button[i]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_mode).bind(i));
uv_button[i]->set_focus_mode(FOCUS_NONE);
}
diff --git a/editor/plugins/polygon_3d_editor_plugin.cpp b/editor/plugins/polygon_3d_editor_plugin.cpp
index 1c69e0d635..83092f990f 100644
--- a/editor/plugins/polygon_3d_editor_plugin.cpp
+++ b/editor/plugins/polygon_3d_editor_plugin.cpp
@@ -532,13 +532,13 @@ Polygon3DEditor::Polygon3DEditor() {
button_create = memnew(Button);
button_create->set_flat(true);
add_child(button_create);
- button_create->connect("pressed", callable_mp(this, &Polygon3DEditor::_menu_option), varray(MODE_CREATE));
+ button_create->connect("pressed", callable_mp(this, &Polygon3DEditor::_menu_option).bind(MODE_CREATE));
button_create->set_toggle_mode(true);
button_edit = memnew(Button);
button_edit->set_flat(true);
add_child(button_edit);
- button_edit->connect("pressed", callable_mp(this, &Polygon3DEditor::_menu_option), varray(MODE_EDIT));
+ button_edit->connect("pressed", callable_mp(this, &Polygon3DEditor::_menu_option).bind(MODE_EDIT));
button_edit->set_toggle_mode(true);
mode = MODE_EDIT;
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index 79fc304242..4e528ef066 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -57,7 +57,7 @@ void ResourcePreloaderEditor::_files_load_request(const Vector<String> &p_paths)
dialog->set_text(TTR("ERROR: Couldn't load resource!"));
dialog->set_title(TTR("Error!"));
//dialog->get_cancel()->set_text("Close");
- dialog->get_ok_button()->set_text(TTR("Close"));
+ dialog->set_ok_button_text(TTR("Close"));
dialog->popup_centered();
return; ///beh should show an error i guess
}
@@ -139,7 +139,7 @@ void ResourcePreloaderEditor::_paste_pressed() {
if (!r.is_valid()) {
dialog->set_text(TTR("Resource clipboard is empty!"));
dialog->set_title(TTR("Error!"));
- dialog->get_ok_button()->set_text(TTR("Close"));
+ dialog->set_ok_button_text(TTR("Close"));
dialog->popup_centered();
return; ///beh should show an error i guess
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 6ab2366a44..c53ac59c11 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -41,6 +41,7 @@
#include "editor/debugger/script_editor_debugger.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
#include "editor/editor_run_script.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -377,7 +378,7 @@ ScriptEditorQuickOpen::ScriptEditorQuickOpen() {
search_box->connect("gui_input", callable_mp(this, &ScriptEditorQuickOpen::_sbox_input));
search_options = memnew(Tree);
vbc->add_margin_child(TTR("Matches:"), search_options, true);
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
get_ok_button()->set_disabled(true);
register_text_enter(search_box);
set_hide_on_ok(false);
@@ -590,7 +591,7 @@ void ScriptEditor::_go_to_tab(int p_idx) {
}
}
- Control *c = Object::cast_to<Control>(tab_container->get_tab_control(p_idx));
+ Control *c = tab_container->get_tab_control(p_idx);
if (!c) {
return;
}
@@ -812,7 +813,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) {
if (history_pos >= 0) {
idx = tab_container->get_tab_idx_from_control(history[history_pos].control);
}
- tab_container->set_current_tab(idx);
+ _go_to_tab(idx);
} else {
_update_selected_editor_menu();
}
@@ -882,7 +883,7 @@ void ScriptEditor::_queue_close_tabs() {
// Maybe there are unsaved changes.
if (se->is_unsaved()) {
_ask_close_current_unsaved_tab(se);
- erase_tab_confirm->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &ScriptEditor::_queue_close_tabs), varray(), CONNECT_ONESHOT);
+ erase_tab_confirm->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &ScriptEditor::_queue_close_tabs), CONNECT_ONESHOT);
break;
}
}
@@ -1188,7 +1189,7 @@ void ScriptEditor::_menu_option(int p_option) {
file_dialog->clear_filters();
for (const String &E : textfile_extensions) {
- file_dialog->add_filter("*." + E + " ; " + E.to_upper());
+ file_dialog->add_filter("*." + E, E.to_upper());
}
file_dialog->popup_file_dialog();
file_dialog->set_title(TTR("New Text File..."));
@@ -1203,11 +1204,11 @@ void ScriptEditor::_menu_option(int p_option) {
ResourceLoader::get_recognized_extensions_for_type("Script", &extensions);
file_dialog->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file_dialog->add_filter("*." + extensions[i], extensions[i].to_upper());
}
for (const String &E : textfile_extensions) {
- file_dialog->add_filter("*." + E + " ; " + E.to_upper());
+ file_dialog->add_filter("*." + E, E.to_upper());
}
file_dialog->popup_file_dialog();
@@ -1447,20 +1448,20 @@ void ScriptEditor::_menu_option(int p_option) {
case WINDOW_MOVE_UP: {
if (tab_container->get_current_tab() > 0) {
tab_container->move_child(current, tab_container->get_current_tab() - 1);
- tab_container->set_current_tab(tab_container->get_current_tab() - 1);
+ tab_container->set_current_tab(tab_container->get_current_tab());
_update_script_names();
}
} break;
case WINDOW_MOVE_DOWN: {
if (tab_container->get_current_tab() < tab_container->get_tab_count() - 1) {
tab_container->move_child(current, tab_container->get_current_tab() + 1);
- tab_container->set_current_tab(tab_container->get_current_tab() + 1);
+ tab_container->set_current_tab(tab_container->get_current_tab());
_update_script_names();
}
} break;
default: {
if (p_option >= WINDOW_SELECT_BASE) {
- tab_container->set_current_tab(p_option - WINDOW_SELECT_BASE);
+ _go_to_tab(p_option - WINDOW_SELECT_BASE);
_update_script_names();
}
}
@@ -1493,14 +1494,14 @@ void ScriptEditor::_menu_option(int p_option) {
case WINDOW_MOVE_UP: {
if (tab_container->get_current_tab() > 0) {
tab_container->move_child(help, tab_container->get_current_tab() - 1);
- tab_container->set_current_tab(tab_container->get_current_tab() - 1);
+ tab_container->set_current_tab(tab_container->get_current_tab());
_update_script_names();
}
} break;
case WINDOW_MOVE_DOWN: {
if (tab_container->get_current_tab() < tab_container->get_tab_count() - 1) {
tab_container->move_child(help, tab_container->get_current_tab() + 1);
- tab_container->set_current_tab(tab_container->get_current_tab() + 1);
+ tab_container->set_current_tab(tab_container->get_current_tab());
_update_script_names();
}
} break;
@@ -1542,7 +1543,7 @@ void ScriptEditor::_show_save_theme_as_dialog() {
file_dialog_option = THEME_SAVE_AS;
file_dialog->clear_filters();
file_dialog->add_filter("*.tet");
- file_dialog->set_current_path(EditorSettings::get_singleton()->get_text_editor_themes_dir().plus_file(EditorSettings::get_singleton()->get("text_editor/theme/color_theme")));
+ file_dialog->set_current_path(EditorPaths::get_singleton()->get_text_editor_themes_dir().plus_file(EditorSettings::get_singleton()->get("text_editor/theme/color_theme")));
file_dialog->popup_file_dialog();
file_dialog->set_title(TTR("Save Theme As..."));
}
@@ -1852,10 +1853,12 @@ void ScriptEditor::_update_members_overview_visibility() {
if (members_overview_enabled && se->show_members_overview()) {
members_overview_alphabeta_sort_button->set_visible(true);
+ filter_methods->set_visible(true);
members_overview->set_visible(true);
overview_vbox->set_visible(true);
} else {
members_overview_alphabeta_sort_button->set_visible(false);
+ filter_methods->set_visible(false);
members_overview->set_visible(false);
overview_vbox->set_visible(false);
}
@@ -1910,6 +1913,7 @@ void ScriptEditor::_update_help_overview_visibility() {
if (help_overview_enabled) {
members_overview_alphabeta_sort_button->set_visible(false);
+ filter_methods->set_visible(false);
help_overview->set_visible(true);
overview_vbox->set_visible(true);
filename->set_text(se->get_name());
@@ -2124,8 +2128,8 @@ void ScriptEditor::_update_script_names() {
sd.index = i;
sedata.set(i, sd);
}
- tab_container->set_current_tab(new_prev_tab);
- tab_container->set_current_tab(new_cur_tab);
+ _go_to_tab(new_prev_tab);
+ _go_to_tab(new_cur_tab);
_sort_list_on_update = false;
}
@@ -2153,8 +2157,10 @@ void ScriptEditor::_update_script_names() {
}
if (tab_container->get_current_tab() == sedata_filtered[i].index) {
script_list->select(index);
+
script_name_label->set_text(sedata_filtered[i].name);
script_icon->set_texture(sedata_filtered[i].icon);
+
ScriptEditorBase *se = _get_current_editor();
if (se) {
se->enable_editor();
@@ -3264,7 +3270,7 @@ void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) {
p_layout->set_value("ScriptEditor", "list_split_offset", list_split->get_split_offset());
// Save the cache.
- script_editor_cache->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("script_editor_cache.cfg"));
+ script_editor_cache->save(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("script_editor_cache.cfg"));
}
void ScriptEditor::_help_class_open(const String &p_class) {
@@ -3645,7 +3651,7 @@ ScriptEditor::ScriptEditor() {
current_theme = "";
script_editor_cache.instantiate();
- script_editor_cache->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("script_editor_cache.cfg"));
+ script_editor_cache->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("script_editor_cache.cfg"));
completion_cache = memnew(EditorScriptCodeCompletionCache);
restoring_layout = false;
@@ -3685,7 +3691,7 @@ ScriptEditor::ScriptEditor() {
script_list->set_v_size_flags(SIZE_EXPAND_FILL);
script_split->set_split_offset(70 * EDSCALE);
_sort_list_on_update = true;
- script_list->connect("gui_input", callable_mp(this, &ScriptEditor::_script_list_gui_input), varray(), CONNECT_DEFERRED);
+ script_list->connect("gui_input", callable_mp(this, &ScriptEditor::_script_list_gui_input), CONNECT_DEFERRED);
script_list->set_allow_rmb_select(true);
script_list->set_drag_forwarding(this);
@@ -3853,14 +3859,14 @@ ScriptEditor::ScriptEditor() {
site_search = memnew(Button);
site_search->set_flat(true);
site_search->set_text(TTR("Online Docs"));
- site_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option), varray(SEARCH_WEBSITE));
+ site_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option).bind(SEARCH_WEBSITE));
menu_hb->add_child(site_search);
site_search->set_tooltip(TTR("Open Godot online documentation."));
help_search = memnew(Button);
help_search->set_flat(true);
help_search->set_text(TTR("Search Help"));
- help_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option), varray(SEARCH_HELP));
+ help_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option).bind(SEARCH_HELP));
menu_hb->add_child(help_search);
help_search->set_tooltip(TTR("Search the reference documentation."));
@@ -3883,9 +3889,9 @@ ScriptEditor::ScriptEditor() {
tab_container->connect("tab_changed", callable_mp(this, &ScriptEditor::_tab_changed));
erase_tab_confirm = memnew(ConfirmationDialog);
- erase_tab_confirm->get_ok_button()->set_text(TTR("Save"));
+ erase_tab_confirm->set_ok_button_text(TTR("Save"));
erase_tab_confirm->add_button(TTR("Discard"), DisplayServer::get_singleton()->get_swap_cancel_ok(), "discard");
- erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab), varray(true));
+ erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab).bind(true));
erase_tab_confirm->connect("custom_action", callable_mp(this, &ScriptEditor::_close_discard_current_tab));
add_child(erase_tab_confirm);
@@ -3916,7 +3922,7 @@ ScriptEditor::ScriptEditor() {
disk_changed_list->set_v_size_flags(SIZE_EXPAND_FILL);
disk_changed->connect("confirmed", callable_mp(this, &ScriptEditor::_reload_scripts));
- disk_changed->get_ok_button()->set_text(TTR("Reload"));
+ disk_changed->set_ok_button_text(TTR("Reload"));
disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave");
disk_changed->connect("custom_action", callable_mp(this, &ScriptEditor::_resave_scripts));
@@ -3939,8 +3945,8 @@ ScriptEditor::ScriptEditor() {
help_search_dialog->connect("go_to_help", callable_mp(this, &ScriptEditor::_help_class_goto));
find_in_files_dialog = memnew(FindInFilesDialog);
- find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_FIND_REQUESTED, callable_mp(this, &ScriptEditor::_start_find_in_files), varray(false));
- find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_REPLACE_REQUESTED, callable_mp(this, &ScriptEditor::_start_find_in_files), varray(true));
+ find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_FIND_REQUESTED, callable_mp(this, &ScriptEditor::_start_find_in_files).bind(false));
+ find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_REPLACE_REQUESTED, callable_mp(this, &ScriptEditor::_start_find_in_files).bind(true));
add_child(find_in_files_dialog);
find_in_files = memnew(FindInFilesPanel);
find_in_files_button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Search Results"), find_in_files);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 7d4ffd1a25..5d5f452390 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;
@@ -1417,7 +1420,9 @@ Control *ScriptTextEditor::get_edit_menu() {
}
void ScriptTextEditor::clear_edit_menu() {
- memdelete(edit_hb);
+ if (editor_enabled) {
+ memdelete(edit_hb);
+ }
}
void ScriptTextEditor::set_find_replace_bar(FindReplaceBar *p_bar) {
@@ -1451,7 +1456,7 @@ void ScriptTextEditor::clear_breakpoints() {
void ScriptTextEditor::set_tooltip_request_func(const Callable &p_toolip_callback) {
Variant args[1] = { this };
const Variant *argp[] = { &args[0] };
- code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bind(argp, 1));
+ code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bindp(argp, 1));
}
void ScriptTextEditor::set_debugger_active(bool p_active) {
@@ -1818,7 +1823,7 @@ void ScriptTextEditor::_enable_code_editor() {
VSplitContainer *editor_box = memnew(VSplitContainer);
add_child(editor_box);
- editor_box->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ editor_box->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
editor_box->set_v_size_flags(SIZE_EXPAND_FILL);
editor_box->add_child(code_editor);
@@ -1857,20 +1862,10 @@ void ScriptTextEditor::_enable_code_editor() {
color_picker = memnew(ColorPicker);
color_picker->set_deferred_mode(true);
color_picker->connect("color_changed", callable_mp(this, &ScriptTextEditor::_color_changed));
+ color_panel->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(color_picker));
color_panel->add_child(color_picker);
- // 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);
- }
-
- int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape");
- color_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape);
-
quick_open = memnew(ScriptEditorQuickOpen);
quick_open->connect("goto_line", callable_mp(this, &ScriptTextEditor::_goto_line));
add_child(quick_open);
@@ -1959,7 +1954,7 @@ void ScriptTextEditor::_enable_code_editor() {
ScriptTextEditor::ScriptTextEditor() {
code_editor = memnew(CodeTextEditor);
code_editor->add_theme_constant_override("separation", 2);
- code_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ code_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
code_editor->set_code_complete_func(_code_complete_scripts, this);
code_editor->set_v_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 04b407ce65..e700412188 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -41,10 +41,10 @@
#include "editor/filesystem_dock.h"
#include "editor/plugins/visual_shader_editor_plugin.h"
#include "editor/project_settings_editor.h"
-#include "editor/property_editor.h"
#include "editor/shader_create_dialog.h"
#include "scene/gui/split_container.h"
#include "servers/display_server.h"
+#include "servers/rendering/shader_preprocessor.h"
#include "servers/rendering/shader_types.h"
/*** SHADER SCRIPT EDITOR ****/
@@ -72,15 +72,65 @@ Ref<Shader> ShaderTextEditor::get_edited_shader() const {
return shader;
}
+Ref<ShaderInclude> ShaderTextEditor::get_edited_shader_include() const {
+ return shader_inc;
+}
+
void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) {
+ set_edited_shader(p_shader, p_shader->get_code());
+}
+
+void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader, const String &p_code) {
if (shader == p_shader) {
return;
}
+ if (shader.is_valid()) {
+ shader->disconnect(SNAME("changed"), callable_mp(this, &ShaderTextEditor::_shader_changed));
+ }
shader = p_shader;
+ shader_inc = Ref<ShaderInclude>();
+
+ set_edited_code(p_code);
+
+ if (shader.is_valid()) {
+ shader->connect(SNAME("changed"), callable_mp(this, &ShaderTextEditor::_shader_changed));
+ }
+}
+
+void ShaderTextEditor::set_edited_shader_include(const Ref<ShaderInclude> &p_shader_inc) {
+ set_edited_shader_include(p_shader_inc, p_shader_inc->get_code());
+}
+
+void ShaderTextEditor::_shader_changed() {
+ // This function is used for dependencies (include changing changes main shader and forces it to revalidate)
+ if (block_shader_changed) {
+ return;
+ }
+ dependencies_version++;
+ _validate_script();
+}
+
+void ShaderTextEditor::set_edited_shader_include(const Ref<ShaderInclude> &p_shader_inc, const String &p_code) {
+ if (shader_inc == p_shader_inc) {
+ return;
+ }
+ if (shader_inc.is_valid()) {
+ shader_inc->disconnect(SNAME("changed"), callable_mp(this, &ShaderTextEditor::_shader_changed));
+ }
+ shader_inc = p_shader_inc;
+ shader = Ref<Shader>();
+
+ set_edited_code(p_code);
+
+ if (shader_inc.is_valid()) {
+ shader_inc->connect(SNAME("changed"), callable_mp(this, &ShaderTextEditor::_shader_changed));
+ }
+}
+void ShaderTextEditor::set_edited_code(const String &p_code) {
_load_theme_settings();
- get_text_editor()->set_text(p_shader->get_code());
+ get_text_editor()->set_text(p_code);
get_text_editor()->clear_undo_history();
get_text_editor()->call_deferred(SNAME("set_h_scroll"), 0);
get_text_editor()->call_deferred(SNAME("set_v_scroll"), 0);
@@ -132,11 +182,12 @@ void ShaderTextEditor::_load_theme_settings() {
syntax_highlighter->clear_keyword_colors();
- List<String> keywords;
- ShaderLanguage::get_keyword_list(&keywords);
const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
+ List<String> keywords;
+ ShaderLanguage::get_keyword_list(&keywords);
+
for (const String &E : keywords) {
if (ShaderLanguage::is_control_flow_keyword(E)) {
syntax_highlighter->add_keyword_color(E, control_flow_keyword_color);
@@ -145,11 +196,41 @@ void ShaderTextEditor::_load_theme_settings() {
}
}
+ List<String> pp_keywords;
+ ShaderPreprocessor::get_keyword_list(&pp_keywords, false);
+
+ for (const String &E : pp_keywords) {
+ syntax_highlighter->add_keyword_color(E, keyword_color);
+ }
+
// Colorize built-ins like `COLOR` differently to make them easier
// to distinguish from keywords at a quick glance.
List<String> built_ins;
- if (shader.is_valid()) {
+
+ if (shader_inc.is_valid()) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i))) {
+ for (const KeyValue<StringName, ShaderLanguage::BuiltInInfo> &F : E.value.built_ins) {
+ built_ins.push_back(F.key);
+ }
+ }
+
+ const Vector<ShaderLanguage::ModeInfo> &modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
+
+ for (int j = 0; j < modes.size(); j++) {
+ const ShaderLanguage::ModeInfo &info = modes[j];
+
+ if (!info.options.is_empty()) {
+ for (int k = 0; k < info.options.size(); k++) {
+ built_ins.push_back(String(info.name) + "_" + String(info.options[k]));
+ }
+ } else {
+ built_ins.push_back(String(info.name));
+ }
+ }
+ }
+ } else if (shader.is_valid()) {
for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode()))) {
for (const KeyValue<StringName, ShaderLanguage::BuiltInInfo> &F : E.value.built_ins) {
built_ins.push_back(F.key);
@@ -191,8 +272,12 @@ void ShaderTextEditor::_load_theme_settings() {
text_editor->add_auto_brace_completion_pair("/*", "*/");
}
+ // Colorize preprocessor include strings.
+ const Color string_color = EDITOR_GET("text_editor/theme/highlighting/string_color");
+ syntax_highlighter->add_color_region("\"", "\"", string_color, false);
+
if (warnings_panel) {
- // Warnings panel
+ // Warnings panel.
warnings_panel->add_theme_font_override("normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("main"), SNAME("EditorFonts")));
warnings_panel->add_theme_font_size_override("normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")));
}
@@ -216,82 +301,204 @@ void ShaderTextEditor::_check_shader_mode() {
}
if (shader->get_mode() != mode) {
+ set_block_shader_changed(true);
shader->set_code(get_text_editor()->get_text());
+ set_block_shader_changed(false);
_load_theme_settings();
}
}
-static ShaderLanguage::DataType _get_global_variable_type(const StringName &p_variable) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_variable);
- return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt);
+static ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_variable) {
+ RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_variable);
+ return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
+}
+
+static String complete_from_path;
+
+static void _complete_include_paths_search(EditorFileSystemDirectory *p_efsd, List<ScriptLanguage::CodeCompletionOption> *r_options) {
+ if (!p_efsd) {
+ return;
+ }
+ for (int i = 0; i < p_efsd->get_file_count(); i++) {
+ if (p_efsd->get_file_type(i) == SNAME("ShaderInclude")) {
+ String path = p_efsd->get_file_path(i);
+ if (path.begins_with(complete_from_path)) {
+ path = path.replace_first(complete_from_path, "");
+ }
+ r_options->push_back(ScriptLanguage::CodeCompletionOption(path, ScriptLanguage::CODE_COMPLETION_KIND_FILE_PATH));
+ }
+ }
+ for (int j = 0; j < p_efsd->get_subdir_count(); j++) {
+ _complete_include_paths_search(p_efsd->get_subdir(j), r_options);
+ }
+}
+
+static void _complete_include_paths(List<ScriptLanguage::CodeCompletionOption> *r_options) {
+ _complete_include_paths_search(EditorFileSystem::get_singleton()->get_filesystem(), r_options);
}
void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptLanguage::CodeCompletionOption> *r_options) {
- _check_shader_mode();
+ List<ScriptLanguage::CodeCompletionOption> pp_options;
+ ShaderPreprocessor preprocessor;
+ String code;
+ complete_from_path = (shader.is_valid() ? shader->get_path() : shader_inc->get_path()).get_base_dir();
+ if (!complete_from_path.ends_with("/")) {
+ complete_from_path += "/";
+ }
+ preprocessor.preprocess(p_code, code, nullptr, nullptr, nullptr, &pp_options, _complete_include_paths);
+ complete_from_path = String();
+ if (pp_options.size()) {
+ for (const ScriptLanguage::CodeCompletionOption &E : pp_options) {
+ r_options->push_back(E);
+ }
+ return;
+ }
ShaderLanguage sl;
String calltip;
-
ShaderLanguage::ShaderCompileInfo info;
+ info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
+
+ if (shader.is_null()) {
+ info.is_include = true;
+
+ sl.complete(code, info, r_options, calltip);
+ get_text_editor()->set_code_hint(calltip);
+ return;
+ }
+ _check_shader_mode();
info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode()));
info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode()));
info.shader_types = ShaderTypes::get_singleton()->get_types();
- info.global_variable_type_func = _get_global_variable_type;
-
- sl.complete(p_code, info, r_options, calltip);
+ sl.complete(code, info, r_options, calltip);
get_text_editor()->set_code_hint(calltip);
}
void ShaderTextEditor::_validate_script() {
- _check_shader_mode();
+ emit_signal(SNAME("script_changed")); // Ensure to notify that it changed, so it is applied
- String code = get_text_editor()->get_text();
- //List<StringName> params;
- //shader->get_param_list(&params);
+ String code;
- ShaderLanguage::ShaderCompileInfo info;
- info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode()));
- info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode()));
- info.shader_types = ShaderTypes::get_singleton()->get_types();
- info.global_variable_type_func = _get_global_variable_type;
-
- ShaderLanguage sl;
+ if (shader.is_valid()) {
+ _check_shader_mode();
+ code = shader->get_code();
+ } else {
+ code = shader_inc->get_code();
+ }
- sl.enable_warning_checking(saved_warnings_enabled);
- sl.set_warning_flags(saved_warning_flags);
+ ShaderPreprocessor preprocessor;
+ String code_pp;
+ String error_pp;
+ List<ShaderPreprocessor::FilePosition> err_positions;
+ last_compile_result = preprocessor.preprocess(code, code_pp, &error_pp, &err_positions);
- last_compile_result = sl.compile(code, info);
+ for (int i = 0; i < get_text_editor()->get_line_count(); i++) {
+ get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0));
+ }
+ set_error("");
+ set_error_count(0);
if (last_compile_result != OK) {
- String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
+ //preprocessor error
+ ERR_FAIL_COND(err_positions.size() == 0);
+
+ String error_text = error_pp;
+ int error_line = err_positions.front()->get().line;
+ if (err_positions.size() == 1) {
+ // Error in main file
+ error_text = "error(" + itos(error_line) + "): " + error_text;
+ } else {
+ error_text = "error(" + itos(error_line) + ") in include " + err_positions.back()->get().file.get_file() + ":" + itos(err_positions.back()->get().line) + ": " + error_text;
+ set_error_count(err_positions.size() - 1);
+ }
+
set_error(error_text);
- set_error_pos(sl.get_error_line() - 1, 0);
+ set_error_pos(error_line - 1, 0);
for (int i = 0; i < get_text_editor()->get_line_count(); i++) {
get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0));
}
- get_text_editor()->set_line_background_color(sl.get_error_line() - 1, marked_line_color);
+ get_text_editor()->set_line_background_color(error_line - 1, marked_line_color);
+
+ set_warning_count(0);
+
} else {
- for (int i = 0; i < get_text_editor()->get_line_count(); i++) {
- get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0));
+ ShaderLanguage sl;
+
+ sl.enable_warning_checking(saved_warnings_enabled);
+ uint32_t flags = saved_warning_flags;
+ if (shader.is_null()) {
+ if (flags & ShaderWarning::UNUSED_CONSTANT) {
+ flags &= ~(ShaderWarning::UNUSED_CONSTANT);
+ }
+ if (flags & ShaderWarning::UNUSED_FUNCTION) {
+ flags &= ~(ShaderWarning::UNUSED_FUNCTION);
+ }
+ if (flags & ShaderWarning::UNUSED_STRUCT) {
+ flags &= ~(ShaderWarning::UNUSED_STRUCT);
+ }
+ if (flags & ShaderWarning::UNUSED_UNIFORM) {
+ flags &= ~(ShaderWarning::UNUSED_UNIFORM);
+ }
+ if (flags & ShaderWarning::UNUSED_VARYING) {
+ flags &= ~(ShaderWarning::UNUSED_VARYING);
+ }
}
- set_error("");
- }
+ sl.set_warning_flags(flags);
- if (warnings.size() > 0 || last_compile_result != OK) {
- warnings_panel->clear();
- }
- warnings.clear();
- for (List<ShaderWarning>::Element *E = sl.get_warnings_ptr(); E; E = E->next()) {
- warnings.push_back(E->get());
- }
- if (warnings.size() > 0 && last_compile_result == OK) {
- warnings.sort_custom<WarningsComparator>();
- _update_warning_panel();
- } else {
- set_warning_count(0);
+ ShaderLanguage::ShaderCompileInfo info;
+ info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
+
+ if (shader.is_null()) {
+ info.is_include = true;
+ } else {
+ Shader::Mode mode = shader->get_mode();
+ info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(mode));
+ info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(mode));
+ info.shader_types = ShaderTypes::get_singleton()->get_types();
+ }
+
+ code = code_pp;
+ //compiler error
+ last_compile_result = sl.compile(code, info);
+
+ if (last_compile_result != OK) {
+ String error_text;
+ int error_line;
+ Vector<ShaderLanguage::FilePosition> include_positions = sl.get_include_positions();
+ if (include_positions.size() > 1) {
+ //error is in an include
+ error_line = include_positions[0].line;
+ error_text = "error(" + itos(error_line) + ") in include " + include_positions[include_positions.size() - 1].file + ":" + itos(include_positions[include_positions.size() - 1].line) + ": " + sl.get_error_text();
+ set_error_count(include_positions.size() - 1);
+ } else {
+ error_line = sl.get_error_line();
+ error_text = "error(" + itos(error_line) + "): " + sl.get_error_text();
+ set_error_count(0);
+ }
+ set_error(error_text);
+ set_error_pos(error_line - 1, 0);
+ get_text_editor()->set_line_background_color(error_line - 1, marked_line_color);
+ } else {
+ set_error("");
+ }
+
+ if (warnings.size() > 0 || last_compile_result != OK) {
+ warnings_panel->clear();
+ }
+ warnings.clear();
+ for (List<ShaderWarning>::Element *E = sl.get_warnings_ptr(); E; E = E->next()) {
+ warnings.push_back(E->get());
+ }
+ if (warnings.size() > 0 && last_compile_result == OK) {
+ warnings.sort_custom<WarningsComparator>();
+ _update_warning_panel();
+ } else {
+ set_warning_count(0);
+ }
}
- emit_signal(SNAME("script_changed"));
+
+ emit_signal(SNAME("script_validated"), last_compile_result == OK); // Notify that validation finished, to update the list of scripts
}
void ShaderTextEditor::_update_warning_panel() {
@@ -338,6 +545,7 @@ void ShaderTextEditor::_update_warning_panel() {
}
void ShaderTextEditor::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("script_validated", PropertyInfo(Variant::BOOL, "valid")));
}
ShaderTextEditor::ShaderTextEditor() {
@@ -473,6 +681,8 @@ void ShaderEditor::_warning_clicked(Variant p_line) {
void ShaderEditor::_bind_methods() {
ClassDB::bind_method("_show_warnings_panel", &ShaderEditor::_show_warnings_panel);
ClassDB::bind_method("_warning_clicked", &ShaderEditor::_warning_clicked);
+
+ ADD_SIGNAL(MethodInfo("validation_changed"));
}
void ShaderEditor::ensure_select_current() {
@@ -524,15 +734,23 @@ void ShaderEditor::_update_warnings(bool p_validate) {
}
void ShaderEditor::_check_for_external_edit() {
- if (shader.is_null() || !shader.is_valid()) {
+ bool use_autoreload = bool(EDITOR_GET("text_editor/behavior/files/auto_reload_scripts_on_external_change"));
+
+ if (shader_inc.is_valid()) {
+ if (shader_inc->get_last_modified_time() != FileAccess::get_modified_time(shader_inc->get_path())) {
+ if (use_autoreload) {
+ _reload_shader_include_from_disk();
+ } else {
+ disk_changed->call_deferred(SNAME("popup_centered"));
+ }
+ }
return;
}
- if (shader->is_built_in()) {
+ if (shader.is_null() || shader->is_built_in()) {
return;
}
- bool use_autoreload = bool(EDITOR_GET("text_editor/behavior/files/auto_reload_scripts_on_external_change"));
if (shader->get_last_modified_time() != FileAccess::get_modified_time(shader->get_path())) {
if (use_autoreload) {
_reload_shader_from_disk();
@@ -546,11 +764,32 @@ void ShaderEditor::_reload_shader_from_disk() {
Ref<Shader> rel_shader = ResourceLoader::load(shader->get_path(), shader->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
ERR_FAIL_COND(!rel_shader.is_valid());
+ shader_editor->set_block_shader_changed(true);
shader->set_code(rel_shader->get_code());
+ shader_editor->set_block_shader_changed(false);
shader->set_last_modified_time(rel_shader->get_last_modified_time());
shader_editor->reload_text();
}
+void ShaderEditor::_reload_shader_include_from_disk() {
+ Ref<ShaderInclude> rel_shader_include = ResourceLoader::load(shader_inc->get_path(), shader_inc->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
+ ERR_FAIL_COND(!rel_shader_include.is_valid());
+
+ shader_editor->set_block_shader_changed(true);
+ shader_inc->set_code(rel_shader_include->get_code());
+ shader_editor->set_block_shader_changed(false);
+ shader_inc->set_last_modified_time(rel_shader_include->get_last_modified_time());
+ shader_editor->reload_text();
+}
+
+void ShaderEditor::_reload() {
+ if (shader.is_valid()) {
+ _reload_shader_from_disk();
+ } else if (shader_inc.is_valid()) {
+ _reload_shader_include_from_disk();
+ }
+}
+
void ShaderEditor::edit(const Ref<Shader> &p_shader) {
if (p_shader.is_null() || !p_shader->is_text_shader()) {
return;
@@ -561,37 +800,79 @@ void ShaderEditor::edit(const Ref<Shader> &p_shader) {
}
shader = p_shader;
+ shader_inc = Ref<ShaderInclude>();
+
+ shader_editor->set_edited_shader(shader);
+}
+
+void ShaderEditor::edit(const Ref<ShaderInclude> &p_shader_inc) {
+ if (p_shader_inc.is_null()) {
+ return;
+ }
+
+ if (shader_inc == p_shader_inc) {
+ return;
+ }
- shader_editor->set_edited_shader(p_shader);
+ shader_inc = p_shader_inc;
+ shader = Ref<Shader>();
- //vertex_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_VERTEX);
- // see if already has it
+ shader_editor->set_edited_shader_include(p_shader_inc);
}
void ShaderEditor::save_external_data(const String &p_str) {
- if (shader.is_null()) {
+ if (shader.is_null() && shader_inc.is_null()) {
disk_changed->hide();
return;
}
apply_shaders();
- if (!shader->is_built_in()) {
- //external shader, save it
- ResourceSaver::save(shader->get_path(), shader);
+
+ Ref<Shader> edited_shader = shader_editor->get_edited_shader();
+ if (edited_shader.is_valid()) {
+ ResourceSaver::save(edited_shader);
+ }
+ if (shader.is_valid() && shader != edited_shader) {
+ ResourceSaver::save(shader);
+ }
+
+ Ref<ShaderInclude> edited_shader_inc = shader_editor->get_edited_shader_include();
+ if (edited_shader_inc.is_valid()) {
+ ResourceSaver::save(edited_shader_inc);
+ }
+ if (shader_inc.is_valid() && shader_inc != edited_shader_inc) {
+ ResourceSaver::save(shader_inc);
}
disk_changed->hide();
}
+void ShaderEditor::validate_script() {
+ shader_editor->_validate_script();
+}
+
void ShaderEditor::apply_shaders() {
+ String editor_code = shader_editor->get_text_editor()->get_text();
if (shader.is_valid()) {
String shader_code = shader->get_code();
- String editor_code = shader_editor->get_text_editor()->get_text();
- if (shader_code != editor_code) {
+ if (shader_code != editor_code || dependencies_version != shader_editor->get_dependencies_version()) {
+ shader_editor->set_block_shader_changed(true);
shader->set_code(editor_code);
+ shader_editor->set_block_shader_changed(false);
shader->set_edited(true);
}
}
+ if (shader_inc.is_valid()) {
+ String shader_inc_code = shader_inc->get_code();
+ if (shader_inc_code != editor_code || dependencies_version != shader_editor->get_dependencies_version()) {
+ shader_editor->set_block_shader_changed(true);
+ shader_inc->set_code(editor_code);
+ shader_editor->set_block_shader_changed(false);
+ shader_inc->set_edited(true);
+ }
+ }
+
+ dependencies_version = shader_editor->get_dependencies_version();
}
void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
@@ -704,9 +985,12 @@ ShaderEditor::ShaderEditor() {
_update_warnings(false);
shader_editor = memnew(ShaderTextEditor);
+
+ shader_editor->connect("script_validated", callable_mp(this, &ShaderEditor::_script_validated));
+
shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
shader_editor->add_theme_constant_override("separation", 0);
- shader_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ shader_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
shader_editor->connect("show_warnings_panel", callable_mp(this, &ShaderEditor::_show_warnings_panel));
shader_editor->connect("script_changed", callable_mp(this, &ShaderEditor::apply_shaders));
@@ -797,7 +1081,7 @@ ShaderEditor::ShaderEditor() {
VSplitContainer *editor_box = memnew(VSplitContainer);
main_container->add_child(editor_box);
- editor_box->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ editor_box->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
editor_box->set_v_size_flags(SIZE_EXPAND_FILL);
editor_box->add_child(shader_editor);
@@ -829,8 +1113,8 @@ ShaderEditor::ShaderEditor() {
dl->set_text(TTR("This shader has been modified on disk.\nWhat action should be taken?"));
vbc->add_child(dl);
- disk_changed->connect("confirmed", callable_mp(this, &ShaderEditor::_reload_shader_from_disk));
- disk_changed->get_ok_button()->set_text(TTR("Reload"));
+ disk_changed->connect("confirmed", callable_mp(this, &ShaderEditor::_reload));
+ disk_changed->set_ok_button_text(TTR("Reload"));
disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave");
disk_changed->connect("custom_action", callable_mp(this, &ShaderEditor::save_external_data));
@@ -844,19 +1128,37 @@ void ShaderEditorPlugin::_update_shader_list() {
shader_list->clear();
for (uint32_t i = 0; i < edited_shaders.size(); i++) {
String text;
- String path = edited_shaders[i].shader->get_path();
- String _class = edited_shaders[i].shader->get_class();
+ String path;
+ String _class;
+ String shader_name;
+ if (edited_shaders[i].shader.is_valid()) {
+ Ref<Shader> shader = edited_shaders[i].shader;
+
+ path = shader->get_path();
+ _class = shader->get_class();
+ shader_name = shader->get_name();
+ } else {
+ Ref<ShaderInclude> shader_inc = edited_shaders[i].shader_inc;
+
+ path = shader_inc->get_path();
+ _class = shader_inc->get_class();
+ shader_name = shader_inc->get_name();
+ }
if (path.is_resource_file()) {
text = path.get_file();
- } else if (edited_shaders[i].shader->get_name() != "") {
- text = edited_shaders[i].shader->get_name();
+ } else if (shader_name != "") {
+ text = shader_name;
} else {
- text = _class + ":" + itos(edited_shaders[i].shader->get_instance_id());
+ if (edited_shaders[i].shader.is_valid()) {
+ text = _class + ":" + itos(edited_shaders[i].shader->get_instance_id());
+ } else {
+ text = _class + ":" + itos(edited_shaders[i].shader_inc->get_instance_id());
+ }
}
if (!shader_list->has_theme_icon(_class, SNAME("EditorIcons"))) {
- _class = "Resource";
+ _class = "TextFile";
}
Ref<Texture2D> icon = shader_list->get_theme_icon(_class, SNAME("EditorIcons"));
@@ -871,38 +1173,70 @@ void ShaderEditorPlugin::_update_shader_list() {
for (int i = 1; i < FILE_MAX; i++) {
file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), edited_shaders.size() == 0);
}
+
+ _update_shader_list_status();
}
-void ShaderEditorPlugin::edit(Object *p_object) {
- Shader *s = Object::cast_to<Shader>(p_object);
- for (uint32_t i = 0; i < edited_shaders.size(); i++) {
- if (edited_shaders[i].shader.ptr() == s) {
- // Exists, select.
- shader_tabs->set_current_tab(i);
- shader_list->select(i);
- return;
+void ShaderEditorPlugin::_update_shader_list_status() {
+ for (int i = 0; i < shader_list->get_item_count(); i++) {
+ ShaderEditor *se = Object::cast_to<ShaderEditor>(shader_tabs->get_tab_control(i));
+ if (se) {
+ if (se->was_compilation_successful()) {
+ shader_list->set_item_tag_icon(i, Ref<Texture2D>());
+ } else {
+ shader_list->set_item_tag_icon(i, shader_list->get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
+ }
}
}
- // Add.
+}
+
+void ShaderEditorPlugin::edit(Object *p_object) {
EditedShader es;
- es.shader = Ref<Shader>(s);
- Ref<VisualShader> vs = es.shader;
- if (vs.is_valid()) {
- es.visual_shader_editor = memnew(VisualShaderEditor);
- es.visual_shader_editor->edit(vs.ptr());
- shader_tabs->add_child(es.visual_shader_editor);
- } else {
+
+ ShaderInclude *si = Object::cast_to<ShaderInclude>(p_object);
+ if (si != nullptr) {
+ for (uint32_t i = 0; i < edited_shaders.size(); i++) {
+ if (edited_shaders[i].shader_inc.ptr() == si) {
+ shader_tabs->set_current_tab(i);
+ shader_list->select(i);
+ return;
+ }
+ }
+ es.shader_inc = Ref<ShaderInclude>(si);
es.shader_editor = memnew(ShaderEditor);
- es.shader_editor->edit(s);
+ es.shader_editor->edit(si);
shader_tabs->add_child(es.shader_editor);
+ es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list_status));
+ } else {
+ Shader *s = Object::cast_to<Shader>(p_object);
+ for (uint32_t i = 0; i < edited_shaders.size(); i++) {
+ if (edited_shaders[i].shader.ptr() == s) {
+ shader_tabs->set_current_tab(i);
+ shader_list->select(i);
+ return;
+ }
+ }
+ es.shader = Ref<Shader>(s);
+ Ref<VisualShader> vs = es.shader;
+ if (vs.is_valid()) {
+ es.visual_shader_editor = memnew(VisualShaderEditor);
+ shader_tabs->add_child(es.visual_shader_editor);
+ es.visual_shader_editor->edit(vs.ptr());
+ } else {
+ es.shader_editor = memnew(ShaderEditor);
+ shader_tabs->add_child(es.shader_editor);
+ es.shader_editor->edit(s);
+ es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list_status));
+ }
}
+
shader_tabs->set_current_tab(shader_tabs->get_tab_count() - 1);
edited_shaders.push_back(es);
_update_shader_list();
}
bool ShaderEditorPlugin::handles(Object *p_object) const {
- return Object::cast_to<Shader>(p_object) != nullptr;
+ return Object::cast_to<Shader>(p_object) != nullptr || Object::cast_to<ShaderInclude>(p_object) != nullptr;
}
void ShaderEditorPlugin::make_visible(bool p_visible) {
@@ -923,6 +1257,15 @@ ShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref<Shader> &p_for_sha
return nullptr;
}
+VisualShaderEditor *ShaderEditorPlugin::get_visual_shader_editor(const Ref<Shader> &p_for_shader) {
+ for (uint32_t i = 0; i < edited_shaders.size(); i++) {
+ if (edited_shaders[i].shader == p_for_shader) {
+ return edited_shaders[i].visual_shader_editor;
+ }
+ }
+ return nullptr;
+}
+
void ShaderEditorPlugin::save_external_data() {
for (uint32_t i = 0; i < edited_shaders.size(); i++) {
if (edited_shaders[i].shader_editor) {
@@ -940,6 +1283,9 @@ void ShaderEditorPlugin::apply_changes() {
}
void ShaderEditorPlugin::_shader_selected(int p_index) {
+ if (edited_shaders[p_index].shader_editor) {
+ edited_shaders[p_index].shader_editor->validate_script();
+ }
shader_tabs->set_current_tab(p_index);
}
@@ -950,6 +1296,7 @@ void ShaderEditorPlugin::_close_shader(int p_index) {
memdelete(c);
edited_shaders.remove_at(index);
_update_shader_list();
+ EditorNode::get_singleton()->get_undo_redo()->clear_history(); // To prevent undo on deleted graphs.
}
void ShaderEditorPlugin::_resource_saved(Object *obj) {
@@ -965,31 +1312,56 @@ void ShaderEditorPlugin::_resource_saved(Object *obj) {
void ShaderEditorPlugin::_menu_item_pressed(int p_index) {
switch (p_index) {
case FILE_NEW: {
- String base_path = FileSystemDock::get_singleton()->get_current_path();
+ String base_path = FileSystemDock::get_singleton()->get_current_path().get_base_dir();
shader_create_dialog->config(base_path.plus_file("new_shader"), false, false, 0);
shader_create_dialog->popup_centered();
} break;
+ case FILE_NEW_INCLUDE: {
+ String base_path = FileSystemDock::get_singleton()->get_current_path().get_base_dir();
+ shader_create_dialog->config(base_path.plus_file("new_shader"), false, false, 2);
+ shader_create_dialog->popup_centered();
+ } break;
case FILE_OPEN: {
InspectorDock::get_singleton()->open_resource("Shader");
} break;
+ case FILE_OPEN_INCLUDE: {
+ InspectorDock::get_singleton()->open_resource("ShaderInclude");
+ } break;
case FILE_SAVE: {
int index = shader_tabs->get_current_tab();
ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
- EditorNode::get_singleton()->save_resource(edited_shaders[index].shader);
+ if (edited_shaders[index].shader.is_valid()) {
+ EditorNode::get_singleton()->save_resource(edited_shaders[index].shader);
+ } else {
+ EditorNode::get_singleton()->save_resource(edited_shaders[index].shader_inc);
+ }
} break;
case FILE_SAVE_AS: {
int index = shader_tabs->get_current_tab();
ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
- String path = edited_shaders[index].shader->get_path();
- if (!path.is_resource_file()) {
- path = "";
+ String path;
+ if (edited_shaders[index].shader.is_valid()) {
+ path = edited_shaders[index].shader->get_path();
+ if (!path.is_resource_file()) {
+ path = "";
+ }
+ EditorNode::get_singleton()->save_resource_as(edited_shaders[index].shader, path);
+ } else {
+ path = edited_shaders[index].shader_inc->get_path();
+ if (!path.is_resource_file()) {
+ path = "";
+ }
+ EditorNode::get_singleton()->save_resource_as(edited_shaders[index].shader_inc, path);
}
- EditorNode::get_singleton()->save_resource_as(edited_shaders[index].shader, path);
} break;
case FILE_INSPECT: {
int index = shader_tabs->get_current_tab();
ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
- EditorNode::get_singleton()->push_item(edited_shaders[index].shader.ptr());
+ if (edited_shaders[index].shader.is_valid()) {
+ EditorNode::get_singleton()->push_item(edited_shaders[index].shader.ptr());
+ } else {
+ EditorNode::get_singleton()->push_item(edited_shaders[index].shader_inc.ptr());
+ }
} break;
case FILE_CLOSE: {
_close_shader(shader_tabs->get_current_tab());
@@ -1001,6 +1373,10 @@ void ShaderEditorPlugin::_shader_created(Ref<Shader> p_shader) {
EditorNode::get_singleton()->push_item(p_shader.ptr());
}
+void ShaderEditorPlugin::_shader_include_created(Ref<ShaderInclude> p_shader_inc) {
+ EditorNode::get_singleton()->push_item(p_shader_inc.ptr());
+}
+
ShaderEditorPlugin::ShaderEditorPlugin() {
main_split = memnew(HSplitContainer);
@@ -1011,18 +1387,20 @@ ShaderEditorPlugin::ShaderEditorPlugin() {
file_menu = memnew(MenuButton);
file_menu->set_text(TTR("File"));
file_menu->get_popup()->add_item(TTR("New Shader"), FILE_NEW);
+ file_menu->get_popup()->add_item(TTR("New Shader Include"), FILE_NEW_INCLUDE);
file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_item(TTR("Load Shader"), FILE_OPEN);
- file_menu->get_popup()->add_item(TTR("Save Shader"), FILE_SAVE);
- file_menu->get_popup()->add_item(TTR("Save Shader As"), FILE_SAVE_AS);
+ file_menu->get_popup()->add_item(TTR("Load Shader File"), FILE_OPEN);
+ file_menu->get_popup()->add_item(TTR("Load Shader Include File"), FILE_OPEN_INCLUDE);
+ file_menu->get_popup()->add_item(TTR("Save File"), FILE_SAVE);
+ file_menu->get_popup()->add_item(TTR("Save File As"), FILE_SAVE_AS);
file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_item(TTR("Open Shader in Inspector"), FILE_INSPECT);
+ file_menu->get_popup()->add_item(TTR("Open File in Inspector"), FILE_INSPECT);
file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_item(TTR("Close Shader"), FILE_CLOSE);
+ file_menu->get_popup()->add_item(TTR("Close File"), FILE_CLOSE);
file_menu->get_popup()->connect("id_pressed", callable_mp(this, &ShaderEditorPlugin::_menu_item_pressed));
file_hb->add_child(file_menu);
- for (int i = 1; i < FILE_MAX; i++) {
+ for (int i = 2; i < FILE_MAX; i++) {
file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), true);
}
@@ -1045,11 +1423,12 @@ ShaderEditorPlugin::ShaderEditorPlugin() {
button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Shader Editor"), main_split);
// Defer connect because Editor class is not in the binding system yet.
- EditorNode::get_singleton()->call_deferred("connect", "resource_saved", callable_mp(this, &ShaderEditorPlugin::_resource_saved), varray(), CONNECT_DEFERRED);
+ EditorNode::get_singleton()->call_deferred("connect", "resource_saved", callable_mp(this, &ShaderEditorPlugin::_resource_saved), CONNECT_DEFERRED);
shader_create_dialog = memnew(ShaderCreateDialog);
vb->add_child(shader_create_dialog);
shader_create_dialog->connect("shader_created", callable_mp(this, &ShaderEditorPlugin::_shader_created));
+ shader_create_dialog->connect("shader_include_created", callable_mp(this, &ShaderEditorPlugin::_shader_include_created));
}
ShaderEditorPlugin::~ShaderEditorPlugin() {
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index e1e815f939..907de6ea87 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -40,6 +40,7 @@
#include "scene/gui/text_edit.h"
#include "scene/main/timer.h"
#include "scene/resources/shader.h"
+#include "scene/resources/shader_include.h"
#include "servers/rendering/shader_warnings.h"
class ItemList;
@@ -59,12 +60,18 @@ class ShaderTextEditor : public CodeTextEditor {
Ref<CodeHighlighter> syntax_highlighter;
RichTextLabel *warnings_panel = nullptr;
Ref<Shader> shader;
+ Ref<ShaderInclude> shader_inc;
List<ShaderWarning> warnings;
Error last_compile_result = Error::OK;
void _check_shader_mode();
void _update_warning_panel();
+ bool block_shader_changed = false;
+ void _shader_changed();
+
+ uint32_t dependencies_version = 0; // Incremented if deps changed
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -73,13 +80,23 @@ protected:
virtual void _code_complete_script(const String &p_code, List<ScriptLanguage::CodeCompletionOption> *r_options) override;
public:
+ void set_block_shader_changed(bool p_block) { block_shader_changed = p_block; }
+ uint32_t get_dependencies_version() const { return dependencies_version; }
+
virtual void _validate_script() override;
void reload_text();
void set_warnings_panel(RichTextLabel *p_warnings_panel);
Ref<Shader> get_edited_shader() const;
+ Ref<ShaderInclude> get_edited_shader_include() const;
+
void set_edited_shader(const Ref<Shader> &p_shader);
+ void set_edited_shader(const Ref<Shader> &p_shader, const String &p_code);
+ void set_edited_shader_include(const Ref<ShaderInclude> &p_include);
+ void set_edited_shader_include(const Ref<ShaderInclude> &p_include, const String &p_code);
+ void set_edited_code(const String &p_code);
+
ShaderTextEditor();
};
@@ -126,38 +143,50 @@ class ShaderEditor : public PanelContainer {
ConfirmationDialog *disk_changed = nullptr;
ShaderTextEditor *shader_editor = nullptr;
+ bool compilation_success = true;
void _menu_option(int p_option);
mutable Ref<Shader> shader;
+ mutable Ref<ShaderInclude> shader_inc;
void _editor_settings_changed();
void _project_settings_changed();
void _check_for_external_edit();
void _reload_shader_from_disk();
+ void _reload_shader_include_from_disk();
+ void _reload();
void _show_warnings_panel(bool p_show);
void _warning_clicked(Variant p_line);
void _update_warnings(bool p_validate);
+ void _script_validated(bool p_valid) {
+ compilation_success = p_valid;
+ emit_signal(SNAME("validation_changed"));
+ }
+
+ uint32_t dependencies_version = 0xFFFFFFFF;
+
protected:
void _notification(int p_what);
static void _bind_methods();
void _make_context_menu(bool p_selection, Vector2 p_position);
- void _text_edit_gui_input(const Ref<InputEvent> &ev);
+ void _text_edit_gui_input(const Ref<InputEvent> &p_ev);
void _update_bookmark_list();
void _bookmark_item_pressed(int p_idx);
public:
+ bool was_compilation_successful() const { return compilation_success; }
void apply_shaders();
-
void ensure_select_current();
void edit(const Ref<Shader> &p_shader);
-
+ void edit(const Ref<ShaderInclude> &p_shader_inc);
void goto_line_selection(int p_line, int p_begin, int p_end);
+ void save_external_data(const String &p_str = "");
+ void validate_script();
virtual Size2 get_minimum_size() const override { return Size2(0, 200); }
- void save_external_data(const String &p_str = "");
ShaderEditor();
};
@@ -167,6 +196,7 @@ class ShaderEditorPlugin : public EditorPlugin {
struct EditedShader {
Ref<Shader> shader;
+ Ref<ShaderInclude> shader_inc;
ShaderEditor *shader_editor = nullptr;
VisualShaderEditor *visual_shader_editor = nullptr;
};
@@ -175,7 +205,9 @@ class ShaderEditorPlugin : public EditorPlugin {
enum {
FILE_NEW,
+ FILE_NEW_INCLUDE,
FILE_OPEN,
+ FILE_OPEN_INCLUDE,
FILE_SAVE,
FILE_SAVE_AS,
FILE_INSPECT,
@@ -199,6 +231,8 @@ class ShaderEditorPlugin : public EditorPlugin {
void _close_shader(int p_index);
void _shader_created(Ref<Shader> p_shader);
+ void _shader_include_created(Ref<ShaderInclude> p_shader_inc);
+ void _update_shader_list_status();
public:
virtual String get_name() const override { return "Shader"; }
@@ -209,6 +243,7 @@ public:
virtual void selected_notify() override;
ShaderEditor *get_shader_editor(const Ref<Shader> &p_for_shader);
+ VisualShaderEditor *get_visual_shader_editor(const Ref<Shader> &p_for_shader);
virtual void save_external_data() override;
virtual void apply_changes() override;
@@ -217,4 +252,4 @@ public:
~ShaderEditorPlugin();
};
-#endif
+#endif // SHADER_EDITOR_PLUGIN_H
diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp
index 4458555de2..4874944d33 100644
--- a/editor/plugins/shader_file_editor_plugin.cpp
+++ b/editor/plugins/shader_file_editor_plugin.cpp
@@ -37,7 +37,6 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
-#include "editor/property_editor.h"
#include "servers/display_server.h"
#include "servers/rendering/shader_types.h"
@@ -282,7 +281,7 @@ ShaderFileEditor::ShaderFileEditor() {
stage_hb->add_child(button);
stages[i] = button;
button->set_button_group(bg);
- button->connect("pressed", callable_mp(this, &ShaderFileEditor::_version_selected), varray(i));
+ button->connect("pressed", callable_mp(this, &ShaderFileEditor::_version_selected).bind(i));
}
error_text = memnew(RichTextLabel);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 8845fe9eca..c453ed26aa 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -42,6 +42,7 @@
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/resources/capsule_shape_3d.h"
+#include "scene/resources/skeleton_profile.h"
#include "scene/resources/sphere_shape_3d.h"
#include "scene/resources/surface_tool.h"
@@ -156,7 +157,7 @@ void BoneTransformEditor::_property_keyed(const String &p_path, bool p_advance)
if (split.size() == 3 && split[0] == "bones") {
int bone_idx = split[1].to_int();
if (split[2] == "position") {
- te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_POSITION_3D, skeleton->get(p_path));
+ te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_POSITION_3D, (Vector3)skeleton->get(p_path) / skeleton->get_motion_scale());
}
if (split[2] == "rotation") {
te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_ROTATION_3D, skeleton->get(p_path));
@@ -250,6 +251,10 @@ void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
create_physical_skeleton();
break;
}
+ case SKELETON_OPTION_EXPORT_SKELETON_PROFILE: {
+ export_skeleton_profile();
+ break;
+ }
}
}
@@ -314,7 +319,7 @@ void Skeleton3DEditor::insert_keys(const bool p_all_bones) {
}
if (pos_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_POSITION_3D))) {
- te->insert_transform_key(skeleton, name, Animation::TYPE_POSITION_3D, skeleton->get_bone_pose_position(i));
+ te->insert_transform_key(skeleton, name, Animation::TYPE_POSITION_3D, skeleton->get_bone_pose_position(i) / skeleton->get_motion_scale());
}
if (rot_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_ROTATION_3D))) {
te->insert_transform_key(skeleton, name, Animation::TYPE_ROTATION_3D, skeleton->get_bone_pose_rotation(i));
@@ -451,6 +456,73 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi
return physical_bone;
}
+void Skeleton3DEditor::export_skeleton_profile() {
+ file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
+ file_dialog->set_title(TTR("Export Skeleton Profile As..."));
+
+ List<String> exts;
+ ResourceLoader::get_recognized_extensions_for_type("SkeletonProfile", &exts);
+ file_dialog->clear_filters();
+ for (const String &K : exts) {
+ file_dialog->add_filter("*." + K);
+ }
+
+ file_dialog->popup_file_dialog();
+}
+
+void Skeleton3DEditor::_file_selected(const String &p_file) {
+ // Export SkeletonProfile.
+ Ref<SkeletonProfile> sp(memnew(SkeletonProfile));
+
+ // Build SkeletonProfile.
+ sp->set_group_size(1);
+
+ Vector<Vector2> handle_positions;
+ Vector2 position_max;
+ Vector2 position_min;
+
+ int len = skeleton->get_bone_count();
+ sp->set_bone_size(len);
+ for (int i = 0; i < len; i++) {
+ sp->set_bone_name(i, skeleton->get_bone_name(i));
+ int parent = skeleton->get_bone_parent(i);
+ if (parent >= 0) {
+ sp->set_bone_parent(i, skeleton->get_bone_name(parent));
+ }
+ sp->set_reference_pose(i, skeleton->get_bone_rest(i));
+
+ Transform3D grest = skeleton->get_bone_global_rest(i);
+ handle_positions.append(Vector2(grest.origin.x, grest.origin.y));
+ if (i == 0) {
+ position_max = Vector2(grest.origin.x, grest.origin.y);
+ position_min = Vector2(grest.origin.x, grest.origin.y);
+ } else {
+ position_max.x = MAX(grest.origin.x, position_max.x);
+ position_max.y = MAX(grest.origin.y, position_max.y);
+ position_min.x = MIN(grest.origin.x, position_min.x);
+ position_min.y = MIN(grest.origin.y, position_min.y);
+ }
+ }
+
+ // Layout handles provisionaly.
+ Vector2 bound = Vector2(position_max.x - position_min.x, position_max.y - position_min.y);
+ Vector2 center = Vector2((position_max.x + position_min.x) * 0.5, (position_max.y + position_min.y) * 0.5);
+ float nrm = MAX(bound.x, bound.y);
+ if (nrm > 0) {
+ for (int i = 0; i < len; i++) {
+ handle_positions.write[i] = (handle_positions[i] - center) / nrm * 0.9;
+ sp->set_handle_offset(i, Vector2(0.5 + handle_positions[i].x, 0.5 - handle_positions[i].y));
+ }
+ }
+
+ Error err = ResourceSaver::save(sp, p_file);
+
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), p_file));
+ return;
+ }
+}
+
Variant Skeleton3DEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
TreeItem *selected = joint_tree->get_selected();
@@ -631,6 +703,11 @@ void Skeleton3DEditor::create_editors() {
Node3DEditor *ne = Node3DEditor::get_singleton();
AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor();
+ // Create File dialog.
+ file_dialog = memnew(EditorFileDialog);
+ file_dialog->connect("file_selected", callable_mp(this, &Skeleton3DEditor::_file_selected));
+ add_child(file_dialog);
+
// Create Top Menu Bar.
separator = memnew(VSeparator);
ne->add_control_to_menu_panel(separator);
@@ -649,6 +726,7 @@ void Skeleton3DEditor::create_editors() {
p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/all_poses_to_rests", TTR("Apply all poses to rests")), SKELETON_OPTION_ALL_POSES_TO_RESTS);
p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/selected_poses_to_rests", TTR("Apply selected poses to rests")), SKELETON_OPTION_SELECTED_POSES_TO_RESTS);
p->add_item(TTR("Create physical skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
+ p->add_item(TTR("Export skeleton profile"), SKELETON_OPTION_EXPORT_SKELETON_PROFILE);
p->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_skeleton_option));
set_bone_options_enabled(false);
@@ -704,7 +782,7 @@ void Skeleton3DEditor::create_editors() {
key_insert_button = memnew(Button);
key_insert_button->set_flat(true);
key_insert_button->set_focus_mode(FOCUS_NONE);
- key_insert_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(false));
+ key_insert_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys).bind(false));
key_insert_button->set_tooltip(TTR("Insert key of bone poses already exist track."));
key_insert_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_to_existing_tracks", TTR("Insert Key (Existing Tracks)"), Key::INSERT));
animation_hb->add_child(key_insert_button);
@@ -712,7 +790,7 @@ void Skeleton3DEditor::create_editors() {
key_insert_all_button = memnew(Button);
key_insert_all_button->set_flat(true);
key_insert_all_button->set_focus_mode(FOCUS_NONE);
- key_insert_all_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(true));
+ key_insert_all_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys).bind(true));
key_insert_all_button->set_tooltip(TTR("Insert key of all bone poses."));
key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTR("Insert Key (All Bones)"), KeyModifierMask::CMD + Key::INSERT));
animation_hb->add_child(key_insert_all_button);
@@ -758,7 +836,7 @@ void Skeleton3DEditor::_notification(int p_what) {
key_scale_button->set_icon(get_theme_icon(SNAME("KeyScale"), SNAME("EditorIcons")));
key_insert_button->set_icon(get_theme_icon(SNAME("Key"), SNAME("EditorIcons")));
key_insert_all_button->set_icon(get_theme_icon(SNAME("NewKey"), SNAME("EditorIcons")));
- get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Vector<Variant>(), Object::CONNECT_ONESHOT);
+ get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Object::CONNECT_ONESHOT);
break;
}
case NOTIFICATION_ENTER_TREE: {
@@ -843,8 +921,8 @@ void fragment() {
)");
handle_material->set_shader(handle_shader);
Ref<Texture2D> handle = EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("EditorBoneHandle"), SNAME("EditorIcons"));
- handle_material->set_shader_param("point_size", handle->get_width());
- handle_material->set_shader_param("texture_albedo", handle);
+ handle_material->set_shader_uniform("point_size", handle->get_width());
+ handle_material->set_shader_uniform("texture_albedo", handle);
handles_mesh_instance = memnew(MeshInstance3D);
handles_mesh_instance->set_cast_shadows_setting(GeometryInstance3D::SHADOW_CASTING_SETTING_OFF);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h
index 8f03e7c8db..975b54fa77 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.h
+++ b/editor/plugins/skeleton_3d_editor_plugin.h
@@ -101,6 +101,7 @@ class Skeleton3DEditor : public VBoxContainer {
SKELETON_OPTION_ALL_POSES_TO_RESTS,
SKELETON_OPTION_SELECTED_POSES_TO_RESTS,
SKELETON_OPTION_CREATE_PHYSICAL_SKELETON,
+ SKELETON_OPTION_EXPORT_SKELETON_PROFILE,
};
struct BoneInfo {
@@ -155,6 +156,8 @@ class Skeleton3DEditor : public VBoxContainer {
void create_physical_skeleton();
PhysicalBone3D *create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos);
+ void export_skeleton_profile();
+
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index ad817f9a41..3323d865c2 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -122,7 +122,7 @@ void Sprite2DEditor::_menu_option(int p_option) {
switch (p_option) {
case MENU_OPTION_CONVERT_TO_MESH_2D: {
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create MeshInstance2D"));
+ debug_uv_dialog->set_ok_button_text(TTR("Create MeshInstance2D"));
debug_uv_dialog->set_title(TTR("MeshInstance2D Preview"));
_update_mesh_data();
@@ -131,7 +131,7 @@ void Sprite2DEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_CONVERT_TO_POLYGON_2D: {
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create Polygon2D"));
+ debug_uv_dialog->set_ok_button_text(TTR("Create Polygon2D"));
debug_uv_dialog->set_title(TTR("Polygon2D Preview"));
_update_mesh_data();
@@ -139,7 +139,7 @@ void Sprite2DEditor::_menu_option(int p_option) {
debug_uv->update();
} break;
case MENU_OPTION_CREATE_COLLISION_POLY_2D: {
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create CollisionPolygon2D"));
+ debug_uv_dialog->set_ok_button_text(TTR("Create CollisionPolygon2D"));
debug_uv_dialog->set_title(TTR("CollisionPolygon2D Preview"));
_update_mesh_data();
@@ -148,7 +148,7 @@ void Sprite2DEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D: {
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create LightOccluder2D"));
+ debug_uv_dialog->set_ok_button_text(TTR("Create LightOccluder2D"));
debug_uv_dialog->set_title(TTR("LightOccluder2D Preview"));
_update_mesh_data();
diff --git a/editor/plugins/sprite_2d_editor_plugin.h b/editor/plugins/sprite_2d_editor_plugin.h
index 8e3dc19c7e..b87f108bd2 100644
--- a/editor/plugins/sprite_2d_editor_plugin.h
+++ b/editor/plugins/sprite_2d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SPRITE_EDITOR_PLUGIN_H
-#define SPRITE_EDITOR_PLUGIN_H
+#ifndef SPRITE_2D_EDITOR_PLUGIN_H
+#define SPRITE_2D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/2d/sprite_2d.h"
@@ -111,4 +111,4 @@ public:
~Sprite2DEditorPlugin();
};
-#endif // SPRITE_EDITOR_PLUGIN_H
+#endif // SPRITE_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 8a40ffbe38..a39d24a167 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -119,7 +119,7 @@ void SpriteFramesEditor::_sheet_preview_draw() {
if (frames_selected.size() == 0) {
split_sheet_dialog->get_ok_button()->set_disabled(true);
- split_sheet_dialog->get_ok_button()->set_text(TTR("No Frames Selected"));
+ split_sheet_dialog->set_ok_button_text(TTR("No Frames Selected"));
return;
}
@@ -140,7 +140,7 @@ void SpriteFramesEditor::_sheet_preview_draw() {
}
split_sheet_dialog->get_ok_button()->set_disabled(false);
- split_sheet_dialog->get_ok_button()->set_text(vformat(TTR("Add %d Frame(s)"), frames_selected.size()));
+ split_sheet_dialog->set_ok_button_text(vformat(TTR("Add %d Frame(s)"), frames_selected.size()));
}
void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
@@ -423,6 +423,7 @@ void SpriteFramesEditor::_notification(int p_what) {
zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons")));
new_anim->set_icon(get_theme_icon(SNAME("New"), SNAME("EditorIcons")));
remove_anim->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ anim_search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
split_sheet_zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons")));
split_sheet_zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons")));
split_sheet_zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons")));
@@ -449,7 +450,7 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_
dialog->set_title(TTR("Error!"));
//dialog->get_cancel()->set_text("Close");
- dialog->get_ok_button()->set_text(TTR("Close"));
+ dialog->set_ok_button_text(TTR("Close"));
dialog->popup_centered();
return; ///beh should show an error i guess
}
@@ -516,7 +517,7 @@ void SpriteFramesEditor::_paste_pressed() {
dialog->set_text(TTR("Resource clipboard is empty or not a texture!"));
dialog->set_title(TTR("Error!"));
//dialog->get_cancel()->set_text("Close");
- dialog->get_ok_button()->set_text(TTR("Close"));
+ dialog->set_ok_button_text(TTR("Close"));
dialog->popup_centered();
return; ///beh should show an error i guess
}
@@ -750,7 +751,7 @@ void SpriteFramesEditor::_animation_name_edited() {
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
- edited_anim = new_name;
+ edited_anim = name;
undo_redo->commit_action();
}
@@ -816,6 +817,10 @@ void SpriteFramesEditor::_animation_remove_confirmed() {
undo_redo->commit_action();
}
+void SpriteFramesEditor::_animation_search_text_changed(const String &p_text) {
+ _update_library();
+}
+
void SpriteFramesEditor::_animation_loop_changed() {
if (updating) {
return;
@@ -900,14 +905,19 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
TreeItem *anim_root = animations->create_item();
List<StringName> anim_names;
-
frames->get_animation_list(&anim_names);
-
anim_names.sort_custom<StringName::AlphCompare>();
+ bool searching = anim_search_box->get_text().size();
+ String searched_string = searching ? anim_search_box->get_text().to_lower() : String();
+
for (const StringName &E : anim_names) {
String name = E;
+ if (searching && name.to_lower().find(searched_string) < 0) {
+ continue;
+ }
+
TreeItem *it = animations->create_item(anim_root);
it->set_metadata(0, name);
@@ -970,7 +980,6 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
anim_loop->set_pressed(frames->get_animation_loop(edited_anim));
updating = false;
- //player->add_resource("default",resource);
}
void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
@@ -1157,6 +1166,13 @@ SpriteFramesEditor::SpriteFramesEditor() {
hbc_animlist->add_child(remove_anim);
remove_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_remove));
+ anim_search_box = memnew(LineEdit);
+ hbc_animlist->add_child(anim_search_box);
+ anim_search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ anim_search_box->set_placeholder(TTR("Filter Animations"));
+ anim_search_box->set_clear_button_enabled(true);
+ anim_search_box->connect("text_changed", callable_mp(this, &SpriteFramesEditor::_animation_search_text_changed));
+
animations = memnew(Tree);
sub_vb->add_child(animations);
animations->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -1290,7 +1306,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
empty2->connect("pressed", callable_mp(this, &SpriteFramesEditor::_empty2_pressed));
move_up->connect("pressed", callable_mp(this, &SpriteFramesEditor::_up_pressed));
move_down->connect("pressed", callable_mp(this, &SpriteFramesEditor::_down_pressed));
- file->connect("files_selected", callable_mp(this, &SpriteFramesEditor::_file_load_request), make_binds(-1));
+ file->connect("files_selected", callable_mp(this, &SpriteFramesEditor::_file_load_request).bind(-1));
loading_scene = false;
sel = -1;
@@ -1317,7 +1333,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_h->set_max(128);
split_sheet_h->set_step(1);
split_sheet_hb->add_child(split_sheet_h);
- split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_FRAME_COUNT));
+ split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_FRAME_COUNT));
split_sheet_hb->add_child(memnew(Label(TTR("Vertical:"))));
split_sheet_v = memnew(SpinBox);
@@ -1325,7 +1341,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_v->set_max(128);
split_sheet_v->set_step(1);
split_sheet_hb->add_child(split_sheet_v);
- split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_FRAME_COUNT));
+ split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_FRAME_COUNT));
split_sheet_hb->add_child(memnew(VSeparator));
split_sheet_hb->add_child(memnew(Label(TTR("Size:"))));
@@ -1333,13 +1349,13 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_size_x->set_min(1);
split_sheet_size_x->set_step(1);
split_sheet_size_x->set_suffix("px");
- split_sheet_size_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_SIZE));
+ split_sheet_size_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_SIZE));
split_sheet_hb->add_child(split_sheet_size_x);
split_sheet_size_y = memnew(SpinBox);
split_sheet_size_y->set_min(1);
split_sheet_size_y->set_step(1);
split_sheet_size_y->set_suffix("px");
- split_sheet_size_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_SIZE));
+ split_sheet_size_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_SIZE));
split_sheet_hb->add_child(split_sheet_size_y);
split_sheet_hb->add_child(memnew(VSeparator));
@@ -1348,13 +1364,13 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_sep_x->set_min(0);
split_sheet_sep_x->set_step(1);
split_sheet_sep_x->set_suffix("px");
- split_sheet_sep_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_sep_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
split_sheet_hb->add_child(split_sheet_sep_x);
split_sheet_sep_y = memnew(SpinBox);
split_sheet_sep_y->set_min(0);
split_sheet_sep_y->set_step(1);
split_sheet_sep_y->set_suffix("px");
- split_sheet_sep_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_sep_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
split_sheet_hb->add_child(split_sheet_sep_y);
split_sheet_hb->add_child(memnew(VSeparator));
@@ -1363,13 +1379,13 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_offset_x->set_min(0);
split_sheet_offset_x->set_step(1);
split_sheet_offset_x->set_suffix("px");
- split_sheet_offset_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_offset_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
split_sheet_hb->add_child(split_sheet_offset_x);
split_sheet_offset_y = memnew(SpinBox);
split_sheet_offset_y->set_min(0);
split_sheet_offset_y->set_step(1);
split_sheet_offset_y->set_suffix("px");
- split_sheet_offset_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_offset_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
split_sheet_hb->add_child(split_sheet_offset_y);
split_sheet_hb->add_spacer();
@@ -1448,6 +1464,10 @@ SpriteFramesEditor::SpriteFramesEditor() {
max_sheet_zoom = 16.0f * MAX(1.0f, EDSCALE);
min_sheet_zoom = 0.01f * MAX(1.0f, EDSCALE);
_zoom_reset();
+
+ // Ensure the anim search box is wide enough by default.
+ // Not by setting its minimum size so it can still be shrinked if desired.
+ set_split_offset(56 * EDSCALE);
}
void SpriteFramesEditorPlugin::edit(Object *p_object) {
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index 3c8c5ef19d..6352259b73 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -37,6 +37,7 @@
#include "scene/gui/check_button.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/item_list.h"
+#include "scene/gui/line_edit.h"
#include "scene/gui/scroll_container.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/split_container.h"
@@ -73,6 +74,7 @@ class SpriteFramesEditor : public HSplitContainer {
Button *new_anim = nullptr;
Button *remove_anim = nullptr;
+ LineEdit *anim_search_box = nullptr;
Tree *animations = nullptr;
SpinBox *anim_speed = nullptr;
@@ -137,6 +139,7 @@ class SpriteFramesEditor : public HSplitContainer {
void _animation_add();
void _animation_remove();
void _animation_remove_confirmed();
+ void _animation_search_text_changed(const String &p_text);
void _animation_loop_changed();
void _animation_fps_changed(double p_value);
diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index 1281ce0cfd..d4baff34e2 100644
--- a/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
@@ -132,7 +132,7 @@ StyleBoxPreview::StyleBoxPreview() {
preview->set_clip_contents(true);
preview->connect("draw", callable_mp(this, &StyleBoxPreview::_redraw));
checkerboard->add_child(preview);
- preview->set_anchors_and_offsets_preset(PRESET_WIDE);
+ preview->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
add_margin_child(TTR("Preview:"), checkerboard);
grid_preview = memnew(TextureButton);
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/text_editor.cpp b/editor/plugins/text_editor.cpp
index 7ca65c073d..196d87da36 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -32,6 +32,7 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
void TextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
ERR_FAIL_COND(p_highlighter.is_null());
@@ -275,7 +276,7 @@ void TextEditor::update_settings() {
void TextEditor::set_tooltip_request_func(const Callable &p_toolip_callback) {
Variant args[1] = { this };
const Variant *argp[] = { &args[0] };
- code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bind(argp, 1));
+ code_editor->get_text_editor()->set_tooltip_request_func(p_toolip_callback.bindp(argp, 1));
}
Control *TextEditor::get_edit_menu() {
@@ -524,7 +525,7 @@ TextEditor::TextEditor() {
code_editor->add_theme_constant_override("separation", 0);
code_editor->connect("load_theme_settings", callable_mp(this, &TextEditor::_load_theme_settings));
code_editor->connect("validate_script", callable_mp(this, &TextEditor::_validate_script));
- code_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ code_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
code_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
code_editor->show_toggle_scripts_button();
diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp
index 0fc7079a24..64cafa17f3 100644
--- a/editor/plugins/texture_3d_editor_plugin.cpp
+++ b/editor/plugins/texture_3d_editor_plugin.cpp
@@ -57,8 +57,8 @@ void Texture3DEditor::_texture_changed() {
}
void Texture3DEditor::_update_material() {
- material->set_shader_param("layer", (layer->get_value() + 0.5) / texture->get_depth());
- material->set_shader_param("tex", texture->get_rid());
+ material->set_shader_uniform("layer", (layer->get_value() + 0.5) / texture->get_depth());
+ material->set_shader_uniform("tex", texture->get_rid());
String format = Image::get_format_name(texture->get_format());
diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h
index 2f7f6f83bb..357bdb0845 100644
--- a/editor/plugins/texture_3d_editor_plugin.h
+++ b/editor/plugins/texture_3d_editor_plugin.h
@@ -91,4 +91,4 @@ public:
Texture3DEditorPlugin();
};
-#endif // TEXTURE_EDITOR_PLUGIN_H
+#endif // TEXTURE_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index 15f03fd46d..f6b02d5f80 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -59,7 +59,7 @@ void TexturePreview::_notification(int p_what) {
}
void TexturePreview::_update_metadata_label_text() {
- Ref<Texture2D> texture = texture_display->get_texture();
+ const Ref<Texture2D> texture = texture_display->get_texture();
String format;
if (Object::cast_to<ImageTexture>(*texture)) {
@@ -70,7 +70,49 @@ void TexturePreview::_update_metadata_label_text() {
format = texture->get_class();
}
- metadata_label->set_text(vformat(String::utf8("%s×%s %s"), itos(texture->get_width()), itos(texture->get_height()), format));
+ const Ref<Image> image = texture->get_image();
+ if (image.is_valid()) {
+ const int mipmaps = image->get_mipmap_count();
+ // Avoid signed integer overflow that could occur with huge texture sizes by casting everything to uint64_t.
+ uint64_t memory = uint64_t(image->get_width()) * uint64_t(image->get_height()) * uint64_t(Image::get_format_pixel_size(image->get_format()));
+ // Handle VRAM-compressed formats that are stored with 4 bpp.
+ memory >>= Image::get_format_pixel_rshift(image->get_format());
+
+ float mipmaps_multiplier = 1.0;
+ float mipmap_increase = 0.25;
+ for (int i = 0; i < mipmaps; i++) {
+ // Each mip adds 25% memory usage of the previous one.
+ // With a complete mipmap chain, memory usage increases by ~33%.
+ mipmaps_multiplier += mipmap_increase;
+ mipmap_increase *= 0.25;
+ }
+ memory *= mipmaps_multiplier;
+
+ if (mipmaps >= 1) {
+ metadata_label->set_text(
+ vformat(String::utf8("%d×%d %s\n") + TTR("%s Mipmaps") + "\n" + TTR("Memory: %s"),
+ texture->get_width(),
+ texture->get_height(),
+ format,
+ mipmaps,
+ String::humanize_size(memory)));
+ } else {
+ // "No Mipmaps" is easier to distinguish than "0 Mipmaps",
+ // especially since 0, 6, and 8 look quite close with the default code font.
+ metadata_label->set_text(
+ vformat(String::utf8("%d×%d %s\n") + TTR("No Mipmaps") + "\n" + TTR("Memory: %s"),
+ texture->get_width(),
+ texture->get_height(),
+ format,
+ String::humanize_size(memory)));
+ }
+ } else {
+ metadata_label->set_text(
+ vformat(String::utf8("%d×%d %s"),
+ texture->get_width(),
+ texture->get_height(),
+ format));
+ }
}
TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
@@ -82,7 +124,7 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
texture_display = memnew(TextureRect);
texture_display->set_texture(p_texture);
- texture_display->set_anchors_preset(TextureRect::PRESET_WIDE);
+ texture_display->set_anchors_preset(TextureRect::PRESET_FULL_RECT);
texture_display->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
texture_display->set_ignore_texture_size(true);
add_child(texture_display);
@@ -97,11 +139,9 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
metadata_label->add_theme_color_override("font_color", Color::named("white"));
metadata_label->add_theme_color_override("font_color_shadow", Color::named("black"));
- metadata_label->add_theme_font_size_override("font_size", 16 * EDSCALE);
+ metadata_label->add_theme_font_size_override("font_size", 14 * EDSCALE);
metadata_label->add_theme_color_override("font_outline_color", Color::named("black"));
- metadata_label->add_theme_constant_override("outline_size", 2 * EDSCALE);
-
- metadata_label->add_theme_constant_override("shadow_outline_size", 1);
+ metadata_label->add_theme_constant_override("outline_size", 8 * EDSCALE);
metadata_label->set_h_size_flags(Control::SIZE_SHRINK_END);
metadata_label->set_v_size_flags(Control::SIZE_SHRINK_END);
diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp
index cb146fd342..2c6f70463d 100644
--- a/editor/plugins/texture_layered_editor_plugin.cpp
+++ b/editor/plugins/texture_layered_editor_plugin.cpp
@@ -68,9 +68,9 @@ void TextureLayeredEditor::_texture_changed() {
}
void TextureLayeredEditor::_update_material() {
- materials[0]->set_shader_param("layer", layer->get_value());
- materials[2]->set_shader_param("layer", layer->get_value());
- materials[texture->get_layered_type()]->set_shader_param("tex", texture->get_rid());
+ materials[0]->set_shader_uniform("layer", layer->get_value());
+ materials[2]->set_shader_uniform("layer", layer->get_value());
+ materials[texture->get_layered_type()]->set_shader_uniform("tex", texture->get_rid());
Vector3 v(1, 1, 1);
v.normalize();
@@ -79,10 +79,10 @@ void TextureLayeredEditor::_update_material() {
b.rotate(Vector3(1, 0, 0), x_rot);
b.rotate(Vector3(0, 1, 0), y_rot);
- materials[1]->set_shader_param("normal", v);
- materials[1]->set_shader_param("rot", b);
- materials[2]->set_shader_param("normal", v);
- materials[2]->set_shader_param("rot", b);
+ materials[1]->set_shader_uniform("normal", v);
+ materials[1]->set_shader_uniform("rot", b);
+ materials[2]->set_shader_uniform("normal", v);
+ materials[2]->set_shader_uniform("rot", b);
String format = Image::get_format_name(texture->get_format());
diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h
index 830916e954..f49aa83eb2 100644
--- a/editor/plugins/texture_layered_editor_plugin.h
+++ b/editor/plugins/texture_layered_editor_plugin.h
@@ -93,4 +93,4 @@ public:
TextureLayeredEditorPlugin();
};
-#endif // TEXTURE_EDITOR_PLUGIN_H
+#endif // TEXTURE_LAYERED_EDITOR_PLUGIN_H
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 3f4f9a4f4d..0bd8a8a484 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -35,7 +35,9 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/gui/check_box.h"
+#include "scene/gui/separator.h"
#include "scene/gui/view_panner.h"
#include "scene/resources/texture.h"
@@ -239,7 +241,7 @@ void TextureRegionEditor::_region_draw() {
hscroll->set_value((hscroll->get_min() + hscroll->get_max() - hscroll->get_page()) / 2);
vscroll->set_value((vscroll->get_min() + vscroll->get_max() - vscroll->get_page()) / 2);
// This ensures that the view is updated correctly.
- callable_bind(callable_mp(this, &TextureRegionEditor::_pan_callback), Vector2(1, 0)).call_deferred(nullptr, 0);
+ callable_mp(this, &TextureRegionEditor::_pan_callback).bind(Vector2(1, 0)).call_deferredp(nullptr, 0);
request_center = false;
}
@@ -989,7 +991,7 @@ Vector2 TextureRegionEditor::snap_point(Vector2 p_target) const {
}
TextureRegionEditor::TextureRegionEditor() {
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
VBoxContainer *vb = memnew(VBoxContainer);
add_child(vb);
node_sprite_2d = nullptr;
@@ -1153,7 +1155,7 @@ bool EditorInspectorPluginTextureRegion::parse_property(Object *p_object, const
if (((Object::cast_to<Sprite2D>(p_object) || Object::cast_to<Sprite3D>(p_object) || Object::cast_to<NinePatchRect>(p_object) || Object::cast_to<StyleBoxTexture>(p_object)) && p_path == "region_rect") || (Object::cast_to<AtlasTexture>(p_object) && p_path == "region")) {
Button *button = EditorInspector::create_inspector_action_button(TTR("Edit Region"));
button->set_icon(texture_region_editor->get_theme_icon(SNAME("RegionEdit"), SNAME("EditorIcons")));
- button->connect("pressed", callable_mp(this, &EditorInspectorPluginTextureRegion::_region_edit), varray(p_object));
+ button->connect("pressed", callable_mp(this, &EditorInspectorPluginTextureRegion::_region_edit).bind(p_object));
add_property_editor(p_path, button, true);
}
}
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index c7dc61b3a8..bbc22c8622 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_resource_picker.h"
#include "editor/editor_scale.h"
#include "editor/progress_dialog.h"
+#include "scene/gui/color_picker.h"
void ThemeItemImportTree::_update_items_tree() {
import_items_tree->clear();
@@ -70,9 +71,17 @@ void ThemeItemImportTree::_update_items_tree() {
for (const StringName &E : types) {
String type_name = (String)E;
+ Ref<Texture2D> type_icon;
+ if (E == "") {
+ type_icon = get_theme_icon(SNAME("NodeDisabled"), SNAME("EditorIcons"));
+ } else {
+ type_icon = EditorNode::get_singleton()->get_class_icon(E, "NodeDisabled");
+ }
+
TreeItem *type_node = import_items_tree->create_item(root);
type_node->set_meta("_can_be_imported", false);
type_node->set_collapsed(true);
+ type_node->set_icon(0, type_icon);
type_node->set_text(0, type_name);
type_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK);
type_node->set_checked(IMPORT_ITEM, false);
@@ -214,7 +223,7 @@ void ThemeItemImportTree::_update_items_tree() {
if (color_amount > 0) {
Array arr;
arr.push_back(color_amount);
- select_colors_label->set_text(TTRN("One color", "{num} colors", color_amount).format(arr, "{num}"));
+ select_colors_label->set_text(TTRN("1 color", "{num} colors", color_amount).format(arr, "{num}"));
select_all_colors_button->set_visible(true);
select_full_colors_button->set_visible(true);
deselect_all_colors_button->set_visible(true);
@@ -228,7 +237,7 @@ void ThemeItemImportTree::_update_items_tree() {
if (constant_amount > 0) {
Array arr;
arr.push_back(constant_amount);
- select_constants_label->set_text(TTRN("One constant", "{num} constants", constant_amount).format(arr, "{num}"));
+ select_constants_label->set_text(TTRN("1 constant", "{num} constants", constant_amount).format(arr, "{num}"));
select_all_constants_button->set_visible(true);
select_full_constants_button->set_visible(true);
deselect_all_constants_button->set_visible(true);
@@ -242,7 +251,7 @@ void ThemeItemImportTree::_update_items_tree() {
if (font_amount > 0) {
Array arr;
arr.push_back(font_amount);
- select_fonts_label->set_text(TTRN("One font", "{num} fonts", font_amount).format(arr, "{num}"));
+ select_fonts_label->set_text(TTRN("1 font", "{num} fonts", font_amount).format(arr, "{num}"));
select_all_fonts_button->set_visible(true);
select_full_fonts_button->set_visible(true);
deselect_all_fonts_button->set_visible(true);
@@ -256,7 +265,7 @@ void ThemeItemImportTree::_update_items_tree() {
if (font_size_amount > 0) {
Array arr;
arr.push_back(font_size_amount);
- select_font_sizes_label->set_text(TTRN("One font size", "{num} font sizes", font_size_amount).format(arr, "{num}"));
+ select_font_sizes_label->set_text(TTRN("1 font size", "{num} font sizes", font_size_amount).format(arr, "{num}"));
select_all_font_sizes_button->set_visible(true);
select_full_font_sizes_button->set_visible(true);
deselect_all_font_sizes_button->set_visible(true);
@@ -270,7 +279,7 @@ void ThemeItemImportTree::_update_items_tree() {
if (icon_amount > 0) {
Array arr;
arr.push_back(icon_amount);
- select_icons_label->set_text(TTRN("One icon", "{num} icons", icon_amount).format(arr, "{num}"));
+ select_icons_label->set_text(TTRN("1 icon", "{num} icons", icon_amount).format(arr, "{num}"));
select_all_icons_button->set_visible(true);
select_full_icons_button->set_visible(true);
deselect_all_icons_button->set_visible(true);
@@ -286,7 +295,7 @@ void ThemeItemImportTree::_update_items_tree() {
if (stylebox_amount > 0) {
Array arr;
arr.push_back(stylebox_amount);
- select_styleboxes_label->set_text(TTRN("One stylebox", "{num} styleboxes", stylebox_amount).format(arr, "{num}"));
+ select_styleboxes_label->set_text(TTRN("1 stylebox", "{num} styleboxes", stylebox_amount).format(arr, "{num}"));
select_all_styleboxes_button->set_visible(true);
select_full_styleboxes_button->set_visible(true);
deselect_all_styleboxes_button->set_visible(true);
@@ -1095,15 +1104,15 @@ ThemeItemImportTree::ThemeItemImportTree() {
select_all_items_button->set_flat(true);
select_all_items_button->set_tooltip(select_all_items_tooltip);
button_set->add_child(select_all_items_button);
- select_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_data_type_pressed), varray(i));
+ select_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_data_type_pressed).bind(i));
select_full_items_button->set_flat(true);
select_full_items_button->set_tooltip(select_full_items_tooltip);
button_set->add_child(select_full_items_button);
- select_full_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_data_type_pressed), varray(i));
+ select_full_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_data_type_pressed).bind(i));
deselect_all_items_button->set_flat(true);
deselect_all_items_button->set_tooltip(deselect_all_items_tooltip);
button_set->add_child(deselect_all_items_button);
- deselect_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_data_type_pressed), varray(i));
+ deselect_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_data_type_pressed).bind(i));
total_selected_items_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
total_selected_items_label->hide();
@@ -1134,12 +1143,12 @@ ThemeItemImportTree::ThemeItemImportTree() {
import_collapse_types_button->set_flat(true);
import_collapse_types_button->set_tooltip(TTR("Collapse types."));
import_buttons->add_child(import_collapse_types_button);
- import_collapse_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(true));
+ import_collapse_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items).bind(true));
import_expand_types_button = memnew(Button);
import_expand_types_button->set_flat(true);
import_expand_types_button->set_tooltip(TTR("Expand types."));
import_buttons->add_child(import_expand_types_button);
- import_expand_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(false));
+ import_expand_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items).bind(false));
import_buttons->add_child(memnew(VSeparator));
@@ -1170,6 +1179,8 @@ ThemeItemImportTree::ThemeItemImportTree() {
import_add_selected_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_import_selected));
}
+///////////////////////
+
void ThemeItemEditorDialog::ok_pressed() {
if (import_default_theme_items->has_selected_items() || import_editor_theme_items->has_selected_items() || import_other_theme_items->has_selected_items()) {
confirm_closing_dialog->set_text(TTR("Import Items tab has some items selected. Selection will be lost upon closing this window.\nClose anyway?"));
@@ -1867,6 +1878,8 @@ void ThemeItemEditorDialog::_notification(int p_what) {
edit_items_remove_custom->set_icon(get_theme_icon(SNAME("ThemeRemoveCustomItems"), SNAME("EditorIcons")));
edit_items_remove_all->set_icon(get_theme_icon(SNAME("ThemeRemoveAllItems"), SNAME("EditorIcons")));
+ edit_add_type_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+
import_another_theme_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
} break;
}
@@ -1883,7 +1896,7 @@ void ThemeItemEditorDialog::set_edited_theme(const Ref<Theme> &p_theme) {
ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_editor) {
set_title(TTR("Manage Theme Items"));
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
set_hide_on_ok(false); // Closing may require a confirmation in some cases.
theme_type_editor = p_theme_type_editor;
@@ -1924,10 +1937,9 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito
edit_add_type_value->set_h_size_flags(Control::SIZE_EXPAND_FILL);
edit_add_type_value->connect("text_submitted", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type));
edit_add_type_hb->add_child(edit_add_type_value);
- Button *edit_add_type_button = memnew(Button);
- edit_add_type_button->set_text(TTR("Add"));
+ edit_add_type_button = memnew(Button);
edit_add_type_hb->add_child(edit_add_type_button);
- edit_add_type_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type), varray(""));
+ edit_add_type_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type).bind(""));
VBoxContainer *edit_items_vb = memnew(VBoxContainer);
edit_items_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -1945,42 +1957,42 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito
edit_items_add_color->set_flat(true);
edit_items_add_color->set_disabled(true);
edit_items_toolbar->add_child(edit_items_add_color);
- edit_items_add_color->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_COLOR));
+ edit_items_add_color->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_COLOR));
edit_items_add_constant = memnew(Button);
edit_items_add_constant->set_tooltip(TTR("Add Constant Item"));
edit_items_add_constant->set_flat(true);
edit_items_add_constant->set_disabled(true);
edit_items_toolbar->add_child(edit_items_add_constant);
- edit_items_add_constant->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_CONSTANT));
+ edit_items_add_constant->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_CONSTANT));
edit_items_add_font = memnew(Button);
edit_items_add_font->set_tooltip(TTR("Add Font Item"));
edit_items_add_font->set_flat(true);
edit_items_add_font->set_disabled(true);
edit_items_toolbar->add_child(edit_items_add_font);
- edit_items_add_font->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_FONT));
+ edit_items_add_font->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_FONT));
edit_items_add_font_size = memnew(Button);
edit_items_add_font_size->set_tooltip(TTR("Add Font Size Item"));
edit_items_add_font_size->set_flat(true);
edit_items_add_font_size->set_disabled(true);
edit_items_toolbar->add_child(edit_items_add_font_size);
- edit_items_add_font_size->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_FONT_SIZE));
+ edit_items_add_font_size->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_FONT_SIZE));
edit_items_add_icon = memnew(Button);
edit_items_add_icon->set_tooltip(TTR("Add Icon Item"));
edit_items_add_icon->set_flat(true);
edit_items_add_icon->set_disabled(true);
edit_items_toolbar->add_child(edit_items_add_icon);
- edit_items_add_icon->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_ICON));
+ edit_items_add_icon->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_ICON));
edit_items_add_stylebox = memnew(Button);
edit_items_add_stylebox->set_tooltip(TTR("Add StyleBox Item"));
edit_items_add_stylebox->set_flat(true);
edit_items_add_stylebox->set_disabled(true);
edit_items_toolbar->add_child(edit_items_add_stylebox);
- edit_items_add_stylebox->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_STYLEBOX));
+ edit_items_add_stylebox->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_STYLEBOX));
edit_items_toolbar->add_child(memnew(VSeparator));
@@ -2017,7 +2029,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito
edit_items_tree->connect("button_clicked", callable_mp(this, &ThemeItemEditorDialog::_item_tree_button_pressed));
edit_items_message = memnew(Label);
- edit_items_message->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ edit_items_message->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
edit_items_message->set_mouse_filter(Control::MOUSE_FILTER_STOP);
edit_items_message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
edit_items_message->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
@@ -2080,7 +2092,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type("Theme", &ext);
for (const String &E : ext) {
- import_another_theme_dialog->add_filter(vformat("*.%s; %s", E, TTR("Theme Resource")));
+ import_another_theme_dialog->add_filter("*." + E, TTR("Theme Resource"));
}
import_another_file_hb->add_child(import_another_theme_dialog);
import_another_theme_dialog->connect("file_selected", callable_mp(this, &ThemeItemEditorDialog::_select_another_theme_cbk));
@@ -2099,6 +2111,8 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito
confirm_closing_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_close_dialog));
}
+///////////////////////
+
void ThemeTypeDialog::_dialog_about_to_show() {
add_type_filter->set_text("");
add_type_filter->grab_focus();
@@ -2237,6 +2251,8 @@ ThemeTypeDialog::ThemeTypeDialog() {
add_child(add_type_confirmation);
}
+///////////////////////
+
VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) {
VBoxContainer *items_tab = memnew(VBoxContainer);
items_tab->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
@@ -2256,11 +2272,11 @@ VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) {
LineEdit *item_add_edit = memnew(LineEdit);
item_add_edit->set_h_size_flags(SIZE_EXPAND_FILL);
item_add_hb->add_child(item_add_edit);
- item_add_edit->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_item_add_lineedit_cbk), varray(p_data_type, item_add_edit));
+ item_add_edit->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_item_add_lineedit_cbk).bind(p_data_type, item_add_edit));
Button *item_add_button = memnew(Button);
item_add_button->set_text(TTR("Add"));
item_add_hb->add_child(item_add_button);
- item_add_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_add_cbk), varray(p_data_type, item_add_edit));
+ item_add_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_add_cbk).bind(p_data_type, item_add_edit));
return items_list;
}
@@ -2403,7 +2419,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_
item_name_edit->set_h_size_flags(SIZE_EXPAND_FILL);
item_name_edit->set_text(p_item_name);
item_name_container->add_child(item_name_edit);
- item_name_edit->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_item_rename_entered), varray(p_data_type, p_item_name, item_name_container));
+ item_name_edit->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_item_rename_entered).bind(p_data_type, p_item_name, item_name_container));
item_name_edit->hide();
Button *item_rename_button = memnew(Button);
@@ -2411,21 +2427,21 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_
item_rename_button->set_tooltip(TTR("Rename Item"));
item_rename_button->set_flat(true);
item_name_container->add_child(item_rename_button);
- item_rename_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_cbk), varray(p_data_type, p_item_name, item_name_container));
+ item_rename_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_cbk).bind(p_data_type, p_item_name, item_name_container));
Button *item_remove_button = memnew(Button);
item_remove_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
item_remove_button->set_tooltip(TTR("Remove Item"));
item_remove_button->set_flat(true);
item_name_container->add_child(item_remove_button);
- item_remove_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_remove_cbk), varray(p_data_type, p_item_name));
+ item_remove_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_remove_cbk).bind(p_data_type, p_item_name));
Button *item_rename_confirm_button = memnew(Button);
item_rename_confirm_button->set_icon(get_theme_icon(SNAME("ImportCheck"), SNAME("EditorIcons")));
item_rename_confirm_button->set_tooltip(TTR("Confirm Item Rename"));
item_rename_confirm_button->set_flat(true);
item_name_container->add_child(item_rename_confirm_button);
- item_rename_confirm_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_confirmed), varray(p_data_type, p_item_name, item_name_container));
+ item_rename_confirm_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_confirmed).bind(p_data_type, p_item_name, item_name_container));
item_rename_confirm_button->hide();
Button *item_rename_cancel_button = memnew(Button);
@@ -2433,7 +2449,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_
item_rename_cancel_button->set_tooltip(TTR("Cancel Item Rename"));
item_rename_cancel_button->set_flat(true);
item_name_container->add_child(item_rename_cancel_button);
- item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled), varray(p_data_type, p_item_name, item_name_container));
+ item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled).bind(p_data_type, p_item_name, item_name_container));
item_rename_cancel_button->hide();
} else {
item_name->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
@@ -2443,7 +2459,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_
item_override_button->set_tooltip(TTR("Override Item"));
item_override_button->set_flat(true);
item_name_container->add_child(item_override_button);
- item_override_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_override_cbk), varray(p_data_type, p_item_name));
+ item_override_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_override_cbk).bind(p_data_type, p_item_name));
}
return item_control;
@@ -2476,7 +2492,8 @@ void ThemeTypeEditor::_update_type_items() {
if (E.value) {
item_editor->set_pick_color(edited_theme->get_color(E.key, edited_type));
- item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed), varray(E.key));
+ item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed).bind(E.key));
+ item_editor->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(item_editor->get_picker()));
} else {
item_editor->set_pick_color(Theme::get_default()->get_color(E.key, edited_type));
item_editor->set_disabled(true);
@@ -2509,7 +2526,7 @@ void ThemeTypeEditor::_update_type_items() {
if (E.value) {
item_editor->set_value(edited_theme->get_constant(E.key, edited_type));
- item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed), varray(E.key));
+ item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed).bind(E.key));
} else {
item_editor->set_value(Theme::get_default()->get_constant(E.key, edited_type));
item_editor->set_editable(false);
@@ -2543,7 +2560,7 @@ void ThemeTypeEditor::_update_type_items() {
item_editor->set_edited_resource(Ref<Resource>());
}
item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
- item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed), varray(E.key));
+ item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed).bind(E.key));
} else {
if (Theme::get_default()->has_font(E.key, edited_type)) {
item_editor->set_edited_resource(Theme::get_default()->get_font(E.key, edited_type));
@@ -2580,7 +2597,7 @@ void ThemeTypeEditor::_update_type_items() {
if (E.value) {
item_editor->set_value(edited_theme->get_font_size(E.key, edited_type));
- item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed), varray(E.key));
+ item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed).bind(E.key));
} else {
item_editor->set_value(Theme::get_default()->get_font_size(E.key, edited_type));
item_editor->set_editable(false);
@@ -2614,7 +2631,7 @@ void ThemeTypeEditor::_update_type_items() {
item_editor->set_edited_resource(Ref<Resource>());
}
item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
- item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed), varray(E.key));
+ item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed).bind(E.key));
} else {
if (Theme::get_default()->has_icon(E.key, edited_type)) {
item_editor->set_edited_resource(Theme::get_default()->get_icon(E.key, edited_type));
@@ -2661,7 +2678,7 @@ void ThemeTypeEditor::_update_type_items() {
item_editor->set_edited_resource(Ref<Resource>());
}
item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
- item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(leading_stylebox.item_name));
+ item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed).bind(leading_stylebox.item_name));
stylebox_items_list->add_child(item_control);
stylebox_items_list->add_child(memnew(HSeparator));
@@ -2686,7 +2703,7 @@ void ThemeTypeEditor::_update_type_items() {
item_editor->set_edited_resource(Ref<Resource>());
}
item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
- item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(E.key));
+ item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed).bind(E.key));
Button *pin_leader_button = memnew(Button);
pin_leader_button->set_flat(true);
@@ -2694,7 +2711,7 @@ void ThemeTypeEditor::_update_type_items() {
pin_leader_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")));
pin_leader_button->set_tooltip(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type."));
item_control->add_child(pin_leader_button);
- pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed), varray(item_editor, E.key));
+ pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed).bind(item_editor, E.key));
} else {
if (Theme::get_default()->has_stylebox(E.key, edited_type)) {
item_editor->set_edited_resource(Theme::get_default()->get_stylebox(E.key, edited_type));
@@ -2733,7 +2750,7 @@ void ThemeTypeEditor::_list_type_selected(int p_index) {
void ThemeTypeEditor::_add_type_button_cbk() {
add_type_mode = ADD_THEME_TYPE;
add_type_dialog->set_title(TTR("Add Item Type"));
- add_type_dialog->get_ok_button()->set_text(TTR("Add Type"));
+ add_type_dialog->set_ok_button_text(TTR("Add Type"));
add_type_dialog->set_include_own_types(false);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
}
@@ -2931,10 +2948,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)) {
@@ -3273,7 +3286,7 @@ void ThemeTypeEditor::_type_variation_changed(const String p_value) {
void ThemeTypeEditor::_add_type_variation_cbk() {
add_type_mode = ADD_VARIATION_BASE;
add_type_dialog->set_title(TTR("Set Variation Base Type"));
- add_type_dialog->get_ok_button()->set_text(TTR("Set Base Type"));
+ add_type_dialog->set_ok_button_text(TTR("Set Base Type"));
add_type_dialog->set_include_own_types(true);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
}
@@ -3368,6 +3381,7 @@ ThemeTypeEditor::ThemeTypeEditor() {
theme_type_list = memnew(OptionButton);
theme_type_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ theme_type_list->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
type_list_hb->add_child(theme_type_list);
theme_type_list->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_list_type_selected));
@@ -3458,6 +3472,8 @@ ThemeTypeEditor::ThemeTypeEditor() {
add_child(update_debounce_timer);
}
+///////////////////////
+
void ThemeEditor::edit(const Ref<Theme> &p_theme) {
if (theme == p_theme) {
return;
@@ -3508,8 +3524,8 @@ void ThemeEditor::_preview_scene_dialog_cbk(const String &p_path) {
}
_add_preview_tab(preview_tab, p_path.get_file(), get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")));
- preview_tab->connect("scene_invalidated", callable_mp(this, &ThemeEditor::_remove_preview_tab_invalid), varray(preview_tab));
- preview_tab->connect("scene_reloaded", callable_mp(this, &ThemeEditor::_update_preview_tab), varray(preview_tab));
+ preview_tab->connect("scene_invalidated", callable_mp(this, &ThemeEditor::_remove_preview_tab_invalid).bind(preview_tab));
+ preview_tab->connect("scene_reloaded", callable_mp(this, &ThemeEditor::_update_preview_tab).bind(preview_tab));
}
void ThemeEditor::_add_preview_tab(ThemeEditorPreview *p_preview_tab, const String &p_preview_name, const Ref<Texture2D> &p_icon) {
@@ -3603,13 +3619,13 @@ ThemeEditor::ThemeEditor() {
Button *theme_save_button = memnew(Button);
theme_save_button->set_text(TTR("Save"));
theme_save_button->set_flat(true);
- theme_save_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk), varray(false));
+ theme_save_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk).bind(false));
top_menu->add_child(theme_save_button);
Button *theme_save_as_button = memnew(Button);
theme_save_as_button->set_text(TTR("Save As..."));
theme_save_as_button->set_flat(true);
- theme_save_as_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk), varray(true));
+ theme_save_as_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk).bind(true));
top_menu->add_child(theme_save_as_button);
top_menu->add_child(memnew(VSeparator));
@@ -3667,7 +3683,7 @@ ThemeEditor::ThemeEditor() {
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &ext);
for (const String &E : ext) {
- preview_scene_dialog->add_filter(vformat("*.%s; %s", E, TTR("Scene")));
+ preview_scene_dialog->add_filter("*." + E, TTR("Scene"));
}
main_hs->add_child(preview_scene_dialog);
preview_scene_dialog->connect("file_selected", callable_mp(this, &ThemeEditor::_preview_scene_dialog_cbk));
@@ -3676,6 +3692,8 @@ ThemeEditor::ThemeEditor() {
theme_type_editor->set_custom_minimum_size(Size2(280, 0) * EDSCALE);
}
+///////////////////////
+
void ThemeEditorPlugin::edit(Object *p_node) {
if (Object::cast_to<Theme>(p_node)) {
theme_editor->edit(Object::cast_to<Theme>(p_node));
@@ -3698,7 +3716,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_plugin.h b/editor/plugins/theme_editor_plugin.h
index 543113a5eb..9f89a047cb 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -198,6 +198,7 @@ class ThemeItemEditorDialog : public AcceptDialog {
Tree *edit_type_list = nullptr;
LineEdit *edit_add_type_value = nullptr;
+ Button *edit_add_type_button = nullptr;
String edited_item_type;
Button *edit_items_add_color = nullptr;
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
index a6e34cf5e0..b5c6c6d651 100644
--- a/editor/plugins/theme_editor_preview.cpp
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "scene/gui/button.h"
+#include "scene/gui/check_button.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/progress_bar.h"
#include "scene/resources/packed_scene.h"
@@ -126,7 +127,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);
@@ -246,7 +247,7 @@ ThemeEditorPreview::ThemeEditorPreview() {
preview_root->set_h_size_flags(SIZE_EXPAND_FILL);
preview_bg = memnew(ColorRect);
- preview_bg->set_anchors_and_offsets_preset(PRESET_WIDE);
+ preview_bg->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
preview_bg->set_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
preview_root->add_child(preview_bg);
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
index e37878ff98..3fe6778f48 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);
}
}
@@ -260,7 +256,7 @@ AtlasMergingDialog::AtlasMergingDialog() {
set_hide_on_ok(false);
// Ok buttons
- get_ok_button()->set_text(TTR("Merge (Keep original Atlases)"));
+ set_ok_button_text(TTR("Merge (Keep original Atlases)"));
get_ok_button()->set_disabled(true);
merge_button = add_button(TTR("Merge"), true, "merge");
merge_button->set_disabled(true);
diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp
index 3073c8a7f2..f119ada810 100644
--- a/editor/plugins/tiles/tile_atlas_view.cpp
+++ b/editor/plugins/tiles/tile_atlas_view.cpp
@@ -544,7 +544,7 @@ TileAtlasView::TileAtlasView() {
Panel *panel = memnew(Panel);
panel->set_clip_contents(true);
panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ panel->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
panel->set_h_size_flags(SIZE_EXPAND_FILL);
panel->set_v_size_flags(SIZE_EXPAND_FILL);
add_child(panel);
@@ -613,32 +613,32 @@ TileAtlasView::TileAtlasView() {
background_left = memnew(Control);
background_left->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- background_left->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ background_left->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
background_left->set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED);
background_left->connect("draw", callable_mp(this, &TileAtlasView::_draw_background_left));
base_tiles_root_control->add_child(background_left);
base_tiles_drawing_root = memnew(Control);
base_tiles_drawing_root->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- base_tiles_drawing_root->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ base_tiles_drawing_root->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
base_tiles_drawing_root->set_texture_filter(TEXTURE_FILTER_NEAREST);
base_tiles_root_control->add_child(base_tiles_drawing_root);
base_tiles_draw = memnew(Control);
base_tiles_draw->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- base_tiles_draw->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ base_tiles_draw->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
base_tiles_draw->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles));
base_tiles_drawing_root->add_child(base_tiles_draw);
base_tiles_texture_grid = memnew(Control);
base_tiles_texture_grid->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- base_tiles_texture_grid->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ base_tiles_texture_grid->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
base_tiles_texture_grid->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles_texture_grid));
base_tiles_drawing_root->add_child(base_tiles_texture_grid);
base_tiles_shape_grid = memnew(Control);
base_tiles_shape_grid->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- base_tiles_shape_grid->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ base_tiles_shape_grid->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
base_tiles_shape_grid->connect("draw", callable_mp(this, &TileAtlasView::_draw_base_tiles_shape_grid));
base_tiles_drawing_root->add_child(base_tiles_shape_grid);
diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h
index ff46b7871f..196a642283 100644
--- a/editor/plugins/tiles/tile_atlas_view.h
+++ b/editor/plugins/tiles/tile_atlas_view.h
@@ -158,4 +158,4 @@ public:
TileAtlasView();
};
-#endif // TILE_ATLAS_VIEW
+#endif // TILE_ATLAS_VIEW_H
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 468681c967..a00e1ed9e8 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));
}
@@ -803,13 +803,13 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() {
add_child(root);
panel = memnew(Panel);
- panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ panel->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
root->add_child(panel);
base_control = memnew(Control);
base_control->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
- base_control->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ base_control->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
base_control->connect("draw", callable_mp(this, &GenericTilePolygonEditor::_base_control_draw));
base_control->connect("gui_input", callable_mp(this, &GenericTilePolygonEditor::_base_control_gui_input));
base_control->set_clip_contents(true);
@@ -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/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index d914b9c363..1bf24a7393 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -2198,7 +2198,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1));
sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_source_display).unbind(1));
sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current));
- sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list), varray(sources_list, source_sort_button));
+ sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list).bind(sources_list, source_sort_button));
sources_list->add_user_signal(MethodInfo("sort_request"));
sources_list->connect("sort_request", callable_mp(this, &TileMapEditorTilesPlugin::_update_tile_set_sources_list));
split_container_left_side->add_child(sources_list);
@@ -3212,7 +3212,7 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() {
terrains_tile_list->set_item_metadata(item_index, list_metadata_dict);
item_index = terrains_tile_list->add_icon_item(main_vbox_container->get_theme_icon(SNAME("TerrainPath"), SNAME("EditorIcons")));
- terrains_tile_list->set_item_tooltip(item_index, TTR("Path mode: paints a terrain, thens connects it to the previous tile painted withing the same stroke."));
+ terrains_tile_list->set_item_tooltip(item_index, TTR("Path mode: paints a terrain, thens connects it to the previous tile painted within the same stroke."));
list_metadata_dict = Dictionary();
list_metadata_dict["type"] = SELECTED_TYPE_PATH;
terrains_tile_list->set_item_metadata(item_index, list_metadata_dict);
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index ff586ebbfe..605fbe4823 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -377,4 +377,4 @@ public:
static Vector<Vector2i> get_line(TileMap *p_tile_map, Vector2i p_from_cell, Vector2i p_to_cell);
};
-#endif // TILE_MAP_EDITOR_PLUGIN_H
+#endif // TILE_MAP_EDITOR_H
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
index 3fe13fd341..12e1615484 100644
--- a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
@@ -340,7 +340,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
source_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
source_level_list->set_select_mode(ItemList::SELECT_MULTI);
source_level_list->set_allow_rmb_select(true);
- source_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(source_level_list));
+ source_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked).bind(source_level_list));
vbox_container->add_child(source_level_list);
Label *coords_level_label = memnew(Label);
@@ -351,7 +351,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
coords_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
coords_level_list->set_select_mode(ItemList::SELECT_MULTI);
coords_level_list->set_allow_rmb_select(true);
- coords_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(coords_level_list));
+ coords_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked).bind(coords_level_list));
vbox_container->add_child(coords_level_list);
Label *alternative_level_label = memnew(Label);
@@ -362,7 +362,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
alternative_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
alternative_level_list->set_select_mode(ItemList::SELECT_MULTI);
alternative_level_list->set_allow_rmb_select(true);
- alternative_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(alternative_level_list));
+ alternative_level_list->connect("item_clicked", callable_mp(this, &TileProxiesManagerDialog::_right_clicked).bind(alternative_level_list));
vbox_container->add_child(alternative_level_list);
popup_menu = memnew(PopupMenu);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 37ccc6ad45..6950f57a00 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -735,15 +735,15 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
// --- Custom Data ---
ADD_TILE_DATA_EDITOR_GROUP("Custom Data");
for (int i = 0; i < tile_set->get_custom_data_layers_count(); i++) {
- if (tile_set->get_custom_data_name(i).is_empty()) {
+ if (tile_set->get_custom_data_layer_name(i).is_empty()) {
ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), vformat("custom_data_%d", i));
} else {
- ADD_TILE_DATA_EDITOR(group, tile_set->get_custom_data_name(i), vformat("custom_data_%d", i));
+ ADD_TILE_DATA_EDITOR(group, tile_set->get_custom_data_layer_name(i), vformat("custom_data_%d", i));
}
if (!tile_data_editors.has(vformat("custom_data_%d", i))) {
TileDataDefaultEditor *tile_data_custom_data_editor = memnew(TileDataDefaultEditor());
tile_data_custom_data_editor->hide();
- tile_data_custom_data_editor->setup_property_editor(tile_set->get_custom_data_type(i), vformat("custom_data_%d", i), tile_set->get_custom_data_name(i));
+ tile_data_custom_data_editor->setup_property_editor(tile_set->get_custom_data_layer_type(i), vformat("custom_data_%d", i), tile_set->get_custom_data_layer_name(i));
tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
tile_data_editors[vformat("custom_data_%d", i)] = tile_data_custom_data_editor;
@@ -913,7 +913,7 @@ void TileSetAtlasSourceEditor::_update_atlas_view() {
button->add_theme_style_override("hover", memnew(StyleBoxEmpty));
button->add_theme_style_override("focus", memnew(StyleBoxEmpty));
button->add_theme_style_override("pressed", memnew(StyleBoxEmpty));
- button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile), varray(tile_id, TileSetSource::INVALID_TILE_ALTERNATIVE));
+ button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile).bind(tile_id, TileSetSource::INVALID_TILE_ALTERNATIVE));
button->set_rect(Rect2(Vector2(pos.x, pos.y + (y_increment - texture_region_base_size.y) / 2.0), Vector2(texture_region_base_size_min, texture_region_base_size_min)));
button->set_expand_icon(true);
@@ -1822,7 +1822,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() {
Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
- xform.translate(position);
+ xform.translate_local(position);
if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, 0 })) {
continue;
@@ -1845,7 +1845,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() {
Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(E.tile, 0);
Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
- xform.translate(position);
+ xform.translate_local(position);
TileMapCell cell;
cell.source_id = tile_set_atlas_source_id;
@@ -1886,6 +1886,12 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In
tile_atlas_control_unscaled->update();
alternative_tiles_control->update();
alternative_tiles_control_unscaled->update();
+
+ if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) {
+ if (Vector2(drag_start_mouse_pos).distance_to(tile_atlas_control->get_local_mouse_position()) > 5.0 * EDSCALE) {
+ drag_type = DRAG_TYPE_NONE;
+ }
+ }
}
Ref<InputEventMouseButton> mb = p_event;
@@ -1911,7 +1917,10 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In
}
} else if (mb->get_button_index() == MouseButton::RIGHT) {
if (mb->is_pressed()) {
- // Right click pressed
+ drag_type = DRAG_TYPE_MAY_POPUP_MENU;
+ drag_start_mouse_pos = alternative_tiles_control->get_local_mouse_position();
+ } else if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) {
+ // Right click released and wasn't dragged too far
Vector3 tile = tile_atlas_view->get_alternative_tile_at_pos(mouse_local_pos);
selection.clear();
@@ -1989,7 +1998,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() {
Vector2 position = rect.get_center();
Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
- xform.translate(position);
+ xform.translate_local(position);
if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, alternative_tile })) {
continue;
@@ -2013,7 +2022,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() {
Vector2 position = rect.get_center();
Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
- xform.translate(position);
+ xform.translate_local(position);
TileMapCell cell;
cell.source_id = tile_set_atlas_source_id;
@@ -2370,7 +2379,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_data_editors_tree = memnew(Tree);
tile_data_editors_tree->set_hide_root(true);
- tile_data_editors_tree->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ tile_data_editors_tree->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
tile_data_editors_tree->set_h_scroll_enabled(false);
tile_data_editors_tree->set_v_scroll_enabled(false);
tile_data_editors_tree->connect("item_selected", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editors_tree_selected));
@@ -2405,7 +2414,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
confirm_auto_create_tiles = memnew(AcceptDialog);
confirm_auto_create_tiles->set_title(TTR("Auto Create Tiles in Non-Transparent Texture Regions?"));
confirm_auto_create_tiles->set_text(TTR("The atlas's texture was modified.\nWould you like to automatically create tiles in the atlas?"));
- confirm_auto_create_tiles->get_ok_button()->set_text(TTR("Yes"));
+ confirm_auto_create_tiles->set_ok_button_text(TTR("Yes"));
confirm_auto_create_tiles->add_cancel_button()->set_text(TTR("No"));
confirm_auto_create_tiles->connect("confirmed", callable_mp(this, &TileSetAtlasSourceEditor::_auto_create_tiles));
add_child(confirm_auto_create_tiles);
@@ -2509,7 +2518,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control);
tile_atlas_control_unscaled = memnew(Control);
- tile_atlas_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ tile_atlas_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
tile_atlas_control_unscaled->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw));
tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control_unscaled, false);
tile_atlas_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
@@ -2526,7 +2535,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control);
alternative_tiles_control_unscaled = memnew(Control);
- alternative_tiles_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ alternative_tiles_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
alternative_tiles_control_unscaled->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw));
tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control_unscaled, false);
alternative_tiles_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index de373e121b..81804710b4 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -710,9 +710,9 @@ TileSetEditor::TileSetEditor() {
sources_list->set_v_size_flags(SIZE_EXPAND_FILL);
sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected));
sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current));
- sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list), varray(sources_list, source_sort_button));
+ sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list).bind(sources_list, source_sort_button));
sources_list->add_user_signal(MethodInfo("sort_request"));
- sources_list->connect("sort_request", callable_mp(this, &TileSetEditor::_update_sources_list), varray(-1));
+ sources_list->connect("sort_request", callable_mp(this, &TileSetEditor::_update_sources_list).bind(-1));
sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
sources_list->set_drag_forwarding(this);
split_container_left_side->add_child(sources_list);
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index e633de37b0..c45240043e 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -108,4 +108,4 @@ public:
~TileSetEditor();
};
-#endif // TILE_SET_EDITOR_PLUGIN_H
+#endif // TILE_SET_EDITOR_H
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
index 657bfca032..77a583e522 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
@@ -142,4 +142,4 @@ public:
~TileSetScenesCollectionSourceEditor();
};
-#endif
+#endif // TILE_SET_SCENES_COLLECTION_SOURCE_EDITOR_H
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 543304346e..b5134f6893 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -116,21 +116,18 @@ void TilesEditorPlugin::_thread() {
// Add the viewport at the last moment to avoid rendering too early.
EditorNode::get_singleton()->add_child(viewport);
- RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT);
+ RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Object::CONNECT_ONESHOT);
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;
- item.callback.call(args_ptr, 2, r, error);
+ item.callback.callp(args_ptr, 2, r, error);
viewport->queue_delete();
} else {
@@ -158,6 +155,9 @@ void TilesEditorPlugin::_update_editors() {
// Update the viewport.
CanvasItemEditor::get_singleton()->update_viewport();
+ // Make sure the tile set editor is visible if we have one assigned.
+ tileset_editor_button->set_visible(is_visible && tile_set.is_valid());
+
// Update visibility of bottom panel buttons.
if (tileset_editor_button->is_pressed() && !tile_set.is_valid()) {
if (tile_map) {
@@ -184,12 +184,14 @@ void TilesEditorPlugin::_notification(int p_what) {
}
void TilesEditorPlugin::make_visible(bool p_visible) {
- if (p_visible) {
+ is_visible = p_visible;
+
+ if (is_visible) {
// Disable and hide invalid editors.
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
tileset_editor_button->set_visible(tile_set.is_valid());
tilemap_editor_button->set_visible(tile_map);
- if (tile_map) {
+ if (tile_map && !is_editing_tile_set) {
EditorNode::get_singleton()->make_bottom_panel_item_visible(tilemap_editor);
} else {
EditorNode::get_singleton()->make_bottom_panel_item_visible(tileset_editor);
@@ -229,14 +231,14 @@ void TilesEditorPlugin::synchronize_sources_list(Object *p_current_list, Object
}
if (item_list->is_visible_in_tree()) {
+ // Make sure the selection is not overwritten after sorting.
+ int atlas_sources_lists_current_mem = atlas_sources_lists_current;
+ item_list->emit_signal(SNAME("sort_request"));
+ atlas_sources_lists_current = atlas_sources_lists_current_mem;
+
if (atlas_sources_lists_current < 0 || atlas_sources_lists_current >= item_list->get_item_count()) {
item_list->deselect_all();
} else {
- // Make sure the selection is not overwritten after sorting.
- int atlas_sources_lists_current_mem = atlas_sources_lists_current;
- item_list->emit_signal(SNAME("sort_request"));
- atlas_sources_lists_current = atlas_sources_lists_current_mem;
-
item_list->set_current(atlas_sources_lists_current);
item_list->ensure_current_is_visible();
item_list->emit_signal(SNAME("item_selected"), atlas_sources_lists_current);
@@ -348,6 +350,8 @@ void TilesEditorPlugin::edit(Object *p_object) {
// Update edited objects.
tile_set = Ref<TileSet>();
+ is_editing_tile_set = false;
+
if (p_object) {
if (p_object->is_class("TileMap")) {
tile_map_id = p_object->get_instance_id();
@@ -362,6 +366,7 @@ void TilesEditorPlugin::edit(Object *p_object) {
tile_map_id = ObjectID();
}
}
+ is_editing_tile_set = true;
EditorNode::get_singleton()->make_bottom_panel_item_visible(tileset_editor);
}
}
diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h
index a22e782b34..b1fe6f8df6 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.h
+++ b/editor/plugins/tiles/tiles_editor_plugin.h
@@ -53,9 +53,12 @@ public:
};
private:
+ bool is_visible = false;
+
bool tile_map_changed_needs_update = false;
ObjectID tile_map_id;
Ref<TileSet> tile_set;
+ bool is_editing_tile_set = false;
Button *tilemap_editor_button = nullptr;
TileMapEditor *tilemap_editor = nullptr;
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index 443d5975cd..cf55465417 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -35,6 +35,8 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "scene/gui/separator.h"
VersionControlEditorPlugin *VersionControlEditorPlugin::singleton = nullptr;
diff --git a/editor/plugins/version_control_editor_plugin.h b/editor/plugins/version_control_editor_plugin.h
index 39a56de772..fa721268ba 100644
--- a/editor/plugins/version_control_editor_plugin.h
+++ b/editor/plugins/version_control_editor_plugin.h
@@ -148,4 +148,4 @@ public:
VARIANT_ENUM_CAST(VersionControlEditorPlugin::ChangeType);
-#endif // !VERSION_CONTROL_EDITOR_PLUGIN_H
+#endif // VERSION_CONTROL_EDITOR_PLUGIN_H
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 8c72a886ea..4a144bc391 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -40,9 +40,17 @@
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_scale.h"
+#include "editor/plugins/curve_editor_plugin.h"
+#include "editor/plugins/shader_editor_plugin.h"
#include "scene/animation/animation_player.h"
+#include "scene/gui/button.h"
+#include "scene/gui/code_edit.h"
+#include "scene/gui/graph_edit.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/panel.h"
+#include "scene/gui/popup.h"
+#include "scene/gui/rich_text_label.h"
+#include "scene/gui/tree.h"
#include "scene/gui/view_panner.h"
#include "scene/main/window.h"
#include "scene/resources/visual_shader_nodes.h"
@@ -72,6 +80,10 @@ const int MAX_FLOAT_CONST_DEFS = sizeof(float_constant_defs) / sizeof(FloatConst
///////////////////
+void VisualShaderNodePlugin::set_editor(VisualShaderEditor *p_editor) {
+ vseditor = p_editor;
+}
+
Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
Object *ret;
if (GDVIRTUAL_CALL(_create_editor, p_parent_resource, p_node, ret)) {
@@ -86,17 +98,6 @@ void VisualShaderNodePlugin::_bind_methods() {
///////////////////
-static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
- Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty));
- style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE);
- style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE);
- style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE);
- style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE);
- return style;
-}
-
-///////////////////
-
VisualShaderGraphPlugin::VisualShaderGraphPlugin() {
}
@@ -115,6 +116,10 @@ void VisualShaderGraphPlugin::_bind_methods() {
ClassDB::bind_method("update_curve_xyz", &VisualShaderGraphPlugin::update_curve_xyz);
}
+void VisualShaderGraphPlugin::set_editor(VisualShaderEditor *p_editor) {
+ editor = p_editor;
+}
+
void VisualShaderGraphPlugin::register_shader(VisualShader *p_shader) {
visual_shader = Ref<VisualShader>(p_shader);
}
@@ -186,15 +191,11 @@ void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_
switch (p_value.get_type()) {
case Variant::COLOR: {
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (!editor) {
- break;
- }
button->set_custom_minimum_size(Size2(30, 0) * EDSCALE);
Callable ce = callable_mp(editor, &VisualShaderEditor::_draw_color_over_button);
if (!button->is_connected("draw", ce)) {
- button->connect("draw", ce, varray(button, p_value));
+ button->connect("draw", ce.bind(button, p_value));
}
} break;
case Variant::BOOL: {
@@ -337,10 +338,6 @@ void VisualShaderGraphPlugin::register_uniform_name(int p_node_id, LineEdit *p_u
}
void VisualShaderGraphPlugin::update_theme() {
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (!editor) {
- return;
- }
vector_expanded_color[0] = editor->get_theme_color(SNAME("axis_x_color"), SNAME("Editor")); // red
vector_expanded_color[1] = editor->get_theme_color(SNAME("axis_y_color"), SNAME("Editor")); // green
vector_expanded_color[2] = editor->get_theme_color(SNAME("axis_z_color"), SNAME("Editor")); // blue
@@ -351,10 +348,6 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (!visual_shader.is_valid() || p_type != visual_shader->get_shader_type()) {
return;
}
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (!editor) {
- return;
- }
GraphEdit *graph = editor->graph;
if (!graph) {
return;
@@ -367,8 +360,6 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Control *offset;
- static Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1);
-
static const Color type_color[] = {
Color(0.38, 0.85, 0.96), // scalar (float)
Color(0.49, 0.78, 0.94), // scalar (int)
@@ -426,7 +417,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
size = resizable_node->get_size();
node->set_resizable(true);
- node->connect("resize_request", callable_mp(editor, &VisualShaderEditor::_node_resized), varray((int)p_type, p_id));
+ node->connect("resize_request", callable_mp(editor, &VisualShaderEditor::_node_resized).bind((int)p_type, p_id));
}
if (is_expression) {
expression = expression_node->get_expression();
@@ -438,10 +429,10 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (p_id >= 2) {
node->set_show_close_button(true);
- node->connect("close_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request), varray(p_type, p_id), CONNECT_DEFERRED);
+ node->connect("close_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request).bind(p_type, p_id), CONNECT_DEFERRED);
}
- node->connect("dragged", callable_mp(editor, &VisualShaderEditor::_node_dragged), varray(p_id));
+ node->connect("dragged", callable_mp(editor, &VisualShaderEditor::_node_dragged).bind(p_id));
Control *custom_editor = nullptr;
int port_offset = 1;
@@ -474,6 +465,12 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
node->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
}
+ Ref<VisualShaderNodeUniformRef> uniform_ref = vsnode;
+ if (uniform_ref.is_valid()) {
+ uniform_ref->set_shader_rid(visual_shader->get_rid());
+ uniform_ref->update_uniform_type();
+ }
+
Ref<VisualShaderNodeUniform> uniform = vsnode;
HBoxContainer *hb = nullptr;
@@ -482,8 +479,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
register_uniform_name(p_id, uniform_name);
uniform_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
uniform_name->set_text(uniform->get_uniform_name());
- uniform_name->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_uniform_line_edit_changed), varray(p_id));
- uniform_name->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_uniform_line_edit_focus_out), varray(uniform_name, p_id));
+ uniform_name->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_uniform_line_edit_changed).bind(p_id));
+ uniform_name->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_uniform_line_edit_focus_out).bind(uniform_name, p_id));
if (vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") {
hb = memnew(HBoxContainer);
@@ -523,7 +520,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Callable ce = callable_mp(graph_plugin, &VisualShaderGraphPlugin::update_curve);
if (curve->get_texture().is_valid() && !curve->get_texture()->is_connected("changed", ce)) {
- curve->get_texture()->connect("changed", ce, varray(p_id));
+ curve->get_texture()->connect("changed", ce.bind(p_id));
}
CurveEditor *curve_editor = memnew(CurveEditor);
@@ -541,7 +538,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Callable ce = callable_mp(graph_plugin, &VisualShaderGraphPlugin::update_curve_xyz);
if (curve_xyz->get_texture().is_valid() && !curve_xyz->get_texture()->is_connected("changed", ce)) {
- curve_xyz->get_texture()->connect("changed", ce, varray(p_id));
+ curve_xyz->get_texture()->connect("changed", ce.bind(p_id));
}
CurveEditor *curve_editor_x = memnew(CurveEditor);
@@ -604,14 +601,14 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Button *add_input_btn = memnew(Button);
add_input_btn->set_text(TTR("Add Input"));
- add_input_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_add_input_port), varray(p_id, group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, input_port_name), CONNECT_DEFERRED);
+ add_input_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_add_input_port).bind(p_id, group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, input_port_name), CONNECT_DEFERRED);
hb2->add_child(add_input_btn);
hb2->add_spacer();
Button *add_output_btn = memnew(Button);
add_output_btn->set_text(TTR("Add Output"));
- add_output_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_add_output_port), varray(p_id, group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, output_port_name), CONNECT_DEFERRED);
+ add_output_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_add_output_port).bind(p_id, group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, output_port_name), CONNECT_DEFERRED);
hb2->add_child(add_output_btn);
node->add_child(hb2);
@@ -719,7 +716,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Button *button = memnew(Button);
hb->add_child(button);
register_default_input_button(p_id, i, button);
- button->connect("pressed", callable_mp(editor, &VisualShaderEditor::_edit_port_default_input), varray(button, p_id, i));
+ button->connect("pressed", callable_mp(editor, &VisualShaderEditor::_edit_port_default_input).bind(button, p_id, i));
if (default_value.get_type() != Variant::NIL) { // only a label
set_input_port_default_value(p_type, p_id, i, default_value);
} else {
@@ -744,32 +741,32 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
type_box->add_item(TTR("Sampler"));
type_box->select(group_node->get_input_port_type(i));
type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- type_box->connect("item_selected", callable_mp(editor, &VisualShaderEditor::_change_input_port_type), varray(p_id, i), CONNECT_DEFERRED);
+ type_box->connect("item_selected", callable_mp(editor, &VisualShaderEditor::_change_input_port_type).bind(p_id, i), CONNECT_DEFERRED);
LineEdit *name_box = memnew(LineEdit);
hb->add_child(name_box);
name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
name_box->set_text(name_left);
- name_box->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_change_input_port_name), varray(name_box, p_id, i), CONNECT_DEFERRED);
- name_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, false), CONNECT_DEFERRED);
+ name_box->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_change_input_port_name).bind(name_box, p_id, i), CONNECT_DEFERRED);
+ name_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, i, false), CONNECT_DEFERRED);
Button *remove_btn = memnew(Button);
remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
remove_btn->set_tooltip(TTR("Remove") + " " + name_left);
- remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_input_port), varray(p_id, i), CONNECT_DEFERRED);
+ remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_input_port).bind(p_id, i), CONNECT_DEFERRED);
hb->add_child(remove_btn);
} else {
Label *label = memnew(Label);
label->set_text(name_left);
- label->add_theme_style_override("normal", label_style); //more compact
+ label->add_theme_style_override("normal", editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); //more compact
hb->add_child(label);
if (vsnode->is_input_port_default(i, mode) && !port_left_used) {
Label *hint_label = memnew(Label);
hint_label->set_text(TTR("[default]"));
hint_label->add_theme_color_override("font_color", editor->get_theme_color(SNAME("font_readonly_color"), SNAME("TextEdit")));
- hint_label->add_theme_style_override("normal", label_style);
+ hint_label->add_theme_style_override("normal", editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor")));
hb->add_child(hint_label);
}
}
@@ -784,7 +781,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Button *remove_btn = memnew(Button);
remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
remove_btn->set_tooltip(TTR("Remove") + " " + name_left);
- remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_output_port), varray(p_id, i), CONNECT_DEFERRED);
+ remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_output_port).bind(p_id, i), CONNECT_DEFERRED);
hb->add_child(remove_btn);
LineEdit *name_box = memnew(LineEdit);
@@ -792,8 +789,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
name_box->set_text(name_right);
- name_box->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_change_output_port_name), varray(name_box, p_id, i), CONNECT_DEFERRED);
- name_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, true), CONNECT_DEFERRED);
+ name_box->connect("text_submitted", callable_mp(editor, &VisualShaderEditor::_change_output_port_name).bind(name_box, p_id, i), CONNECT_DEFERRED);
+ name_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, i, true), CONNECT_DEFERRED);
OptionButton *type_box = memnew(OptionButton);
hb->add_child(type_box);
@@ -806,11 +803,11 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
type_box->add_item(TTR("Transform"));
type_box->select(group_node->get_output_port_type(i));
type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- type_box->connect("item_selected", callable_mp(editor, &VisualShaderEditor::_change_output_port_type), varray(p_id, i), CONNECT_DEFERRED);
+ type_box->connect("item_selected", callable_mp(editor, &VisualShaderEditor::_change_output_port_type).bind(p_id, i), CONNECT_DEFERRED);
} else {
Label *label = memnew(Label);
label->set_text(name_right);
- label->add_theme_style_override("normal", label_style); //more compact
+ label->add_theme_style_override("normal", editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); //more compact
hb->add_child(label);
}
}
@@ -824,7 +821,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
expand->set_pressed_texture(editor->get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")));
expand->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
expand->set_pressed(vsnode->_is_output_port_expanded(i));
- expand->connect("pressed", callable_mp(editor, &VisualShaderEditor::_expand_output_port), varray(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED);
+ expand->connect("pressed", callable_mp(editor, &VisualShaderEditor::_expand_output_port).bind(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED);
hb->add_child(expand);
}
if (vsnode->has_output_port_preview(i) && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
@@ -836,7 +833,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
register_output_port(p_id, j, preview);
- preview->connect("pressed", callable_mp(editor, &VisualShaderEditor::_preview_select_port), varray(p_id, j), CONNECT_DEFERRED);
+ preview->connect("pressed", callable_mp(editor, &VisualShaderEditor::_preview_select_port).bind(p_id, j), CONNECT_DEFERRED);
hb->add_child(preview);
}
}
@@ -1018,7 +1015,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
expression_box->set_context_menu_enabled(false);
expression_box->set_draw_line_numbers(true);
- expression_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_expression_focus_out), varray(expression_box, p_id));
+ expression_box->connect("focus_exited", callable_mp(editor, &VisualShaderEditor::_expression_focus_out).bind(expression_box, p_id));
}
if (is_comment) {
@@ -1035,10 +1032,6 @@ void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int p_id) {
}
void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (!editor) {
- return;
- }
GraphEdit *graph = editor->graph;
if (!graph) {
return;
@@ -1055,10 +1048,6 @@ void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_fro
}
void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (!editor) {
- return;
- }
GraphEdit *graph = editor->graph;
if (!graph) {
return;
@@ -1085,6 +1074,27 @@ VisualShaderGraphPlugin::~VisualShaderGraphPlugin() {
/////////////////
+void VisualShaderEditedProperty::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_edited_property", "value"), &VisualShaderEditedProperty::set_edited_property);
+ ClassDB::bind_method(D_METHOD("get_edited_property"), &VisualShaderEditedProperty::get_edited_property);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NIL, "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_edited_property", "get_edited_property");
+}
+
+void VisualShaderEditedProperty::set_edited_property(Variant p_variant) {
+ edited_property = p_variant;
+}
+
+Variant VisualShaderEditedProperty::get_edited_property() const {
+ return edited_property;
+}
+
+/////////////////
+
+Vector2 VisualShaderEditor::selection_center;
+List<VisualShaderEditor::CopyItem> VisualShaderEditor::copy_items_buffer;
+List<VisualShader::Connection> VisualShaderEditor::copy_connections_buffer;
+
void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
bool changed = false;
if (p_visual_shader) {
@@ -1602,7 +1612,7 @@ void VisualShaderEditor::_update_created_node(GraphNode *node) {
}
void VisualShaderEditor::_update_uniforms(bool p_update_refs) {
- VisualShaderNodeUniformRef::clear_uniforms();
+ VisualShaderNodeUniformRef::clear_uniforms(visual_shader->get_rid());
for (int t = 0; t < VisualShader::TYPE_MAX; t++) {
Vector<int> tnodes = visual_shader->get_node_list((VisualShader::Type)t);
@@ -1640,7 +1650,7 @@ void VisualShaderEditor::_update_uniforms(bool p_update_refs) {
} else {
uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_SAMPLER;
}
- VisualShaderNodeUniformRef::add_uniform(uniform->get_uniform_name(), uniform_type);
+ VisualShaderNodeUniformRef::add_uniform(visual_shader->get_rid(), uniform->get_uniform_name(), uniform_type);
}
}
}
@@ -2288,10 +2298,8 @@ void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id,
}
}
-void VisualShaderEditor::_port_edited() {
+void VisualShaderEditor::_port_edited(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
VisualShader::Type type = get_current_shader_type();
-
- Variant value = property_editor->get_variant();
Ref<VisualShaderNode> vsn = visual_shader->get_node(type, editing_node);
ERR_FAIL_COND(!vsn.is_valid());
@@ -2299,30 +2307,51 @@ void VisualShaderEditor::_port_edited() {
Ref<VisualShaderNodeCustom> custom = Object::cast_to<VisualShaderNodeCustom>(vsn.ptr());
if (custom.is_valid()) {
- undo_redo->add_do_method(custom.ptr(), "_set_input_port_default_value", editing_port, value);
+ undo_redo->add_do_method(custom.ptr(), "_set_input_port_default_value", editing_port, p_value);
undo_redo->add_undo_method(custom.ptr(), "_set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port));
} else {
- undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value);
+ undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, p_value);
undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port));
}
- undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, value);
+ undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, p_value);
undo_redo->add_undo_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, vsn->get_input_port_default_value(editing_port));
undo_redo->commit_action();
-
- property_editor->hide();
}
void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node, int p_port) {
VisualShader::Type type = get_current_shader_type();
+ Ref<VisualShaderNode> vs_node = visual_shader->get_node(type, p_node);
+ Variant value = vs_node->get_input_port_default_value(p_port);
+
+ edited_property_holder->set_edited_property(value);
+
+ if (property_editor) {
+ property_editor->disconnect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited));
+ property_editor_popup->remove_child(property_editor);
+ }
+
+ // TODO: Define these properties with actual PropertyInfo and feed it to the property editor widget.
+ property_editor = EditorInspector::instantiate_property_editor(edited_property_holder.ptr(), value.get_type(), "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE);
+ if (property_editor) {
+ property_editor->set_object_and_property(edited_property_holder.ptr(), "edited_property");
+ property_editor->update_property();
+ property_editor->set_name_split_ratio(0);
+ property_editor_popup->add_child(property_editor);
- Ref<VisualShaderNode> vsn = visual_shader->get_node(type, p_node);
+ property_editor->connect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited));
+
+ Button *button = Object::cast_to<Button>(p_button);
+ if (button) {
+ property_editor_popup->set_position(button->get_screen_position() + Vector2(0, button->get_size().height) * graph->get_zoom());
+ }
+ property_editor_popup->reset_size();
+ if (button) {
+ property_editor_popup->popup();
+ } else {
+ property_editor_popup->popup_centered_ratio();
+ }
+ }
- Button *button = Object::cast_to<Button>(p_button);
- ERR_FAIL_COND(!button);
- Variant value = vsn->get_input_port_default_value(p_port);
- property_editor->set_position(button->get_screen_position() + Vector2(0, button->get_size().height));
- property_editor->edit(nullptr, "", value.get_type(), value, 0, "");
- property_editor->popup();
editing_node = p_node;
editing_port = p_port;
}
@@ -2645,7 +2674,6 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri
_setup_node(vsn, p_ops);
}
VisualShaderNodeUniformRef *uniform_ref = Object::cast_to<VisualShaderNodeUniformRef>(vsn);
-
if (uniform_ref && to_node != -1 && to_slot != -1) {
VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot);
bool success = false;
@@ -4565,9 +4593,9 @@ void VisualShaderEditor::_preview_size_changed() {
preview_vbox->set_custom_minimum_size(preview_window->get_size());
}
-static ShaderLanguage::DataType _get_global_variable_type(const StringName &p_variable) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_variable);
- return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt);
+static ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_variable) {
+ RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_variable);
+ return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
}
void VisualShaderEditor::_update_preview() {
@@ -4584,7 +4612,7 @@ void VisualShaderEditor::_update_preview() {
info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode()));
info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
info.shader_types = ShaderTypes::get_singleton()->get_types();
- info.global_variable_type_func = _get_global_variable_type;
+ info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
ShaderLanguage sl;
@@ -4644,10 +4672,7 @@ void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_is_available", &VisualShaderEditor::_is_available);
}
-VisualShaderEditor *VisualShaderEditor::singleton = nullptr;
-
VisualShaderEditor::VisualShaderEditor() {
- singleton = this;
ShaderLanguage::get_keyword_list(&keyword_list);
graph = memnew(GraphEdit);
@@ -4671,13 +4696,13 @@ VisualShaderEditor::VisualShaderEditor() {
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SAMPLER);
//graph->add_valid_left_disconnect_type(0);
graph->set_v_size_flags(SIZE_EXPAND_FILL);
- graph->connect("connection_request", callable_mp(this, &VisualShaderEditor::_connection_request), varray(), CONNECT_DEFERRED);
- graph->connect("disconnection_request", callable_mp(this, &VisualShaderEditor::_disconnection_request), varray(), CONNECT_DEFERRED);
+ graph->connect("connection_request", callable_mp(this, &VisualShaderEditor::_connection_request), CONNECT_DEFERRED);
+ graph->connect("disconnection_request", callable_mp(this, &VisualShaderEditor::_disconnection_request), CONNECT_DEFERRED);
graph->connect("node_selected", callable_mp(this, &VisualShaderEditor::_node_selected));
graph->connect("scroll_offset_changed", callable_mp(this, &VisualShaderEditor::_scroll_changed));
graph->connect("duplicate_nodes_request", callable_mp(this, &VisualShaderEditor::_duplicate_nodes));
- graph->connect("copy_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes), varray(false));
- graph->connect("paste_nodes_request", callable_mp(this, &VisualShaderEditor::_paste_nodes), varray(false, Point2()));
+ graph->connect("copy_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes).bind(false));
+ graph->connect("paste_nodes_request", callable_mp(this, &VisualShaderEditor::_paste_nodes).bind(false, Point2()));
graph->connect("delete_nodes_request", callable_mp(this, &VisualShaderEditor::_delete_nodes_request));
graph->connect("gui_input", callable_mp(this, &VisualShaderEditor::_graph_gui_input));
graph->connect("connection_to_empty", callable_mp(this, &VisualShaderEditor::_connection_to_empty));
@@ -4780,7 +4805,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_node->set_text(TTR("Add Node..."));
graph->get_zoom_hbox()->add_child(add_node);
graph->get_zoom_hbox()->move_child(add_node, 0);
- add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog), varray(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX));
+ add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog).bind(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX));
varying_button = memnew(Button);
varying_button->set_flat(true);
@@ -4911,7 +4936,7 @@ VisualShaderEditor::VisualShaderEditor() {
members_dialog->set_title(TTR("Create Shader Node"));
members_dialog->set_exclusive(false);
members_dialog->add_child(members_vb);
- members_dialog->get_ok_button()->set_text(TTR("Create"));
+ members_dialog->set_ok_button_text(TTR("Create"));
members_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualShaderEditor::_member_create));
members_dialog->get_ok_button()->set_disabled(true);
members_dialog->connect("cancelled", callable_mp(this, &VisualShaderEditor::_member_cancel));
@@ -4922,7 +4947,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_varying_dialog = memnew(ConfirmationDialog);
add_varying_dialog->set_title(TTR("Create Shader Varying"));
add_varying_dialog->set_exclusive(false);
- add_varying_dialog->get_ok_button()->set_text(TTR("Create"));
+ add_varying_dialog->set_ok_button_text(TTR("Create"));
add_varying_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualShaderEditor::_varying_create));
add_varying_dialog->get_ok_button()->set_disabled(true);
add_child(add_varying_dialog);
@@ -4966,7 +4991,7 @@ VisualShaderEditor::VisualShaderEditor() {
remove_varying_dialog = memnew(ConfirmationDialog);
remove_varying_dialog->set_title(TTR("Delete Shader Varying"));
remove_varying_dialog->set_exclusive(false);
- remove_varying_dialog->get_ok_button()->set_text(TTR("Delete"));
+ remove_varying_dialog->set_ok_button_text(TTR("Delete"));
remove_varying_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualShaderEditor::_varying_deleted));
add_child(remove_varying_dialog);
@@ -5152,6 +5177,10 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("ViewIndex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("NodePositionWorld", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraPositionWorld", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraDirectionWorld", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("NodePositionView", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
@@ -5167,6 +5196,10 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("ViewIndex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("NodePositionWorld", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraPositionWorld", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraDirectionWorld", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("NodePositionView", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "albedo", "ALBEDO"), { "albedo" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation", "ATTENUATION"), { "attenuation" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
@@ -5544,8 +5577,12 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
+ add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
+ add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
@@ -5635,19 +5672,23 @@ VisualShaderEditor::VisualShaderEditor() {
Ref<VisualShaderNodePluginDefault> default_plugin;
default_plugin.instantiate();
+ default_plugin->set_editor(this);
add_plugin(default_plugin);
graph_plugin.instantiate();
+ graph_plugin->set_editor(this);
- property_editor = memnew(CustomPropertyEditor);
- add_child(property_editor);
+ property_editor_popup = memnew(PopupPanel);
+ property_editor_popup->set_min_size(Size2i(180, 0) * EDSCALE);
+ add_child(property_editor_popup);
- property_editor->connect("variant_changed", callable_mp(this, &VisualShaderEditor::_port_edited));
+ edited_property_holder.instantiate();
}
class VisualShaderNodePluginInputEditor : public OptionButton {
GDCLASS(VisualShaderNodePluginInputEditor, OptionButton);
+ VisualShaderEditor *editor = nullptr;
Ref<VisualShaderNodeInput> input;
public:
@@ -5660,13 +5701,11 @@ public:
}
void _item_selected(int p_item) {
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (editor) {
- editor->call_deferred(SNAME("_input_select_item"), input, get_item_text(p_item));
- }
+ editor->call_deferred(SNAME("_input_select_item"), input, get_item_text(p_item));
}
- void setup(const Ref<VisualShaderNodeInput> &p_input) {
+ void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeInput> &p_input) {
+ editor = p_editor;
input = p_input;
Ref<Texture2D> type_icon[] = {
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")),
@@ -5699,6 +5738,7 @@ public:
class VisualShaderNodePluginVaryingEditor : public OptionButton {
GDCLASS(VisualShaderNodePluginVaryingEditor, OptionButton);
+ VisualShaderEditor *editor = nullptr;
Ref<VisualShaderNodeVarying> varying;
public:
@@ -5709,13 +5749,11 @@ public:
}
void _item_selected(int p_item) {
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (editor) {
- editor->call_deferred(SNAME("_varying_select_item"), varying, get_item_text(p_item));
- }
+ editor->call_deferred(SNAME("_varying_select_item"), varying, get_item_text(p_item));
}
- void setup(const Ref<VisualShaderNodeVarying> &p_varying, VisualShader::Type p_type) {
+ void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeVarying> &p_varying, VisualShader::Type p_type) {
+ editor = p_editor;
varying = p_varying;
Ref<Texture2D> type_icon[] = {
@@ -5776,6 +5814,7 @@ public:
class VisualShaderNodePluginUniformRefEditor : public OptionButton {
GDCLASS(VisualShaderNodePluginUniformRefEditor, OptionButton);
+ VisualShaderEditor *editor = nullptr;
Ref<VisualShaderNodeUniformRef> uniform_ref;
public:
@@ -5788,13 +5827,11 @@ public:
}
void _item_selected(int p_item) {
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (editor) {
- editor->call_deferred(SNAME("_uniform_select_item"), uniform_ref, get_item_text(p_item));
- }
+ editor->call_deferred(SNAME("_uniform_select_item"), uniform_ref, get_item_text(p_item));
}
- void setup(const Ref<VisualShaderNodeUniformRef> &p_uniform_ref) {
+ void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeUniformRef> &p_uniform_ref) {
+ editor = p_editor;
uniform_ref = p_uniform_ref;
Ref<Texture2D> type_icon[] = {
@@ -5828,6 +5865,7 @@ public:
class VisualShaderNodePluginDefaultEditor : public VBoxContainer {
GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer);
+ VisualShaderEditor *editor = nullptr;
Ref<Resource> parent_resource;
int node_id = 0;
VisualShader::Type shader_type;
@@ -5861,13 +5899,10 @@ public:
}
}
if (p_property != "constant") {
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (editor) {
- VisualShaderGraphPlugin *graph_plugin = editor->get_graph_plugin();
- if (graph_plugin) {
- undo_redo->add_do_method(graph_plugin, "update_node_deferred", shader_type, node_id);
- undo_redo->add_undo_method(graph_plugin, "update_node_deferred", shader_type, node_id);
- }
+ VisualShaderGraphPlugin *graph_plugin = editor->get_graph_plugin();
+ if (graph_plugin) {
+ undo_redo->add_do_method(graph_plugin, "update_node_deferred", shader_type, node_id);
+ undo_redo->add_undo_method(graph_plugin, "update_node_deferred", shader_type, node_id);
}
}
undo_redo->commit_action();
@@ -5903,7 +5938,8 @@ public:
}
}
- void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, const HashMap<StringName, String> &p_overrided_names, Ref<VisualShaderNode> p_node) {
+ void setup(VisualShaderEditor *p_editor, Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, const HashMap<StringName, String> &p_overrided_names, Ref<VisualShaderNode> p_node) {
+ editor = p_editor;
parent_resource = p_parent_resource;
updating = false;
node = p_node;
@@ -5956,19 +5992,19 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par
if (p_shader.is_valid() && (p_node->is_class("VisualShaderNodeVaryingGetter") || p_node->is_class("VisualShaderNodeVaryingSetter"))) {
VisualShaderNodePluginVaryingEditor *editor = memnew(VisualShaderNodePluginVaryingEditor);
- editor->setup(p_node, p_shader->get_shader_type());
+ editor->setup(vseditor, p_node, p_shader->get_shader_type());
return editor;
}
if (p_node->is_class("VisualShaderNodeUniformRef")) {
VisualShaderNodePluginUniformRefEditor *editor = memnew(VisualShaderNodePluginUniformRefEditor);
- editor->setup(p_node);
+ editor->setup(vseditor, p_node);
return editor;
}
if (p_node->is_class("VisualShaderNodeInput")) {
VisualShaderNodePluginInputEditor *editor = memnew(VisualShaderNodePluginInputEditor);
- editor->setup(p_node);
+ editor->setup(vseditor, p_node);
return editor;
}
@@ -6023,22 +6059,22 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par
properties.push_back(pinfo[i].name);
}
VisualShaderNodePluginDefaultEditor *editor = memnew(VisualShaderNodePluginDefaultEditor);
- editor->setup(p_parent_resource, editors, properties, p_node->get_editable_properties_names(), p_node);
+ editor->setup(vseditor, p_parent_resource, editors, properties, p_node->get_editable_properties_names(), p_node);
return editor;
}
void EditorPropertyShaderMode::_option_selected(int p_which) {
- VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
- if (!editor) {
+ Ref<VisualShader> visual_shader(Object::cast_to<VisualShader>(get_edited_object()));
+ if (visual_shader->get_mode() == p_which) {
return;
}
- //will not use this, instead will do all the logic setting manually
- //emit_signal(SNAME("property_changed"), get_edited_property(), p_which);
-
- Ref<VisualShader> visual_shader(Object::cast_to<VisualShader>(get_edited_object()));
-
- if (visual_shader->get_mode() == p_which) {
+ ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_singleton()->get_editor_data().get_editor("Shader"));
+ if (!shader_editor) {
+ return;
+ }
+ VisualShaderEditor *editor = shader_editor->get_visual_shader_editor(visual_shader);
+ if (!editor) {
return;
}
@@ -6145,10 +6181,10 @@ bool EditorInspectorShaderModePlugin::can_handle(Object *p_object) {
bool EditorInspectorShaderModePlugin::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 == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) {
- EditorPropertyShaderMode *editor = memnew(EditorPropertyShaderMode);
+ EditorPropertyShaderMode *mode_editor = memnew(EditorPropertyShaderMode);
Vector<String> options = p_hint_text.split(",");
- editor->setup(options);
- add_property_editor(p_path, editor);
+ mode_editor->setup(options);
+ add_property_editor(p_path, mode_editor);
return true;
}
@@ -6196,7 +6232,7 @@ void VisualShaderNodePortPreview::_shader_changed() {
}
if (src_mat && src_mat->get_shader().is_valid()) {
List<PropertyInfo> params;
- src_mat->get_shader()->get_param_list(&params);
+ src_mat->get_shader()->get_shader_uniform_list(&params);
for (const PropertyInfo &E : params) {
material->set(E.name, src_mat->get(E.name));
}
@@ -6217,7 +6253,7 @@ void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, Visua
}
Size2 VisualShaderNodePortPreview::get_minimum_size() const {
- int port_preview_size = EditorSettings::get_singleton()->get("editors/visual_editors/visualshader/port_preview_size");
+ int port_preview_size = EditorSettings::get_singleton()->get("editors/visual_editors/visual_shader/port_preview_size");
return Size2(port_preview_size, port_preview_size) * EDSCALE;
}
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index b8da266ed7..b846c34f9e 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -32,25 +32,36 @@
#define VISUAL_SHADER_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "editor/plugins/curve_editor_plugin.h"
-#include "editor/property_editor.h"
-#include "scene/gui/button.h"
-#include "scene/gui/code_edit.h"
-#include "scene/gui/graph_edit.h"
-#include "scene/gui/popup.h"
-#include "scene/gui/rich_text_label.h"
-#include "scene/gui/tree.h"
+#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "scene/resources/visual_shader.h"
+class Button;
+class CodeEdit;
+class CodeHighlighter;
+class CurveEditor;
+class GraphEdit;
+class GraphNode;
+class PopupMenu;
+class PopupPanel;
+class RichTextLabel;
+class TextEdit;
+class Tree;
+
+class VisualShaderEditor;
+
class VisualShaderNodePlugin : public RefCounted {
GDCLASS(VisualShaderNodePlugin, RefCounted);
protected:
+ VisualShaderEditor *vseditor = nullptr;
+
+protected:
static void _bind_methods();
GDVIRTUAL2RC(Object *, _create_editor, Ref<Resource>, Ref<VisualShaderNode>)
public:
+ void set_editor(VisualShaderEditor *p_editor);
virtual Control *create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node);
};
@@ -58,6 +69,8 @@ class VisualShaderGraphPlugin : public RefCounted {
GDCLASS(VisualShaderGraphPlugin, RefCounted);
private:
+ VisualShaderEditor *editor = nullptr;
+
struct InputPort {
Button *default_input_button = nullptr;
};
@@ -91,6 +104,7 @@ protected:
static void _bind_methods();
public:
+ void set_editor(VisualShaderEditor *p_editor);
void register_shader(VisualShader *p_visual_shader);
void set_connections(const List<VisualShader::Connection> &p_connections);
void register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node);
@@ -128,13 +142,31 @@ public:
~VisualShaderGraphPlugin();
};
+class VisualShaderEditedProperty : public RefCounted {
+ GDCLASS(VisualShaderEditedProperty, RefCounted);
+
+private:
+ Variant edited_property;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_edited_property(Variant p_variant);
+ Variant get_edited_property() const;
+
+ VisualShaderEditedProperty() {}
+};
+
class VisualShaderEditor : public VBoxContainer {
GDCLASS(VisualShaderEditor, VBoxContainer);
friend class VisualShaderGraphPlugin;
- CustomPropertyEditor *property_editor = nullptr;
+ PopupPanel *property_editor_popup = nullptr;
+ EditorProperty *property_editor = nullptr;
int editing_node = -1;
int editing_port = -1;
+ Ref<VisualShaderEditedProperty> edited_property_holder;
Ref<VisualShader> visual_shader;
GraphEdit *graph = nullptr;
@@ -324,8 +356,6 @@ class VisualShaderEditor : public VBoxContainer {
void _update_preview();
String _get_description(int p_idx);
- static VisualShaderEditor *singleton;
-
struct DragOp {
VisualShader::Type type = VisualShader::Type::TYPE_MAX;
int node = 0;
@@ -351,7 +381,7 @@ class VisualShaderEditor : public VBoxContainer {
void _node_changed(int p_id);
void _edit_port_default_input(Object *p_button, int p_node, int p_port);
- void _port_edited();
+ void _port_edited(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing);
int to_node = -1;
int to_slot = -1;
@@ -403,9 +433,9 @@ class VisualShaderEditor : public VBoxContainer {
void _duplicate_nodes();
- Vector2 selection_center;
- List<CopyItem> copy_items_buffer;
- List<VisualShader::Connection> copy_connections_buffer;
+ static Vector2 selection_center;
+ static List<CopyItem> copy_items_buffer;
+ static List<VisualShader::Connection> copy_connections_buffer;
void _clear_copy_buffer();
void _copy_nodes(bool p_cut);
@@ -482,7 +512,6 @@ public:
void add_plugin(const Ref<VisualShaderNodePlugin> &p_plugin);
void remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin);
- static VisualShaderEditor *get_singleton() { return singleton; }
VisualShaderGraphPlugin *get_graph_plugin() { return graph_plugin.ptr(); }
void clear_custom_types();
diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp
index 6fc6c1ad39..e3b2be33df 100644
--- a/editor/plugins/voxel_gi_editor_plugin.cpp
+++ b/editor/plugins/voxel_gi_editor_plugin.cpp
@@ -139,7 +139,7 @@ void VoxelGIEditorPlugin::_voxel_gi_save_path_and_bake(const String &p_path) {
if (voxel_gi) {
voxel_gi->bake();
ERR_FAIL_COND(voxel_gi->get_probe_data().is_null());
- ResourceSaver::save(p_path, voxel_gi->get_probe_data(), ResourceSaver::FLAG_CHANGE_PATH);
+ ResourceSaver::save(voxel_gi->get_probe_data(), p_path, ResourceSaver::FLAG_CHANGE_PATH);
}
}
diff --git a/editor/plugins/voxel_gi_editor_plugin.h b/editor/plugins/voxel_gi_editor_plugin.h
index 621e98beef..43d6f71e26 100644
--- a/editor/plugins/voxel_gi_editor_plugin.h
+++ b/editor/plugins/voxel_gi_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VOXEL_GIEDITORPLUGIN_H
-#define VOXEL_GIEDITORPLUGIN_H
+#ifndef VOXEL_GI_EDITOR_PLUGIN_H
+#define VOXEL_GI_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/3d/voxel_gi.h"
@@ -71,4 +71,4 @@ public:
~VoxelGIEditorPlugin();
};
-#endif // VOXEL_GIEDITORPLUGIN_H
+#endif // VOXEL_GI_EDITOR_PLUGIN_H
diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp
index ed13afc235..1c9afa8be8 100644
--- a/editor/progress_dialog.cpp
+++ b/editor/progress_dialog.cpp
@@ -50,7 +50,7 @@ void BackgroundProgress::_add_task(const String &p_task, const String &p_label,
Control *ec = memnew(Control);
ec->set_h_size_flags(SIZE_EXPAND_FILL);
ec->set_v_size_flags(SIZE_EXPAND_FILL);
- t.progress->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ t.progress->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
ec->add_child(t.progress);
ec->set_custom_minimum_size(Size2(80, 5) * EDSCALE);
t.hb->add_child(ec);
@@ -235,7 +235,7 @@ void ProgressDialog::_bind_methods() {
ProgressDialog::ProgressDialog() {
main = memnew(VBoxContainer);
add_child(main);
- main->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ main->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
set_exclusive(true);
last_progress_tick = 0;
singleton = this;
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 9ed3b72587..421e56f9a1 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -42,7 +42,8 @@ const int ERROR_CODE = 77;
#include "core/templates/hash_map.h"
#include "core/templates/list.h"
-const int CONVERSION_MAX_FILE_SIZE = 1024 * 1024 * 4; // 4 MB
+const uint64_t CONVERSION_MAX_FILE_SIZE_MB = 4;
+const uint64_t CONVERSION_MAX_FILE_SIZE = 1024 * 1024 * CONVERSION_MAX_FILE_SIZE_MB;
static const char *enum_renames[][2] = {
//// constants
@@ -120,7 +121,7 @@ static const char *enum_renames[][2] = {
{ "JOINT_PIN", "JOINT_TYPE_PIN" }, // PhysicsServer2D
{ "JOINT_SLIDER", "JOINT_TYPE_SLIDER" }, // PhysicsServer3D
{ "KEY_CONTROL", "KEY_CTRL" }, // Globals
- { "LOOP_PING_PONG", "LOOP_PINGPONG" }, //AudioStreamSample
+ { "LOOP_PING_PONG", "LOOP_PINGPONG" }, // AudioStreamWAV
{ "MATH_RAND", "MATH_RANDF_RANGE" }, // VisualScriptBuiltinFunc
{ "MATH_RANDOM", "MATH_RANDI_RANGE" }, // VisualScriptBuiltinFunc
{ "MATH_STEPIFY", "MATH_STEP_DECIMALS" }, // VisualScriptBuiltinFunc
@@ -255,6 +256,7 @@ static const char *gdscript_function_renames[][2] = {
{ "damped_spring_joint_create", "joint_make_damped_spring" }, // PhysicsServer2D
{ "damped_string_joint_get_param", "damped_spring_joint_get_param" }, // PhysicsServer2D
{ "damped_string_joint_set_param", "damped_spring_joint_set_param" }, // PhysicsServer2D
+ { "dectime", "move_toward" }, // GDScript, Math functions
{ "delete_char_at_cursor", "delete_char_at_caret" }, // LineEdit
{ "deselect_items", "deselect_all" }, // FileDialog
{ "disable_plugin", "_disable_plugin" }, // EditorPlugin
@@ -427,6 +429,7 @@ static const char *gdscript_function_renames[][2] = {
{ "joint_create_slider", "joint_make_slider" }, // PhysicsServer3D
{ "line_intersects_line_2d", "line_intersects_line" }, // Geometry2D
{ "load_from_globals", "load_from_project_settings" }, // InputMap
+ { "load_interactive", "load_threaded_request" }, // ResourceLoader - load_threaded_request is alternative, but is used differently
{ "make_convex_from_brothers", "make_convex_from_siblings" }, // CollisionShape3D
{ "make_visible", "_make_visible" }, // EditorPlugin
{ "merge_polygons_2d", "merge_polygons" }, // Geometry2D
@@ -484,6 +487,7 @@ static const char *gdscript_function_renames[][2] = {
{ "set_enabled_focus_mode", "set_focus_mode" }, // BaseButton
{ "set_endian_swap", "set_big_endian" }, // File
{ "set_expand_to_text_length", "set_expand_to_text_length_enabled" }, // LineEdit
+ { "set_filename", "set_scene_file_path" }, // Node, WARNING, this may be used in a lot of other places
{ "set_focus_neighbour", "set_focus_neighbor" }, // Control
{ "set_frame_color", "set_color" }, // ColorRect
{ "set_global_rate_scale", "set_playback_speed_scale" }, // AudioServer
@@ -975,6 +979,7 @@ static const char *gdscript_properties_renames[][2] = {
// { "wrap_enabled", "wrap_mode" }, // TextEdit
// { "zfar", "far" }, // Camera3D
// { "znear", "near" }, // Camera3D
+ // { "filename", "scene_file_path" }, // Node
{ "as_normalmap", "as_normal_map" }, // NoiseTexture
{ "bbcode_text", "text" }, // RichTextLabel
{ "caret_moving_by_right_click", "caret_move_on_right_click" }, // TextEdit
@@ -1250,10 +1255,12 @@ static const char *class_renames[][2] = {
{ "AnimatedSprite", "AnimatedSprite2D" },
{ "AnimationTreePlayer", "AnimationTree" },
{ "Area", "Area3D" }, // Be careful, this will be used everywhere
+ { "AudioStreamOGGVorbis", "AudioStreamOggVorbis" },
{ "AudioStreamRandomPitch", "AudioStreamRandomizer" },
+ { "AudioStreamSample", "AudioStreamWAV" },
{ "BakedLightmap", "LightmapGI" },
{ "BakedLightmapData", "LightmapGIData" },
- { "BitmapFont", "Font" },
+ { "BitmapFont", "FontFile" },
{ "BoneAttachment", "BoneAttachment3D" },
{ "BoxShape", "BoxShape3D" },
{ "CPUParticles", "CPUParticles3D" },
@@ -1279,8 +1286,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" },
@@ -1593,12 +1600,33 @@ static const char *colors_renames[][2] = {
{ nullptr, nullptr },
};
+class ProjectConverter3To4::RegExContainer {
+public:
+ RegEx reg_is_empty = RegEx("\\bempty\\(");
+ RegEx reg_super = RegEx("([\t ])\\.([a-zA-Z_])");
+ RegEx reg_json_to = RegEx("\\bto_json\\b");
+ RegEx reg_json_parse = RegEx("([\t]{0,})([^\n]+)parse_json\\(([^\n]+)");
+ RegEx reg_json_non_new = RegEx("([\t]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)");
+ RegEx reg_export = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)");
+ RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)");
+ RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)");
+ RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^a-z^A-Z^0-9^_]*$");
+ RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$");
+ RegEx reg_join = RegEx("([\\(\\)a-zA-Z0-9_]+)\\.join\\(([^\n^\\)]+)\\)");
+ RegEx reg_mixed_tab_space = RegEx("([\t]+)([ ]+)");
+ RegEx reg_image_lock = RegEx("([a-zA-Z0-9_\\.]+)\\.lock\\(\\)");
+ RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)");
+ RegEx reg_os_fullscreen = RegEx("OS.window_fullscreen[= ]+([^#^\n]+)");
+};
+
// Function responsible for converting project
int ProjectConverter3To4::convert() {
print_line("Starting conversion.");
+ RegExContainer reg_container = RegExContainer();
+
ERR_FAIL_COND_V_MSG(!test_array_names(), ERROR_CODE, "Cannot start converting due to problems with data in arrays.");
- ERR_FAIL_COND_V_MSG(!test_conversion(), ERROR_CODE, "Cannot start converting due to problems with converting arrays.");
+ ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), ERROR_CODE, "Cannot start converting due to problems with converting arrays.");
// Checking if folder contains valid Godot 3 project.
// Project cannot be converted 2 times
@@ -1638,7 +1666,7 @@ int ProjectConverter3To4::convert() {
uint64_t start_time = Time::get_singleton()->get_ticks_msec();
if (file_name.ends_with(".shader")) {
- DirAccess::remove_file_or_error(file_name);
+ DirAccess::remove_file_or_error(file_name.trim_prefix("res://"));
file_name = file_name.replace(".shader", ".gdshader");
}
@@ -1651,7 +1679,7 @@ int ProjectConverter3To4::convert() {
rename_enums(file_content); // Require to additional rename
rename_common(gdscript_function_renames, file_content);
- rename_gdscript_functions(file_content); // Require to additional rename
+ rename_gdscript_functions(file_content, reg_container, false); // Require to additional rename
rename_common(project_settings_renames, file_content);
rename_gdscript_keywords(file_content);
@@ -1669,7 +1697,7 @@ int ProjectConverter3To4::convert() {
rename_enums(file_content); // Require to additional rename
rename_common(gdscript_function_renames, file_content);
- rename_gdscript_functions(file_content); // Require to additional rename
+ rename_gdscript_functions(file_content, reg_container, true); // Require to additional rename
rename_common(project_settings_renames, file_content);
rename_gdscript_keywords(file_content);
@@ -1686,6 +1714,7 @@ int ProjectConverter3To4::convert() {
rename_common(csharp_properties_renames, file_content);
rename_common(csharp_signals_renames, file_content);
rename_csharp_functions(file_content);
+ rename_csharp_attributes(file_content);
custom_rename(file_content, "public class ", "public partial class ");
} else if (file_name.ends_with(".gdshader") || file_name.ends_with(".shader")) {
rename_common(shaders_renames, file_content);
@@ -1706,7 +1735,7 @@ int ProjectConverter3To4::convert() {
continue;
}
} else {
- reason.append(" ERROR: File has exceeded the maximum size allowed - 500 KB");
+ reason.append(" ERROR: File has exceeded the maximum size allowed - " + itos(CONVERSION_MAX_FILE_SIZE_MB) + " MB");
is_ignored = true;
}
@@ -1716,7 +1745,7 @@ int ProjectConverter3To4::convert() {
uint64_t hash_after = file_content.hash64();
// Don't need to save file without any changes
// Save if this is a shader, because it was renamed
- if (hash_before != hash_after || file_name.find(".gdshader") != -1) {
+ if (hash_before != hash_after || file_name.ends_with(".gdshader")) {
converted_files++;
Ref<FileAccess> file = FileAccess::open(file_name, FileAccess::WRITE);
@@ -1740,8 +1769,10 @@ int ProjectConverter3To4::convert() {
int ProjectConverter3To4::validate_conversion() {
print_line("Starting checking if project conversion can be done.");
+ RegExContainer reg_container = RegExContainer();
+
ERR_FAIL_COND_V_MSG(!test_array_names(), ERROR_CODE, "Cannot start converting due to problems with data in arrays.");
- ERR_FAIL_COND_V_MSG(!test_conversion(), ERROR_CODE, "Cannot start converting due to problems with converting arrays.");
+ ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), ERROR_CODE, "Cannot start converting due to problems with converting arrays.");
// Checking if folder contains valid Godot 3 project.
// Project cannot be converted 2 times
@@ -1782,7 +1813,7 @@ int ProjectConverter3To4::validate_conversion() {
bool is_ignored = false;
uint64_t start_time = Time::get_singleton()->get_ticks_msec();
- if (file_name.ends_with(".sader")) {
+ if (file_name.ends_with(".shader")) {
reason.append("\tFile extension will be renamed from `shader` to `gdshader`.");
}
@@ -1794,7 +1825,7 @@ int ProjectConverter3To4::validate_conversion() {
changed_elements.append_array(check_for_rename_enums(file_content));
changed_elements.append_array(check_for_rename_common(gdscript_function_renames, file_content));
- changed_elements.append_array(check_for_rename_gdscript_functions(file_content));
+ changed_elements.append_array(check_for_rename_gdscript_functions(file_content, reg_container, false));
changed_elements.append_array(check_for_rename_common(project_settings_renames, file_content));
changed_elements.append_array(check_for_rename_gdscript_keywords(file_content));
@@ -1812,7 +1843,7 @@ int ProjectConverter3To4::validate_conversion() {
changed_elements.append_array(check_for_rename_enums(file_content));
changed_elements.append_array(check_for_rename_common(gdscript_function_renames, file_content));
- changed_elements.append_array(check_for_rename_gdscript_functions(file_content));
+ changed_elements.append_array(check_for_rename_gdscript_functions(file_content, reg_container, true));
changed_elements.append_array(check_for_rename_common(project_settings_renames, file_content));
changed_elements.append_array(check_for_rename_gdscript_keywords(file_content));
@@ -1829,6 +1860,7 @@ int ProjectConverter3To4::validate_conversion() {
changed_elements.append_array(check_for_rename_common(csharp_properties_renames, file_content));
changed_elements.append_array(check_for_rename_common(csharp_signals_renames, file_content));
changed_elements.append_array(check_for_rename_csharp_functions(file_content));
+ changed_elements.append_array(check_for_rename_csharp_attributes(file_content));
changed_elements.append_array(check_for_custom_rename(file_content, "public class ", "public partial class "));
} else if (file_name.ends_with(".gdshader") || file_name.ends_with(".shader")) {
changed_elements.append_array(check_for_rename_common(shaders_renames, file_content));
@@ -1849,7 +1881,7 @@ int ProjectConverter3To4::validate_conversion() {
continue;
}
} else {
- reason.append("\tERROR: File has exceeded the maximum size allowed - 500 KB");
+ reason.append("\tERROR: File has exceeded the maximum size allowed - " + itos(CONVERSION_MAX_FILE_SIZE_MB) + " MB");
is_ignored = true;
}
@@ -1896,14 +1928,14 @@ Vector<String> ProjectConverter3To4::check_for_files() {
continue;
}
if (dir.current_is_dir()) {
- directories_to_check.append(current_dir + file_name + "/");
+ directories_to_check.append(current_dir.plus_file(file_name) + "/");
} else {
bool proper_extension = false;
if (file_name.ends_with(".gd") || file_name.ends_with(".shader") || file_name.ends_with(".tscn") || file_name.ends_with(".tres") || file_name.ends_with(".godot") || file_name.ends_with(".cs") || file_name.ends_with(".csproj"))
proper_extension = true;
if (proper_extension) {
- collected_files.append(current_dir + file_name);
+ collected_files.append(current_dir.plus_file(file_name));
}
}
file_name = dir.get_next();
@@ -1926,6 +1958,17 @@ bool ProjectConverter3To4::test_conversion_single_additional(String name, String
return true;
}
+bool ProjectConverter3To4::test_conversion_single_additional_builtin(String name, String expected, void (ProjectConverter3To4::*func)(String &, const RegExContainer &, bool), String what, const RegExContainer &reg_container, bool builtin_script) {
+ String got = name;
+ (this->*func)(got, reg_container, builtin_script);
+ if (expected != got) {
+ ERR_PRINT("Failed to convert " + what + " `" + name + "` to `" + expected + "`, got instead `" + got + "`");
+ return false;
+ }
+
+ return true;
+}
+
bool ProjectConverter3To4::test_conversion_single_normal(String name, String expected, const char *array[][2], String what) {
String got = name;
rename_common(array, got);
@@ -1937,7 +1980,7 @@ bool ProjectConverter3To4::test_conversion_single_normal(String name, String exp
}
// Validate if conversions are proper
-bool ProjectConverter3To4::test_conversion() {
+bool ProjectConverter3To4::test_conversion(const RegExContainer &reg_container) {
bool valid = true;
valid = valid & test_conversion_single_normal("Spatial", "Node3D", class_renames, "class");
@@ -1968,26 +2011,37 @@ bool ProjectConverter3To4::test_conversion() {
valid = valid & test_conversion_single_additional("(Disconnect(A,B,C) != OK):", "(Disconnect(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp");
valid = valid & test_conversion_single_additional("(IsConnected(A,B,C) != OK):", "(IsConnected(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename");
- valid = valid & test_conversion_single_additional("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\"display/window/size/fullscreen\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("[Remote]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp");
+ valid = valid & test_conversion_single_additional("[RemoteSync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp");
+ valid = valid & test_conversion_single_additional("[Sync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp");
+ valid = valid & test_conversion_single_additional("[Slave]", "[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp");
+ valid = valid & test_conversion_single_additional("[Puppet]", "[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp");
+ valid = valid & test_conversion_single_additional("[PuppetSync]", "[RPC(CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp");
+ valid = valid & test_conversion_single_additional("[Master]", "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp");
+ valid = valid & test_conversion_single_additional("[MasterSync]", "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n[RPC(CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp");
- valid = valid & test_conversion_single_additional("\tvar aa = roman(r.move_and_slide( a, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("\tvar aa = roman(r.move_and_slide_with_snap( a, g, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\t# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `g`\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional_builtin("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\"display/window/size/fullscreen\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\\\"display/window/size/fullscreen\\\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, true);
+ valid = valid & test_conversion_single_additional_builtin("OS.get_window_safe_area()", "DisplayServer.get_display_safe_area()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
- valid = valid & test_conversion_single_additional("list_dir_begin( a , b )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("list_dir_begin( a )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("list_dir_begin( )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional_builtin("\tvar aa = roman(r.move_and_slide( a, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("\tvar aa = roman(r.move_and_slide_with_snap( a, g, b, c, d, e, f )) # Roman", "\tr.set_motion_velocity(a)\n\t# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `g`\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tvar aa = roman(r.move_and_slide()) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
- valid = valid & test_conversion_single_additional("sort_custom( a , b )", "sort_custom(Callable(a,b))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional_builtin("list_dir_begin( a , b )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("list_dir_begin( a )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("list_dir_begin( )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
- valid = valid & test_conversion_single_additional("func c(var a, var b)", "func c(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional_builtin("sort_custom( a , b )", "sort_custom(Callable(a,b))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
- valid = valid & test_conversion_single_additional("draw_line(1, 2, 3, 4, 5)", "draw_line(1,2,3,4)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional_builtin("func c(var a, var b)", "func c(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
- valid = valid & test_conversion_single_additional("\timage.lock()", "\tfalse # image.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("\timage.unlock()", "\tfalse # image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("\troman.image.unlock()", "\tfalse # roman.image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("\tmtx.lock()", "\tmtx.lock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("\tmutex.unlock()", "\tmutex.unlock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional_builtin("draw_line(1, 2, 3, 4, 5)", "draw_line(1,2,3,4)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("\timage.lock()", "\tfalse # image.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("\timage.unlock()", "\tfalse # image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("\troman.image.unlock()", "\tfalse # roman.image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("\tmtx.lock()", "\tmtx.lock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("\tmutex.unlock()", "\tmutex.unlock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
valid = valid & test_conversion_single_additional("\nonready", "\n@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
valid = valid & test_conversion_single_additional("onready", "@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
@@ -2000,82 +2054,88 @@ bool ProjectConverter3To4::test_conversion() {
valid = valid & test_conversion_single_additional("tool", "@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
valid = valid & test_conversion_single_additional("\n tool", "\n tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
valid = valid & test_conversion_single_additional("\n\ntool", "\n\n@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
- valid = valid & test_conversion_single_additional("\n\nmaster func", "\n\n@rpc(any) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
- valid = valid & test_conversion_single_additional("\n\npuppet func", "\n\n@rpc(auth) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
- valid = valid & test_conversion_single_additional("\n\nremote func", "\n\n@rpc(any) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
- valid = valid & test_conversion_single_additional("\n\nremotesync func", "\n\n@rpc(any,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
- valid = valid & test_conversion_single_additional("\n\nsync func", "\n\n@rpc(any,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
- valid = valid & test_conversion_single_additional("\n\npuppetsync func", "\n\n@rpc(auth,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
- valid = valid & test_conversion_single_additional("\n\nmastersync func", "\n\n@rpc(any,sync) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
-
- valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function\n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function \n set(mod_value):\n mod_value # TODOConverter40 Non existent set function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("yield(this, \"timeout\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional(" Transform.xform(Vector3(a,b,c)) ", " Transform * Vector3(a,b,c) ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional(" Transform.xform_inv(Vector3(a,b,c)) ", " Vector3(a,b,c) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename"); // TODO, this is only a workaround
- valid = valid & test_conversion_single_additional("export(PackedScene) var mob_scene", "export var mob_scene: PackedScene", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("var d = parse_json(roman(sfs))", "var test_json_conv = JSON.new()\ntest_json_conv.parse(roman(sfs))\nvar d = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("to_json( AA ) szon", "JSON.new().stringify( AA ) szon", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("s to_json", "s JSON.new().stringify", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("AF to_json2", "AF to_json2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("var rr = JSON.parse(a)", "var test_json_conv = JSON.new()\ntest_json_conv.parse(a)\nvar rr = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("empty()", "is_empty()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional(".empty", ".empty", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional(").roman(", ").roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("\t.roman(", "\tsuper.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional(" .roman(", " super.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional(".1", ".1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional(" .1", " .1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("'.'", "'.'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("'.a'", "'.a'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("\t._input(_event)", "\tsuper._input(_event)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("(start(A,B,C,D,E,F,G) != OK):", "(start(A,Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("(connect(A,B,C,D,E,F,G) != OK):", "(connect(A,Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("(connect(A,B,C) != OK):", "(connect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("disconnect(A,B,C) != OK):", "disconnect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("is_connected(A,B,C) != OK):", "is_connected(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("is_connected(A,B,C))", "is_connected(A,Callable(B,C)))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("func _init(p_x:int)->void:", "func _init(p_x:int):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("q_PackedDataContainer._iter_init(variable1)", "q_PackedDataContainer._iter_init(variable1)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("assert(speed < 20, str(randi()%10))", "assert(speed < 20) #,str(randi()%10))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("assert(speed < 2)", "assert(speed < 2)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("assert(false, \"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", "assert(false) #,\"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("create_from_image(aa, bb)", "create_from_image(aa) #,bb", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("q_ImageTexture.create_from_image(variable1, variable2)", "q_ImageTexture.create_from_image(variable1) #,variable2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("set_cell_item(a, b, c, d ,e) # AA", "set_cell_item( Vector3(a,b,c) ,d,e) # AA", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("set_cell_item(a, b)", "set_cell_item(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("get_cell_item_orientation(a, b,c)", "get_cell_item_orientation(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("get_cell_item(a, b,c)", "get_cell_item(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("map_to_world(a, b,c)", "map_to_world(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("PackedStringArray(req_godot).join('.')", "'.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("=PackedStringArray(req_godot).join('.')", "='.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional(" aa", " aa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("\taa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("\t aa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional(" \taa", " \taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
-
- valid = valid & test_conversion_single_additional("apply_force(position, impulse)", "apply_force(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
- valid = valid & test_conversion_single_additional("apply_impulse(position, impulse)", "apply_impulse(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename");
+ valid = valid & test_conversion_single_additional("\n\nremote func", "\n\n@rpc(any_peer) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nremotesync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nsync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nslave func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\npuppet func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\npuppetsync func", "\n\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nmaster func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+ valid = valid & test_conversion_single_additional("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword");
+
+ valid = valid & test_conversion_single_additional_builtin("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function\n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function \n set(mod_value):\n mod_value # TODOConverter40 Non existent set function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("yield(this, \"timeout\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("yield(this, \"timeout\")", "await this.\"timeout\"", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, true);
+
+ valid = valid & test_conversion_single_additional_builtin(" Transform.xform(Vector3(a,b,c)) ", " Transform * Vector3(a,b,c) ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin(" Transform.xform_inv(Vector3(a,b,c)) ", " Vector3(a,b,c) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); // TODO, this is only a workaround
+ valid = valid & test_conversion_single_additional_builtin("export(PackedScene) var mob_scene", "export var mob_scene: PackedScene", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("var d = parse_json(roman(sfs))", "var test_json_conv = JSON.new()\ntest_json_conv.parse(roman(sfs))\nvar d = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("to_json( AA ) szon", "JSON.new().stringify( AA ) szon", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("s to_json", "s JSON.new().stringify", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("AF to_json2", "AF to_json2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("var rr = JSON.parse(a)", "var test_json_conv = JSON.new()\ntest_json_conv.parse(a)\nvar rr = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("empty()", "is_empty()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin(".empty", ".empty", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin(").roman(", ").roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("\t.roman(", "\tsuper.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin(" .roman(", " super.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin(".1", ".1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin(" .1", " .1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("'.'", "'.'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("'.a'", "'.a'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("\t._input(_event)", "\tsuper._input(_event)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("(connect(A,B,C) != OK):", "(connect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("(connect(A,B,C,D) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("(connect(A,B,C,[D]) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("(connect(A,B,C,D,E) != OK):", "(connect(A,Callable(B,C).bind(D),E) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("(start(A,B) != OK):", "(start(Callable(A,B)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("(start(A,B,C,D,E,F,G) != OK):", "(start(Callable(A,B).bind(C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("disconnect(A,B,C) != OK):", "disconnect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("is_connected(A,B,C) != OK):", "is_connected(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("is_connected(A,B,C))", "is_connected(A,Callable(B,C)))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("func _init(p_x:int)->void:", "func _init(p_x:int):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("q_PackedDataContainer._iter_init(variable1)", "q_PackedDataContainer._iter_init(variable1)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("assert(speed < 20, str(randi()%10))", "assert(speed < 20) #,str(randi()%10))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("assert(speed < 2)", "assert(speed < 2)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("assert(false, \"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", "assert(false) #,\"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("create_from_image(aa, bb)", "create_from_image(aa) #,bb", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("q_ImageTexture.create_from_image(variable1, variable2)", "q_ImageTexture.create_from_image(variable1) #,variable2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("set_cell_item(a, b, c, d ,e) # AA", "set_cell_item( Vector3(a,b,c) ,d,e) # AA", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("set_cell_item(a, b)", "set_cell_item(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("get_cell_item_orientation(a, b,c)", "get_cell_item_orientation(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("get_cell_item(a, b,c)", "get_cell_item(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("map_to_world(a, b,c)", "map_to_world(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("PackedStringArray(req_godot).join('.')", "'.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("=PackedStringArray(req_godot).join('.')", "='.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin(" aa", " aa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("\taa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("\t aa", "\taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin(" \taa", " \taa", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+
+ valid = valid & test_conversion_single_additional_builtin("apply_force(position, impulse)", "apply_force(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid & test_conversion_single_additional_builtin("apply_impulse(position, impulse)", "apply_impulse(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
valid = valid & test_conversion_single_additional("AAA Color.white AF", "AAA Color.WHITE AF", &ProjectConverter3To4::rename_enums, "custom rename");
@@ -2209,7 +2269,7 @@ bool ProjectConverter3To4::test_array_names() {
// Callable is special class, to which normal classes may be renamed
if (!ClassDB::class_exists(StringName(new_class)) && new_class != "Callable") {
- ERR_PRINT(String("Class `") + new_class + "` doesn't exists in Godot 4.0, so cannot be used in convertion.");
+ ERR_PRINT(String("Class `") + new_class + "` doesn't exists in Godot 4.0, so cannot be used in conversion.");
valid = false; // This probably should be only a warning, but not 100% sure - this would need to be added to CI
}
current_index++;
@@ -2295,7 +2355,7 @@ bool ProjectConverter3To4::test_array_names() {
}
// Validate in one array if names don't do cyclic renames `Node` -> `Node2D` | `Node2D` -> `2DNode`
-// Also checks if in name contains spaces at the end or beggining
+// Also checks if in name contains spaces at the end or beginning
bool ProjectConverter3To4::test_single_array(const char *array[][2], bool ignore_second_check) {
bool valid = true;
int current_index = 0;
@@ -2517,7 +2577,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_enums(Vector<String> &file
int current_line = 1;
for (String &line : file_content) {
- Array reg_match = reg.search_all(line);
+ TypedArray<RegExMatch> reg_match = reg.search_all(line);
if (reg_match.size() > 0) {
found_things.append(line_formatter(current_line, colors_renames[current_index][0], colors_renames[current_index][1], line));
}
@@ -2533,7 +2593,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_enums(Vector<String> &file
void ProjectConverter3To4::rename_classes(String &file_content) {
int current_index = 0;
- // TODO Maybe it is better way to not rename gd, tscn and other files which are named are classes
+ // TODO Maybe it is better way to not rename gd, tscn and other files which are named as classes
while (class_renames[current_index][0]) {
// Begin renaming workaround `Resource.gd` -> `RefCounter.gd`
RegEx reg_before = RegEx(String("\\b") + class_renames[current_index][0] + ".tscn\\b");
@@ -2594,7 +2654,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_classes(Vector<String> &fi
line = reg_before.sub(line, "TEMP_RENAMED_CLASS.tscn", true);
line = reg_before2.sub(line, "TEMP_RENAMED_CLASS.gd", true);
- Array reg_match = reg.search_all(line);
+ TypedArray<RegExMatch> reg_match = reg.search_all(line);
if (reg_match.size() > 0) {
found_things.append(line_formatter(current_line, class_renames[current_index][0], class_renames[current_index][1], line));
}
@@ -2623,432 +2683,11 @@ Vector<String> ProjectConverter3To4::check_for_rename_classes(Vector<String> &fi
return found_things;
}
-void ProjectConverter3To4::rename_gdscript_functions(String &file_content) {
- // Custom renaming, each rule needs to be set manually
- // Don't forget to put validate each rule in validate_conversion function
+void ProjectConverter3To4::rename_gdscript_functions(String &file_content, const RegExContainer &reg_container, bool builtin) {
Vector<String> lines = file_content.split("\n");
- RegEx reg_is_empty = RegEx("\\bempty\\(");
- RegEx reg_super = RegEx("([\t ])\\.([a-zA-Z_])");
- RegEx reg_json_to = RegEx("\\bto_json\\b");
- RegEx reg_json_parse = RegEx("([\t]{0,})([^\n]+)parse_json\\(([^\n]+)");
- RegEx reg_json_non_new = RegEx("([\t]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)");
- RegEx reg_export = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)");
- RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)");
- RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)");
- RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^a-z^A-Z^0-9^_]*$");
- RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$");
- RegEx reg_join = RegEx("([\\(\\)a-zA-Z0-9_]+)\\.join\\(([^\n^\\)]+)\\)");
- RegEx reg_mixed_tab_space = RegEx("([\t]+)([ ]+)");
- RegEx reg_image_lock = RegEx("([a-zA-Z0-9_\\.]+)\\.lock\\(\\)");
- RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)");
- RegEx reg_os_fullscreen = RegEx("OS.window_fullscreen[= ]+([^#^\n]+)");
-
- CRASH_COND(!reg_is_empty.is_valid());
- CRASH_COND(!reg_super.is_valid());
- CRASH_COND(!reg_json_to.is_valid());
- CRASH_COND(!reg_json_parse.is_valid());
- CRASH_COND(!reg_json_non_new.is_valid());
- CRASH_COND(!reg_export.is_valid());
- CRASH_COND(!reg_export_advanced.is_valid());
- CRASH_COND(!reg_setget_setget.is_valid());
- CRASH_COND(!reg_setget_set.is_valid());
- CRASH_COND(!reg_setget_get.is_valid());
- CRASH_COND(!reg_join.is_valid());
- CRASH_COND(!reg_mixed_tab_space.is_valid());
- CRASH_COND(!reg_image_lock.is_valid());
- CRASH_COND(!reg_image_unlock.is_valid());
- CRASH_COND(!reg_os_fullscreen.is_valid());
-
for (String &line : lines) {
- if (line.find("mtx") == -1 && line.find("mutex") == -1 && line.find("Mutex") == -1) {
- line = reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
- line = reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
- }
-
- // Mixed use of spaces and tabs - tabs as first - TODO, this probably is problem problem, but not sure
- line = reg_mixed_tab_space.sub(line, "$1", true);
-
- // PackedStringArray(req_godot).join('.') -> '.'.join(PackedStringArray(req_godot)) PoolStringArray
- line = reg_join.sub(line, "$2.join($1)", true);
-
- // -- empty() -> is_empty() Pool*Array
- line = reg_is_empty.sub(line, "is_empty(", true);
-
- // -- \t.func() -> \tsuper.func() Object
- line = reg_super.sub(line, "$1super.$2", true); // TODO, not sure if possible, but for now this brake String text e.g. "Choosen .gitignore" -> "Choosen super.gitignore"
-
- // -- JSON.parse(a) -> JSON.new().parse(a) etc. JSON
- line = reg_json_non_new.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
-
- // -- to_json(a) -> JSON.new().stringify(a) Object
- line = reg_json_to.sub(line, "JSON.new().stringify", true);
-
- // -- parse_json(a) -> JSON.get_data() etc. Object
- line = reg_json_parse.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
-
- // -- get_node(@ -> get_node( Node
- line = line.replace("get_node(@", "get_node(");
-
- // export(float) var lifetime = 3.0 -> export var lifetime: float = 3.0 GDScript
- line = reg_export.sub(line, "export var $2: $1");
-
- // export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro' -> export var _font_name = 'AnonymousPro' #(String, 'AnonymousPro', 'CourierPrime') GDScript
- line = reg_export_advanced.sub(line, "export var $2$3 # ($1)");
-
- // Setget Setget
- line = reg_setget_setget.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $4\n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
-
- // Setget set
- line = reg_setget_set.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Non existent get function \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
-
- // Setget get
- line = reg_setget_get.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $3 \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Non existent set function", true);
-
- // OS.window_fullscreen = true -> ProjectSettings.set("display/window/size/fullscreen",true)
- line = reg_os_fullscreen.sub(line, "ProjectSettings.set(\"display/window/size/fullscreen\", $1)", true);
-
- // -- r.move_and_slide( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
- if (line.find("move_and_slide(") != -1) {
- int start = line.find("move_and_slide(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- String base_obj = get_object_of_execution(line.substr(0, start));
- String starting_space = get_starting_space(line);
-
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 1) {
- String line_new;
-
- // motion_velocity
- line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
-
- // up_direction
- if (parts.size() >= 2) {
- line_new += starting_space + base_obj + "set_up_direction(" + parts[1] + ")\n";
- }
-
- // stop_on_slope
- if (parts.size() >= 3) {
- line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[2] + ")\n";
- }
-
- // max_slides
- if (parts.size() >= 4) {
- line_new += starting_space + base_obj + "set_max_slides(" + parts[3] + ")\n";
- }
-
- // floor_max_angle
- if (parts.size() >= 5) {
- line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[4] + ")\n";
- }
-
- // infiinite_interia
- if (parts.size() >= 6) {
- line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[5] + "`\n";
- }
-
- line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
- }
- }
- }
-
- // -- r.move_and_slide_with_snap( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
- if (line.find("move_and_slide_with_snap(") != -1) {
- int start = line.find("move_and_slide_with_snap(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- String base_obj = get_object_of_execution(line.substr(0, start));
- String starting_space = get_starting_space(line);
-
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 1) {
- String line_new;
-
- // motion_velocity
- line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
-
- // snap
- if (parts.size() >= 2) {
- line_new += starting_space + "# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `" + parts[1] + "`\n";
- }
-
- // up_direction
- if (parts.size() >= 3) {
- line_new += starting_space + base_obj + "set_up_direction(" + parts[2] + ")\n";
- }
-
- // stop_on_slope
- if (parts.size() >= 4) {
- line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[3] + ")\n";
- }
-
- // max_slides
- if (parts.size() >= 5) {
- line_new += starting_space + base_obj + "set_max_slides(" + parts[4] + ")\n";
- }
-
- // floor_max_angle
- if (parts.size() >= 6) {
- line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[5] + ")\n";
- }
-
- // infiinite_interia
- if (parts.size() >= 7) {
- line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[6] + "`\n";
- }
-
- line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
- }
- }
- }
-
- // -- sort_custom( a , b ) -> sort_custom(Callable( a , b )) Object
- if (line.find("sort_custom(") != -1) {
- int start = line.find("sort_custom(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start);
- }
- }
- }
-
- // -- list_dir_begin( ) -> list_dir_begin() Object
- if (line.find("list_dir_begin(") != -1) {
- int start = line.find("list_dir_begin(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- line = line.substr(0, start) + "list_dir_begin() " + line.substr(end + start) + "# TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547";
- }
- }
-
- // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem
- if (line.find("draw_line(") != -1) {
- int start = line.find("draw_line(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 5) {
- line = line.substr(0, start) + "draw_line(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start);
- }
- }
- }
-
- // -- func c(var a, var b) -> func c(a, b)
- if (line.find("func ") != -1 && line.find("var ") != -1) {
- int start = line.find("func ");
- start = line.substr(start).find("(") + start;
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
-
- String start_string = line.substr(0, start) + "(";
- for (int i = 0; i < parts.size(); i++) {
- start_string += parts[i].strip_edges().trim_prefix("var ");
- if (i != parts.size() - 1) {
- start_string += ", ";
- }
- }
- line = start_string + ")" + line.substr(end + start);
- }
- }
-
- // -- yield(this, \"timeout\") -> await this.timeout GDScript
- if (line.find("yield(") != -1) {
- int start = line.find("yield(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "await " + parts[0] + "." + parts[1].replace("\"", "").replace("\'", "").replace(" ", "") + line.substr(end + start);
- }
- }
- }
-
- // -- parse_json( AA ) -> TODO Object
- if (line.find("parse_json(") != -1) {
- int start = line.find("parse_json(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- line = line.substr(0, start) + "JSON.new().stringify(" + connect_arguments(parts, 0) + ")" + line.substr(end + start);
- }
- }
-
- // -- .xform(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform
- if (line.find(".xform(") != -1) {
- int start = line.find(".xform(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 1) {
- line = line.substr(0, start) + " * " + parts[0] + line.substr(end + start);
- }
- }
- }
-
- // -- .xform_inv(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform
- if (line.find(".xform_inv(") != -1) {
- int start = line.find(".xform_inv(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- String object_exec = get_object_of_execution(line.substr(0, start));
- if (line.find(object_exec + ".xform") != -1) {
- int start2 = line.find(object_exec + ".xform");
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 1) {
- line = line.substr(0, start2) + parts[0] + " * " + object_exec + line.substr(end + start);
- }
- }
- }
- }
-
- // -- connect(,,,things) -> connect(,Callable(,),things) Object
- if (line.find("connect(") != -1) {
- int start = line.find("connect(");
- // Protection from disconnect
- if (start == 0 || line.get(start - 1) != 's') {
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 3) {
- line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
- }
- }
- }
- }
- // -- disconnect(a,b,c) -> disconnect(a,Callable(b,c)) Object
- if (line.find("disconnect(") != -1) {
- int start = line.find("disconnect(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
- }
- }
- // -- is_connected(a,b,c) -> is_connected(a,Callable(b,c)) Object
- if (line.find("is_connected(") != -1) {
- int start = line.find("is_connected(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "is_connected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
- }
- }
- // -- start(a,b,c) -> start(a,Callable(b,c)) Thread
- if (line.find("start(") != -1) {
- int start = line.find("start(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 3) {
- line = line.substr(0, start) + "start(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
- }
- }
- }
- // -- func _init(p_x:int)->void: -> func _init(p_x:int): Object # https://github.com/godotengine/godot/issues/50589
- if (line.find(" _init(") != -1) {
- int start = line.find(" _init(");
- int end = line.rfind(":") + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- line = line.substr(0, start) + " _init(" + connect_arguments(parts, 0) + "):" + line.substr(end + start);
- }
- }
- // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message
- if (line.find("assert(") != -1) {
- int start = line.find("assert(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "assert(" + parts[0] + ") " + line.substr(end + start) + "#," + parts[1] + ")";
- }
- }
- }
- // create_from_image(aa, bb) -> create_from_image(aa) #, bb ImageTexture
- if (line.find("create_from_image(") != -1) {
- int start = line.find("create_from_image(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "create_from_image(" + parts[0] + ") " + "#," + parts[1] + line.substr(end + start);
- }
- }
- }
- // set_cell_item(a, b, c, d ,e) -> set_cell_item(Vector3(a, b, c), d ,e)
- if (line.find("set_cell_item(") != -1) {
- int start = line.find("set_cell_item(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() > 2) {
- line = line.substr(0, start) + "set_cell_item( Vector3(" + parts[0] + "," + parts[1] + "," + parts[2] + ") " + connect_arguments(parts, 3) + ")" + line.substr(end + start);
- }
- }
- }
- // get_cell_item(a, b, c) -> get_cell_item(Vector3i(a, b, c))
- if (line.find("get_cell_item(") != -1) {
- int start = line.find("get_cell_item(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
- }
- }
- // get_cell_item_orientation(a, b, c) -> get_cell_item_orientation(Vector3i(a, b, c))
- if (line.find("get_cell_item_orientation(") != -1) {
- int start = line.find("get_cell_item_orientation(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
- }
- }
- // apply_impulse(A, B) -> apply_impulse(B, A)
- if (line.find("apply_impulse(") != -1) {
- int start = line.find("apply_impulse(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "apply_impulse(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start);
- }
- }
- }
- // apply_force(A, B) -> apply_force(B, A)
- if (line.find("apply_force(") != -1) {
- int start = line.find("apply_force(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "apply_force(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start);
- }
- }
- }
- // map_to_world(a, b, c) -> map_to_world(Vector3i(a, b, c))
- if (line.find("map_to_world(") != -1) {
- int start = line.find("map_to_world(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "map_to_world(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
- }
- }
+ process_gdscript_line(line, reg_container, builtin);
}
// Collect vector to string
@@ -3062,478 +2701,484 @@ void ProjectConverter3To4::rename_gdscript_functions(String &file_content) {
}
};
-// This is almost 1:1 copy of function which rename gdscript functions
-Vector<String> ProjectConverter3To4::check_for_rename_gdscript_functions(Vector<String> &file_content) {
+Vector<String> ProjectConverter3To4::check_for_rename_gdscript_functions(Vector<String> &file_content, const RegExContainer &reg_container, bool builtin) {
int current_line = 1;
Vector<String> found_things;
- RegEx reg_is_empty = RegEx("\\bempty\\(");
- RegEx reg_super = RegEx("([\t ])\\.([a-zA-Z_])");
- RegEx reg_json_to = RegEx("\\bto_json\\b");
- RegEx reg_json_parse = RegEx("([\t]{0,})([^\n]+)parse_json\\(([^\n]+)");
- RegEx reg_json_non_new = RegEx("([\t]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)");
- RegEx reg_export = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)");
- RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)");
- RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)");
- RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^a-z^A-Z^0-9^_]*$");
- RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$");
- RegEx reg_join = RegEx("([\\(\\)a-zA-Z0-9_]+)\\.join\\(([^\n^\\)]+)\\)");
- RegEx reg_mixed_tab_space = RegEx("([\t]+)([ ]+)");
- RegEx reg_image_lock = RegEx("([a-zA-Z0-9_\\.]+)\\.lock\\(\\)");
- RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)");
- RegEx reg_os_fullscreen = RegEx("OS.window_fullscreen[= ]+([^#^\n]+)");
-
- CRASH_COND(!reg_is_empty.is_valid());
- CRASH_COND(!reg_super.is_valid());
- CRASH_COND(!reg_json_to.is_valid());
- CRASH_COND(!reg_json_parse.is_valid());
- CRASH_COND(!reg_json_non_new.is_valid());
- CRASH_COND(!reg_export.is_valid());
- CRASH_COND(!reg_export_advanced.is_valid());
- CRASH_COND(!reg_setget_setget.is_valid());
- CRASH_COND(!reg_setget_set.is_valid());
- CRASH_COND(!reg_setget_get.is_valid());
- CRASH_COND(!reg_join.is_valid());
- CRASH_COND(!reg_mixed_tab_space.is_valid());
- CRASH_COND(!reg_image_lock.is_valid());
- CRASH_COND(!reg_image_unlock.is_valid());
- CRASH_COND(!reg_os_fullscreen.is_valid());
-
for (String &line : file_content) {
String old_line = line;
-
- if (line.find("mtx") == -1 && line.find("mutex") == -1 && line.find("Mutex") == -1) {
- line = reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
- line = reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
+ process_gdscript_line(line, reg_container, builtin);
+ if (old_line != line) {
+ found_things.append(simple_line_formatter(current_line, old_line, line));
}
+ }
- // Mixed use of spaces and tabs - tabs as first - TODO, this probably is problem problem, but not sure
- line = reg_mixed_tab_space.sub(line, "$1", true);
+ return found_things;
+}
+void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContainer &reg_container, bool builtin) {
+ if (line.find("mtx") == -1 && line.find("mutex") == -1 && line.find("Mutex") == -1) {
+ line = reg_container.reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
+ line = reg_container.reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true);
+ }
- // PackedStringArray(req_godot).join('.') -> '.'.join(PackedStringArray(req_godot)) PoolStringArray
- line = reg_join.sub(line, "$2.join($1)", true);
+ // Mixed use of spaces and tabs - tabs as first - TODO, this probably is problem problem, but not sure
+ line = reg_container.reg_mixed_tab_space.sub(line, "$1", true);
- // -- empty() -> is_empty() Pool*Array
- line = reg_is_empty.sub(line, "is_empty(", true);
+ // PackedStringArray(req_godot).join('.') -> '.'.join(PackedStringArray(req_godot)) PoolStringArray
+ line = reg_container.reg_join.sub(line, "$2.join($1)", true);
- // -- \t.func() -> \tsuper.func() Object
- line = reg_super.sub(line, "$1super.$2", true); // TODO, not sure if possible, but for now this brake String text e.g. "Choosen .gitignore" -> "Choosen super.gitignore"
+ // -- empty() -> is_empty() Pool*Array
+ line = reg_container.reg_is_empty.sub(line, "is_empty(", true);
- // -- JSON.parse(a) -> JSON.new().parse(a) etc. JSON
- line = reg_json_non_new.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
+ // -- \t.func() -> \tsuper.func() Object
+ line = reg_container.reg_super.sub(line, "$1super.$2", true); // TODO, not sure if possible, but for now this brake String text e.g. "Choosen .gitignore" -> "Choosen super.gitignore"
- // -- to_json(a) -> JSON.new().stringify(a) Object
- line = reg_json_to.sub(line, "JSON.new().stringify", true);
+ // -- JSON.parse(a) -> JSON.new().parse(a) etc. JSON
+ line = reg_container.reg_json_non_new.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
- // -- parse_json(a) -> JSON.get_data() etc. Object
- line = reg_json_parse.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
+ // -- to_json(a) -> JSON.new().stringify(a) Object
+ line = reg_container.reg_json_to.sub(line, "JSON.new().stringify", true);
- // -- get_node(@ -> get_node( Node
- line = line.replace("get_node(@", "get_node(");
+ // -- parse_json(a) -> JSON.get_data() etc. Object
+ line = reg_container.reg_json_parse.sub(line, "$1var test_json_conv = JSON.new()\n$1test_json_conv.parse($3\n$1$2test_json_conv.get_data()", true);
- // export(float) var lifetime = 3.0 -> export var lifetime: float = 3.0 GDScript
- line = reg_export.sub(line, "export var $2: $1");
+ // -- get_node(@ -> get_node( Node
+ line = line.replace("get_node(@", "get_node(");
- // export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro' -> export var _font_name = 'AnonymousPro' #(String, 'AnonymousPro', 'CourierPrime') GDScript
- line = reg_export_advanced.sub(line, "export var $2$3 # ($1)");
+ // export(float) var lifetime = 3.0 -> export var lifetime: float = 3.0 GDScript
+ line = reg_container.reg_export.sub(line, "export var $2: $1");
- // Setget Setget
- line = reg_setget_setget.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $4\n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
+ // export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro' -> export var _font_name = 'AnonymousPro' #(String, 'AnonymousPro', 'CourierPrime') GDScript
+ line = reg_container.reg_export_advanced.sub(line, "export var $2$3 # ($1)");
- // Setget set
- line = reg_setget_set.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Non existent get function \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
+ // Setget Setget
+ line = reg_container.reg_setget_setget.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $4\n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
- // Setget get
- line = reg_setget_get.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $3 \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Non existent set function", true);
+ // Setget set
+ line = reg_container.reg_setget_set.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Non existent get function \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Copy here content of $3", true);
- // OS.window_fullscreen = true -> ProjectSettings.set("display/window/size/fullscreen",true)
- line = reg_os_fullscreen.sub(line, "ProjectSettings.set(\"display/window/size/fullscreen\", $1)", true);
+ // Setget get
+ line = reg_container.reg_setget_get.sub(line, "var $1$2:\n\tget:\n\t\treturn $1 # TODOConverter40 Copy here content of $3 \n\tset(mod_value):\n\t\tmod_value # TODOConverter40 Non existent set function", true);
- // -- r.move_and_slide( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
- if (line.find("move_and_slide(") != -1) {
- int start = line.find("move_and_slide(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- String base_obj = get_object_of_execution(line.substr(0, start));
- String starting_space = get_starting_space(line);
+ // OS.window_fullscreen = true -> ProjectSettings.set("display/window/size/fullscreen",true)
+ if (builtin) {
+ line = reg_container.reg_os_fullscreen.sub(line, "ProjectSettings.set(\\\"display/window/size/fullscreen\\\", $1)", true);
+ } else {
+ line = reg_container.reg_os_fullscreen.sub(line, "ProjectSettings.set(\"display/window/size/fullscreen\", $1)", true);
+ }
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 1) {
- String line_new;
+ // -- r.move_and_slide( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
+ if (line.find("move_and_slide(") != -1) {
+ int start = line.find("move_and_slide(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ String base_obj = get_object_of_execution(line.substr(0, start));
+ String starting_space = get_starting_space(line);
- // motion_velocity
- line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 1) {
+ String line_new;
- // up_direction
- if (parts.size() >= 2) {
- line_new += starting_space + base_obj + "set_up_direction(" + parts[1] + ")\n";
- }
+ // motion_velocity
+ line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
- // stop_on_slope
- if (parts.size() >= 3) {
- line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[2] + ")\n";
- }
+ // up_direction
+ if (parts.size() >= 2) {
+ line_new += starting_space + base_obj + "set_up_direction(" + parts[1] + ")\n";
+ }
- // max_slides
- if (parts.size() >= 4) {
- line_new += starting_space + base_obj + "set_max_slides(" + parts[3] + ")\n";
- }
+ // stop_on_slope
+ if (parts.size() >= 3) {
+ line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[2] + ")\n";
+ }
- // floor_max_angle
- if (parts.size() >= 5) {
- line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[4] + ")\n";
- }
+ // max_slides
+ if (parts.size() >= 4) {
+ line_new += starting_space + base_obj + "set_max_slides(" + parts[3] + ")\n";
+ }
- // infiinite_interia
- if (parts.size() >= 6) {
- line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[5] + "`\n";
- }
+ // floor_max_angle
+ if (parts.size() >= 5) {
+ line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[4] + ")\n";
+ }
- line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
+ // infiinite_interia
+ if (parts.size() >= 6) {
+ line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[5] + "`\n";
}
+
+ line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
}
}
+ }
- // -- r.move_and_slide_with_snap( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
- if (line.find("move_and_slide_with_snap(") != -1) {
- int start = line.find("move_and_slide_with_snap(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- String base_obj = get_object_of_execution(line.substr(0, start));
- String starting_space = get_starting_space(line);
-
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 1) {
- String line_new;
+ // -- r.move_and_slide_with_snap( a, b, c, d, e ) -> r.set_motion_velocity(a) ... r.move_and_slide() KinematicBody
+ if (line.find("move_and_slide_with_snap(") != -1) {
+ int start = line.find("move_and_slide_with_snap(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ String base_obj = get_object_of_execution(line.substr(0, start));
+ String starting_space = get_starting_space(line);
- // motion_velocity
- line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() >= 1) {
+ String line_new;
- // snap
- if (parts.size() >= 2) {
- line_new += starting_space + "# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `" + parts[1] + "`\n";
- }
+ // motion_velocity
+ line_new += starting_space + base_obj + "set_motion_velocity(" + parts[0] + ")\n";
- // up_direction
- if (parts.size() >= 3) {
- line_new += starting_space + base_obj + "set_up_direction(" + parts[2] + ")\n";
- }
+ // snap
+ if (parts.size() >= 2) {
+ line_new += starting_space + "# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `" + parts[1] + "`\n";
+ }
- // stop_on_slope
- if (parts.size() >= 4) {
- line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[3] + ")\n";
- }
+ // up_direction
+ if (parts.size() >= 3) {
+ line_new += starting_space + base_obj + "set_up_direction(" + parts[2] + ")\n";
+ }
- // max_slides
- if (parts.size() >= 5) {
- line_new += starting_space + base_obj + "set_max_slides(" + parts[4] + ")\n";
- }
+ // stop_on_slope
+ if (parts.size() >= 4) {
+ line_new += starting_space + base_obj + "set_floor_stop_on_slope_enabled(" + parts[3] + ")\n";
+ }
- // floor_max_angle
- if (parts.size() >= 6) {
- line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[5] + ")\n";
- }
+ // max_slides
+ if (parts.size() >= 5) {
+ line_new += starting_space + base_obj + "set_max_slides(" + parts[4] + ")\n";
+ }
- // infiinite_interia
- if (parts.size() >= 7) {
- line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[6] + "`\n";
- }
+ // floor_max_angle
+ if (parts.size() >= 6) {
+ line_new += starting_space + base_obj + "set_floor_max_angle(" + parts[5] + ")\n";
+ }
- line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
+ // infiinite_interia
+ if (parts.size() >= 7) {
+ line_new += starting_space + "# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `" + parts[6] + "`\n";
}
+
+ line = line_new + line.substr(0, start) + "move_and_slide()" + line.substr(end + start);
}
}
+ }
- // -- sort_custom( a , b ) -> sort_custom(Callable( a , b )) Object
- if (line.find("sort_custom(") != -1) {
- int start = line.find("sort_custom(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start);
- }
+ // -- sort_custom( a , b ) -> sort_custom(Callable( a , b )) Object
+ if (line.find("sort_custom(") != -1) {
+ int start = line.find("sort_custom(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start);
}
}
+ }
- // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem
- if (line.find("draw_line(") != -1) {
- int start = line.find("draw_line(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 5) {
- line = line.substr(0, start) + "draw_line(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start);
- }
- }
+ // -- list_dir_begin( ) -> list_dir_begin() Object
+ if (line.find("list_dir_begin(") != -1) {
+ int start = line.find("list_dir_begin(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ line = line.substr(0, start) + "list_dir_begin() " + line.substr(end + start) + "# TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547";
}
+ }
- // -- func c(var a, var b) -> func c(a, b)
- if (line.find("func ") != -1 && line.find("var ") != -1) {
- int start = line.find("func ");
- start = line.substr(start).find("(") + start;
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
+ // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem
+ if (line.find("draw_line(") != -1) {
+ int start = line.find("draw_line(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 5) {
+ line = line.substr(0, start) + "draw_line(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start);
+ }
+ }
+ }
- String start_string = line.substr(0, start) + "(";
- for (int i = 0; i < parts.size(); i++) {
- start_string += parts[i].strip_edges().trim_prefix("var ");
- if (i != parts.size() - 1) {
- start_string += ", ";
- }
+ // -- func c(var a, var b) -> func c(a, b)
+ if (line.find("func ") != -1 && line.find("var ") != -1) {
+ int start = line.find("func ");
+ start = line.substr(start).find("(") + start;
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+
+ String start_string = line.substr(0, start) + "(";
+ for (int i = 0; i < parts.size(); i++) {
+ start_string += parts[i].strip_edges().trim_prefix("var ");
+ if (i != parts.size() - 1) {
+ start_string += ", ";
}
- line = start_string + ")" + line.substr(end + start);
}
+ line = start_string + ")" + line.substr(end + start);
}
+ }
- // -- yield(this, \"timeout\") -> await this.timeout GDScript
- if (line.find("yield(") != -1) {
- int start = line.find("yield(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
+ // -- yield(this, \"timeout\") -> await this.timeout GDScript
+ if (line.find("yield(") != -1) {
+ int start = line.find("yield(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ if (builtin) {
+ line = line.substr(0, start) + "await " + parts[0] + "." + parts[1].replace(" ", "") + line.substr(end + start);
+ } else {
line = line.substr(0, start) + "await " + parts[0] + "." + parts[1].replace("\"", "").replace("\'", "").replace(" ", "") + line.substr(end + start);
}
}
}
+ }
- // -- parse_json( AA ) -> TODO Object
- if (line.find("parse_json(") != -1) {
- int start = line.find("parse_json(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- line = line.substr(0, start) + "JSON.new().stringify(" + connect_arguments(parts, 0) + ")" + line.substr(end + start);
- }
+ // -- parse_json( AA ) -> TODO Object
+ if (line.find("parse_json(") != -1) {
+ int start = line.find("parse_json(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ line = line.substr(0, start) + "JSON.new().stringify(" + connect_arguments(parts, 0) + ")" + line.substr(end + start);
}
+ }
- // -- .xform(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform
- if (line.find(".xform(") != -1) {
- int start = line.find(".xform(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 1) {
- line = line.substr(0, start) + " * " + parts[0] + line.substr(end + start);
- }
+ // -- .xform(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform
+ if (line.find(".xform(") != -1) {
+ int start = line.find(".xform(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 1) {
+ line = line.substr(0, start) + " * " + parts[0] + line.substr(end + start);
}
}
+ }
- // -- .xform_inv(Vector3(a,b,c)) -> / Vector3(a,b,c) Transform
- if (line.find(".xform_inv(") != -1) {
- int start = line.find(".xform_inv(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
+ // -- .xform_inv(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform
+ if (line.find(".xform_inv(") != -1) {
+ int start = line.find(".xform_inv(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ String object_exec = get_object_of_execution(line.substr(0, start));
+ if (line.find(object_exec + ".xform") != -1) {
+ int start2 = line.find(object_exec + ".xform");
Vector<String> parts = parse_arguments(line.substr(start, end));
if (parts.size() == 1) {
- line = line.substr(0, start) + " / " + parts[0] + line.substr(end + start);
+ line = line.substr(0, start2) + parts[0] + " * " + object_exec + line.substr(end + start);
}
}
}
+ }
- // -- connect(,,,things) -> connect(,Callable(,),things) Object
- if (line.find("connect(") != -1) {
- int start = line.find("connect(");
- // Protection from disconnect
- if (start == 0 || line.get(start - 1) != 's') {
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 3) {
- line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
- }
- }
- }
- }
- // -- disconnect(a,b,c) -> disconnect(a,Callable(b,c)) Object
- if (line.find("disconnect(") != -1) {
- int start = line.find("disconnect(");
+ // -- "(connect(A,B,C,D,E) != OK):", "(connect(A,Callable(B,C).bind(D),E) Object
+ if (line.find("connect(") != -1) {
+ int start = line.find("connect(");
+ // Protection from disconnect
+ if (start == 0 || line.get(start - 1) != 's') {
int end = get_end_parenthess(line.substr(start)) + 1;
if (end > -1) {
Vector<String> parts = parse_arguments(line.substr(start, end));
if (parts.size() == 3) {
- line = line.substr(0, start) + "disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ } else if (parts.size() >= 4) {
+ line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ").bind(" + parts[3].lstrip("[").rstrip("]") + ")" + connect_arguments(parts, 4) + ")" + line.substr(end + start);
}
}
}
- // -- is_connected(a,b,c) -> is_connected(a,Callable(b,c)) Object
- if (line.find("is_connected(") != -1) {
- int start = line.find("is_connected(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "is_connected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
+ }
+ // -- disconnect(a,b,c) -> disconnect(a,Callable(b,c)) Object
+ if (line.find("disconnect(") != -1) {
+ int start = line.find("disconnect(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
}
}
- // -- start(a,b,c) -> start(a,Callable(b,c)) Thread
- if (line.find("start(") != -1) {
- int start = line.find("start(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 3) {
- line = line.substr(0, start) + "start(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
- }
+ }
+ // -- is_connected(a,b,c) -> is_connected(a,Callable(b,c)) Object
+ if (line.find("is_connected(") != -1) {
+ int start = line.find("is_connected(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "is_connected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
}
}
- // -- func _init(p_x:int)->void: -> func _init(p_x:int): Object # https://github.com/godotengine/godot/issues/50589
- if (line.find(" _init(") != -1) {
- int start = line.find(" _init(");
- int end = line.rfind(":") + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- line = line.substr(0, start) + " _init(" + connect_arguments(parts, 0) + "):" + line.substr(end + start);
+ }
+ // -- start(a,b) -> start(Callable(a,b)) Thread
+ // -- start(a,b,c,d) -> start(Callable(a,b).bind(c),d) Thread
+ if (line.find("start(") != -1) {
+ int start = line.find("start(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "start(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start);
+ } else if (parts.size() >= 3) {
+ line = line.substr(0, start) + "start(Callable(" + parts[0] + "," + parts[1] + ").bind(" + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
}
}
- // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message
- if (line.find("assert(") != -1) {
- int start = line.find("assert(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "assert(" + parts[0] + ") " + line.substr(end + start) + "#," + parts[1] + ")";
- }
+ }
+ // -- func _init(p_x:int)->void: -> func _init(p_x:int): Object # https://github.com/godotengine/godot/issues/50589
+ if (line.find(" _init(") != -1) {
+ int start = line.find(" _init(");
+ int end = line.rfind(":") + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ line = line.substr(0, start) + " _init(" + connect_arguments(parts, 0) + "):" + line.substr(end + start);
+ }
+ }
+ // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message
+ if (line.find("assert(") != -1) {
+ int start = line.find("assert(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "assert(" + parts[0] + ") " + line.substr(end + start) + "#," + parts[1] + ")";
}
}
- // create_from_image(aa, bb) -> create_from_image(aa) #, bb ImageTexture
- if (line.find("create_from_image(") != -1) {
- int start = line.find("create_from_image(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "create_from_image(" + parts[0] + ") " + "#," + parts[1] + line.substr(end + start);
- }
+ }
+ // create_from_image(aa, bb) -> create_from_image(aa) #, bb ImageTexture
+ if (line.find("create_from_image(") != -1) {
+ int start = line.find("create_from_image(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "create_from_image(" + parts[0] + ") " + "#," + parts[1] + line.substr(end + start);
}
}
- // set_cell_item(a, b, c, d ,e) -> set_cell_item(Vector3(a, b, c), d ,e)
- if (line.find("set_cell_item(") != -1) {
- int start = line.find("set_cell_item(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() > 2) {
- line = line.substr(0, start) + "set_cell_item( Vector3(" + parts[0] + "," + parts[1] + "," + parts[2] + ") " + connect_arguments(parts, 3) + ")" + line.substr(end + start);
- }
+ }
+ // set_cell_item(a, b, c, d ,e) -> set_cell_item(Vector3(a, b, c), d ,e)
+ if (line.find("set_cell_item(") != -1) {
+ int start = line.find("set_cell_item(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() > 2) {
+ line = line.substr(0, start) + "set_cell_item( Vector3(" + parts[0] + "," + parts[1] + "," + parts[2] + ") " + connect_arguments(parts, 3) + ")" + line.substr(end + start);
}
}
- // get_cell_item(a, b, c) -> get_cell_item(Vector3i(a, b, c))
- if (line.find("get_cell_item(") != -1) {
- int start = line.find("get_cell_item(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
+ }
+ // get_cell_item(a, b, c) -> get_cell_item(Vector3i(a, b, c))
+ if (line.find("get_cell_item(") != -1) {
+ int start = line.find("get_cell_item(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
}
}
- // get_cell_item_orientation(a, b, c) -> get_cell_item_orientation(Vector3i(a, b, c))
- if (line.find("get_cell_item_orientation(") != -1) {
- int start = line.find("get_cell_item_orientation(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
+ }
+ // get_cell_item_orientation(a, b, c) -> get_cell_item_orientation(Vector3i(a, b, c))
+ if (line.find("get_cell_item_orientation(") != -1) {
+ int start = line.find("get_cell_item_orientation(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
}
}
-
- // apply_impulse(A, B) -> apply_impulse(B, A)
- if (line.find("apply_impulse(") != -1) {
- int start = line.find("apply_impulse(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "apply_impulse(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start);
- }
+ }
+ // apply_impulse(A, B) -> apply_impulse(B, A)
+ if (line.find("apply_impulse(") != -1) {
+ int start = line.find("apply_impulse(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "apply_impulse(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start);
}
}
- // apply_force(A, B) -> apply_force(B, A)
- if (line.find("apply_force(") != -1) {
- int start = line.find("apply_force(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 2) {
- line = line.substr(0, start) + "apply_force(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start);
- }
+ }
+ // apply_force(A, B) -> apply_force(B, A)
+ if (line.find("apply_force(") != -1) {
+ int start = line.find("apply_force(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 2) {
+ line = line.substr(0, start) + "apply_force(" + parts[1] + ", " + parts[0] + ")" + line.substr(end + start);
}
}
- // map_to_world(a, b, c) -> map_to_world(Vector3i(a, b, c))
- if (line.find("map_to_world(") != -1) {
- int start = line.find("get_cell_item_orientation(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "map_to_world(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
+ }
+ // map_to_world(a, b, c) -> map_to_world(Vector3i(a, b, c))
+ if (line.find("map_to_world(") != -1) {
+ int start = line.find("map_to_world(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "map_to_world(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
}
}
-
- if (old_line != line) {
- found_things.append(simple_line_formatter(current_line, old_line, line));
+ }
+ // OS.get_window_safe_area() -> DisplayServer.get_display_safe_area()
+ if (line.find("OS.get_window_safe_area(") != -1) {
+ int start = line.find("OS.get_window_safe_area(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 0) {
+ line = line.substr(0, start) + "DisplayServer.get_display_safe_area()" + line.substr(end + start);
+ }
}
}
-
- return found_things;
}
-void ProjectConverter3To4::rename_csharp_functions(String &file_content) {
- // Custom renaming, each rule needs to be set manually
- // Don't forget to put validate each rule in validate_conversion function
- Vector<String> lines = file_content.split("\n");
+void ProjectConverter3To4::process_csharp_line(String &line) {
+ // TODO maybe this can be changed to normal rule
+ line = line.replace("OS.GetWindowSafeArea()", "DisplayServer.ScreenGetUsableRect()");
- for (String &line : lines) {
- // TODO maybe this can be changed to normal rule
- line = line.replace("OS.GetWindowSafeArea()", "DisplayServer.ScreenGetUsableRect()");
-
- // -- Connect(,,,things) -> Connect(,Callable(,),things) Object
- if (line.find("Connect(") != -1) {
- int start = line.find("Connect(");
- // Protection from disconnect
- if (start == 0 || line.get(start - 1) != 's') {
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 3) {
- line = line.substr(0, start) + "Connect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
- }
- }
- }
- }
- // -- Disconnect(a,b,c) -> Disconnect(a,Callable(b,c)) Object
- if (line.find("Disconnect(") != -1) {
- int start = line.find("Disconnect(");
+ // -- Connect(,,,things) -> Connect(,Callable(,),things) Object
+ if (line.find("Connect(") != -1) {
+ int start = line.find("Connect(");
+ // Protection from disconnect
+ if (start == 0 || line.get(start - 1) != 's') {
int end = get_end_parenthess(line.substr(start)) + 1;
if (end > -1) {
Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "Disconnect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ if (parts.size() >= 3) {
+ line = line.substr(0, start) + "Connect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
}
}
}
- // -- IsConnected(a,b,c) -> IsConnected(a,Callable(b,c)) Object
- if (line.find("IsConnected(") != -1) {
- int start = line.find("IsConnected(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "IsConnected(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
+ }
+ // -- Disconnect(a,b,c) -> Disconnect(a,Callable(b,c)) Object
+ if (line.find("Disconnect(") != -1) {
+ int start = line.find("Disconnect(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "Disconnect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
}
}
}
+ // -- IsConnected(a,b,c) -> IsConnected(a,Callable(b,c)) Object
+ if (line.find("IsConnected(") != -1) {
+ int start = line.find("IsConnected(");
+ int end = get_end_parenthess(line.substr(start)) + 1;
+ if (end > -1) {
+ Vector<String> parts = parse_arguments(line.substr(start, end));
+ if (parts.size() == 3) {
+ line = line.substr(0, start) + "IsConnected(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
+ }
+ }
+ }
+}
+
+void ProjectConverter3To4::rename_csharp_functions(String &file_content) {
+ Vector<String> lines = file_content.split("\n");
+
+ for (String &line : lines) {
+ process_csharp_line(line);
+ }
// Collect vector to string
file_content = "";
@@ -3554,47 +3199,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_csharp_functions(Vector<St
for (String &line : file_content) {
String old_line = line;
-
- // TODO maybe this can be changed to normal rule
- line = line.replace("OS.GetWindowSafeArea()", "DisplayServer.ScreenGetUsableRect()");
-
- // -- Connect(,,,things) -> connect(,Callable(,),things) Object
- if (line.find("Connect(") != -1) {
- int start = line.find("Connect(");
- // Protection from disconnect
- if (start == 0 || line.get(start - 1) != 's') {
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() >= 3) {
- line = line.substr(0, start) + "Connect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start);
- }
- }
- }
- }
- // -- Disconnect(a,b,c) -> Disconnect(a,Callable(b,c)) Object
- if (line.find("Disconnect(") != -1) {
- int start = line.find("Disconnect(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "Disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
- }
- }
- // -- IsConnected(a,b,c) -> IsConnected(a,Callable(b,c)) Object
- if (line.find("IsConnected(") != -1) {
- int start = line.find("IsConnected(");
- int end = get_end_parenthess(line.substr(start)) + 1;
- if (end > -1) {
- Vector<String> parts = parse_arguments(line.substr(start, end));
- if (parts.size() == 3) {
- line = line.substr(0, start) + "IsConnected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start);
- }
- }
- }
-
+ process_csharp_line(line);
if (old_line != line) {
found_things.append(simple_line_formatter(current_line, old_line, line));
}
@@ -3603,88 +3208,205 @@ Vector<String> ProjectConverter3To4::check_for_rename_csharp_functions(Vector<St
return found_things;
}
-void ProjectConverter3To4::rename_gdscript_keywords(String &file_content){
- { RegEx reg_tool = RegEx("([\n]+)tool");
-CRASH_COND(!reg_tool.is_valid());
-file_content = reg_tool.sub(file_content, "$1@tool", true);
-RegEx reg_tool2 = RegEx("^tool");
-CRASH_COND(!reg_tool2.is_valid());
-file_content = reg_tool2.sub(file_content, "@tool", true);
-}
-{
- RegEx reg_export = RegEx("([\n\t]+)export\\b");
- CRASH_COND(!reg_export.is_valid());
- file_content = reg_export.sub(file_content, "$1@export", true);
- RegEx reg_export2 = RegEx("^export");
- CRASH_COND(!reg_export2.is_valid());
- file_content = reg_export2.sub(file_content, "@export", true);
-}
-{
- RegEx reg_onready = RegEx("([\n]+)onready");
- CRASH_COND(!reg_onready.is_valid());
- file_content = reg_onready.sub(file_content, "$1@onready", true);
- RegEx reg_onready2 = RegEx("^onready");
- CRASH_COND(!reg_onready2.is_valid());
- file_content = reg_onready2.sub(file_content, "@onready", true);
-}
-{
- RegEx reg_master = RegEx("([\n]+)master func");
- CRASH_COND(!reg_master.is_valid());
- file_content = reg_master.sub(file_content, "$1@rpc(any) func", true);
- RegEx reg_master2 = RegEx("^master func");
- CRASH_COND(!reg_master2.is_valid());
- file_content = reg_master2.sub(file_content, "@rpc(any) func", true);
-}
-{
- RegEx reg_puppet = RegEx("([\n]+)puppet func");
- CRASH_COND(!reg_puppet.is_valid());
- file_content = reg_puppet.sub(file_content, "$1@rpc(auth) func", true);
- RegEx reg_puppet2 = RegEx("^puppet func");
- CRASH_COND(!reg_puppet2.is_valid());
- file_content = reg_puppet2.sub(file_content, "@rpc(auth) func", true);
-}
-{
- RegEx reg_remote = RegEx("([\n]+)remote func");
- CRASH_COND(!reg_remote.is_valid());
- file_content = reg_remote.sub(file_content, "$1@rpc(any) func", true);
- RegEx reg_remote2 = RegEx("^remote func");
- CRASH_COND(!reg_remote2.is_valid());
- file_content = reg_remote2.sub(file_content, "@rpc(any) func", true);
-}
-{
- RegEx reg_remotesync = RegEx("([\n]+)remotesync func");
- CRASH_COND(!reg_remotesync.is_valid());
- file_content = reg_remotesync.sub(file_content, "$1@rpc(any,sync) func", true);
- RegEx reg_remotesync2 = RegEx("^remotesync func");
- CRASH_COND(!reg_remotesync2.is_valid());
- file_content = reg_remotesync2.sub(file_content, "@rpc(any,sync) func", true);
-}
-{
- RegEx reg_sync = RegEx("([\n]+)sync func");
- CRASH_COND(!reg_sync.is_valid());
- file_content = reg_sync.sub(file_content, "$1@rpc(any,sync) func", true);
- RegEx reg_sync2 = RegEx("^sync func");
- CRASH_COND(!reg_sync2.is_valid());
- file_content = reg_sync2.sub(file_content, "@rpc(any,sync) func", true);
-}
-{
- RegEx reg_puppetsync = RegEx("([\n]+)puppetsync func");
- CRASH_COND(!reg_puppetsync.is_valid());
- file_content = reg_puppetsync.sub(file_content, "$1@rpc(auth,sync) func", true);
- RegEx reg_puppetsync2 = RegEx("^puppetsync func");
- CRASH_COND(!reg_puppetsync2.is_valid());
- file_content = reg_puppetsync2.sub(file_content, "@rpc(auth,sync) func", true);
+void ProjectConverter3To4::rename_csharp_attributes(String &file_content) {
+ // -- [Remote] -> [RPC(MultiplayerAPI.RPCMode.AnyPeer)]
+ {
+ RegEx reg_remote = RegEx("\\[Remote(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!reg_remote.is_valid());
+ file_content = reg_remote.sub(file_content, "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", true);
+ }
+ // -- [RemoteSync] -> [RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]
+ {
+ RegEx reg_remotesync = RegEx("\\[(Remote)?Sync(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!reg_remotesync.is_valid());
+ file_content = reg_remotesync.sub(file_content, "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", true);
+ }
+ // -- [Puppet] -> [RPC]
+ {
+ RegEx reg_puppet = RegEx("\\[(Puppet|Slave)(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!reg_puppet.is_valid());
+ file_content = reg_puppet.sub(file_content, "[RPC]", true);
+ }
+ // -- [PuppetSync] -> [RPC(CallLocal = true)]
+ {
+ RegEx reg_puppetsync = RegEx("\\[PuppetSync(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!reg_puppetsync.is_valid());
+ file_content = reg_puppetsync.sub(file_content, "[RPC(CallLocal = true)]", true);
+ }
+ String error_message = "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n";
+ // -- [Master] -> [RPC]
+ {
+ RegEx reg_remote = RegEx("\\[Master(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!reg_remote.is_valid());
+ file_content = reg_remote.sub(file_content, error_message + "[RPC]", true);
+ }
+ // -- [MasterSync] -> [RPC(CallLocal = true)]
+ {
+ RegEx reg_remote = RegEx("\\[MasterSync(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!reg_remote.is_valid());
+ file_content = reg_remote.sub(file_content, error_message + "[RPC(CallLocal = true)]", true);
+ }
}
-{
- RegEx reg_mastersync = RegEx("([\n]+)mastersync func");
- CRASH_COND(!reg_mastersync.is_valid());
- file_content = reg_mastersync.sub(file_content, "$1@rpc(any,sync) func", true);
- RegEx reg_mastersync2 = RegEx("^mastersync func");
- CRASH_COND(!reg_mastersync2.is_valid());
- file_content = reg_mastersync2.sub(file_content, "@rpc(any,sync) func", true);
+
+Vector<String> ProjectConverter3To4::check_for_rename_csharp_attributes(Vector<String> &file_content) {
+ int current_line = 1;
+
+ Vector<String> found_things;
+
+ for (String &line : file_content) {
+ String old;
+ old = line;
+ {
+ RegEx regex = RegEx("\\[Remote(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "[Remote]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", line));
+ }
+ old = line;
+ {
+ RegEx regex = RegEx("\\[(Remote)?Sync(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "[RemoteSync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", line));
+ }
+ old = line;
+ {
+ RegEx regex = RegEx("\\[Puppet(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "[RPC]", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "[Puppet]", "[RPC]", line));
+ }
+ old = line;
+ {
+ RegEx regex = RegEx("\\[(Puppet|Slave)Sync(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "[RPC(CallLocal = true)]", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "[PuppetSync]", "[RPC(CallLocal = true)]", line));
+ }
+ old = line;
+ {
+ RegEx regex = RegEx("\\[Master(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "[RPC]", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "[Master]", "[RPC]", line));
+ }
+ old = line;
+ {
+ RegEx regex = RegEx("\\[MasterSync(Attribute)?(\\(\\))?\\]");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "[RPC(CallLocal = true)]", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "[MasterSync]", "[RPC(CallLocal = true)]", line));
+ }
+
+ current_line++;
+ }
+
+ return found_things;
}
+
+void ProjectConverter3To4::rename_gdscript_keywords(String &file_content) {
+ {
+ RegEx reg_first = RegEx("([\n]+)tool");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1@tool", true);
+ RegEx reg_second = RegEx("^tool");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, "@tool", true);
+ }
+ {
+ RegEx reg_first = RegEx("([\n\t]+)export\\b");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1@export", true);
+ RegEx reg_second = RegEx("^export");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, "@export", true);
+ }
+ {
+ RegEx reg_first = RegEx("([\n]+)onready");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1@onready", true);
+ RegEx reg_second = RegEx("^onready");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, "@onready", true);
+ }
+ {
+ RegEx reg_first = RegEx("([\n]+)remote func");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1@rpc(any_peer) func", true);
+ RegEx reg_second = RegEx("^remote func");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, "@rpc(any_peer) func", true);
+ }
+ {
+ RegEx reg_first = RegEx("([\n]+)remotesync func");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1@rpc(any_peer, call_local) func", true);
+ RegEx reg_second = RegEx("^remotesync func");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, "@rpc(any_peer, call_local) func", true);
+ }
+ {
+ RegEx reg_first = RegEx("([\n]+)sync func");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1@rpc(any_peer, call_local) func", true);
+ RegEx reg_second = RegEx("^sync func");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, "@rpc(any_peer, call_local) func", true);
+ }
+ {
+ RegEx reg_first = RegEx("([\n]+)slave func");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1@rpc func", true);
+ RegEx reg_second = RegEx("^slave func");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, "@rpc func", true);
+ }
+ {
+ RegEx reg_first = RegEx("([\n]+)puppet func");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1@rpc func", true);
+ RegEx reg_second = RegEx("^puppet func");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, "@rpc func", true);
+ }
+ {
+ RegEx reg_first = RegEx("([\n]+)puppetsync func");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1@rpc(call_local) func", true);
+ RegEx reg_second = RegEx("^puppetsync func");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, "@rpc(call_local) func", true);
+ }
+ String error_message = "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n";
+ {
+ RegEx reg_first = RegEx("([\n]+)master func");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1" + error_message + "@rpc func", true);
+ RegEx reg_second = RegEx("^master func");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, error_message + "@rpc func", true);
+ }
+ {
+ RegEx reg_first = RegEx("([\n]+)mastersync func");
+ CRASH_COND(!reg_first.is_valid());
+ file_content = reg_first.sub(file_content, "$1" + error_message + "@rpc(call_local) func", true);
+ RegEx reg_second = RegEx("^mastersync func");
+ CRASH_COND(!reg_second.is_valid());
+ file_content = reg_second.sub(file_content, error_message + "@rpc(call_local) func", true);
+ }
}
-;
Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<String> &file_content) {
Vector<String> found_things;
@@ -3695,96 +3417,105 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S
String old;
old = line;
{
- RegEx reg_tool2 = RegEx("^tool");
- CRASH_COND(!reg_tool2.is_valid());
- line = reg_tool2.sub(line, "@tool", true);
+ RegEx reg_first = RegEx("^tool");
+ CRASH_COND(!reg_first.is_valid());
+ line = reg_first.sub(line, "@tool", true);
}
if (old != line) {
found_things.append(line_formatter(current_line, "tool", "@tool", line));
}
old = line;
{
- RegEx reg_export = RegEx("([\t]+)export\\b");
- CRASH_COND(!reg_export.is_valid());
- line = reg_export.sub(line, "$1@export", true);
- RegEx reg_export2 = RegEx("^export");
- CRASH_COND(!reg_export2.is_valid());
- line = reg_export2.sub(line, "@export", true);
+ RegEx reg_first = RegEx("([\t]+)export\\b");
+ CRASH_COND(!reg_first.is_valid());
+ line = reg_first.sub(line, "$1@export", true);
+ RegEx reg_second = RegEx("^export");
+ CRASH_COND(!reg_second.is_valid());
+ line = reg_second.sub(line, "@export", true);
}
if (old != line) {
found_things.append(line_formatter(current_line, "export", "@export", line));
}
old = line;
{
- RegEx reg_onready2 = RegEx("^onready");
- CRASH_COND(!reg_onready2.is_valid());
- line = reg_onready2.sub(line, "@onready", true);
+ RegEx reg_first = RegEx("^onready");
+ CRASH_COND(!reg_first.is_valid());
+ line = reg_first.sub(line, "@onready", true);
}
if (old != line) {
found_things.append(line_formatter(current_line, "onready", "@onready", line));
}
old = line;
{
- RegEx reg_master2 = RegEx("^master func");
- CRASH_COND(!reg_master2.is_valid());
- line = reg_master2.sub(line, "@rpc(any) func", true);
+ RegEx regex = RegEx("^remote func");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "@rpc(any_peer) func", true);
+ }
+ if (old != line) {
+ found_things.append(line_formatter(current_line, "remote func", "@rpc(any_peer) func", line));
+ }
+ old = line;
+ {
+ RegEx regex = RegEx("^remotesync func");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "@rpc(any_peer, call_local)) func", true);
}
if (old != line) {
- found_things.append(line_formatter(current_line, "master func", "@rpc(any) func", line));
+ found_things.append(line_formatter(current_line, "remotesync func", "@rpc(any_peer, call_local)) func", line));
}
old = line;
{
- RegEx reg_puppet2 = RegEx("^puppet func");
- CRASH_COND(!reg_puppet2.is_valid());
- line = reg_puppet2.sub(line, "@rpc(auth) func", true);
+ RegEx regex = RegEx("^sync func");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "@rpc(any_peer, call_local)) func", true);
}
if (old != line) {
- found_things.append(line_formatter(current_line, "puppet func", "@rpc(auth) func", line));
+ found_things.append(line_formatter(current_line, "sync func", "@rpc(any_peer, call_local)) func", line));
}
old = line;
{
- RegEx reg_remote2 = RegEx("^remote func");
- CRASH_COND(!reg_remote2.is_valid());
- line = reg_remote2.sub(line, "@rpc(any) func", true);
+ RegEx regex = RegEx("^slave func");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "@rpc func", true);
}
if (old != line) {
- found_things.append(line_formatter(current_line, "remote func", "@rpc(any) func", line));
+ found_things.append(line_formatter(current_line, "slave func", "@rpc func", line));
}
old = line;
{
- RegEx reg_remotesync2 = RegEx("^remotesync func");
- CRASH_COND(!reg_remotesync2.is_valid());
- line = reg_remotesync2.sub(line, "@rpc(any,sync) func", true);
+ RegEx regex = RegEx("^puppet func");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "@rpc func", true);
}
if (old != line) {
- found_things.append(line_formatter(current_line, "remotesync func", "@rpc(any,sync) func", line));
+ found_things.append(line_formatter(current_line, "puppet func", "@rpc func", line));
}
old = line;
{
- RegEx reg_sync2 = RegEx("^sync func");
- CRASH_COND(!reg_sync2.is_valid());
- line = reg_sync2.sub(line, "@rpc(any,sync) func", true);
+ RegEx regex = RegEx("^puppetsync func");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "@rpc(call_local) func", true);
}
if (old != line) {
- found_things.append(line_formatter(current_line, "sync func", "@rpc(any,sync) func", line));
+ found_things.append(line_formatter(current_line, "puppetsync func", "@rpc(call_local) func", line));
}
old = line;
{
- RegEx reg_puppetsync2 = RegEx("^puppetsync func");
- CRASH_COND(!reg_puppetsync2.is_valid());
- line = reg_puppetsync2.sub(line, "@rpc(auth,sync) func", true);
+ RegEx regex = RegEx("^master func");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "@rpc func", true);
}
if (old != line) {
- found_things.append(line_formatter(current_line, "puppetsync func", "@rpc(any,sync) func", line));
+ found_things.append(line_formatter(current_line, "master func", "@rpc func", line));
}
old = line;
{
- RegEx reg_mastersync2 = RegEx("^mastersync func");
- CRASH_COND(!reg_mastersync2.is_valid());
- line = reg_mastersync2.sub(line, "@rpc(any,sync) func", true);
+ RegEx regex = RegEx("^mastersync func");
+ CRASH_COND(!regex.is_valid());
+ line = regex.sub(line, "@rpc(call_local) func", true);
}
if (old != line) {
- found_things.append(line_formatter(current_line, "mastersync", "@rpc(any,sync) func", line));
+ found_things.append(line_formatter(current_line, "mastersync func", "@rpc(call_local) func", line));
}
old = line;
@@ -3808,7 +3539,7 @@ Vector<String> ProjectConverter3To4::check_for_custom_rename(Vector<String> &fil
int current_line = 1;
for (String &line : file_content) {
- Array reg_match = reg.search_all(line);
+ TypedArray<RegExMatch> reg_match = reg.search_all(line);
if (reg_match.size() > 0) {
found_things.append(line_formatter(current_line, from.replace("\\.", "."), to, line)); // Without replacing it will print "\.shader" instead ".shader"
}
@@ -3839,7 +3570,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_common(const char *array[]
int current_line = 1;
for (String &line : file_content) {
- Array reg_match = reg.search_all(line);
+ TypedArray<RegExMatch> reg_match = reg.search_all(line);
if (reg_match.size() > 0) {
found_things.append(line_formatter(current_line, array[current_index][0], array[current_index][1], line));
}
diff --git a/editor/project_converter_3_to_4.h b/editor/project_converter_3_to_4.h
index 95239666e0..8526e2ceb9 100644
--- a/editor/project_converter_3_to_4.h
+++ b/editor/project_converter_3_to_4.h
@@ -37,17 +37,26 @@
#include "core/string/ustring.h"
class ProjectConverter3To4 {
+public:
+ class RegExContainer;
+
+private:
void rename_enums(String &file_content);
Vector<String> check_for_rename_enums(Vector<String> &file_content);
void rename_classes(String &file_content);
Vector<String> check_for_rename_classes(Vector<String> &file_content);
- void rename_gdscript_functions(String &file_content);
- Vector<String> check_for_rename_gdscript_functions(Vector<String> &file_content);
+ void rename_gdscript_functions(String &file_content, const RegExContainer &reg_container, bool builtin);
+ Vector<String> check_for_rename_gdscript_functions(Vector<String> &file_content, const RegExContainer &reg_container, bool builtin);
+ void process_gdscript_line(String &line, const RegExContainer &reg_container, bool builtin);
void rename_csharp_functions(String &file_content);
Vector<String> check_for_rename_csharp_functions(Vector<String> &file_content);
+ void process_csharp_line(String &line);
+
+ void rename_csharp_attributes(String &file_content);
+ Vector<String> check_for_rename_csharp_attributes(Vector<String> &file_content);
void rename_gdscript_keywords(String &file_content);
Vector<String> check_for_rename_gdscript_keywords(Vector<String> &file_content);
@@ -71,9 +80,10 @@ class ProjectConverter3To4 {
bool test_single_array(const char *array[][2], bool ignore_second_check = false);
bool test_conversion_single_additional(String name, String expected, void (ProjectConverter3To4::*func)(String &), String what);
+ bool test_conversion_single_additional_builtin(String name, String expected, void (ProjectConverter3To4::*func)(String &, const RegExContainer &, bool), String what, const RegExContainer &reg_container, bool builtin);
bool test_conversion_single_normal(String name, String expected, const char *array[][2], String what);
bool test_array_names();
- bool test_conversion();
+ bool test_conversion(const RegExContainer &reg_container);
public:
int validate_conversion();
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 2e7b6f7476..21891e381b 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -42,6 +42,7 @@
#include "core/string/translation.h"
#include "core/version.h"
#include "editor/editor_file_dialog.h"
+#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_themes.h"
@@ -57,10 +58,6 @@
#include "servers/navigation_server_3d.h"
#include "servers/physics_server_2d.h"
-static inline String get_project_key_from_path(const String &dir) {
- return dir.replace("/", "::");
-}
-
class ProjectDialog : public ConfirmationDialog {
GDCLASS(ProjectDialog, ConfirmationDialog);
@@ -362,8 +359,8 @@ private:
if (mode == MODE_IMPORT) {
fdialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
fdialog->clear_filters();
- fdialog->add_filter(vformat("project.godot ; %s %s", VERSION_NAME, TTR("Project")));
- fdialog->add_filter("*.zip ; " + TTR("ZIP File"));
+ fdialog->add_filter("project.godot", vformat("%s %s", VERSION_NAME, TTR("Project")));
+ fdialog->add_filter("*.zip", TTR("ZIP File"));
} else {
fdialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR);
}
@@ -491,7 +488,7 @@ private:
if (ProjectSettings::get_singleton()->save_custom(dir.plus_file("project.godot"), initial_settings, Vector<String>(), false) != OK) {
set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR);
} else {
- ResourceSaver::save(dir.plus_file("icon.png"), create_unscaled_default_project_icon());
+ ResourceSaver::save(create_unscaled_default_project_icon(), dir.plus_file("icon.png"));
EditorVCSInterface::create_vcs_metadata_files(EditorVCSInterface::VCSMetadata(vcs_metadata_selection->get_selected()), dir);
}
} else if (mode == MODE_INSTALL) {
@@ -600,9 +597,6 @@ private:
if (dir.ends_with("/")) {
dir = dir.substr(0, dir.length() - 1);
}
- String proj = get_project_key_from_path(dir);
- EditorSettings::get_singleton()->set("projects/" + proj, dir);
- EditorSettings::get_singleton()->save();
hide();
emit_signal(SNAME("project_created"), dir);
@@ -646,14 +640,6 @@ private:
protected:
static void _bind_methods() {
- ClassDB::bind_method("_browse_path", &ProjectDialog::_browse_path);
- ClassDB::bind_method("_create_folder", &ProjectDialog::_create_folder);
- ClassDB::bind_method("_text_changed", &ProjectDialog::_text_changed);
- ClassDB::bind_method("_path_text_changed", &ProjectDialog::_path_text_changed);
- ClassDB::bind_method("_path_selected", &ProjectDialog::_path_selected);
- ClassDB::bind_method("_file_selected", &ProjectDialog::_file_selected);
- ClassDB::bind_method("_install_path_selected", &ProjectDialog::_install_path_selected);
- ClassDB::bind_method("_browse_install_path", &ProjectDialog::_browse_install_path);
ADD_SIGNAL(MethodInfo("project_created"));
ADD_SIGNAL(MethodInfo("projects_updated"));
}
@@ -681,7 +667,7 @@ public:
install_browse->hide();
set_title(TTR("Rename Project"));
- get_ok_button()->set_text(TTR("Rename"));
+ set_ok_button_text(TTR("Rename"));
name_container->show();
status_rect->hide();
msg->hide();
@@ -735,7 +721,7 @@ public:
if (mode == MODE_IMPORT) {
set_title(TTR("Import Existing Project"));
- get_ok_button()->set_text(TTR("Import & Edit"));
+ set_ok_button_text(TTR("Import & Edit"));
name_container->hide();
install_path_container->hide();
rasterizer_container->hide();
@@ -744,7 +730,7 @@ public:
} else if (mode == MODE_NEW) {
set_title(TTR("Create New Project"));
- get_ok_button()->set_text(TTR("Create & Edit"));
+ set_ok_button_text(TTR("Create & Edit"));
name_container->show();
install_path_container->hide();
rasterizer_container->show();
@@ -754,7 +740,7 @@ public:
} else if (mode == MODE_INSTALL) {
set_title(TTR("Install Project:") + " " + zip_title);
- get_ok_button()->set_text(TTR("Install & Edit"));
+ set_ok_button_text(TTR("Install & Edit"));
project_name->set_text(zip_title);
name_container->show();
install_path_container->hide();
@@ -997,7 +983,6 @@ public:
// Can often be passed by copy
struct Item {
- String project_key;
String project_name;
String description;
String path;
@@ -1014,8 +999,7 @@ public:
Item() {}
- Item(const String &p_project,
- const String &p_name,
+ Item(const String &p_name,
const String &p_description,
const String &p_path,
const String &p_icon,
@@ -1026,7 +1010,6 @@ public:
bool p_grayed,
bool p_missing,
int p_version) {
- project_key = p_project;
project_name = p_name;
description = p_description;
path = p_path;
@@ -1042,7 +1025,7 @@ public:
}
_FORCE_INLINE_ bool operator==(const Item &l) const {
- return project_key == l.project_key;
+ return path == l.path;
}
};
@@ -1055,6 +1038,7 @@ public:
void _global_menu_open_project(const Variant &p_tag);
void update_dock_menu();
+ void migrate_config();
void load_projects();
void set_search_term(String p_search_term);
void set_order_option(int p_option);
@@ -1070,6 +1054,8 @@ public:
bool is_any_project_missing() const;
void erase_missing_projects();
int refresh_project(const String &dir_path);
+ void add_project(const String &dir_path, bool favorite);
+ void save_config();
private:
static void _bind_methods();
@@ -1090,12 +1076,15 @@ private:
String _search_term;
FilterOption _order_option;
- HashSet<String> _selected_project_keys;
+ HashSet<String> _selected_project_paths;
String _last_clicked; // Project key
VBoxContainer *_scroll_children;
int _icon_load_index;
Vector<Item> _projects;
+
+ ConfigFile _config;
+ String _config_path;
};
struct ProjectListComparator {
@@ -1111,7 +1100,7 @@ struct ProjectListComparator {
}
switch (order_option) {
case PATH:
- return a.project_key < b.project_key;
+ return a.path < b.path;
case EDIT_DATE:
return a.last_edited > b.last_edited;
default:
@@ -1128,6 +1117,7 @@ ProjectList::ProjectList() {
_icon_load_index = 0;
project_opening_initiated = false;
+ _config_path = EditorPaths::get_singleton()->get_data_dir().plus_file("projects.cfg");
}
ProjectList::~ProjectList() {
@@ -1167,9 +1157,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()) {
@@ -1181,9 +1169,8 @@ void ProjectList::load_project_icon(int p_index) {
}
// Load project data from p_property_key and return it in a ProjectList::Item. p_favorite is passed directly into the Item.
-ProjectList::Item ProjectList::load_project_data(const String &p_property_key, bool p_favorite) {
- String path = EditorSettings::get_singleton()->get(p_property_key);
- String conf = path.plus_file("project.godot");
+ProjectList::Item ProjectList::load_project_data(const String &p_path, bool p_favorite) {
+ String conf = p_path.plus_file("project.godot");
bool grayed = false;
bool missing = false;
@@ -1219,7 +1206,7 @@ ProjectList::Item ProjectList::load_project_data(const String &p_property_key, b
// when editing a project (but not when running it).
last_edited = FileAccess::get_modified_time(conf);
- String fscache = path.plus_file(".fscache");
+ String fscache = p_path.plus_file(".fscache");
if (FileAccess::exists(fscache)) {
uint64_t cache_modified = FileAccess::get_modified_time(fscache);
if (cache_modified > last_edited) {
@@ -1232,9 +1219,38 @@ ProjectList::Item ProjectList::load_project_data(const String &p_property_key, b
print_line("Project is missing: " + conf);
}
- const String project_key = p_property_key.get_slice("/", 1);
+ return Item(project_name, description, p_path, icon, main_scene, unsupported_features, last_edited, p_favorite, grayed, missing, config_version);
+}
+
+void ProjectList::migrate_config() {
+ // Proposal #1637 moved the project list from editor settings to a separate config file
+ // If the new config file doesn't exist, populate it from EditorSettings
+ if (FileAccess::exists(_config_path)) {
+ return;
+ }
+ print_line("Migrating legacy project list");
+
+ List<PropertyInfo> properties;
+ EditorSettings::get_singleton()->get_property_list(&properties);
+
+ for (const PropertyInfo &E : properties) {
+ // This is actually something like "projects/C:::Documents::Godot::Projects::MyGame"
+ String property_key = E.name;
+ if (!property_key.begins_with("projects/")) {
+ continue;
+ }
+
+ String path = EditorSettings::get_singleton()->get(property_key);
+ String favoriteKey = "favorite_projects/" + property_key.get_slice("/", 1);
+ bool favorite = EditorSettings::get_singleton()->has_setting(favoriteKey);
+ add_project(path, favorite);
+ if (favorite) {
+ EditorSettings::get_singleton()->erase(favoriteKey);
+ }
+ EditorSettings::get_singleton()->erase(property_key);
+ }
- return Item(project_key, project_name, description, path, icon, main_scene, unsupported_features, last_edited, p_favorite, grayed, missing, config_version);
+ save_config();
}
void ProjectList::load_projects() {
@@ -1249,37 +1265,15 @@ void ProjectList::load_projects() {
}
_projects.clear();
_last_clicked = "";
- _selected_project_keys.clear();
+ _selected_project_paths.clear();
- // Load data
- // TODO Would be nice to change how projects and favourites are stored... it complicates things a bit.
- // Use a dictionary associating project path to metadata (like is_favorite).
+ List<String> sections;
+ _config.load(_config_path);
+ _config.get_sections(&sections);
- List<PropertyInfo> properties;
- EditorSettings::get_singleton()->get_property_list(&properties);
-
- HashSet<String> favorites;
- // Find favourites...
- for (const PropertyInfo &E : properties) {
- String property_key = E.name;
- if (property_key.begins_with("favorite_projects/")) {
- favorites.insert(property_key);
- }
- }
-
- for (const PropertyInfo &E : properties) {
- // This is actually something like "projects/C:::Documents::Godot::Projects::MyGame"
- String property_key = E.name;
- if (!property_key.begins_with("projects/")) {
- continue;
- }
-
- String project_key = property_key.get_slice("/", 1);
- bool favorite = favorites.has("favorite_projects/" + project_key);
-
- Item item = load_project_data(property_key, favorite);
-
- _projects.push_back(item);
+ for (const String &path : sections) {
+ bool favorite = _config.get_value(path, "favorite", false);
+ _projects.push_back(load_project_data(path, favorite));
}
// Create controls
@@ -1350,8 +1344,8 @@ void ProjectList::create_project_item_control(int p_index) {
Color font_color = get_theme_color(SNAME("font_color"), SNAME("Tree"));
ProjectListItemControl *hb = memnew(ProjectListItemControl);
- hb->connect("draw", callable_mp(this, &ProjectList::_panel_draw), varray(hb));
- hb->connect("gui_input", callable_mp(this, &ProjectList::_panel_input), varray(hb));
+ hb->connect("draw", callable_mp(this, &ProjectList::_panel_draw).bind(hb));
+ hb->connect("gui_input", callable_mp(this, &ProjectList::_panel_input).bind(hb));
hb->add_theme_constant_override("separation", 10 * EDSCALE);
hb->set_tooltip(item.description);
@@ -1362,7 +1356,7 @@ void ProjectList::create_project_item_control(int p_index) {
favorite->set_normal_texture(favorite_icon);
// This makes the project's "hover" style display correctly when hovering the favorite icon.
favorite->set_mouse_filter(MOUSE_FILTER_PASS);
- favorite->connect("pressed", callable_mp(this, &ProjectList::_favorite_pressed), varray(hb));
+ favorite->connect("pressed", callable_mp(this, &ProjectList::_favorite_pressed).bind(hb));
favorite_box->add_child(favorite);
favorite_box->set_alignment(BoxContainer::ALIGNMENT_CENTER);
hb->add_child(favorite_box);
@@ -1435,7 +1429,7 @@ void ProjectList::create_project_item_control(int p_index) {
path_hb->add_child(show);
if (!item.missing) {
- show->connect("pressed", callable_mp(this, &ProjectList::_show_project), varray(item.path));
+ show->connect("pressed", callable_mp(this, &ProjectList::_show_project).bind(item.path));
show->set_tooltip(TTR("Show in File Manager"));
} else {
show->set_tooltip(TTR("Error: Project is missing on the filesystem."));
@@ -1506,19 +1500,19 @@ void ProjectList::sort_projects() {
const HashSet<String> &ProjectList::get_selected_project_keys() const {
// Faster if that's all you need
- return _selected_project_keys;
+ return _selected_project_paths;
}
Vector<ProjectList::Item> ProjectList::get_selected_projects() const {
Vector<Item> items;
- if (_selected_project_keys.size() == 0) {
+ if (_selected_project_paths.size() == 0) {
return items;
}
- items.resize(_selected_project_keys.size());
+ items.resize(_selected_project_paths.size());
int j = 0;
for (int i = 0; i < _projects.size(); ++i) {
const Item &item = _projects[i];
- if (_selected_project_keys.has(item.project_key)) {
+ if (_selected_project_paths.has(item.path)) {
items.write[j++] = item;
}
}
@@ -1532,41 +1526,40 @@ void ProjectList::ensure_project_visible(int p_index) {
}
int ProjectList::get_single_selected_index() const {
- if (_selected_project_keys.size() == 0) {
+ if (_selected_project_paths.size() == 0) {
// Default selection
return 0;
}
String key;
- if (_selected_project_keys.size() == 1) {
+ if (_selected_project_paths.size() == 1) {
// Only one selected
- key = *_selected_project_keys.begin();
+ key = *_selected_project_paths.begin();
} else {
// Multiple selected, consider the last clicked one as "main"
key = _last_clicked;
}
for (int i = 0; i < _projects.size(); ++i) {
- if (_projects[i].project_key == key) {
+ if (_projects[i].path == key) {
return i;
}
}
return 0;
}
-void ProjectList::remove_project(int p_index, bool p_update_settings) {
+void ProjectList::remove_project(int p_index, bool p_update_config) {
const Item item = _projects[p_index]; // Take a copy
- _selected_project_keys.erase(item.project_key);
+ _selected_project_paths.erase(item.path);
- if (_last_clicked == item.project_key) {
+ if (_last_clicked == item.path) {
_last_clicked = "";
}
memdelete(item.control);
_projects.remove_at(p_index);
- if (p_update_settings) {
- EditorSettings::get_singleton()->erase("projects/" + item.project_key);
- EditorSettings::get_singleton()->erase("favorite_projects/" + item.project_key);
+ if (p_update_config) {
+ _config.erase_section(item.path);
// Not actually saving the file, in case you are doing more changes to settings
}
@@ -1604,41 +1597,19 @@ void ProjectList::erase_missing_projects() {
}
print_line("Removed " + itos(deleted_count) + " projects from the list, remaining " + itos(remaining_count) + " projects");
-
- EditorSettings::get_singleton()->save();
+ save_config();
}
int ProjectList::refresh_project(const String &dir_path) {
- // Reads editor settings and reloads information about a specific project.
+ // Reloads information about a specific project.
// If it wasn't loaded and should be in the list, it is added (i.e new project).
// If it isn't in the list anymore, it is removed.
// If it is in the list but doesn't exist anymore, it is marked as missing.
- String project_key = get_project_key_from_path(dir_path);
+ bool should_be_in_list = _config.has_section(dir_path);
+ bool is_favourite = _config.get_value(dir_path, "favorite", false);
- // Read project manager settings
- bool is_favourite = false;
- bool should_be_in_list = false;
- String property_key = "projects/" + project_key;
- {
- List<PropertyInfo> properties;
- EditorSettings::get_singleton()->get_property_list(&properties);
- String favorite_property_key = "favorite_projects/" + project_key;
-
- bool found = false;
- for (const PropertyInfo &E : properties) {
- String prop = E.name;
- if (!found && prop == property_key) {
- found = true;
- } else if (!is_favourite && prop == favorite_property_key) {
- is_favourite = true;
- }
- }
-
- should_be_in_list = found;
- }
-
- bool was_selected = _selected_project_keys.has(project_key);
+ bool was_selected = _selected_project_paths.has(dir_path);
// Remove item in any case
for (int i = 0; i < _projects.size(); ++i) {
@@ -1653,7 +1624,7 @@ int ProjectList::refresh_project(const String &dir_path) {
if (should_be_in_list) {
// Recreate it with updated info
- Item item = load_project_data(property_key, is_favourite);
+ Item item = load_project_data(dir_path, is_favourite);
_projects.push_back(item);
create_project_item_control(_projects.size() - 1);
@@ -1661,7 +1632,7 @@ int ProjectList::refresh_project(const String &dir_path) {
sort_projects();
for (int i = 0; i < _projects.size(); ++i) {
- if (_projects[i].project_key == project_key) {
+ if (_projects[i].path == dir_path) {
if (was_selected) {
select_project(i);
ensure_project_visible(i);
@@ -1677,13 +1648,23 @@ int ProjectList::refresh_project(const String &dir_path) {
return index;
}
+void ProjectList::add_project(const String &dir_path, bool favorite) {
+ if (!_config.has_section(dir_path)) {
+ _config.set_value(dir_path, "favorite", favorite);
+ }
+}
+
+void ProjectList::save_config() {
+ _config.save(_config_path);
+}
+
int ProjectList::get_project_count() const {
return _projects.size();
}
void ProjectList::select_project(int p_index) {
Vector<Item> previous_selected_items = get_selected_projects();
- _selected_project_keys.clear();
+ _selected_project_paths.clear();
for (int i = 0; i < previous_selected_items.size(); ++i) {
previous_selected_items[i].control->update();
@@ -1705,7 +1686,7 @@ void ProjectList::select_first_visible_project() {
if (!found) {
// Deselect all projects if there are no visible projects in the list.
- _selected_project_keys.clear();
+ _selected_project_paths.clear();
}
}
@@ -1727,24 +1708,23 @@ void ProjectList::select_range(int p_begin, int p_end) {
void ProjectList::toggle_select(int p_index) {
Item &item = _projects.write[p_index];
- if (_selected_project_keys.has(item.project_key)) {
- _selected_project_keys.erase(item.project_key);
+ if (_selected_project_paths.has(item.path)) {
+ _selected_project_paths.erase(item.path);
} else {
- _selected_project_keys.insert(item.project_key);
+ _selected_project_paths.insert(item.path);
}
item.control->update();
}
void ProjectList::erase_selected_projects(bool p_delete_project_contents) {
- if (_selected_project_keys.size() == 0) {
+ if (_selected_project_paths.size() == 0) {
return;
}
for (int i = 0; i < _projects.size(); ++i) {
Item &item = _projects.write[i];
- if (_selected_project_keys.has(item.project_key) && item.control->is_visible()) {
- EditorSettings::get_singleton()->erase("projects/" + item.project_key);
- EditorSettings::get_singleton()->erase("favorite_projects/" + item.project_key);
+ if (_selected_project_paths.has(item.path) && item.control->is_visible()) {
+ _config.erase_section(item.path);
if (p_delete_project_contents) {
OS::get_singleton()->move_to_trash(item.path);
@@ -1756,9 +1736,8 @@ void ProjectList::erase_selected_projects(bool p_delete_project_contents) {
}
}
- EditorSettings::get_singleton()->save();
-
- _selected_project_keys.clear();
+ save_config();
+ _selected_project_paths.clear();
_last_clicked = "";
update_dock_menu();
@@ -1774,9 +1753,9 @@ void ProjectList::_panel_draw(Node *p_hb) {
hb->draw_line(Point2(0, hb->get_size().y + 1), Point2(hb->get_size().x, hb->get_size().y + 1), get_theme_color(SNAME("guide_color"), SNAME("Tree")));
}
- String key = _projects[p_hb->get_index()].project_key;
+ String key = _projects[p_hb->get_index()].path;
- if (_selected_project_keys.has(key)) {
+ if (_selected_project_paths.has(key)) {
hb->draw_style_box(get_theme_stylebox(SNAME("selected"), SNAME("Tree")), Rect2(Point2(), hb->get_size()));
}
}
@@ -1788,11 +1767,11 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
const Item &clicked_project = _projects[clicked_index];
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
- if (mb->is_shift_pressed() && _selected_project_keys.size() > 0 && !_last_clicked.is_empty() && clicked_project.project_key != _last_clicked) {
+ if (mb->is_shift_pressed() && _selected_project_paths.size() > 0 && !_last_clicked.is_empty() && clicked_project.path != _last_clicked) {
int anchor_index = -1;
for (int i = 0; i < _projects.size(); ++i) {
const Item &p = _projects[i];
- if (p.project_key == _last_clicked) {
+ if (p.path == _last_clicked) {
anchor_index = p.control->get_index();
break;
}
@@ -1804,7 +1783,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
toggle_select(clicked_index);
} else {
- _last_clicked = clicked_project.project_key;
+ _last_clicked = clicked_project.path;
select_project(clicked_index);
}
@@ -1826,12 +1805,8 @@ void ProjectList::_favorite_pressed(Node *p_hb) {
item.favorite = !item.favorite;
- if (item.favorite) {
- EditorSettings::get_singleton()->set("favorite_projects/" + item.project_key, item.path);
- } else {
- EditorSettings::get_singleton()->erase("favorite_projects/" + item.project_key);
- }
- EditorSettings::get_singleton()->save();
+ _config.set_value(item.path, "favorite", item.favorite);
+ save_config();
_projects.write[index] = item;
@@ -1841,7 +1816,7 @@ void ProjectList::_favorite_pressed(Node *p_hb) {
if (item.favorite) {
for (int i = 0; i < _projects.size(); ++i) {
- if (_projects[i].project_key == item.project_key) {
+ if (_projects[i].path == item.path) {
ensure_project_visible(i);
break;
}
@@ -1895,7 +1870,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"));
@@ -2001,7 +1975,7 @@ void ProjectManager::shortcut_input(const Ref<InputEvent> &p_ev) {
// Pressing Command + Q quits the Project Manager
// This is handled by the platform implementation on macOS,
// so only define the shortcut on other platforms
-#ifndef OSX_ENABLED
+#ifndef MACOS_ENABLED
if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::Q)) {
_dim_window();
get_tree()->quit();
@@ -2100,6 +2074,8 @@ void ProjectManager::_on_projects_updated() {
}
void ProjectManager::_on_project_created(const String &dir) {
+ _project_list->add_project(dir, false);
+ _project_list->save_config();
search_box->clear();
int i = _project_list->refresh_project(dir);
_project_list->select_project(i);
@@ -2120,9 +2096,7 @@ void ProjectManager::_open_selected_projects() {
const HashSet<String> &selected_list = _project_list->get_selected_project_keys();
- for (const String &E : selected_list) {
- const String &selected = E;
- String path = EditorSettings::get_singleton()->get("projects/" + selected);
+ for (const String &path : selected_list) {
String conf = path.plus_file("project.godot");
if (!FileAccess::exists(conf)) {
@@ -2131,7 +2105,7 @@ void ProjectManager::_open_selected_projects() {
return;
}
- print_line("Editing project: " + path + " (" + selected + ")");
+ print_line("Editing project: " + path);
List<String> args;
@@ -2255,8 +2229,7 @@ void ProjectManager::_run_project_confirm() {
continue;
}
- const String &selected = selected_list[i].project_key;
- String path = EditorSettings::get_singleton()->get("projects/" + selected);
+ const String &path = selected_list[i].path;
// `.substr(6)` on `ProjectSettings::get_singleton()->get_imported_files_path()` strips away the leading "res://".
if (!DirAccess::exists(path.plus_file(ProjectSettings::get_singleton()->get_imported_files_path().substr(6)))) {
@@ -2265,7 +2238,7 @@ void ProjectManager::_run_project_confirm() {
continue;
}
- print_line("Running project: " + path + " (" + selected + ")");
+ print_line("Running project: " + path);
List<String> args;
@@ -2296,7 +2269,7 @@ void ProjectManager::_run_project() {
}
}
-void ProjectManager::_scan_dir(const String &path, List<String> *r_projects) {
+void ProjectManager::_scan_dir(const String &path) {
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error error = da->change_dir(path);
ERR_FAIL_COND_MSG(error != OK, "Could not scan directory at: " + path);
@@ -2304,26 +2277,18 @@ void ProjectManager::_scan_dir(const String &path, List<String> *r_projects) {
String n = da->get_next();
while (!n.is_empty()) {
if (da->current_is_dir() && !n.begins_with(".")) {
- _scan_dir(da->get_current_dir().plus_file(n), r_projects);
+ _scan_dir(da->get_current_dir().plus_file(n));
} else if (n == "project.godot") {
- r_projects->push_back(da->get_current_dir());
+ _project_list->add_project(da->get_current_dir(), false);
}
n = da->get_next();
}
da->list_dir_end();
}
-
void ProjectManager::_scan_begin(const String &p_base) {
print_line("Scanning projects at: " + p_base);
- List<String> projects;
- _scan_dir(p_base, &projects);
- print_line("Found " + itos(projects.size()) + " projects.");
-
- for (const String &E : projects) {
- String proj = get_project_key_from_path(E);
- EditorSettings::get_singleton()->set("projects/" + proj, E);
- }
- EditorSettings::get_singleton()->save();
+ _scan_dir(p_base);
+ _project_list->save_config();
_load_recent_projects();
}
@@ -2349,9 +2314,7 @@ void ProjectManager::_rename_project() {
}
for (const String &E : selected_list) {
- const String &selected = E;
- String path = EditorSettings::get_singleton()->get("projects/" + selected);
- npdialog->set_project_path(path);
+ npdialog->set_project_path(E);
npdialog->set_mode(ProjectDialog::MODE_RENAME);
npdialog->show_dialog();
}
@@ -2454,7 +2417,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files) {
}
if (confirm) {
multi_scan_ask->get_ok_button()->disconnect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders));
- multi_scan_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders), varray(folders));
+ multi_scan_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders).bind(folders));
multi_scan_ask->set_text(
vformat(TTR("Are you sure to scan %s folders for existing Godot projects?\nThis could take a while."), folders.size()));
multi_scan_ask->popup_centered();
@@ -2565,19 +2528,19 @@ ProjectManager::ProjectManager() {
EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
- set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
set_theme(create_custom_theme());
- set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
Panel *panel = memnew(Panel);
add_child(panel);
- panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ panel->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("Background"), SNAME("EditorStyles")));
VBoxContainer *vb = memnew(VBoxContainer);
panel->add_child(vb);
- vb->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8 * EDSCALE);
+ vb->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 8 * EDSCALE);
Control *center_box = memnew(Control);
center_box->set_v_size_flags(Control::SIZE_EXPAND_FILL);
@@ -2585,7 +2548,7 @@ ProjectManager::ProjectManager() {
tabs = memnew(TabContainer);
center_box->add_child(tabs);
- tabs->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ tabs->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
tabs->connect("tab_changed", callable_mp(this, &ProjectManager::_on_tab_changed));
local_projects_hb = memnew(HBoxContainer);
@@ -2792,25 +2755,21 @@ ProjectManager::ProjectManager() {
center_box->add_child(settings_hb);
}
- // Asset Library can't work on Web editor for now as most assets are sourced
- // directly from GitHub which does not set CORS.
-#ifndef JAVASCRIPT_ENABLED
- if (StreamPeerSSL::is_available()) {
+ if (AssetLibraryEditorPlugin::is_available()) {
asset_library = memnew(EditorAssetLibrary(true));
asset_library->set_name(TTR("Asset Library Projects"));
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).");
}
-#endif
{
// Dialogs
language_restart_ask = memnew(ConfirmationDialog);
- language_restart_ask->get_ok_button()->set_text(TTR("Restart Now"));
+ language_restart_ask->set_ok_button_text(TTR("Restart Now"));
language_restart_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_restart_confirm));
- language_restart_ask->get_cancel_button()->set_text(TTR("Continue"));
+ language_restart_ask->set_cancel_button_text(TTR("Continue"));
add_child(language_restart_ask);
scan_dir = memnew(EditorFileDialog);
@@ -2823,12 +2782,12 @@ ProjectManager::ProjectManager() {
scan_dir->connect("dir_selected", callable_mp(this, &ProjectManager::_scan_begin));
erase_missing_ask = memnew(ConfirmationDialog);
- erase_missing_ask->get_ok_button()->set_text(TTR("Remove All"));
+ erase_missing_ask->set_ok_button_text(TTR("Remove All"));
erase_missing_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_erase_missing_projects_confirm));
add_child(erase_missing_ask);
erase_ask = memnew(ConfirmationDialog);
- erase_ask->get_ok_button()->set_text(TTR("Remove"));
+ erase_ask->set_ok_button_text(TTR("Remove"));
erase_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_erase_project_confirm));
add_child(erase_ask);
@@ -2843,17 +2802,17 @@ ProjectManager::ProjectManager() {
erase_ask_vb->add_child(delete_project_contents);
multi_open_ask = memnew(ConfirmationDialog);
- multi_open_ask->get_ok_button()->set_text(TTR("Edit"));
+ multi_open_ask->set_ok_button_text(TTR("Edit"));
multi_open_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_open_selected_projects));
add_child(multi_open_ask);
multi_run_ask = memnew(ConfirmationDialog);
- multi_run_ask->get_ok_button()->set_text(TTR("Run"));
+ multi_run_ask->set_ok_button_text(TTR("Run"));
multi_run_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_run_project_confirm));
add_child(multi_run_ask);
multi_scan_ask = memnew(ConfirmationDialog);
- multi_scan_ask->get_ok_button()->set_text(TTR("Scan"));
+ multi_scan_ask->set_ok_button_text(TTR("Scan"));
add_child(multi_scan_ask);
ask_update_settings = memnew(ConfirmationDialog);
@@ -2875,7 +2834,7 @@ ProjectManager::ProjectManager() {
if (asset_library) {
open_templates = memnew(ConfirmationDialog);
open_templates->set_text(TTR("You currently don't have any projects.\nWould you like to explore official example projects in the Asset Library?"));
- open_templates->get_ok_button()->set_text(TTR("Open Asset Library"));
+ open_templates->set_ok_button_text(TTR("Open Asset Library"));
open_templates->connect("confirmed", callable_mp(this, &ProjectManager::_open_asset_library));
add_child(open_templates);
}
@@ -2886,6 +2845,7 @@ ProjectManager::ProjectManager() {
_build_icon_type_cache(get_theme());
}
+ _project_list->migrate_config();
_load_recent_projects();
Ref<DirAccess> dir_access = DirAccess::create(DirAccess::AccessType::ACCESS_FILESYSTEM);
diff --git a/editor/project_manager.h b/editor/project_manager.h
index 28383e4142..10bf25c048 100644
--- a/editor/project_manager.h
+++ b/editor/project_manager.h
@@ -125,7 +125,7 @@ class ProjectManager : public Control {
void _on_projects_updated();
void _scan_multiple_folders(PackedStringArray p_files);
void _scan_begin(const String &p_base);
- void _scan_dir(const String &path, List<String> *r_projects);
+ void _scan_dir(const String &path);
void _install_project(const String &p_zip_path, const String &p_title);
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 1524993bd0..ca5eeaa787 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -31,14 +31,18 @@
#include "project_settings_editor.h"
#include "core/config/project_settings.h"
-#include "editor/editor_export.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "servers/movie_writer/movie_writer.h"
ProjectSettingsEditor *ProjectSettingsEditor::singleton = nullptr;
+void ProjectSettingsEditor::connect_filesystem_dock_signals(FileSystemDock *p_fs_dock) {
+ localization_editor->connect_filesystem_dock_signals(p_fs_dock);
+}
+
void ProjectSettingsEditor::popup_project_settings() {
// Restore valid window bounds or pop up at default size.
Rect2 saved_size = EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "project_settings", Rect2());
@@ -75,8 +79,13 @@ void ProjectSettingsEditor::_setting_edited(const String &p_name) {
queue_save();
}
+void ProjectSettingsEditor::_update_advanced(bool p_is_advanced) {
+ custom_properties->set_visible(p_is_advanced);
+}
+
void ProjectSettingsEditor::_advanced_toggled(bool p_button_pressed) {
EditorSettings::get_singleton()->set_project_metadata("project_settings", "advanced_mode", p_button_pressed);
+ _update_advanced(p_button_pressed);
general_settings_inspector->set_restrict_to_basic_settings(!p_button_pressed);
}
@@ -585,35 +594,35 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
advanced->connect("toggled", callable_mp(this, &ProjectSettingsEditor::_advanced_toggled));
search_bar->add_child(advanced);
- HBoxContainer *header = memnew(HBoxContainer);
- general_editor->add_child(header);
+ custom_properties = memnew(HBoxContainer);
+ general_editor->add_child(custom_properties);
property_box = memnew(LineEdit);
property_box->set_placeholder(TTR("Select a Setting or Type its Name"));
property_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
property_box->connect("text_changed", callable_mp(this, &ProjectSettingsEditor::_property_box_changed));
- header->add_child(property_box);
+ custom_properties->add_child(property_box);
feature_box = memnew(OptionButton);
feature_box->set_custom_minimum_size(Size2(120, 0) * EDSCALE);
feature_box->connect("item_selected", callable_mp(this, &ProjectSettingsEditor::_feature_selected));
- header->add_child(feature_box);
+ custom_properties->add_child(feature_box);
type_box = memnew(OptionButton);
type_box->set_custom_minimum_size(Size2(120, 0) * EDSCALE);
- header->add_child(type_box);
+ custom_properties->add_child(type_box);
add_button = memnew(Button);
add_button->set_text(TTR("Add"));
add_button->set_disabled(true);
add_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_add_setting));
- header->add_child(add_button);
+ custom_properties->add_child(add_button);
del_button = memnew(Button);
del_button->set_text(TTR("Delete"));
del_button->set_disabled(true);
del_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_delete_setting));
- header->add_child(del_button);
+ custom_properties->add_child(del_button);
general_settings_inspector = memnew(SectionedInspector);
general_settings_inspector->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo());
@@ -670,10 +679,10 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
autoload_settings->connect("autoload_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
tab_container->add_child(autoload_settings);
- shaders_global_variables_editor = memnew(ShaderGlobalsEditor);
- shaders_global_variables_editor->set_name(TTR("Shader Globals"));
- shaders_global_variables_editor->connect("globals_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
- tab_container->add_child(shaders_global_variables_editor);
+ shaders_global_shader_uniforms_editor = memnew(ShaderGlobalsEditor);
+ shaders_global_shader_uniforms_editor->set_name(TTR("Shader Globals"));
+ shaders_global_shader_uniforms_editor->connect("globals_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
+ tab_container->add_child(shaders_global_shader_uniforms_editor);
plugin_settings = memnew(EditorPluginSettings);
plugin_settings->set_name(TTR("Plugins"));
@@ -685,7 +694,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
timer->set_one_shot(true);
add_child(timer);
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
set_hide_on_ok(true);
bool use_advanced = EditorSettings::get_singleton()->get_project_metadata("project_settings", "advanced_mode", false);
@@ -694,6 +703,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
advanced->set_pressed(true);
}
+ _update_advanced(use_advanced);
general_settings_inspector->set_restrict_to_basic_settings(!use_advanced);
import_defaults_editor = memnew(ImportDefaultsEditor);
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index 24d61db443..c2d2c2d8f4 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -43,6 +43,8 @@
#include "editor/shader_globals_editor.h"
#include "scene/gui/tab_container.h"
+class FileSystemDock;
+
class ProjectSettingsEditor : public AcceptDialog {
GDCLASS(ProjectSettingsEditor, AcceptDialog);
@@ -55,12 +57,13 @@ class ProjectSettingsEditor : public AcceptDialog {
ActionMapEditor *action_map_editor = nullptr;
LocalizationEditor *localization_editor = nullptr;
EditorAutoloadSettings *autoload_settings = nullptr;
- ShaderGlobalsEditor *shaders_global_variables_editor = nullptr;
+ ShaderGlobalsEditor *shaders_global_shader_uniforms_editor = nullptr;
EditorPluginSettings *plugin_settings = nullptr;
LineEdit *search_box = nullptr;
CheckButton *advanced = nullptr;
+ HBoxContainer *custom_properties = nullptr;
LineEdit *property_box = nullptr;
OptionButton *feature_box = nullptr;
OptionButton *type_box = nullptr;
@@ -77,6 +80,7 @@ class ProjectSettingsEditor : public AcceptDialog {
UndoRedo *undo_redo = nullptr;
void _advanced_toggled(bool p_button_pressed);
+ void _update_advanced(bool p_is_advanced);
void _property_box_changed(const String &p_text);
void _update_property_box();
void _feature_selected(int p_index);
@@ -118,6 +122,7 @@ public:
TabContainer *get_tabs() { return tab_container; }
void queue_save();
+ void connect_filesystem_dock_signals(FileSystemDock *p_fs_dock);
ProjectSettingsEditor(EditorData *p_data);
};
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
deleted file mode 100644
index d936e821df..0000000000
--- a/editor/property_editor.cpp
+++ /dev/null
@@ -1,1911 +0,0 @@
-/*************************************************************************/
-/* property_editor.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 "property_editor.h"
-
-#include "core/config/project_settings.h"
-#include "core/input/input.h"
-#include "core/io/image_loader.h"
-#include "core/io/marshalls.h"
-#include "core/io/resource_loader.h"
-#include "core/math/expression.h"
-#include "core/object/class_db.h"
-#include "core/os/keyboard.h"
-#include "core/string/print_string.h"
-#include "core/templates/pair.h"
-#include "editor/array_property_edit.h"
-#include "editor/create_dialog.h"
-#include "editor/dictionary_property_edit.h"
-#include "editor/editor_export.h"
-#include "editor/editor_file_dialog.h"
-#include "editor/editor_file_system.h"
-#include "editor/editor_help.h"
-#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
-#include "editor/editor_settings.h"
-#include "editor/filesystem_dock.h"
-#include "editor/multi_node_edit.h"
-#include "editor/property_selector.h"
-#include "editor/scene_tree_dock.h"
-#include "scene/gui/label.h"
-#include "scene/main/window.h"
-#include "scene/resources/font.h"
-#include "scene/resources/packed_scene.h"
-#include "scene/scene_string_names.h"
-
-void EditorResourceConversionPlugin::_bind_methods() {
- GDVIRTUAL_BIND(_converts_to);
- GDVIRTUAL_BIND(_handles, "resource");
- GDVIRTUAL_BIND(_convert, "resource");
-}
-
-String EditorResourceConversionPlugin::converts_to() const {
- String ret;
- if (GDVIRTUAL_CALL(_converts_to, ret)) {
- return ret;
- }
-
- return "";
-}
-
-bool EditorResourceConversionPlugin::handles(const Ref<Resource> &p_resource) const {
- bool ret;
- if (GDVIRTUAL_CALL(_handles, p_resource, ret)) {
- return ret;
- }
-
- return false;
-}
-
-Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) const {
- Ref<Resource> ret;
- if (GDVIRTUAL_CALL(_convert, p_resource, ret)) {
- return ret;
- }
-
- return Ref<Resource>();
-}
-
-void CustomPropertyEditor::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_WM_CLOSE_REQUEST: {
- hide();
- } break;
- }
-}
-
-void CustomPropertyEditor::_menu_option(int p_which) {
- switch (type) {
- case Variant::INT: {
- if (hint == PROPERTY_HINT_FLAGS) {
- int idx = menu->get_item_index(p_which);
- uint32_t item_value = menu->get_item_metadata(idx);
- uint32_t value = v;
- // If the item wasn't previously checked it means it was pressed,
- // otherwise it was unpressed.
- if (!menu->is_item_checked(idx)) {
- v = value | item_value;
- } else {
- v = value & ~item_value;
- }
- emit_signal(SNAME("variant_changed"));
- } else if (hint == PROPERTY_HINT_ENUM) {
- v = menu->get_item_metadata(p_which);
- emit_signal(SNAME("variant_changed"));
- }
- } break;
- case Variant::STRING: {
- if (hint == PROPERTY_HINT_ENUM) {
- v = hint_text.get_slice(",", p_which);
- emit_signal(SNAME("variant_changed"));
- }
- } break;
- case Variant::OBJECT: {
- switch (p_which) {
- case OBJ_MENU_LOAD: {
- file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
- String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String();
-
- List<String> extensions;
- for (int i = 0; i < type.get_slice_count(","); i++) {
- ResourceLoader::get_recognized_extensions_for_type(type.get_slice(",", i), &extensions);
- }
-
- HashSet<String> valid_extensions;
- for (const String &E : extensions) {
- valid_extensions.insert(E);
- }
-
- file->clear_filters();
- for (const String &E : valid_extensions) {
- file->add_filter("*." + E + " ; " + E.to_upper());
- }
-
- file->popup_file_dialog();
- } break;
-
- case OBJ_MENU_EDIT: {
- Ref<RefCounted> r = v;
-
- if (!r.is_null()) {
- emit_signal(SNAME("resource_edit_request"));
- hide();
- }
- } break;
- case OBJ_MENU_CLEAR: {
- v = Variant();
- emit_signal(SNAME("variant_changed"));
- hide();
- } break;
-
- case OBJ_MENU_MAKE_UNIQUE: {
- Ref<Resource> res_orig = v;
- if (res_orig.is_null()) {
- return;
- }
-
- List<PropertyInfo> property_list;
- res_orig->get_property_list(&property_list);
- List<Pair<String, Variant>> propvalues;
-
- for (const PropertyInfo &pi : property_list) {
- Pair<String, Variant> p;
- if (pi.usage & PROPERTY_USAGE_STORAGE) {
- p.first = pi.name;
- p.second = res_orig->get(pi.name);
- }
-
- propvalues.push_back(p);
- }
-
- String orig_type = res_orig->get_class();
-
- Object *inst = ClassDB::instantiate(orig_type);
-
- Ref<Resource> res = Ref<Resource>(Object::cast_to<Resource>(inst));
-
- ERR_FAIL_COND(res.is_null());
-
- for (const Pair<String, Variant> &p : propvalues) {
- res->set(p.first, p.second);
- }
-
- v = res;
- emit_signal(SNAME("variant_changed"));
- hide();
- } break;
-
- case OBJ_MENU_COPY: {
- EditorSettings::get_singleton()->set_resource_clipboard(v);
-
- } break;
- case OBJ_MENU_PASTE: {
- v = EditorSettings::get_singleton()->get_resource_clipboard();
- emit_signal(SNAME("variant_changed"));
-
- } break;
- case OBJ_MENU_NEW_SCRIPT: {
- if (Object::cast_to<Node>(owner)) {
- SceneTreeDock::get_singleton()->open_script_dialog(Object::cast_to<Node>(owner), false);
- }
-
- } break;
- case OBJ_MENU_EXTEND_SCRIPT: {
- if (Object::cast_to<Node>(owner)) {
- SceneTreeDock::get_singleton()->open_script_dialog(Object::cast_to<Node>(owner), true);
- }
-
- } break;
- case OBJ_MENU_SHOW_IN_FILE_SYSTEM: {
- Ref<Resource> r = v;
- FileSystemDock *file_system_dock = FileSystemDock::get_singleton();
- file_system_dock->navigate_to_path(r->get_path());
- // Ensure that the FileSystem dock is visible.
- TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control();
- tab_container->set_current_tab(tab_container->get_tab_idx_from_control(file_system_dock));
- } break;
- default: {
- if (p_which >= CONVERT_BASE_ID) {
- int to_type = p_which - CONVERT_BASE_ID;
-
- Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(Ref<Resource>(v));
-
- ERR_FAIL_INDEX(to_type, conversions.size());
-
- Ref<Resource> new_res = conversions[to_type]->convert(v);
-
- v = new_res;
- emit_signal(SNAME("variant_changed"));
- break;
- }
- ERR_FAIL_COND(inheritors_array.is_empty());
-
- String intype = inheritors_array[p_which - TYPE_BASE_ID];
-
- if (intype == "ViewportTexture") {
- scene_tree->set_title(TTR("Pick a Viewport"));
- scene_tree->popup_scenetree_dialog();
- picking_viewport = true;
- return;
- }
-
- Variant obj = ClassDB::instantiate(intype);
-
- if (!obj) {
- if (ScriptServer::is_global_class(intype)) {
- obj = EditorNode::get_editor_data().script_class_instance(intype);
- } else {
- obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
- }
- }
-
- ERR_BREAK(!obj);
- Resource *res = Object::cast_to<Resource>(obj);
- ERR_BREAK(!res);
- if (owner && hint == PROPERTY_HINT_RESOURCE_TYPE && hint_text == "Script") {
- //make visual script the right type
- res->call("set_instance_base_type", owner->get_class());
- }
-
- EditorNode::get_editor_data().instantiate_object_properties(obj);
- v = obj;
-
- emit_signal(SNAME("variant_changed"));
-
- } break;
- }
-
- } break;
- default: {
- }
- }
-}
-
-void CustomPropertyEditor::hide_menu() {
- menu->hide();
-}
-
-Variant CustomPropertyEditor::get_variant() const {
- return v;
-}
-
-String CustomPropertyEditor::get_name() const {
- return name;
-}
-
-bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::Type p_type, const Variant &p_variant, int p_hint, String p_hint_text) {
- owner = p_owner;
- updating = true;
- name = p_name;
- v = p_variant;
- field_names.clear();
- hint = p_hint;
- hint_text = p_hint_text;
- type_button->hide();
- if (color_picker) {
- color_picker->hide();
- }
- texture_preview->hide();
- inheritors_array.clear();
- text_edit->hide();
- easing_draw->hide();
- spinbox->hide();
- slider->hide();
- menu->clear();
- menu->reset_size();
-
- for (int i = 0; i < MAX_VALUE_EDITORS; i++) {
- if (i < MAX_VALUE_EDITORS / 4) {
- value_hboxes[i]->hide();
- }
- value_editor[i]->hide();
- value_label[i]->hide();
- if (i < 4) {
- scroll[i]->hide();
- }
- }
-
- for (int i = 0; i < MAX_ACTION_BUTTONS; i++) {
- action_buttons[i]->hide();
- }
-
- checks20gc->hide();
- for (int i = 0; i < 20; i++) {
- checks20[i]->hide();
- }
-
- type = (p_variant.get_type() != Variant::NIL && p_variant.get_type() != Variant::RID && p_type != Variant::OBJECT) ? p_variant.get_type() : p_type;
-
- switch (type) {
- case Variant::BOOL: {
- checks20gc->show();
-
- CheckBox *c = checks20[0];
- c->set_text("True");
- checks20gc->set_position(Vector2(4, 4) * EDSCALE);
- c->set_pressed(v);
- c->show();
-
- checks20gc->set_size(checks20gc->get_minimum_size());
- set_size(checks20gc->get_position() + checks20gc->get_size() + c->get_size() + Vector2(4, 4) * EDSCALE);
-
- } break;
- case Variant::INT:
- case Variant::FLOAT: {
- if (hint == PROPERTY_HINT_RANGE) {
- int c = hint_text.get_slice_count(",");
- float min = 0, max = 100, step = type == Variant::FLOAT ? .01 : 1;
- if (c >= 1) {
- if (!hint_text.get_slice(",", 0).is_empty()) {
- min = hint_text.get_slice(",", 0).to_float();
- }
- }
- if (c >= 2) {
- if (!hint_text.get_slice(",", 1).is_empty()) {
- max = hint_text.get_slice(",", 1).to_float();
- }
- }
-
- if (c >= 3) {
- if (!hint_text.get_slice(",", 2).is_empty()) {
- step = hint_text.get_slice(",", 2).to_float();
- }
- }
-
- if (c >= 4 && hint_text.get_slice(",", 3) == "slider") {
- slider->set_min(min);
- slider->set_max(max);
- slider->set_step(step);
- slider->set_value(v);
- slider->show();
- set_size(Size2(110, 30) * EDSCALE);
- } else {
- spinbox->set_min(min);
- spinbox->set_max(max);
- spinbox->set_step(step);
- spinbox->set_value(v);
- spinbox->show();
- set_size(Size2(70, 35) * EDSCALE);
- }
-
- } else if (hint == PROPERTY_HINT_ENUM) {
- Vector<String> options = hint_text.split(",");
- int current_val = 0;
- for (int i = 0; i < options.size(); i++) {
- Vector<String> text_split = options[i].split(":");
- if (text_split.size() != 1) {
- current_val = text_split[1].to_int();
- }
- menu->add_item(text_split[0]);
- menu->set_item_metadata(i, current_val);
- current_val += 1;
- }
- menu->set_position(get_position());
- menu->popup();
- hide();
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS ||
- hint == PROPERTY_HINT_LAYERS_2D_RENDER ||
- hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION ||
- hint == PROPERTY_HINT_LAYERS_3D_PHYSICS ||
- hint == PROPERTY_HINT_LAYERS_3D_RENDER ||
- hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) {
- String basename;
- switch (hint) {
- case PROPERTY_HINT_LAYERS_2D_RENDER:
- basename = "layer_names/2d_render";
- break;
- case PROPERTY_HINT_LAYERS_2D_PHYSICS:
- basename = "layer_names/2d_physics";
- break;
- case PROPERTY_HINT_LAYERS_2D_NAVIGATION:
- basename = "layer_names/2d_navigation";
- break;
- case PROPERTY_HINT_LAYERS_3D_RENDER:
- basename = "layer_names/3d_render";
- break;
- case PROPERTY_HINT_LAYERS_3D_PHYSICS:
- basename = "layer_names/3d_physics";
- break;
- case PROPERTY_HINT_LAYERS_3D_NAVIGATION:
- basename = "layer_names/3d_navigation";
- break;
- }
-
- checks20gc->show();
- uint32_t flgs = v;
- for (int i = 0; i < 2; i++) {
- Point2 ofs(4, 4);
- ofs.y += 22 * i;
- for (int j = 0; j < 10; j++) {
- int idx = i * 10 + j;
- CheckBox *c = checks20[idx];
- c->set_text(ProjectSettings::get_singleton()->get(basename + "/layer_" + itos(idx + 1)));
- c->set_pressed(flgs & (1 << (i * 10 + j)));
- c->show();
- }
- }
-
- show();
-
- checks20gc->set_position(Vector2(4, 4) * EDSCALE);
- checks20gc->set_size(checks20gc->get_minimum_size());
-
- set_size(Vector2(4, 4) * EDSCALE + checks20gc->get_position() + checks20gc->get_size());
-
- } else if (hint == PROPERTY_HINT_EXP_EASING) {
- easing_draw->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 5 * EDSCALE);
- easing_draw->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -5 * EDSCALE);
- easing_draw->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_BEGIN, 5 * EDSCALE);
- easing_draw->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -30 * EDSCALE);
- type_button->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 3 * EDSCALE);
- type_button->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -3 * EDSCALE);
- type_button->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_END, -25 * EDSCALE);
- type_button->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -7 * EDSCALE);
- type_button->set_text(TTR("Preset..."));
- type_button->get_popup()->clear();
- type_button->get_popup()->add_item(TTR("Linear"), EASING_LINEAR);
- type_button->get_popup()->add_item(TTR("Ease In"), EASING_EASE_IN);
- type_button->get_popup()->add_item(TTR("Ease Out"), EASING_EASE_OUT);
- if (hint_text != "attenuation") {
- type_button->get_popup()->add_item(TTR("Zero"), EASING_ZERO);
- type_button->get_popup()->add_item(TTR("Easing In-Out"), EASING_IN_OUT);
- type_button->get_popup()->add_item(TTR("Easing Out-In"), EASING_OUT_IN);
- }
-
- type_button->show();
- easing_draw->show();
- set_size(Size2(200, 150) * EDSCALE);
- } else if (hint == PROPERTY_HINT_FLAGS) {
- Vector<String> flags = hint_text.split(",");
- uint32_t value = v;
- for (int i = 0; i < flags.size(); i++) {
- uint32_t current_val;
- Vector<String> text_split = flags[i].split(":");
- if (text_split.size() != 1) {
- current_val = text_split[1].to_int();
- } else {
- current_val = 1 << i;
- }
- menu->add_check_item(text_split[0], current_val);
- menu->set_item_metadata(i, current_val);
- if ((value & current_val) == current_val) {
- menu->set_item_checked(menu->get_item_index(current_val), true);
- }
- }
- menu->set_position(get_position());
- menu->popup();
- hide();
- updating = false;
- return false;
-
- } else {
- List<String> names;
- names.push_back("value:");
- config_value_editors(1, 1, 50, names);
- value_editor[0]->set_text(TS->format_number(String::num(v)));
- }
-
- } break;
- case Variant::STRING: {
- if (hint == PROPERTY_HINT_LOCALE_ID) {
- List<String> names;
- names.push_back(TTR("Locale..."));
- names.push_back(TTR("Clear"));
- config_action_buttons(names);
- } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) {
- List<String> names;
- names.push_back(TTR("File..."));
- names.push_back(TTR("Clear"));
- config_action_buttons(names);
- } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) {
- List<String> names;
- names.push_back(TTR("Dir..."));
- names.push_back(TTR("Clear"));
- config_action_buttons(names);
- } else if (hint == PROPERTY_HINT_ENUM) {
- Vector<String> options = hint_text.split(",");
- for (int i = 0; i < options.size(); i++) {
- menu->add_item(options[i], i);
- }
- menu->set_position(get_position());
- menu->popup();
- hide();
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_MULTILINE_TEXT) {
- text_edit->show();
- text_edit->set_text(v);
- text_edit->deselect();
-
- int button_margin = text_edit->get_theme_constant(SNAME("button_margin"), SNAME("Dialogs"));
- int margin = text_edit->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
-
- action_buttons[0]->set_anchor(SIDE_LEFT, Control::ANCHOR_END);
- action_buttons[0]->set_anchor(SIDE_TOP, Control::ANCHOR_END);
- action_buttons[0]->set_anchor(SIDE_RIGHT, Control::ANCHOR_END);
- action_buttons[0]->set_anchor(SIDE_BOTTOM, Control::ANCHOR_END);
- action_buttons[0]->set_begin(Point2(-70 * EDSCALE, -button_margin + 5 * EDSCALE));
- action_buttons[0]->set_end(Point2(-margin, -margin));
- action_buttons[0]->set_text(TTR("Close"));
- action_buttons[0]->show();
-
- } else if (hint == PROPERTY_HINT_TYPE_STRING) {
- if (!create_dialog) {
- create_dialog = memnew(CreateDialog);
- create_dialog->connect("create", callable_mp(this, &CustomPropertyEditor::_create_dialog_callback));
- add_child(create_dialog);
- }
-
- if (!hint_text.is_empty()) {
- create_dialog->set_base_type(hint_text);
- } else {
- create_dialog->set_base_type("Object");
- }
-
- create_dialog->popup_create(false);
- hide();
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_METHOD_OF_VARIANT_TYPE) {
-#define MAKE_PROPSELECT \
- if (!property_select) { \
- property_select = memnew(PropertySelector); \
- property_select->connect("selected", callable_mp(this, &CustomPropertyEditor::_create_selected_property)); \
- add_child(property_select); \
- } \
- hide();
-
- MAKE_PROPSELECT;
-
- Variant::Type type = Variant::NIL;
- for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- if (hint_text == Variant::get_type_name(Variant::Type(i))) {
- type = Variant::Type(i);
- }
- }
- if (type != Variant::NIL) {
- property_select->select_method_from_basic_type(type, v);
- }
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_METHOD_OF_BASE_TYPE) {
- MAKE_PROPSELECT
-
- property_select->select_method_from_base_type(hint_text, v);
-
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_METHOD_OF_INSTANCE) {
- MAKE_PROPSELECT
-
- Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int()));
- if (instance) {
- property_select->select_method_from_instance(instance, v);
- }
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_METHOD_OF_SCRIPT) {
- MAKE_PROPSELECT
-
- Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int()));
- if (Object::cast_to<Script>(obj)) {
- property_select->select_method_from_script(Object::cast_to<Script>(obj), v);
- }
-
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE) {
- MAKE_PROPSELECT
- Variant::Type type = Variant::NIL;
- String tname = hint_text;
- if (tname.contains(".")) {
- tname = tname.get_slice(".", 0);
- }
- for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- if (tname == Variant::get_type_name(Variant::Type(i))) {
- type = Variant::Type(Variant::Type(i));
- }
- }
-
- if (type != Variant::NIL) {
- property_select->select_property_from_basic_type(type, v);
- }
-
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_PROPERTY_OF_BASE_TYPE) {
- MAKE_PROPSELECT
-
- property_select->select_property_from_base_type(hint_text, v);
-
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_PROPERTY_OF_INSTANCE) {
- MAKE_PROPSELECT
-
- Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int()));
- if (instance) {
- property_select->select_property_from_instance(instance, v);
- }
-
- updating = false;
- return false;
-
- } else if (hint == PROPERTY_HINT_PROPERTY_OF_SCRIPT) {
- MAKE_PROPSELECT
-
- Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int()));
- if (Object::cast_to<Script>(obj)) {
- property_select->select_property_from_script(Object::cast_to<Script>(obj), v);
- }
-
- updating = false;
- return false;
-
- } else {
- List<String> names;
- names.push_back("string:");
- config_value_editors(1, 1, 50, names);
- value_editor[0]->set_text(v);
- }
-
- } break;
- case Variant::VECTOR2: {
- field_names.push_back("x");
- field_names.push_back("y");
- config_value_editors(2, 2, 10, field_names);
- Vector2 vec = v;
- value_editor[0]->set_text(String::num(vec.x));
- value_editor[1]->set_text(String::num(vec.y));
- } break;
- case Variant::RECT2: {
- field_names.push_back("x");
- field_names.push_back("y");
- field_names.push_back("w");
- field_names.push_back("h");
- config_value_editors(4, 4, 10, field_names);
- Rect2 r = v;
- value_editor[0]->set_text(String::num(r.position.x));
- value_editor[1]->set_text(String::num(r.position.y));
- value_editor[2]->set_text(String::num(r.size.x));
- value_editor[3]->set_text(String::num(r.size.y));
- } break;
- case Variant::VECTOR3: {
- field_names.push_back("x");
- field_names.push_back("y");
- field_names.push_back("z");
- config_value_editors(3, 3, 10, field_names);
- Vector3 vec = v;
- value_editor[0]->set_text(String::num(vec.x));
- value_editor[1]->set_text(String::num(vec.y));
- value_editor[2]->set_text(String::num(vec.z));
- } break;
- case Variant::PLANE: {
- field_names.push_back("x");
- field_names.push_back("y");
- field_names.push_back("z");
- field_names.push_back("d");
- config_value_editors(4, 4, 10, field_names);
- Plane plane = v;
- value_editor[0]->set_text(String::num(plane.normal.x));
- value_editor[1]->set_text(String::num(plane.normal.y));
- value_editor[2]->set_text(String::num(plane.normal.z));
- value_editor[3]->set_text(String::num(plane.d));
-
- } break;
- case Variant::QUATERNION: {
- field_names.push_back("x");
- field_names.push_back("y");
- field_names.push_back("z");
- field_names.push_back("w");
- config_value_editors(4, 4, 10, field_names);
- Quaternion q = v;
- value_editor[0]->set_text(String::num(q.x));
- value_editor[1]->set_text(String::num(q.y));
- value_editor[2]->set_text(String::num(q.z));
- value_editor[3]->set_text(String::num(q.w));
-
- } break;
- case Variant::AABB: {
- field_names.push_back("px");
- field_names.push_back("py");
- field_names.push_back("pz");
- field_names.push_back("sx");
- field_names.push_back("sy");
- field_names.push_back("sz");
- config_value_editors(6, 3, 16, field_names);
-
- AABB aabb = v;
- value_editor[0]->set_text(String::num(aabb.position.x));
- value_editor[1]->set_text(String::num(aabb.position.y));
- value_editor[2]->set_text(String::num(aabb.position.z));
- value_editor[3]->set_text(String::num(aabb.size.x));
- value_editor[4]->set_text(String::num(aabb.size.y));
- value_editor[5]->set_text(String::num(aabb.size.z));
-
- } break;
- case Variant::TRANSFORM2D: {
- field_names.push_back("xx");
- field_names.push_back("xy");
- field_names.push_back("yx");
- field_names.push_back("yy");
- field_names.push_back("ox");
- field_names.push_back("oy");
- config_value_editors(6, 2, 16, field_names);
-
- Transform2D basis = v;
- for (int i = 0; i < 6; i++) {
- value_editor[i]->set_text(String::num(basis.columns[i / 2][i % 2]));
- }
-
- } break;
- case Variant::BASIS: {
- field_names.push_back("xx");
- field_names.push_back("xy");
- field_names.push_back("xz");
- field_names.push_back("yx");
- field_names.push_back("yy");
- field_names.push_back("yz");
- field_names.push_back("zx");
- field_names.push_back("zy");
- field_names.push_back("zz");
- config_value_editors(9, 3, 16, field_names);
-
- Basis basis = v;
- for (int i = 0; i < 9; i++) {
- value_editor[i]->set_text(String::num(basis.rows[i / 3][i % 3]));
- }
-
- } break;
- case Variant::TRANSFORM3D: {
- field_names.push_back("xx");
- field_names.push_back("xy");
- field_names.push_back("xz");
- field_names.push_back("xo");
- field_names.push_back("yx");
- field_names.push_back("yy");
- field_names.push_back("yz");
- field_names.push_back("yo");
- field_names.push_back("zx");
- field_names.push_back("zy");
- field_names.push_back("zz");
- field_names.push_back("zo");
- config_value_editors(12, 4, 16, field_names);
-
- Transform3D tr = v;
- for (int i = 0; i < 9; i++) {
- value_editor[(i / 3) * 4 + i % 3]->set_text(String::num(tr.basis.rows[i / 3][i % 3]));
- }
-
- value_editor[3]->set_text(String::num(tr.origin.x));
- value_editor[7]->set_text(String::num(tr.origin.y));
- value_editor[11]->set_text(String::num(tr.origin.z));
-
- } break;
- case Variant::COLOR: {
- if (!color_picker) {
- //late init for performance
- color_picker = memnew(ColorPicker);
- color_picker->set_deferred_mode(true);
- value_vbox->add_child(color_picker);
- color_picker->hide();
- color_picker->connect("color_changed", callable_mp(this, &CustomPropertyEditor::_color_changed));
-
- // 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);
- }
-
- int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape");
- color_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape);
- }
-
- color_picker->show();
- color_picker->set_edit_alpha(hint != PROPERTY_HINT_COLOR_NO_ALPHA);
- color_picker->set_pick_color(v);
- color_picker->set_focus_on_line_edit();
-
- } break;
-
- case Variant::NODE_PATH: {
- List<String> names;
- names.push_back(TTR("Assign"));
- names.push_back(TTR("Clear"));
-
- if (owner && owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) {
- names.push_back(TTR("Select Node"));
- }
-
- config_action_buttons(names);
-
- } break;
- case Variant::OBJECT: {
- if (hint != PROPERTY_HINT_RESOURCE_TYPE) {
- break;
- }
-
- if (p_name == "script" && hint_text == "Script" && Object::cast_to<Node>(owner)) {
- menu->add_item(TTR("New Script"), OBJ_MENU_NEW_SCRIPT);
- menu->add_separator();
- } else if (!hint_text.is_empty()) {
- int idx = 0;
-
- Vector<EditorData::CustomType> custom_resources;
-
- if (EditorNode::get_editor_data().get_custom_types().has("Resource")) {
- custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"];
- }
-
- for (int i = 0; i < hint_text.get_slice_count(","); i++) {
- String base = hint_text.get_slice(",", i);
-
- HashSet<String> valid_inheritors;
- valid_inheritors.insert(base);
- List<StringName> inheritors;
- ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors);
-
- for (int j = 0; j < custom_resources.size(); j++) {
- inheritors.push_back(custom_resources[j].name);
- }
-
- List<StringName>::Element *E = inheritors.front();
- while (E) {
- valid_inheritors.insert(E->get());
- E = E->next();
- }
-
- for (const String &j : valid_inheritors) {
- const String &t = j;
-
- bool is_custom_resource = false;
- Ref<Texture2D> icon;
- if (!custom_resources.is_empty()) {
- for (int k = 0; k < custom_resources.size(); k++) {
- if (custom_resources[k].name == t) {
- is_custom_resource = true;
- if (custom_resources[k].icon.is_valid()) {
- icon = custom_resources[k].icon;
- }
- break;
- }
- }
- }
-
- if (!is_custom_resource && (!ClassDB::can_instantiate(t) || ClassDB::is_virtual(t))) {
- continue;
- }
-
- inheritors_array.push_back(t);
-
- int id = TYPE_BASE_ID + idx;
-
- menu->add_item(vformat(TTR("New %s"), t), id);
-
- idx++;
- }
- }
-
- if (menu->get_item_count()) {
- menu->add_separator();
- }
- }
-
- menu->add_item(TTR("Load"), OBJ_MENU_LOAD);
-
- if (!Ref<Resource>(v).is_null()) {
- menu->add_item(TTR("Edit"), OBJ_MENU_EDIT);
- menu->add_item(TTR("Clear"), OBJ_MENU_CLEAR);
- menu->add_item(TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
-
- Ref<Resource> r = v;
- if (r.is_valid() && r->get_path().is_resource_file()) {
- menu->add_separator();
- menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM);
- }
- }
-
- Ref<Resource> cb = EditorSettings::get_singleton()->get_resource_clipboard();
- bool paste_valid = false;
- if (cb.is_valid()) {
- if (hint_text.is_empty()) {
- paste_valid = true;
- } else {
- for (int i = 0; i < hint_text.get_slice_count(","); i++) {
- if (ClassDB::is_parent_class(cb->get_class(), hint_text.get_slice(",", i))) {
- paste_valid = true;
- break;
- }
- }
- }
- }
-
- if (!Ref<Resource>(v).is_null() || paste_valid) {
- menu->add_separator();
-
- if (!Ref<Resource>(v).is_null()) {
- menu->add_item(TTR("Copy"), OBJ_MENU_COPY);
- }
-
- if (paste_valid) {
- menu->add_item(TTR("Paste"), OBJ_MENU_PASTE);
- }
- }
-
- if (!Ref<Resource>(v).is_null()) {
- Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(Ref<Resource>(v));
- if (conversions.size()) {
- menu->add_separator();
- }
- for (int i = 0; i < conversions.size(); i++) {
- String what = conversions[i]->converts_to();
- menu->add_item(vformat(TTR("Convert to %s"), what), CONVERT_BASE_ID + i);
- }
- }
-
- menu->set_position(get_position());
- menu->popup();
- hide();
- updating = false;
- return false;
- } break;
- case Variant::DICTIONARY: {
- } break;
- case Variant::PACKED_BYTE_ARRAY: {
- } break;
- case Variant::PACKED_INT32_ARRAY: {
- } break;
- case Variant::PACKED_FLOAT32_ARRAY: {
- } break;
- case Variant::PACKED_INT64_ARRAY: {
- } break;
- case Variant::PACKED_FLOAT64_ARRAY: {
- } break;
- case Variant::PACKED_STRING_ARRAY: {
- } break;
- case Variant::PACKED_VECTOR3_ARRAY: {
- } break;
- case Variant::PACKED_COLOR_ARRAY: {
- } break;
- default: {
- }
- }
-
- updating = false;
- return true;
-}
-
-void CustomPropertyEditor::_file_selected(String p_file) {
- switch (type) {
- case Variant::STRING: {
- if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_DIR) {
- v = ProjectSettings::get_singleton()->localize_path(p_file);
- emit_signal(SNAME("variant_changed"));
- hide();
- }
-
- if (hint == PROPERTY_HINT_GLOBAL_FILE || hint == PROPERTY_HINT_GLOBAL_DIR) {
- v = p_file;
- emit_signal(SNAME("variant_changed"));
- hide();
- }
-
- } break;
- case Variant::OBJECT: {
- String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String();
-
- Ref<Resource> res = ResourceLoader::load(p_file, type);
- if (res.is_null()) {
- error->set_text(TTR("Error loading file: Not a resource!"));
- error->popup_centered();
- break;
- }
- v = res;
- emit_signal(SNAME("variant_changed"));
- hide();
- } break;
- default: {
- }
- }
-}
-
-void CustomPropertyEditor::_locale_selected(String p_locale) {
- if (type == Variant::STRING && hint == PROPERTY_HINT_LOCALE_ID) {
- v = p_locale;
- emit_signal(SNAME("variant_changed"));
- hide();
- }
-}
-
-void CustomPropertyEditor::_type_create_selected(int p_idx) {
- if (type == Variant::INT || type == Variant::FLOAT) {
- float newval = 0;
- switch (p_idx) {
- case EASING_LINEAR: {
- newval = 1;
- } break;
- case EASING_EASE_IN: {
- newval = 2.0;
- } break;
- case EASING_EASE_OUT: {
- newval = 0.5;
- } break;
- case EASING_ZERO: {
- newval = 0;
- } break;
- case EASING_IN_OUT: {
- newval = -0.5;
- } break;
- case EASING_OUT_IN: {
- newval = -2.0;
- } break;
- }
-
- v = newval;
- emit_signal(SNAME("variant_changed"));
- easing_draw->update();
-
- } else if (type == Variant::OBJECT) {
- ERR_FAIL_INDEX(p_idx, inheritors_array.size());
-
- String intype = inheritors_array[p_idx];
-
- Variant obj = ClassDB::instantiate(intype);
-
- if (!obj) {
- if (ScriptServer::is_global_class(intype)) {
- obj = EditorNode::get_editor_data().script_class_instance(intype);
- } else {
- obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
- }
- }
-
- ERR_FAIL_COND(!obj);
- ERR_FAIL_COND(!Object::cast_to<Resource>(obj));
-
- EditorNode::get_editor_data().instantiate_object_properties(obj);
- v = obj;
-
- emit_signal(SNAME("variant_changed"));
- hide();
- }
-}
-
-void CustomPropertyEditor::_color_changed(const Color &p_color) {
- v = p_color;
- emit_signal(SNAME("variant_changed"));
-}
-
-void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
- if (picking_viewport) {
- Node *to_node = get_node(p_path);
- if (!Object::cast_to<Viewport>(to_node)) {
- EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!"));
- return;
- }
-
- Ref<ViewportTexture> vt;
- vt.instantiate();
- vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node));
- vt->setup_local_to_scene();
- v = vt;
- emit_signal(SNAME("variant_changed"));
- return;
- }
-
- if (hint == PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && !hint_text.is_empty()) {
- Node *node = get_node(hint_text);
- if (node) {
- Node *tonode = node->get_node(p_path);
- if (tonode) {
- p_path = node->get_path_to(tonode);
- }
- }
-
- } else if (owner) {
- Node *node = nullptr;
-
- if (owner->is_class("Node")) {
- node = Object::cast_to<Node>(owner);
- } else if (owner->is_class("ArrayPropertyEdit")) {
- node = Object::cast_to<ArrayPropertyEdit>(owner)->get_node();
- } else if (owner->is_class("DictionaryPropertyEdit")) {
- node = Object::cast_to<DictionaryPropertyEdit>(owner)->get_node();
- }
- if (!node) {
- v = p_path;
- emit_signal(SNAME("variant_changed"));
- call_deferred(SNAME("hide")); //to not mess with dialogs
- return;
- }
-
- Node *tonode = node->get_node(p_path);
- if (tonode) {
- p_path = node->get_path_to(tonode);
- }
- }
-
- v = p_path;
- emit_signal(SNAME("variant_changed"));
- call_deferred(SNAME("hide")); //to not mess with dialogs
-}
-
-void CustomPropertyEditor::_action_pressed(int p_which) {
- if (updating) {
- return;
- }
-
- switch (type) {
- case Variant::BOOL: {
- v = checks20[0]->is_pressed();
- emit_signal(SNAME("variant_changed"));
- } break;
- case Variant::INT: {
- if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS ||
- hint == PROPERTY_HINT_LAYERS_2D_RENDER ||
- hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION ||
- hint == PROPERTY_HINT_LAYERS_3D_PHYSICS ||
- hint == PROPERTY_HINT_LAYERS_3D_RENDER ||
- hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) {
- uint32_t f = v;
- if (checks20[p_which]->is_pressed()) {
- f |= (1 << p_which);
- } else {
- f &= ~(1 << p_which);
- }
-
- v = f;
- emit_signal(SNAME("variant_changed"));
- }
-
- } break;
- case Variant::STRING: {
- if (hint == PROPERTY_HINT_MULTILINE_TEXT) {
- hide();
- } else if (hint == PROPERTY_HINT_LOCALE_ID) {
- locale->popup_locale_dialog();
- } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) {
- if (p_which == 0) {
- if (hint == PROPERTY_HINT_FILE) {
- file->set_access(EditorFileDialog::ACCESS_RESOURCES);
- } else {
- file->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- }
-
- file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
- file->clear_filters();
-
- file->clear_filters();
-
- if (!hint_text.is_empty()) {
- Vector<String> extensions = hint_text.split(",");
- for (int i = 0; i < extensions.size(); i++) {
- String filter = extensions[i];
- if (filter.begins_with(".")) {
- filter = "*" + extensions[i];
- } else if (!filter.begins_with("*")) {
- filter = "*." + extensions[i];
- }
-
- file->add_filter(filter + " ; " + extensions[i].to_upper());
- }
- }
- file->popup_file_dialog();
- } else {
- v = "";
- emit_signal(SNAME("variant_changed"));
- hide();
- }
-
- } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) {
- if (p_which == 0) {
- if (hint == PROPERTY_HINT_DIR) {
- file->set_access(EditorFileDialog::ACCESS_RESOURCES);
- } else {
- file->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- }
- file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR);
- file->clear_filters();
- file->popup_file_dialog();
- } else {
- v = "";
- emit_signal(SNAME("variant_changed"));
- hide();
- }
- }
-
- } break;
- case Variant::NODE_PATH: {
- if (p_which == 0) {
- picking_viewport = false;
- scene_tree->set_title(TTR("Pick a Node"));
- scene_tree->popup_scenetree_dialog();
-
- } else if (p_which == 1) {
- v = NodePath();
- emit_signal(SNAME("variant_changed"));
- hide();
- } else if (p_which == 2) {
- if (owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) {
- Node *target_node = Object::cast_to<Node>(owner)->get_node(v);
- EditorNode::get_singleton()->get_editor_selection()->clear();
- SceneTreeDock::get_singleton()->set_selected(target_node);
- }
-
- hide();
- }
-
- } break;
- case Variant::OBJECT: {
- if (p_which == 0) {
- ERR_FAIL_COND(inheritors_array.is_empty());
-
- String intype = inheritors_array[0];
-
- if (hint == PROPERTY_HINT_RESOURCE_TYPE) {
- Variant obj = ClassDB::instantiate(intype);
-
- if (!obj) {
- if (ScriptServer::is_global_class(intype)) {
- obj = EditorNode::get_editor_data().script_class_instance(intype);
- } else {
- obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
- }
- }
-
- ERR_BREAK(!obj);
- ERR_BREAK(!Object::cast_to<Resource>(obj));
-
- EditorNode::get_editor_data().instantiate_object_properties(obj);
- v = obj;
-
- emit_signal(SNAME("variant_changed"));
- hide();
- }
- } else if (p_which == 1) {
- file->set_access(EditorFileDialog::ACCESS_RESOURCES);
- file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
- List<String> extensions;
- String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String();
-
- ResourceLoader::get_recognized_extensions_for_type(type, &extensions);
- file->clear_filters();
- for (const String &E : extensions) {
- file->add_filter("*." + E + " ; " + E.to_upper());
- }
-
- file->popup_file_dialog();
-
- } else if (p_which == 2) {
- Ref<Resource> r = v;
-
- if (!r.is_null()) {
- emit_signal(SNAME("resource_edit_request"));
- hide();
- }
-
- } else if (p_which == 3) {
- v = Variant();
- emit_signal(SNAME("variant_changed"));
- hide();
- } else if (p_which == 4) {
- Ref<Resource> res_orig = v;
- if (res_orig.is_null()) {
- return;
- }
-
- List<PropertyInfo> property_list;
- res_orig->get_property_list(&property_list);
- List<Pair<String, Variant>> propvalues;
-
- for (const PropertyInfo &pi : property_list) {
- Pair<String, Variant> p;
- if (pi.usage & PROPERTY_USAGE_STORAGE) {
- p.first = pi.name;
- p.second = res_orig->get(pi.name);
- }
-
- propvalues.push_back(p);
- }
-
- Ref<Resource> res = Ref<Resource>(ClassDB::instantiate(res_orig->get_class()));
-
- ERR_FAIL_COND(res.is_null());
-
- for (const Pair<String, Variant> &p : propvalues) {
- res->set(p.first, p.second);
- }
-
- v = res;
- emit_signal(SNAME("variant_changed"));
- hide();
- }
-
- } break;
-
- default: {
- };
- }
-}
-
-void CustomPropertyEditor::_drag_easing(const Ref<InputEvent> &p_ev) {
- Ref<InputEventMouseMotion> mm = p_ev;
-
- if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
- float rel = mm->get_relative().x;
- if (rel == 0) {
- return;
- }
-
- bool flip = hint_text == "attenuation";
-
- if (flip) {
- rel = -rel;
- }
-
- float val = v;
- if (val == 0) {
- return;
- }
- bool sg = val < 0;
- val = Math::absf(val);
-
- val = Math::log(val) / Math::log((float)2.0);
- //logspace
- val += rel * 0.05;
-
- val = Math::pow(2.0f, val);
- if (sg) {
- val = -val;
- }
-
- v = val;
- easing_draw->update();
- emit_signal(SNAME("variant_changed"));
- }
-}
-
-void CustomPropertyEditor::_draw_easing() {
- RID ci = easing_draw->get_canvas_item();
-
- Size2 s = easing_draw->get_size();
- Rect2 r(Point2(), s);
- r = r.grow(3);
- easing_draw->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"))->draw(ci, r);
-
- int points = 48;
-
- float prev = 1.0;
- float exp = v;
- bool flip = hint_text == "attenuation";
-
- Ref<Font> f = easing_draw->get_theme_font(SNAME("font"), SNAME("Label"));
- int font_size = easing_draw->get_theme_font_size(SNAME("font_size"), SNAME("Label"));
- Color color = easing_draw->get_theme_color(SNAME("font_color"), SNAME("Label"));
-
- for (int i = 1; i <= points; i++) {
- float ifl = i / float(points);
- float iflp = (i - 1) / float(points);
-
- float h = 1.0 - Math::ease(ifl, exp);
-
- if (flip) {
- ifl = 1.0 - ifl;
- iflp = 1.0 - iflp;
- }
-
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(iflp * s.width, prev * s.height), Point2(ifl * s.width, h * s.height), color);
- prev = h;
- }
-
- f->draw_string(ci, Point2(10, 10 + f->get_ascent(font_size)), String::num(exp, 2), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color);
-}
-
-void CustomPropertyEditor::_text_edit_changed() {
- v = text_edit->get_text();
- emit_signal(SNAME("variant_changed"));
-}
-
-void CustomPropertyEditor::_create_dialog_callback() {
- v = create_dialog->get_selected_type();
- emit_signal(SNAME("variant_changed"));
-}
-
-void CustomPropertyEditor::_create_selected_property(const String &p_prop) {
- v = p_prop;
- emit_signal(SNAME("variant_changed"));
-}
-
-void CustomPropertyEditor::_modified(String p_string) {
- if (updating) {
- return;
- }
-
- Variant prev_v = v;
-
- updating = true;
- switch (type) {
- case Variant::INT: {
- String text = TS->parse_number(value_editor[0]->get_text());
- Ref<Expression> expr;
- expr.instantiate();
- Error err = expr->parse(text);
- if (err != OK) {
- v = value_editor[0]->get_text().to_int();
- return;
- } else {
- v = expr->execute(Array(), nullptr, false, false);
- }
-
- if (v != prev_v) {
- emit_signal(SNAME("variant_changed"));
- }
- } break;
- case Variant::FLOAT: {
- if (hint != PROPERTY_HINT_EXP_EASING) {
- String text = TS->parse_number(value_editor[0]->get_text());
- v = _parse_real_expression(text);
- if (v != prev_v) {
- emit_signal(SNAME("variant_changed"));
- }
- }
-
- } break;
- case Variant::STRING: {
- v = value_editor[0]->get_text();
- emit_signal(SNAME("variant_changed"));
- } break;
- case Variant::VECTOR2: {
- Vector2 vec;
- vec.x = _parse_real_expression(value_editor[0]->get_text());
- vec.y = _parse_real_expression(value_editor[1]->get_text());
- v = vec;
- if (v != prev_v) {
- _emit_changed_whole_or_field();
- }
-
- } break;
- case Variant::RECT2: {
- Rect2 r2;
-
- r2.position.x = _parse_real_expression(value_editor[0]->get_text());
- r2.position.y = _parse_real_expression(value_editor[1]->get_text());
- r2.size.x = _parse_real_expression(value_editor[2]->get_text());
- r2.size.y = _parse_real_expression(value_editor[3]->get_text());
- v = r2;
- if (v != prev_v) {
- _emit_changed_whole_or_field();
- }
-
- } break;
-
- case Variant::VECTOR3: {
- Vector3 vec;
- vec.x = _parse_real_expression(value_editor[0]->get_text());
- vec.y = _parse_real_expression(value_editor[1]->get_text());
- vec.z = _parse_real_expression(value_editor[2]->get_text());
- v = vec;
- if (v != prev_v) {
- _emit_changed_whole_or_field();
- }
-
- } break;
- case Variant::PLANE: {
- Plane pl;
- pl.normal.x = _parse_real_expression(value_editor[0]->get_text());
- pl.normal.y = _parse_real_expression(value_editor[1]->get_text());
- pl.normal.z = _parse_real_expression(value_editor[2]->get_text());
- pl.d = _parse_real_expression(value_editor[3]->get_text());
- v = pl;
- if (v != prev_v) {
- _emit_changed_whole_or_field();
- }
-
- } break;
- case Variant::QUATERNION: {
- Quaternion q;
- q.x = _parse_real_expression(value_editor[0]->get_text());
- q.y = _parse_real_expression(value_editor[1]->get_text());
- q.z = _parse_real_expression(value_editor[2]->get_text());
- q.w = _parse_real_expression(value_editor[3]->get_text());
- v = q;
- if (v != prev_v) {
- _emit_changed_whole_or_field();
- }
-
- } break;
- case Variant::AABB: {
- Vector3 pos;
- Vector3 size;
-
- pos.x = _parse_real_expression(value_editor[0]->get_text());
- pos.y = _parse_real_expression(value_editor[1]->get_text());
- pos.z = _parse_real_expression(value_editor[2]->get_text());
- size.x = _parse_real_expression(value_editor[3]->get_text());
- size.y = _parse_real_expression(value_editor[4]->get_text());
- size.z = _parse_real_expression(value_editor[5]->get_text());
- v = AABB(pos, size);
- if (v != prev_v) {
- _emit_changed_whole_or_field();
- }
-
- } break;
- case Variant::TRANSFORM2D: {
- Transform2D m;
- for (int i = 0; i < 6; i++) {
- m.columns[i / 2][i % 2] = _parse_real_expression(value_editor[i]->get_text());
- }
-
- v = m;
- if (v != prev_v) {
- _emit_changed_whole_or_field();
- }
-
- } break;
- case Variant::BASIS: {
- Basis m;
- for (int i = 0; i < 9; i++) {
- m.rows[i / 3][i % 3] = _parse_real_expression(value_editor[i]->get_text());
- }
-
- v = m;
- if (v != prev_v) {
- _emit_changed_whole_or_field();
- }
-
- } break;
- case Variant::TRANSFORM3D: {
- Basis basis;
- for (int i = 0; i < 9; i++) {
- basis.rows[i / 3][i % 3] = _parse_real_expression(value_editor[(i / 3) * 4 + i % 3]->get_text());
- }
-
- Vector3 origin;
-
- origin.x = _parse_real_expression(value_editor[3]->get_text());
- origin.y = _parse_real_expression(value_editor[7]->get_text());
- origin.z = _parse_real_expression(value_editor[11]->get_text());
-
- v = Transform3D(basis, origin);
- if (v != prev_v) {
- _emit_changed_whole_or_field();
- }
-
- } break;
- case Variant::COLOR: {
- } break;
-
- case Variant::NODE_PATH: {
- v = NodePath(value_editor[0]->get_text());
- if (v != prev_v) {
- emit_signal(SNAME("variant_changed"));
- }
- } break;
- case Variant::DICTIONARY: {
- } break;
- case Variant::PACKED_BYTE_ARRAY: {
- } break;
- case Variant::PACKED_INT32_ARRAY: {
- } break;
- case Variant::PACKED_FLOAT32_ARRAY: {
- } break;
- case Variant::PACKED_STRING_ARRAY: {
- } break;
- case Variant::PACKED_VECTOR3_ARRAY: {
- } break;
- case Variant::PACKED_COLOR_ARRAY: {
- } break;
- default: {
- }
- }
-
- updating = false;
-}
-
-real_t CustomPropertyEditor::_parse_real_expression(String text) {
- Ref<Expression> expr;
- expr.instantiate();
- Error err = expr->parse(text);
- real_t out;
- if (err != OK) {
- out = value_editor[0]->get_text().to_float();
- } else {
- out = expr->execute(Array(), nullptr, false, true);
- }
- return out;
-}
-
-void CustomPropertyEditor::_emit_changed_whole_or_field() {
- if (!Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
- emit_signal(SNAME("variant_changed"));
- } else {
- emit_signal(SNAME("variant_field_changed"), field_names[focused_value_editor]);
- }
-}
-
-void CustomPropertyEditor::_range_modified(double p_value) {
- v = p_value;
- emit_signal(SNAME("variant_changed"));
-}
-
-void CustomPropertyEditor::_focus_enter() {
- switch (type) {
- case Variant::FLOAT:
- case Variant::STRING:
- case Variant::VECTOR2:
- case Variant::RECT2:
- case Variant::VECTOR3:
- case Variant::PLANE:
- case Variant::QUATERNION:
- case Variant::AABB:
- case Variant::TRANSFORM2D:
- case Variant::BASIS:
- case Variant::TRANSFORM3D: {
- for (int i = 0; i < MAX_VALUE_EDITORS; ++i) {
- if (value_editor[i]->has_focus()) {
- focused_value_editor = i;
- value_editor[i]->select_all();
- break;
- }
- }
- } break;
- default: {
- }
- }
-}
-
-void CustomPropertyEditor::_focus_exit() {
- _modified(String());
-}
-
-void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) {
- Ref<StyleBox> sb = action_buttons[0]->get_theme_stylebox(SNAME("button"));
- int margin_top = sb->get_margin(SIDE_TOP);
- int margin_left = sb->get_margin(SIDE_LEFT);
- int margin_bottom = sb->get_margin(SIDE_BOTTOM);
- int margin_right = sb->get_margin(SIDE_RIGHT);
-
- int max_width = 0;
- int height = 0;
-
- for (int i = 0; i < MAX_ACTION_BUTTONS; i++) {
- if (i < p_strings.size()) {
- action_buttons[i]->show();
- action_buttons[i]->set_text(p_strings[i]);
-
- Size2 btn_m_size = action_buttons[i]->get_minimum_size();
- if (btn_m_size.width > max_width) {
- max_width = btn_m_size.width;
- }
-
- } else {
- action_buttons[i]->hide();
- }
- }
-
- for (int i = 0; i < p_strings.size(); i++) {
- Size2 btn_m_size = action_buttons[i]->get_size();
- action_buttons[i]->set_position(Point2(0, height) + Point2(margin_left, margin_top));
- action_buttons[i]->set_size(Size2(max_width, btn_m_size.height));
-
- height += btn_m_size.height;
- }
- set_size(Size2(max_width, height) + Size2(margin_left + margin_right, margin_top + margin_bottom));
-}
-
-void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns, int p_label_w, const List<String> &p_strings) {
- int cell_width = 95;
- int cell_height = 25;
- int cell_margin = 5;
- int rows = ((p_amount - 1) / p_columns) + 1;
-
- set_size(Size2(cell_margin + p_label_w + (cell_width + cell_margin + p_label_w) * p_columns, cell_margin + (cell_height + cell_margin) * rows) * EDSCALE);
-
- for (int i = 0; i < MAX_VALUE_EDITORS; i++) {
- value_label[i]->get_parent()->remove_child(value_label[i]);
- value_editor[i]->get_parent()->remove_child(value_editor[i]);
-
- int box_id = i / p_columns;
- value_hboxes[box_id]->add_child(value_label[i]);
- value_hboxes[box_id]->add_child(value_editor[i]);
-
- if (i < MAX_VALUE_EDITORS / 4) {
- if (i <= p_amount / 4) {
- value_hboxes[i]->show();
- } else {
- value_hboxes[i]->hide();
- }
- }
-
- if (i < p_amount) {
- value_editor[i]->show();
- value_label[i]->show();
- value_label[i]->set_text(i < p_strings.size() ? p_strings[i] : String(""));
- value_editor[i]->set_editable(!read_only);
- } else {
- value_editor[i]->hide();
- value_label[i]->hide();
- }
- }
-}
-
-void CustomPropertyEditor::_bind_methods() {
- ADD_SIGNAL(MethodInfo("variant_changed"));
- ADD_SIGNAL(MethodInfo("variant_field_changed", PropertyInfo(Variant::STRING, "field")));
- ADD_SIGNAL(MethodInfo("resource_edit_request"));
-}
-
-CustomPropertyEditor::CustomPropertyEditor() {
- value_vbox = memnew(VBoxContainer);
- add_child(value_vbox);
-
- for (int i = 0; i < MAX_VALUE_EDITORS; i++) {
- if (i < MAX_VALUE_EDITORS / 4) {
- value_hboxes[i] = memnew(HBoxContainer);
- value_vbox->add_child(value_hboxes[i]);
- value_hboxes[i]->hide();
- }
- int hbox_idx = i / 4;
- value_label[i] = memnew(Label);
- value_hboxes[hbox_idx]->add_child(value_label[i]);
- value_label[i]->hide();
- value_editor[i] = memnew(LineEdit);
- value_hboxes[hbox_idx]->add_child(value_editor[i]);
- value_editor[i]->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- value_editor[i]->hide();
- value_editor[i]->connect("text_submitted", callable_mp(this, &CustomPropertyEditor::_modified));
- value_editor[i]->connect("focus_entered", callable_mp(this, &CustomPropertyEditor::_focus_enter));
- value_editor[i]->connect("focus_exited", callable_mp(this, &CustomPropertyEditor::_focus_exit));
- }
- focused_value_editor = -1;
-
- for (int i = 0; i < 4; i++) {
- scroll[i] = memnew(HScrollBar);
- scroll[i]->hide();
- scroll[i]->set_min(0);
- scroll[i]->set_max(1.0);
- scroll[i]->set_step(0.01);
- add_child(scroll[i]);
- }
-
- checks20gc = memnew(GridContainer);
- add_child(checks20gc);
- checks20gc->set_columns(11);
-
- for (int i = 0; i < 20; i++) {
- if (i == 5 || i == 15) {
- Control *space = memnew(Control);
- space->set_custom_minimum_size(Size2(20, 0) * EDSCALE);
- checks20gc->add_child(space);
- }
-
- checks20[i] = memnew(CheckBox);
- checks20[i]->set_toggle_mode(true);
- checks20[i]->set_focus_mode(Control::FOCUS_NONE);
- checks20gc->add_child(checks20[i]);
- checks20[i]->hide();
- checks20[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed), make_binds(i));
- checks20[i]->set_tooltip(vformat(TTR("Bit %d, val %d."), i, 1 << i));
- }
-
- text_edit = memnew(TextEdit);
- value_vbox->add_child(text_edit);
- text_edit->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
- text_edit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- text_edit->set_offset(SIDE_BOTTOM, -30);
-
- text_edit->hide();
- text_edit->connect("text_changed", callable_mp(this, &CustomPropertyEditor::_text_edit_changed));
-
- color_picker = nullptr;
-
- file = memnew(EditorFileDialog);
- value_vbox->add_child(file);
- file->hide();
-
- file->connect("file_selected", callable_mp(this, &CustomPropertyEditor::_file_selected));
- file->connect("dir_selected", callable_mp(this, &CustomPropertyEditor::_file_selected));
-
- locale = memnew(EditorLocaleDialog);
- value_vbox->add_child(locale);
- locale->hide();
-
- locale->connect("locale_selected", callable_mp(this, &CustomPropertyEditor::_locale_selected));
-
- error = memnew(ConfirmationDialog);
- error->set_title(TTR("Error!"));
- value_vbox->add_child(error);
-
- scene_tree = memnew(SceneTreeDialog);
- value_vbox->add_child(scene_tree);
- scene_tree->connect("selected", callable_mp(this, &CustomPropertyEditor::_node_path_selected));
- scene_tree->get_scene_tree()->set_show_enabled_subscene(true);
-
- texture_preview = memnew(TextureRect);
- value_vbox->add_child(texture_preview);
- texture_preview->hide();
-
- easing_draw = memnew(Control);
- value_vbox->add_child(easing_draw);
- easing_draw->hide();
- easing_draw->connect("draw", callable_mp(this, &CustomPropertyEditor::_draw_easing));
- easing_draw->connect("gui_input", callable_mp(this, &CustomPropertyEditor::_drag_easing));
- easing_draw->set_default_cursor_shape(Control::CURSOR_MOVE);
-
- type_button = memnew(MenuButton);
- value_vbox->add_child(type_button);
- type_button->hide();
- type_button->get_popup()->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_type_create_selected));
-
- menu = memnew(PopupMenu);
- // menu->set_pass_on_modal_close_click(false);
- value_vbox->add_child(menu);
- menu->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_menu_option));
-
- evaluator = nullptr;
-
- spinbox = memnew(SpinBox);
- value_vbox->add_child(spinbox);
- spinbox->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
- spinbox->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified));
-
- slider = memnew(HSlider);
- value_vbox->add_child(slider);
- slider->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
- slider->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified));
-
- action_hboxes = memnew(HBoxContainer);
- action_hboxes->set_alignment(BoxContainer::ALIGNMENT_CENTER);
- value_vbox->add_child(action_hboxes);
- for (int i = 0; i < MAX_ACTION_BUTTONS; i++) {
- action_buttons[i] = memnew(Button);
- action_buttons[i]->hide();
- action_hboxes->add_child(action_buttons[i]);
- Vector<Variant> binds;
- binds.push_back(i);
- action_buttons[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed), binds);
- }
-
- create_dialog = nullptr;
- property_select = nullptr;
-}
diff --git a/editor/property_editor.h b/editor/property_editor.h
deleted file mode 100644
index 3230834d00..0000000000
--- a/editor/property_editor.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*************************************************************************/
-/* property_editor.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 PROPERTY_EDITOR_H
-#define PROPERTY_EDITOR_H
-
-#include "editor/editor_locale_dialog.h"
-#include "editor/scene_tree_editor.h"
-#include "scene/gui/button.h"
-#include "scene/gui/check_box.h"
-#include "scene/gui/check_button.h"
-#include "scene/gui/color_picker.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/grid_container.h"
-#include "scene/gui/label.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/split_container.h"
-#include "scene/gui/text_edit.h"
-#include "scene/gui/texture_rect.h"
-#include "scene/gui/tree.h"
-
-class CreateDialog;
-class EditorFileDialog;
-class PropertyValueEvaluator;
-class PropertySelector;
-
-class EditorResourceConversionPlugin : public RefCounted {
- GDCLASS(EditorResourceConversionPlugin, RefCounted);
-
-protected:
- static void _bind_methods();
-
- GDVIRTUAL0RC(String, _converts_to)
- GDVIRTUAL1RC(bool, _handles, Ref<Resource>)
- GDVIRTUAL1RC(Ref<Resource>, _convert, Ref<Resource>)
-
-public:
- virtual String converts_to() const;
- virtual bool handles(const Ref<Resource> &p_resource) const;
- virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const;
-};
-
-class CustomPropertyEditor : public PopupPanel {
- GDCLASS(CustomPropertyEditor, PopupPanel);
-
- enum {
- MAX_VALUE_EDITORS = 12,
- MAX_ACTION_BUTTONS = 5,
- OBJ_MENU_LOAD = 0,
- OBJ_MENU_EDIT = 1,
- OBJ_MENU_CLEAR = 2,
- OBJ_MENU_MAKE_UNIQUE = 3,
- OBJ_MENU_COPY = 4,
- OBJ_MENU_PASTE = 5,
- OBJ_MENU_NEW_SCRIPT = 6,
- OBJ_MENU_EXTEND_SCRIPT = 7,
- OBJ_MENU_SHOW_IN_FILE_SYSTEM = 8,
- TYPE_BASE_ID = 100,
- CONVERT_BASE_ID = 1000
- };
-
- enum {
- EASING_LINEAR,
- EASING_EASE_IN,
- EASING_EASE_OUT,
- EASING_ZERO,
- EASING_IN_OUT,
- EASING_OUT_IN
- };
-
- PopupMenu *menu = nullptr;
- SceneTreeDialog *scene_tree = nullptr;
- EditorFileDialog *file = nullptr;
- EditorLocaleDialog *locale = nullptr;
- ConfirmationDialog *error = nullptr;
- String name;
- Variant::Type type;
- Variant v;
- List<String> field_names;
- int hint = 0;
- String hint_text;
- HBoxContainer *value_hboxes[MAX_VALUE_EDITORS / 4];
- VBoxContainer *value_vbox = nullptr;
- LineEdit *value_editor[MAX_VALUE_EDITORS];
- int focused_value_editor;
- Label *value_label[MAX_VALUE_EDITORS];
- HScrollBar *scroll[4];
- HBoxContainer *action_hboxes = nullptr;
- Button *action_buttons[MAX_ACTION_BUTTONS];
- MenuButton *type_button = nullptr;
- Vector<String> inheritors_array;
- TextureRect *texture_preview = nullptr;
- ColorPicker *color_picker = nullptr;
- TextEdit *text_edit = nullptr;
- bool read_only = false;
- bool picking_viewport = false;
- GridContainer *checks20gc = nullptr;
- CheckBox *checks20[20];
- SpinBox *spinbox = nullptr;
- HSlider *slider = nullptr;
-
- Control *easing_draw = nullptr;
- CreateDialog *create_dialog = nullptr;
- PropertySelector *property_select = nullptr;
-
- Object *owner = nullptr;
-
- bool updating = false;
-
- PropertyValueEvaluator *evaluator = nullptr;
-
- void _text_edit_changed();
- void _file_selected(String p_file);
- void _locale_selected(String p_locale);
- void _modified(String p_string);
-
- real_t _parse_real_expression(String text);
-
- void _range_modified(double p_value);
- void _focus_enter();
- void _focus_exit();
- void _action_pressed(int p_which);
- void _type_create_selected(int p_idx);
- void _create_dialog_callback();
- void _create_selected_property(const String &p_prop);
-
- void _color_changed(const Color &p_color);
- void _draw_easing();
- void _menu_option(int p_which);
-
- void _drag_easing(const Ref<InputEvent> &p_ev);
-
- void _node_path_selected(NodePath p_path);
- void show_value_editors(int p_amount);
- void config_value_editors(int p_amount, int p_columns, int p_label_w, const List<String> &p_strings);
- void config_action_buttons(const List<String> &p_strings);
-
- void _emit_changed_whole_or_field();
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- void hide_menu();
-
- Variant get_variant() const;
- String get_name() const;
-
- void set_read_only(bool p_read_only) { read_only = p_read_only; }
-
- bool edit(Object *p_owner, const String &p_name, Variant::Type p_type, const Variant &p_variant, int p_hint, String p_hint_text);
-
- CustomPropertyEditor();
-};
-
-#endif
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index c136eae1bc..1b17a740dd 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -32,8 +32,12 @@
#include "core/os/keyboard.h"
#include "editor/doc_tools.h"
+#include "editor/editor_help.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/rich_text_label.h"
+#include "scene/gui/tree.h"
void PropertySelector::_text_changed(const String &p_newtext) {
_update_search();
@@ -581,7 +585,7 @@ PropertySelector::PropertySelector() {
search_box->connect("gui_input", callable_mp(this, &PropertySelector::_sbox_input));
search_options = memnew(Tree);
vbc->add_margin_child(TTR("Matches:"), search_options, true);
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
get_ok_button()->set_disabled(true);
register_text_enter(search_box);
set_hide_on_ok(false);
diff --git a/editor/property_selector.h b/editor/property_selector.h
index f42f5daa3f..9f1af576dd 100644
--- a/editor/property_selector.h
+++ b/editor/property_selector.h
@@ -28,12 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PROPERTYSELECTOR_H
-#define PROPERTYSELECTOR_H
+#ifndef PROPERTY_SELECTOR_H
+#define PROPERTY_SELECTOR_H
-#include "editor/editor_help.h"
-#include "editor/property_editor.h"
-#include "scene/gui/rich_text_label.h"
+#include "scene/gui/dialogs.h"
+
+class EditorHelpBit;
+class LineEdit;
+class Tree;
class PropertySelector : public ConfirmationDialog {
GDCLASS(PropertySelector, ConfirmationDialog);
@@ -80,4 +82,4 @@ public:
PropertySelector();
};
-#endif // PROPERTYSELECTOR_H
+#endif // PROPERTY_SELECTOR_H
diff --git a/editor/register_exporters.h b/editor/register_exporters.h
index 09076af978..9aa98f509f 100644
--- a/editor/register_exporters.h
+++ b/editor/register_exporters.h
@@ -33,4 +33,4 @@
void register_exporters();
-#endif
+#endif // REGISTER_EXPORTERS_H
diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp
index a8278b9aab..665aca6a37 100644
--- a/editor/rename_dialog.cpp
+++ b/editor/rename_dialog.cpp
@@ -42,6 +42,7 @@
#include "plugins/script_editor_plugin.h"
#include "scene/gui/control.h"
#include "scene/gui/label.h"
+#include "scene/gui/separator.h"
#include "scene/gui/tab_container.h"
RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_undo_redo) {
@@ -139,7 +140,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
but_insert_name->set_text("NAME");
but_insert_name->set_tooltip(String("${NAME}\n") + TTR("Node name."));
but_insert_name->set_focus_mode(Control::FOCUS_NONE);
- but_insert_name->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${NAME}"));
+ but_insert_name->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${NAME}"));
but_insert_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grd_substitute->add_child(but_insert_name);
@@ -149,7 +150,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
but_insert_parent->set_text("PARENT");
but_insert_parent->set_tooltip(String("${PARENT}\n") + TTR("Node's parent name, if available."));
but_insert_parent->set_focus_mode(Control::FOCUS_NONE);
- but_insert_parent->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${PARENT}"));
+ but_insert_parent->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${PARENT}"));
but_insert_parent->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grd_substitute->add_child(but_insert_parent);
@@ -159,7 +160,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
but_insert_type->set_text("TYPE");
but_insert_type->set_tooltip(String("${TYPE}\n") + TTR("Node type."));
but_insert_type->set_focus_mode(Control::FOCUS_NONE);
- but_insert_type->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${TYPE}"));
+ but_insert_type->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${TYPE}"));
but_insert_type->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grd_substitute->add_child(but_insert_type);
@@ -169,7 +170,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
but_insert_scene->set_text("SCENE");
but_insert_scene->set_tooltip(String("${SCENE}\n") + TTR("Current scene name."));
but_insert_scene->set_focus_mode(Control::FOCUS_NONE);
- but_insert_scene->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${SCENE}"));
+ but_insert_scene->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${SCENE}"));
but_insert_scene->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grd_substitute->add_child(but_insert_scene);
@@ -179,7 +180,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
but_insert_root->set_text("ROOT");
but_insert_root->set_tooltip(String("${ROOT}\n") + TTR("Root node name."));
but_insert_root->set_focus_mode(Control::FOCUS_NONE);
- but_insert_root->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${ROOT}"));
+ but_insert_root->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${ROOT}"));
but_insert_root->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grd_substitute->add_child(but_insert_root);
@@ -189,7 +190,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
but_insert_count->set_text("COUNTER");
but_insert_count->set_tooltip(String("${COUNTER}\n") + TTR("Sequential integer counter.\nCompare counter options."));
but_insert_count->set_focus_mode(Control::FOCUS_NONE);
- but_insert_count->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${COUNTER}"));
+ but_insert_count->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${COUNTER}"));
but_insert_count->set_h_size_flags(Control::SIZE_EXPAND_FILL);
grd_substitute->add_child(but_insert_count);
@@ -289,7 +290,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
// ---- Dialog related
set_min_size(Size2(383, 0));
- get_ok_button()->set_text(TTR("Rename"));
+ set_ok_button_text(TTR("Rename"));
Button *but_reset = add_button(TTR("Reset"));
eh.errfunc = _error_handler;
@@ -321,9 +322,9 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
spn_count_padding->connect("value_changed", callable_mp(this, &RenameDialog::_update_preview_int));
opt_style->connect("item_selected", callable_mp(this, &RenameDialog::_update_preview_int));
opt_case->connect("item_selected", callable_mp(this, &RenameDialog::_update_preview_int));
- cbut_substitute->connect("pressed", callable_mp(this, &RenameDialog::_update_preview), varray(""));
- cbut_regex->connect("pressed", callable_mp(this, &RenameDialog::_update_preview), varray(""));
- cbut_process->connect("pressed", callable_mp(this, &RenameDialog::_update_preview), varray(""));
+ cbut_substitute->connect("pressed", callable_mp(this, &RenameDialog::_update_preview).bind(""));
+ cbut_regex->connect("pressed", callable_mp(this, &RenameDialog::_update_preview).bind(""));
+ cbut_process->connect("pressed", callable_mp(this, &RenameDialog::_update_preview).bind(""));
but_reset->connect("pressed", callable_mp(this, &RenameDialog::reset));
diff --git a/editor/reparent_dialog.cpp b/editor/reparent_dialog.cpp
index 5a8fe24518..75098b25b1 100644
--- a/editor/reparent_dialog.cpp
+++ b/editor/reparent_dialog.cpp
@@ -89,7 +89,7 @@ ReparentDialog::ReparentDialog() {
//cancel->connect("pressed", this,"_cancel");
- get_ok_button()->set_text(TTR("Reparent"));
+ set_ok_button_text(TTR("Reparent"));
}
ReparentDialog::~ReparentDialog() {
diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp
index 64aea54c5f..94a5c07709 100644
--- a/editor/scene_create_dialog.cpp
+++ b/editor/scene_create_dialog.cpp
@@ -76,7 +76,7 @@ void SceneCreateDialog::accept_create() {
void SceneCreateDialog::browse_types() {
select_node_dialog->popup_create(true);
select_node_dialog->set_title(TTR("Pick Root Node Type"));
- select_node_dialog->get_ok_button()->set_text(TTR("Pick"));
+ select_node_dialog->set_ok_button_text(TTR("Pick"));
}
void SceneCreateDialog::on_type_picked() {
@@ -171,7 +171,7 @@ Node *SceneCreateDialog::create_scene_root() {
break;
case ROOT_USER_INTERFACE: {
Control *gui = memnew(Control);
- gui->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ gui->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
root = gui;
} break;
case ROOT_OTHER:
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 2e1090e6c0..d19a40599f 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -39,6 +39,7 @@
#include "editor/editor_feature_profile.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/multi_node_edit.h"
@@ -72,7 +73,7 @@ void SceneTreeDock::input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT)) {
- if (mb->is_pressed() && scene_tree->get_rect().has_point(mb->get_position())) {
+ if (mb->is_pressed() && scene_tree->get_rect().has_point(scene_tree->get_local_mouse_position())) {
tree_clicked = true;
} else if (!mb->is_pressed()) {
tree_clicked = false;
@@ -910,7 +911,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
ResourceSaver::get_recognized_extensions(sd, &extensions);
new_scene_from_dialog->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- new_scene_from_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ new_scene_from_dialog->add_filter("*." + extensions[i], extensions[i].to_upper());
}
String existing;
@@ -1122,7 +1123,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
break;
case TOOL_CREATE_USER_INTERFACE: {
Control *node = memnew(Control);
- node->set_anchors_and_offsets_preset(PRESET_WIDE); //more useful for resizable UIs.
+ node->set_anchors_and_offsets_preset(PRESET_FULL_RECT); //more useful for resizable UIs.
new_node = node;
} break;
@@ -1257,19 +1258,19 @@ void SceneTreeDock::_notification(int p_what) {
beginner_node_shortcuts->add_child(button_2d);
button_2d->set_text(TTR("2D Scene"));
button_2d->set_icon(get_theme_icon(SNAME("Node2D"), SNAME("EditorIcons")));
- button_2d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_2D_SCENE, false));
+ button_2d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_2D_SCENE, false));
button_3d = memnew(Button);
beginner_node_shortcuts->add_child(button_3d);
button_3d->set_text(TTR("3D Scene"));
button_3d->set_icon(get_theme_icon(SNAME("Node3D"), SNAME("EditorIcons")));
- button_3d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_3D_SCENE, false));
+ button_3d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_3D_SCENE, false));
button_ui = memnew(Button);
beginner_node_shortcuts->add_child(button_ui);
button_ui->set_text(TTR("User Interface"));
button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons")));
- button_ui->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_USER_INTERFACE, false));
+ button_ui->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_USER_INTERFACE, false));
VBoxContainer *favorite_node_shortcuts = memnew(VBoxContainer);
favorite_node_shortcuts->set_name("FavoriteNodeShortcuts");
@@ -1279,19 +1280,19 @@ void SceneTreeDock::_notification(int p_what) {
node_shortcuts->add_child(button_custom);
button_custom->set_text(TTR("Other Node"));
button_custom->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- button_custom->connect("pressed", callable_bind(callable_mp(this, &SceneTreeDock::_tool_selected), TOOL_NEW, false));
+ button_custom->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_NEW, false));
button_clipboard = memnew(Button);
node_shortcuts->add_child(button_clipboard);
button_clipboard->set_text(TTR("Paste From Clipboard"));
button_clipboard->set_icon(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")));
- button_clipboard->connect("pressed", callable_bind(callable_mp(this, &SceneTreeDock::_tool_selected), TOOL_PASTE, false));
+ button_clipboard->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_PASTE, false));
_update_create_root_dialog();
} break;
case NOTIFICATION_ENTER_TREE: {
- clear_inherit_confirm->connect("confirmed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM, false));
+ clear_inherit_confirm->connect("confirmed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM, false));
scene_tree->set_auto_expand_selected(EditorSettings::get_singleton()->get("docks/scene_tree/auto_expand_to_selected"), false);
} break;
@@ -1337,14 +1338,14 @@ void SceneTreeDock::_node_replace_owner(Node *p_base, Node *p_node, Node *p_root
UndoRedo *undo_redo = &editor_data->get_undo_redo();
switch (p_mode) {
case MODE_BIDI: {
- bool is_unique = p_node->is_unique_name_in_owner() && p_base->get_node_or_null(UNIQUE_NODE_PREFIX + String(p_node->get_name())) != nullptr;
- if (is_unique) {
+ bool disable_unique = p_node->is_unique_name_in_owner() && p_root->get_node_or_null(UNIQUE_NODE_PREFIX + String(p_node->get_name())) != nullptr;
+ if (disable_unique) {
// Will create a unique name conflict. Disable before setting owner.
undo_redo->add_do_method(p_node, "set_unique_name_in_owner", false);
}
undo_redo->add_do_method(p_node, "set_owner", p_root);
undo_redo->add_undo_method(p_node, "set_owner", p_base);
- if (is_unique) {
+ if (disable_unique) {
// Will create a unique name conflict. Enable after setting owner.
undo_redo->add_undo_method(p_node, "set_unique_name_in_owner", true);
}
@@ -1952,17 +1953,36 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
return;
}
- editor_data->get_undo_redo().create_action(TTR("Attach Script"));
- for (Node *E : selected) {
- Ref<Script> existing = E->get_script();
- editor_data->get_undo_redo().add_do_method(E, "set_script", p_script);
- editor_data->get_undo_redo().add_undo_method(E, "set_script", existing);
+ if (selected.size() == 1) {
+ Node *node = selected.front()->get();
+ Ref<Script> existing = node->get_script();
+
+ editor_data->get_undo_redo().create_action(TTR("Attach Script"));
+ editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "store_script_properties", node);
+ editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "store_script_properties", node);
+ editor_data->get_undo_redo().add_do_method(node, "set_script", p_script);
+ editor_data->get_undo_redo().add_undo_method(node, "set_script", existing);
+ editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "apply_script_properties", node);
+ editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", node);
editor_data->get_undo_redo().add_do_method(this, "_update_script_button");
editor_data->get_undo_redo().add_undo_method(this, "_update_script_button");
+ editor_data->get_undo_redo().commit_action();
+ } else {
+ editor_data->get_undo_redo().create_action(TTR("Attach Script"));
+ for (List<Node *>::Element *E = selected.front(); E; E = E->next()) {
+ Ref<Script> existing = E->get()->get_script();
+ editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "store_script_properties", E->get());
+ editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "store_script_properties", E->get());
+ editor_data->get_undo_redo().add_do_method(E->get(), "set_script", p_script);
+ editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing);
+ editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "apply_script_properties", E->get());
+ editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", E->get());
+ editor_data->get_undo_redo().add_do_method(this, "_update_script_button");
+ editor_data->get_undo_redo().add_undo_method(this, "_update_script_button");
+ }
+ editor_data->get_undo_redo().commit_action();
}
- editor_data->get_undo_redo().commit_action();
-
_push_item(p_script.operator->());
_update_script_button();
}
@@ -2347,7 +2367,7 @@ void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_prop
if (!(c.flags & Object::CONNECT_PERSIST)) {
continue;
}
- newnode->connect(c.signal.get_name(), c.callable, c.binds, Object::CONNECT_PERSIST);
+ newnode->connect(c.signal.get_name(), c.callable, Object::CONNECT_PERSIST);
}
}
@@ -2437,7 +2457,7 @@ void SceneTreeDock::_new_scene_from(String p_file) {
flg |= ResourceSaver::FLAG_COMPRESS;
}
- err = ResourceSaver::save(p_file, sdata, flg);
+ err = ResourceSaver::save(sdata, p_file, flg);
if (err != OK) {
accept->set_text(TTR("Error saving scene."));
accept->popup_centered();
@@ -2586,11 +2606,14 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files, NodePath p_to, int p_
void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) {
Ref<Script> scr = ResourceLoader::load(p_file);
ERR_FAIL_COND(!scr.is_valid());
- Node *n = get_node(p_to);
- if (n) {
+ if (Node *n = get_node(p_to)) {
editor_data->get_undo_redo().create_action(TTR("Attach Script"));
+ editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "store_script_properties", n);
+ editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "store_script_properties", n);
editor_data->get_undo_redo().add_do_method(n, "set_script", scr);
editor_data->get_undo_redo().add_undo_method(n, "set_script", n->get_script());
+ editor_data->get_undo_redo().add_do_method(InspectorDock::get_singleton(), "apply_script_properties", n);
+ editor_data->get_undo_redo().add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", n);
editor_data->get_undo_redo().add_do_method(this, "_update_script_button");
editor_data->get_undo_redo().add_undo_method(this, "_update_script_button");
editor_data->get_undo_redo().commit_action();
@@ -3177,7 +3200,7 @@ void SceneTreeDock::_update_create_root_dialog() {
favorite_nodes->get_child(i)->queue_delete();
}
- Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ);
+ Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ);
if (f.is_valid()) {
while (!f->eof_reached()) {
String l = f->get_line().strip_edges();
@@ -3192,7 +3215,7 @@ void SceneTreeDock::_update_create_root_dialog() {
name = ScriptServer::get_global_class_native_base(name);
}
button->set_icon(EditorNode::get_singleton()->get_class_icon(name));
- button->connect("pressed", callable_mp(this, &SceneTreeDock::_favorite_root_selected), make_binds(l));
+ button->connect("pressed", callable_mp(this, &SceneTreeDock::_favorite_root_selected).bind(l));
}
}
}
@@ -3374,14 +3397,14 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
button_add = memnew(Button);
button_add->set_flat(true);
- button_add->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_NEW, false));
+ button_add->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_NEW, false));
button_add->set_tooltip(TTR("Add/Create a New Node."));
button_add->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_child_node"));
filter_hbc->add_child(button_add);
button_instance = memnew(Button);
button_instance->set_flat(true);
- button_instance->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_INSTANTIATE, false));
+ button_instance->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_INSTANTIATE, false));
button_instance->set_tooltip(TTR("Instantiate a scene file as a Node. Creates an inherited scene if no root node exists."));
button_instance->set_shortcut(ED_GET_SHORTCUT("scene_tree/instance_scene"));
filter_hbc->add_child(button_instance);
@@ -3396,7 +3419,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
button_create_script = memnew(Button);
button_create_script->set_flat(true);
- button_create_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_ATTACH_SCRIPT, false));
+ button_create_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_ATTACH_SCRIPT, false));
button_create_script->set_tooltip(TTR("Attach a new or existing script to the selected node."));
button_create_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/attach_script"));
filter_hbc->add_child(button_create_script);
@@ -3404,7 +3427,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
button_detach_script = memnew(Button);
button_detach_script->set_flat(true);
- button_detach_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_DETACH_SCRIPT, false));
+ button_detach_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_DETACH_SCRIPT, false));
button_detach_script->set_tooltip(TTR("Detach the script from the selected node."));
button_detach_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/detach_script"));
filter_hbc->add_child(button_detach_script);
@@ -3417,7 +3440,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
PopupMenu *tree_menu = button_tree_menu->get_popup();
tree_menu->add_check_item(TTR("Auto Expand to Selected"), TOOL_AUTO_EXPAND);
- tree_menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false));
+ tree_menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(false));
button_hb = memnew(HBoxContainer);
vbc->add_child(button_hb);
@@ -3454,8 +3477,8 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
scene_tree->set_v_size_flags(SIZE_EXPAND | SIZE_FILL);
scene_tree->connect("rmb_pressed", callable_mp(this, &SceneTreeDock::_tree_rmb));
- scene_tree->connect("node_selected", callable_mp(this, &SceneTreeDock::_node_selected), varray(), CONNECT_DEFERRED);
- scene_tree->connect("node_renamed", callable_mp(this, &SceneTreeDock::_node_renamed), varray(), CONNECT_DEFERRED);
+ scene_tree->connect("node_selected", callable_mp(this, &SceneTreeDock::_node_selected), CONNECT_DEFERRED);
+ scene_tree->connect("node_renamed", callable_mp(this, &SceneTreeDock::_node_renamed), CONNECT_DEFERRED);
scene_tree->connect("node_prerename", callable_mp(this, &SceneTreeDock::_node_prerenamed));
scene_tree->connect("open", callable_mp(this, &SceneTreeDock::_load_request));
scene_tree->connect("open_script", callable_mp(this, &SceneTreeDock::_script_open_request));
@@ -3505,7 +3528,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
delete_dialog = memnew(ConfirmationDialog);
add_child(delete_dialog);
- delete_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_delete_confirm), varray(false));
+ delete_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_delete_confirm).bind(false));
editable_instance_remove_dialog = memnew(ConfirmationDialog);
add_child(editable_instance_remove_dialog);
@@ -3522,11 +3545,11 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
menu = memnew(PopupMenu);
add_child(menu);
- menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false));
+ menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(false));
menu_subresources = memnew(PopupMenu);
menu_subresources->set_name("Sub-Resources");
- menu_subresources->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false));
+ menu_subresources->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(false));
menu->add_child(menu_subresources);
menu_properties = memnew(PopupMenu);
@@ -3535,7 +3558,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
clear_inherit_confirm = memnew(ConfirmationDialog);
clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)"));
- clear_inherit_confirm->get_ok_button()->set_text(TTR("Clear"));
+ clear_inherit_confirm->set_ok_button_text(TTR("Clear"));
add_child(clear_inherit_confirm);
set_process_input(true);
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index dc7f3476ee..e15865036b 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -33,8 +33,8 @@
#include "editor/create_dialog.h"
#include "editor/editor_data.h"
+#include "editor/editor_quick_open.h"
#include "editor/groups_editor.h"
-#include "editor/quick_open.h"
#include "editor/reparent_dialog.h"
#include "editor/script_create_dialog.h"
#include "scene/animation/animation_player.h"
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 86fa9222c0..282cfa80e8 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -268,7 +268,17 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
String warning = p_node->get_configuration_warnings_as_string();
if (!warning.is_empty()) {
- item->add_button(0, get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning);
+ const int num_warnings = p_node->get_configuration_warnings().size();
+ String warning_icon;
+ if (num_warnings == 1) {
+ warning_icon = SNAME("NodeWarning");
+ } else if (num_warnings <= 3) {
+ warning_icon = vformat("NodeWarnings%d", num_warnings);
+ } else {
+ warning_icon = SNAME("NodeWarnings4Plus");
+ }
+
+ item->add_button(0, get_theme_icon(warning_icon, SNAME("EditorIcons")), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning);
}
if (p_node->is_unique_name_in_owner()) {
@@ -358,7 +368,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
if (can_open_instance && undo_redo) { //Show buttons only when necessary(SceneTreeDock) to avoid crashes
if (!p_node->is_connected("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed))) {
- p_node->connect("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed), varray(p_node));
+ p_node->connect("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed).bind(p_node));
}
Ref<Script> script = p_node->get_script();
@@ -375,7 +385,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
}
if (p_node->has_meta("_edit_group_")) {
- item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable."));
+ item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make them selectable."));
}
bool v = p_node->call("is_visible");
@@ -386,7 +396,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
}
if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) {
- p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed), varray(p_node));
+ p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed).bind(p_node));
}
_update_visibility_color(p_node, item);
@@ -399,7 +409,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
}
if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) {
- p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed), varray(p_node));
+ p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed).bind(p_node));
}
} else if (p_node->is_class("Node3D")) {
if (p_node->has_meta("_edit_lock_")) {
@@ -407,7 +417,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
}
if (p_node->has_meta("_edit_group_")) {
- item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable."));
+ item->add_button(0, get_theme_icon(SNAME("Group"), SNAME("EditorIcons")), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make them selectable."));
}
bool v = p_node->call("is_visible");
@@ -418,7 +428,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
}
if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) {
- p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed), varray(p_node));
+ p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed).bind(p_node));
}
_update_visibility_color(p_node, item);
@@ -733,7 +743,7 @@ void SceneTreeEditor::_notification(int p_what) {
get_tree()->connect("tree_process_mode_changed", callable_mp(this, &SceneTreeEditor::_tree_process_mode_changed));
get_tree()->connect("node_removed", callable_mp(this, &SceneTreeEditor::_node_removed));
get_tree()->connect("node_renamed", callable_mp(this, &SceneTreeEditor::_node_renamed));
- get_tree()->connect("node_configuration_warning_changed", callable_mp(this, &SceneTreeEditor::_warning_changed), varray(), CONNECT_DEFERRED);
+ get_tree()->connect("node_configuration_warning_changed", callable_mp(this, &SceneTreeEditor::_warning_changed), CONNECT_DEFERRED);
tree->connect("item_collapsed", callable_mp(this, &SceneTreeEditor::_cell_collapsed));
@@ -1301,7 +1311,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
blocked = 0;
update_timer = memnew(Timer);
- update_timer->connect("timeout", callable_mp(this, &SceneTreeEditor::_update_tree), varray(false));
+ update_timer->connect("timeout", callable_mp(this, &SceneTreeEditor::_update_tree).bind(false));
update_timer->set_one_shot(true);
update_timer->set_wait_time(0.5);
add_child(update_timer);
@@ -1359,6 +1369,10 @@ void SceneTreeDialog::_select() {
}
}
+void SceneTreeDialog::_selected_changed() {
+ get_ok_button()->set_disabled(!tree->get_selected());
+}
+
void SceneTreeDialog::_filter_changed(const String &p_filter) {
tree->set_filter(p_filter);
}
@@ -1386,6 +1400,10 @@ SceneTreeDialog::SceneTreeDialog() {
tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tree->get_scene_tree()->connect("item_activated", callable_mp(this, &SceneTreeDialog::_select));
vbc->add_child(tree);
+
+ // Disable the OK button when no node is selected.
+ get_ok_button()->set_disabled(!tree->get_selected());
+ tree->connect("node_selected", callable_mp(this, &SceneTreeDialog::_selected_changed));
}
SceneTreeDialog::~SceneTreeDialog() {
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index 5d4230059c..31772e55b5 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -176,6 +176,7 @@ class SceneTreeDialog : public ConfirmationDialog {
void _select();
void _cancel();
+ void _selected_changed();
void _filter_changed(const String &p_filter);
void _update_theme();
@@ -191,4 +192,4 @@ public:
~SceneTreeDialog();
};
-#endif
+#endif // SCENE_TREE_EDITOR_H
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index e8561de19c..77e0321f83 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -384,7 +385,7 @@ void ScriptCreateDialog::_create_new() {
} else {
String lpath = ProjectSettings::get_singleton()->localize_path(file_path->get_text());
scr->set_path(lpath);
- Error err = ResourceSaver::save(lpath, scr, ResourceSaver::FLAG_CHANGE_PATH);
+ Error err = ResourceSaver::save(scr, lpath, ResourceSaver::FLAG_CHANGE_PATH);
if (err != OK) {
alert->set_text(TTR("Error - Could not create script in filesystem."));
alert->popup_centered();
@@ -481,7 +482,7 @@ void ScriptCreateDialog::_browse_path(bool browse_parent, bool p_save) {
if (p_save) {
file_browse->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
file_browse->set_title(TTR("Open Script / Choose Location"));
- file_browse->get_ok_button()->set_text(TTR("Open"));
+ file_browse->set_ok_button_text(TTR("Open"));
} else {
file_browse->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
file_browse->set_title(TTR("Open Script"));
@@ -528,7 +529,7 @@ void ScriptCreateDialog::_browse_class_in_tree() {
select_class->set_base_type(base_type);
select_class->popup_create(true);
select_class->set_title(vformat(TTR("Inherit %s"), base_type));
- select_class->get_ok_button()->set_text(TTR("Inherit"));
+ select_class->set_ok_button_text(TTR("Inherit"));
}
void ScriptCreateDialog::_path_changed(const String &p_path) {
@@ -620,9 +621,9 @@ void ScriptCreateDialog::_update_template_menu() {
} else {
String template_directory;
if (template_location == ScriptLanguage::TEMPLATE_PROJECT) {
- template_directory = EditorSettings::get_singleton()->get_project_script_templates_dir();
+ template_directory = EditorPaths::get_singleton()->get_project_script_templates_dir();
} else {
- template_directory = EditorSettings::get_singleton()->get_script_templates_dir();
+ template_directory = EditorPaths::get_singleton()->get_script_templates_dir();
}
templates_found = _get_user_templates(language, current_node, template_directory, template_location);
}
@@ -750,7 +751,7 @@ void ScriptCreateDialog::_update_dialog() {
parent_browse_button->set_disabled(!is_new_file || !can_inherit_from_file);
template_inactive_message = "";
String button_text = is_new_file ? TTR("Create") : TTR("Load");
- get_ok_button()->set_text(button_text);
+ set_ok_button_text(button_text);
if (is_new_file) {
if (is_built_in) {
@@ -1008,7 +1009,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
parent_search_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_class_in_tree));
hb->add_child(parent_search_button);
parent_browse_button = memnew(Button);
- parent_browse_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path), varray(true, false));
+ parent_browse_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path).bind(true, false));
hb->add_child(parent_browse_button);
gc->add_child(memnew(Label(TTR("Inherits:"))));
gc->add_child(hb);
@@ -1057,7 +1058,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
file_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
hb->add_child(file_path);
path_button = memnew(Button);
- path_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path), varray(false, true));
+ path_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_path).bind(false, true));
hb->add_child(path_button);
Label *label = memnew(Label(TTR("Path:")));
gc->add_child(label);
@@ -1088,7 +1089,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
file_browse->connect("file_selected", callable_mp(this, &ScriptCreateDialog::_file_selected));
file_browse->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
add_child(file_browse);
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
alert = memnew(AcceptDialog);
alert->get_label()->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
alert->get_label()->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp
index f70c46c8d8..bd1f2529ca 100644
--- a/editor/shader_create_dialog.cpp
+++ b/editor/shader_create_dialog.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_scale.h"
+#include "scene/resources/shader_include.h"
#include "scene/resources/visual_shader.h"
#include "servers/rendering/shader_types.h"
@@ -43,15 +44,15 @@ void ShaderCreateDialog::_notification(int p_what) {
String last_lang = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_language", "");
if (!last_lang.is_empty()) {
- for (int i = 0; i < language_menu->get_item_count(); i++) {
- if (language_menu->get_item_text(i) == last_lang) {
- language_menu->select(i);
- current_language = i;
+ for (int i = 0; i < type_menu->get_item_count(); i++) {
+ if (type_menu->get_item_text(i) == last_lang) {
+ type_menu->select(i);
+ current_type = i;
break;
}
}
} else {
- language_menu->select(default_language);
+ type_menu->select(default_type);
}
current_mode = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_mode", 0);
@@ -67,12 +68,17 @@ void ShaderCreateDialog::_notification(int p_what) {
void ShaderCreateDialog::_update_theme() {
Ref<Texture2D> shader_icon = gc->get_theme_icon(SNAME("Shader"), SNAME("EditorIcons"));
if (shader_icon.is_valid()) {
- language_menu->set_item_icon(0, shader_icon);
+ type_menu->set_item_icon(0, shader_icon);
}
Ref<Texture2D> visual_shader_icon = gc->get_theme_icon(SNAME("VisualShader"), SNAME("EditorIcons"));
if (visual_shader_icon.is_valid()) {
- language_menu->set_item_icon(1, visual_shader_icon);
+ type_menu->set_item_icon(1, visual_shader_icon);
+ }
+
+ Ref<Texture2D> include_icon = gc->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons"));
+ if (include_icon.is_valid()) {
+ type_menu->set_item_icon(2, include_icon);
}
path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
@@ -80,7 +86,7 @@ void ShaderCreateDialog::_update_theme() {
}
void ShaderCreateDialog::_update_language_info() {
- language_data.clear();
+ type_data.clear();
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
ShaderTypeData data;
@@ -88,12 +94,15 @@ void ShaderCreateDialog::_update_language_info() {
data.use_templates = true;
data.extensions.push_back("gdshader");
data.default_extension = "gdshader";
+ } else if (i == int(SHADER_TYPE_INC)) {
+ data.extensions.push_back("gdshaderinc");
+ data.default_extension = "gdshaderinc";
} else {
data.default_extension = "tres";
}
data.extensions.push_back("res");
data.extensions.push_back("tres");
- language_data.push_back(data);
+ type_data.push_back(data);
}
}
@@ -136,69 +145,97 @@ void ShaderCreateDialog::ok_pressed() {
void ShaderCreateDialog::_create_new() {
Ref<Resource> shader;
-
- if (language_menu->get_selected() == int(SHADER_TYPE_TEXT)) {
- Ref<Shader> text_shader;
- text_shader.instantiate();
- shader = text_shader;
-
- StringBuilder code;
- code += vformat("shader_type %s;\n", mode_menu->get_text().replace(" ", "").camelcase_to_underscore());
-
- if (current_template == 0) { // Default template.
- code += "\n";
- switch (current_mode) {
- case Shader::MODE_SPATIAL:
- code += "void fragment() {\n";
- code += "\t// Place fragment code here.\n";
- code += "}\n";
- break;
- case Shader::MODE_CANVAS_ITEM:
- code += "void fragment() {\n";
- code += "\t// Place fragment code here.\n";
- code += "}\n";
- break;
- case Shader::MODE_PARTICLES:
- code += "void start() {\n";
- code += "\t// Place start code here.\n";
- code += "}\n";
- code += "\n";
- code += "void process() {\n";
- code += "\t// Place process code here.\n";
- code += "}\n";
- break;
- case Shader::MODE_SKY:
- code += "void sky() {\n";
- code += "\t// Place sky code here.\n";
- code += "}\n";
- break;
- case Shader::MODE_FOG:
- code += "void fog() {\n";
- code += "\t// Place fog code here.\n";
- code += "}\n";
- break;
+ Ref<Resource> shader_inc;
+
+ switch (type_menu->get_selected()) {
+ case SHADER_TYPE_TEXT: {
+ Ref<Shader> text_shader;
+ text_shader.instantiate();
+ shader = text_shader;
+
+ StringBuilder code;
+ code += vformat("shader_type %s;\n", mode_menu->get_text().replace(" ", "").camelcase_to_underscore());
+
+ if (current_template == 0) { // Default template.
+ code += "\n";
+ switch (current_mode) {
+ case Shader::MODE_SPATIAL:
+ code += "void fragment() {\n";
+ code += "\t// Place fragment code here.\n";
+ code += "}\n";
+ break;
+ case Shader::MODE_CANVAS_ITEM:
+ code += "void fragment() {\n";
+ code += "\t// Place fragment code here.\n";
+ code += "}\n";
+ break;
+ case Shader::MODE_PARTICLES:
+ code += "void start() {\n";
+ code += "\t// Place start code here.\n";
+ code += "}\n";
+ code += "\n";
+ code += "void process() {\n";
+ code += "\t// Place process code here.\n";
+ code += "}\n";
+ break;
+ case Shader::MODE_SKY:
+ code += "void sky() {\n";
+ code += "\t// Place sky code here.\n";
+ code += "}\n";
+ break;
+ case Shader::MODE_FOG:
+ code += "void fog() {\n";
+ code += "\t// Place fog code here.\n";
+ code += "}\n";
+ break;
+ }
}
- }
- text_shader->set_code(code.as_string());
- } else {
- Ref<VisualShader> visual_shader;
- visual_shader.instantiate();
- shader = visual_shader;
- visual_shader->set_mode(Shader::Mode(current_mode));
+ text_shader->set_code(code.as_string());
+ } break;
+ case SHADER_TYPE_VISUAL: {
+ Ref<VisualShader> visual_shader;
+ visual_shader.instantiate();
+ shader = visual_shader;
+ visual_shader->set_mode(Shader::Mode(current_mode));
+ } break;
+ case SHADER_TYPE_INC: {
+ Ref<ShaderInclude> include;
+ include.instantiate();
+ shader_inc = include;
+ } break;
+ default: {
+ } break;
}
- if (!is_built_in) {
+ if (shader.is_null()) {
String lpath = ProjectSettings::get_singleton()->localize_path(file_path->get_text());
- shader->set_path(lpath);
- Error err = ResourceSaver::save(lpath, shader, ResourceSaver::FLAG_CHANGE_PATH);
- if (err != OK) {
- alert->set_text(TTR("Error - Could not create shader in filesystem."));
+ shader_inc->set_path(lpath);
+
+ Error error = ResourceSaver::save(shader_inc, lpath, ResourceSaver::FLAG_CHANGE_PATH);
+ if (error != OK) {
+ alert->set_text(TTR("Error - Could not create shader include in filesystem."));
alert->popup_centered();
return;
}
+
+ emit_signal(SNAME("shader_include_created"), shader_inc);
+ } else {
+ if (!is_built_in) {
+ String lpath = ProjectSettings::get_singleton()->localize_path(file_path->get_text());
+ shader->set_path(lpath);
+
+ Error error = ResourceSaver::save(shader, lpath, ResourceSaver::FLAG_CHANGE_PATH);
+ if (error != OK) {
+ alert->set_text(TTR("Error - Could not create shader in filesystem."));
+ alert->popup_centered();
+ return;
+ }
+ }
+
+ emit_signal(SNAME("shader_created"), shader);
}
- emit_signal(SNAME("shader_created"), shader);
+ file_path->set_text(file_path->get_text().get_base_dir());
hide();
}
@@ -215,9 +252,9 @@ void ShaderCreateDialog::_load_exist() {
hide();
}
-void ShaderCreateDialog::_language_changed(int p_language) {
- current_language = p_language;
- ShaderTypeData data = language_data[p_language];
+void ShaderCreateDialog::_type_changed(int p_language) {
+ current_type = p_language;
+ ShaderTypeData data = type_data[p_language];
String selected_ext = "." + data.default_extension;
String path = file_path->get_text();
@@ -238,6 +275,8 @@ void ShaderCreateDialog::_language_changed(int p_language) {
_path_changed(path);
file_path->set_text(path);
+ type_menu->set_item_disabled(int(SHADER_TYPE_INC), load_enabled);
+ mode_menu->set_disabled(p_language == SHADER_TYPE_INC);
template_menu->set_disabled(!data.use_templates);
template_menu->clear();
@@ -253,7 +292,7 @@ void ShaderCreateDialog::_language_changed(int p_language) {
template_menu->add_item(TTR("N/A"));
}
- EditorSettings::get_singleton()->set_project_metadata("shader_setup", "last_selected_language", language_menu->get_item_text(language_menu->get_selected()));
+ EditorSettings::get_singleton()->set_project_metadata("shader_setup", "last_selected_language", type_menu->get_item_text(type_menu->get_selected()));
_update_dialog();
}
@@ -270,12 +309,12 @@ void ShaderCreateDialog::_built_in_toggled(bool p_enabled) {
void ShaderCreateDialog::_browse_path() {
file_browse->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
file_browse->set_title(TTR("Open Shader / Choose Location"));
- file_browse->get_ok_button()->set_text(TTR("Open"));
+ file_browse->set_ok_button_text(TTR("Open"));
file_browse->set_disable_overwrite_warning(true);
file_browse->clear_filters();
- List<String> extensions = language_data[language_menu->get_selected()].extensions;
+ List<String> extensions = type_data[type_menu->get_selected()].extensions;
for (const String &E : extensions) {
file_browse->add_filter("*." + E);
@@ -330,8 +369,8 @@ void ShaderCreateDialog::_path_submitted(const String &p_path) {
void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabled, bool p_load_enabled, int p_preferred_type, int p_preferred_mode) {
if (!p_base_path.is_empty()) {
initial_base_path = p_base_path.get_basename();
- file_path->set_text(initial_base_path + "." + language_data[language_menu->get_selected()].default_extension);
- current_language = language_menu->get_selected();
+ file_path->set_text(initial_base_path + "." + type_data[type_menu->get_selected()].default_extension);
+ current_type = type_menu->get_selected();
} else {
initial_base_path = "";
file_path->set_text("");
@@ -342,8 +381,8 @@ void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabl
load_enabled = p_load_enabled;
if (p_preferred_type > -1) {
- language_menu->select(p_preferred_type);
- _language_changed(p_preferred_type);
+ type_menu->select(p_preferred_type);
+ _type_changed(p_preferred_type);
}
if (p_preferred_mode > -1) {
@@ -351,7 +390,7 @@ void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabl
_mode_changed(p_preferred_mode);
}
- _language_changed(current_language);
+ _type_changed(current_type);
_path_changed(file_path->get_text());
}
@@ -384,14 +423,14 @@ String ShaderCreateDialog::_validate_path(const String &p_path) {
HashSet<String> extensions;
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
- for (const String &ext : language_data[i].extensions) {
+ for (const String &ext : type_data[i].extensions) {
if (!extensions.has(ext)) {
extensions.insert(ext);
}
}
}
- ShaderTypeData data = language_data[language_menu->get_selected()];
+ ShaderTypeData data = type_data[type_menu->get_selected()];
bool found = false;
bool match = false;
@@ -399,8 +438,8 @@ String ShaderCreateDialog::_validate_path(const String &p_path) {
for (const String &ext : extensions) {
if (ext.nocasecmp_to(extension) == 0) {
found = true;
- for (const String &lang_ext : language_data[current_language].extensions) {
- if (lang_ext.nocasecmp_to(extension) == 0) {
+ for (const String &type_ext : type_data[current_type].extensions) {
+ if (type_ext.nocasecmp_to(extension) == 0) {
match = true;
break;
}
@@ -469,20 +508,20 @@ void ShaderCreateDialog::_update_dialog() {
builtin_warning_label->set_visible(is_built_in);
if (is_built_in) {
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
_msg_path_valid(true, TTR("Built-in shader (into scene file)."));
} else if (is_new_shader_created) {
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
if (is_path_valid) {
_msg_path_valid(true, TTR("Will create a new shader file."));
}
} else if (load_enabled) {
- get_ok_button()->set_text(TTR("Load"));
+ set_ok_button_text(TTR("Load"));
if (is_path_valid) {
_msg_path_valid(true, TTR("Will load an existing shader file."));
}
} else {
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
_msg_path_valid(false, TTR("Shader file already exists."));
shader_ok = false;
@@ -504,6 +543,7 @@ void ShaderCreateDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("config", "path", "built_in_enabled", "load_enabled"), &ShaderCreateDialog::config, DEFVAL(true), DEFVAL(true));
ADD_SIGNAL(MethodInfo("shader_created", PropertyInfo(Variant::OBJECT, "shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader")));
+ ADD_SIGNAL(MethodInfo("shader_include_created", PropertyInfo(Variant::OBJECT, "shader_include", PROPERTY_HINT_RESOURCE_TYPE, "ShaderInclude")));
}
ShaderCreateDialog::ShaderCreateDialog() {
@@ -547,24 +587,27 @@ ShaderCreateDialog::ShaderCreateDialog() {
vb->add_child(status_panel);
add_child(vb);
- // Language.
+ // Type.
- language_menu = memnew(OptionButton);
- language_menu->set_custom_minimum_size(Size2(250, 0) * EDSCALE);
- language_menu->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- gc->add_child(memnew(Label(TTR("Language:"))));
- gc->add_child(language_menu);
+ type_menu = memnew(OptionButton);
+ type_menu->set_custom_minimum_size(Size2(250, 0) * EDSCALE);
+ type_menu->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ gc->add_child(memnew(Label(TTR("Type:"))));
+ gc->add_child(type_menu);
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
- String language;
+ String type;
bool invalid = false;
switch (i) {
case SHADER_TYPE_TEXT:
- language = "Shader";
- default_language = i;
+ type = "Shader";
+ default_type = i;
break;
case SHADER_TYPE_VISUAL:
- language = "VisualShader";
+ type = "VisualShader";
+ break;
+ case SHADER_TYPE_INC:
+ type = "ShaderInclude";
break;
case SHADER_TYPE_MAX:
invalid = true;
@@ -576,13 +619,13 @@ ShaderCreateDialog::ShaderCreateDialog() {
if (invalid) {
continue;
}
- language_menu->add_item(language);
+ type_menu->add_item(type);
}
- if (default_language >= 0) {
- language_menu->select(default_language);
+ if (default_type >= 0) {
+ type_menu->select(default_type);
}
- current_language = default_language;
- language_menu->connect("item_selected", callable_mp(this, &ShaderCreateDialog::_language_changed));
+ current_type = default_type;
+ type_menu->connect("item_selected", callable_mp(this, &ShaderCreateDialog::_type_changed));
// Modes.
@@ -638,7 +681,7 @@ ShaderCreateDialog::ShaderCreateDialog() {
alert->get_label()->set_custom_minimum_size(Size2(325, 60) * EDSCALE);
add_child(alert);
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
set_hide_on_ok(false);
set_title(TTR("Create Shader"));
diff --git a/editor/shader_create_dialog.h b/editor/shader_create_dialog.h
index 6737ce4f10..bf031c3601 100644
--- a/editor/shader_create_dialog.h
+++ b/editor/shader_create_dialog.h
@@ -47,6 +47,7 @@ class ShaderCreateDialog : public ConfirmationDialog {
enum ShaderType {
SHADER_TYPE_TEXT,
SHADER_TYPE_VISUAL,
+ SHADER_TYPE_INC,
SHADER_TYPE_MAX,
};
@@ -56,14 +57,14 @@ class ShaderCreateDialog : public ConfirmationDialog {
bool use_templates = false;
};
- List<ShaderTypeData> language_data;
+ List<ShaderTypeData> type_data;
GridContainer *gc = nullptr;
Label *error_label = nullptr;
Label *path_error_label = nullptr;
Label *builtin_warning_label = nullptr;
PanelContainer *status_panel = nullptr;
- OptionButton *language_menu = nullptr;
+ OptionButton *type_menu = nullptr;
OptionButton *mode_menu = nullptr;
OptionButton *template_menu = nullptr;
CheckBox *internal = nullptr;
@@ -79,8 +80,8 @@ class ShaderCreateDialog : public ConfirmationDialog {
bool built_in_enabled = true;
bool load_enabled = false;
bool re_check_path = false;
- int current_language = -1;
- int default_language = -1;
+ int current_type = -1;
+ int default_type = -1;
int current_mode = 0;
int current_template = 0;
@@ -89,7 +90,7 @@ class ShaderCreateDialog : public ConfirmationDialog {
void _path_hbox_sorted();
void _path_changed(const String &p_path = String());
void _path_submitted(const String &p_path = String());
- void _language_changed(int p_language = 0);
+ void _type_changed(int p_type = 0);
void _built_in_toggled(bool p_enabled);
void _template_changed(int p_template = 0);
void _mode_changed(int p_mode = 0);
@@ -113,4 +114,4 @@ public:
ShaderCreateDialog();
};
-#endif
+#endif // SHADER_CREATE_DIALOG_H
diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index bfabf269bf..1cd1b4ea00 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -79,7 +79,7 @@ protected:
}
bool _set(const StringName &p_name, const Variant &p_value) {
- Variant existing = RS::get_singleton()->global_variable_get(p_name);
+ Variant existing = RS::get_singleton()->global_shader_uniform_get(p_name);
if (existing.get_type() == Variant::NIL) {
return false;
@@ -88,9 +88,9 @@ protected:
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(TTR("Set Shader Global Variable"));
- undo_redo->add_do_method(RS::get_singleton(), "global_variable_set", p_name, p_value);
- undo_redo->add_undo_method(RS::get_singleton(), "global_variable_set", p_name, existing);
- RS::GlobalVariableType type = RS::get_singleton()->global_variable_get_type(p_name);
+ undo_redo->add_do_method(RS::get_singleton(), "global_shader_uniform_set", p_name, p_value);
+ undo_redo->add_undo_method(RS::get_singleton(), "global_shader_uniform_set", p_name, existing);
+ RS::GlobalShaderUniformType type = RS::get_singleton()->global_shader_uniform_get_type(p_name);
Dictionary gv;
gv["type"] = global_var_type_names[type];
if (type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
@@ -117,17 +117,17 @@ protected:
}
bool _get(const StringName &p_name, Variant &r_ret) const {
- r_ret = RS::get_singleton()->global_variable_get(p_name);
+ r_ret = RS::get_singleton()->global_shader_uniform_get(p_name);
return r_ret.get_type() != Variant::NIL;
}
void _get_property_list(List<PropertyInfo> *p_list) const {
Vector<StringName> variables;
- variables = RS::get_singleton()->global_variable_get_list();
+ variables = RS::get_singleton()->global_shader_uniform_get_list();
for (int i = 0; i < variables.size(); i++) {
PropertyInfo pinfo;
pinfo.name = variables[i];
- switch (RS::get_singleton()->global_variable_get_type(variables[i])) {
+ switch (RS::get_singleton()->global_shader_uniform_get_type(variables[i])) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
pinfo.type = Variant::BOOL;
} break;
@@ -156,7 +156,7 @@ protected:
pinfo.type = Variant::VECTOR3I;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC4: {
- pinfo.type = Variant::PACKED_INT32_ARRAY;
+ pinfo.type = Variant::VECTOR4I;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2I: {
pinfo.type = Variant::RECT2I;
@@ -171,7 +171,7 @@ protected:
pinfo.type = Variant::VECTOR3I;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC4: {
- pinfo.type = Variant::PACKED_INT32_ARRAY;
+ pinfo.type = Variant::VECTOR4I;
} break;
case RS::GLOBAL_VAR_TYPE_FLOAT: {
pinfo.type = Variant::FLOAT;
@@ -183,7 +183,7 @@ protected:
pinfo.type = Variant::VECTOR3;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- pinfo.type = Variant::QUATERNION;
+ pinfo.type = Variant::VECTOR4;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
pinfo.type = Variant::RECT2;
@@ -204,7 +204,7 @@ protected:
pinfo.type = Variant::TRANSFORM3D;
} break;
case RS::GLOBAL_VAR_TYPE_MAT4: {
- pinfo.type = Variant::PACKED_INT32_ARRAY;
+ pinfo.type = Variant::PROJECTION;
} break;
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
pinfo.type = Variant::OBJECT;
@@ -241,7 +241,7 @@ public:
}
};
-static Variant create_var(RS::GlobalVariableType p_type) {
+static Variant create_var(RS::GlobalShaderUniformType p_type) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
return false;
@@ -376,12 +376,12 @@ static Variant create_var(RS::GlobalVariableType p_type) {
void ShaderGlobalsEditor::_variable_added() {
String var = variable_name->get_text().strip_edges();
if (var.is_empty() || !var.is_valid_identifier()) {
- EditorNode::get_singleton()->show_warning(TTR("Please specify a valid variable identifier name."));
+ EditorNode::get_singleton()->show_warning(TTR("Please specify a valid shader uniform identifier name."));
return;
}
- if (RenderingServer::get_singleton()->global_variable_get(var).get_type() != Variant::NIL) {
- EditorNode::get_singleton()->show_warning(vformat(TTR("Global variable '%s' already exists'"), var));
+ if (RenderingServer::get_singleton()->global_shader_uniform_get(var).get_type() != Variant::NIL) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Global shader uniform '%s' already exists'"), var));
return;
}
@@ -395,11 +395,11 @@ void ShaderGlobalsEditor::_variable_added() {
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
- Variant value = create_var(RS::GlobalVariableType(variable_type->get_selected()));
+ Variant value = create_var(RS::GlobalShaderUniformType(variable_type->get_selected()));
- undo_redo->create_action(TTR("Add Shader Global Variable"));
- undo_redo->add_do_method(RS::get_singleton(), "global_variable_add", var, RS::GlobalVariableType(variable_type->get_selected()), value);
- undo_redo->add_undo_method(RS::get_singleton(), "global_variable_remove", var);
+ undo_redo->create_action(TTR("Add Shader Global Uniform"));
+ undo_redo->add_do_method(RS::get_singleton(), "global_shader_uniform_add", var, RS::GlobalShaderUniformType(variable_type->get_selected()), value);
+ undo_redo->add_undo_method(RS::get_singleton(), "global_shader_uniform_remove", var);
Dictionary gv;
gv["type"] = global_var_type_names[variable_type->get_selected()];
gv["value"] = value;
@@ -414,9 +414,9 @@ void ShaderGlobalsEditor::_variable_added() {
void ShaderGlobalsEditor::_variable_deleted(const String &p_variable) {
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
- undo_redo->create_action(TTR("Add Shader Global Variable"));
- undo_redo->add_do_method(RS::get_singleton(), "global_variable_remove", p_variable);
- undo_redo->add_undo_method(RS::get_singleton(), "global_variable_add", p_variable, RS::get_singleton()->global_variable_get_type(p_variable), RS::get_singleton()->global_variable_get(p_variable));
+ undo_redo->create_action(TTR("Add Shader Global Uniform"));
+ undo_redo->add_do_method(RS::get_singleton(), "global_shader_uniform_remove", p_variable);
+ undo_redo->add_undo_method(RS::get_singleton(), "global_shader_uniform_add", p_variable, RS::get_singleton()->global_shader_uniform_get_type(p_variable), RS::get_singleton()->global_shader_uniform_get(p_variable));
undo_redo->add_do_property(ProjectSettings::get_singleton(), "shader_globals/" + p_variable, Variant());
undo_redo->add_undo_property(ProjectSettings::get_singleton(), "shader_globals/" + p_variable, ProjectSettings::get_singleton()->get("shader_globals/" + p_variable));
@@ -479,7 +479,7 @@ ShaderGlobalsEditor::ShaderGlobalsEditor() {
inspector->set_use_wide_editors(true);
inspector->set_property_name_style(EditorPropertyNameProcessor::STYLE_RAW);
inspector->set_use_deletable_properties(true);
- inspector->connect("property_deleted", callable_mp(this, &ShaderGlobalsEditor::_variable_deleted), varray(), CONNECT_DEFERRED);
+ inspector->connect("property_deleted", callable_mp(this, &ShaderGlobalsEditor::_variable_deleted), CONNECT_DEFERRED);
interface = memnew(ShaderGlobalsEditorInterface);
interface->connect("var_changed", Callable(this, "_changed"));
diff --git a/editor/translations/af.po b/editor/translations/af.po
index 00c05287a1..f2e389b6f5 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
@@ -468,6 +473,10 @@ msgid "Pressure"
msgstr "Herset Zoem"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2182,14 +2191,15 @@ msgstr "Gunstelinge:"
msgid "Recent:"
msgstr "Onlangse:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Soek:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Passendes:"
@@ -2251,8 +2261,8 @@ msgstr "Soek Vervanging Hulpbron:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2846,8 +2856,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Verwyder Seleksie"
#: editor/editor_export.cpp
#, fuzzy
@@ -5556,6 +5567,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11854,6 +11874,11 @@ msgid "New Animation"
msgstr "Optimaliseer Animasie"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Eienskappe"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18703,6 +18728,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 +18741,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 +18787,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 +19024,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 +19038,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20374,15 +20424,15 @@ msgstr "Kon nie vouer skep nie."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Moet 'n geldige uitbreiding gebruik."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20406,15 +20456,15 @@ msgstr "Ongeldige naam."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Moet 'n geldige uitbreiding gebruik."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20645,7 +20695,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 +21405,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 +21418,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 ""
@@ -21426,7 +21486,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstant"
@@ -23389,6 +23449,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Anim Verander Transform"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24563,6 +24628,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 +25017,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..cda76c44c8 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -64,13 +64,17 @@
# ywmaa <ywmaa.personal@gmail.com>, 2022.
# Awab Najim <dev.djvan@gmail.com>, 2022.
# Abderrahim <abdoudido117@gmail.com>, 2022.
+# Jhon Smith <jhonsmaith3@gmail.com>, 2022.
+# Oo mohab oO <mohab9225@gmail.com>, 2022.
+# عبد الرحمن أبو سعدة ||Abd Alrahman abo saada <abdalrahmanabs2005@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-23 03:57+0000\n"
+"Last-Translator: عبد الرحمن أبو سعدة ||Abd Alrahman abo saada "
+"<abdalrahmanabs2005@gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/"
"godot/ar/>\n"
"Language: ar\n"
@@ -79,7 +83,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -447,6 +451,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
@@ -479,7 +488,7 @@ msgstr "الموقع العالمي"
#: core/os/input_event.cpp
msgid "Factor"
-msgstr "المعامل"
+msgstr "العامل"
#: core/os/input_event.cpp
msgid "Button Index"
@@ -498,6 +507,10 @@ msgid "Pressure"
msgstr "الضغط"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "نسبي"
@@ -542,7 +555,7 @@ msgstr "قناة"
#: core/os/input_event.cpp main/main.cpp
msgid "Message"
-msgstr "الرسالة"
+msgstr "رسالة"
#: core/os/input_event.cpp
msgid "Pitch"
@@ -574,7 +587,7 @@ msgstr "التطبيق"
#: core/project_settings.cpp main/main.cpp
msgid "Config"
-msgstr "تعديل"
+msgstr "إعداد"
#: core/project_settings.cpp
msgid "Project Settings Override"
@@ -591,7 +604,7 @@ msgstr "تجاوز إعدادات المشروع"
#: scene/3d/skeleton.cpp scene/main/node.cpp scene/resources/mesh_library.cpp
#: scene/resources/skin.cpp
msgid "Name"
-msgstr "الأسم"
+msgstr "الاسم"
#: core/project_settings.cpp editor/editor_help.cpp
#: modules/visual_script/visual_script_nodes.cpp platform/uwp/export/export.cpp
@@ -851,9 +864,8 @@ msgid "Compression"
msgstr "ضغط"
#: core/project_settings.cpp
-#, fuzzy
msgid "Formats"
-msgstr "البنية (اللاحقة)"
+msgstr "التنسيقات"
#: core/project_settings.cpp
#, fuzzy
@@ -933,7 +945,7 @@ msgstr "المسار"
#: core/script_language.cpp
msgid "Source Code"
-msgstr "مصدر الرمز"
+msgstr "الكود المصدري || Ø§Ù„Ø´ÙØ±Ø© المصدرية"
#: core/translation.cpp editor/project_settings_editor.cpp
msgid "Locale"
@@ -945,7 +957,7 @@ msgstr "إختبار"
#: core/translation.cpp scene/resources/font.cpp
msgid "Fallback"
-msgstr "تقهقر"
+msgstr "تراجع | انسحاب"
#: core/ustring.cpp scene/resources/segment_shape_2d.cpp
msgid "B"
@@ -1003,7 +1015,7 @@ msgstr "حجم Ùهرس المخزن المؤقت للوحة المضلعات (K
#: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp
#: servers/visual_server.cpp
msgid "2D"
-msgstr "2D"
+msgstr "ثنائي الأبعاد"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
@@ -2166,14 +2178,15 @@ msgstr "Ø§Ù„Ù…ÙØ¶Ù„Ø©:"
msgid "Recent:"
msgstr "الحالي:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "بحث:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "يطابق:"
@@ -2233,8 +2246,8 @@ msgstr "البحث عن مورد بديل:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2807,7 +2820,7 @@ msgstr "تصدير المشروع لمنصة:"
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "نسخ مسار العÙقدة"
#: editor/editor_export.cpp
@@ -4857,7 +4870,7 @@ msgstr "نظام Ø§Ù„Ù…Ù„ÙØ§Øª"
#: editor/editor_node.cpp
msgid "Expand Bottom Panel"
-msgstr "توسيع التبويب السÙلي"
+msgstr "توسيع القائمة السÙلية"
#: editor/editor_node.cpp
msgid "Don't Save"
@@ -5592,6 +5605,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "تنقل ÙÙŠ سجل أزرار الماوس الإضاÙية"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "تحديد الملئ خريطة-الشبكة"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "المظهر"
@@ -9288,7 +9310,7 @@ msgstr "المحاذاة الذكية"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Hide"
-msgstr ""
+msgstr "Ø§Ø®ÙØ§Ø¡"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -9672,7 +9694,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 +10770,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"
@@ -11831,6 +11853,11 @@ msgid "New Animation"
msgstr "رسومية متحركة جديدة"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "ترشيح الدوال"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "السرعة:"
@@ -16267,26 +16294,24 @@ msgid "Set Room Point Position"
msgstr "حدد موقع نقطة الإنحناء"
#: editor/spatial_editor_gizmos.cpp scene/3d/portal.cpp
-#, fuzzy
msgid "Portal Margin"
-msgstr "تحديد الهامش"
+msgstr "هامش البوابة"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Edge"
-msgstr ""
+msgstr "Ø­Ø§ÙØ© Ø§Ù„ØºØ±ÙØ©"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Arrow"
-msgstr ""
+msgstr "سهم البوابة"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Portal Point Position"
-msgstr "حدد موقع نقطة الإنحناء"
+msgstr "حدد موقع نقطة البوابة"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Front"
-msgstr ""
+msgstr "واجهة البوابة"
#: editor/spatial_editor_gizmos.cpp
#, fuzzy
@@ -16325,18 +16350,16 @@ msgid "Occluder Polygon Front"
msgstr "أنشئ شكل Ù…ÙØ·Ø¨Ù‚"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Polygon Back"
-msgstr "أنشئ شكل Ù…ÙØ·Ø¨Ù‚"
+msgstr ""
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Hole"
-msgstr "أنشئ شكل Ù…ÙØ·Ø¨Ù‚"
+msgstr ""
#: main/main.cpp
msgid "Godot Physics"
-msgstr ""
+msgstr "Ùيزيائيات جودو"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
@@ -16415,9 +16438,8 @@ msgid "Driver"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Driver Name"
-msgstr "اسم النص البرمجي:"
+msgstr "اسم النص البرمجي"
#: main/main.cpp
msgid "Fallback To GLES2"
@@ -16436,22 +16458,20 @@ msgid "Allow hiDPI"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "V-Sync"
-msgstr "مزامنة"
+msgstr "مزامنة (مزامنة كرت الشاشة)"
#: main/main.cpp
-#, fuzzy
msgid "Use V-Sync"
-msgstr "استخدام المحاذاة"
+msgstr "استخدام مزامنة كرت الشاشة"
#: main/main.cpp
msgid "Per Pixel Transparency"
-msgstr ""
+msgstr "Ø´ÙØ§Ùية بيكسل القلم"
#: main/main.cpp
msgid "Allowed"
-msgstr ""
+msgstr "مسموح"
#: main/main.cpp
msgid "Intended Usage"
@@ -16463,18 +16483,16 @@ msgid "Framebuffer Allocation"
msgstr "تحديد الإطار"
#: main/main.cpp platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Energy Saving"
-msgstr "خطأ ÙÙŠ Ø§Ù„Ø­ÙØ¸"
+msgstr "توÙير الطاقة"
#: main/main.cpp
msgid "Threads"
-msgstr ""
+msgstr "مسارات"
#: main/main.cpp servers/physics_2d/physics_2d_server_wrap_mt.h
-#, fuzzy
msgid "Thread Model"
-msgstr "أظهر المود"
+msgstr "نوع المسار"
#: main/main.cpp
msgid "Thread Safe BVH"
@@ -16492,9 +16510,8 @@ msgstr "الوثائق الإلكترونية"
#: main/main.cpp scene/gui/scroll_container.cpp scene/gui/text_edit.cpp
#: scene/main/scene_tree.cpp scene/register_scene_types.cpp
-#, fuzzy
msgid "Common"
-msgstr "المجتمع"
+msgstr "شائع"
#: main/main.cpp
#, fuzzy
@@ -16514,7 +16531,7 @@ msgstr ""
#: scene/gui/scroll_container.cpp scene/gui/text_edit.cpp scene/gui/tree.cpp
#: scene/main/viewport.cpp scene/register_scene_types.cpp
msgid "GUI"
-msgstr ""
+msgstr "واجهة المستخدم الرسومية"
#: main/main.cpp
msgid "Drop Mouse On GUI Input Disabled"
@@ -16538,9 +16555,8 @@ msgid "Physics Interpolation"
msgstr "وضعية Ø§Ù„Ø£Ø³ØªÙŠÙØ§Ø¡"
#: main/main.cpp
-#, fuzzy
msgid "Enable Warnings"
-msgstr "تمكين الترشيح Filtering"
+msgstr "ØªÙØ¹ÙŠÙ„ التحذيرات"
#: main/main.cpp
#, fuzzy
@@ -16557,25 +16573,23 @@ msgstr ""
#: main/main.cpp
msgid "iOS"
-msgstr ""
+msgstr "IOS"
#: main/main.cpp
msgid "Hide Home Indicator"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Input Devices"
-msgstr "جميع الأجهزة"
+msgstr "أجهزة الإدخال"
#: main/main.cpp
-#, fuzzy
msgid "Pointing"
-msgstr "نقطة"
+msgstr "يشير"
#: main/main.cpp
msgid "Touch Delay"
-msgstr ""
+msgstr "تأخير اللمس"
#: main/main.cpp servers/visual_server.cpp
msgid "GLES3"
@@ -16617,7 +16631,7 @@ msgstr ""
#: main/main.cpp
msgid "Fullsize"
-msgstr ""
+msgstr "الحجم الكامل"
#: main/main.cpp scene/resources/dynamic_font.cpp
#, fuzzy
@@ -16690,21 +16704,20 @@ msgstr "انتهت المهلة."
#: main/main.cpp
msgid "Runtime"
-msgstr ""
+msgstr "اثناء التشغيل"
#: main/main.cpp
msgid "Unhandled Exception Policy"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Main Loop Type"
-msgstr "إيجاد نوع العÙقدة"
+msgstr "نوع الحلقة الرئيسية"
#: main/main.cpp scene/gui/texture_progress.cpp
#: scene/gui/viewport_container.cpp
msgid "Stretch"
-msgstr ""
+msgstr "تمدد"
#: main/main.cpp
#, fuzzy
@@ -16759,38 +16772,33 @@ msgstr "تغيير نص٠قطر الدائرة الداخلي"
#: modules/csg/csg_gizmos.cpp
msgid "Change Torus Outer Radius"
-msgstr "تعديل نص٠القطر الخارجي للطارة Torus Outer Radius"
+msgstr "تعديل نص٠القطر الخارجي للمسنن"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Operation"
-msgstr "الإعدادات"
+msgstr "عملية"
#: modules/csg/csg_shape.cpp
msgid "Calculate Tangents"
-msgstr ""
+msgstr "احسب الظلال"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Use Collision"
-msgstr "التصادم"
+msgstr "استخدم التصادم"
#: modules/csg/csg_shape.cpp servers/physics_2d_server.cpp
-#, fuzzy
msgid "Collision Layer"
-msgstr "وضع التصادم"
+msgstr ""
#: modules/csg/csg_shape.cpp scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp
#: scene/3d/ray_cast.cpp scene/3d/spring_arm.cpp
#: scene/resources/navigation_mesh.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collision Mask"
-msgstr "وضع التصادم"
+msgstr ""
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Invert Faces"
-msgstr "حالة التحويل"
+msgstr "اقلب الوجوه"
#: modules/csg/csg_shape.cpp scene/2d/navigation_agent_2d.cpp
#: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_agent.cpp
@@ -16810,37 +16818,32 @@ msgid "Radial Segments"
msgstr "معاملات المشهد الرئيس:"
#: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Rings"
-msgstr "تحذيرات"
+msgstr "خواتم"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Smooth Faces"
-msgstr "خطوة ناعمة"
+msgstr "وجوه ناعمة"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Sides"
-msgstr "أظهر الموجهات"
+msgstr "جهات"
#: modules/csg/csg_shape.cpp
msgid "Cone"
msgstr ""
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Inner Radius"
-msgstr "تغيير نص٠قطر الدائرة الداخلي"
+msgstr "القطر الداخلي"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Outer Radius"
-msgstr "تعديل نص٠القطر الخارجي للطارة Torus Outer Radius"
+msgstr "القطر الخارجي"
#: modules/csg/csg_shape.cpp
msgid "Ring Sides"
-msgstr ""
+msgstr "جهات الخاتم"
#: modules/csg/csg_shape.cpp scene/2d/collision_polygon_2d.cpp
#: scene/2d/light_occluder_2d.cpp scene/2d/polygon_2d.cpp
@@ -16851,16 +16854,15 @@ msgstr "Ø§Ù„Ù…ÙØ¶Ù„عات"
#: modules/csg/csg_shape.cpp
msgid "Spin Degrees"
-msgstr ""
+msgstr "درجة الدوران"
#: modules/csg/csg_shape.cpp
msgid "Spin Sides"
-msgstr ""
+msgstr "جهة الدوران"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Node"
-msgstr "لصق العÙقد"
+msgstr "مسار العقدة"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16891,9 +16893,8 @@ msgid "Path Continuous U"
msgstr "متواصل"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path U Distance"
-msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
+msgstr "المسار المحلي"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16901,28 +16902,26 @@ msgid "Path Joined"
msgstr "دوران عشوائي:"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Compression Mode"
-msgstr "وضع التصادم"
+msgstr "وضع الضغط"
#: modules/enet/networked_multiplayer_enet.cpp
#, fuzzy
msgid "Transfer Channel"
-msgstr "تعديل التحولات"
+msgstr "نقل القنوات"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Channel Count"
-msgstr "كائن"
+msgstr "عدد القنوات"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Always Ordered"
-msgstr "إظهار الشبكة دوماً"
+msgstr "مطلوب دائمًا"
#: modules/enet/networked_multiplayer_enet.cpp
+#, fuzzy
msgid "Server Relay"
-msgstr ""
+msgstr "تناوب الخادم"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "DTLS Verify"
@@ -16946,30 +16945,25 @@ msgid "Use FBX"
msgstr ""
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Config File"
-msgstr "تخزين الملÙ:"
+msgstr "مل٠التهيئة"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Load Once"
-msgstr "تحميل المورد"
+msgstr "حمل مرة واحدة"
#: modules/gdnative/gdnative.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Singleton"
-msgstr "الهيكل"
+msgstr ""
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Symbol Prefix"
-msgstr "بادئة:"
+msgstr "رمز البادئة"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Reloadable"
-msgstr "إعادة تحميل"
+msgstr "قابل لإعادة التحميل"
#: modules/gdnative/gdnative.cpp
#: modules/gdnative/gdnative_library_singleton_editor.cpp
@@ -16987,7 +16981,7 @@ msgstr "اختر تبعيات المكتبة لأجل هذا الإدخال"
#: modules/gdnative/gdnative_library_editor_plugin.cpp
msgid "Remove current entry"
-msgstr "مسح المدخلة الحالية"
+msgstr "مسح المدخلات الحالية"
#: modules/gdnative/gdnative_library_editor_plugin.cpp
msgid "Double click to create a new entry"
@@ -17036,9 +17030,8 @@ msgid "Script Class"
msgstr "اسم النص البرمجي:"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Icon Path"
-msgstr "مسار التركيز"
+msgstr "مسار الأيقونة"
#: modules/gdnative/register_types.cpp
msgid "GDNative"
@@ -17046,18 +17039,16 @@ msgstr "لغة البرمجة GDNative"
#: modules/gdscript/editor/gdscript_highlighter.cpp
#: modules/gdscript/gdscript.cpp
-#, fuzzy
msgid "GDScript"
-msgstr "النص البرمجي"
+msgstr "لغة جي دي"
#: modules/gdscript/editor/gdscript_highlighter.cpp
msgid "Function Definition Color"
-msgstr ""
+msgstr "لون تعري٠الدالة"
#: modules/gdscript/editor/gdscript_highlighter.cpp
-#, fuzzy
msgid "Node Path Color"
-msgstr "نسخ مسار العÙقدة"
+msgstr "لون مسار العقدة"
#: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp
msgid "Max Call Stack"
@@ -17085,11 +17076,11 @@ msgstr "ليس نص برمجي مع نموذج"
#: modules/gdscript/gdscript_functions.cpp
msgid "Not based on a script"
-msgstr "لا تستند الى نص برمجي"
+msgstr "غير مبني على نص برمجي"
#: modules/gdscript/gdscript_functions.cpp
msgid "Not based on a resource file"
-msgstr "لا يعتمد على مل٠موارد"
+msgstr "غير مبني على مل٠موارد"
#: modules/gdscript/gdscript_functions.cpp
msgid "Invalid instance dictionary format (missing @path)"
@@ -17112,14 +17103,12 @@ msgid "Object can't provide a length."
msgstr "لا يمكن للكائن أن يمنح طولاً."
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Language Server"
-msgstr "اللغة:"
+msgstr "لغة الخادك"
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Enable Smart Resolve"
-msgstr "لا يمكن الحل"
+msgstr "ØªÙØ¹ÙŠÙ„ الحل الذكي"
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Show Native Symbols In Editor"
@@ -17127,7 +17116,7 @@ msgstr ""
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Use Thread"
-msgstr ""
+msgstr "استخدم المسار"
#: modules/gltf/editor_scene_exporter_gltf_plugin.cpp
#, fuzzy
@@ -17150,14 +17139,12 @@ msgid "Byte Offset"
msgstr "مقدار إزاحة الشبكة:"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Component Type"
-msgstr "مكونات"
+msgstr "نوع المكون"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Normalized"
-msgstr "البنية (اللاحقة)"
+msgstr ""
#: modules/gltf/gltf_accessor.cpp
#, fuzzy
@@ -17165,14 +17152,12 @@ msgid "Count"
msgstr "الكمية:"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Min"
-msgstr "ميبي بايت (MiB)"
+msgstr "أقل"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Max"
-msgstr "خلط"
+msgstr "أعلى"
#: modules/gltf/gltf_accessor.cpp
#, fuzzy
@@ -17222,7 +17207,7 @@ msgstr "جميع الأجهزة"
#: modules/gltf/gltf_camera.cpp
#, fuzzy
msgid "FOV Size"
-msgstr "الحجم:"
+msgstr "حجم مساحةالرؤية"
#: modules/gltf/gltf_camera.cpp
msgid "Zfar"
@@ -17241,27 +17226,25 @@ msgstr "خطي"
#: scene/resources/environment.cpp scene/resources/material.cpp
#: scene/resources/particles_material.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp
-#, fuzzy
msgid "Color"
msgstr "الألوان"
#: modules/gltf/gltf_light.cpp scene/3d/reflection_probe.cpp
#: scene/resources/environment.cpp
msgid "Intensity"
-msgstr ""
+msgstr "Ø§Ù„ÙƒØ«Ø§ÙØ© | الشدة"
#: modules/gltf/gltf_light.cpp scene/2d/light_2d.cpp scene/3d/light.cpp
-#, fuzzy
msgid "Range"
-msgstr "تغير"
+msgstr "نطاق"
#: modules/gltf/gltf_light.cpp
msgid "Inner Cone Angle"
-msgstr ""
+msgstr "زاوية المخروط الداخلية"
#: modules/gltf/gltf_light.cpp
msgid "Outer Cone Angle"
-msgstr ""
+msgstr "زاوية المخروط الخارجية"
#: modules/gltf/gltf_mesh.cpp
#, fuzzy
@@ -17274,9 +17257,8 @@ msgid "Instance Materials"
msgstr "تغيرات المادة:"
#: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp
-#, fuzzy
msgid "Parent"
-msgstr "إعادة اختيار الأبوة"
+msgstr "أب"
#: modules/gltf/gltf_node.cpp
#, fuzzy
@@ -17300,20 +17282,20 @@ msgstr "أبناء قابلين للتعديل"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp
#, fuzzy
msgid "Joints"
-msgstr "نقطة"
+msgstr "Ø§Ù„Ù…ÙØ§ØµÙ„"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp
msgid "Roots"
-msgstr ""
+msgstr "الجذور"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_state.cpp
msgid "Unique Names"
-msgstr ""
+msgstr "أسماء مميزة"
#: modules/gltf/gltf_skeleton.cpp
#, fuzzy
msgid "Godot Bone Node"
-msgstr "عقدة التنقل الزمني"
+msgstr "عقدة جودو العظمية"
#: modules/gltf/gltf_skin.cpp
#, fuzzy
@@ -17330,9 +17312,8 @@ msgid "Inverse Binds"
msgstr ""
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Non Joints"
-msgstr "تحريك النÙقطة"
+msgstr "بلا Ù…ÙØ§ØµÙ„"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Bone I"
@@ -17356,12 +17337,11 @@ msgstr ""
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Gloss Factor"
-msgstr ""
+msgstr "عامل اللمعان"
#: modules/gltf/gltf_spec_gloss.cpp
-#, fuzzy
msgid "Specular Factor"
-msgstr "Ù…ÙØ´ØºÙ„ الكمية القياسية Scalar."
+msgstr "عامل ال"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Spec Gloss Img"
@@ -17369,17 +17349,15 @@ msgstr ""
#: modules/gltf/gltf_state.cpp
msgid "Json"
-msgstr ""
+msgstr "جيسون"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Major Version"
-msgstr "الإصدار"
+msgstr "إصدار رئيسي"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Minor Version"
-msgstr "الإصدار"
+msgstr "إصدار ÙØ±Ø¹ÙŠ"
#: modules/gltf/gltf_state.cpp
#, fuzzy
@@ -17400,9 +17378,8 @@ msgid "Accessors"
msgstr ""
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Scene Name"
-msgstr "المسار للمشهد:"
+msgstr "اسم المشهد"
#: modules/gltf/gltf_state.cpp
#, fuzzy
@@ -17417,21 +17394,19 @@ msgstr "المزايا"
#: modules/gltf/gltf_state.cpp platform/uwp/export/export.cpp
msgid "Images"
-msgstr ""
+msgstr "الصور"
#: modules/gltf/gltf_state.cpp
msgid "Cameras"
-msgstr ""
+msgstr "الكاميرات"
#: modules/gltf/gltf_state.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Lights"
-msgstr "ضوء"
+msgstr "الأضواء"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Unique Animation Names"
-msgstr "إسم رسم المتحرك جديد:"
+msgstr "أسماء حركات مميزة"
#: modules/gltf/gltf_state.cpp
#, fuzzy
@@ -17439,37 +17414,32 @@ msgid "Skeletons"
msgstr "الهيكل"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Skeleton To Node"
-msgstr "اختر عÙقدة"
+msgstr "هيكل إلى عقدة"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Animations"
-msgstr "الرسومات المتحركة:"
+msgstr "الحركات"
#: modules/gltf/gltf_texture.cpp
-#, fuzzy
msgid "Src Image"
-msgstr "إظهار العظام"
+msgstr "مصدر الصورة"
#: modules/gridmap/grid_map.cpp
msgid "Mesh Library"
msgstr "مكتبة المجسم"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Physics Material"
-msgstr "نسبة الإطار الÙيزيائي %"
+msgstr "مادة"
#: modules/gridmap/grid_map.cpp scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Use In Baked Light"
-msgstr "طبخ (إعداد) خرائط الضوء"
+msgstr "استخدام ÙÙŠ الإضاءة المطبوخة"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
msgid "Cell"
-msgstr ""
+msgstr "خلية"
#: modules/gridmap/grid_map.cpp
#, fuzzy
@@ -17477,19 +17447,16 @@ msgid "Octant Size"
msgstr "الواجهة View الأمامية"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center X"
-msgstr "المنتصÙ"
+msgstr "منتص٠س"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Y"
-msgstr "المنتصÙ"
+msgstr "منتص٠ص"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Z"
-msgstr "المنتصÙ"
+msgstr "منتصÙ"
#: modules/gridmap/grid_map.cpp scene/2d/collision_object_2d.cpp
#: scene/2d/tile_map.cpp scene/3d/collision_object.cpp scene/3d/soft_body.cpp
@@ -17655,14 +17622,12 @@ msgid "Generate buffers"
msgstr "ولد AABB"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Direct lighting"
-msgstr "الاتجاهات"
+msgstr "إضاءة مباشرة"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
-#, fuzzy
msgid "Indirect lighting"
-msgstr "Ø§Ù„Ù…Ø³Ø§ÙØ© البادئة يميناً"
+msgstr "إضاءة غير مباشرة"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
#, fuzzy
@@ -17698,27 +17663,24 @@ msgstr ""
#: modules/minimp3/resource_importer_mp3.cpp
#: modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
#: modules/stb_vorbis/resource_importer_ogg_vorbis.cpp
-#, fuzzy
msgid "Loop Offset"
-msgstr "Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ù„:"
+msgstr "إزاحة الحلقة"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Eye Height"
-msgstr ""
+msgstr "Ø§Ø±ØªÙØ§Ø¹ الغين"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "IOD"
msgstr ""
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display Width"
-msgstr "عرض Ø§Ù„Ù…ÙØ®Ø·Ø· Wireframe"
+msgstr "عرض الشاشة"
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display To Lens"
-msgstr "عرض من غير ظلال"
+msgstr "شاشة إلى عدسة"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Oversample"
@@ -17737,14 +17699,12 @@ msgid "Class name can't be a reserved keyword"
msgstr "لا يمكن أن يكون اسم الص٠كلمة محجوزة"
#: modules/mono/csharp_script.cpp
-#, fuzzy
msgid "Build Solution"
-msgstr "تعبئة Ø§Ù„Ù…ÙØ­Ø¯Ø¯"
+msgstr ""
#: modules/mono/editor/csharp_project.cpp
-#, fuzzy
msgid "Auto Update Project"
-msgstr "مشروع غير مسمى"
+msgstr "تحديث المشروع تلقائيًا"
#: modules/mono/mono_gd/gd_mono_utils.cpp
msgid "End of inner exception stack trace"
@@ -17821,9 +17781,8 @@ msgid "Seamless"
msgstr ""
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "As Normal Map"
-msgstr "حجم عشوائي:"
+msgstr "كخريطة عادية"
#: modules/opensimplex/noise_texture.cpp
msgid "Bump Strength"
@@ -17831,7 +17790,7 @@ msgstr ""
#: modules/opensimplex/noise_texture.cpp
msgid "Noise"
-msgstr ""
+msgstr "ضوضاء"
#: modules/opensimplex/noise_texture.cpp
#, fuzzy
@@ -17844,7 +17803,7 @@ msgstr ""
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Period"
-msgstr ""
+msgstr "ÙØªØ±Ø©"
#: modules/opensimplex/open_simplex_noise.cpp
#, fuzzy
@@ -17860,14 +17819,12 @@ msgid "Subject"
msgstr ""
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Names"
-msgstr "الأسم"
+msgstr "الأسماء"
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Strings"
-msgstr "الإعدادات:"
+msgstr "النصوص"
#: modules/upnp/upnp.cpp
msgid "Discover Multicast If"
@@ -17882,14 +17839,12 @@ msgid "Discover IPv6"
msgstr ""
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Description URL"
-msgstr "الوصÙ"
+msgstr "وص٠الرابط"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Service Type"
-msgstr "تحيد نوع المتغير"
+msgstr "نوع الخدمة"
#: modules/upnp/upnp_device.cpp
msgid "IGD Control URL"
@@ -17943,9 +17898,8 @@ msgid "Stack overflow with stack depth:"
msgstr "حدوث تجاوز للتكدس ( Stack overflow) مع عمق التكدس:"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Visual Script"
-msgstr "بحث VisualScript"
+msgstr "البرمجة المرئية"
#: modules/visual_script/visual_script_editor.cpp
msgid "Change Signal Arguments"
@@ -17976,14 +17930,12 @@ msgid "Add Output Port"
msgstr "Ø£Ø¶Ù Ù…Ù†ÙØ° إخراج"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Port Type"
-msgstr "تغيير النوع"
+msgstr "تغيير نوع Ø§Ù„Ù…Ù†ÙØ°"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Port Name"
-msgstr "غيّر اسم Ù…Ù†ÙØ° Ø§Ù„Ù…ÙØ¯Ø®Ù„ات"
+msgstr "تغيير اسم Ø§Ù„Ù…Ù†ÙØ°"
#: modules/visual_script/visual_script_editor.cpp
msgid "Override an existing built-in function."
@@ -18169,7 +18121,7 @@ msgstr "تعديل قيمة الإدخال"
#: modules/visual_script/visual_script_editor.cpp
msgid "Resize Comment"
-msgstr "تغيير حجم التعليق"
+msgstr "تغيير حجم الملاحظة"
#: modules/visual_script/visual_script_editor.cpp
msgid "Can't create function with a function node."
@@ -18844,6 +18796,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 +18809,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 +18862,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 +19121,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 +19129,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 +19143,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\"."
@@ -20592,15 +20570,15 @@ msgstr "لا يمكن العثور على Ù…ÙØªØ§Ø­ المتجر، لا يمكÙ
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "صيغة غير صالحة."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20624,15 +20602,15 @@ msgstr "اسم غير صالح."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "صيغة غير صالحة."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20874,7 +20852,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 +21633,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 +21646,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 +21678,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."
@@ -21734,7 +21722,7 @@ msgstr "Ø§Ù„Ø³ÙØ±"
msgid "Rotation Degrees"
msgstr "ÙŠÙØ¯ÙŠØ± %s من الدرجات."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "ثابت"
@@ -22784,9 +22772,8 @@ msgstr ""
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
#: scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Pixel Size"
-msgstr "محاذاة البكسل"
+msgstr "حجم البكسل"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Billboard"
@@ -23325,9 +23312,8 @@ msgid "Solver"
msgstr ""
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Exclude Nodes"
-msgstr "حذ٠العÙقد"
+msgstr "استثناء العÙقد"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23393,14 +23379,12 @@ msgid "Linear Ortho"
msgstr "نظر من الخل٠(متعامد/ليس له بعد ثالث)"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Upper Angle"
-msgstr "الأحر٠الكبيرة (Uppercase)"
+msgstr "الزاوية العلوية"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Lower Angle"
-msgstr "الأحر٠الصغيرة (Lowercase)"
+msgstr "الزاوية السÙلية"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23556,9 +23540,8 @@ msgid "Thickness"
msgstr ""
#: scene/3d/reflection_probe.cpp scene/main/viewport.cpp
-#, fuzzy
msgid "Update Mode"
-msgstr "وضع التدوير"
+msgstr "وضع التحديث"
#: scene/3d/reflection_probe.cpp
#, fuzzy
@@ -23657,7 +23640,7 @@ msgstr "يجب ØªÙˆØ§ÙØ± مدير-غر٠(RoomManager) واحد Ùقط ÙÙŠ Ø´Ø
#: scene/3d/room_manager.cpp
msgid "Main"
-msgstr ""
+msgstr "رئيسي | الرئيسي"
#: scene/3d/room_manager.cpp scene/animation/animation_blend_tree.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
@@ -23866,6 +23849,11 @@ msgstr ""
"قم بتغيير الحجم ÙÙŠ أشكال تصادم الأتباع (Children) بدلاً من ذلك."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Ø§Ù„Ø§Ø­ØªÙØ§Ø¸ بالتحوّل الشمولي Global"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23915,13 +23903,12 @@ msgid "Per-Wheel Motion"
msgstr "زر العجلة للأسÙÙ„"
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Engine Force"
-msgstr "مستندات الإنترنت"
+msgstr "قوة المحرك"
#: scene/3d/vehicle_body.cpp
msgid "Brake"
-msgstr ""
+msgstr "ÙØ±Ø§Ù…Ù„ | مكابح"
#: scene/3d/vehicle_body.cpp
msgid "Steering"
@@ -23941,9 +23928,8 @@ msgid "Use As Steering"
msgstr ""
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Wheel"
-msgstr "العجلة نحو الأقصى."
+msgstr "عجلة"
#: scene/3d/vehicle_body.cpp
msgid "Roll Influence"
@@ -24073,14 +24059,12 @@ msgid "Fadeout Time"
msgstr "وقت التلاشي X (ثواني):"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Auto Restart"
-msgstr "إعادة تشغيل تلقائية:"
+msgstr "إعادة تشغيل تلقائية"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Autorestart"
-msgstr "إعادة تشغيل تلقائية:"
+msgstr "إعادة تشغيل تلقائية"
#: scene/animation/animation_blend_tree.cpp
msgid "Delay"
@@ -25122,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 "ØªÙØ¹ÙŠÙ„"
@@ -25525,17 +25514,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 +25521,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..af28a85240 100644
--- a/editor/translations/az.po
+++ b/editor/translations/az.po
@@ -5,49 +5,49 @@
#
# Jafar Tarverdiyev <cefertarverdiyevv@gmail.com>, 2021.
# Lucifer25x <umudyt2006@gmail.com>, 2021.
+# Ümid Quliyev <lucifer25x@protonmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2021-09-16 14:36+0000\n"
-"Last-Translator: Lucifer25x <umudyt2006@gmail.com>\n"
+"PO-Revision-Date: 2022-08-05 01:04+0000\n"
+"Last-Translator: Ümid Quliyev <lucifer25x@protonmail.com>\n"
"Language-Team: Azerbaijani <https://hosted.weblate.org/projects/godot-engine/"
"godot/az/>\n"
"Language: az\n"
"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.9-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
+#, fuzzy
msgid "Tablet Driver"
-msgstr ""
+msgstr "Planşet sürücü"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Clipboard"
-msgstr "Pano boÅŸdur!"
+msgstr "Pano"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Current Screen"
-msgstr "Animasiya xüsusiyyətləri."
+msgstr "Aktiv Ekran"
#: core/bind/core_bind.cpp
msgid "Exit Code"
-msgstr ""
+msgstr "Çıxış Kodu"
#: core/bind/core_bind.cpp
msgid "V-Sync Enabled"
-msgstr ""
+msgstr "V-Sync Aktivdir"
#: core/bind/core_bind.cpp main/main.cpp
msgid "V-Sync Via Compositor"
-msgstr ""
+msgstr "V-Sync Kompozitor Vasitəsilə"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Delta Smoothing"
-msgstr ""
+msgstr "Delta hamarlanması"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode"
@@ -59,28 +59,28 @@ msgstr ""
#: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp
msgid "Keep Screen On"
-msgstr ""
+msgstr "Ekranı Açıq Tut"
#: core/bind/core_bind.cpp
msgid "Min Window Size"
-msgstr ""
+msgstr "Minimum Pəncərə Ölçüsü"
#: core/bind/core_bind.cpp
msgid "Max Window Size"
-msgstr ""
+msgstr "Maksimum Pəncərə Ölçüsü"
#: core/bind/core_bind.cpp
msgid "Screen Orientation"
-msgstr ""
+msgstr "Pəncərə Nisbəti"
#: core/bind/core_bind.cpp core/project_settings.cpp main/main.cpp
#: platform/uwp/os_uwp.cpp
msgid "Window"
-msgstr ""
+msgstr "Pəncərə"
#: core/bind/core_bind.cpp core/project_settings.cpp
msgid "Borderless"
-msgstr ""
+msgstr "Kənarsız"
#: core/bind/core_bind.cpp
msgid "Per Pixel Transparency Enabled"
@@ -88,29 +88,28 @@ msgstr ""
#: core/bind/core_bind.cpp core/project_settings.cpp
msgid "Fullscreen"
-msgstr ""
+msgstr "Bütün Ekran"
#: core/bind/core_bind.cpp
msgid "Maximized"
-msgstr ""
+msgstr "Böyüdülmüş"
#: core/bind/core_bind.cpp
msgid "Minimized"
-msgstr ""
+msgstr "Kiçildilmiş"
#: core/bind/core_bind.cpp core/project_settings.cpp scene/gui/dialogs.cpp
#: scene/gui/graph_node.cpp
msgid "Resizable"
-msgstr ""
+msgstr "Ölçüsü Dəyişdirilə Bilər"
#: core/bind/core_bind.cpp core/os/input_event.cpp scene/2d/node_2d.cpp
#: scene/2d/physics_body_2d.cpp scene/2d/remote_transform_2d.cpp
#: scene/3d/physics_body.cpp scene/3d/remote_transform.cpp
#: scene/gui/control.cpp scene/gui/line_edit.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Position"
-msgstr "Animasiyanı Təmizləmə"
+msgstr "Pozisiya"
#: core/bind/core_bind.cpp core/project_settings.cpp editor/editor_settings.cpp
#: main/main.cpp modules/gridmap/grid_map.cpp
@@ -122,7 +121,7 @@ msgstr "Animasiyanı Təmizləmə"
#: scene/resources/style_box.cpp scene/resources/texture.cpp
#: scene/resources/visual_shader.cpp servers/visual_server.cpp
msgid "Size"
-msgstr ""
+msgstr "Ölçü"
#: core/bind/core_bind.cpp
msgid "Endian Swap"
@@ -131,25 +130,23 @@ msgstr ""
#: core/bind/core_bind.cpp
#, fuzzy
msgid "Editor Hint"
-msgstr "RedaktÉ™ et"
+msgstr "Editor İpucu"
#: core/bind/core_bind.cpp
msgid "Print Error Messages"
-msgstr ""
+msgstr "Xəta Mesajlarını Yazdır"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Iterations Per Second"
-msgstr "İnterpolasiya rejimi"
+msgstr "Hər Saniyədə İterasiya Sayı"
#: core/bind/core_bind.cpp
msgid "Target FPS"
-msgstr ""
+msgstr "Hədəf FPS"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Time Scale"
-msgstr "Animasya Açarlarını Ölçülə"
+msgstr "Zaman Ölçəyi"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Physics Jitter Fix"
@@ -157,25 +154,23 @@ msgstr ""
#: core/bind/core_bind.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Error"
-msgstr ""
+msgstr "Xəta"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Error String"
-msgstr "Yükləmə xətası:"
+msgstr "Xəta Yazısı"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Error Line"
-msgstr "Yükləmə xətası:"
+msgstr "Xəta Sətiri"
#: core/bind/core_bind.cpp
msgid "Result"
-msgstr ""
+msgstr "Nəticə"
#: core/command_queue_mt.cpp core/message_queue.cpp main/main.cpp
msgid "Memory"
-msgstr ""
+msgstr "YaddaÅŸ"
#: core/command_queue_mt.cpp core/message_queue.cpp
#: core/register_core_types.cpp drivers/gles2/rasterizer_canvas_base_gles2.cpp
@@ -186,11 +181,11 @@ msgstr ""
#: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h
#: servers/visual_server.cpp
msgid "Limits"
-msgstr ""
+msgstr "Limitlər"
#: core/command_queue_mt.cpp
msgid "Command Queue"
-msgstr ""
+msgstr "Æmr NövbÉ™si"
#: core/command_queue_mt.cpp
msgid "Multithreading Queue Size (KB)"
@@ -200,14 +195,13 @@ msgstr ""
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
#: scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Function"
-msgstr "Funksiyalar:"
+msgstr "Funksiya"
#: core/image.cpp core/packed_data_container.cpp scene/2d/polygon_2d.cpp
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
msgid "Data"
-msgstr ""
+msgstr "Məlumat"
#: core/io/file_access_network.cpp core/register_core_types.cpp
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp main/main.cpp
@@ -215,16 +209,15 @@ msgstr ""
#: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h
#: scene/gui/file_dialog.cpp
msgid "Network"
-msgstr ""
+msgstr "Şəbəkə"
#: core/io/file_access_network.cpp
-#, fuzzy
msgid "Remote FS"
-msgstr "Sil"
+msgstr "Uzaqdan FS"
#: core/io/file_access_network.cpp
msgid "Page Size"
-msgstr ""
+msgstr "Səhifə Ölçüsü"
#: core/io/file_access_network.cpp
msgid "Page Read Ahead"
@@ -232,12 +225,11 @@ msgstr ""
#: core/io/http_client.cpp
msgid "Blocking Mode Enabled"
-msgstr ""
+msgstr "Bloklama Modu Aktivdir"
#: core/io/http_client.cpp
-#, fuzzy
msgid "Connection"
-msgstr "QoÅŸ"
+msgstr "ÆlaqÉ™"
#: core/io/http_client.cpp
msgid "Read Chunk Size"
@@ -245,15 +237,15 @@ msgstr ""
#: core/io/marshalls.cpp
msgid "Object ID"
-msgstr ""
+msgstr "Obyekt ID"
#: core/io/multiplayer_api.cpp core/io/packet_peer.cpp
msgid "Allow Object Decoding"
-msgstr ""
+msgstr "Obyekt Deşifrəsinə İzn Verin"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
msgid "Refuse New Network Connections"
-msgstr ""
+msgstr "Yeni ŞəbÉ™kÉ™ ÆlaqÉ™lÉ™rindÉ™n İmtina Et"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
msgid "Network Peer"
@@ -261,16 +253,15 @@ msgstr ""
#: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp
msgid "Root Node"
-msgstr ""
+msgstr "Kök Düyün"
#: core/io/networked_multiplayer_peer.cpp
-#, fuzzy
msgid "Refuse New Connections"
-msgstr "QoÅŸ"
+msgstr "Yeni ÆlaqÉ™lÉ™rdÉ™n İmtina Et"
#: core/io/networked_multiplayer_peer.cpp
msgid "Transfer Mode"
-msgstr ""
+msgstr "Transfer Modu"
#: core/io/packet_peer.cpp
msgid "Encode Buffer Max Size"
@@ -294,16 +285,15 @@ msgstr ""
#: core/io/stream_peer.cpp
msgid "Data Array"
-msgstr ""
+msgstr "Məlumat Siyahısı"
#: core/io/stream_peer_ssl.cpp
msgid "Blocking Handshake"
-msgstr ""
+msgstr "Æl Sıxmağın Qarşısının Alınması"
#: core/io/udp_server.cpp
-#, fuzzy
msgid "Max Pending Connections"
-msgstr "ÆlaqÉ™ni redaktÉ™ edin:"
+msgstr "GözlÉ™nilÉ™n Maksimum ÆlaqÉ™lÉ™r"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -325,7 +315,6 @@ msgstr ""
"format."
#: core/math/expression.cpp
-#, fuzzy
msgid "Invalid input %d (not passed) in expression"
msgstr "İfadədə uyğunsuz giriş %d (ötürülmədi)"
@@ -407,6 +396,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
@@ -459,6 +453,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2154,14 +2152,15 @@ msgstr "Favoritlər:"
msgid "Recent:"
msgstr "Son:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Axtar:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "UyÄŸunlaÅŸmalar:"
@@ -2221,8 +2220,8 @@ msgstr "ÆvÉ™zetmÉ™ mÉ™nbÉ™yini axtarın:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2800,8 +2799,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Animasiyanı Təmizləmə"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5396,6 +5396,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11431,6 +11440,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Animasiyanı Təmizləmə"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18002,6 +18016,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 +18029,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 +18073,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 +18298,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 +18312,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
@@ -19592,14 +19631,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19621,14 +19659,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19848,7 +19885,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 +20566,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 +20579,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 ""
@@ -20600,7 +20646,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22511,6 +22557,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Animasiyanı Təmizləmə"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23636,6 +23687,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 +24058,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..d2d7a56dc3 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
@@ -487,6 +492,10 @@ msgid "Pressure"
msgstr "ÐатиÑк"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2168,14 +2177,15 @@ msgstr "Любими:"
msgid "Recent:"
msgstr "ПоÑледни:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "ТърÑене:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "СъвпадениÑ:"
@@ -2235,8 +2245,8 @@ msgstr "ТърÑене на замеÑтващ реÑурÑ:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2804,8 +2814,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Копиране на избраното"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5480,6 +5491,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "ÐаÑтройки"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11645,6 +11665,11 @@ msgid "New Animation"
msgstr "Ðова анимациÑ"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Филтриране на методите"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "СкороÑÑ‚:"
@@ -18343,6 +18368,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 +18381,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 +18432,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 +18677,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 +18692,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“."
@@ -20058,15 +20111,15 @@ msgstr "Ðе е намерено хранилище за ключове. ИзнÐ
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Ðеправилно разширение."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20090,15 +20143,15 @@ msgstr "Ðеправилно име."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Ðеправилно разширение."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20333,7 +20386,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 +21134,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 +21147,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 +21178,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."
@@ -21157,7 +21220,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr "ГрадуÑи на завъртане"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Глобална конÑтанта"
@@ -23195,6 +23258,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "ИзчиÑтване на транÑформациÑта"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24391,6 +24459,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 +24861,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..6f1e8f945d 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
@@ -479,6 +484,10 @@ msgid "Pressure"
msgstr "পà§à¦°à¦¿à¦¸à§‡à¦Ÿ..."
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "আপেকà§à¦·à¦¿à¦• সà§à¦¨à§à¦¯à¦¾à¦ª"
@@ -2224,14 +2233,15 @@ msgstr "ফেবরিট/পà§à¦°à¦¿à¦¯à¦¼-সমূহ:"
msgid "Recent:"
msgstr "সামà§à¦ªà§à¦°à¦¤à¦¿à¦•:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ করà§à¦¨:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "মিলসমূহ:"
@@ -2293,8 +2303,8 @@ msgstr "পà§à¦°à¦¤à¦¿à¦¸à§à¦¥à¦¾à¦ªà¦• রিসোরà§à¦¸-à¦à¦° অনà§
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2894,7 +2904,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "পথ পà§à¦°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿/কপি করà§à¦¨"
#: editor/editor_export.cpp
@@ -5807,6 +5817,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সমূহ অপসারণ করà§à¦¨"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -12468,6 +12487,11 @@ msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨"
#: editor/plugins/sprite_frames_editor_plugin.cpp
#, fuzzy
+msgid "Filter animations"
+msgstr "ফিলà§à¦Ÿà¦¾à¦°à¦¸à¦®à§‚হ"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
msgid "Speed:"
msgstr "গতি (FPS):"
@@ -19778,6 +19802,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 +19815,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 +19866,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 +20112,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 +20126,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
@@ -21490,15 +21539,15 @@ msgstr "ফোলà§à¦¡à¦¾à¦° তৈরী করা সমà§à¦­à¦¬ হয়নà¦
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "অগà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21522,15 +21571,15 @@ msgstr "অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯ নাম।"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "অগà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21776,7 +21825,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 +22584,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 +22597,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 +22628,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."
@@ -22613,7 +22672,7 @@ msgstr "ভà§à¦°à¦®à¦£"
msgid "Rotation Degrees"
msgstr "%s ডিগà§à¦°à¦¿ ঘূরà§à¦£à¦¿à¦¤ হচà§à¦›à§‡à¥¤"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "ধà§à¦°à§à¦¬à¦•/কনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦Ÿ"
@@ -24686,6 +24745,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "সারà§à¦¬à¦œà¦¨à§€à¦¨ রূপানà§à¦¤à¦° রাখà§à¦¨"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25926,6 +25990,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 +26396,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..823490a280 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
@@ -449,6 +454,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2099,14 +2108,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2162,8 +2172,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2722,8 +2732,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Tro Fiñvskeudenn"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5305,6 +5316,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11296,6 +11315,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Tro Fiñvskeudenn"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17814,6 +17838,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 +17851,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 +17895,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 +18117,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 +18131,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
@@ -19385,14 +19434,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19414,14 +19462,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19639,7 +19686,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 +20358,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 +20370,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 ""
@@ -20381,7 +20437,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22274,6 +22330,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Tro Fiñvskeudenn"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23379,6 +23440,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 +23803,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..04c9b7761c 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -22,7 +22,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:15+0000\n"
+"PO-Revision-Date: 2022-07-09 21:11+0000\n"
"Last-Translator: Roger VC <rogervilarasau@gmail.com>\n"
"Language-Team: Catalan <https://hosted.weblate.org/projects/godot-engine/"
"godot/ca/>\n"
@@ -67,7 +67,7 @@ msgstr "Mode de Baix Us del Processador"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode Sleep (µsec)"
-msgstr ""
+msgstr "Mode d'ús del processador baix en repòs (µseg)"
#: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp
msgid "Keep Screen On"
@@ -136,8 +136,9 @@ msgid "Size"
msgstr "Mida"
#: core/bind/core_bind.cpp
+#, fuzzy
msgid "Endian Swap"
-msgstr ""
+msgstr "Intercanvi d'endian"
#: core/bind/core_bind.cpp
msgid "Editor Hint"
@@ -161,9 +162,8 @@ msgid "Time Scale"
msgstr "Escala de Temps"
#: core/bind/core_bind.cpp main/main.cpp
-#, fuzzy
msgid "Physics Jitter Fix"
-msgstr "Fotograma de Física %"
+msgstr "Correcció de fluctuacions de física"
#: core/bind/core_bind.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Error"
@@ -246,25 +246,23 @@ msgstr "Connexió"
#: core/io/http_client.cpp
msgid "Read Chunk Size"
-msgstr ""
+msgstr "Llegeix la mida del fragment"
#: core/io/marshalls.cpp
msgid "Object ID"
msgstr "ID de l'Objecte"
#: core/io/multiplayer_api.cpp core/io/packet_peer.cpp
-#, fuzzy
msgid "Allow Object Decoding"
-msgstr "Activa l'Efecte Paper Ceba"
+msgstr "Permet la descodificació d'objectes"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
msgid "Refuse New Network Connections"
msgstr "Rebutja les noves connexions de xarxa"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Network Peer"
-msgstr "Perfilador de Xarxa"
+msgstr "Parell de xarxa"
#: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp
msgid "Root Node"
@@ -275,13 +273,12 @@ msgid "Refuse New Connections"
msgstr "Rebutjar Noves Connexions"
#: core/io/networked_multiplayer_peer.cpp
-#, fuzzy
msgid "Transfer Mode"
-msgstr "Tipus de Transformació"
+msgstr "Mode de transferència"
#: core/io/packet_peer.cpp
msgid "Encode Buffer Max Size"
-msgstr ""
+msgstr "Mida màxima de la memòria intermèdia de codificació"
#: core/io/packet_peer.cpp
msgid "Input Buffer Max Size"
@@ -297,7 +294,7 @@ msgstr ""
#: core/io/stream_peer.cpp
msgid "Big Endian"
-msgstr ""
+msgstr "Endian gran"
#: core/io/stream_peer.cpp
msgid "Data Array"
@@ -373,14 +370,12 @@ msgid "Max Size (KB)"
msgstr "Mida màxima (KB)"
#: core/os/input.cpp
-#, fuzzy
msgid "Mouse Mode"
-msgstr "Mode de moviment"
+msgstr "Mode ratolí"
#: core/os/input.cpp
-#, fuzzy
msgid "Use Accumulated Input"
-msgstr "Elimina l'Entrada"
+msgstr "Utilitza l'entrada acumulada"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
@@ -388,9 +383,8 @@ msgid "Device"
msgstr "Dispositiu"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Alt"
-msgstr "Tot"
+msgstr "Alt"
#: core/os/input_event.cpp
msgid "Shift"
@@ -409,6 +403,10 @@ msgstr "Meta"
msgid "Command"
msgstr "Comunitat"
+#: core/os/input_event.cpp
+msgid "Physical"
+msgstr "Físic"
+
#: 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
@@ -416,9 +414,8 @@ msgid "Pressed"
msgstr "Premut"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Scancode"
-msgstr "Explora"
+msgstr "Codi d'escaneig"
#: core/os/input_event.cpp
msgid "Physical Scancode"
@@ -463,6 +460,10 @@ msgid "Pressure"
msgstr "Configuracions prestablertes"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relatiu"
@@ -794,7 +795,7 @@ msgstr "Renderitzat"
#: scene/resources/multimesh.cpp servers/visual/visual_server_scene.cpp
#: servers/visual_server.cpp
msgid "Quality"
-msgstr ""
+msgstr "Qualitat"
#: core/project_settings.cpp scene/gui/file_dialog.cpp
#: scene/main/scene_tree.cpp scene/resources/navigation_mesh.cpp
@@ -803,8 +804,9 @@ msgid "Filters"
msgstr "Filtres"
#: core/project_settings.cpp scene/main/viewport.cpp
+#, fuzzy
msgid "Sharpen Intensity"
-msgstr ""
+msgstr "Intensitat d'agudització"
#: core/project_settings.cpp editor/editor_export.cpp editor/editor_node.cpp
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
@@ -829,9 +831,8 @@ msgid "Profiler"
msgstr "Perfilador"
#: core/project_settings.cpp
-#, fuzzy
msgid "Max Functions"
-msgstr "Reanomena Funció"
+msgstr "Funcions màximes"
#: core/project_settings.cpp scene/3d/vehicle_body.cpp
msgid "Compression"
@@ -843,39 +844,39 @@ msgstr "Formats"
#: core/project_settings.cpp
msgid "Zstd"
-msgstr ""
+msgstr "Zstd"
#: core/project_settings.cpp
msgid "Long Distance Matching"
-msgstr ""
+msgstr "Coincidència de llarga distància"
#: core/project_settings.cpp
msgid "Compression Level"
-msgstr ""
+msgstr "Nivell de compressió"
#: core/project_settings.cpp
msgid "Window Log Size"
-msgstr ""
+msgstr "Mida del registre de la finestra"
#: core/project_settings.cpp
msgid "Zlib"
-msgstr ""
+msgstr "Zlib"
#: core/project_settings.cpp
msgid "Gzip"
-msgstr ""
+msgstr "Gzip"
#: core/project_settings.cpp platform/android/export/export.cpp
msgid "Android"
-msgstr ""
+msgstr "Android"
#: core/project_settings.cpp
msgid "Modules"
-msgstr ""
+msgstr "Mòduls"
#: core/register_core_types.cpp
msgid "TCP"
-msgstr ""
+msgstr "TCP"
#: core/register_core_types.cpp
msgid "Connect Timeout Seconds"
@@ -887,11 +888,11 @@ msgstr ""
#: core/register_core_types.cpp
msgid "Max Buffer (Power of 2)"
-msgstr ""
+msgstr "Memòria intermèdia màxima (potència de 2)"
#: core/register_core_types.cpp editor/editor_settings.cpp main/main.cpp
msgid "SSL"
-msgstr ""
+msgstr "SSL"
#: core/register_core_types.cpp main/main.cpp
msgid "Certificates"
@@ -904,9 +905,8 @@ msgid "Resource"
msgstr "Recurs"
#: core/resource.cpp
-#, fuzzy
msgid "Local To Scene"
-msgstr "Tanca l'Escena"
+msgstr "Local a l'escena"
#: core/resource.cpp editor/dependency_editor.cpp
#: editor/editor_autoload_settings.cpp editor/plugins/path_editor_plugin.cpp
@@ -975,7 +975,7 @@ msgstr ""
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Canvas Polygon Index Buffer Size (KB)"
-msgstr ""
+msgstr "Mida de la memòria intermèdia de l'índex del polígon de llenç (KB)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp editor/editor_settings.cpp
@@ -987,7 +987,7 @@ msgstr ""
#: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp
#: servers/visual_server.cpp
msgid "2D"
-msgstr ""
+msgstr "2D"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
@@ -997,14 +997,13 @@ msgstr "Ajustament Intel·ligent"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
-#, fuzzy
msgid "Use GPU Pixel Snap"
-msgstr "Utilitzar ajustament amb els Píxels"
+msgstr "Utilitza l'ajust de píxels de la GPU"
#: drivers/gles2/rasterizer_scene_gles2.cpp
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Immediate Buffer Size (KB)"
-msgstr ""
+msgstr "Mida de la memòria intermèdia immediata (KB)"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1015,28 +1014,27 @@ msgstr "Precalcular Lightmaps"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
msgid "Use Bicubic Sampling"
-msgstr ""
+msgstr "Utilitza el mostreig bicúbic"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Renderable Elements"
-msgstr ""
+msgstr "Elements renderitzables màxims"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Renderable Lights"
-msgstr ""
+msgstr "Llums màximes renderitzables"
#: drivers/gles3/rasterizer_scene_gles3.cpp
-#, fuzzy
msgid "Max Renderable Reflections"
-msgstr "Centra la Selecció"
+msgstr "Reflexions màximes renderitzables"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Lights Per Object"
-msgstr ""
+msgstr "Llums màximes per objecte"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Subsurface Scattering"
-msgstr ""
+msgstr "Dispersió subsuperficial"
#: drivers/gles3/rasterizer_scene_gles3.cpp editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
@@ -1052,9 +1050,8 @@ msgid "Scale"
msgstr "Escala"
#: drivers/gles3/rasterizer_scene_gles3.cpp
-#, fuzzy
msgid "Follow Surface"
-msgstr "Omple la Superfície"
+msgstr "Segueix la superfície"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Weight Samples"
@@ -1062,11 +1059,11 @@ msgstr ""
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Voxel Cone Tracing"
-msgstr ""
+msgstr "Traçat del con Voxel"
#: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp
msgid "High Quality"
-msgstr ""
+msgstr "Alta qualitat"
#: drivers/gles3/rasterizer_storage_gles3.cpp
msgid "Blend Shape Max Buffer Size (KB)"
@@ -1144,9 +1141,8 @@ msgstr "Canviar crida d'animació"
#: editor/animation_track_editor.cpp scene/2d/animated_sprite.cpp
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Frame"
-msgstr "% del Fotograma"
+msgstr "Fotograma"
#: editor/animation_track_editor.cpp editor/editor_profiler.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
@@ -1157,9 +1153,8 @@ msgstr "Temps"
#: editor/animation_track_editor.cpp editor/import/resource_importer_scene.cpp
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Location"
-msgstr "Localització"
+msgstr "Ubicació"
#: editor/animation_track_editor.cpp modules/gltf/gltf_node.cpp
#: scene/2d/polygon_2d.cpp scene/2d/remote_transform_2d.cpp
@@ -1179,7 +1174,7 @@ msgstr "Quantitat d'arguments"
#: editor/animation_track_editor.cpp main/main.cpp
#: modules/mono/mono_gd/gd_mono.cpp
msgid "Args"
-msgstr ""
+msgstr "Args"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp
@@ -1343,9 +1338,8 @@ msgid "Position:"
msgstr "Posició:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Rotation:"
-msgstr "Pas de la Rotació:"
+msgstr "Rotació:"
#: editor/animation_track_editor.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -1368,7 +1362,7 @@ msgstr "(No vàlid, tipus esperat: %s)"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "Easing:"
-msgstr "Esmorteeix Entrada-Sortida"
+msgstr "Alleugeriment:"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1386,19 +1380,16 @@ msgid "Stream:"
msgstr "Element de ràdio"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start (s):"
-msgstr "Reinici (s):"
+msgstr "Inici (s):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End (s):"
-msgstr "Fosa d'entrada (s):"
+msgstr "Final (s):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation Clip:"
-msgstr "Animacions:"
+msgstr "Clip d'animació:"
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
@@ -1487,9 +1478,8 @@ msgid "Editors"
msgstr "Editors"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Confirm Insert Track"
-msgstr "Insereix una Pista i una Clau"
+msgstr "Confirmeu la inserció de pista"
#. TRANSLATORS: %s will be replaced by a phrase describing the target of track.
#: editor/animation_track_editor.cpp
@@ -1768,9 +1758,8 @@ msgid "Go to Previous Step"
msgstr "Anar al Pas Anterior"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Apply Reset"
-msgstr "Resetejar"
+msgstr "Aplica reinicialització"
#: editor/animation_track_editor.cpp
msgid "Optimize Animation"
@@ -2154,14 +2143,15 @@ msgstr "Favorits:"
msgid "Recent:"
msgstr "Recents:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Cerca:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Coincidències:"
@@ -2221,8 +2211,8 @@ msgstr "Cerca Recurs Reemplaçant:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2231,7 +2221,7 @@ msgstr "Obre"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "Propietaris de: %s (Total: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2425,10 +2415,10 @@ msgid "Licenses"
msgstr "Llicències"
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Error opening asset file for \"%s\" (not in ZIP format)."
msgstr ""
-"S'ha produit un error en obrir el fitxer comprimit, no té el format ZIP."
+"S'ha produït un error en obrir el fitxer de recursos per a \"%s\" (no en "
+"format ZIP)."
#: editor/editor_asset_installer.cpp
msgid "%s (already exists)"
@@ -2451,9 +2441,8 @@ msgid "Uncompressing Assets"
msgstr "Descomprimint Recursos"
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "The following files failed extraction from asset \"%s\":"
-msgstr "Ha fracassat l'extracció del paquet dels següents fitxers:"
+msgstr "Els fitxers següents no s'han pogut extraure del recurs \"%s\":"
#: editor/editor_asset_installer.cpp
msgid "(and %s more files)"
@@ -2473,9 +2462,8 @@ msgid "Install"
msgstr "Instal·la"
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Asset Installer"
-msgstr "Instal·lador de paquets"
+msgstr "Instal·lador de recursos"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
@@ -2645,9 +2633,8 @@ msgid "Create a new Bus Layout."
msgstr "Crea un nou Disseny de Bus."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Audio Bus Layout"
-msgstr "Obre un Disseny de Bus d'Àudio"
+msgstr "Disseny del bus d'àudio"
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -2803,7 +2790,8 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
+#, fuzzy
+msgid "Completed with warnings."
msgstr "Completat amb errors."
#: editor/editor_export.cpp
@@ -5616,6 +5604,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11971,6 +11968,11 @@ msgstr "Nova Animació"
#: editor/plugins/sprite_frames_editor_plugin.cpp
#, fuzzy
+msgid "Filter animations"
+msgstr "Filtrar mètodes"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
msgid "Speed:"
msgstr "Velocitat (FPS):"
@@ -19209,6 +19211,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 +19224,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 +19276,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 +19530,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 +19544,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
@@ -20947,15 +20974,15 @@ msgstr "No es pot obrir la plantilla per exportar."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "L'extensió no és vàlida."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20979,15 +21006,15 @@ msgstr "Nom no vàlid."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "L'extensió no és vàlida."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21234,7 +21261,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 +22028,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 +22041,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 +22073,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."
@@ -22081,7 +22118,7 @@ msgstr "Viatge"
msgid "Rotation Degrees"
msgstr "Rotació de %s graus."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Constant"
@@ -24195,6 +24232,11 @@ msgstr ""
"Modifica la mida de les Formes de Col. lisió Filles."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Manté la Transformació Global"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25451,6 +25493,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 +25905,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..1e92a92ae7 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
@@ -511,6 +516,10 @@ msgid "Pressure"
msgstr "Profil"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Přichytávat relativně"
@@ -2229,14 +2238,15 @@ msgstr "Oblíbené:"
msgid "Recent:"
msgstr "Nedávné:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Hledat:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Shody:"
@@ -2296,8 +2306,8 @@ msgstr "Hledat náhradní zdroj:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2872,7 +2882,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Kopírovat cestu k uzlu"
#: editor/editor_export.cpp
@@ -5667,6 +5677,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11939,6 +11958,11 @@ msgid "New Animation"
msgstr "Nová animace"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filtrovat metody"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Rychlost:"
@@ -18952,6 +18976,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 +18989,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 +19041,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 +19290,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 +19298,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 +19312,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
@@ -20685,15 +20734,15 @@ msgstr "NepodaÅ™ilo se najít úložiÅ¡tÄ› klíÄů, nelze exportovat."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Neplatná přípona."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20717,15 +20766,15 @@ msgstr "Neplatný název."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Neplatná přípona."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20968,7 +21017,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 +21785,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 +21798,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 +21830,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."
@@ -21815,7 +21874,7 @@ msgstr "Cestovat"
msgid "Rotation Degrees"
msgstr "Rotuji %s stupňů."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstantní"
@@ -23925,6 +23984,11 @@ msgstr ""
"Změňte velikost kolizních tvarů v uzlech potomků."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Zachovat globální transformaci"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25180,6 +25244,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 +25654,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 +25662,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..1bb05be6f9 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
@@ -481,6 +486,10 @@ msgid "Pressure"
msgstr "Forudindstillet..."
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2218,14 +2227,15 @@ msgstr "Favoritter:"
msgid "Recent:"
msgstr "Seneste:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Søgning:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Matches:"
@@ -2287,8 +2297,8 @@ msgstr "Søg Erstatnings Ressource:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2885,8 +2895,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Fjern Markering"
#: editor/editor_export.cpp
#, fuzzy
@@ -5720,6 +5731,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -12131,6 +12151,11 @@ msgid "New Animation"
msgstr "Ny Animation Navn:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filter mode:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -19157,6 +19182,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 +19195,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 +19243,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 +19488,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 +19502,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20862,15 +20912,15 @@ msgstr "Kan ikke åbne skabelon til eksport:\n"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Du skal bruge en gyldig udvidelse."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20894,15 +20944,15 @@ msgstr "Ugyldigt navn."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Du skal bruge en gyldig udvidelse."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21142,7 +21192,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 +21925,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 +21938,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 ""
@@ -21949,7 +22009,7 @@ msgstr "Rejse"
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstant"
@@ -23973,6 +24033,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Anim Skift Transformering"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25177,6 +25242,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 +25642,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..aa92914ada 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -82,13 +82,14 @@
# Christian Packenius <christian@packenius.com>, 2022.
# Sajeg <jfx@posteo.de>, 2022.
# Tobias Jacobs <tobi@jacobs.rocks>, 2022.
+# JeremyStarTM <jeremystartm@tuta.io>, 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: So Wieso <sowieso@dukun.de>\n"
+"PO-Revision-Date: 2022-07-31 18:34+0000\n"
+"Last-Translator: JeremyStarTM <jeremystartm@tuta.io>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot/de/>\n"
"Language: de\n"
@@ -96,7 +97,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -465,6 +466,10 @@ msgstr "Meta"
msgid "Command"
msgstr "Befehl"
+#: core/os/input_event.cpp
+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
@@ -516,6 +521,10 @@ msgid "Pressure"
msgstr "Druck"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr "Stift invertiert"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relativ"
@@ -1624,7 +1633,7 @@ msgstr "Methodenaufrufsspurschlüssel hinzufügen"
#: editor/animation_track_editor.cpp
msgid "Method not found in object:"
-msgstr "Methode nicht in Objekt gefunden:"
+msgstr "Methode im Objekt nicht gefunden:"
#: editor/animation_track_editor.cpp
msgid "Anim Move Keys"
@@ -2160,14 +2169,15 @@ msgstr "Favoriten:"
msgid "Recent:"
msgstr "Kürzlich:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Suche:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Treffer:"
@@ -2227,8 +2237,8 @@ msgstr "Ersatzressource suchen:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2805,7 +2815,8 @@ msgid "Project export for platform:"
msgstr "Projektexport für Plattform:"
#: editor/editor_export.cpp
-msgid "Completed with errors."
+#, fuzzy
+msgid "Completed with warnings."
msgstr "Fertiggestellt mit Fehlern."
#: editor/editor_export.cpp
@@ -5555,6 +5566,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Extramaustasten blättern durch Verlauf"
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr "Auswahl ziehen und fallen lassen"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr "Im Skript Editor bei ausgewähltem Node bleiben"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Aussehen"
@@ -11680,6 +11699,10 @@ msgid "New Animation"
msgstr "Neue Animation"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Filter animations"
+msgstr "Animationen filtern"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Geschwindigkeit:"
@@ -18129,7 +18152,7 @@ msgstr "Ungültiges Argument vom Typ:"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Invalid arguments:"
-msgstr "Ungültige Argumente:"
+msgstr "Ungültige Parameter:"
#: modules/visual_script/visual_script_nodes.cpp
msgid "a if cond, else b"
@@ -18439,6 +18462,10 @@ msgid "The package must have at least one '.' separator."
msgstr "Das Paket muss mindestens einen Punkt-Unterteiler ‚.‘ haben."
#: platform/android/export/export_plugin.cpp
+msgid "Custom Build"
+msgstr "Eigener Build"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr "Einen Build verwenden"
@@ -18446,6 +18473,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 +18517,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"
@@ -18729,16 +18756,16 @@ 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“ ist nur gültig wenn „Xr Mode“ als „Occulus Mobile VrApi“ "
-"oder „OpenXR“ gesetzt wurde."
+"„Hand Tracking“ ist nur gültig wenn „XR Mode“ als „Oculus Mobile VrApi“ oder "
+"„OpenXR“ gesetzt wurde."
#: 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“ ist nur gültig wenn „Xr Mode“ als „OpenXR“ gesetzt wurde."
+"„Passthrough“ ist nur gültig wenn „XR Mode“ als „OpenXR“ gesetzt wurde."
#: platform/android/export/export_plugin.cpp
msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
@@ -18746,23 +18773,51 @@ msgstr "„Export AAB“ ist nur gültig wenn „Use Custom Build“ aktiviert i
#: 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 ""
+"Das „Min SDK“ zu überschreiben 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 ""
-"Das „Min Sdk“ zu ändern ist nur möglich wenn „Use Custom Build“ aktiviert "
+"„Min SDK“ sollte eine gültige Ganzzahl sein, war aber „%s“, was ungültig ist."
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+"„Min SDK“ kann nicht niedriger als %d sein, der Version, die die Godot-"
+"Bibliothek benötigt."
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+"„Target SDK“ kann nur überschrieben werden wenn „Use Custom Build“ aktiviert "
"ist."
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
-"Das „Target Sdk“ zu ändern ist nur möglich wenn „Use Custom Build“ aktiviert "
+"„Taret SDK“ sollte eine gültige Ganzzahl sein, war aber „%s“, was ungültig "
"ist."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
msgstr ""
-"Die Version des „Target Sdk“ muss größer gleich der des „Min Sdk“ sein."
+"„Target SDK“ %d ist höher als die Standardversion %d. Diese Kombination "
+"könnte funktionieren, wurde aber nicht getestet und könnte gegebenenfalls "
+"instabil sein."
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
+msgstr ""
+"Die „Target SDK“-Version muss größer gleich der „Min SDK“-Version sein."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
@@ -19598,8 +19653,8 @@ msgid ""
"Could not start codesign executable, make sure Xcode command line tools are "
"installed."
msgstr ""
-"Codesign-Anwendung konnte nicht gestartet werden. Wurden die Xcode-"
-"Kommandozeilen-Hilfsprogramme installiert?"
+"Codesign-Anwendung konnte nicht gestartet werden, stelle sicher dass die "
+"Xcode-Kommandozeilen-Tools installiert sind."
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
msgid "No identity found."
@@ -20091,17 +20146,18 @@ msgid "Could not find wine executable at \"%s\"."
msgstr "Anwendung wine konnte nicht gefunden werden in „%s“."
#: platform/windows/export/export.cpp
+#, fuzzy
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
"Anwendung rcedit konnte nicht gestartet werden. Bitte rcedit-Pfad in "
"Editoreinstellungen festlegen (Export > Windows > Rcedit)."
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
msgstr ""
"Modifikation der Anwendung durch rcedit fehlgeschlagen:\n"
"%s"
@@ -20123,17 +20179,18 @@ msgid "Invalid timestamp server."
msgstr "Ungültiger Zeitstempelserver."
#: platform/windows/export/export.cpp
+#, fuzzy
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
"Anwendung signtool konnte nicht gestartet werden. Bitte signtool-Pfad in "
"Editoreinstellungen festlegen (Export > Windows > Signtool)."
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
msgstr ""
"Signieren der Anwendung durch Signtool ist fehlgeschlagen:\n"
"%s"
@@ -20354,7 +20411,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 +21105,35 @@ 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
+msgid "Pathfinding"
+msgstr "Pfadfinden"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
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
+msgid "Avoidance"
+msgstr "Vermeiden"
+
+#: 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 +21149,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."
@@ -21125,7 +21192,7 @@ msgstr "Reisekosten"
msgid "Rotation Degrees"
msgstr "Rotationswinkel"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr "Globale Rotation"
@@ -22217,6 +22284,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"
@@ -23051,6 +23121,10 @@ msgstr ""
"geändert werden."
#: scene/3d/spatial.cpp
+msgid "Global Translation"
+msgstr "Globale Verschiebung"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr "Matrix"
@@ -24158,6 +24232,10 @@ msgid "Fold Gutter"
msgstr "Einklappenspalte"
#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr "Ziehen-und-Fallenlassen-Auswahl aktiviert"
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr "Verstecken aktiviert"
@@ -24518,19 +24596,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 +24603,20 @@ 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 ""
+"In diesem Ansichtsfenster ist HDR aktiv, jedoch wurde dessen Nutzung auf 2D "
+"oder 2D-No-Sampling eingestellt.\n"
+"HDR wird nur in Ansichtsfenstern deren Nutzung auf 3D oder 3D-No-Effects "
+"eingestellt sind unterstützt.\n"
+"HDR wird für dieses Ansichtsfenster deaktiviert."
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr "ARVR"
@@ -26045,14 +26124,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..23c58c5ffb 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
@@ -431,6 +435,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2052,14 +2060,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2115,8 +2124,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2675,7 +2684,7 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr ""
#: editor/editor_export.cpp
@@ -5244,6 +5253,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11194,6 +11211,10 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Filter animations"
+msgstr ""
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17666,6 +17687,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 +17698,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 +17742,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 +17959,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 +17973,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
@@ -19213,14 +19258,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19241,14 +19285,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19460,7 +19503,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 +20165,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 +20177,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
@@ -20191,7 +20242,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22006,6 +22057,10 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+msgid "Global Translation"
+msgstr ""
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23074,6 +23129,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 +23484,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..4b71ed8528 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
@@ -464,6 +469,10 @@ msgid "Pressure"
msgstr "Πίεση"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Σχετικό"
@@ -2175,14 +2184,15 @@ msgstr "Αγαπημένα:"
msgid "Recent:"
msgstr "ΠÏόσφατα:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Αναζήτηση:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Αντιστοιχίες:"
@@ -2242,8 +2252,8 @@ msgstr "Αναζήτηση αντικαταστάτη πόÏου:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2831,7 +2841,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "ΑντιγÏαφή διαδÏομής κόμβου"
#: editor/editor_export.cpp
@@ -5649,6 +5659,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap Γέμισμα Επιλογής"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -12030,6 +12049,11 @@ msgid "New Animation"
msgstr "Îέα Κίνηση"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "ΦιλτÏάÏισμα μεθόδων"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "ΤαχÏτητα:"
@@ -19116,6 +19140,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 +19153,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 +19205,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 +19466,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 +19474,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 +19485,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
@@ -20858,15 +20907,15 @@ msgstr "Σφάλμα κατά το άνοιγμα Ï€ÏοτÏπου για εξα
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "ΆκυÏη επέκταση."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20890,15 +20939,15 @@ msgstr "Μη έγκυÏο όνομα."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "ΆκυÏη επέκταση."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21143,7 +21192,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 +21963,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 +21976,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 +22008,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."
@@ -21993,7 +22052,7 @@ msgstr "Ταξίδι"
msgid "Rotation Degrees"
msgstr "ΠεÏιστÏοφή %s μοίÏες."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "ΣταθεÏή"
@@ -24118,6 +24177,11 @@ msgstr ""
"Αλλάξτε μέγεθος στα σχήματα σÏγκÏουσης των παιδιών."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "ΔιατήÏηση παγκόσμιου μετασχηματισμοÏ"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25376,6 +25440,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 +25850,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 +25859,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..361c10ce1a 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
@@ -442,6 +447,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2074,14 +2083,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2137,8 +2147,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2697,8 +2707,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "ð‘“ð‘³ð‘™ð‘’ð‘–ð‘©ð‘¯ð‘Ÿ:"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5271,6 +5282,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11244,6 +11263,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "ð‘¦ð‘¯ð‘‘ð‘»ð‘ð‘©ð‘¤ð‘±ð‘–ð‘©ð‘¯ ð‘¥ð‘´ð‘›"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17739,6 +17763,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 +17776,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 +17820,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 +18041,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 +18055,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
@@ -19305,14 +19354,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19334,14 +19382,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19556,7 +19603,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 +20271,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 +20283,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 ""
@@ -20294,7 +20350,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22175,6 +22231,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "ð‘“ð‘³ð‘™ð‘’ð‘–ð‘©ð‘¯ð‘Ÿ:"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23269,6 +23330,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 +23692,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..0139382972 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
@@ -488,6 +493,10 @@ msgid "Pressure"
msgstr "AntaÅ­agordo"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Kapti relative"
@@ -2197,14 +2206,15 @@ msgstr "Favoritaj:"
msgid "Recent:"
msgstr "Lastatempe:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Serĉo:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Matĉoj:"
@@ -2264,8 +2274,8 @@ msgstr "Serĉi anstataŭiga risurco:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2842,8 +2852,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Kopii elektaron"
#: editor/editor_export.cpp
#, fuzzy
@@ -5642,6 +5653,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11925,6 +11945,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Forigi animacion?"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18811,6 +18836,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 +18849,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 +18898,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 +19143,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 +19157,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20506,15 +20556,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Nevalida kromprogramo."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20536,15 +20586,15 @@ msgstr "Malvalida nomo."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Nevalida kromprogramo."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20786,7 +20836,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 +21563,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 +21576,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 ""
@@ -21587,7 +21647,7 @@ msgstr "VojaÄa"
msgid "Rotation Degrees"
msgstr "Rotacia paÅo:"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstanto"
@@ -23609,6 +23669,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Transformo"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24822,6 +24887,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 +25294,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..173b195cc4 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -81,13 +81,17 @@
# David Martínez <goddrinksjava@gmail.com>, 2022.
# Nagamine-j <jimmy.kochi@unmsm.edu.pe>, 2022.
# Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>, 2022.
+# Luis Ortiz <luisortiz66@hotmail.com>, 2022.
+# Angel Andrade <aandradeb99@gmail.com>, 2022.
+# Juan Felipe Gómez López <juanfgomez0912@gmail.com>, 2022.
+# Pineappletooth <yochank003@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: Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>\n"
+"PO-Revision-Date: 2022-08-05 01:04+0000\n"
+"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot/es/>\n"
"Language: es\n"
@@ -95,7 +99,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -225,7 +229,7 @@ msgstr "Escala de Tiempo"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Physics Jitter Fix"
-msgstr "Arreglo de las Fluctuaciones Físicas"
+msgstr "Corrección de Fluctuaciones de Física"
#: core/bind/core_bind.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Error"
@@ -466,6 +470,10 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+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
@@ -517,6 +525,10 @@ msgid "Pressure"
msgstr "Presionado"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr "Pluma Invertida"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relativo"
@@ -716,14 +728,12 @@ msgid "Script Templates Search Path"
msgstr "Ruta de Búsqueda de Plantillas de Scripts"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Autoload On Startup"
-msgstr "Cargar automáticamente al inicio"
+msgstr "Carga Automática de Control de Versiones al Inicio"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Plugin Name"
-msgstr "Control de Versiones"
+msgstr "Nombre del Plugin de Control de Versiones"
#: core/project_settings.cpp scene/2d/collision_object_2d.cpp
#: scene/3d/collision_object.cpp scene/gui/control.cpp
@@ -1213,21 +1223,19 @@ msgid "Type"
msgstr "Tipo"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In Handle"
-msgstr "Establecer Manipulador"
+msgstr "En el Manipulador"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out Handle"
-msgstr "Establecer Manipulador"
+msgstr "Fuera del Manipulador"
#: editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
msgid "Stream"
-msgstr ""
+msgstr "Stream"
#: editor/animation_track_editor.cpp
msgid "Start Offset"
@@ -1248,9 +1256,8 @@ msgid "Animation"
msgstr "Animación"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing"
-msgstr "Entrada-Salida Suave"
+msgstr "Suavizar"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
@@ -1405,19 +1412,16 @@ msgid "Stream:"
msgstr "Stream:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start (s):"
-msgstr "Reiniciar (s):"
+msgstr "Inicio (s):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End (s):"
-msgstr "Fundido de entrada (s):"
+msgstr "Fin (s):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation Clip:"
-msgstr "Animaciones:"
+msgstr "Clip de Animación:"
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
@@ -2171,14 +2175,15 @@ msgstr "Favoritos:"
msgid "Recent:"
msgstr "Recientes:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Buscar:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Coincidencias:"
@@ -2238,8 +2243,8 @@ msgstr "Buscar Recurso de Reemplazo:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2248,7 +2253,7 @@ msgstr "Abrir"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "Propietarios de: %s (Total: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2812,7 +2817,8 @@ msgid "Project export for platform:"
msgstr "Exportar proyecto para la plataforma:"
#: editor/editor_export.cpp
-msgid "Completed with errors."
+#, fuzzy
+msgid "Completed with warnings."
msgstr "Completado con errores."
#: editor/editor_export.cpp
@@ -2975,9 +2981,8 @@ msgid "Custom release template not found."
msgstr "Plantilla release personalizada no encontrada."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Prepare Template"
-msgstr "Administrar Plantillas"
+msgstr "Preparar Plantilla"
#: editor/editor_export.cpp platform/osx/export/export.cpp
msgid "The given export path doesn't exist."
@@ -2993,9 +2998,8 @@ msgstr "Fallo al copiar la plantilla de exportación."
#: editor/editor_export.cpp platform/windows/export/export.cpp
#: platform/x11/export/export.cpp
-#, fuzzy
msgid "PCK Embedding"
-msgstr "Relleno"
+msgstr "Integrar PCK"
#: editor/editor_export.cpp
msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
@@ -3394,7 +3398,7 @@ msgstr "Mostrar/Ocultar archivos ocultos."
#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
msgid "View items as a grid of thumbnails."
-msgstr "Ver elementos como una cuadrícula de miniaturas."
+msgstr "Sesgo del nivel de división de la cuadrícula."
#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
msgid "View items as a list."
@@ -4574,7 +4578,7 @@ msgstr "Exportar…"
#: editor/editor_node.cpp
msgid "Install Android Build Template..."
-msgstr "Instalar plantilla de compilación de Android..."
+msgstr "Instalar Plantilla de Compilación de Android..."
#: editor/editor_node.cpp
msgid "Open User Data Folder"
@@ -4893,8 +4897,8 @@ msgstr ""
"personalizado al exportarlo (agregando módulos, cambiando el AndroidManifest."
"xml, etc.).\n"
"Ten en cuenta que para realizar compilaciones personalizadas en lugar de "
-"usar APKs predefinidos, la opción \"Use Custom Build\" debería estar "
-"habilitada en la configuración de exportación de Android."
+"usar APKs predefinidos, la opción \"Usar Compilación Personalizada\" debería "
+"estar habilitada en la configuración de exportación de Android."
#: editor/editor_node.cpp
msgid ""
@@ -5276,9 +5280,8 @@ msgstr ""
"preset existente como ejecutable."
#: editor/editor_run_native.cpp
-#, fuzzy
msgid "Project Run"
-msgstr "Proyecto"
+msgstr "Ejecutar Proyecto"
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -5350,11 +5353,11 @@ msgstr "Atenuar Editor en Diálogo de Popup"
#: editor/editor_settings.cpp main/main.cpp
msgid "Low Processor Mode Sleep (µsec)"
-msgstr ""
+msgstr "Modo de Reposo en Consumo Bajo del Procesador (µsec)"
#: editor/editor_settings.cpp
msgid "Unfocused Low Processor Mode Sleep (µsec)"
-msgstr ""
+msgstr "Modo de Bajo Uso del Procesador Desconectado (µseg)"
#: editor/editor_settings.cpp
msgid "Separate Distraction Mode"
@@ -5366,7 +5369,7 @@ msgstr "Abrir Capturas De Pantalla Automáticamente"
#: editor/editor_settings.cpp
msgid "Max Array Dictionary Items Per Page"
-msgstr ""
+msgstr "Cantidad Máxima de Elementos del Diccionario por Página"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp
@@ -5444,7 +5447,7 @@ msgstr "Comprimir Recursos Binarios"
#: editor/editor_settings.cpp
msgid "Safe Save On Backup Then Rename"
-msgstr ""
+msgstr "Guardar de Forma Segura en el Backup y luego Renombrar"
#: editor/editor_settings.cpp
msgid "File Dialog"
@@ -5456,7 +5459,7 @@ msgstr "Tamaño de las Miniaturas"
#: editor/editor_settings.cpp
msgid "Docks"
-msgstr ""
+msgstr "Paneles"
#: editor/editor_settings.cpp
msgid "Scene Tree"
@@ -5479,9 +5482,8 @@ msgid "Auto Refresh Interval"
msgstr "Intervalo de Auto Refrescar"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Subresource Hue Tint"
-msgstr "Sub-Recursos"
+msgstr "Subrecurso Tinte del Tono"
#: editor/editor_settings.cpp
msgid "Color Theme"
@@ -5561,6 +5563,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Botones Extra del Ratón Navegar por el Historial"
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr "Arrastrar y Soltar la Selección"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr "Permanecer En Editor de Scripts En Nodo Seleccionado"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Apariencia"
@@ -5602,7 +5612,7 @@ msgstr "Directriz de longitud de Línea de Columna Flexible"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Hard Column"
-msgstr ""
+msgstr "Longitud de Línea de la Guía de la Columna Rígida"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
msgid "Script List"
@@ -5688,11 +5698,11 @@ msgstr "Espera de Completado de Código"
#: editor/editor_settings.cpp
msgid "Put Callhint Tooltip Below Current Line"
-msgstr "Colocar la Información Sobre la Llamada Debajo de la Línea Actual"
+msgstr "Colocar Tooltip de Llamada Debajo de la Línea Actual"
#: editor/editor_settings.cpp
msgid "Callhint Tooltip Offset"
-msgstr "Desplazamiento de la Información Sobre la Llamada"
+msgstr "Desplazamiento del Tooltip de Llamada"
#: editor/editor_settings.cpp
msgid "Complete File Paths"
@@ -5792,7 +5802,7 @@ msgstr "Nivel Mínimo de División de Cuadrícula"
#: editor/editor_settings.cpp
msgid "Grid Division Level Bias"
-msgstr ""
+msgstr "Sesgo del Nivel de División de la Cuadrícula"
#: editor/editor_settings.cpp
msgid "Grid XZ Plane"
@@ -5851,23 +5861,20 @@ msgid "Orbit Modifier"
msgstr "Modificador de Órbita"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Pan Modifier"
-msgstr "Modo desplazamiento lateral"
+msgstr "Modificador Panorámico"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Zoom Modifier"
-msgstr "Modificado/s"
+msgstr "Modificador de Zoom"
#: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp
msgid "Warped Mouse Panning"
-msgstr ""
+msgstr "Paneo del Mouse Deformado"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Navigation Feel"
-msgstr "Modo de Navegación"
+msgstr "Sensación de Navegación"
#: editor/editor_settings.cpp
msgid "Orbit Sensitivity"
@@ -5910,9 +5917,8 @@ msgid "Freelook Activation Modifier"
msgstr "Modificador de Activación de Vista Libre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Speed Zoom Link"
-msgstr "Modificador de Velocidad de Vista Libre"
+msgstr "Velocidad de Zoom de Vista Libre"
#: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Grid Color"
@@ -5960,7 +5966,7 @@ msgstr "Color del Borde del Viewport"
#: editor/editor_settings.cpp
msgid "Constrain Editor View"
-msgstr ""
+msgstr "Vista del Editor de Restricciones"
#: editor/editor_settings.cpp
msgid "Simple Panning"
@@ -6021,14 +6027,12 @@ msgstr "Ubicación de la Ventana"
#: editor/editor_settings.cpp scene/2d/back_buffer_copy.cpp scene/2d/sprite.cpp
#: scene/2d/visibility_notifier_2d.cpp scene/3d/sprite_3d.cpp
#: scene/gui/control.cpp
-#, fuzzy
msgid "Rect"
-msgstr "Completo"
+msgstr "Rect"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Rect Custom Position"
-msgstr "Establecer Posición de Salida de Curva"
+msgstr "Posición Personalizada de Rect"
#: editor/editor_settings.cpp platform/android/export/export_plugin.cpp
msgid "Screen"
@@ -6094,24 +6098,23 @@ msgstr "Color de Palabra Clave"
#: editor/editor_settings.cpp
msgid "Control Flow Keyword Color"
-msgstr ""
+msgstr "Control de Flujo Color de Palabra Clave"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Type Color"
-msgstr "Tipo Base"
+msgstr "Tipo de Color Base"
#: editor/editor_settings.cpp
msgid "Engine Type Color"
-msgstr ""
+msgstr "Tipo de Color del Engine"
#: editor/editor_settings.cpp
msgid "User Type Color"
-msgstr ""
+msgstr "Tipo de Color del Usuario"
#: editor/editor_settings.cpp
msgid "Comment Color"
-msgstr ""
+msgstr "Color de los Comentarios"
#: editor/editor_settings.cpp
msgid "String Color"
@@ -6128,25 +6131,24 @@ msgid "Completion Background Color"
msgstr "Completar Color de Fondo"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Completion Selected Color"
-msgstr "Importar Seleccionado"
+msgstr "Completar Color Seleccionado"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Existing Color"
-msgstr ""
+msgstr "Completar Color Existente"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Scroll Color"
-msgstr ""
+msgstr "Completar Color de Scroll"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Font Color"
-msgstr ""
+msgstr "Completar Color de la Fuente"
#: editor/editor_settings.cpp
msgid "Text Color"
-msgstr "Color de Texto"
+msgstr "Color del Texto"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Line Number Color"
@@ -6158,7 +6160,7 @@ msgstr "Color de Número de Línea Seguro"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Caret Color"
-msgstr ""
+msgstr "Color del Caret"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Caret Background Color"
@@ -6185,33 +6187,28 @@ msgid "Line Length Guideline Color"
msgstr ""
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Word Highlighted Color"
-msgstr "Resaltador de Sintaxis"
+msgstr "Color de la Palabra Resaltada"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Number Color"
-msgstr ""
+msgstr "Número del Color"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Function Color"
-msgstr "Función"
+msgstr "Función Color"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Member Variable Color"
-msgstr "Cambiar nombre de variable"
+msgstr "Color de la Variable Miembro"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Mark Color"
-msgstr "Seleccionar Color"
+msgstr "Marcar Color"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Bookmark Color"
-msgstr "Marcadores"
+msgstr "Color del Marcador"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Breakpoint Color"
@@ -6219,21 +6216,19 @@ msgstr "Puntos de Interrupción"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Executing Line Color"
-msgstr ""
+msgstr "Color de la línea de ejecución"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Code Folding Color"
msgstr ""
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Search Result Color"
-msgstr "Resultados de la Búsqueda"
+msgstr "Color del Resultado de Búsqueda"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Search Result Border Color"
-msgstr "Resultados de la Búsqueda"
+msgstr "Color de los Bordes del Resultado de Búsqueda"
#: editor/editor_spin_slider.cpp
msgid "Hold %s to round to integers. Hold Shift for more precise changes."
@@ -6242,14 +6237,12 @@ msgstr ""
"la tecla Mayús para cambios más precisos."
#: editor/editor_spin_slider.cpp scene/gui/button.cpp
-#, fuzzy
msgid "Flat"
-msgstr "Plano 0"
+msgstr "Plano"
#: editor/editor_spin_slider.cpp
-#, fuzzy
msgid "Hide Slider"
-msgstr "Modo de Colisión"
+msgstr "Ocultar Deslizador"
#: editor/editor_sub_scene.cpp
msgid "Select Node(s) to Import"
@@ -6927,9 +6920,8 @@ msgid "Use Ambient"
msgstr ""
#: editor/import/resource_importer_bitmask.cpp
-#, fuzzy
msgid "Create From"
-msgstr "Crear Carpeta"
+msgstr "Crear Desde"
#: editor/import/resource_importer_bitmask.cpp
#: servers/audio/effects/audio_effect_compressor.cpp
@@ -6949,9 +6941,8 @@ msgid "Delimiter"
msgstr "Delimitador"
#: editor/import/resource_importer_layered_texture.cpp
-#, fuzzy
msgid "ColorCorrect"
-msgstr "Corrección del Color"
+msgstr "Corrección de Color"
#: editor/import/resource_importer_layered_texture.cpp
msgid "No BPTC If RGB"
@@ -6979,9 +6970,8 @@ msgstr "Filtro"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Mipmaps"
-msgstr "Señales"
+msgstr "Mipmaps"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
@@ -7012,14 +7002,12 @@ msgid "Vertical"
msgstr "Vertical"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Generate Tangents"
-msgstr "Generar puntos"
+msgstr "Generar Tangentes"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Scale Mesh"
-msgstr "Modo de Escalado"
+msgstr "Escalar Mesh"
#: editor/import/resource_importer_obj.cpp
msgid "Offset Mesh"
@@ -7027,14 +7015,12 @@ msgstr "Offset de Malla"
#: editor/import/resource_importer_obj.cpp
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Octahedral Compression"
-msgstr "Compresión"
+msgstr "Compresión Octaédrica"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Optimize Mesh Flags"
-msgstr "Tamaño de los Indicadores"
+msgstr "Optimizar Marcadores de Malla"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Single Scene"
@@ -7078,29 +7064,24 @@ msgstr "Importar como Escenas y Materiales Múltiples"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Nodes"
msgstr "Nodos"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Type"
-msgstr "Regresar"
+msgstr "Tipo de Raíz"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Name"
-msgstr "Nombre Remoto"
+msgstr "Nombre de Raíz"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Scale"
-msgstr "Escala"
+msgstr "Escala de Raíz"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Custom Script"
-msgstr "CustomNode"
+msgstr "Script Personalizado"
#: editor/import/resource_importer_scene.cpp scene/resources/texture.cpp
msgid "Storage"
@@ -7115,62 +7096,52 @@ msgid "Materials"
msgstr "Materiales"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep On Reimport"
-msgstr "Reimportar"
+msgstr "Seguir Reimportando"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Meshes"
-msgstr "Malla"
+msgstr "Meshes"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Ensure Tangents"
-msgstr "Modificar Tangente de Curva"
+msgstr "Asegurar Tangentes"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Light Baking"
-msgstr "Lightmapping"
+msgstr "Bake de Luces"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Lightmap Texel Size"
-msgstr "Calcular Lightmaps"
+msgstr "Tamaño Lightmap Texel"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
msgid "Skins"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Use Named Skins"
-msgstr "Usar Ajuste de Escalado"
+msgstr "Usar Skins con Nombre"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "External Files"
-msgstr "Abrir un Archivo"
+msgstr "Archivos Externos"
#: editor/import/resource_importer_scene.cpp
msgid "Store In Subdir"
msgstr ""
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Filter Script"
-msgstr "Filtrar scripts"
+msgstr "Filtrar Script"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep Custom Tracks"
-msgstr "Transformar"
+msgstr "Mantener Pistas Personalizadas"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Optimizer"
-msgstr "Optimizar"
+msgstr "Optimizador"
#: editor/import/resource_importer_scene.cpp
#: editor/plugins/item_list_editor_plugin.cpp main/main.cpp
@@ -7184,9 +7155,8 @@ msgstr "Optimizar"
#: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp
#: scene/gui/rich_text_label.cpp scene/resources/curve.cpp
#: scene/resources/environment.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Enabled"
-msgstr "Activar"
+msgstr "Activado"
#: editor/import/resource_importer_scene.cpp
msgid "Max Linear Error"
@@ -7197,19 +7167,16 @@ msgid "Max Angular Error"
msgstr "Error Angular Máximo"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Max Angle"
-msgstr "Valor"
+msgstr "Ãngulo Máximo"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Remove Unused Tracks"
-msgstr "Eliminar Pista de Animación"
+msgstr "Eliminar Pistas Sin Usar"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Clips"
-msgstr "Clips de Animación"
+msgstr "Clips"
#: editor/import/resource_importer_scene.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/particles_2d.cpp scene/3d/area.cpp scene/3d/cpu_particles.cpp
@@ -7276,18 +7243,16 @@ msgid "2D, Detect 3D"
msgstr ""
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "2D Pixel"
-msgstr "Pixeles Sólidos"
+msgstr "Pixel 2D"
#: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp
msgid "Lossy Quality"
msgstr ""
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "HDR Mode"
-msgstr "Modo de Selección"
+msgstr "Modo HDR"
#: editor/import/resource_importer_texture.cpp
msgid "BPTC LDR"
@@ -7301,45 +7266,40 @@ msgid "Normal Map"
msgstr ""
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Process"
-msgstr "Post procesado"
+msgstr "Proceso"
#: editor/import/resource_importer_texture.cpp
msgid "Fix Alpha Border"
msgstr ""
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Premult Alpha"
-msgstr "Editar Polígono"
+msgstr "Premult Alpha"
#: editor/import/resource_importer_texture.cpp
msgid "Hdr As Srgb"
msgstr ""
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Invert Color"
-msgstr "Vértice"
+msgstr "Invertir Color"
#: editor/import/resource_importer_texture.cpp
msgid "Normal Map Invert Y"
msgstr "Invertir Y en Mapa Normal"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Size Limit"
-msgstr "Límites"
+msgstr "Tamaño Límite"
#: editor/import/resource_importer_texture.cpp
msgid "Detect 3D"
msgstr ""
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "SVG"
-msgstr "HSV"
+msgstr "SVG"
#: editor/import/resource_importer_texture.cpp
msgid ""
@@ -7356,18 +7316,16 @@ msgid "Import Mode"
msgstr "Modo de Importación"
#: editor/import/resource_importer_texture_atlas.cpp
-#, fuzzy
msgid "Crop To Region"
-msgstr "Establecer Región de Tile"
+msgstr "Recortar la Región"
#: editor/import/resource_importer_texture_atlas.cpp
msgid "Trim Alpha Border From Region"
msgstr ""
#: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp
-#, fuzzy
msgid "Force"
-msgstr "Forzar Push"
+msgstr "Fuerza"
#: editor/import/resource_importer_wav.cpp
msgid "8 Bit"
@@ -7379,41 +7337,35 @@ msgid "Mono"
msgstr ""
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate"
-msgstr "Nodo Mix"
+msgstr "Tasa Máxima"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate Hz"
-msgstr "Nodo Mix"
+msgstr "Tasa Máxima Hz"
#: editor/import/resource_importer_wav.cpp
msgid "Trim"
msgstr ""
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Normalize"
-msgstr "Formato"
+msgstr "Normalizar"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop Mode"
-msgstr "Modo de Movimiento"
+msgstr "Modo Bucle"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop Begin"
-msgstr "Modo de Movimiento"
+msgstr "Inicio del Bucle"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop End"
-msgstr "Modo de Movimiento"
+msgstr "Fin del Bucle"
#: editor/import_defaults_editor.cpp
msgid "Select Importer"
@@ -7500,14 +7452,12 @@ msgid "Raw"
msgstr "Raw"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Capitalized"
-msgstr "Capitalizar"
+msgstr "Capitalización"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Localized"
-msgstr "Idioma"
+msgstr "Localizado"
#: editor/inspector_dock.cpp
msgid "Localization not available for current language."
@@ -8061,9 +8011,8 @@ msgid "New"
msgstr "Nuevo"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Paste As Reference"
-msgstr "%s Referencia de Clase"
+msgstr "Pegar Como Referencia"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Edit Transitions..."
@@ -8555,25 +8504,21 @@ msgid "Loading..."
msgstr "Cargar..."
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "First"
msgstr "Primero"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Previous"
msgstr "Anterior"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Next"
msgstr "Siguiente"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Last"
msgstr "Último"
@@ -9192,9 +9137,8 @@ msgid "View"
msgstr "Ver"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show"
-msgstr "Ver Cuadrícula"
+msgstr "Mostrar"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Show When Snapping"
@@ -9202,12 +9146,11 @@ msgstr "Mostrar Al Ajustar"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Hide"
-msgstr ""
+msgstr "Ocultar"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Grid"
-msgstr "Cambiar Modo"
+msgstr "Cambiar Cuadrícula"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/polygon_2d_editor_plugin.cpp
@@ -9829,7 +9772,6 @@ msgstr ""
"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "MeshLibrary"
msgstr "Librería de Mallas"
@@ -9854,14 +9796,12 @@ msgid "Update from Scene"
msgstr "Actualizar desde escena"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply without Transforms"
-msgstr "Aplicar Transformaciones al MeshInstance"
+msgstr "Aplicar sin Transformaciones"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply with Transforms"
-msgstr "Aplicar Transformaciones al MeshInstance"
+msgstr "Aplicar con Transformaciones"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "No mesh source specified (and no MultiMesh set in node)."
@@ -10209,7 +10149,7 @@ msgid ""
"viewport."
msgstr ""
"El polígono 2D tiene vértices internos, por lo que ya no se puede editar en "
-"la ventanilla."
+"el viewport."
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Create Polygon & UV"
@@ -10730,19 +10670,16 @@ msgid "External"
msgstr ""
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Use External Editor"
-msgstr "Depurar con Editor Externo"
+msgstr "Usar un Editor Externo"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Exec Path"
-msgstr "Ruta de Exportación"
+msgstr "Ruta de Ejecución"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Script Temperature Enabled"
-msgstr "Seleccionar el archivo de la plantilla"
+msgstr "Temperatura del Script Activada"
#: editor/plugins/script_editor_plugin.cpp
msgid "Highlight Current Script"
@@ -10757,14 +10694,12 @@ msgid "Current Script Background Color"
msgstr "Color de Fondo del Script Actual"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Group Help Pages"
-msgstr "Agrupar Seleccionados"
+msgstr "Páginas de Ayuda para Grupos"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Sort Scripts By"
-msgstr "Crear Script"
+msgstr "Ordenar Scripts por"
#: editor/plugins/script_editor_plugin.cpp
msgid "List Script Names As"
@@ -10981,8 +10916,8 @@ msgid ""
"This shader has been modified on on disk.\n"
"What action should be taken?"
msgstr ""
-"Este shader ha sido modificado en disco.\n"
-"¿Qué acciones deben tomarse?"
+"Este shader ha sido modificado en el disco.\n"
+"¿Qué acción debe tomarse?"
#: editor/plugins/shader_editor_plugin.cpp scene/resources/material.cpp
msgid "Shader"
@@ -11480,27 +11415,27 @@ msgstr "Dialogo de Transformación..."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "1 Viewport"
-msgstr "1 Ventana"
+msgstr "1 Viewport"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "2 Viewports"
-msgstr "2 Ventanas"
+msgstr "2 Viewports"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "2 Viewports (Alt)"
-msgstr "2 Ventanas (Alt)"
+msgstr "2 Viewports (Alt)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "3 Viewports"
-msgstr "3 Ventanas"
+msgstr "3 Viewports"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "3 Viewports (Alt)"
-msgstr "3 Ventanas (Alt)"
+msgstr "3 Viewports (Alt)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "4 Viewports"
-msgstr "4 Ventanas"
+msgstr "4 Viewports"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Gizmos"
@@ -11545,7 +11480,7 @@ msgstr "Ajuste de Escala (%):"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Viewport Settings"
-msgstr "Configuración de ventanilla"
+msgstr "Configuración del Viewport"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Perspective FOV (deg.):"
@@ -11596,9 +11531,8 @@ msgid "Manipulator Gizmo Opacity"
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Show Viewport Rotation Gizmo"
-msgstr "Bloquear Rotación de Vista"
+msgstr "Mostrar Gizmo de Rotación del Viewport"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Unnamed Gizmo"
@@ -11650,9 +11584,8 @@ msgid "Invalid geometry, can't replace by mesh."
msgstr "Geometría inválida, no puede ser reemplazada por una malla."
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Convert to MeshInstance2D"
-msgstr "Convertir a Mesh2D"
+msgstr "Convertir a MeshInstance2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create polygon."
@@ -11755,6 +11688,10 @@ msgid "New Animation"
msgstr "Nueva Animación"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Filter animations"
+msgstr "Filtrar animaciones"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Velocidad:"
@@ -12052,9 +11989,8 @@ msgstr ""
"¿Cerrar de todos modos?"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Type"
-msgstr "Eliminar Tile"
+msgstr "Eliminar Tipo"
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
@@ -12098,14 +12034,12 @@ msgstr ""
"Añade más propiedades manualmente o impórtalas desde otro Theme."
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Add Theme Type"
-msgstr "Añadir Tipo de Elemento"
+msgstr "Añadir Tipo de Theme"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Theme Type"
-msgstr "Eliminar Remoto"
+msgstr "Eliminar Tipo de Theme"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Color Item"
@@ -12552,55 +12486,46 @@ msgid "Clear Transform"
msgstr "Reestablecer Transformación"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Tile Map"
-msgstr "Dibujar TileMap"
+msgstr "Mapa de Tiles"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Palette Min Width"
-msgstr ""
+msgstr "Ancho Mínimo de la Paleta"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Palette Item H Separation"
-msgstr "Separador con nombre"
+msgstr "Separación del Elemento H de la Paleta"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Show Tile Names"
-msgstr "Mostrar Todos los Idiomas"
+msgstr "Mostrar Nombres de Tiles"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Show Tile Ids"
-msgstr "Mostrar Reglas"
+msgstr "Mostrar ID de los Tiles"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Sort Tiles By Name"
-msgstr "Ordenar archivos"
+msgstr "Ordenar Tiles por Nombre"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill Preview"
-msgstr "Bote de Relleno"
+msgstr "Vista previa del Bote de Relleno"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Editor Side"
-msgstr "Editor"
+msgstr "Lado del Editor"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Display Grid"
-msgstr "Mostrar Overdraw"
+msgstr "Mostrar Cuadrícula"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Axis Color"
-msgstr "Seleccionar Color"
+msgstr "Color de los Ejes"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Add Texture(s) to TileSet."
@@ -12939,7 +12864,6 @@ msgid "This property can't be changed."
msgstr "Esta propiedad no se puede cambiar."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Snap Options"
msgstr "Opciones de Ajuste"
@@ -12968,9 +12892,8 @@ msgid "Separation"
msgstr "Separación"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Tile"
-msgstr "Seleccionar"
+msgstr "Tiles Seleccionados"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/light_2d.cpp scene/2d/line_2d.cpp scene/2d/mesh_instance_2d.cpp
@@ -12979,14 +12902,12 @@ msgstr "Seleccionar"
#: scene/gui/nine_patch_rect.cpp scene/gui/texture_rect.cpp
#: scene/resources/material.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Texture"
-msgstr "Texto"
+msgstr "Textura"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tex Offset"
-msgstr "Desplazamiento de Byte"
+msgstr "Desplazamiento de Textura"
#: editor/plugins/tile_set_editor_plugin.cpp modules/csg/csg_shape.cpp
#: scene/2d/canvas_item.cpp scene/2d/particles_2d.cpp
@@ -12996,79 +12917,64 @@ msgstr "Material"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/canvas_item.cpp
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Modulate"
-msgstr "Rellenar"
+msgstr "Modular"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tile Mode"
-msgstr "Cambiar Modo"
+msgstr "Modo Tile"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Autotile Bitmask Mode"
-msgstr "Modo de Bitmask"
+msgstr "Modo Bitmask Automático"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Size"
-msgstr "Tamaño del Contorno"
+msgstr "Tamaño de Subtile"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Spacing"
-msgstr "Espaciado de Línea"
+msgstr "Espaciado de Subtile"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Occluder Offset"
-msgstr "Crear Polígono Oclusor"
+msgstr "Desplazamiento del Oclusor"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Navigation Offset"
-msgstr "Modo de Navegación"
+msgstr "Desplazamiento de Navegación"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Shape Offset"
-msgstr "Desplazamiento Base"
+msgstr "Desplazamiento del Shape"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Shape Transform"
-msgstr "Transformar"
+msgstr "Transformar Shape"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision"
-msgstr "Colisión"
+msgstr "Colisión Seleccionada"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision One Way"
-msgstr "Sólo selección"
+msgstr "Colisión Seleccionada en Una Dirección"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision One Way Margin"
-msgstr "Modo de Colisión"
+msgstr "Margen Seleccionado de Colisión en Una Dirección"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Navigation"
-msgstr "Navegación Visible"
+msgstr "Navegación Seleccionada"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Occlusion"
-msgstr "Seleccionar"
+msgstr "Oclusión Seleccionada"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tileset Script"
-msgstr "Filtrar scripts"
+msgstr "Script de Tileset"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "TileSet"
@@ -14279,9 +14185,8 @@ msgid ""
msgstr ""
#: editor/project_export.cpp
-#, fuzzy
msgid "More Info..."
-msgstr "Mover a..."
+msgstr "Más información..."
#: editor/project_export.cpp
msgid "Export PCK/Zip..."
@@ -14308,18 +14213,16 @@ msgid "ZIP File"
msgstr "Archivo ZIP"
#: editor/project_export.cpp
-#, fuzzy
msgid "Godot Project Pack"
-msgstr "Godot Game Pack"
+msgstr "Paquete de Proyectos de Godot"
#: editor/project_export.cpp
msgid "Export templates for this platform are missing:"
msgstr "Faltan plantillas de exportación para esta plataforma:"
#: editor/project_export.cpp
-#, fuzzy
msgid "Project Export"
-msgstr "Fundadores del Proyecto"
+msgstr "Exportación del Proyecto"
#: editor/project_export.cpp
msgid "Manage Export Templates"
@@ -14634,7 +14537,6 @@ msgstr ""
#. TRANSLATORS: This refers to the application where users manage their Godot projects.
#: editor/project_manager.cpp
-#, fuzzy
msgctxt "Application"
msgid "Project Manager"
msgstr "Administrador de Proyectos"
@@ -15442,14 +15344,12 @@ msgid "Another node already uses this unique name in the scene."
msgstr ""
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Enable Scene Unique Name"
-msgstr "Nombre Único"
+msgstr "Activar Nombre Único de Escena"
#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Disable Scene Unique Name"
-msgstr "Nombre Único"
+msgstr "Desactivar Nombre Único de Escena"
#: editor/scene_tree_dock.cpp
msgid "New Scene Root"
@@ -15624,18 +15524,16 @@ msgid "Clear Inheritance? (No Undo!)"
msgstr "¿Quieres limpiar la herencia? (No se puede deshacer)"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Show Scene Tree Root Selection"
-msgstr "Centrar Selección"
+msgstr "Mostrar Selección de la Raíz del Ãrbol de Escenas"
#: editor/scene_tree_dock.cpp
msgid "Derive Script Globals By Name"
msgstr ""
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Use Favorites Root Selection"
-msgstr "Seleccionar Fotogramas"
+msgstr "Usar Selección de Raíces Favoritas"
#: editor/scene_tree_editor.cpp
msgid "Toggle Visible"
@@ -16094,23 +15992,20 @@ msgid "Change Particles AABB"
msgstr "Cambiar partículas AABB"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Reflection Probe"
-msgstr "Seleccionar Propiedad"
+msgstr "Sonda de Reflexión"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Probe Extents"
msgstr "Cambiar Alcance de la Sonda"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "GI Probe"
-msgstr "Calcular GI Probe"
+msgstr "Sonda GI"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Baked Indirect Light"
-msgstr "Iluminación indirecta"
+msgstr "Iluminación Indirecta Bakeada"
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
msgid "Change Sphere Shape Radius"
@@ -16141,24 +16036,20 @@ msgid "Change Ray Shape Length"
msgstr "Cambiar Longitud de la Forma del Rayo"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Edge"
-msgstr "Modo de Navegación"
+msgstr "Borde de Navegación"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Edge Disabled"
-msgstr "Modo de Navegación"
+msgstr "Borde de Navegación Desactivado"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Solid"
-msgstr "Modo de Navegación"
+msgstr "Navegación Sólida"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Solid Disabled"
-msgstr "Modo de Navegación"
+msgstr "Navegación Sólida Desactivada"
#: editor/spatial_editor_gizmos.cpp
msgid "Joint Body A"
@@ -16181,9 +16072,8 @@ msgid "Set Room Point Position"
msgstr "Establecer Posición del Room Point"
#: editor/spatial_editor_gizmos.cpp scene/3d/portal.cpp
-#, fuzzy
msgid "Portal Margin"
-msgstr "Asignar Margen"
+msgstr "Margen del Portal"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Edge"
@@ -16202,15 +16092,13 @@ msgid "Portal Front"
msgstr ""
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Portal Back"
-msgstr "Retroceder"
+msgstr "Portal de Regreso"
#: editor/spatial_editor_gizmos.cpp scene/2d/light_occluder_2d.cpp
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Occluder"
-msgstr "Modo de Oclusión"
+msgstr "Oclusor"
#: editor/spatial_editor_gizmos.cpp
msgid "Set Occluder Sphere Radius"
@@ -16229,19 +16117,16 @@ msgid "Set Occluder Hole Point Position"
msgstr "Establecer posición del orificio del oclusor"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Polygon Front"
-msgstr "Crear Polígono Oclusor"
+msgstr "Frente del Polígono Oclusor"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Polygon Back"
-msgstr "Crear Polígono Oclusor"
+msgstr "Posterior del Polígono Oclusor"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Hole"
-msgstr "Crear Polígono Oclusor"
+msgstr "Orificio Oclusor"
#: main/main.cpp
msgid "Godot Physics"
@@ -16250,32 +16135,28 @@ msgstr ""
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
msgid "Use BVH"
-msgstr ""
+msgstr "Usar BVH"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
-#, fuzzy
msgid "BVH Collision Margin"
-msgstr "Modo de Colisión"
+msgstr "Margen de Colisión BVH"
#: main/main.cpp
-#, fuzzy
msgid "Crash Handler"
-msgstr "Establecer Manipulador"
+msgstr "Manipulador de Colisiones"
#: main/main.cpp
-#, fuzzy
msgid "Multithreaded Server"
-msgstr "Establecer multinodo"
+msgstr "Servidor Multihilo"
#: main/main.cpp
msgid "RID Pool Prealloc"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Debugger stdout"
-msgstr "Depurador"
+msgstr "Depurador stdout"
#: main/main.cpp
msgid "Max Chars Per Second"
@@ -16306,14 +16187,12 @@ msgid "File Logging"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Enable File Logging"
-msgstr "Habilitar Filtrado"
+msgstr "Activar Registro de Archivos"
#: main/main.cpp
-#, fuzzy
msgid "Log Path"
-msgstr "Copiar Ruta"
+msgstr "Ruta del Registro"
#: main/main.cpp
msgid "Max Log Files"
@@ -16344,14 +16223,12 @@ msgid "Allow hiDPI"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "V-Sync"
-msgstr "Sincronizar"
+msgstr "Sincronización Vertical"
#: main/main.cpp
-#, fuzzy
msgid "Use V-Sync"
-msgstr "Usar Snap"
+msgstr "Usar Sincronización Vertical"
#: main/main.cpp
msgid "Per Pixel Transparency"
@@ -16366,23 +16243,20 @@ msgid "Intended Usage"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Framebuffer Allocation"
-msgstr "Seleccionar Fotogramas"
+msgstr "Asignación del Buffer de Imágenes"
#: main/main.cpp platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Energy Saving"
-msgstr "Error al Guardar"
+msgstr "Ahorro de Energía"
#: main/main.cpp
msgid "Threads"
msgstr ""
#: main/main.cpp servers/physics_2d/physics_2d_server_wrap_mt.h
-#, fuzzy
msgid "Thread Model"
-msgstr "Cambiar Modo"
+msgstr "Modelo de Hilo"
#: main/main.cpp
msgid "Thread Safe BVH"
@@ -16394,25 +16268,21 @@ msgstr ""
#: main/main.cpp platform/javascript/export/export.cpp
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Orientation"
-msgstr "Documentación en línea"
+msgstr "Orientación"
#: main/main.cpp scene/gui/scroll_container.cpp scene/gui/text_edit.cpp
#: scene/main/scene_tree.cpp scene/register_scene_types.cpp
-#, fuzzy
msgid "Common"
-msgstr "Comunidad"
+msgstr "Común"
#: main/main.cpp
-#, fuzzy
msgid "Physics FPS"
-msgstr "Fotogramas de Física %"
+msgstr "Física FPS"
#: main/main.cpp
-#, fuzzy
msgid "Force FPS"
-msgstr "Forzar Push"
+msgstr "Forzar FPS"
#: main/main.cpp
msgid "Enable Pause Aware Picking"
@@ -16441,19 +16311,16 @@ msgid "Verbose stdout"
msgstr ""
#: main/main.cpp scene/main/scene_tree.cpp scene/resources/multimesh.cpp
-#, fuzzy
msgid "Physics Interpolation"
-msgstr "Modo de Interpolación"
+msgstr "Interpolación de Física"
#: main/main.cpp
-#, fuzzy
msgid "Enable Warnings"
-msgstr "Habilitar Filtrado"
+msgstr "Activar Advertencias"
#: main/main.cpp
-#, fuzzy
msgid "Frame Delay Msec"
-msgstr "Seleccionar Fotogramas"
+msgstr "Retraso de los Fotogramas Msec"
#: main/main.cpp
msgid "Low Processor Mode"
@@ -16472,14 +16339,12 @@ msgid "Hide Home Indicator"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Input Devices"
-msgstr "Todos los Dispositivos"
+msgstr "Dispositivos de Entrada"
#: main/main.cpp
-#, fuzzy
msgid "Pointing"
-msgstr "Punto"
+msgstr "Apuntador"
#: main/main.cpp
msgid "Touch Delay"
@@ -16490,21 +16355,18 @@ msgid "GLES3"
msgstr ""
#: main/main.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Shaders"
-msgstr "Shader"
+msgstr "Shaders"
#: main/main.cpp
-#, fuzzy
msgid "Debug Shader Fallbacks"
-msgstr "Forzar Shader Fallbacks"
+msgstr "Depurar Fallbacks de Shader"
#: main/main.cpp scene/3d/baked_lightmap.cpp scene/3d/camera.cpp
#: scene/3d/world_environment.cpp scene/main/scene_tree.cpp
#: scene/resources/world.cpp
-#, fuzzy
msgid "Environment"
-msgstr "Ver Entorno"
+msgstr "Entorno"
#: main/main.cpp
msgid "Default Clear Color"
@@ -16515,9 +16377,8 @@ msgid "Boot Splash"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Show Image"
-msgstr "Mostrar Huesos"
+msgstr "Mostrar Imagen"
#: main/main.cpp
msgid "Image"
@@ -16532,14 +16393,12 @@ msgid "Use Filter"
msgstr "Usar Filtro"
#: main/main.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "BG Color"
-msgstr "Colores"
+msgstr "Color de Fondo"
#: main/main.cpp
-#, fuzzy
msgid "macOS Native Icon"
-msgstr "Establecer Icono de Tile"
+msgstr "Icono Nativo de macOS"
#: main/main.cpp
msgid "Windows Native Icon"
@@ -16562,14 +16421,12 @@ msgid "Emulate Mouse From Touch"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Mouse Cursor"
-msgstr "Botón del Mouse"
+msgstr "Cursor del Mouse"
#: main/main.cpp
-#, fuzzy
msgid "Custom Image"
-msgstr "CustomNode"
+msgstr "Imagen Personalizada"
#: main/main.cpp
msgid "Custom Image Hotspot"
@@ -16577,17 +16434,15 @@ msgstr ""
#: main/main.cpp
msgid "Tooltip Position Offset"
-msgstr "Offset de la Posición del Tooltip"
+msgstr "Desplazamiento de Posición del Tooltip"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
-#, fuzzy
msgid "Debugger Agent"
-msgstr "Depurador"
+msgstr "Agente de Depuración"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
-#, fuzzy
msgid "Wait For Debugger"
-msgstr "Depurador"
+msgstr "Esperar al Depurador"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
msgid "Wait Timeout"
@@ -16602,20 +16457,17 @@ msgid "Unhandled Exception Policy"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Main Loop Type"
-msgstr "Buscar Tipo de Nodo"
+msgstr "Tipo de Bucle Principal"
#: main/main.cpp scene/gui/texture_progress.cpp
#: scene/gui/viewport_container.cpp
-#, fuzzy
msgid "Stretch"
-msgstr "Buscar"
+msgstr "Estirar"
#: main/main.cpp
-#, fuzzy
msgid "Aspect"
-msgstr "Inspector"
+msgstr "Aspecto"
#: main/main.cpp
msgid "Shrink"
@@ -16626,14 +16478,12 @@ msgid "Auto Accept Quit"
msgstr ""
#: main/main.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Quit On Go Back"
-msgstr "Retroceder"
+msgstr "Salir y Regresar"
#: main/main.cpp scene/main/viewport.cpp
-#, fuzzy
msgid "Snap Controls To Pixels"
-msgstr "Ajustar a los Lados del Nodo"
+msgstr "Ajustar Controles a Píxeles"
#: main/main.cpp
msgid "Dynamic Fonts"
@@ -16668,35 +16518,30 @@ msgid "Change Torus Outer Radius"
msgstr "Cambiar Radio Externo de Torus"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Operation"
-msgstr "Opciones"
+msgstr "Operación"
#: modules/csg/csg_shape.cpp
msgid "Calculate Tangents"
msgstr ""
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Use Collision"
-msgstr "Colisión"
+msgstr "Usar Colisión"
#: modules/csg/csg_shape.cpp servers/physics_2d_server.cpp
-#, fuzzy
msgid "Collision Layer"
-msgstr "Modo de Colisión"
+msgstr "Capa de Colisión"
#: modules/csg/csg_shape.cpp scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp
#: scene/3d/ray_cast.cpp scene/3d/spring_arm.cpp
#: scene/resources/navigation_mesh.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collision Mask"
-msgstr "Modo de Colisión"
+msgstr "Máscara de Colisión"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Invert Faces"
-msgstr "Convertir Mayúsculas/Minúsculas"
+msgstr "Invertir Caras"
#: modules/csg/csg_shape.cpp scene/2d/navigation_agent_2d.cpp
#: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_agent.cpp
@@ -16714,33 +16559,28 @@ msgid "Radial Segments"
msgstr "Segmentos Radiales"
#: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Rings"
-msgstr "Advertencias"
+msgstr "Anillos"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Smooth Faces"
-msgstr "Suavizado"
+msgstr "Caras Suaves"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Sides"
-msgstr "Mostrar Guías"
+msgstr "Lados"
#: modules/csg/csg_shape.cpp
msgid "Cone"
msgstr ""
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Inner Radius"
-msgstr "Cambiar Radio Interno de Torus"
+msgstr "Radio Interior"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Outer Radius"
-msgstr "Cambiar Radio Externo de Torus"
+msgstr "Radio Exterior"
#: modules/csg/csg_shape.cpp
msgid "Ring Sides"
@@ -16749,9 +16589,8 @@ msgstr ""
#: modules/csg/csg_shape.cpp scene/2d/collision_polygon_2d.cpp
#: scene/2d/light_occluder_2d.cpp scene/2d/polygon_2d.cpp
#: scene/3d/collision_polygon.cpp
-#, fuzzy
msgid "Polygon"
-msgstr "Polígonos"
+msgstr "Polígono"
#: modules/csg/csg_shape.cpp
msgid "Spin Degrees"
@@ -16762,14 +16601,12 @@ msgid "Spin Sides"
msgstr ""
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Node"
-msgstr "Pegar Nodos"
+msgstr "Ruta del Nodo"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Interval Type"
-msgstr "Crear Vértice Interno"
+msgstr "Tipo de Intervalo de Ruta"
#: modules/csg/csg_shape.cpp
msgid "Path Interval"
@@ -16784,14 +16621,12 @@ msgid "Path Rotation"
msgstr "Rotación de Trayectoria"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Local"
-msgstr "Crear Local"
+msgstr "Ruta Local"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Continuous U"
-msgstr "Continuo"
+msgstr "Ruta Continua U"
#: modules/csg/csg_shape.cpp
msgid "Path U Distance"
@@ -16802,24 +16637,20 @@ msgid "Path Joined"
msgstr "Ruta Unida"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Compression Mode"
-msgstr "Modo de Colisión"
+msgstr "Modo de Compresión"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Transfer Channel"
-msgstr "Cambio de Transformación"
+msgstr "Canal de Transferencia"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Channel Count"
-msgstr "Instanciar"
+msgstr "Conteo de Canales"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Always Ordered"
-msgstr "Mostrar Siempre la Cuadrícula"
+msgstr "Siempre Ordenado"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "Server Relay"
@@ -16834,9 +16665,8 @@ msgid "DTLS Hostname"
msgstr ""
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Use DTLS"
-msgstr "Usar Snap"
+msgstr "Usar DTLS"
#: modules/fbx/editor_scene_importer_fbx.cpp
msgid "FBX"
@@ -16851,24 +16681,21 @@ msgid "Config File"
msgstr "Archivo de Configuración"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Load Once"
-msgstr "Cargar Recurso"
+msgstr "Cargar Una Vez"
#: modules/gdnative/gdnative.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Singleton"
-msgstr "Esqueleto"
+msgstr "Singleton"
#: modules/gdnative/gdnative.cpp
msgid "Symbol Prefix"
msgstr "Prefijo de Símbolo"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Reloadable"
-msgstr "Recargar"
+msgstr "Recargable"
#: modules/gdnative/gdnative.cpp
#: modules/gdnative/gdnative_library_singleton_editor.cpp
@@ -16933,9 +16760,8 @@ msgid "Script Class"
msgstr "Clase del Script"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Icon Path"
-msgstr "Foco en Ruta"
+msgstr "Ruta del Icono"
#: modules/gdnative/register_types.cpp
msgid "GDNative"
@@ -16943,18 +16769,16 @@ msgstr "GDNative"
#: modules/gdscript/editor/gdscript_highlighter.cpp
#: modules/gdscript/gdscript.cpp
-#, fuzzy
msgid "GDScript"
-msgstr "Script"
+msgstr "GDScript"
#: modules/gdscript/editor/gdscript_highlighter.cpp
msgid "Function Definition Color"
msgstr ""
#: modules/gdscript/editor/gdscript_highlighter.cpp
-#, fuzzy
msgid "Node Path Color"
-msgstr "Copiar Ruta del Nodo"
+msgstr "Color de la Ruta del Nodo"
#: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp
msgid "Max Call Stack"
@@ -17017,9 +16841,8 @@ msgid "Language Server"
msgstr "Servidor de Lenguaje"
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Enable Smart Resolve"
-msgstr "No se puede resolver"
+msgstr "Activar Smart Resolve"
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Show Native Symbols In Editor"
@@ -17038,42 +16861,36 @@ msgid "Export GLTF..."
msgstr "Exportar GLTF..."
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Buffer View"
-msgstr "Vista Trasera"
+msgstr "Vista del Buffer"
#: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp
msgid "Byte Offset"
msgstr "Desplazamiento de Byte"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Component Type"
-msgstr "Componentes"
+msgstr "Tipo de Componente"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Normalized"
-msgstr "Formato"
+msgstr "Normalizado"
#: modules/gltf/gltf_accessor.cpp
msgid "Count"
msgstr "Cuenta"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Min"
-msgstr "MiB"
+msgstr "Min"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Max"
-msgstr "Mix"
+msgstr "Max"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Sparse Count"
-msgstr "Instanciar"
+msgstr "Recuento Parcial"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Buffer View"
@@ -17096,23 +16913,20 @@ msgid "Sparse Values Byte Offset"
msgstr ""
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Buffer"
-msgstr "Vista Trasera"
+msgstr "Buffer"
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Byte Length"
-msgstr "Theme Predeterminado"
+msgstr "Longitud de Bytes"
#: modules/gltf/gltf_buffer_view.cpp
msgid "Byte Stride"
msgstr ""
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Indices"
-msgstr "Todos los Dispositivos"
+msgstr "Ãndices"
#: modules/gltf/gltf_camera.cpp
msgid "FOV Size"
@@ -17123,9 +16937,8 @@ msgid "Zfar"
msgstr ""
#: modules/gltf/gltf_camera.cpp
-#, fuzzy
msgid "Znear"
-msgstr "Lineal"
+msgstr "Znear"
#: modules/gltf/gltf_light.cpp scene/2d/canvas_modulate.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/light_2d.cpp scene/2d/polygon_2d.cpp
@@ -17135,9 +16948,8 @@ msgstr "Lineal"
#: scene/resources/environment.cpp scene/resources/material.cpp
#: scene/resources/particles_material.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp
-#, fuzzy
msgid "Color"
-msgstr "Colores"
+msgstr "Color"
#: modules/gltf/gltf_light.cpp scene/3d/reflection_probe.cpp
#: scene/resources/environment.cpp
@@ -17145,9 +16957,8 @@ msgid "Intensity"
msgstr ""
#: modules/gltf/gltf_light.cpp scene/2d/light_2d.cpp scene/3d/light.cpp
-#, fuzzy
msgid "Range"
-msgstr "Cambiar"
+msgstr "Rango"
#: modules/gltf/gltf_light.cpp
msgid "Inner Cone Angle"
@@ -17158,42 +16969,36 @@ msgid "Outer Cone Angle"
msgstr ""
#: modules/gltf/gltf_mesh.cpp
-#, fuzzy
msgid "Blend Weights"
-msgstr "Calcular Lightmaps"
+msgstr "Mezcla de Pesos"
#: modules/gltf/gltf_mesh.cpp
msgid "Instance Materials"
msgstr "Materiales de Instancia"
#: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp
-#, fuzzy
msgid "Parent"
-msgstr "Reemparentar"
+msgstr "Padre"
#: modules/gltf/gltf_node.cpp
-#, fuzzy
msgid "Xform"
-msgstr "Plataforma"
+msgstr "Xform"
#: modules/gltf/gltf_node.cpp scene/3d/mesh_instance.cpp
msgid "Skin"
msgstr ""
#: modules/gltf/gltf_node.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Translation"
-msgstr "Traducciones"
+msgstr "Traducción"
#: modules/gltf/gltf_node.cpp
-#, fuzzy
msgid "Children"
-msgstr "Hijos Editables"
+msgstr "Hijos"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Joints"
-msgstr "Punto"
+msgstr "Articulaciones"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp
msgid "Roots"
@@ -17204,28 +17009,24 @@ msgid "Unique Names"
msgstr ""
#: modules/gltf/gltf_skeleton.cpp
-#, fuzzy
msgid "Godot Bone Node"
-msgstr "Obtener Nodo de Escena"
+msgstr "Nodo de Huesos de Godot"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Skin Root"
-msgstr "Nueva Raíz de Escena"
+msgstr "Raíz de la Skin"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Joints Original"
-msgstr "Foco en Origen"
+msgstr "Articulaciones Originales"
#: modules/gltf/gltf_skin.cpp
msgid "Inverse Binds"
msgstr ""
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Non Joints"
-msgstr "Mover Unión"
+msgstr "Sin Articulaciones"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Bone I"
@@ -17264,28 +17065,24 @@ msgid "Json"
msgstr ""
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Major Version"
-msgstr "Versión"
+msgstr "Versión Mayor"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Minor Version"
-msgstr "Versión"
+msgstr "Versión Menor"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "GLB Data"
-msgstr "Con Datos"
+msgstr "Datos GLB"
#: modules/gltf/gltf_state.cpp
msgid "Use Named Skin Binds"
msgstr ""
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Buffer Views"
-msgstr "Vista Trasera"
+msgstr "Vistas del Buffer"
#: modules/gltf/gltf_state.cpp
msgid "Accessors"
@@ -17296,15 +17093,13 @@ msgid "Scene Name"
msgstr "Nombre de la Escena"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Root Nodes"
-msgstr "Nombre del nodo raíz"
+msgstr "Nodos Raíz"
#: modules/gltf/gltf_state.cpp scene/2d/particles_2d.cpp
#: scene/gui/texture_button.cpp scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Textures"
-msgstr "Características"
+msgstr "Texturas"
#: modules/gltf/gltf_state.cpp platform/uwp/export/export.cpp
msgid "Images"
@@ -17315,70 +17110,60 @@ msgid "Cameras"
msgstr ""
#: modules/gltf/gltf_state.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Lights"
-msgstr "Luz"
+msgstr "Luces"
#: modules/gltf/gltf_state.cpp
msgid "Unique Animation Names"
msgstr "Nombres Únicos de Animación"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Skeletons"
-msgstr "Esqueleto"
+msgstr "Esqueletos"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Skeleton To Node"
-msgstr "Selecciona un Nodo"
+msgstr "Esqueleto a Nodo"
#: modules/gltf/gltf_state.cpp
msgid "Animations"
msgstr "Animaciones"
#: modules/gltf/gltf_texture.cpp
-#, fuzzy
msgid "Src Image"
-msgstr "Mostrar Huesos"
+msgstr "Imagen de Origen"
#: modules/gridmap/grid_map.cpp
msgid "Mesh Library"
msgstr "Librería de Mallas"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Physics Material"
-msgstr "Fotogramas de Física %"
+msgstr "Material de Física"
#: modules/gridmap/grid_map.cpp scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Use In Baked Light"
-msgstr "Calcular Lightmaps"
+msgstr "Uso en Luz Bakeada"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
msgid "Cell"
msgstr ""
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Octant Size"
-msgstr "Vista Frontal"
+msgstr "Tamaño del Octante"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center X"
-msgstr "Centro"
+msgstr "Centro X"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Y"
-msgstr "Centro"
+msgstr "Centro Y"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Z"
-msgstr "Centro"
+msgstr "Centro Z"
#: modules/gridmap/grid_map.cpp scene/2d/collision_object_2d.cpp
#: scene/2d/tile_map.cpp scene/3d/collision_object.cpp scene/3d/soft_body.cpp
@@ -17387,17 +17172,15 @@ msgid "Mask"
msgstr ""
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
-#, fuzzy
msgid "Bake Navigation"
-msgstr "Navegación"
+msgstr "Bakear Navegación"
#: modules/gridmap/grid_map.cpp scene/2d/navigation_2d.cpp
#: scene/2d/navigation_agent_2d.cpp scene/2d/navigation_polygon.cpp
#: scene/2d/tile_map.cpp scene/3d/navigation.cpp scene/3d/navigation_agent.cpp
#: scene/3d/navigation_mesh_instance.cpp
-#, fuzzy
msgid "Navigation Layers"
-msgstr "Modo de Navegación"
+msgstr "Capas de Navegación"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Plane"
@@ -17557,9 +17340,8 @@ msgid "Plotting lightmaps"
msgstr "Trazar lightmaps"
#: modules/lightmapper_cpu/register_types.cpp
-#, fuzzy
msgid "CPU Lightmapper"
-msgstr "Calcular Lightmaps"
+msgstr "CPU Lightmapper"
#: modules/lightmapper_cpu/register_types.cpp
msgid "Low Quality Ray Count"
@@ -17593,14 +17375,12 @@ msgid "IOD"
msgstr ""
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display Width"
-msgstr "Mostrar Wireframe"
+msgstr "Ancho de Pantalla"
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display To Lens"
-msgstr "Mostrar Sin Sombreado"
+msgstr "Pantalla a Lente"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Oversample"
@@ -17623,9 +17403,8 @@ msgid "Build Solution"
msgstr "Crear Solución"
#: modules/mono/editor/csharp_project.cpp
-#, fuzzy
msgid "Auto Update Project"
-msgstr "Proyecto Sin Nombre"
+msgstr "Actualización Automática del Proyecto"
#: modules/mono/mono_gd/gd_mono_utils.cpp
msgid "End of inner exception stack trace"
@@ -17727,9 +17506,8 @@ msgid "Period"
msgstr ""
#: modules/opensimplex/open_simplex_noise.cpp
-#, fuzzy
msgid "Persistence"
-msgstr "Perspectiva"
+msgstr "Persistencia"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Lacunarity"
@@ -17740,9 +17518,8 @@ msgid "Subject"
msgstr ""
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Names"
-msgstr "Nombre"
+msgstr "Nombres"
#: modules/regex/regex.cpp
msgid "Strings"
@@ -17761,32 +17538,28 @@ msgid "Discover IPv6"
msgstr ""
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Description URL"
-msgstr "Descripción"
+msgstr "Descripción URL"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Service Type"
-msgstr "Establecer Tipo de la Variable"
+msgstr "Tipo de Servicio"
#: modules/upnp/upnp_device.cpp
msgid "IGD Control URL"
msgstr ""
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Service Type"
-msgstr "Establecer Tipo de la Variable"
+msgstr "Tipo de Servicio IGD"
#: modules/upnp/upnp_device.cpp
msgid "IGD Our Addr"
msgstr ""
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Status"
-msgstr "Estado"
+msgstr "Estado del IGD"
#: modules/visual_script/visual_script.cpp
msgid ""
@@ -17827,9 +17600,8 @@ msgid "Stack overflow with stack depth:"
msgstr "Desbordamiento de pila con profundidad de pila:"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Visual Script"
-msgstr "Buscar en VisualScript"
+msgstr "Visual Script"
#: modules/visual_script/visual_script_editor.cpp
msgid "Change Signal Arguments"
@@ -18159,14 +17931,12 @@ msgid "Return"
msgstr "Regresar"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Enabled"
-msgstr "Ejecutable"
+msgstr "Retorno Activado"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Type"
-msgstr "Regresar"
+msgstr "Tipo de Retorno"
#: modules/visual_script/visual_script_flow_control.cpp
#: scene/resources/visual_shader_nodes.cpp
@@ -18214,9 +17984,8 @@ msgid "in order:"
msgstr "en orden:"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Steps"
-msgstr "Paso"
+msgstr "Pasos"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Switch"
@@ -18236,9 +18005,8 @@ msgstr "¿Es %s?"
#: modules/visual_script/visual_script_flow_control.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Base Script"
-msgstr "Nuevo Script"
+msgstr "Script Base"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "On %s"
@@ -18250,36 +18018,31 @@ msgstr "Sobre Sí Mismo"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Call Mode"
-msgstr "Modo de Escalado"
+msgstr "Modo de Llamada"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Basic Type"
-msgstr "Tipo Base"
+msgstr "Tipo Básico"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Node Path"
-msgstr "Copiar Ruta del Nodo"
+msgstr "Ruta del Nodo"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Use Default Args"
-msgstr "Restablecer Valores por Defecto"
+msgstr "Usar Argumentos por Defecto"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Validate"
msgstr "Validar"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "RPC Call Mode"
-msgstr "Modo de Escalado"
+msgstr "Modo de Llamada RPC"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Subtract %s"
@@ -18318,14 +18081,12 @@ msgid "BitXor %s"
msgstr "BitXor %s"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Set Mode"
-msgstr "Modo de Selección"
+msgstr "Modo de Ajuste"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Assign Op"
-msgstr "Asignar"
+msgstr "Asignar Op"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
@@ -18342,9 +18103,8 @@ msgid "Base object is not a Node!"
msgstr "¡El objeto base no es un nodo!"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Path does not lead to Node!"
-msgstr "¡La ruta no apunta a un Nodo!"
+msgstr "¡La ruta no lleva al nodo!"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Invalid index property name '%s' in node %s."
@@ -18360,9 +18120,8 @@ msgstr "Ordenar Array"
#: modules/visual_script/visual_script_nodes.cpp scene/resources/material.cpp
#: scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Operator"
-msgstr "Iterador"
+msgstr "Operador"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Invalid argument of type:"
@@ -18377,9 +18136,8 @@ msgid "a if cond, else b"
msgstr "a si cond, sino b"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Var Name"
-msgstr "Nombre"
+msgstr "Nombre de la Variable"
#: modules/visual_script/visual_script_nodes.cpp
msgid "VariableGet not found in script:"
@@ -18504,9 +18262,8 @@ msgid "%s sec(s)"
msgstr "%s seg(s)"
#: modules/visual_script/visual_script_yield_nodes.cpp scene/main/timer.cpp
-#, fuzzy
msgid "Wait Time"
-msgstr "Dibujar Tile"
+msgstr "Tiempo de Espera"
#: modules/visual_script/visual_script_yield_nodes.cpp
msgid "WaitSignal"
@@ -18521,18 +18278,16 @@ msgid "WaitInstanceSignal"
msgstr "WaitInstanceSignal"
#: modules/webrtc/webrtc_data_channel.cpp
-#, fuzzy
msgid "Write Mode"
-msgstr "Modo de Prioridad"
+msgstr "Modo de Escritura"
#: modules/webrtc/webrtc_data_channel.h
msgid "WebRTC"
msgstr ""
#: modules/webrtc/webrtc_data_channel.h
-#, fuzzy
msgid "Max Channel In Buffer (KB)"
-msgstr "Tamaño del buffer del índice del polígono del lienzo (KB)"
+msgstr "Buffer de Canal Máximo (KB)"
#: modules/websocket/websocket_client.cpp
msgid "Verify SSL"
@@ -18543,59 +18298,52 @@ msgid "Trusted SSL Certificate"
msgstr ""
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Client"
-msgstr "Red de Pares"
+msgstr "Cliente WebSocket"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "Max In Buffer (KB)"
-msgstr "Tamaño Máximo (KB)"
+msgstr "Buffer de Entrada Máximo (KB)"
#: modules/websocket/websocket_macros.h
msgid "Max In Packets"
msgstr ""
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "Max Out Buffer (KB)"
-msgstr "Tamaño Máximo (KB)"
+msgstr "Buffer de Salida Máximo (KB)"
#: modules/websocket/websocket_macros.h
msgid "Max Out Packets"
msgstr ""
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Server"
-msgstr "Red de Pares"
+msgstr "Servidor WebSocket"
#: modules/websocket/websocket_server.cpp
msgid "Bind IP"
msgstr ""
#: modules/websocket/websocket_server.cpp
-#, fuzzy
msgid "Private Key"
-msgstr "Ruta de la Clave Privada SSH"
+msgstr "Clave Privada"
#: modules/websocket/websocket_server.cpp platform/javascript/export/export.cpp
msgid "SSL Certificate"
msgstr ""
#: modules/websocket/websocket_server.cpp
-#, fuzzy
msgid "CA Chain"
-msgstr "Reestrablecer cadena IK"
+msgstr "Cadena CA"
#: modules/websocket/websocket_server.cpp
msgid "Handshake Timeout"
msgstr "Tiempo de Espera del Handshake"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Session Mode"
-msgstr "Modo de Región"
+msgstr "Modo de Sesión"
#: modules/webxr/webxr_interface.cpp
msgid "Required Features"
@@ -18614,28 +18362,24 @@ msgid "Reference Space Type"
msgstr ""
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Visibility State"
-msgstr "Cambiar Visibilidad"
+msgstr "Estado de Visibilidad"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Bounds Geometry"
-msgstr "Reintentar"
+msgstr "Límites Geométricos"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "XR Standard Mapping"
-msgstr "Ajuste Inteligente"
+msgstr "Mapeo Estándar XR"
#: platform/android/export/export.cpp
msgid "Android SDK Path"
msgstr ""
#: platform/android/export/export.cpp
-#, fuzzy
msgid "Debug Keystore"
-msgstr "Depurador"
+msgstr "Debug Keystore"
#: platform/android/export/export.cpp
msgid "Debug Keystore User"
@@ -18697,79 +18441,72 @@ 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
+msgid "Custom Build"
+msgstr "Build Personalizada"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
-msgstr ""
+msgstr "Usar Compilación Personalizada"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Export Format"
-msgstr "Ruta de Exportación"
+msgstr "Formato de Exportación"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "SDK Mínimo"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr "SDK de Destino"
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
-#, fuzzy
msgid "Architectures"
-msgstr "Añadir una entrada de arquitectura"
+msgstr "Arquitecturas"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Keystore"
-msgstr "Depurador"
+msgstr "Keystore"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Debug User"
-msgstr "Depurador"
+msgstr "Usuario de Depuración"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Debug Password"
-msgstr "Contraseña"
+msgstr "Contraseña de Depuración"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Release User"
-msgstr "Release"
+msgstr "Usuario de Release"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Release Password"
-msgstr "Contraseña"
+msgstr "Contraseña de Release"
#: platform/android/export/export_plugin.cpp
msgid "One Click Deploy"
msgstr ""
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Clear Previous Install"
-msgstr "Inspeccionar Instancia Anterior"
+msgstr "Limpiar Instalación Previa"
#: platform/android/export/export_plugin.cpp
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"
-msgstr "Empaquetando"
+msgstr "Paquete"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Unique Name"
msgstr "Nombre Único"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Signed"
-msgstr "Señal"
+msgstr "Firmado"
#: platform/android/export/export_plugin.cpp
msgid "Classify As Game"
@@ -18780,33 +18517,28 @@ msgid "Retain Data On Uninstall"
msgstr ""
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Exclude From Recents"
-msgstr "Eliminar Nodos"
+msgstr "Excluir de los Recientes"
#: platform/android/export/export_plugin.cpp
msgid "Graphics"
msgstr "Gráficos"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "OpenGL Debug"
-msgstr "Abrir"
+msgstr "Depuración de OpenGL"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "XR Features"
-msgstr "Características"
+msgstr "Características del XR"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "XR Mode"
-msgstr "Modo desplazamiento lateral"
+msgstr "Modo XR"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Hand Tracking"
-msgstr "Empaquetando"
+msgstr "Seguimiento de Manos"
#: platform/android/export/export_plugin.cpp
msgid "Hand Tracking Frequency"
@@ -18817,71 +18549,60 @@ msgid "Passthrough"
msgstr ""
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Immersive Mode"
-msgstr "Modo de Prioridad"
+msgstr "Modo Inmersivo"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Small"
-msgstr "Soporte"
+msgstr "Soporte Pequeño"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Normal"
-msgstr "Soporte"
+msgstr "Soporte Normal"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Large"
-msgstr "Soporte"
+msgstr "Soporte Grande"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Support Xlarge"
-msgstr "Soporte"
+msgstr "Soporte Xlarge"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "User Data Backup"
-msgstr "Interfaz de usuario"
+msgstr "Backup de Datos del Usuario"
#: platform/android/export/export_plugin.cpp
msgid "Allow"
msgstr ""
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Command Line"
-msgstr "Command"
+msgstr "Línea de Comandos"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Extra Args"
msgstr "Argumentos extras"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "APK Expansion"
-msgstr "Expresión"
+msgstr "Expansión del APK"
#: platform/android/export/export_plugin.cpp
msgid "Salt"
msgstr ""
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Public Key"
-msgstr "Ruta de la clave pública SSH"
+msgstr "Clave Pública"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Permissions"
-msgstr "Máscara de Emisión"
+msgstr "Permisos"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Custom Permissions"
-msgstr "Reproducir Escena Personalizada"
+msgstr "Permisos Personalizados"
#: platform/android/export/export_plugin.cpp
msgid "Select device from the list"
@@ -19010,51 +18731,75 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid "\"Use Custom Build\" must be enabled to use the plugins."
-msgstr "\"Use Custom Build\" debe estar activado para usar los plugins."
+msgstr ""
+"\"Usar Compilación Personalizada\" debe estar activado para usar los 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\" solo es válido cuando \"Xr Mode\" es \"Oculus Mobile "
-"VrApi\" u \"OpenXR\"."
+"\"Seguimiento de Manos\" solo es válido cuando el \"Modo XR\" es \"Oculus "
+"Mobile VrApi\" u \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
-msgstr "\"Passthrough\" solo es válido cuando \"Xr Mode\" es \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
+msgstr "\"Passthrough\" solo es válido cuando el \"Modo XR\" es \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
msgstr ""
-"\"Export AAB\" sólo es válido cuando \"Use Custom Build\" está activado."
+"\"Exportar AAB\" solo es válido cuando \"Usar Compilación Personalizada\" "
+"está activado."
#: 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 ""
+"\"Min SDK\" solo puede sobrescribirse cuando está activada la opción \"Usar "
+"Compilación Personalizada\"."
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
-"Cambiar el \"Min Sdk\" solo es válido cuando \"Use Custom Build\" está "
-"activado."
#: 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 ""
-"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\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
-"La versión de \"Target Sdk\" debe ser mayor o igual que la versión de \"Min "
-"Sdk\"."
+"\"SDK de Destino\" solo se puede sobrescribir cuando \"Usar Compilación "
+"Personalizada\" está activado."
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+"\"SDK de Destino\" debería ser un entero válido, pero obtuvo \"%s\" inválido."
+
+#: 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 ""
+"\"SDK de Destino\" %d es superior a la versión por defecto %d. Podría "
+"funcionar, pero no se ha probado y puede ser inestable."
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
+msgstr ""
+"La versión \"SDK de Destino\" debe ser mayor o igual a la versión \"Min "
+"SDK\"."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Code Signing"
-msgstr "Firma de código DMG"
+msgstr "Firma del Código"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19284,9 +19029,8 @@ msgid "Code Sign Identity Debug"
msgstr ""
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Export Method Debug"
-msgstr "Exportar Con Depuración"
+msgstr "Exportar Método de Depuración"
#: platform/iphone/export/export.cpp
msgid "Provisioning Profile UUID Release"
@@ -19313,39 +19057,33 @@ msgid "Identifier"
msgstr "Identificador"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Signature"
-msgstr "Señal"
+msgstr "Firma"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Short Version"
-msgstr "Versión"
+msgstr "Versión Corta"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Copyright"
-msgstr "Superior Derecha"
+msgstr "Copyright"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Capabilities"
-msgstr "Capitalizar Propiedades"
+msgstr "Capacidades"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Access Wi-Fi"
-msgstr "Acceso"
+msgstr "Acceso Wi-Fi"
#: platform/iphone/export/export.cpp
msgid "Push Notifications"
msgstr "Notificaciones Push"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "User Data"
-msgstr "Interfaz de usuario"
+msgstr "Datos de Usuario"
#: platform/iphone/export/export.cpp
msgid "Accessible From Files App"
@@ -19356,24 +19094,20 @@ msgid "Accessible From iTunes Sharing"
msgstr ""
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Privacy"
-msgstr "Ruta de la Clave Privada SSH"
+msgstr "Privacidad"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Camera Usage Description"
-msgstr "Descripción"
+msgstr "Descripción del Uso de la Cámara"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Microphone Usage Description"
-msgstr "Descripciones de Propiedades"
+msgstr "Descripción del Uso del Micrófono"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Photolibrary Usage Description"
-msgstr "Descripciones de Propiedades"
+msgstr "Descripción del Uso de la Fotolibrería"
#: platform/iphone/export/export.cpp
msgid "iPhone 120 X 120"
@@ -19416,40 +19150,33 @@ msgid "Use Launch Screen Storyboard"
msgstr ""
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Image Scale Mode"
-msgstr "Modo de Escalado"
+msgstr "Modo de Escalado de Imagen"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom Image @2x"
-msgstr "CustomNode"
+msgstr "Imagen Personalizada @2x"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom Image @3x"
-msgstr "CustomNode"
+msgstr "Imagen Personalizada @3x"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Use Custom BG Color"
-msgstr "CustomNode"
+msgstr "Usar Color de Fondo Personalizado"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom BG Color"
-msgstr "CustomNode"
+msgstr "Color de Fondo Personalizado"
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Prepare Templates"
-msgstr "Administrar Plantillas"
+msgstr "Preparar Plantillas"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Export template not found."
-msgstr "Plantilla release personalizada no encontrada."
+msgstr "No se ha encontrado la plantilla de exportación."
#: platform/iphone/export/export.cpp
msgid "App Store Team ID not specified - cannot configure the project."
@@ -19485,9 +19212,8 @@ msgid "Could not write file: \"%s\"."
msgstr "No se pudo escribir el archivo: \"%s\"."
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Icon Creation"
-msgstr "Asignar Margen"
+msgstr "Creación de Iconos"
#: platform/javascript/export/export.cpp
msgid "Could not read file: \"%s\"."
@@ -19502,14 +19228,12 @@ msgid "Variant"
msgstr "Variante"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Export Type"
-msgstr "Exportar"
+msgstr "Tipo de Exportación"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "VRAM Texture Compression"
-msgstr "Expresión"
+msgstr "Compresión de Texturas en la VRAM"
#: platform/javascript/export/export.cpp
msgid "For Desktop"
@@ -19524,14 +19248,12 @@ msgid "HTML"
msgstr ""
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Export Icon"
-msgstr "Expandir Todo"
+msgstr "Icono de Exportación"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Custom HTML Shell"
-msgstr "CustomNode"
+msgstr "HTML Shell Personalizado"
#: platform/javascript/export/export.cpp
msgid "Head Include"
@@ -19546,9 +19268,8 @@ msgid "Focus Canvas On Start"
msgstr ""
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Experimental Virtual Keyboard"
-msgstr "Filtrar señales"
+msgstr "Teclado Virtual Experimental"
#: platform/javascript/export/export.cpp
msgid "Progressive Web App"
@@ -19595,9 +19316,8 @@ msgid "HTTP Port"
msgstr ""
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Use SSL"
-msgstr "Usar Snap"
+msgstr "Usar SSL"
#: platform/javascript/export/export.cpp
msgid "SSL Key"
@@ -19684,33 +19404,28 @@ msgid "High Res"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Location Usage Description"
-msgstr "Descripción"
+msgstr "Ubicación de la Descripción de Uso"
#: platform/osx/export/export.cpp
msgid "Address Book Usage Description"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Calendar Usage Description"
-msgstr "Descripción"
+msgstr "Descripción del Uso del Calendario"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Photos Library Usage Description"
-msgstr "Descripciones de Propiedades"
+msgstr "Descripción de Uso de la Librería de Fotos"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Desktop Folder Usage Description"
-msgstr "Descripciones de Métodos"
+msgstr "Descripción de Uso de la Carpeta de Escritorio"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Documents Folder Usage Description"
-msgstr "Descripciones de Métodos"
+msgstr "Descripción de Uso de la Carpeta de Documentos"
#: platform/osx/export/export.cpp
msgid "Downloads Folder Usage Description"
@@ -19725,39 +19440,33 @@ msgid "Removable Volumes Usage Description"
msgstr ""
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Codesign"
-msgstr "Firma de código DMG"
+msgstr "Codesign"
#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Identity"
-msgstr "Indentar a la Izquierda"
+msgstr "Identidad"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Timestamp"
-msgstr "Tiempo"
+msgstr "Marca de Tiempo"
#: platform/osx/export/export.cpp
msgid "Hardened Runtime"
-msgstr ""
+msgstr "Hardened Runtime"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Replace Existing Signature"
-msgstr "Reemplazar en Archivos"
+msgstr "Reemplazar Firma Existente"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Entitlements"
-msgstr "Gizmos"
+msgstr "Derechos"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Custom File"
-msgstr "CustomNode"
+msgstr "Archivo Personalizado"
#: platform/osx/export/export.cpp
msgid "Allow JIT Code Execution"
@@ -19772,14 +19481,12 @@ msgid "Allow Dyld Environment Variables"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Disable Library Validation"
-msgstr "Botón Desactivado"
+msgstr "Desactivar Validación de Bibliotecas"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Audio Input"
-msgstr "Añadir Entrada"
+msgstr "Entrada de Audio"
#: platform/osx/export/export.cpp
msgid "Address Book"
@@ -19790,81 +19497,68 @@ msgid "Calendars"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Photos Library"
-msgstr "Exportar Librería"
+msgstr "Librería de Fotos"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Apple Events"
-msgstr "Añadir Evento"
+msgstr "Eventos de Apple"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Debugging"
-msgstr "Depurar"
+msgstr "Depuración"
#: platform/osx/export/export.cpp
msgid "App Sandbox"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Network Server"
-msgstr "Red de Pares"
+msgstr "Servidor de Red"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Network Client"
-msgstr "Red de Pares"
+msgstr "Cliente de Red"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Device USB"
-msgstr "Dispositivo"
+msgstr "Dispositivo USB"
#: platform/osx/export/export.cpp
msgid "Device Bluetooth"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Downloads"
-msgstr "Descargar"
+msgstr "Descargas de Archivos"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Pictures"
-msgstr "Características"
+msgstr "Archivos de Imágenes"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Music"
-msgstr "Archivo"
+msgstr "Archivos de Música"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Files Movies"
-msgstr "Filtrar tiles"
+msgstr "Archivos de Vídeo"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Custom Options"
-msgstr "Opciones de Bus"
+msgstr "Opciones Personalizadas"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization"
-msgstr "Traducciones"
+msgstr "Notarización"
#: platform/osx/export/export.cpp
msgid "Apple ID Name"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Apple ID Password"
-msgstr "Contraseña"
+msgstr "Contraseña del ID de Apple"
#: platform/osx/export/export.cpp
msgid "Apple Team ID"
@@ -19887,13 +19581,12 @@ msgid "Notarization request UUID: \"%s\""
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid ""
"The notarization process generally takes less than an hour. When the process "
"is completed, you'll receive an email."
msgstr ""
-"Nota: El proceso de notarización generalmente toma menos de una hora. Cuando "
-"se complete el proceso, recibirá un correo electrónico."
+"El proceso de notarización suele durar menos de una hora. Cuando el proceso "
+"haya finalizado, recibirás un correo electrónico."
#: platform/osx/export/export.cpp
msgid ""
@@ -19912,17 +19605,15 @@ msgstr ""
"notarial a la aplicación exportada (opcional):"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Timestamping is not compatible with ad-hoc signature, and was disabled!"
msgstr ""
-"El sellado de tiempo no es compatible con la firma ad-hoc, y se desactivará!"
+"¡La marca de tiempo no es compatible con la firma ad-hoc, y fue desactivada!"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid ""
"Hardened Runtime is not compatible with ad-hoc signature, and was disabled!"
msgstr ""
-"Hardened Runtime no es compatible con la firma ad-hoc, y se desactivará!"
+"¡Hardened Runtime no es compatible con la firma ad-hoc, y fue desactivado!"
#: platform/osx/export/export.cpp
msgid "Built-in CodeSign failed with error \"%s\"."
@@ -19947,16 +19638,14 @@ msgid "Cannot sign file %s."
msgstr "No se puede firmar el archivo %s."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Relative symlinks are not supported, exported \"%s\" might be broken!"
msgstr ""
-"Los enlaces simbólicos relativos no son compatibles con este sistema "
-"operativo, ¡el proyecto exportado podría estar dañado!"
+"Los enlaces simbólicos relativos no son compatibles, ¡los \"%s\" exportados "
+"podrían estar rotos!"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "DMG Creation"
-msgstr "Direcciones"
+msgstr "Creación de DMG"
#: platform/osx/export/export.cpp
msgid "Could not start hdiutil executable."
@@ -19992,13 +19681,12 @@ msgstr ""
"operativo, ¡el proyecto exportado podría estar dañado!"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid ""
"Requested template binary \"%s\" not found. It might be missing from your "
"template archive."
msgstr ""
-"Plantilla binaria solicitada '%s' no encontrada. Es posible que falte en el "
-"archivo de plantillas."
+"No se ha encontrado la plantilla binaria \"%s\" solicitada. Es posible que "
+"no se encuentre en el archivo de plantillas."
#: platform/osx/export/export.cpp
msgid "Making PKG"
@@ -20041,9 +19729,8 @@ msgid "Sending archive for notarization"
msgstr "Enviando archivo para notarización"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "ZIP Creation"
-msgstr "Proyecto"
+msgstr "Creación de ZIP"
#: platform/osx/export/export.cpp
msgid "Could not open file to read from path \"%s\"."
@@ -20082,9 +19769,7 @@ msgstr "Notarización: Se requiere la firma del código para la notarización."
#: platform/osx/export/export.cpp
msgid "Notarization: Hardened runtime is required for notarization."
-msgstr ""
-"Notarización: se requiere tiempo de ejecución endurecido para la "
-"certificación notarial."
+msgstr "Notarización: Se requiere Hardened runtime para la notarización."
#: platform/osx/export/export.cpp
msgid "Notarization: Timestamp runtime is required for notarization."
@@ -20121,7 +19806,7 @@ msgid ""
"Hardened Runtime is not compatible with ad-hoc signature, and will be "
"disabled!"
msgstr ""
-"Hardened Runtime no es compatible con la firma ad-hoc, y se desactivará!"
+"¡Hardened Runtime no es compatible con la firma ad-hoc, y se desactivará!"
#: platform/osx/export/export.cpp
msgid ""
@@ -20193,14 +19878,12 @@ msgid "Force Builtin Codesign"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Architecture"
-msgstr "Añadir una entrada de arquitectura"
+msgstr "Arquitectura"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Display Name"
-msgstr "Escala de Visualización"
+msgstr "Nombre a Mostrar"
#: platform/uwp/export/export.cpp
msgid "Short Name"
@@ -20219,24 +19902,20 @@ msgid "Product GUID"
msgstr "GUID del producto"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Publisher GUID"
-msgstr "Limpiar Guías"
+msgstr "GUID del Editor"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Signing"
-msgstr "Señal"
+msgstr "Firmando"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Certificate"
-msgstr "Certificados"
+msgstr "Certificado"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Algorithm"
-msgstr "Depurador"
+msgstr "Algoritmo"
#: platform/uwp/export/export.cpp
msgid "Major"
@@ -20247,23 +19926,20 @@ msgid "Minor"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Build"
-msgstr "Modo de Regla"
+msgstr "Compilación"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Revision"
-msgstr "Expresión"
+msgstr "Revisión"
#: platform/uwp/export/export.cpp
msgid "Landscape"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Portrait"
-msgstr "Voltear Portales"
+msgstr "Retrato"
#: platform/uwp/export/export.cpp
msgid "Landscape Flipped"
@@ -20274,9 +19950,8 @@ msgid "Portrait Flipped"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Store Logo"
-msgstr "Modo de Escalado"
+msgstr "Logo de Tienda"
#: platform/uwp/export/export.cpp
msgid "Square 44 X 44 Logo"
@@ -20303,9 +19978,8 @@ msgid "Splash Screen"
msgstr "Pantalla de Bienvenida"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Tiles"
-msgstr "Archivo"
+msgstr "Tiles"
#: platform/uwp/export/export.cpp
msgid "Show Name On Square 150 X 150"
@@ -20389,18 +20063,16 @@ msgid "UWP"
msgstr ""
#: platform/uwp/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Signtool"
-msgstr "Señal"
+msgstr "Signtool"
#: platform/uwp/export/export.cpp
msgid "Debug Certificate"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Debug Algorithm"
-msgstr "Depurador"
+msgstr "Algoritmo de Depuración"
#: platform/windows/export/export.cpp
msgid "Failed to rename temporary file \"%s\"."
@@ -20415,19 +20087,16 @@ msgid "Timestamp Server URL"
msgstr ""
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Digest Algorithm"
-msgstr "Depurador"
+msgstr "Algoritmo de Compilación"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Modify Resources"
-msgstr "Copiar Recurso"
+msgstr "Modificar Recursos"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "File Version"
-msgstr "Versión"
+msgstr "Versión del Archivo"
#: platform/windows/export/export.cpp
msgid "Product Version"
@@ -20442,79 +20111,70 @@ msgid "Product Name"
msgstr "Nombre del Producto"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "File Description"
-msgstr "Descripción"
+msgstr "Descripción del Archivo"
#: platform/windows/export/export.cpp
msgid "Trademarks"
msgstr ""
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Resources Modification"
-msgstr "Notificaciones Push"
+msgstr "Modificación de los Recursos"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Could not find rcedit executable at \"%s\"."
-msgstr "No se pudo encontrar la keystore, no se puedo exportar."
+msgstr "No se pudo encontrar el ejecutable rcedit en \"%s\"."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Could not find wine executable at \"%s\"."
-msgstr "No se pudo encontrar la keystore, no se puedo exportar."
+msgstr "No se pudo encontrar el ejecutable de wine en \"%s\"."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
-"La herramienta rcedit debe configurarse en la configuración del editor "
-"(Exportar > Windows > Rcedit) para cambiar los datos de información del "
-"ícono o la aplicación."
+"No se ha podido iniciar el ejecutable rcedit, configura la ruta de rcedit en "
+"la configuración del editor (Exportar > Windows > Rcedit)."
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Fallo al abrir el archivo ejecutable \"%s\"."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Could not find signtool executable at \"%s\"."
-msgstr "No se pudo encontrar la keystore, no se puedo exportar."
+msgstr "No se pudo encontrar el ejecutable de signtool en \"%s\"."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Could not find osslsigncode executable at \"%s\"."
-msgstr "No se pudo encontrar la keystore, no se puedo exportar."
+msgstr "No se pudo encontrar el ejecutable osslsigncode en \"%s\"."
#: platform/windows/export/export.cpp
msgid "Invalid identity type."
msgstr "Tipo de identificador inválido."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Invalid timestamp server."
-msgstr "Nombre inválido."
+msgstr "Servidor de marcas de tiempo inválido."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
-"La herramienta rcedit debe configurarse en la configuración del editor "
-"(Exportar > Windows > Rcedit) para cambiar los datos de información del "
-"ícono o la aplicación."
+"No se ha podido iniciar el ejecutable de signtool, configura la ruta de "
+"signtool en la configuración del editor (Exportar > Windows > Signtool)."
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Fallo al abrir el archivo ejecutable \"%s\"."
#: platform/windows/export/export.cpp
msgid "Failed to remove temporary file \"%s\"."
@@ -20546,9 +20206,8 @@ msgid "Windows executables cannot be >= 4 GiB."
msgstr ""
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
-#, fuzzy
msgid "Failed to open executable file \"%s\"."
-msgstr "Archivo ejecutable no válido."
+msgstr "Fallo al abrir el archivo ejecutable \"%s\"."
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
msgid "Executable file header corrupted."
@@ -20559,9 +20218,8 @@ msgid "Executable \"pck\" section not found."
msgstr ""
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Windows"
-msgstr "Nueva Ventana"
+msgstr "Windows"
#: platform/windows/export/export.cpp
msgid "Rcedit"
@@ -20581,9 +20239,8 @@ msgstr ""
#: scene/2d/animated_sprite.cpp scene/3d/sprite_3d.cpp
#: scene/resources/texture.cpp
-#, fuzzy
msgid "Frames"
-msgstr "Fotograma %"
+msgstr "Fotogramas"
#: scene/2d/animated_sprite.cpp
msgid ""
@@ -20595,21 +20252,18 @@ msgstr ""
#: scene/2d/animated_sprite.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Speed Scale"
-msgstr "Escala"
+msgstr "Escala de Velocidad"
#: scene/2d/animated_sprite.cpp scene/2d/audio_stream_player_2d.cpp
#: scene/3d/audio_stream_player_3d.cpp scene/3d/sprite_3d.cpp
#: scene/audio/audio_stream_player.cpp
-#, fuzzy
msgid "Playing"
msgstr "Reproducir"
#: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
-#, fuzzy
msgid "Centered"
-msgstr "Centro"
+msgstr "Centrado"
#: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#: scene/gui/texture_button.cpp scene/gui/texture_rect.cpp
@@ -20622,39 +20276,32 @@ msgid "Flip V"
msgstr ""
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Monitoring"
-msgstr "Monitor"
+msgstr "Monitorización"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Monitorable"
-msgstr "Monitor"
+msgstr "Monitorizable"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Physics Overrides"
-msgstr "Anulaciones"
+msgstr "Anulaciones de Físicas"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Space Override"
-msgstr "Anulaciones"
+msgstr "Anulación de Espacio"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Gravity Point"
-msgstr "Generar puntos"
+msgstr "Punto de Gravedad"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Gravity Distance Scale"
-msgstr "WaitInstanceSignal"
+msgstr "Escala de Distancia de la Gravedad"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Gravity Vec"
-msgstr "Vista Previa Por Defecto"
+msgstr "Velocidad de la Gravedad"
#: scene/2d/area_2d.cpp scene/2d/cpu_particles_2d.cpp scene/3d/area.cpp
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
@@ -20662,42 +20309,36 @@ msgid "Gravity"
msgstr ""
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Linear Damp"
-msgstr "Lineal"
+msgstr "Amortiguación Lineal"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
msgid "Angular Damp"
msgstr ""
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Audio Bus"
-msgstr "Añadir Bus de Audio"
+msgstr "Bus de Audio"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Override"
-msgstr "Anulaciones"
+msgstr "Anular"
#: scene/2d/audio_stream_player_2d.cpp scene/audio/audio_stream_player.cpp
#: scene/gui/video_player.cpp servers/audio/effects/audio_effect_amplify.cpp
-#, fuzzy
msgid "Volume dB"
-msgstr "Volumen"
+msgstr "Volumen dB"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp
#: servers/audio/effects/audio_effect_pitch_shift.cpp
-#, fuzzy
msgid "Pitch Scale"
-msgstr "Escala"
+msgstr "Escala de Tono"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
-#, fuzzy
msgid "Autoplay"
-msgstr "Act./Desact. Reproducción Automática"
+msgstr "Reproducción Automática"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp
@@ -20712,29 +20353,25 @@ msgid "Max Distance"
msgstr "Distancia Maxima"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/light.cpp
-#, fuzzy
msgid "Attenuation"
-msgstr "Animación"
+msgstr "Atenuación"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
-#, fuzzy
msgid "Bus"
-msgstr "Añadir Bus"
+msgstr "Bus"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
msgid "Area Mask"
msgstr ""
#: scene/2d/back_buffer_copy.cpp
-#, fuzzy
msgid "Copy Mode"
-msgstr "Copiar Nodos"
+msgstr "Modo de Copia"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Anchor Mode"
-msgstr "Modo de Icono"
+msgstr "Modo de Anclaje"
#: scene/2d/camera_2d.cpp
msgid "Rotating"
@@ -20746,83 +20383,70 @@ msgid "Current"
msgstr "Actual"
#: scene/2d/camera_2d.cpp scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom"
-msgstr "Acercar Zoom"
+msgstr "Zoom"
#: scene/2d/camera_2d.cpp scene/main/canvas_layer.cpp
-#, fuzzy
msgid "Custom Viewport"
-msgstr "1 Viewport"
+msgstr "Viewport Personalizado"
-#: 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
msgid "Process Mode"
-msgstr "Modo de Movimiento"
+msgstr "Modo de Proceso"
#: scene/2d/camera_2d.cpp
msgid "Limit"
-msgstr ""
+msgstr "Limite"
#: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp
#: scene/resources/style_box.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Left"
-msgstr "UI Izquierda"
+msgstr "Izquierda"
#: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp
#: scene/resources/style_box.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Right"
-msgstr "Luz"
+msgstr "Derecha"
#: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp
#: scene/resources/dynamic_font.cpp scene/resources/style_box.cpp
#: scene/resources/texture.cpp
-#, fuzzy
msgid "Bottom"
-msgstr "Inferior Izquierda"
+msgstr "Inferior"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Smoothed"
msgstr "Suavizado"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Draw Margin"
-msgstr "Asignar Margen"
+msgstr "Margen de Arrastre"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Drag Margin H Enabled"
-msgstr "Asignar Margen"
+msgstr "Margen de Arrastre H Activado"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Drag Margin V Enabled"
-msgstr "Asignar Margen"
+msgstr "Margen de Arrastre V Activado"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Smoothing"
-msgstr "Suavizado"
+msgstr "Suavizar"
#: scene/2d/camera_2d.cpp
msgid "H"
msgstr ""
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "V"
-msgstr "UV"
+msgstr "V"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Drag Margin"
-msgstr "Asignar Margen"
+msgstr "Margen de Arrastre"
#: scene/2d/camera_2d.cpp
msgid "Draw Screen"
@@ -20833,25 +20457,21 @@ msgid "Draw Limits"
msgstr "Límites de Dibujo"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Draw Drag Margin"
-msgstr "Asignar Margen"
+msgstr "Margen de Arrastre del Trazado"
#: scene/2d/canvas_item.cpp scene/resources/environment.cpp
#: scene/resources/material.cpp
-#, fuzzy
msgid "Blend Mode"
-msgstr "Nodo Blend2"
+msgstr "Modo de Fusión"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Light Mode"
-msgstr "Ancho Derecha"
+msgstr "Modo de Iluminación"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Particles Animation"
-msgstr "Partículas"
+msgstr "Animación de Partículas"
#: scene/2d/canvas_item.cpp
msgid "Particles Anim H Frames"
@@ -20862,40 +20482,34 @@ msgid "Particles Anim V Frames"
msgstr ""
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Particles Anim Loop"
-msgstr "Partículas"
+msgstr "Bucle de Animación de Partículas"
#: scene/2d/canvas_item.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Visibility"
-msgstr "Cambiar Visibilidad"
+msgstr "Visibilidad"
#: scene/2d/canvas_item.cpp scene/3d/spatial.cpp scene/gui/progress_bar.cpp
#: scene/gui/rich_text_effect.cpp scene/main/canvas_layer.cpp
-#, fuzzy
msgid "Visible"
-msgstr "Cambiar Visibilidad"
+msgstr "Visible"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Self Modulate"
-msgstr "Rellenar"
+msgstr "Modulación Automática"
#: scene/2d/canvas_item.cpp
msgid "Show Behind Parent"
msgstr ""
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Show On Top"
-msgstr "Mostrar Origen"
+msgstr "Mostrar Arriba"
#: scene/2d/canvas_item.cpp scene/2d/light_occluder_2d.cpp
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Light Mask"
-msgstr "Luz"
+msgstr "Máscara de Luz"
#: scene/2d/canvas_item.cpp
msgid "Use Parent Material"
@@ -20922,9 +20536,8 @@ msgstr ""
"CollisionPolygon2D para definir su forma."
#: scene/2d/collision_object_2d.cpp
-#, fuzzy
msgid "Pickable"
-msgstr "Elegir Tile"
+msgstr "Seleccionable"
#: scene/2d/collision_polygon_2d.cpp
msgid ""
@@ -20957,29 +20570,27 @@ msgstr ""
msgid ""
"The One Way Collision property will be ignored when the parent is an Area2D."
msgstr ""
+"La propiedad Colisión en Una Dirección será ignorada cuando el padre sea un "
+"Area2D."
#: scene/2d/collision_polygon_2d.cpp
-#, fuzzy
msgid "Build Mode"
-msgstr "Modo de Regla"
+msgstr "Modo de Compilación"
#: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp
#: scene/3d/collision_polygon.cpp scene/3d/collision_shape.cpp
#: scene/animation/animation_node_state_machine.cpp scene/gui/base_button.cpp
#: scene/gui/texture_button.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Disabled"
-msgstr "Desactivar Elemento"
+msgstr "Desactivado"
#: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp
-#, fuzzy
msgid "One Way Collision"
-msgstr "Crear Polígono de Colisión"
+msgstr "Colisión en Una Dirección"
#: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp
-#, fuzzy
msgid "One Way Collision Margin"
-msgstr "Crear Polígono de Colisión"
+msgstr "Margen de Colisión en Una Dirección"
#: scene/2d/collision_shape_2d.cpp
msgid ""
@@ -21028,15 +20639,13 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp scene/main/timer.cpp
-#, fuzzy
msgid "One Shot"
-msgstr "Nodo OneShot"
+msgstr "Un Disparo"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Preprocess"
-msgstr "Post procesado"
+msgstr "Preproceso"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -21055,9 +20664,8 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Fixed FPS"
-msgstr "Ver FPS"
+msgstr "FPS Fijos"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -21071,9 +20679,8 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Local Coords"
-msgstr "Proyectos Locales"
+msgstr "Coordenadas Locales"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -21082,9 +20689,8 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Emission Shape"
-msgstr "Máscara de Emisión"
+msgstr "Forma de la Emisión"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21092,26 +20698,22 @@ msgid "Sphere Radius"
msgstr "Radio de la Esfera"
#: scene/2d/cpu_particles_2d.cpp
-#, fuzzy
msgid "Rect Extents"
-msgstr "Gizmos"
+msgstr "Extender Completo"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
-#, fuzzy
msgid "Normals"
-msgstr "Formato"
+msgstr "Normales"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Align Y"
-msgstr "Asignar"
+msgstr "Alineación Y"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Direction"
-msgstr "Direcciones"
+msgstr "Dirección"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21121,15 +20723,13 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Initial Velocity"
-msgstr "Inicializar"
+msgstr "Velocidad Inicial"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Velocity Random"
-msgstr "Velocidad"
+msgstr "Velocidad Aleatoria"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
@@ -21139,27 +20739,23 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Velocity Curve"
-msgstr "Velocidad"
+msgstr "Curva de Velocidad"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Orbit Velocity"
-msgstr "Vista de Órbita Derecha"
+msgstr "Velocidad de la Órbita"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Linear Accel"
-msgstr "Lineal"
+msgstr "Aceleración Lineal"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Accel"
-msgstr "Acceso"
+msgstr "Aceleración"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21168,9 +20764,8 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Accel Curve"
-msgstr "Partir Curva"
+msgstr "Curva de Aceleración"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21197,9 +20792,8 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Damping Curve"
-msgstr "Partir Curva"
+msgstr "Curva de Amortiguación"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/light.cpp
#: scene/resources/particles_material.cpp
@@ -21213,9 +20807,8 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Angle Curve"
-msgstr "Cerrar Curva"
+msgstr "Curva de Ãngulo"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
msgid "Scale Amount"
@@ -21226,15 +20819,13 @@ msgid "Scale Amount Random"
msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
-#, fuzzy
msgid "Scale Amount Curve"
-msgstr "Escalar Desde Cursor"
+msgstr "Curva de Cantidad de Escala"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Color Ramp"
-msgstr "Colores"
+msgstr "Rampa de Color"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21263,15 +20854,13 @@ msgstr "Curva de Variación"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Speed Random"
-msgstr "Escala"
+msgstr "Velocidad Aleatoria"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Speed Curve"
-msgstr "Partir Curva"
+msgstr "Curva de Velocidad"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21280,9 +20869,8 @@ msgstr "Desplazamiento Aleatorio"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Offset Curve"
-msgstr "Cerrar Curva"
+msgstr "Curva de Desplazamiento"
#: scene/2d/joints_2d.cpp
msgid "Node A and Node B must be PhysicsBody2Ds"
@@ -21305,14 +20893,12 @@ msgid "Node A and Node B must be different PhysicsBody2Ds"
msgstr "El Nodo A y el Nodo B deben ser diferentes PhysicsBody2D"
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Node A"
-msgstr "Nodos"
+msgstr "Nodo A"
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Node B"
-msgstr "Nodos"
+msgstr "Nodo B"
#: scene/2d/joints_2d.cpp scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/light.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
@@ -21321,9 +20907,8 @@ msgid "Bias"
msgstr ""
#: scene/2d/joints_2d.cpp
-#, fuzzy
msgid "Disable Collision"
-msgstr "Botón Desactivado"
+msgstr "Desactivar Colisión"
#: scene/2d/joints_2d.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Softness"
@@ -21335,9 +20920,8 @@ msgid "Length"
msgstr ""
#: scene/2d/joints_2d.cpp
-#, fuzzy
msgid "Initial Offset"
-msgstr "Inicializar"
+msgstr "Desplazamiento Inicial"
#: scene/2d/joints_2d.cpp scene/3d/vehicle_body.cpp
msgid "Rest Length"
@@ -21356,14 +20940,12 @@ msgstr ""
"Texture\"."
#: scene/2d/light_2d.cpp scene/3d/light.cpp scene/gui/reference_rect.cpp
-#, fuzzy
msgid "Editor Only"
-msgstr "Editor"
+msgstr "Sólo para el Editor"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Texture Scale"
-msgstr "Región de Textura"
+msgstr "Escala de Textura"
#: scene/2d/light_2d.cpp scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/light.cpp scene/resources/environment.cpp
@@ -21380,48 +20962,40 @@ msgid "Z Max"
msgstr ""
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Layer Min"
-msgstr "Cambiar Tamaño de Cámara"
+msgstr "Capa Mínima"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Layer Max"
-msgstr "Capa"
+msgstr "Capa Máxima"
#: scene/2d/light_2d.cpp
msgid "Item Cull Mask"
msgstr ""
#: scene/2d/light_2d.cpp scene/3d/light.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Shadow"
-msgstr "Shader"
+msgstr "Sombra"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Buffer Size"
-msgstr "Vista Trasera"
+msgstr "Tamaño del Buffer"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Gradient Length"
-msgstr "Degradado Editado"
+msgstr "Longitud del Gradiente"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Filter Smooth"
-msgstr "Filtrar métodos"
+msgstr "Filtro Suavizado"
#: scene/2d/light_occluder_2d.cpp
-#, fuzzy
msgid "Closed"
-msgstr "Cerrar"
+msgstr "Cerrado"
#: scene/2d/light_occluder_2d.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Cull Mode"
-msgstr "Modo de Regla"
+msgstr "Modo de Sacrificio"
#: scene/2d/light_occluder_2d.cpp
msgid ""
@@ -21437,47 +21011,40 @@ msgstr ""
"polígono."
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Width Curve"
-msgstr "Partir Curva"
+msgstr "Curva de Ancho"
#: scene/2d/line_2d.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Default Color"
-msgstr "Por defecto"
+msgstr "Color por Defecto"
#: scene/2d/line_2d.cpp scene/resources/texture.cpp
msgid "Fill"
-msgstr ""
+msgstr "Rellenar"
#: scene/2d/line_2d.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Gradient"
-msgstr "Degradado Editado"
+msgstr "Gradiente"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Texture Mode"
-msgstr "Región de Textura"
+msgstr "Modo de Textura"
#: scene/2d/line_2d.cpp
msgid "Capping"
-msgstr ""
+msgstr "Tapado"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Joint Mode"
-msgstr "Modo de Icono"
+msgstr "Modo de Unión"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Begin Cap Mode"
-msgstr "Modo de Región"
+msgstr "Iniciar Modo Cap"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "End Cap Mode"
-msgstr "Modo de Ajuste:"
+msgstr "Modo Tapón"
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp scene/resources/style_box.cpp
msgid "Border"
@@ -21493,14 +21060,12 @@ msgstr ""
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp
#: scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Antialiased"
-msgstr "Inicializar"
+msgstr "Suavizado Espacial"
#: scene/2d/multimesh_instance_2d.cpp scene/3d/multimesh_instance.cpp
-#, fuzzy
msgid "Multimesh"
-msgstr "Multiplicar %s"
+msgstr "Multimesh"
#: scene/2d/navigation_2d.cpp scene/3d/baked_lightmap.cpp
#: scene/3d/navigation.cpp scene/animation/root_motion_view.cpp
@@ -21520,50 +21085,54 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
+msgid "Pathfinding"
+msgstr "Pathfinding"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
-msgstr "Distancia de la Ruta U"
+msgstr "Ruta Distancia Deseada"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Target Desired Distance"
-msgstr ""
+msgstr "Distancia Deseada del Objetivo"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr "Distancia Máxima de la Ruta"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Avoidance"
+msgstr "Evasión"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Avoidance Enabled"
+msgstr "Evasión Activada"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
-msgstr ""
+msgstr "Dist. de Vecinos"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Max Neighbors"
-msgstr ""
+msgstr "Máximo de Vecinos"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
msgid "Time Horizon"
-msgstr "Voltear Horizontalmente"
+msgstr "Horizonte del Tiempo"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
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 ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
-msgstr "El NavigationAgent2D sólo puede utilizarse bajo un nodo Node2D."
+msgstr ""
+"El NavigationAgent2D sólo puede utilizarse bajo un nodo padre hijo de Node2D."
#: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_obstacle.cpp
-#, fuzzy
msgid "Estimate Radius"
-msgstr "Cambiar Radio Externo de Torus"
+msgstr "Estimación del Radio"
#: scene/2d/navigation_obstacle_2d.cpp
msgid ""
@@ -21578,32 +21147,29 @@ msgid ""
"A NavigationPolygon resource must be set or created for this node to work. "
"Please set a property or draw a polygon."
msgstr ""
-"Se debe crear o asignar un recurso NavigationPolygon a este nodo para que "
-"funcione. Por favor, establece la propiedad o dibuja un polígono."
+"Un recurso NavigationPolygon debe ser establecido o creado para que este "
+"nodo funcione. Por favor, establece una propiedad o dibuja un polígono."
#: scene/2d/navigation_polygon.cpp
msgid "Navpoly"
-msgstr ""
+msgstr "Navpoly"
#: scene/2d/navigation_polygon.cpp scene/3d/navigation_mesh_instance.cpp
-#, fuzzy
msgid "Enter Cost"
-msgstr "Centro Inferior"
+msgstr "Introduce Costo"
#: scene/2d/navigation_polygon.cpp scene/3d/navigation_mesh_instance.cpp
-#, fuzzy
msgid "Travel Cost"
-msgstr "Viaje"
+msgstr "Costo del Viaje"
#: scene/2d/node_2d.cpp scene/2d/polygon_2d.cpp scene/3d/spatial.cpp
#: scene/main/canvas_layer.cpp
msgid "Rotation Degrees"
msgstr "Grados de Rotación"
-#: scene/2d/node_2d.cpp
-#, fuzzy
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
-msgstr "Constante Global"
+msgstr "Rotación Global"
#: scene/2d/node_2d.cpp
msgid "Global Rotation Degrees"
@@ -21614,41 +21180,37 @@ msgid "Global Scale"
msgstr "Escala Global"
#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Global Transform"
-msgstr "Mantener transformación global"
+msgstr "Transformación Global"
#: scene/2d/node_2d.cpp
-#, fuzzy
msgid "Z As Relative"
-msgstr "Ajuste Relativo"
+msgstr "Z Como Relativo"
#: scene/2d/parallax_background.cpp scene/gui/scroll_container.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Scroll"
-msgstr ""
+msgstr "Scroll"
#: scene/2d/parallax_background.cpp
msgid "Base Offset"
msgstr "Desplazamiento Base"
#: scene/2d/parallax_background.cpp
-#, fuzzy
msgid "Base Scale"
-msgstr "Usar Ajuste de Escalado"
+msgstr "Escala Base"
#: scene/2d/parallax_background.cpp
msgid "Limit Begin"
-msgstr ""
+msgstr "Inicio del Límite"
#: scene/2d/parallax_background.cpp
-#, fuzzy
msgid "Limit End"
-msgstr "Al Final"
+msgstr "Fin del Límite"
#: scene/2d/parallax_background.cpp
msgid "Ignore Camera Zoom"
-msgstr ""
+msgstr "Ignorar Zoom de la Cámara"
#: scene/2d/parallax_layer.cpp
msgid ""
@@ -21660,12 +21222,10 @@ msgstr ""
#: scene/2d/parallax_layer.cpp scene/2d/physics_body_2d.cpp
#: scene/3d/physics_body.cpp scene/3d/vehicle_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Motion"
-msgstr "Acción"
+msgstr "Movimiento"
#: scene/2d/parallax_layer.cpp
-#, fuzzy
msgid "Mirroring"
msgstr "Reflejar"
@@ -21712,9 +21272,8 @@ msgstr ""
"\"Particles Animation\" activado."
#: scene/2d/particles_2d.cpp
-#, fuzzy
msgid "Visibility Rect"
-msgstr "Modo de Prioridad"
+msgstr "Visibilidad Rect"
#: scene/2d/particles_2d.cpp scene/3d/particles.cpp
msgid "Process Material"
@@ -21722,9 +21281,8 @@ msgstr ""
#: scene/2d/path_2d.cpp scene/3d/path.cpp scene/resources/sky.cpp
#: scene/resources/texture.cpp
-#, fuzzy
msgid "Curve"
-msgstr "Partir Curva"
+msgstr "Curva"
#: scene/2d/path_2d.cpp
msgid "PathFollow2D only works when set as a child of a Path2D node."
@@ -21752,25 +21310,21 @@ msgid "Lookahead"
msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Layers"
-msgstr "Capa"
+msgstr "Capas"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Constant Linear Velocity"
-msgstr "Inicializar"
+msgstr "Velocidad Lineal Constante"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Constant Angular Velocity"
-msgstr "Inicializar"
+msgstr "Velocidad Angular Constante"
#: scene/2d/physics_body_2d.cpp scene/2d/tile_map.cpp scene/3d/physics_body.cpp
#: scene/resources/physics_material.cpp
-#, fuzzy
msgid "Friction"
-msgstr "Función"
+msgstr "Fricción"
#: scene/2d/physics_body_2d.cpp scene/2d/tile_map.cpp scene/3d/physics_body.cpp
#: scene/resources/physics_material.cpp
@@ -21783,9 +21337,8 @@ msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: scene/resources/world.cpp scene/resources/world_2d.cpp
-#, fuzzy
msgid "Default Gravity"
-msgstr "Vista Previa Por Defecto"
+msgstr "Gravedad por Defecto"
#: scene/2d/physics_body_2d.cpp
msgid ""
@@ -21806,38 +21359,33 @@ msgid "Inertia"
msgstr "Inercia"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Weight"
-msgstr "Luz"
+msgstr "Peso"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Gravity Scale"
msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Custom Integrator"
-msgstr "CustomNode"
+msgstr "Integrador Personalizado"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Continuous CD"
-msgstr "Continuo"
+msgstr "CD Continuo"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Contacts Reported"
msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Contact Monitor"
-msgstr "Seleccionar Color"
+msgstr "Monitor de Contacto"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Sleeping"
-msgstr "Ajuste Inteligente"
+msgstr "Resposo"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Can Sleep"
@@ -21860,18 +21408,16 @@ msgid "Torque"
msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Safe Margin"
-msgstr "Asignar Margen"
+msgstr "Margen de Seguridad"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Sync To Physics"
msgstr "Sincronización Con La Física"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Moving Platform"
-msgstr "Moviendo salida"
+msgstr "Plataforma Móvil"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Apply Velocity On Leave"
@@ -21881,24 +21427,21 @@ msgstr ""
#: scene/3d/physics_body.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
#: scene/resources/line_shape_2d.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Normal"
-msgstr "Formato"
+msgstr "Normal"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Remainder"
msgstr "Recordatorio"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Local Shape"
-msgstr "Idioma"
+msgstr "Forma Local"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collider"
-msgstr "Modo de Colisión"
+msgstr "Colisionador"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
@@ -21907,26 +21450,22 @@ msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collider RID"
-msgstr "RID inválido"
+msgstr "Colisionador RID"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collider Shape"
-msgstr "Modo de Colisión"
+msgstr "Forma de Colisión"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Collider Shape Index"
-msgstr "Modo de Colisión"
+msgstr "Ãndice de Formas de Colisión"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collider Velocity"
-msgstr "Vista de Órbita Derecha"
+msgstr "Velocidad del Colisionador"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Collider Metadata"
@@ -21937,28 +21476,24 @@ msgid "Invert"
msgstr ""
#: scene/2d/polygon_2d.cpp
-#, fuzzy
msgid "Vertex Colors"
-msgstr "Vértice"
+msgstr "Color de los Vértices"
#: scene/2d/polygon_2d.cpp
-#, fuzzy
msgid "Internal Vertex Count"
-msgstr "Crear Vértice Interno"
+msgstr "Conteo de Vértices Internos"
#: scene/2d/position_2d.cpp
-#, fuzzy
msgid "Gizmo Extents"
-msgstr "Gizmos"
+msgstr "Extensión de Gizmos"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Exclude Parent"
msgstr ""
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
-#, fuzzy
msgid "Cast To"
-msgstr "Crear Nodo Shader"
+msgstr "Lanzar A"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Collide With"
@@ -21977,24 +21512,20 @@ msgid "Path property must point to a valid Node2D node to work."
msgstr "La propiedad Path debe apuntar a un nodo Node2D válido para funcionar."
#: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp
-#, fuzzy
msgid "Remote Path"
-msgstr "Eliminar Punto"
+msgstr "Ruta Remota"
#: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp
-#, fuzzy
msgid "Use Global Coordinates"
-msgstr "Siguiente Coordenada"
+msgstr "Utilizar Coordenadas Globales"
#: scene/2d/skeleton_2d.cpp scene/3d/skeleton.cpp
-#, fuzzy
msgid "Rest"
-msgstr "Reiniciar"
+msgstr "Reposo"
#: scene/2d/skeleton_2d.cpp
-#, fuzzy
msgid "Default Length"
-msgstr "Theme Predeterminado"
+msgstr "Longitud por Defecto"
#: scene/2d/skeleton_2d.cpp
msgid "This Bone2D chain should end at a Skeleton2D node."
@@ -22021,14 +21552,12 @@ msgid "Vframes"
msgstr ""
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
-#, fuzzy
msgid "Frame Coords"
-msgstr "Fotograma %"
+msgstr "Coordenadas del Marco"
#: scene/2d/sprite.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Filter Clip"
-msgstr "Filtrar scripts"
+msgstr "Filtrar Clips"
#: scene/2d/tile_map.cpp
msgid ""
@@ -22041,44 +21570,36 @@ msgstr ""
"RigidBody2D, KinematicBody2D, etc. para que puedan tener forma."
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Tile Set"
-msgstr "TileSet"
+msgstr "Tile Set"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Quadrant Size"
-msgstr "Cambiar Tamaño de Cámara"
+msgstr "Tamaño del Cuadrante"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Custom Transform"
-msgstr "Transformar"
+msgstr "Transformación Personalizada"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Half Offset"
-msgstr "Inicializar"
+msgstr "Medio Desplazamiento"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Tile Origin"
-msgstr "Ver Origen"
+msgstr "Origen de los Tiles"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Y Sort"
-msgstr "Ordenar"
+msgstr "Ordenar Y"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Show Collision"
-msgstr "Colisión"
+msgstr "Mostrar Colisión"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Compatibility Mode"
-msgstr "Modo de Prioridad"
+msgstr "Modo de Compatibilidad"
#: scene/2d/tile_map.cpp
msgid "Centered Textures"
@@ -22089,32 +21610,28 @@ msgid "Cell Clip UV"
msgstr ""
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Use Parent"
-msgstr "Modo de Colisión"
+msgstr "Usar Padres"
#: scene/2d/tile_map.cpp
msgid "Use Kinematic"
msgstr ""
#: scene/2d/touch_screen_button.cpp
-#, fuzzy
msgid "Shape Centered"
-msgstr "Ajustar al Centro del Nodo"
+msgstr "Forma Centrada"
#: scene/2d/touch_screen_button.cpp
-#, fuzzy
msgid "Shape Visible"
-msgstr "Act./Desact. Visible"
+msgstr "Forma Visible"
#: scene/2d/touch_screen_button.cpp
msgid "Passby Press"
msgstr ""
#: scene/2d/touch_screen_button.cpp
-#, fuzzy
msgid "Visibility Mode"
-msgstr "Modo de Prioridad"
+msgstr "Modo de Visibilidad"
#: scene/2d/visibility_notifier_2d.cpp
msgid ""
@@ -22125,28 +21642,24 @@ msgstr ""
"editada directamente como padre."
#: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp
-#, fuzzy
msgid "Pause Animations"
-msgstr "Pegar Animación"
+msgstr "Pausar Animaciones"
#: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp
msgid "Freeze Bodies"
msgstr ""
#: scene/2d/visibility_notifier_2d.cpp
-#, fuzzy
msgid "Pause Particles"
-msgstr "Partículas"
+msgstr "Pausar Partículas"
#: scene/2d/visibility_notifier_2d.cpp
-#, fuzzy
msgid "Pause Animated Sprites"
-msgstr "Pegar Animación"
+msgstr "Pausar Sprites Animados"
#: scene/2d/visibility_notifier_2d.cpp
-#, fuzzy
msgid "Process Parent"
-msgstr "Activar Prioridad"
+msgstr "Procesamiento de los Padres"
#: scene/2d/visibility_notifier_2d.cpp
msgid "Physics Process Parent"
@@ -22157,9 +21670,8 @@ msgid "Reverb Bus"
msgstr ""
#: scene/3d/area.cpp
-#, fuzzy
msgid "Uniformity"
-msgstr "Establecer Nombre de Uniform"
+msgstr "Uniformidad"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent."
@@ -22186,9 +21698,8 @@ msgstr ""
"un controlador real."
#: scene/3d/arvr_nodes.cpp
-#, fuzzy
msgid "Anchor ID"
-msgstr "Sólo anclado"
+msgstr "ID de Ancla"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRAnchor must have an ARVROrigin node as its parent."
@@ -22211,9 +21722,8 @@ msgid "World Scale"
msgstr "Escala del Mundo"
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Attenuation Model"
-msgstr "Nodo de Animación"
+msgstr "Modelo de Atenuación"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Unit dB"
@@ -22232,18 +21742,16 @@ msgid "Out Of Range Mode"
msgstr ""
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Emission Angle"
-msgstr "Colores de Emisión"
+msgstr "Ãngulo de Emisión"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Degrees"
msgstr "Grados"
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Filter Attenuation dB"
-msgstr "Animación"
+msgstr "Filtro de Atenuación dB"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Attenuation Filter"
@@ -22257,19 +21765,16 @@ msgstr ""
#: scene/3d/audio_stream_player_3d.cpp
#: servers/audio/effects/audio_effect_filter.cpp
-#, fuzzy
msgid "dB"
-msgstr "B"
+msgstr "dB"
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Doppler"
-msgstr "Activar Doppler"
+msgstr "Doppler"
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Tracking"
-msgstr "Empaquetando"
+msgstr "Seguimiento"
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/reflection_probe.cpp
@@ -22303,9 +21808,8 @@ msgstr "Hecho"
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/reflection_probe.cpp scene/resources/box_shape.cpp
#: scene/resources/rectangle_shape_2d.cpp
-#, fuzzy
msgid "Extents"
-msgstr "Gizmos"
+msgstr "Extensiones"
#: scene/3d/baked_lightmap.cpp
msgid "Tweaks"
@@ -22328,66 +21832,56 @@ msgid "Use HDR"
msgstr ""
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Use Color"
-msgstr "Colores"
+msgstr "Usar Color"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Default Texels Per Unit"
-msgstr "Theme Predeterminado"
+msgstr "Texeles Por Unidad Predeterminados"
#: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Atlas"
-msgstr "Nuevo Atlas"
+msgstr "Atlas"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generate"
-msgstr "General"
+msgstr "Generar"
#: scene/3d/baked_lightmap.cpp
msgid "Max Size"
msgstr "Tamaño Máximo"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Custom Sky"
-msgstr "CustomNode"
+msgstr "Cielo Personalizado"
#: scene/3d/baked_lightmap.cpp
msgid "Custom Sky Rotation Degrees"
msgstr "Grados de Rotación del Cielo Personalizados"
#: scene/3d/baked_lightmap.cpp scene/3d/ray_cast.cpp
-#, fuzzy
msgid "Custom Color"
-msgstr "CustomNode"
+msgstr "Color Personalizado"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Custom Energy"
-msgstr "Mover Efecto de Bus"
+msgstr "Energía Personalizada"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Min Light"
-msgstr "Indentar a la Derecha"
+msgstr "Luz Mínima"
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
-#, fuzzy
msgid "Propagation"
-msgstr "Navegación"
+msgstr "Propagación"
#: scene/3d/baked_lightmap.cpp
msgid "Image Path"
msgstr ""
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Light Data"
-msgstr "Con Datos"
+msgstr "Datos de Iluminación"
#: scene/3d/bone_attachment.cpp scene/3d/physics_body.cpp
msgid "Bone Name"
@@ -22402,14 +21896,12 @@ msgid "Cull Mask"
msgstr ""
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Doppler Tracking"
-msgstr "Pista de Propiedades"
+msgstr "Seguimiento de Doppler"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Projection"
-msgstr "Proyecto"
+msgstr "Proyección"
#: scene/3d/camera.cpp
msgid "FOV"
@@ -22420,9 +21912,8 @@ msgid "Frustum Offset"
msgstr "Offset de Frustum"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Near"
-msgstr "Más Cercano"
+msgstr "Cercano"
#: scene/3d/camera.cpp
msgid "Far"
@@ -22433,23 +21924,20 @@ msgstr ""
#: scene/resources/shape.cpp scene/resources/style_box.cpp
#: scene/resources/texture.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
-#, fuzzy
msgid "Margin"
-msgstr "Asignar Margen"
+msgstr "Margen"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Clip To"
-msgstr "Clip Arriba"
+msgstr "Recortar A"
#: scene/3d/collision_object.cpp scene/3d/soft_body.cpp
msgid "Ray Pickable"
msgstr ""
#: scene/3d/collision_object.cpp
-#, fuzzy
msgid "Capture On Drag"
-msgstr "Captura"
+msgstr "Captura Al Arrastrar"
#: scene/3d/collision_object.cpp
msgid ""
@@ -22521,53 +22009,44 @@ msgstr ""
"Billboard esté ajustado a \"Particle Billboard\"."
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Box Extents"
-msgstr "Gizmos"
+msgstr "Extensión de Cajas"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Ring Radius"
-msgstr "Máscara de Emisión"
+msgstr "Radio del Anillo"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Ring Inner Radius"
-msgstr "Cambiar Radio Interno de Torus"
+msgstr "Radio Interior del Anillo"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Ring Height"
-msgstr "Rotar a la Derecha"
+msgstr "Altura del Anillo"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Ring Axis"
-msgstr "Advertencias"
+msgstr "Eje del Anillo"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Rotate Y"
-msgstr "Rotar"
+msgstr "Rotar Y"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Disable Z"
-msgstr "Desactivar Elemento"
+msgstr "Desactivar Z"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
msgid "Flatness"
msgstr ""
#: scene/3d/cull_instance.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Portals"
-msgstr "Voltear Portales"
+msgstr "Portales"
#: scene/3d/cull_instance.cpp
-#, fuzzy
msgid "Portal Mode"
-msgstr "Modo de Prioridad"
+msgstr "Modo Portal"
#: scene/3d/cull_instance.cpp
msgid "Include In Bound"
@@ -22578,9 +22057,8 @@ msgid "Allow Merging"
msgstr ""
#: scene/3d/cull_instance.cpp
-#, fuzzy
msgid "Autoplace Priority"
-msgstr "Activar Prioridad"
+msgstr "Prioridad de Autoemplazamiento"
#: scene/3d/gi_probe.cpp
msgid "Plotting Meshes"
@@ -22613,9 +22091,8 @@ msgid "Subdiv"
msgstr ""
#: scene/3d/gi_probe.cpp
-#, fuzzy
msgid "Dynamic Range"
-msgstr "Librería Dinámica"
+msgstr "Rango Dinámico"
#: scene/3d/gi_probe.cpp scene/3d/light.cpp
msgid "Normal Bias"
@@ -22623,18 +22100,16 @@ msgstr ""
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
#: scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Pixel Size"
-msgstr "Ajuste de Píxeles"
+msgstr "Tamaño de Píxeles"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Billboard"
msgstr ""
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
-#, fuzzy
msgid "Shaded"
-msgstr "Shader"
+msgstr "Sombreado"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Double Sided"
@@ -22645,9 +22120,8 @@ msgid "No Depth Test"
msgstr ""
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Fixed Size"
-msgstr "Vista Frontal"
+msgstr "Tamaño Fijo"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Alpha Cut"
@@ -22658,119 +22132,98 @@ msgid "Alpha Scissor Threshold"
msgstr ""
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Render Priority"
-msgstr "Activar Prioridad"
+msgstr "Prioridad de Renderización"
#: scene/3d/label_3d.cpp
-#, fuzzy
msgid "Outline Render Priority"
-msgstr "Activar Prioridad"
+msgstr "Prioridad de Renderización del Contorno"
#: scene/3d/label_3d.cpp
-#, fuzzy
msgid "Outline Modulate"
-msgstr "Forzar Modulación en Blanco"
+msgstr "Modular Contorno"
#: scene/3d/label_3d.cpp scene/resources/default_theme/default_theme.cpp
#: scene/resources/dynamic_font.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Font"
-msgstr "Fuentes"
+msgstr "Fuente"
#: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Horizontal Alignment"
-msgstr "Horizontal Activado"
+msgstr "Alineación Horizontal"
#: scene/3d/label_3d.cpp
-#, fuzzy
msgid "Vertical Alignment"
-msgstr "Filtrar señales"
+msgstr "Alineación Vertical"
#: scene/3d/label_3d.cpp scene/gui/dialogs.cpp scene/gui/label.cpp
-#, fuzzy
msgid "Autowrap"
-msgstr "AutoLoad"
+msgstr "Envoltura Automática"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Indirect Energy"
-msgstr "Colores de Emisión"
+msgstr "Energía Indirecta"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Negative"
-msgstr "GDNative"
+msgstr "Negativo"
#: scene/3d/light.cpp scene/resources/material.cpp
#: scene/resources/visual_shader.cpp
-#, fuzzy
msgid "Specular"
-msgstr "Modo de Regla"
+msgstr "Especular"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Bake Mode"
-msgstr "Modo de Bitmask"
+msgstr "Modo de Bakeo"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Contact"
-msgstr "Seleccionar Color"
+msgstr "Contacto"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Reverse Cull Face"
-msgstr "Restablecer Volumen de Bus"
+msgstr "Eliminar Caras Invertidas"
#: scene/3d/light.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Directional Shadow"
-msgstr "Direcciones"
+msgstr "Sombra Direccional"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Split 1"
-msgstr "Dividir"
+msgstr "Dividir 1"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Split 2"
-msgstr "Dividir"
+msgstr "Dividir 2"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Split 3"
-msgstr "Dividir"
+msgstr "Dividir 3"
#: scene/3d/light.cpp
msgid "Blend Splits"
msgstr "Mezclar Divisiones"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Bias Split Scale"
-msgstr "Usar Ajuste de Escalado"
+msgstr "Escala de División del Sesgo"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Depth Range"
-msgstr "Profundidad"
+msgstr "Rango de Profundidad"
#: scene/3d/light.cpp
msgid "Omni"
msgstr ""
#: scene/3d/light.cpp
-#, fuzzy
msgid "Shadow Mode"
-msgstr "Shader"
+msgstr "Modo de Sombreado"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Shadow Detail"
-msgstr "Mostrar Por Defecto"
+msgstr "Detalle de la Sombra"
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
@@ -22782,9 +22235,8 @@ msgid "Spot"
msgstr ""
#: scene/3d/light.cpp
-#, fuzzy
msgid "Angle Attenuation"
-msgstr "Animación"
+msgstr "Atenuación del Ãngulo"
#: scene/3d/mesh_instance.cpp
msgid "Software Skinning"
@@ -22802,43 +22254,38 @@ msgid ""
msgstr ""
#: scene/3d/navigation.cpp scene/resources/curve.cpp
-#, fuzzy
msgid "Up Vector"
-msgstr "Vector"
+msgstr "Vector Superior"
#: scene/3d/navigation.cpp
-#, fuzzy
msgid "Cell Height"
-msgstr "Prueba"
+msgstr "Altura de la Celda"
#: scene/3d/navigation_agent.cpp
msgid "Agent Height Offset"
msgstr ""
#: scene/3d/navigation_agent.cpp
-#, fuzzy
msgid "Ignore Y"
-msgstr "[Ignorar]"
+msgstr "Ignorar Y"
#: scene/3d/navigation_agent.cpp
-#, fuzzy
msgid ""
"The NavigationAgent can be used only under a Spatial inheriting parent node."
-msgstr "El NavigationAgent sólo puede utilizarse bajo un nodo spatial."
+msgstr ""
+"El NavigationAgent solo puede utilizarse en un nodo padre de tipo Spatial."
#: scene/3d/navigation_mesh_instance.cpp scene/resources/mesh_library.cpp
-#, fuzzy
msgid "NavMesh"
-msgstr "Calcular NavMesh"
+msgstr "NavMesh"
#: scene/3d/navigation_obstacle.cpp
-#, fuzzy
msgid ""
"The NavigationObstacle only serves to provide collision avoidance to a "
"Spatial inheriting parent object."
msgstr ""
-"El NavigationObstacle sólo sirve para evitar la colisión de un objeto "
-"spatial."
+"El NavigationObstacle solo sirve para evitar colisiones en un objeto padre "
+"de tipo Spatial."
#: scene/3d/occluder.cpp
msgid "No shape is set."
@@ -22889,9 +22336,8 @@ msgstr ""
"Billboard esté ajustado a \"Particle Billboard\"."
#: scene/3d/particles.cpp
-#, fuzzy
msgid "Visibility AABB"
-msgstr "Cambiar Visibilidad"
+msgstr "Visibilidad AABB"
#: scene/3d/particles.cpp
msgid "Draw Passes"
@@ -22915,7 +22361,6 @@ msgstr ""
"el recurso Curve de su Path padre."
#: scene/3d/path.cpp
-#, fuzzy
msgid "Rotation Mode"
msgstr "Modo de Rotación"
@@ -22930,65 +22375,56 @@ msgstr ""
"En su lugar, cambia el tamaño en las formas de colisión de los hijos."
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Axis Lock"
-msgstr "Eje"
+msgstr "Bloquear Ejes"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear X"
-msgstr "Lineal"
+msgstr "Lineal X"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Y"
-msgstr "Lineal"
+msgstr "Lineal Y"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Z"
-msgstr "Lineal"
+msgstr "Lineal Z"
#: scene/3d/physics_body.cpp
msgid "Angular X"
-msgstr ""
+msgstr "Angular X"
#: scene/3d/physics_body.cpp
msgid "Angular Y"
-msgstr ""
+msgstr "Angular Y"
#: scene/3d/physics_body.cpp
msgid "Angular Z"
-msgstr ""
+msgstr "Angular Z"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion X"
-msgstr "Acción"
+msgstr "Movimiento X"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion Y"
-msgstr "Acción"
+msgstr "Movimiento Y"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion Z"
-msgstr "Acción"
+msgstr "Movimiento Z"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Joint Constraints"
-msgstr "Constantes"
+msgstr "Restringir Articulaciones"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Impulse Clamp"
msgstr ""
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Swing Span"
-msgstr "Guardar Escena"
+msgstr "Expansión de Swing"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Twist Span"
@@ -23000,147 +22436,124 @@ msgid "Relaxation"
msgstr "Relajación"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Enabled"
-msgstr "Filtrar señales"
+msgstr "Límite Angular Activado"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Upper"
-msgstr "Lineal"
+msgstr "Límite Angular Superior"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Lower"
-msgstr "Ortogonal Angular"
+msgstr "Límite Angular Inferior"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Bias"
-msgstr "Lineal"
+msgstr "Sesgo de Límite Angular"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Softness"
-msgstr "Animación"
+msgstr "Límite Angular de Suavizado"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Relaxation"
-msgstr "Animación"
+msgstr "Relajación del Límite Angular"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Upper"
-msgstr "Lineal"
+msgstr "Límite Lineal Superior"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Lower"
-msgstr "Lineal"
+msgstr "Límite Lineal Inferior"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Softness"
-msgstr "Lineal"
+msgstr "Límite Lineal de Suavizado"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Restitution"
-msgstr "Lineal"
+msgstr "Restitución del Límite Lineal"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Damping"
-msgstr "Lineal"
+msgstr "Amortiguación de Límite Lineal"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Restitution"
-msgstr "Animación"
+msgstr "Restitución del Límite Angular"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Damping"
-msgstr "Animación"
+msgstr "Amortiguación de Límite Angular"
#: scene/3d/physics_body.cpp
msgid "X"
-msgstr ""
+msgstr "X"
#: scene/3d/physics_body.cpp
msgid "Y"
-msgstr ""
+msgstr "Y"
#: scene/3d/physics_body.cpp
msgid "Z"
-msgstr ""
+msgstr "Z"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Enabled"
-msgstr "Lineal"
+msgstr "Límite Lineal Activado"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Spring Enabled"
-msgstr "Lineal"
+msgstr "Amortiguador Lineal Activado"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Spring Stiffness"
-msgstr "Lineal"
+msgstr "Rigidez Lineal del Amortiguador"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Spring Damping"
-msgstr "Lineal"
+msgstr "Atenuación Lineal del Amortiguador"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Equilibrium Point"
-msgstr "Lineal"
+msgstr "Punto de Equilibrio Lineal"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Restitution"
-msgstr "Descripción"
+msgstr "Restitución Lineal"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Damping"
-msgstr "Lineal"
+msgstr "Amortiguación Lineal"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Restitution"
-msgstr "Descripción"
+msgstr "Restitución Angular"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Damping"
-msgstr "Animación"
+msgstr "Amortiguación Angular"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "ERP"
-msgstr ""
+msgstr "ERP"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Spring Enabled"
-msgstr "Filtrar señales"
+msgstr "Amortiguación Angular Activada"
#: scene/3d/physics_body.cpp
msgid "Angular Spring Stiffness"
-msgstr ""
+msgstr "Rigidez del Amortiguador Angular"
#: scene/3d/physics_body.cpp
msgid "Angular Spring Damping"
-msgstr ""
+msgstr "Amortiguación Angular del Muelle"
#: scene/3d/physics_body.cpp
msgid "Angular Equilibrium Point"
-msgstr ""
+msgstr "Punto de Equilibrio Angular"
#: scene/3d/physics_body.cpp
msgid "Body Offset"
@@ -23171,9 +22584,8 @@ msgid "Solver"
msgstr ""
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Exclude Nodes"
-msgstr "Eliminar Nodos"
+msgstr "Excluir Nodos"
#: scene/3d/physics_joint.cpp
msgid "Params"
@@ -23184,32 +22596,28 @@ msgid "Angular Limit"
msgstr ""
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Upper"
-msgstr "Mayúsculas"
+msgstr "Superior"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Lower"
-msgstr "Minúsculas"
+msgstr "Inferior"
#: scene/3d/physics_joint.cpp
msgid "Motor"
-msgstr ""
+msgstr "Motor"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Target Velocity"
-msgstr "Vista de Órbita Derecha"
+msgstr "Velocidad del Objetivo"
#: scene/3d/physics_joint.cpp
msgid "Max Impulse"
msgstr "Impulso Máximo"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Limit"
-msgstr "Lineal"
+msgstr "Límite Lineal"
#: scene/3d/physics_joint.cpp
msgid "Upper Distance"
@@ -23220,57 +22628,48 @@ msgid "Lower Distance"
msgstr "Distancia Inferior"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Restitution"
-msgstr "Descripción"
+msgstr "Restitución"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Motion"
-msgstr "Inicializar"
+msgstr "Movimiento Lineal"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Ortho"
-msgstr "Ortogonal Trasera"
+msgstr "Ortogonal Lineal"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Upper Angle"
-msgstr "Mayúsculas"
+msgstr "Ãngulo Superior"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Lower Angle"
-msgstr "Minúsculas"
+msgstr "Ãngulo Inferior"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Angular Motion"
-msgstr "Animación"
+msgstr "Movimiento Angular"
#: scene/3d/physics_joint.cpp
msgid "Angular Ortho"
msgstr "Ortogonal Angular"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Limit X"
-msgstr "Lineal"
+msgstr "Límite Lineal X"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Motor X"
-msgstr "Inicializar"
+msgstr "Motor Lineal X"
#: scene/3d/physics_joint.cpp
msgid "Force Limit"
msgstr "Forzar Límite"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Spring X"
-msgstr "Lineal"
+msgstr "Amortiguación Lineal X"
#: scene/3d/physics_joint.cpp
msgid "Equilibrium Point"
@@ -23286,22 +22685,19 @@ msgstr ""
#: scene/3d/physics_joint.cpp
msgid "Angular Spring X"
-msgstr ""
+msgstr "Amortiguación Angular X"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Limit Y"
-msgstr "Lineal"
+msgstr "Límite Lineal Y"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Motor Y"
-msgstr "Inicializar"
+msgstr "Motor Lineal Y"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Spring Y"
-msgstr "Lineal"
+msgstr "Amortiguación Lineal Y"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit Y"
@@ -23313,22 +22709,19 @@ msgstr ""
#: scene/3d/physics_joint.cpp
msgid "Angular Spring Y"
-msgstr ""
+msgstr "Amortiguación Angular Y"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Limit Z"
-msgstr "Lineal"
+msgstr "Límite Lineal Z"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Motor Z"
-msgstr "Inicializar"
+msgstr "Motor Lineal Z"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Spring Z"
-msgstr "Lineal"
+msgstr "Amortiguación Lineal Z"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit Z"
@@ -23340,7 +22733,7 @@ msgstr ""
#: scene/3d/physics_joint.cpp
msgid "Angular Spring Z"
-msgstr ""
+msgstr "Amortiguación Angular Z"
#: scene/3d/portal.cpp
msgid "The RoomManager should not be a child or grandchild of a Portal."
@@ -23367,14 +22760,12 @@ msgid "Linked Room"
msgstr "Sala Vinculada"
#: scene/3d/portal.cpp
-#, fuzzy
msgid "Use Default Margin"
-msgstr "Por defecto"
+msgstr "Usar Margen por Defecto"
#: scene/3d/proximity_group.cpp
-#, fuzzy
msgid "Group Name"
-msgstr "Agrupado"
+msgstr "Nombre del Grupo"
#: scene/3d/proximity_group.cpp
msgid "Dispatch Mode"
@@ -23385,47 +22776,40 @@ msgid "Grid Radius"
msgstr "Radio de Cuadrícula"
#: scene/3d/ray_cast.cpp
-#, fuzzy
msgid "Debug Shape"
-msgstr "Depurador"
+msgstr "Depurar Shape"
#: scene/3d/ray_cast.cpp scene/resources/style_box.cpp
msgid "Thickness"
msgstr ""
#: scene/3d/reflection_probe.cpp scene/main/viewport.cpp
-#, fuzzy
msgid "Update Mode"
-msgstr "Modo de Rotación"
+msgstr "Modo de Actualización"
#: scene/3d/reflection_probe.cpp
msgid "Origin Offset"
msgstr "Desplazamiento de Origen"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Box Projection"
-msgstr "Proyecto"
+msgstr "Proyección de Cajas"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Enable Shadows"
-msgstr "Activar Ajuste"
+msgstr "Activar Sombras"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Ambient Color"
-msgstr "Seleccionar Color"
+msgstr "Color de Ambiente"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Ambient Energy"
-msgstr "Colores de Emisión"
+msgstr "Energía Ambiental"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Ambient Contrib"
-msgstr "Indentar a la Derecha"
+msgstr "Contribución Ambiental"
#: scene/3d/remote_transform.cpp
msgid ""
@@ -23469,9 +22853,8 @@ msgid "Bound"
msgstr ""
#: scene/3d/room_group.cpp
-#, fuzzy
msgid "Roomgroup Priority"
-msgstr "Prioridad"
+msgstr "Prioridad del Roomgroup"
#: scene/3d/room_group.cpp
msgid "The RoomManager should not be placed inside a RoomGroup."
@@ -23505,80 +22888,68 @@ msgstr ""
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp
#: servers/audio/effects/audio_effect_delay.cpp
-#, fuzzy
msgid "Active"
-msgstr "Acción"
+msgstr "Activo"
#: scene/3d/room_manager.cpp
msgid "Roomlist"
msgstr ""
#: scene/3d/room_manager.cpp servers/visual_server.cpp
-#, fuzzy
msgid "PVS"
-msgstr "FPS"
+msgstr "PVS"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "PVS Mode"
-msgstr "Modo desplazamiento lateral"
+msgstr "Modo PVS"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "PVS Filename"
-msgstr "Archivo ZIP"
+msgstr "Nombre del Archivo PVS"
#: scene/3d/room_manager.cpp servers/visual_server.cpp
msgid "Gameplay"
msgstr ""
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Gameplay Monitor"
-msgstr "Monitor"
+msgstr "Monitor de Juego"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Use Secondary PVS"
-msgstr "Usar Ajuste de Escalado"
+msgstr "Usar PVS Secundario"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Merge Meshes"
-msgstr "Malla"
+msgstr "Fusionar Mallas"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Show Margins"
-msgstr "Mostrar Origen"
+msgstr "Mostrar Márgenes"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Debug Sprawl"
-msgstr "Depurar"
+msgstr "Depurar Extensión"
#: scene/3d/room_manager.cpp
msgid "Overlap Warning Threshold"
msgstr ""
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Preview Camera"
-msgstr "Vista Previa"
+msgstr "Vista previa de la Cámara"
#: scene/3d/room_manager.cpp
msgid "Portal Depth Limit"
msgstr ""
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Default Portal Margin"
-msgstr "Asignar Margen"
+msgstr "Margen del Portal por Defecto"
#: scene/3d/room_manager.cpp
-#, fuzzy
msgid "Roaming Expansion Margin"
-msgstr "Expandir Todo"
+msgstr "Margen de Expansión del Roaming"
#: scene/3d/room_manager.cpp
msgid ""
@@ -23631,43 +23002,36 @@ msgstr ""
"Asegúrate de que todas las rooms contienen geometría o límites manuales."
#: scene/3d/skeleton.cpp scene/resources/skin.cpp
-#, fuzzy
msgid "Pose"
-msgstr "Copiar Pose"
+msgstr "Pose"
#: scene/3d/skeleton.cpp
-#, fuzzy
msgid "Bound Children"
-msgstr "Hijos Editables"
+msgstr "Hijos Vinculados"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Pinned Points"
-msgstr "Fijado %s"
+msgstr "Puntos de Anclaje"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Attachments"
-msgstr "Gizmos"
+msgstr "Adjuntos"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Point Index"
-msgstr "Obtener Ãndice"
+msgstr "Ãndice de Puntos"
#: scene/3d/soft_body.cpp
msgid "Spatial Attachment Path"
msgstr ""
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Physics Enabled"
-msgstr "Fotogramas de Física %"
+msgstr "Física Activada"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Parent Collision Ignore"
-msgstr "Crear Polígono de Colisión"
+msgstr "Ignorar Colisión de los Padres"
#: scene/3d/soft_body.cpp
msgid "Simulation Precision"
@@ -23720,31 +23084,32 @@ msgstr ""
"En su lugar, cambia el tamaño en las formas de colisión de los hijos."
#: scene/3d/spatial.cpp
+msgid "Global Translation"
+msgstr "Transformación Global"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
-msgstr ""
+msgstr "Matriz"
#: scene/3d/spatial.cpp
-#, fuzzy
msgid "Gizmo"
-msgstr "Gizmos"
+msgstr "Gizmo"
#: scene/3d/spatial_velocity_tracker.cpp
-#, fuzzy
msgid "Track Physics Step"
-msgstr "Fotogramas de Física %"
+msgstr "Paso de Física de Pistas"
#: scene/3d/spring_arm.cpp
msgid "Spring Length"
-msgstr ""
+msgstr "Cantidad de Amortiguación"
#: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp
msgid "Opacity"
msgstr ""
#: scene/3d/sprite_3d.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Transparent"
-msgstr "Transponer"
+msgstr "Transparente"
#: scene/3d/sprite_3d.cpp
msgid ""
@@ -23763,14 +23128,12 @@ msgstr ""
"Por favor, úselo como hijo de un VehicleBody."
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Per-Wheel Motion"
-msgstr "Botón Bajar la Rueda"
+msgstr "Movimiento por Rueda"
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Engine Force"
-msgstr "Documentación Online"
+msgstr "Fuerza del Motor"
#: scene/3d/vehicle_body.cpp
msgid "Brake"
@@ -23801,19 +23164,16 @@ msgid "Roll Influence"
msgstr ""
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Friction Slip"
-msgstr "Función"
+msgstr "Deslizamiento por Fricción"
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Suspension"
-msgstr "Expresión"
+msgstr "Suspensión"
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Max Force"
-msgstr "Error"
+msgstr "Fuerza Máxima"
#: scene/3d/visibility_notifier.cpp
msgid "AABB"
@@ -23840,14 +23200,12 @@ msgid "Extra Cull Margin"
msgstr "Margen de Sacrificio Extra"
#: scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Baked Light"
-msgstr "Calcular Lightmaps"
+msgstr "Bakear Luces"
#: scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Generate Lightmap"
-msgstr "Generando Lightmaps"
+msgstr "Generar Lightmap"
#: scene/3d/visual_instance.cpp
msgid "Lightmap Scale"
@@ -23903,9 +23261,8 @@ msgid "Animation not found: '%s'"
msgstr "No se encontró la animación: '%s'"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Mix Mode"
-msgstr "Nodo Mix"
+msgstr "Modo Mix"
#: scene/animation/animation_blend_tree.cpp
msgid "Fadein Time"
@@ -23932,24 +23289,20 @@ msgid "Random Delay"
msgstr "Retraso Aleatorio"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Add Amount"
-msgstr "Cantidad"
+msgstr "Añadir Cantidad"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Blend Amount"
-msgstr "Cantidad de Escala"
+msgstr "Cantidad de Mezcla"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Seek Position"
-msgstr "Establecer Posición de Entrada de Curva"
+msgstr "Buscar Posición"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Input Count"
-msgstr "Añadir Puerto de Entrada"
+msgstr "Conteo de Entradas"
#: scene/animation/animation_blend_tree.cpp
#: scene/animation/animation_node_state_machine.cpp
@@ -23957,56 +23310,48 @@ msgid "Xfade Time"
msgstr "Tiempo de Fundido Cruzado"
#: scene/animation/animation_node_state_machine.cpp
-#, fuzzy
msgid "Switch Mode"
-msgstr "Cambiar"
+msgstr "Modo de Conmutación"
#: scene/animation/animation_node_state_machine.cpp
-#, fuzzy
msgid "Auto Advance"
-msgstr "Establecer avance automático"
+msgstr "Auto Avance"
#: scene/animation/animation_node_state_machine.cpp
-#, fuzzy
msgid "Advance Condition"
-msgstr "Opciones Avanzadas"
+msgstr "Condición de Avance"
#: scene/animation/animation_player.cpp
msgid "Anim Apply Reset"
msgstr "Aplicar Reset de la Animación"
#: scene/animation/animation_player.cpp
-#, fuzzy
msgid "Current Animation"
-msgstr "Establecer Animación"
+msgstr "Animación Actual"
#: scene/animation/animation_player.cpp
-#, fuzzy
msgid "Assigned Animation"
-msgstr "Añadir Animación"
+msgstr "Animación Asignada"
#: scene/animation/animation_player.cpp
msgid "Reset On Save"
msgstr ""
#: scene/animation/animation_player.cpp
-#, fuzzy
msgid "Current Animation Length"
-msgstr "Cambiar Duración de la Animación"
+msgstr "Duración Actual de la Animación"
#: scene/animation/animation_player.cpp
-#, fuzzy
msgid "Current Animation Position"
-msgstr "Añadir Punto de Animación"
+msgstr "Posición Actual de la Animación"
#: scene/animation/animation_player.cpp
msgid "Playback Options"
msgstr "Opciones de Reproducción"
#: scene/animation/animation_player.cpp
-#, fuzzy
msgid "Default Blend Time"
-msgstr "Theme Predeterminado"
+msgstr "Tiempo de Mezcla por Defecto"
#: scene/animation/animation_player.cpp
msgid "Method Call Mode"
@@ -24047,67 +23392,56 @@ msgid "Tree Root"
msgstr "Raíz del Ãrbol"
#: scene/animation/animation_tree.cpp
-#, fuzzy
msgid "Anim Player"
-msgstr "Fijar AnimationPlayer"
+msgstr "Reproductor de Animación"
#: scene/animation/animation_tree.cpp
msgid "Root Motion"
msgstr ""
#: scene/animation/animation_tree.cpp
-#, fuzzy
msgid "Track"
-msgstr "Agregar Pista"
+msgstr "Pista"
#: scene/animation/animation_tree_player.cpp
msgid "This node has been deprecated. Use AnimationTree instead."
msgstr "Este nodo ha quedado obsoleto. Usa AnimationTree en su lugar."
#: scene/animation/animation_tree_player.cpp
-#, fuzzy
msgid "Playback"
msgstr "Reproducir"
#: scene/animation/animation_tree_player.cpp
-#, fuzzy
msgid "Master Player"
-msgstr "Pegar Parámetros"
+msgstr "Reproductor Principal"
#: scene/animation/animation_tree_player.cpp
-#, fuzzy
msgid "Base Path"
-msgstr "Ruta de Exportación"
+msgstr "Ruta Base"
#: scene/animation/root_motion_view.cpp
-#, fuzzy
msgid "Animation Path"
-msgstr "Animación"
+msgstr "Ruta de la Animación"
#: scene/animation/root_motion_view.cpp
-#, fuzzy
msgid "Zero Y"
-msgstr "Cero"
+msgstr "Cero Y"
#: scene/animation/skeleton_ik.cpp
-#, fuzzy
msgid "Root Bone"
-msgstr "Nombre del nodo raíz"
+msgstr "Hueso Raíz"
#: scene/animation/skeleton_ik.cpp
-#, fuzzy
msgid "Tip Bone"
-msgstr "Huesos"
+msgstr "Punta del Hueso"
#: scene/animation/skeleton_ik.cpp
-#, fuzzy
msgid "Interpolation"
-msgstr "Modo de Interpolación"
+msgstr "Interpolación"
#: scene/animation/skeleton_ik.cpp
-#, fuzzy
msgid "Override Tip Basis"
-msgstr "Anulaciones"
+msgstr "Anular Base de la Punta"
#: scene/animation/skeleton_ik.cpp
msgid "Use Magnet"
@@ -24118,54 +23452,46 @@ msgid "Magnet"
msgstr ""
#: scene/animation/skeleton_ik.cpp
-#, fuzzy
msgid "Target Node"
-msgstr "Reemparentar nodo"
+msgstr "Nodo Objetivo"
#: scene/animation/skeleton_ik.cpp
-#, fuzzy
msgid "Max Iterations"
-msgstr "Crear Función"
+msgstr "Iteraciones Máximas"
#: scene/animation/tween.cpp
msgid "Playback Process Mode"
msgstr ""
#: scene/animation/tween.cpp
-#, fuzzy
msgid "Playback Speed"
-msgstr "Reproducir Escena"
+msgstr "Velocidad de Reproducción"
#: scene/audio/audio_stream_player.cpp
-#, fuzzy
msgid "Mix Target"
-msgstr "Objetivo"
+msgstr "Objetivo de la Mezcla"
#: scene/gui/aspect_ratio_container.cpp scene/gui/range.cpp
#: servers/audio/effects/audio_effect_compressor.cpp
-#, fuzzy
msgid "Ratio"
-msgstr "Mantener Proporciones"
+msgstr "Proporción"
#: scene/gui/aspect_ratio_container.cpp scene/gui/texture_button.cpp
#: scene/gui/texture_rect.cpp
-#, fuzzy
msgid "Stretch Mode"
-msgstr "Modo de Selección"
+msgstr "Modo de Estiramiento"
#: scene/gui/aspect_ratio_container.cpp scene/gui/box_container.cpp
msgid "Alignment"
msgstr ""
#: scene/gui/base_button.cpp
-#, fuzzy
msgid "Shortcut In Tooltip"
-msgstr "Mostrar Origen"
+msgstr "Atajo en el Tooltip"
#: scene/gui/base_button.cpp
-#, fuzzy
msgid "Action Mode"
-msgstr "Modo de Icono"
+msgstr "Modo de Acción"
#: scene/gui/base_button.cpp
msgid "Enabled Focus Mode"
@@ -24176,38 +23502,33 @@ msgid "Keep Pressed Outside"
msgstr ""
#: scene/gui/base_button.cpp scene/gui/shortcut.cpp
-#, fuzzy
msgid "Shortcut"
-msgstr "Atajos"
+msgstr "Atajo"
#: scene/gui/base_button.cpp
-#, fuzzy
msgid "Group"
-msgstr "Grupos"
+msgstr "Grupo"
#: scene/gui/button.cpp scene/gui/label.cpp
-#, fuzzy
msgid "Clip Text"
-msgstr "Copiar Texto"
+msgstr "Texto del Clip"
#: scene/gui/button.cpp scene/gui/label.cpp scene/gui/line_edit.cpp
#: scene/gui/spin_box.cpp
msgid "Align"
-msgstr ""
+msgstr "Alinear"
#: scene/gui/button.cpp
msgid "Icon Align"
-msgstr ""
+msgstr "Alinear Icono"
#: scene/gui/button.cpp
-#, fuzzy
msgid "Expand Icon"
-msgstr "Expandir Todo"
+msgstr "Expandir Icono"
#: scene/gui/center_container.cpp
-#, fuzzy
msgid "Use Top Left"
-msgstr "Superior Izquierda"
+msgstr "Usar Superior Izquierda"
#: scene/gui/color_picker.cpp
msgid ""
@@ -24220,34 +23541,28 @@ msgstr ""
"Clic der: Borrar configuración predeterminada"
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Edit Alpha"
-msgstr "Editar Polígono"
+msgstr "Editar Alfa"
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "HSV Mode"
-msgstr "Modo de Selección"
+msgstr "Modo HSV"
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Raw Mode"
-msgstr "Modo desplazamiento lateral"
+msgstr "Modo Raw"
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Deferred Mode"
-msgstr "Diferido"
+msgstr "Modo Diferido"
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Presets Enabled"
-msgstr "Ajustes preestablecidos"
+msgstr "Preajustes Activados"
#: scene/gui/color_picker.cpp
-#, fuzzy
msgid "Presets Visible"
-msgstr "Act./Desact. Visible"
+msgstr "Preajustes Visibles"
#: scene/gui/color_picker.cpp
msgid "Pick a color from the editor window."
@@ -24277,9 +23592,8 @@ msgstr ""
"sencillo."
#: scene/gui/control.cpp
-#, fuzzy
msgid "Theme Overrides"
-msgstr "Anulaciones"
+msgstr "Anulación de Temas"
#: scene/gui/control.cpp
msgid ""
@@ -24291,14 +23605,12 @@ msgstr ""
"Filtro del Ratón en \"Stop\" o \"Pass\"."
#: scene/gui/control.cpp
-#, fuzzy
msgid "Anchor"
-msgstr "Sólo anclado"
+msgstr "Anclaje"
#: scene/gui/control.cpp
-#, fuzzy
msgid "Grow Direction"
-msgstr "Direcciones"
+msgstr "Dirección de Crecimiento"
#: scene/gui/control.cpp scene/resources/navigation_mesh.cpp
msgid "Min Size"
@@ -24309,40 +23621,36 @@ msgid "Pivot Offset"
msgstr "Pivote de Desplazamiento"
#: scene/gui/control.cpp
-#, fuzzy
msgid "Clip Content"
-msgstr "Constante de Clase"
+msgstr "Contenido del Clip"
#: scene/gui/control.cpp scene/resources/visual_shader_nodes.cpp
msgid "Hint"
msgstr ""
#: scene/gui/control.cpp
-#, fuzzy
msgid "Tooltip"
-msgstr "Herramientas"
+msgstr "Tooltip"
#: scene/gui/control.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Focus"
-msgstr "Foco en Ruta"
+msgstr "Foco"
#: scene/gui/control.cpp
msgid "Neighbour Left"
-msgstr ""
+msgstr "Vecino Izquierda"
#: scene/gui/control.cpp
msgid "Neighbour Top"
-msgstr ""
+msgstr "Vecino Superior"
#: scene/gui/control.cpp
msgid "Neighbour Right"
-msgstr ""
+msgstr "Vecino Derecha"
#: scene/gui/control.cpp
-#, fuzzy
msgid "Neighbour Bottom"
-msgstr "Centro Inferior"
+msgstr "Vecino Inferior"
#: scene/gui/control.cpp
msgid "Next"
@@ -24369,23 +23677,20 @@ msgid "Size Flags"
msgstr "Tamaño de los Indicadores"
#: scene/gui/control.cpp
-#, fuzzy
msgid "Stretch Ratio"
-msgstr "Modo de Selección"
+msgstr "Relación de Estiramiento"
#: scene/gui/control.cpp
-#, fuzzy
msgid "Theme Type Variation"
-msgstr "Propiedades del Theme"
+msgstr "Propiedades del Tema"
#: scene/gui/dialogs.cpp
msgid "Window Title"
msgstr ""
#: scene/gui/dialogs.cpp
-#, fuzzy
msgid "Dialog"
-msgstr "Diálogo XForm"
+msgstr "Diálogo"
#: scene/gui/dialogs.cpp
msgid "Hide On OK"
@@ -24400,18 +23705,16 @@ msgid "Please Confirm..."
msgstr "Por favor, Confirma..."
#: scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Mode Overrides Title"
-msgstr "Elemento de Anulación"
+msgstr "Sobreescritura"
#: scene/gui/file_dialog.cpp
msgid "Must use a valid extension."
msgstr "Debe tener una extensión válida."
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Right Disconnects"
-msgstr "Desconectar"
+msgstr "Desconexión Correcta"
#: scene/gui/graph_edit.cpp
msgid "Scroll Offset"
@@ -24422,24 +23725,20 @@ msgid "Snap Distance"
msgstr "Ajustar Distancia"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom Min"
-msgstr "Acercar Zoom"
+msgstr "Zoom Mínimo"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom Max"
-msgstr "Acercar Zoom"
+msgstr "Zoom Máximo"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom Step"
-msgstr "Alejar Zoom"
+msgstr "Paso Zoom"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Show Zoom Label"
-msgstr "Mostrar Huesos"
+msgstr "Mostrar Etiqueta Zoom"
#: scene/gui/graph_edit.cpp scene/gui/text_edit.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -24451,58 +23750,50 @@ msgid "Enable grid minimap."
msgstr "Activar minimapa de cuadrícula."
#: scene/gui/graph_node.cpp
-#, fuzzy
msgid "Show Close"
-msgstr "Mostrar Huesos"
+msgstr "Mostrar Cerrar"
#: scene/gui/graph_node.cpp scene/gui/option_button.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Selected"
-msgstr "Seleccionar"
+msgstr "Seleccionado"
#: scene/gui/graph_node.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Comment"
-msgstr "Confirmar"
+msgstr "Comentario"
#: scene/gui/graph_node.cpp
msgid "Overlay"
msgstr ""
#: scene/gui/grid_container.cpp scene/gui/item_list.cpp scene/gui/tree.cpp
-#, fuzzy
msgid "Columns"
-msgstr "Volumen"
+msgstr "Columnas"
#: scene/gui/item_list.cpp scene/gui/popup_menu.cpp scene/gui/text_edit.cpp
#: scene/gui/tree.cpp scene/main/viewport.cpp
-#, fuzzy
msgid "Timers"
-msgstr "Tiempo"
+msgstr "Temporizadores"
#: scene/gui/item_list.cpp scene/gui/popup_menu.cpp scene/gui/tree.cpp
msgid "Incremental Search Max Interval Msec"
msgstr ""
#: scene/gui/item_list.cpp scene/gui/tree.cpp
-#, fuzzy
msgid "Allow Reselect"
-msgstr "Aplicar Restablecer"
+msgstr "Permitir Volver A Seleccionar"
#: scene/gui/item_list.cpp scene/gui/tree.cpp
-#, fuzzy
msgid "Allow RMB Select"
-msgstr "Rellenar Selección"
+msgstr "Permitir Selección Con Botón Derecho Del Ratón"
#: scene/gui/item_list.cpp
msgid "Max Text Lines"
msgstr ""
#: scene/gui/item_list.cpp
-#, fuzzy
msgid "Auto Height"
-msgstr "Prueba"
+msgstr "Altura Automática"
#: scene/gui/item_list.cpp
msgid "Max Columns"
@@ -24521,23 +23812,20 @@ msgid "Icon Scale"
msgstr "Escala de Icono"
#: scene/gui/item_list.cpp
-#, fuzzy
msgid "Fixed Icon Size"
-msgstr "Vista Frontal"
+msgstr "Tamaño Fijo de Icono"
#: scene/gui/label.cpp
-#, fuzzy
msgid "V Align"
-msgstr "Asignar"
+msgstr "Alineamiento V"
#: scene/gui/label.cpp scene/gui/rich_text_label.cpp
msgid "Visible Characters"
msgstr "Caracteres Visibles"
#: scene/gui/label.cpp scene/gui/rich_text_label.cpp
-#, fuzzy
msgid "Percent Visible"
-msgstr "Act./Desact. Visible"
+msgstr "Porcentaje Visible"
#: scene/gui/label.cpp
msgid "Lines Skipped"
@@ -24564,34 +23852,28 @@ msgid "Expand To Text Length"
msgstr ""
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Context Menu Enabled"
-msgstr "Ayuda Contextual"
+msgstr "Menú Contextual Activado"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Virtual Keyboard Enabled"
-msgstr "Filtrar señales"
+msgstr "Teclado Virtual Activado"
#: scene/gui/line_edit.cpp
-#, fuzzy
msgid "Clear Button Enabled"
-msgstr "Filtrar señales"
+msgstr "Botón de Borrado Activado"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Shortcut Keys Enabled"
-msgstr "Atajos"
+msgstr "Atajos Activados"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Middle Mouse Paste Enabled"
-msgstr "Filtrar señales"
+msgstr "Pegar Con Botón Intermedio Ratón Activado"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Selecting Enabled"
-msgstr "Sólo selección"
+msgstr "Selección Activada"
#: scene/gui/line_edit.cpp scene/gui/rich_text_label.cpp
#: scene/gui/text_edit.cpp
@@ -24599,14 +23881,12 @@ msgid "Deselect On Focus Loss Enabled"
msgstr ""
#: scene/gui/line_edit.cpp
-#, fuzzy
msgid "Right Icon"
-msgstr "Botón Derecho"
+msgstr "Icono Derecho"
#: scene/gui/line_edit.cpp
-#, fuzzy
msgid "Placeholder"
-msgstr "Cargar Como Placeholder"
+msgstr "Marcador"
#: scene/gui/line_edit.cpp
msgid "Alpha"
@@ -24629,24 +23909,20 @@ msgid "Underline"
msgstr ""
#: scene/gui/menu_button.cpp
-#, fuzzy
msgid "Switch On Hover"
-msgstr "Cambiar"
+msgstr "Cambiar Al Pasar Por Encima"
#: scene/gui/nine_patch_rect.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Draw Center"
-msgstr "Centro"
+msgstr "Dibujar al Centro"
#: scene/gui/nine_patch_rect.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Region Rect"
-msgstr "Establecer Region Rect"
+msgstr "Región Rectángulo"
#: scene/gui/nine_patch_rect.cpp
-#, fuzzy
msgid "Patch Margin"
-msgstr "Asignar Margen"
+msgstr "Parche de Margen"
#: scene/gui/nine_patch_rect.cpp scene/resources/style_box.cpp
msgid "Axis Stretch"
@@ -24665,14 +23941,12 @@ msgstr ""
"como Stretch en su lugar."
#: scene/gui/popup.cpp
-#, fuzzy
msgid "Popup"
-msgstr "Rellenar"
+msgstr "Popup"
#: scene/gui/popup.cpp
-#, fuzzy
msgid "Exclusive"
-msgstr "Inclusivo"
+msgstr "Exclusivo"
#: scene/gui/popup.cpp
msgid ""
@@ -24685,28 +23959,24 @@ msgstr ""
"edición, pero se esconderán al iniciar."
#: scene/gui/popup_menu.cpp
-#, fuzzy
msgid "Hide On Item Selection"
-msgstr "Centrar Selección"
+msgstr "Ocultar Al Seleccionar Elemento"
#: scene/gui/popup_menu.cpp
-#, fuzzy
msgid "Hide On Checkable Item Selection"
-msgstr "Eliminar Selección de GridMap"
+msgstr "Ocultar Al Seleccionar Elemento Activable"
#: scene/gui/popup_menu.cpp
-#, fuzzy
msgid "Hide On State Item Selection"
-msgstr "Eliminar Selección"
+msgstr "Ocultar Al Seleccionar Elemento de Estado"
#: scene/gui/popup_menu.cpp
msgid "Submenu Popup Delay"
msgstr ""
#: scene/gui/popup_menu.cpp
-#, fuzzy
msgid "Allow Search"
-msgstr "Buscar"
+msgstr "Permitir Búsqueda"
#: scene/gui/progress_bar.cpp
msgid "Percent"
@@ -24717,28 +23987,24 @@ msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0."
msgstr "Si \"Exp Edit\" está activado, \"Min Value\" debe ser mayor que 0."
#: scene/gui/range.cpp scene/resources/curve.cpp
-#, fuzzy
msgid "Min Value"
-msgstr "Fijar Valor"
+msgstr "Valor Mínimo"
#: scene/gui/range.cpp scene/resources/curve.cpp
-#, fuzzy
msgid "Max Value"
-msgstr "Valor"
+msgstr "Valor Máximo"
#: scene/gui/range.cpp
msgid "Page"
msgstr "Página"
#: scene/gui/range.cpp
-#, fuzzy
msgid "Exp Edit"
-msgstr "Editar"
+msgstr "Editar Exp"
#: scene/gui/range.cpp
-#, fuzzy
msgid "Rounded"
-msgstr "Agrupado"
+msgstr "Redondeado"
#: scene/gui/range.cpp
msgid "Allow Greater"
@@ -24749,24 +24015,20 @@ msgid "Allow Lesser"
msgstr ""
#: scene/gui/reference_rect.cpp
-#, fuzzy
msgid "Border Color"
-msgstr "Cambiar Nombre del Elemento Color"
+msgstr "Color Del Borde"
#: scene/gui/reference_rect.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Border Width"
-msgstr "Píxeles del Borde"
+msgstr "Anchura Del Borde"
#: scene/gui/rich_text_effect.cpp
-#, fuzzy
msgid "Relative Index"
-msgstr "Obtener Ãndice"
+msgstr "Ãndice Relativo"
#: scene/gui/rich_text_effect.cpp
-#, fuzzy
msgid "Absolute Index"
-msgstr "Auto Sangría"
+msgstr "Ãndice Absoluto"
#: scene/gui/rich_text_effect.cpp
msgid "Elapsed Time"
@@ -24775,7 +24037,7 @@ msgstr "Tiempo Transcurrido"
#: scene/gui/rich_text_effect.cpp
#, fuzzy
msgid "Env"
-msgstr "Fin"
+msgstr "Env"
#: scene/gui/rich_text_effect.cpp
msgid "Character"
@@ -24794,9 +24056,8 @@ msgid "Tab Size"
msgstr "Tamaño de Tabulación"
#: scene/gui/rich_text_label.cpp
-#, fuzzy
msgid "Fit Content Height"
-msgstr "Pintar Peso de Huesos"
+msgstr "Ajustar Altura Del Contenido"
#: scene/gui/rich_text_label.cpp
msgid "Scroll Active"
@@ -24807,23 +24068,20 @@ msgid "Scroll Following"
msgstr ""
#: scene/gui/rich_text_label.cpp
-#, fuzzy
msgid "Selection Enabled"
-msgstr "Sólo selección"
+msgstr "Selección Activada"
#: scene/gui/rich_text_label.cpp scene/gui/text_edit.cpp
msgid "Override Selected Font Color"
msgstr "Sobrescribir Color de Fuente Seleccionada"
#: scene/gui/rich_text_label.cpp
-#, fuzzy
msgid "Custom Effects"
-msgstr "Mover Efecto de Bus"
+msgstr "Efectos Personalizados"
#: scene/gui/scroll_bar.cpp
-#, fuzzy
msgid "Custom Step"
-msgstr "CustomNode"
+msgstr "Paso Personalizado"
#: scene/gui/scroll_container.cpp
msgid ""
@@ -24836,18 +24094,16 @@ msgstr ""
"manualmente el tamaño mínimo personalizado."
#: scene/gui/scroll_container.cpp
-#, fuzzy
msgid "Follow Focus"
-msgstr "Llenar superficie"
+msgstr "Seguir Focus"
#: scene/gui/scroll_container.cpp
msgid "Horizontal Enabled"
msgstr "Horizontal Activado"
#: scene/gui/scroll_container.cpp
-#, fuzzy
msgid "Vertical Enabled"
-msgstr "Filtrar señales"
+msgstr "Vertical Activada"
#: scene/gui/scroll_container.cpp
msgid "Default Scroll Deadzone"
@@ -24858,9 +24114,8 @@ msgid "Scrollable"
msgstr ""
#: scene/gui/slider.cpp
-#, fuzzy
msgid "Tick Count"
-msgstr "Seleccionar Color"
+msgstr "Cantidad De Marcas"
#: scene/gui/slider.cpp
msgid "Ticks On Borders"
@@ -24879,14 +24134,12 @@ msgid "Split Offset"
msgstr "Desplazamiento de División"
#: scene/gui/split_container.cpp scene/gui/tree.cpp
-#, fuzzy
msgid "Collapsed"
-msgstr "Colapsar Todo"
+msgstr "Colapsado"
#: scene/gui/split_container.cpp
-#, fuzzy
msgid "Dragger Visibility"
-msgstr "Cambiar Visibilidad"
+msgstr "Visibilidad de los Arrastradores"
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
msgid "Tab Align"
@@ -24897,9 +24150,8 @@ msgid "Current Tab"
msgstr "Pestaña Actual"
#: scene/gui/tab_container.cpp
-#, fuzzy
msgid "Tabs Visible"
-msgstr "Act./Desact. Visible"
+msgstr "Pestañas Visibles"
#: scene/gui/tab_container.cpp
msgid "All Tabs In Front"
@@ -24926,28 +24178,28 @@ msgid "Readonly"
msgstr ""
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Bookmark Gutter"
-msgstr "Marcadores"
+msgstr "Canalón de Marcadores"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Breakpoint Gutter"
-msgstr "Saltar Breakpoints"
+msgstr "Canalón de Puntos de Ruptura"
#: scene/gui/text_edit.cpp
msgid "Fold Gutter"
-msgstr "Plegar Gutter"
+msgstr "Canalón Plegable"
+
+#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr "Selección de Arrastrar y Soltar Activada"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Hiding Enabled"
-msgstr "Activar"
+msgstr "Ocultación Activada"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Wrap Enabled"
-msgstr "Activar"
+msgstr "Ajuste Activado"
#: scene/gui/text_edit.cpp
msgid "Scroll Vertical"
@@ -24962,9 +24214,8 @@ msgid "Draw"
msgstr "Dibujar"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Block Mode"
-msgstr "Desbloquear Nodo"
+msgstr "Modo Bloque"
#: scene/gui/text_edit.cpp
msgid "Moving By Right Click"
@@ -24983,34 +24234,29 @@ msgid "Hover"
msgstr ""
#: scene/gui/texture_button.cpp
-#, fuzzy
msgid "Focused"
-msgstr "Foco en Ruta"
+msgstr "Enfocado"
#: scene/gui/texture_button.cpp
-#, fuzzy
msgid "Click Mask"
-msgstr "Modo de Colisión"
+msgstr "Máscara de Clic"
#: scene/gui/texture_button.cpp scene/gui/texture_rect.cpp
#: scene/gui/video_player.cpp
-#, fuzzy
msgid "Expand"
-msgstr "Expandir Todo"
+msgstr "Expandir"
#: scene/gui/texture_progress.cpp
msgid "Under"
msgstr ""
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Over"
-msgstr "Sobreescribir"
+msgstr "Sobre"
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Progress"
-msgstr "Propiedades del Theme"
+msgstr "Progreso"
#: scene/gui/texture_progress.cpp
msgid "Progress Offset"
@@ -25029,43 +24275,36 @@ msgid "Radial Fill"
msgstr ""
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Initial Angle"
-msgstr "Inicializar"
+msgstr "Ãngulo Inicial"
#: scene/gui/texture_progress.cpp
msgid "Fill Degrees"
msgstr "Completar Grados"
#: scene/gui/texture_progress.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Center Offset"
-msgstr "Centro Izquierda"
+msgstr "Desplazamiento Central"
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Nine Patch Stretch"
-msgstr "Modo de Interpolación"
+msgstr "Estiramiento de Nine Patch"
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Stretch Margin Left"
-msgstr "Asignar Margen"
+msgstr "Estiramiento de Margen Izquierdo"
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Stretch Margin Top"
-msgstr "Asignar Margen"
+msgstr "Estiramiento de Margen Superior"
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Stretch Margin Right"
-msgstr "Asignar Margen"
+msgstr "Estiramiento de Margen Derecho"
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Stretch Margin Bottom"
-msgstr "Modo de Selección"
+msgstr "Estiramiento de Margen Inferior"
#: scene/gui/tree.cpp
msgid "Custom Minimum Height"
@@ -25076,14 +24315,12 @@ msgid "(Other)"
msgstr "(Otros)"
#: scene/gui/tree.cpp
-#, fuzzy
msgid "Column Titles Visible"
-msgstr "Act./Desact. Visible"
+msgstr "Títulos de Columnas Visibles"
#: scene/gui/tree.cpp
-#, fuzzy
msgid "Hide Folding"
-msgstr "Botón Desactivado"
+msgstr "Plegado de Pieles"
#: scene/gui/tree.cpp
msgid "Hide Root"
@@ -25094,43 +24331,36 @@ msgid "Drop Mode Flags"
msgstr ""
#: scene/gui/video_player.cpp
-#, fuzzy
msgid "Audio Track"
-msgstr "Agregar Pista"
+msgstr "Pista de Audio"
#: scene/gui/video_player.cpp scene/main/scene_tree.cpp scene/main/timer.cpp
msgid "Paused"
-msgstr ""
+msgstr "Pausado"
#: scene/gui/video_player.cpp
-#, fuzzy
msgid "Buffering Msec"
-msgstr "Vista Trasera"
+msgstr "Buffering Msec"
#: scene/gui/video_player.cpp
-#, fuzzy
msgid "Stream Position"
-msgstr "Establecer Posición de Entrada de Curva"
+msgstr "Posición del Stream"
#: scene/gui/viewport_container.cpp
-#, fuzzy
msgid "Stretch Shrink"
-msgstr "Buscar"
+msgstr "Encogimiento por Estiramiento"
#: scene/main/canvas_layer.cpp
-#, fuzzy
msgid "Follow Viewport"
-msgstr "Mostrar Viewport"
+msgstr "Seguir el Viewport"
#: scene/main/http_request.cpp
-#, fuzzy
msgid "Download File"
-msgstr "Descargar"
+msgstr "Descargar Archivo"
#: scene/main/http_request.cpp
-#, fuzzy
msgid "Download Chunk Size"
-msgstr "Descargando"
+msgstr "Descargar Tamaño del Fragmento"
#: scene/main/http_request.cpp
msgid "Body Size Limit"
@@ -25151,89 +24381,76 @@ msgid ""
msgstr ""
#: scene/main/node.cpp
-#, fuzzy
msgid "Name Num Separator"
-msgstr "Separador con nombre"
+msgstr "Separador Numérico del Nombre"
#: scene/main/node.cpp
msgid "Name Casing"
msgstr ""
#: scene/main/node.cpp
-#, fuzzy
msgid "Editor Description"
-msgstr "Descripción"
+msgstr "Descripción del Editor"
#: scene/main/node.cpp
-#, fuzzy
msgid "Pause Mode"
-msgstr "Modo desplazamiento lateral"
+msgstr "Modo Pausa"
#: scene/main/node.cpp
-#, fuzzy
msgid "Physics Interpolation Mode"
-msgstr "Modo de Interpolación"
+msgstr "Modo de Interpolación Física"
#: scene/main/node.cpp
-#, fuzzy
msgid "Display Folded"
-msgstr "Mostrar Sin Sombreado"
+msgstr "Vista Plegada"
#: scene/main/node.cpp
-#, fuzzy
msgid "Filename"
-msgstr "Renombrar"
+msgstr "Nombre del Archivo"
#: scene/main/node.cpp
msgid "Owner"
msgstr "Propietario"
#: scene/main/node.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Multiplayer"
-msgstr "Multiplicar %s"
+msgstr "Multijugador"
#: scene/main/node.cpp
msgid "Custom Multiplayer"
msgstr "Multijugador Personalizado"
#: scene/main/node.cpp
-#, fuzzy
msgid "Process Priority"
-msgstr "Activar Prioridad"
+msgstr "Prioridad del Proceso"
#: scene/main/scene_tree.cpp scene/main/timer.cpp
-#, fuzzy
msgid "Time Left"
-msgstr "Superior Izquierda"
+msgstr "Tiempo Restante"
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Debug Collisions Hint"
-msgstr "Modo de Colisión"
+msgstr "Sugerencia de Depuración de Colisiones"
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Debug Navigation Hint"
-msgstr "Modo de Navegación"
+msgstr "Sugerencia de Depuración de Navegación"
#: scene/main/scene_tree.cpp
msgid "Use Font Oversampling"
msgstr ""
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Edited Scene Root"
-msgstr "Nueva Raíz de Escena"
+msgstr "Escena Raíz Editada"
#: scene/main/scene_tree.cpp
msgid "Root"
msgstr ""
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Multiplayer Poll"
-msgstr "Multiplicar %s"
+msgstr "Encuesta Multijugador"
#: scene/main/scene_tree.cpp scene/resources/mesh_library.cpp
#: scene/resources/shape_2d.cpp
@@ -25245,32 +24462,28 @@ msgid "Shape Color"
msgstr ""
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Contact Color"
-msgstr "Seleccionar Color"
+msgstr "Color de Contacto"
#: scene/main/scene_tree.cpp
msgid "Geometry Color"
msgstr ""
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Disabled Geometry Color"
-msgstr "Desactivar Elemento"
+msgstr "Color de la Geometría Desactivada"
#: scene/main/scene_tree.cpp
msgid "Max Contacts Displayed"
msgstr ""
#: scene/main/scene_tree.cpp scene/resources/shape_2d.cpp
-#, fuzzy
msgid "Draw 2D Outlines"
-msgstr "Crear Outline"
+msgstr "Dibujar Contornos 2D"
#: scene/main/scene_tree.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Reflections"
-msgstr "Direcciones"
+msgstr "Reflexiones"
#: scene/main/scene_tree.cpp
msgid "Atlas Size"
@@ -25301,9 +24514,8 @@ msgid "Use 32 BPC Depth"
msgstr ""
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Default Environment"
-msgstr "Ver Entorno"
+msgstr "Entorno por Defecto"
#: scene/main/scene_tree.cpp
msgid ""
@@ -25314,9 +24526,8 @@ msgstr ""
"(Rendering -> Environment -> Default Environment) no se ha podido cargar."
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Enable Object Picking"
-msgstr "Activar Papel Cebolla"
+msgstr "Activar Selección de Objetos"
#: scene/main/timer.cpp
msgid ""
@@ -25336,22 +24547,8 @@ msgid "Autostart"
msgstr "Inicio Automático"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Viewport Path"
-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."
+msgstr "Ruta del Viewport"
#: scene/main/viewport.cpp
msgid ""
@@ -25362,63 +24559,71 @@ msgstr ""
"dimensiones para renderizar cualquier cosa."
#: scene/main/viewport.cpp
-msgid "ARVR"
+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 ""
+"Este Viewport tiene HDR habilitado, pero su uso está establecido en 2D o 2D "
+"sin muestreo.\n"
+"El HDR solo está soportado en los Viewports que tienen su uso establecido en "
+"3D o 3D Sin Efectos.\n"
+"El HDR estará desactivado para esta ventana."
+
+#: scene/main/viewport.cpp
+msgid "ARVR"
+msgstr "ARVR"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Size Override Stretch"
-msgstr "Elemento de Anulación"
+msgstr "Anulación del Tamaño de Estiramiento"
#: scene/main/viewport.cpp
msgid "Own World"
-msgstr ""
+msgstr "Mundo Propio"
#: scene/main/viewport.cpp scene/resources/world_2d.cpp
msgid "World"
-msgstr ""
+msgstr "Mundo"
#: scene/main/viewport.cpp
msgid "World 2D"
-msgstr ""
+msgstr "Mundo 2D"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Transparent BG"
-msgstr "Transponer"
+msgstr "Fondo Transparente"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Handle Input Locally"
-msgstr "Cambiar Valor de Entrada"
+msgstr "Manejar Entradas Localmente"
#: scene/main/viewport.cpp
msgid "FXAA"
-msgstr ""
+msgstr "FXAA"
#: scene/main/viewport.cpp
#, fuzzy
msgid "Debanding"
-msgstr "Vinculación"
+msgstr "Debanding"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Disable 3D"
-msgstr "Desactivar Elemento"
+msgstr "Desactivar 3D"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Keep 3D Linear"
-msgstr "Izquierda Lineal"
+msgstr "Mantener 3D Lineal"
#: scene/main/viewport.cpp
msgid "Render Direct To Screen"
-msgstr ""
+msgstr "Renderización Directa en Pantalla"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Debug Draw"
-msgstr "Depurar"
+msgstr "Depurar Dibujo"
#: scene/main/viewport.cpp
msgid "Render Target"
@@ -25429,34 +24634,28 @@ msgid "V Flip"
msgstr ""
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Clear Mode"
-msgstr "Modo de Regla"
+msgstr "Modo de Limpieza"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Enable 2D"
-msgstr "Activar"
+msgstr "Activar 2D"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Enable 3D"
-msgstr "Activar"
+msgstr "Activar 3D"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Object Picking"
-msgstr "Activar Papel Cebolla"
+msgstr "Selección de Objetos"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Disable Input"
-msgstr "Desactivar Elemento"
+msgstr "Desactivar Entrada"
#: scene/main/viewport.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Shadow Atlas"
-msgstr "Nuevo Atlas"
+msgstr "Sombra del Atlas"
#: scene/main/viewport.cpp
msgid "Quad 0"
@@ -25475,78 +24674,66 @@ msgid "Quad 3"
msgstr ""
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Canvas Transform"
-msgstr "Reestablecer Transformación"
+msgstr "Transformación del Canvas"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Global Canvas Transform"
-msgstr "Mantener transformación global"
+msgstr "Transformación Global del Canvas"
#: scene/main/viewport.cpp
msgid "Tooltip Delay (sec)"
-msgstr ""
+msgstr "Retraso del Tooltip (sec)"
#: scene/register_scene_types.cpp
#, fuzzy
msgid "Swap OK Cancel"
-msgstr "Cancelar UI"
+msgstr "Intercambio OK Cancelar"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "Layer Names"
-msgstr "Nombre"
+msgstr "Nombres de las Capas"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "2D Render"
-msgstr "Renderización"
+msgstr "Renderización 2D"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "3D Render"
-msgstr "Renderización"
+msgstr "Renderización 3D"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "2D Physics"
-msgstr "Física"
+msgstr "Física 2D"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "3D Physics"
-msgstr "Física"
+msgstr "Física 3D"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "2D Navigation"
-msgstr "Navegación"
+msgstr "Navegación 2D"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "3D Navigation"
-msgstr "Navegación"
+msgstr "Navegación 3D"
#: scene/register_scene_types.cpp
msgid "Use hiDPI"
msgstr ""
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "Custom"
-msgstr "CustomNode"
+msgstr "Personalizado"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "Custom Font"
-msgstr "CustomNode"
+msgstr "Fuente Personalizada"
#: scene/resources/audio_stream_sample.cpp
#: servers/audio/effects/audio_stream_generator.cpp servers/audio_server.cpp
-#, fuzzy
msgid "Mix Rate"
-msgstr "Nodo Mix"
+msgstr "Tasa de Mezcla"
#: scene/resources/audio_stream_sample.cpp
msgid "Stereo"
@@ -25557,9 +24744,8 @@ msgid "Segments"
msgstr "Segmentos"
#: scene/resources/curve.cpp
-#, fuzzy
msgid "Bake Resolution"
-msgstr "Media Resolución"
+msgstr "Bakear Resolución"
#: scene/resources/curve.cpp
msgid "Bake Interval"
@@ -25570,77 +24756,64 @@ msgid "Panel"
msgstr ""
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color"
-msgstr "Seleccionar Color"
+msgstr "Color de la Fuente"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color Pressed"
-msgstr "Color Hueso 1"
+msgstr "Color de la Fuente Presionada"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color Hover"
-msgstr "Color Hueso 1"
+msgstr "Color de la Fuente por Encima"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color Focus"
-msgstr "Llenar superficie"
+msgstr "Color de la Fuente Enfocada"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color Disabled"
-msgstr "Clip Deshabilitado"
+msgstr "Color de la Fuente Desactivada"
#: scene/resources/default_theme/default_theme.cpp
msgid "H Separation"
msgstr "Separación en H"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Underline Spacing"
-msgstr "Espaciado de Línea"
+msgstr "Espaciado del Subrayado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Arrow"
msgstr ""
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Arrow Margin"
-msgstr "Asignar Margen"
+msgstr "Margen de la Flecha"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Hover Pressed"
-msgstr "Preset"
+msgstr "Presionado por Encima"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Checked Disabled"
-msgstr "Chequeable"
+msgstr "Marcado Desactivado"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Unchecked"
-msgstr "Chequeado"
+msgstr "Sin marcar"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Unchecked Disabled"
-msgstr "Desactivar Elemento"
+msgstr "Sin marcar Desactivado"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Radio Checked"
-msgstr "Chequeado"
+msgstr "Radio Marcado"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Radio Checked Disabled"
-msgstr "(Editor Desactivado)"
+msgstr "Radio Marcado Desactivado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Radio Unchecked"
@@ -25661,27 +24834,23 @@ msgstr ""
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "On Disabled"
-msgstr "Desactivar Elemento"
+msgstr "Desactivado"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Off"
-msgstr "Desplazamiento"
+msgstr "Apagado"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Off Disabled"
-msgstr "Desactivar Elemento"
+msgstr "Apagado Desactivado"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color Shadow"
-msgstr "Color Hueso 1"
+msgstr "Color de la Sombra de la Fuente"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Outline Modulate"
-msgstr "Forzar Modulación en Blanco"
+msgstr "Modulación del Contorno de la Fuente"
#: scene/resources/default_theme/default_theme.cpp
msgid "Shadow Offset X"
@@ -25692,59 +24861,50 @@ msgid "Shadow Offset Y"
msgstr "Desplazamiento de la Sombra en Y"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Shadow As Outline"
-msgstr "Mostrar Contorno Anterior"
+msgstr "Sombra como Contorno"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color Selected"
-msgstr "Desbloquear Seleccionado"
+msgstr "Color de Fuente Seleccionada"
#: scene/resources/default_theme/default_theme.cpp
msgid "Font Color Uneditable"
msgstr ""
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Cursor Color"
-msgstr "CustomNode"
+msgstr "Color del Cursor"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Clear Button Color"
-msgstr "Filtrar señales"
+msgstr "Limpiar Color del Botón"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Clear Button Color Pressed"
-msgstr "Filtrar señales"
+msgstr "Limpiar Color del Botón Presionado"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Minimum Spaces"
-msgstr "Escena Principal"
+msgstr "Espacios Mínimos"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "BG"
-msgstr "B"
+msgstr "BG"
#: scene/resources/default_theme/default_theme.cpp
msgid "FG"
msgstr ""
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Tab"
-msgstr "Tab 1"
+msgstr "Tab"
#: scene/resources/default_theme/default_theme.cpp
#: scene/resources/dynamic_font.cpp scene/resources/world.cpp
#: scene/resources/world_2d.cpp
-#, fuzzy
msgid "Space"
-msgstr "Escena Principal"
+msgstr "Espacio"
#: scene/resources/default_theme/default_theme.cpp
msgid "Folded"
@@ -25759,9 +24919,8 @@ msgid "Font Color Readonly"
msgstr ""
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Completion Lines"
-msgstr "Completar"
+msgstr "Finalización de Líneas"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25820,9 +24979,8 @@ msgid "Decrement Pressed"
msgstr ""
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Slider"
-msgstr "Modo de Colisión"
+msgstr "Deslizador"
#: scene/resources/default_theme/default_theme.cpp
msgid "Grabber Area"
@@ -26261,13 +25419,12 @@ msgid "Mono Font"
msgstr "Fuente Principal"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Table H Separation"
-msgstr "Separación de Tabla H"
+msgstr "Separación H de Tabla"
#: scene/resources/default_theme/default_theme.cpp
msgid "Table V Separation"
-msgstr "Separación de Tabla V"
+msgstr "Separación V de Tabla"
#: scene/resources/default_theme/default_theme.cpp
msgid "Margin Left"
@@ -27540,7 +26697,7 @@ msgstr "Margen de Conexión de Bordes"
#: scene/resources/world_2d.cpp
msgid "Canvas"
-msgstr ""
+msgstr "Lienzo"
#: servers/arvr/arvr_interface.cpp
msgid "Is Primary"
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index aa0a7c6258..10a562d0b8 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -20,13 +20,14 @@
# M3CG <cgmario1999@gmail.com>, 2021, 2022.
# Manuel González <mgoopazo@gmail.com>, 2021.
# emnrx <emanuelermancia@gmail.com>, 2022.
+# Mau_Restor <restor@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-21 15:56+0000\n"
-"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n"
+"PO-Revision-Date: 2022-07-23 03:57+0000\n"
+"Last-Translator: Mau_Restor <restor@gmail.com>\n"
"Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/"
"godot-engine/godot/es_AR/>\n"
"Language: es_AR\n"
@@ -34,7 +35,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -268,9 +269,8 @@ msgid "Network Peer"
msgstr "Profiler de Red"
#: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp
-#, fuzzy
msgid "Root Node"
-msgstr "Nombre del nodo raíz"
+msgstr "Nodo raíz"
#: core/io/networked_multiplayer_peer.cpp
msgid "Refuse New Connections"
@@ -302,7 +302,7 @@ msgstr ""
#: core/io/stream_peer.cpp
msgid "Data Array"
-msgstr ""
+msgstr "Array de datos"
#: core/io/stream_peer_ssl.cpp
msgid "Blocking Handshake"
@@ -331,9 +331,8 @@ msgstr ""
"No hay suficientes bytes para decodificar bytes, o el formato es inválido."
#: core/math/expression.cpp
-#, fuzzy
msgid "Invalid input %d (not passed) in expression"
-msgstr "Entrada inválida %i (no se transmitió) en la expresión"
+msgstr "Entrada inválida %d (no se transmitió) en la expresión"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
@@ -362,7 +361,7 @@ msgstr "En la llamada a '%s':"
#: core/math/random_number_generator.cpp
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Seed"
-msgstr ""
+msgstr "Semilla"
#: core/math/random_number_generator.cpp
#, fuzzy
@@ -371,16 +370,15 @@ msgstr "Estado"
#: core/message_queue.cpp
msgid "Message Queue"
-msgstr ""
+msgstr "Cola de mesajes"
#: core/message_queue.cpp
msgid "Max Size (KB)"
-msgstr ""
+msgstr "Tamaño máximo (KB)"
#: core/os/input.cpp
-#, fuzzy
msgid "Mouse Mode"
-msgstr "Modo Mover"
+msgstr "Modo Mouse"
#: core/os/input.cpp
#, fuzzy
@@ -409,9 +407,13 @@ msgid "Meta"
msgstr "Meta"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Command"
-msgstr "Comunidad"
+msgstr "Comando"
+
+#: 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
@@ -435,7 +437,7 @@ msgstr "Unicode"
#: core/os/input_event.cpp
msgid "Echo"
-msgstr ""
+msgstr "Echo"
#: core/os/input_event.cpp scene/gui/base_button.cpp
msgid "Button Mask"
@@ -459,7 +461,7 @@ msgstr "Dobleclick"
#: core/os/input_event.cpp
msgid "Tilt"
-msgstr ""
+msgstr "Inclinación"
#: core/os/input_event.cpp
#, fuzzy
@@ -468,8 +470,12 @@ msgstr "Preset"
#: core/os/input_event.cpp
#, fuzzy
+msgid "Pen Inverted"
+msgstr "Invertir"
+
+#: core/os/input_event.cpp
msgid "Relative"
-msgstr "Ajuste Relativo"
+msgstr "Relativo"
#: core/os/input_event.cpp scene/2d/camera_2d.cpp scene/2d/cpu_particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/interpolated_camera.cpp
@@ -527,7 +533,7 @@ msgstr "Velocidad"
#: core/os/input_event.cpp
msgid "Instrument"
-msgstr ""
+msgstr "Instrumento"
#: core/os/input_event.cpp
msgid "Controller Number"
@@ -535,7 +541,7 @@ msgstr "Número de Controlador"
#: core/os/input_event.cpp
msgid "Controller Value"
-msgstr ""
+msgstr "Valor del controlador"
#: core/project_settings.cpp editor/editor_node.cpp main/main.cpp
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
@@ -607,9 +613,8 @@ msgstr "Nombre de Directorio de Usuario Personalizado"
#: core/project_settings.cpp main/main.cpp
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
#: platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Display"
-msgstr "Mostrar Todo"
+msgstr "Mostrar"
#: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp
#: modules/opensimplex/noise_texture.cpp scene/2d/line_2d.cpp
@@ -628,17 +633,15 @@ msgstr "Altura"
#: core/project_settings.cpp
msgid "Always On Top"
-msgstr ""
+msgstr "Siempre encima"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Width"
-msgstr "Izquierda Ancha"
+msgstr "probar ancho"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Height"
-msgstr "Prueba"
+msgstr "probar altura"
#: core/project_settings.cpp editor/animation_track_editor.cpp
#: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp
@@ -676,14 +679,12 @@ msgid "Script Templates Search Path"
msgstr "Ruta de Búsqueda de Plantillas de Scripts"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Autoload On Startup"
-msgstr "Sistema de Control de Versiones"
+msgstr "Al iniciar el Sistema de Control de Versiones"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Plugin Name"
-msgstr "Control de Versiones"
+msgstr "Nombre del sistema de control de versiones"
#: core/project_settings.cpp scene/2d/collision_object_2d.cpp
#: scene/3d/collision_object.cpp scene/gui/control.cpp
@@ -692,17 +693,15 @@ msgstr "Entrada"
#: core/project_settings.cpp
msgid "UI Accept"
-msgstr ""
+msgstr "Aceptar Interfaz del usuario"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Select"
-msgstr "Seleccionar"
+msgstr "Seleccionar Interfaz de Usuario"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Cancel"
-msgstr "Cancelar"
+msgstr "Cancelar la interfaz de usuario"
#: core/project_settings.cpp
#, fuzzy
@@ -744,12 +743,11 @@ msgstr ""
#: core/project_settings.cpp
msgid "UI Home"
-msgstr ""
+msgstr "Inicio de la interfaz de usuario"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI End"
-msgstr "Al Final"
+msgstr "Al Final de la interfaz de usuario"
#: core/project_settings.cpp main/main.cpp modules/bullet/register_types.cpp
#: modules/bullet/space_bullet.cpp scene/2d/physics_body_2d.cpp
@@ -807,7 +805,7 @@ msgstr "Filtros"
#: core/project_settings.cpp scene/main/viewport.cpp
msgid "Sharpen Intensity"
-msgstr ""
+msgstr "Intensidad de la nitidez"
#: core/project_settings.cpp editor/editor_export.cpp editor/editor_node.cpp
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
@@ -857,7 +855,7 @@ msgstr "Nivel de Compresión"
#: core/project_settings.cpp
msgid "Window Log Size"
-msgstr ""
+msgstr "medida del registro de la ventana"
#: core/project_settings.cpp
msgid "Zlib"
@@ -880,9 +878,8 @@ msgid "TCP"
msgstr "TCP"
#: core/register_core_types.cpp
-#, fuzzy
msgid "Connect Timeout Seconds"
-msgstr "Conexiones al método:"
+msgstr "Tiempo de espera en segundos de la conexion"
#: core/register_core_types.cpp
msgid "Packet Peer Stream"
@@ -907,9 +904,8 @@ msgid "Resource"
msgstr "Recursos"
#: core/resource.cpp
-#, fuzzy
msgid "Local To Scene"
-msgstr "Cerrar Escena"
+msgstr "Local a la escena"
#: core/resource.cpp editor/dependency_editor.cpp
#: editor/editor_autoload_settings.cpp editor/plugins/path_editor_plugin.cpp
@@ -1190,9 +1186,8 @@ msgid "Type"
msgstr "Tipo"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In Handle"
-msgstr "Setear Handle"
+msgstr "En manejo"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1343,9 +1338,8 @@ msgid "Time (s):"
msgstr "Tiempo (s): "
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Position:"
-msgstr "Posición del Panel"
+msgstr "Posición:"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -2158,14 +2152,15 @@ msgstr "Favoritos:"
msgid "Recent:"
msgstr "Recientes:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Buscar:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Coincidencias:"
@@ -2225,8 +2220,8 @@ msgstr "Buscar Reemplazo de Recurso:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2805,7 +2800,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Copiar Ruta del Nodo"
#: editor/editor_export.cpp
@@ -5630,6 +5625,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11917,6 +11921,11 @@ msgid "New Animation"
msgstr "Nueva Animación"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filtrar métodos"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Velocidad:"
@@ -18901,6 +18910,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 +18923,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 +18976,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 +19227,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 +19246,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 ""
+"\"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 ""
"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\"."
@@ -20703,15 +20742,15 @@ msgstr "No se pudo encontrar la keystore, no se puedo exportar."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Archivo ejecutable no válido."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20735,15 +20774,15 @@ msgstr "Nombre inválido."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Archivo ejecutable no válido."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20984,7 +21023,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 +21801,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 +21814,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 +21845,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."
@@ -21840,7 +21889,7 @@ msgstr "Viaje"
msgid "Rotation Degrees"
msgstr "Rotando %s grados."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Constante Global"
@@ -23945,6 +23994,11 @@ msgstr ""
"En su lugar, cambiá el tamaño de los collision shapes hijos."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Mantener Transformación Global"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr "Matriz"
@@ -25190,6 +25244,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 +25661,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 +25668,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..3976c9f0bd 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
@@ -472,6 +477,10 @@ msgid "Pressure"
msgstr "Eelseadistus"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2145,14 +2154,15 @@ msgstr "Lemmikud:"
msgid "Recent:"
msgstr "Hiljutised:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Otsi:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Vasted:"
@@ -2208,8 +2218,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2779,7 +2789,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Kopeeri sõlme tee"
#: editor/editor_export.cpp
@@ -5473,6 +5483,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11575,6 +11594,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Kustuta animatsioon?"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18297,6 +18321,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 +18334,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 +18382,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 +18620,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 +18634,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
@@ -19964,15 +20013,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Vigane nimi."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -19994,15 +20043,15 @@ msgstr "Vigane nimi."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Vigane nimi."
#: platform/windows/export/export.cpp
msgid "Failed to remove temporary file \"%s\"."
@@ -20238,7 +20287,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 +21000,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 +21013,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 ""
@@ -21023,7 +21082,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstant"
@@ -22996,6 +23055,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Tõlked"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24170,6 +24234,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 +24625,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 +24632,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..3e69f3c4b9 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
@@ -446,6 +451,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Atxikitze erlatiboa"
@@ -2107,14 +2116,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2170,8 +2180,8 @@ msgstr "Bilatu ordezko baliabidea:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2746,8 +2756,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Kargatu animazioa"
#: editor/editor_export.cpp
#, fuzzy
@@ -5380,6 +5391,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11454,6 +11473,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Ezabatu animazioa?"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18122,6 +18146,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 +18159,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 +18205,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 +18442,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 +18456,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
@@ -19767,15 +19816,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Animazio izen baliogabea!"
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -19797,15 +19846,15 @@ msgstr "Animazio izen baliogabea!"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Animazio izen baliogabea!"
#: platform/windows/export/export.cpp
msgid "Failed to remove temporary file \"%s\"."
@@ -20032,7 +20081,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 +20778,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 +20791,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 ""
@@ -20800,7 +20859,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstantea"
@@ -22746,6 +22805,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Translazio atzikitzea:"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23887,6 +23951,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 +24335,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..86b847e530 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
@@ -498,6 +503,10 @@ msgid "Pressure"
msgstr "بازنشانی بزرگنمایی"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "GDNative"
@@ -2189,14 +2198,15 @@ msgstr "برگزیده‌ها:"
msgid "Recent:"
msgstr "اخیر:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "جستجو:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "تطبیق‌ها:"
@@ -2256,8 +2266,8 @@ msgstr "منبع جایگزینی را جستجو کن:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2830,7 +2840,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "کپی کردن مسیر node"
#: editor/editor_export.cpp
@@ -5535,6 +5545,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "انتخاب شده را حذ٠کن"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11948,6 +11967,11 @@ msgid "New Animation"
msgstr "تغییر نام انیمیشن"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "حالت صاÙÛŒ:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -19006,6 +19030,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 +19043,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 +19091,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 +19335,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 +19349,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
@@ -20703,15 +20752,15 @@ msgstr "نمی‌تواند یک پوشه ایجاد شود."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "باید از یک پسوند معتبر Ø§Ø³ØªÙØ§Ø¯Ù‡ شود."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20735,15 +20784,15 @@ msgstr "نام نامعتبر."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "باید از یک پسوند معتبر Ø§Ø³ØªÙØ§Ø¯Ù‡ شود."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20980,7 +21029,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 +21763,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 +21776,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 ""
@@ -21787,7 +21846,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "ثابت"
@@ -23812,6 +23871,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "انتقال را در انیمیشن تغییر بده"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25012,6 +25076,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 +25477,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..db841ef48a 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
@@ -496,6 +501,10 @@ msgid "Pressure"
msgstr "Esiasetukset"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Suhteellinen tarttuminen"
@@ -2207,14 +2216,15 @@ msgstr "Suosikit:"
msgid "Recent:"
msgstr "Viimeaikaiset:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Hae:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Osumat:"
@@ -2274,8 +2284,8 @@ msgstr "Etsi korvaava resurssi:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2854,7 +2864,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Kopioi solmun polku"
#: editor/editor_export.cpp
@@ -5662,6 +5672,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11936,6 +11955,11 @@ msgid "New Animation"
msgstr "Uusi animaatio"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Suodata metodeja"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Nopeus:"
@@ -18902,6 +18926,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 +18939,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 +18992,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 +19245,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 +19267,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."
@@ -20702,17 +20756,17 @@ msgstr "Keystorea ei löytynyt, ei voida viedä."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
"rcedit-työkalu täytyy olla konfiguroituna editorin asetuksissa (Export > "
"Windows > Rcedit) ikonin tai sovelluksen tietojen muuttamiseksi."
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Virheellinen käynnistystiedosto."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20737,17 +20791,17 @@ msgstr "Virheellinen nimi."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
"rcedit-työkalu täytyy olla konfiguroituna editorin asetuksissa (Export > "
"Windows > Rcedit) ikonin tai sovelluksen tietojen muuttamiseksi."
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Virheellinen käynnistystiedosto."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20991,7 +21045,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 +21820,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 +21833,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 +21865,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 ""
@@ -21849,7 +21913,7 @@ msgstr "Matkaa"
msgid "Rotation Degrees"
msgstr "Kierto %s astetta."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Globaali vakio"
@@ -23999,6 +24063,11 @@ msgstr ""
"Muuta kokoa sen sijaan alisolmujen törmäysmuodoissa."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Pidä globaali muunnos"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25260,6 +25329,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 +25746,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 +25753,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..0a154fd6ae 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
@@ -443,6 +448,10 @@ msgid "Pressure"
msgstr "Presyur"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relatibo"
@@ -2079,14 +2088,15 @@ msgstr "Mga Paborito:"
msgid "Recent:"
msgstr "Kamakailan:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Paghahanap:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2142,8 +2152,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2702,8 +2712,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Pagulit ng Animation"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5297,6 +5308,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11308,6 +11327,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Pagulit ng Animation"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17868,6 +17892,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 +17905,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 +17949,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 +18172,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 +18186,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
@@ -19453,14 +19502,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19482,14 +19530,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19706,7 +19753,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 +20430,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 +20442,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 ""
@@ -20453,7 +20509,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22325,6 +22381,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "3D Transform Track"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23426,6 +23487,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 +23851,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..88c4966b54 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,17 @@
# Nathan Hamy <hamynathan92@gmail.com>, 2022.
# HOUA <ninjacowzx@gmail.com>, 2022.
# DinosaurHorseSword <ewenlandry@mailfence.com>, 2022.
+# Arnaud Lier <arnaud@ric-rac.org>, 2022.
+# Jérémie Guegain <mirejai@orange.fr>, 2022.
+# cwulveryck <cwulveryck@online.fr>, 2022.
+# Helix Sir <vincentbarkmann@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: DinosaurHorseSword <ewenlandry@mailfence.com>\n"
+"PO-Revision-Date: 2022-08-05 01:04+0000\n"
+"Last-Translator: Helix Sir <vincentbarkmann@gmail.com>\n"
"Language-Team: French <https://hosted.weblate.org/projects/godot-engine/"
"godot/fr/>\n"
"Language: fr\n"
@@ -113,7 +116,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -145,11 +148,11 @@ msgstr "Lissage de Delta"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode"
-msgstr "Mode d'Utilisation Faible du Processeur"
+msgstr "Mode d'utilisation faible du processeur"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode Sleep (µsec)"
-msgstr "Mode d'Utilisation Faible du Processeur (µs)"
+msgstr "Mode d'utilisation faible du processeur Veille (µsec)"
#: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp
msgid "Keep Screen On"
@@ -242,9 +245,8 @@ msgid "Time Scale"
msgstr "Echelle de temps"
#: core/bind/core_bind.cpp main/main.cpp
-#, fuzzy
msgid "Physics Jitter Fix"
-msgstr "Correction de la physique gigue"
+msgstr "Correction des sursauts de physique"
#: core/bind/core_bind.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Error"
@@ -315,7 +317,7 @@ msgstr "Taille de page"
#: core/io/file_access_network.cpp
msgid "Page Read Ahead"
-msgstr ""
+msgstr "Pré-lecture de page"
#: core/io/http_client.cpp
msgid "Blocking Mode Enabled"
@@ -327,7 +329,7 @@ msgstr "Connexion"
#: core/io/http_client.cpp
msgid "Read Chunk Size"
-msgstr ""
+msgstr "Taile des tronçons de lecture"
#: core/io/marshalls.cpp
msgid "Object ID"
@@ -359,23 +361,23 @@ msgstr "Mode de Transfert"
#: core/io/packet_peer.cpp
msgid "Encode Buffer Max Size"
-msgstr ""
+msgstr "Taille maximale du tampon d'encodage"
#: core/io/packet_peer.cpp
msgid "Input Buffer Max Size"
-msgstr ""
+msgstr "Taille maximale du tampon d'entrée"
#: core/io/packet_peer.cpp
msgid "Output Buffer Max Size"
-msgstr ""
+msgstr "Taille maximale du tampon de sortie"
#: core/io/packet_peer.cpp
msgid "Stream Peer"
-msgstr ""
+msgstr "Pair de flux"
#: core/io/stream_peer.cpp
msgid "Big Endian"
-msgstr ""
+msgstr "Gros-boutiste"
#: core/io/stream_peer.cpp
msgid "Data Array"
@@ -483,6 +485,10 @@ msgstr "Méta"
msgid "Command"
msgstr "Commande"
+#: core/os/input_event.cpp
+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
@@ -491,7 +497,7 @@ msgstr "Pressé"
#: core/os/input_event.cpp
msgid "Scancode"
-msgstr "Scancode"
+msgstr "Code de scan"
#: core/os/input_event.cpp
msgid "Physical Scancode"
@@ -534,6 +540,10 @@ msgid "Pressure"
msgstr "Pression"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr "Stylo Inversé"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relatif"
@@ -610,7 +620,7 @@ msgstr "Application"
#: core/project_settings.cpp main/main.cpp
msgid "Config"
-msgstr "Config"
+msgstr "Configuration"
#: core/project_settings.cpp
msgid "Project Settings Override"
@@ -717,9 +727,8 @@ msgid "Editor"
msgstr "Éditeur"
#: core/project_settings.cpp
-#, fuzzy
msgid "Main Run Args"
-msgstr "Arguments de la scène principale :"
+msgstr "Paramètres d'exécution du programme principal"
#: core/project_settings.cpp
msgid "Scene Naming"
@@ -727,11 +736,11 @@ msgstr "Noms de scènes"
#: core/project_settings.cpp
msgid "Search In File Extensions"
-msgstr ""
+msgstr "Rechercher dans les extensions de fichiers"
#: core/project_settings.cpp
msgid "Script Templates Search Path"
-msgstr ""
+msgstr "Chemin où chercher les modèles de scripts"
#: core/project_settings.cpp
msgid "Version Control Autoload On Startup"
@@ -748,15 +757,13 @@ msgstr "Entrée"
#: core/project_settings.cpp
msgid "UI Accept"
-msgstr ""
+msgstr "Accepter"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Select"
msgstr "Sélectionner"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Cancel"
msgstr "Annuler"
@@ -778,24 +785,23 @@ msgstr "Droite"
#: core/project_settings.cpp
msgid "UI Up"
-msgstr ""
+msgstr "Haut"
#: core/project_settings.cpp
msgid "UI Down"
msgstr "Bas"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Page Up"
-msgstr "Page Haut"
+msgstr "Page Haut (Interface)"
#: core/project_settings.cpp
msgid "UI Page Down"
-msgstr ""
+msgstr "Page Bas"
#: core/project_settings.cpp
msgid "UI Home"
-msgstr ""
+msgstr "Accueil Interface Utilisateur"
#: core/project_settings.cpp
msgid "UI End"
@@ -823,9 +829,8 @@ msgid "3D"
msgstr "3D"
#: core/project_settings.cpp
-#, fuzzy
msgid "Smooth Trimesh Collision"
-msgstr "Collision Lisse Trimesh"
+msgstr "Lissage de Collision Trimesh"
#: core/project_settings.cpp drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles2/rasterizer_scene_gles2.cpp
@@ -857,7 +862,7 @@ msgstr "Filtres"
#: core/project_settings.cpp scene/main/viewport.cpp
msgid "Sharpen Intensity"
-msgstr ""
+msgstr "Augmenter l'intensité"
#: core/project_settings.cpp editor/editor_export.cpp editor/editor_node.cpp
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
@@ -895,11 +900,11 @@ msgstr "Formats"
#: core/project_settings.cpp
msgid "Zstd"
-msgstr ""
+msgstr "Zstd"
#: core/project_settings.cpp
msgid "Long Distance Matching"
-msgstr ""
+msgstr "Appairement longue distance"
#: core/project_settings.cpp
msgid "Compression Level"
@@ -907,7 +912,7 @@ msgstr "Niveau de Compression"
#: core/project_settings.cpp
msgid "Window Log Size"
-msgstr ""
+msgstr "Taille du journal de la fenêtre"
#: core/project_settings.cpp
msgid "Zlib"
@@ -923,11 +928,11 @@ msgstr "Android"
#: core/project_settings.cpp
msgid "Modules"
-msgstr ""
+msgstr "Modules"
#: 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"
@@ -935,11 +940,11 @@ msgstr "Délai d'expiration de la connexion en secondes"
#: core/register_core_types.cpp
msgid "Packet Peer Stream"
-msgstr ""
+msgstr "Flux de pair de paquet"
#: core/register_core_types.cpp
msgid "Max Buffer (Power of 2)"
-msgstr ""
+msgstr "Tampon Max (puissance de 2)"
#: core/register_core_types.cpp editor/editor_settings.cpp main/main.cpp
msgid "SSL"
@@ -980,7 +985,7 @@ msgstr "Test"
#: core/translation.cpp scene/resources/font.cpp
msgid "Fallback"
-msgstr ""
+msgstr "Repli"
#: core/ustring.cpp scene/resources/segment_shape_2d.cpp
msgid "B"
@@ -1016,17 +1021,17 @@ msgstr "Eio"
#: drivers/gles3/rasterizer_scene_gles3.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp modules/gltf/gltf_state.cpp
msgid "Buffers"
-msgstr ""
+msgstr "Tampons"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Canvas Polygon Buffer Size (KB)"
-msgstr ""
+msgstr "Taille du tampon des polygones du canevas (Ko)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Canvas Polygon Index Buffer Size (KB)"
-msgstr ""
+msgstr "Taille de l'index des polygones du canevas (Ko)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp editor/editor_settings.cpp
@@ -1038,56 +1043,52 @@ msgstr ""
#: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp
#: servers/visual_server.cpp
msgid "2D"
-msgstr ""
+msgstr "2D"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
-#, fuzzy
msgid "Snapping"
-msgstr "Magnétisme intelligent"
+msgstr "Magnétisme"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
-#, fuzzy
msgid "Use GPU Pixel Snap"
-msgstr "Aligner au pixel près"
+msgstr "Arrondissement GPU au pixel le plus proche"
#: drivers/gles2/rasterizer_scene_gles2.cpp
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Immediate Buffer Size (KB)"
-msgstr ""
+msgstr "Taille du tampon immédiat (Ko)"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
-#, fuzzy
msgid "Lightmapping"
-msgstr "Précalculer les lightmaps"
+msgstr "Cartographie des lumières"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
msgid "Use Bicubic Sampling"
-msgstr ""
+msgstr "Utiliser l’échantillonnage bicubique"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Renderable Elements"
-msgstr ""
+msgstr "Maximum d'éléments pouvant être rendus"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Renderable Lights"
-msgstr ""
+msgstr "Maximum de lumières pouvant être rendues"
#: drivers/gles3/rasterizer_scene_gles3.cpp
-#, fuzzy
msgid "Max Renderable Reflections"
-msgstr "Centrer sur la sélection"
+msgstr "Nombre maximum de reflets pouvant être rendus"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Lights Per Object"
-msgstr ""
+msgstr "Maximum de lumières par objet"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Subsurface Scattering"
-msgstr ""
+msgstr "Transluminescence"
#: drivers/gles3/rasterizer_scene_gles3.cpp editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
@@ -1108,11 +1109,11 @@ msgstr "Suivre la surface"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Weight Samples"
-msgstr ""
+msgstr "Échantillons de poids"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Voxel Cone Tracing"
-msgstr ""
+msgstr "Traçage de cone voxel"
#: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp
msgid "High Quality"
@@ -1120,7 +1121,7 @@ msgstr "Haute Qualité"
#: drivers/gles3/rasterizer_storage_gles3.cpp
msgid "Blend Shape Max Buffer Size (KB)"
-msgstr ""
+msgstr "Taille max du tampon de mélange de formes"
#. TRANSLATORS: Adjective, refers to the mode for Bezier handles (Free, Balanced, Mirror).
#: editor/animation_bezier_editor.cpp
@@ -1177,7 +1178,7 @@ msgstr "Modifier le temps de l’image-clé"
#: editor/animation_track_editor.cpp
msgid "Anim Change Transition"
-msgstr "Changer la transition de l’animation"
+msgstr "Transition de changement de l’animation"
#: editor/animation_track_editor.cpp
msgid "Anim Change Transform"
@@ -1194,9 +1195,8 @@ msgstr "Changer l’appel de l’animation"
#: editor/animation_track_editor.cpp scene/2d/animated_sprite.cpp
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Frame"
-msgstr "Image %"
+msgstr "Trame"
#: editor/animation_track_editor.cpp editor/editor_profiler.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
@@ -1222,14 +1222,13 @@ msgid "Value"
msgstr "Valeur"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Arg Count"
-msgstr "Compte"
+msgstr "Nombre d'arguments"
#: editor/animation_track_editor.cpp main/main.cpp
#: modules/mono/mono_gd/gd_mono.cpp
msgid "Args"
-msgstr ""
+msgstr "Args"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp
@@ -1239,31 +1238,27 @@ msgid "Type"
msgstr "Type"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In Handle"
-msgstr "Définir la poignée"
+msgstr "Poignée d'entrée"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out Handle"
-msgstr "Définir la poignée"
+msgstr "Poignée de sortie"
#: editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
msgid "Stream"
-msgstr ""
+msgstr "Flux"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start Offset"
-msgstr "Décalage du Pivot"
+msgstr "Décalage du Départ"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End Offset"
-msgstr "Décalage :"
+msgstr "Décalage à la fin"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/import/resource_importer_scene.cpp
@@ -1276,9 +1271,8 @@ msgid "Animation"
msgstr "Animation"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing"
-msgstr "Ease in-out"
+msgstr "Transition entrée-sortie"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
@@ -1413,44 +1407,36 @@ msgid "Type:"
msgstr "Type :"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "(Invalid, expected type: %s)"
-msgstr "Modèle d'exportation non valide :"
+msgstr "(Invalide, type attendu : %s)"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing:"
-msgstr "Ease in-out"
+msgstr "Transition entrée-sortie :"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In-Handle:"
-msgstr "Définir la poignée"
+msgstr "Poignée d'entrée :"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out-Handle:"
-msgstr "Définir la poignée"
+msgstr "Poignée de sortie :"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Stream:"
-msgstr "Item radio"
+msgstr "Flux :"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start (s):"
-msgstr "Redémarrer (s) :"
+msgstr "Début (s) :"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End (s):"
-msgstr "Fondu entrant (s) :"
+msgstr "Fin (s) :"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation Clip:"
-msgstr "Animations :"
+msgstr "Clip d'animation :"
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
@@ -1538,9 +1524,8 @@ msgid "Editors"
msgstr "Éditeurs"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Confirm Insert Track"
-msgstr "Insérer une piste et clé d’animation"
+msgstr "Confirmer l'ajout de piste"
#. TRANSLATORS: %s will be replaced by a phrase describing the target of track.
#: editor/animation_track_editor.cpp
@@ -1690,7 +1675,7 @@ msgstr "Méthodes"
#: editor/animation_track_editor.cpp
msgid "Bezier"
-msgstr ""
+msgstr "Bezier"
#: editor/animation_track_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
@@ -2207,14 +2192,15 @@ msgstr "Favoris :"
msgid "Recent:"
msgstr "Récents :"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Rechercher :"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Correspondances :"
@@ -2274,8 +2260,8 @@ msgstr "Recherche ressource de remplacement :"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2284,7 +2270,7 @@ msgstr "Ouvrir"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "Possesseur de : %s (Total : %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2852,22 +2838,19 @@ msgstr "Choisir"
#: editor/editor_export.cpp
msgid "Project export for platform:"
-msgstr ""
+msgstr "Exportation du projet pour la plateforme :"
#: editor/editor_export.cpp
-#, fuzzy
-msgid "Completed with errors."
-msgstr "Copier le chemin du nœud"
+msgid "Completed with warnings."
+msgstr "Terminé avec des avertissements."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Completed successfully."
-msgstr "Paquetage installé avec succès !"
+msgstr "Terminé avec succès."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed."
-msgstr "Échec :"
+msgstr "Échec."
#: editor/editor_export.cpp
msgid "Storing File:"
@@ -2882,29 +2865,24 @@ msgid "Packing"
msgstr "Empaquetage"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Save PCK"
-msgstr "Enregistrer sous"
+msgstr "Enregistrer PCK"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Cannot create file \"%s\"."
-msgstr "Impossible de créer le dossier."
+msgstr "Impossible de créer le fichier \"%s\"."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed to export project files."
-msgstr "Impossible d'exporter les fichiers du projet"
+msgstr "Impossible d'exporter les fichiers du projet."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Can't open file to read from path \"%s\"."
-msgstr "Impossible d'ouvrir le fichier pour écriture :"
+msgstr "Impossible d'ouvrir le fichier en lecture depuis le chemin \"%s\"."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Save ZIP"
-msgstr "Enregistrer sous"
+msgstr "Enregistrer le ZIP"
#: editor/editor_export.cpp
msgid ""
@@ -2985,28 +2963,27 @@ msgstr "64 Bits"
#: editor/editor_export.cpp
msgid "Embed PCK"
-msgstr ""
+msgstr "Intégrer PCK"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Texture Format"
-msgstr "RegionDeTexture"
+msgstr "Format de la texture"
#: editor/editor_export.cpp
msgid "BPTC"
-msgstr ""
+msgstr "BPTC"
#: editor/editor_export.cpp platform/osx/export/export.cpp
msgid "S3TC"
-msgstr ""
+msgstr "S3TC"
#: editor/editor_export.cpp platform/osx/export/export.cpp
msgid "ETC"
-msgstr ""
+msgstr "ETC"
#: editor/editor_export.cpp platform/osx/export/export.cpp
msgid "ETC2"
-msgstr ""
+msgstr "ETC2"
#: editor/editor_export.cpp
msgid "No BPTC Fallbacks"
@@ -3025,30 +3002,25 @@ msgid "Custom release template not found."
msgstr "Modèle de version personnalisée introuvable."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Prepare Template"
-msgstr "Gérer les modèles"
+msgstr "Préparer le modèle type"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "The given export path doesn't exist."
-msgstr "Le chemin de l'exportation donné n'existe pas :"
+msgstr "Le chemin de l'exportation donné n'existe pas."
#: editor/editor_export.cpp platform/javascript/export/export.cpp
-#, fuzzy
msgid "Template file not found: \"%s\"."
-msgstr "Fichier modèle introuvable :"
+msgstr "Fichier modèle introuvable : \"%s\"."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed to copy export template."
-msgstr "Modèle d'exportation non valide :"
+msgstr "La copie du modèle d'exportation a échoué."
#: editor/editor_export.cpp platform/windows/export/export.cpp
#: platform/x11/export/export.cpp
-#, fuzzy
msgid "PCK Embedding"
-msgstr "Remplissage(Padding)"
+msgstr "Intégration PCK"
#: editor/editor_export.cpp
msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
@@ -3056,7 +3028,7 @@ msgstr "Le PCK inclus dans un export 32-bits ne peut dépasser 4 Go."
#: editor/editor_export.cpp
msgid "Convert Text Resources To Binary On Export"
-msgstr ""
+msgstr "Convertir les ressources textuelles en binaire lors de l'exportation"
#: editor/editor_feature_profile.cpp
msgid "3D Editor"
@@ -3269,9 +3241,8 @@ msgid "Manage Editor Feature Profiles"
msgstr "Gérer les profils de fonctionnalités de l'éditeur"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Default Feature Profile"
-msgstr "Profil des fonctionnalités de Godot"
+msgstr "Profil de fonctionalités par défaut"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Select Current Folder"
@@ -3383,7 +3354,7 @@ msgstr "Afficher les fichiers cachés"
#: editor/editor_file_dialog.cpp
msgid "Disable Overwrite Warning"
-msgstr ""
+msgstr "Désactiver l'avertissement de réécriture"
#: editor/editor_file_dialog.cpp
msgid "Go Back"
@@ -3486,7 +3457,7 @@ msgstr "Ré-importation des assets"
#: editor/editor_file_system.cpp
msgid "Reimport Missing Imported Files"
-msgstr ""
+msgstr "Réimporter les fichiers importés manquants"
#: editor/editor_help.cpp scene/2d/camera_2d.cpp scene/gui/control.cpp
#: scene/gui/nine_patch_rect.cpp scene/resources/dynamic_font.cpp
@@ -3597,7 +3568,7 @@ msgstr "Aide"
#: editor/editor_help.cpp
msgid "Sort Functions Alphabetically"
-msgstr ""
+msgstr "Trier les fonctions par ordre alphabétique"
#: editor/editor_help_search.cpp editor/editor_node.cpp
#: editor/plugins/script_editor_plugin.cpp
@@ -3686,25 +3657,21 @@ msgid "Read Only"
msgstr "Lecture Seule"
#: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp
-#, fuzzy
msgid "Checkable"
-msgstr "Item à cocher"
+msgstr "Cochable"
#: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Checked"
-msgstr "Item coché"
+msgstr "Coché"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Draw Red"
-msgstr "Appels de dessin :"
+msgstr "Dessiner en rouge"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Keying"
-msgstr "Jouer"
+msgstr "En train de taper"
#: editor/editor_inspector.cpp
msgid "Pin value"
@@ -4078,9 +4045,8 @@ msgid "Save & Reload"
msgstr "Sauvegarder & Recharger"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save changes to '%s' before reloading?"
-msgstr "Sauvegarder les modifications effectuées à « %s » avant de quitter ?"
+msgstr "Sauvegarder les modifications dans '%s' avant de recharger ?"
#: editor/editor_node.cpp
msgid "Save & Close"
@@ -4199,11 +4165,9 @@ msgid "Open Project Manager?"
msgstr "Ouvrir le gestionnaire de projets ?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save changes to the following scene(s) before reloading?"
msgstr ""
-"Sauvegarder les modifications sur la (les) scène(s) suivante(s) avant de "
-"quitter ?"
+"Sauvegarder les modifications de scène(s) suivante(s) avant de recharger ?"
#: editor/editor_node.cpp
msgid "Save & Quit"
@@ -4399,6 +4363,8 @@ msgstr "%d fichiers supplémentaires"
msgid ""
"Unable to write to file '%s', file in use, locked or lacking permissions."
msgstr ""
+"Impossible d'écrire dans le fichier '%s', le fichier est peut être utilisé, "
+"verrouillé ou vous n'avez pas les permissions pour écrire dessus."
#: editor/editor_node.cpp editor/editor_settings.cpp editor/scene_tree_dock.cpp
#: servers/arvr/arvr_interface.cpp
@@ -4406,58 +4372,52 @@ msgid "Interface"
msgstr "Interface"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Scene Tabs"
-msgstr "Basculer entre onglets de scène"
+msgstr "Onglets de scène"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Always Show Close Button"
-msgstr "Toujours afficher la grille"
+msgstr "Toujours afficher le bouton fermer"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Resize If Many Tabs"
-msgstr ""
+msgstr "Redimensionner si plusieurs onglets"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Minimum Width"
-msgstr ""
+msgstr "Largeur Minimum"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Output"
msgstr "Sortie"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Always Clear Output On Play"
-msgstr "Effacer la sortie"
+msgstr "Toujours nettoyer la sortie lors du lancement"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Open Output On Play"
-msgstr ""
+msgstr "Toujours afficher la sortie lors du lancement"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Close Output On Stop"
-msgstr ""
+msgstr "Toujours fermer la sortie à l'arrêt"
#: editor/editor_node.cpp
msgid "Save On Focus Loss"
-msgstr ""
+msgstr "Enregistrer lorsque le focus est perdu"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Save Each Scene On Quit"
-msgstr "Sauvegarder la branche comme scène"
+msgstr "Enregistrer toutes les scènes à la fermeture"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Quit Confirmation"
-msgstr "Voir information"
+msgstr "Confirmer avant de quitter"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Show Update Spinner"
-msgstr "Cacher l'indicateur d'activité"
+msgstr "Afficher l'indicateur d'activité"
#: editor/editor_node.cpp
msgid "Update Continuously"
@@ -4469,62 +4429,56 @@ msgid "Update Vital Only"
msgstr "Changements de matériau"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Localize Settings"
-msgstr "Localisation"
+msgstr "Traduction des réglages"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Restore Scenes On Load"
-msgstr "Le nœud de la scène"
+msgstr "Restaurer les scènes au chargement"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Show Thumbnail On Hover"
-msgstr ""
+msgstr "Afficher l’aperçu au survol"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Inspector"
msgstr "Inspecteur"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Default Property Name Style"
-msgstr "Chemin du projet :"
+msgstr "Style par défaut des noms de propriétés"
#: editor/editor_node.cpp
msgid "Default Float Step"
-msgstr ""
+msgstr "Pas par défaut des flottant"
#: editor/editor_node.cpp scene/gui/tree.cpp
-#, fuzzy
msgid "Disable Folding"
-msgstr "Bouton désactivé"
+msgstr "Désactiver le repliage"
#: editor/editor_node.cpp
msgid "Auto Unfold Foreign Scenes"
-msgstr ""
+msgstr "Déplier automatiquement les scènes étrangères"
#: editor/editor_node.cpp
msgid "Horizontal Vector2 Editing"
-msgstr ""
+msgstr "Édition horizontale de Vector2"
#: editor/editor_node.cpp
msgid "Horizontal Vector Types Editing"
-msgstr ""
+msgstr "Édition de Types de Vecteur Horizontal"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Resources In Current Inspector"
-msgstr "Ouvrir dans l'Inspecteur"
+msgstr "Ouvrir les ressources dans l'inspecteur actuel"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Resources To Open In New Inspector"
-msgstr "Ouvrir dans l'Inspecteur"
+msgstr "Ressources à ouvrir dans un nouvel inspecteur"
#: editor/editor_node.cpp
msgid "Default Color Picker Mode"
-msgstr ""
+msgstr "Mode par défaut du sélectionneur de couleur"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Version Control"
@@ -5185,12 +5139,11 @@ msgstr "Débogueur"
#: editor/editor_profiler.cpp
msgid "Profiler Frame History Size"
-msgstr ""
+msgstr "Taille de l'historique de la trame du profileur"
#: editor/editor_profiler.cpp
-#, fuzzy
msgid "Profiler Frame Max Functions"
-msgstr "Renommer la fonction"
+msgstr "Nombre maximum de fonctions par trame de profileur"
#: editor/editor_properties.cpp
msgid "Edit Text:"
@@ -5323,20 +5276,17 @@ msgstr "Nouveau %s"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Base Type"
-msgstr "Changer le type de base"
+msgstr "Type de base"
#: editor/editor_resource_picker.cpp
-#, fuzzy
msgid "Edited Resource"
-msgstr "Ajouter une ressource"
+msgstr "Ressource modifiée"
#: editor/editor_resource_picker.cpp scene/gui/line_edit.cpp
#: scene/gui/slider.cpp scene/gui/spin_box.cpp
-#, fuzzy
msgid "Editable"
-msgstr "Élément modifiable"
+msgstr "Modifiable"
#: editor/editor_resource_picker.cpp editor/property_editor.cpp
msgid "New Script"
@@ -5360,9 +5310,8 @@ msgstr ""
"Ajoutez un préréglage exécutable dans le menu d'exportation."
#: editor/editor_run_native.cpp
-#, fuzzy
msgid "Project Run"
-msgstr "Projet"
+msgstr "Exécution du projet"
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -5389,34 +5338,32 @@ msgid "Did you forget the '_run' method?"
msgstr "Avez-vous oublié la méthode « _run » ?"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Editor Language"
-msgstr "Disposition de l'éditeur"
+msgstr "Langue de l'Éditeur"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Display Scale"
-msgstr "Tout afficher"
+msgstr "Échelle de l'affichage"
#: editor/editor_settings.cpp
msgid "Custom Display Scale"
-msgstr ""
+msgstr "Échelle personnalisé de l'affichage"
#: editor/editor_settings.cpp
msgid "Main Font Size"
-msgstr ""
+msgstr "Taille de la police principale"
#: editor/editor_settings.cpp
msgid "Code Font Size"
-msgstr ""
+msgstr "Taille de la police du code"
#: editor/editor_settings.cpp
msgid "Font Antialiased"
-msgstr ""
+msgstr "Police anticrénelée"
#: editor/editor_settings.cpp
msgid "Font Hinting"
-msgstr ""
+msgstr "Indication de police"
#: editor/editor_settings.cpp
msgid "Main Font"
@@ -5424,7 +5371,7 @@ msgstr "Police Principale"
#: editor/editor_settings.cpp
msgid "Main Font Bold"
-msgstr ""
+msgstr "Principale police grasse"
#: editor/editor_settings.cpp
msgid "Code Font"
@@ -5432,28 +5379,27 @@ msgstr "Police du Code"
#: editor/editor_settings.cpp
msgid "Dim Editor On Dialog Popup"
-msgstr ""
+msgstr "Assombrir l'éditeur à l'ouverture d'un dialogue"
#: editor/editor_settings.cpp main/main.cpp
msgid "Low Processor Mode Sleep (µsec)"
-msgstr ""
+msgstr "Veille du Mode faible latence Processeur (µsec)"
#: editor/editor_settings.cpp
msgid "Unfocused Low Processor Mode Sleep (µsec)"
-msgstr ""
+msgstr "Veille du mode d'utilisation faible du processeur quand inactif (µsec)"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Separate Distraction Mode"
-msgstr "Mode Sans Distraction"
+msgstr "Mode distraction séparée"
#: editor/editor_settings.cpp
msgid "Automatically Open Screenshots"
-msgstr ""
+msgstr "Ouvrir automatiquement les captures d'écran"
#: editor/editor_settings.cpp
msgid "Max Array Dictionary Items Per Page"
-msgstr ""
+msgstr "Nombre maximum d'articles tableau de dictionnaire par page"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp
@@ -5467,85 +5413,75 @@ msgstr "Préréglage"
#: editor/editor_settings.cpp
msgid "Icon And Font Color"
-msgstr ""
+msgstr "Couleur de police et d'icône"
#: editor/editor_settings.cpp
msgid "Base Color"
msgstr "Couleur de Base"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Accent Color"
-msgstr "Prélever une couleur"
+msgstr "Couleur d'accentuation"
#: editor/editor_settings.cpp scene/resources/environment.cpp
msgid "Contrast"
-msgstr ""
+msgstr "Contraste"
#: editor/editor_settings.cpp
msgid "Relationship Line Opacity"
-msgstr ""
+msgstr "Opacité des lignes de relation"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Highlight Tabs"
-msgstr "Enregistrement des lightmaps"
+msgstr "Surligner les onglets"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Border Size"
-msgstr "Pixels de bordure"
+msgstr "Taille de bordure"
#: editor/editor_settings.cpp
msgid "Use Graph Node Headers"
-msgstr ""
+msgstr "Utiliser les en-têtes de graphes des nœuds"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Additional Spacing"
-msgstr "Bouclage de l’animation"
+msgstr "Espacement supplémentaire"
#: editor/editor_settings.cpp
msgid "Custom Theme"
msgstr "Thème Personnalisé"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Script Button"
-msgstr "Molette bouton droit"
+msgstr "Afficher le bouton script"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Directories"
-msgstr "Directions"
+msgstr "Dossiers"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Autoscan Project Path"
-msgstr "Chemin du projet :"
+msgstr "Scan auto du chemin du projet"
#: editor/editor_settings.cpp
msgid "Default Project Path"
msgstr "Chemin du Projet par Défaut"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "On Save"
-msgstr "Enregistrer"
+msgstr "À l'enregistrement"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Compress Binary Resources"
-msgstr "Copier la ressource"
+msgstr "Compresser les ressources binaires"
#: editor/editor_settings.cpp
msgid "Safe Save On Backup Then Rename"
-msgstr ""
+msgstr "Sauvegarde sécurisée lors de l'archivage avant de renommer"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "File Dialog"
-msgstr "Dialogue XForm"
+msgstr "Fenêtre de sélection de fichiers"
#: editor/editor_settings.cpp
msgid "Thumbnail Size"
@@ -5553,7 +5489,7 @@ msgstr "Taille de la vignette"
#: editor/editor_settings.cpp
msgid "Docks"
-msgstr ""
+msgstr "S'attache"
#: editor/editor_settings.cpp
msgid "Scene Tree"
@@ -5561,12 +5497,11 @@ msgstr "une arborescence, arbre des scènes"
#: editor/editor_settings.cpp
msgid "Start Create Dialog Fully Expanded"
-msgstr ""
+msgstr "Lancer le dialogue de création complètement déplié"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Always Show Folders"
-msgstr "Toujours afficher la grille"
+msgstr "Toujours afficher les dossiers"
#: editor/editor_settings.cpp
msgid "Property Editor"
@@ -5574,69 +5509,61 @@ msgstr "Éditeur de Propriétés"
#: editor/editor_settings.cpp
msgid "Auto Refresh Interval"
-msgstr ""
+msgstr "Intervalle d’autorafraîchissement"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Subresource Hue Tint"
-msgstr "Ressources secondaires"
+msgstr "Teinte des sous-ressources"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Color Theme"
-msgstr "Thème de l'éditeur"
+msgstr "Thème de couleurs"
#: editor/editor_settings.cpp scene/3d/label_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Line Spacing"
-msgstr ""
+msgstr "Espace entre les lignes"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
#: modules/gdscript/editor/gdscript_highlighter.cpp
-#, fuzzy
msgid "Highlighting"
-msgstr "Éclairage direct"
+msgstr "Surlignage"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Syntax Highlighting"
msgstr "Coloration syntaxique"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Highlight All Occurrences"
-msgstr ""
+msgstr "Mettre en évidence toutes les occurrences"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Highlight Current Line"
-msgstr ""
+msgstr "Mettre en évidence la ligne actuelle"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
msgid "Highlight Type Safe Lines"
-msgstr ""
+msgstr "Surligner les lignes à types sûrs"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Indent"
-msgstr "Indenter vers la gauche"
+msgstr "Indenter"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
msgid "Auto Indent"
msgstr "Indentation automatique"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Convert Indent On Save"
-msgstr "Convertir indentations en espaces"
+msgstr "Convertir les indentations à l'enregistrement"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Draw Tabs"
-msgstr "Appels de dessin :"
+msgstr "Montrer les tabulations"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Draw Spaces"
-msgstr "Appels de dessin :"
+msgstr "Afficher les espaces"
#: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/tile_map.cpp
@@ -5647,70 +5574,75 @@ msgstr "Navigation"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Smooth Scrolling"
-msgstr ""
+msgstr "Défilement Doux"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "V Scroll Speed"
-msgstr ""
+msgstr "Vitesse du défilement vertical"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Minimap"
-msgstr "Afficher l'origine"
+msgstr "Afficher la minimap"
#: editor/editor_settings.cpp
msgid "Minimap Width"
-msgstr ""
+msgstr "Largeur de la mini-carte"
#: editor/editor_settings.cpp
msgid "Mouse Extra Buttons Navigate History"
-msgstr ""
+msgstr "Boutons additionnels de la souris déplacent dans l'historique"
+
+#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr "Sélection glisser/déposer"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr "Rester sur l’éditeur de script en sélectionnant un nœud"
#: editor/editor_settings.cpp
msgid "Appearance"
-msgstr ""
+msgstr "Apparence"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Show Line Numbers"
msgstr "Afficher les Numéros de Ligne"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Line Numbers Zero Padded"
-msgstr "Numéro de ligne :"
+msgstr "Numéros de lignes avec remplissage en zéros"
#: editor/editor_settings.cpp
msgid "Show Bookmark Gutter"
-msgstr ""
+msgstr "Montrer le bandeau de marque-page"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Breakpoint Gutter"
-msgstr "Passer les points d'arrêt"
+msgstr "Afficher le bandeau de points d’arrêt"
#: editor/editor_settings.cpp
msgid "Show Info Gutter"
-msgstr ""
+msgstr "Montrer le bandeau d'information"
#: editor/editor_settings.cpp
msgid "Code Folding"
-msgstr ""
+msgstr "Rétrécir le code"
#: editor/editor_settings.cpp
msgid "Word Wrap"
-msgstr ""
+msgstr "Retour à la ligne des mots"
#: editor/editor_settings.cpp
msgid "Show Line Length Guidelines"
-msgstr ""
+msgstr "Montrer les guides de longueur de ligne"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Soft Column"
-msgstr ""
+msgstr "Colonne douce des guides de longueur de ligne"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Hard Column"
-msgstr ""
+msgstr "Colonne dure des guides de longueur de ligne"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
msgid "Script List"
@@ -5718,66 +5650,64 @@ msgstr "Liste des Scripts"
#: editor/editor_settings.cpp
msgid "Show Members Overview"
-msgstr ""
+msgstr "Montrer l'ensemble des Membres"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
msgid "Files"
msgstr "Fichiers"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Trim Trailing Whitespace On Save"
-msgstr "Supprimer les espaces de fin de ligne"
+msgstr "Retirer les espaces de fin de ligne à l'enregistrement"
#: editor/editor_settings.cpp
msgid "Autosave Interval Secs"
-msgstr ""
+msgstr "Intervalle entre les sauvegardes automatiques (en secondes)"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
msgid "Restore Scripts On Load"
-msgstr ""
+msgstr "Restaurer les scripts au chargement"
#: editor/editor_settings.cpp
msgid "Auto Reload And Parse Scripts On Save"
msgstr ""
+"Recharger et parcourir les scripts automatiquement lors de la sauvegarde"
#: editor/editor_settings.cpp
msgid "Auto Reload Scripts On External Change"
-msgstr ""
+msgstr "Recharger automatiquement les scripts sur changement externe"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Create Signal Callbacks"
-msgstr "Forcer les replis du shader"
+msgstr "Créer des rappels de signaux"
#: editor/editor_settings.cpp
msgid "Sort Members Outline Alphabetically"
-msgstr ""
+msgstr "Trier le contour des membres alphabétiquement"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Cursor"
-msgstr ""
+msgstr "Curseur"
#: editor/editor_settings.cpp
msgid "Scroll Past End Of File"
-msgstr ""
+msgstr "Défiler au-delà de la fin du fichier"
#: editor/editor_settings.cpp
msgid "Block Caret"
-msgstr ""
+msgstr "Caret bloc"
#: editor/editor_settings.cpp
msgid "Caret Blink"
-msgstr ""
+msgstr "Clignotement du caret"
#: editor/editor_settings.cpp
msgid "Caret Blink Speed"
-msgstr ""
+msgstr "Vitesse du clignotement du caret"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Right Click Moves Caret"
-msgstr "Clic droit pour ajouter un point"
+msgstr "Clic droit déplace le caret"
#: editor/editor_settings.cpp modules/gdscript/gdscript.cpp
#: modules/gdscript/gdscript_editor.cpp
@@ -5791,39 +5721,35 @@ msgstr ""
#: editor/editor_settings.cpp
msgid "Auto Brace Complete"
-msgstr ""
+msgstr "Complétion automatique des accolades"
#: editor/editor_settings.cpp
msgid "Code Complete Delay"
-msgstr ""
+msgstr "Délai d'auto-complétion du code"
#: editor/editor_settings.cpp
msgid "Put Callhint Tooltip Below Current Line"
-msgstr ""
+msgstr "Placer l'info-bulle d'appel sous la ligne actuelle"
#: editor/editor_settings.cpp
msgid "Callhint Tooltip Offset"
-msgstr ""
+msgstr "Décalage des info-bulles d'appel"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Complete File Paths"
-msgstr "Copier le chemin du nœud"
+msgstr "Compléter les chemins de fichiers"
#: editor/editor_settings.cpp modules/gdscript/gdscript_editor.cpp
-#, fuzzy
msgid "Add Type Hints"
-msgstr "Ajouter un type"
+msgstr "Ajouter des indices de type"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Use Single Quotes"
-msgstr "Nouvelle Simple Tuile"
+msgstr "Utiliser des simples guillemets"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Help Index"
-msgstr "Afficher les aides"
+msgstr "Afficher l'index d'aide"
#: editor/editor_settings.cpp
msgid "Help Font Size"
@@ -5835,16 +5761,15 @@ msgstr "Taille de la police de l'aide de la source"
#: editor/editor_settings.cpp
msgid "Help Title Font Size"
-msgstr ""
+msgstr "Taille de la police du titre Aide"
#: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp
msgid "Grid Map"
msgstr "Grille"
#: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance"
-msgstr "Choisissez distance :"
+msgstr "Choisissez la distance"
#: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Preview Size"
@@ -5852,39 +5777,34 @@ msgstr "Aperçu de la taille"
#: editor/editor_settings.cpp
msgid "Primary Grid Color"
-msgstr ""
+msgstr "Couleur de la grille principale"
#: editor/editor_settings.cpp
msgid "Secondary Grid Color"
-msgstr ""
+msgstr "Couleur de la grille secondaire"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Selection Box Color"
-msgstr "Sélection uniquement"
+msgstr "Couleur de la boîte de sélection"
#: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
-#, fuzzy
msgid "3D Gizmos"
-msgstr "Gadgets"
+msgstr "Manipulateurs 3D"
#: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
-#, fuzzy
msgid "Gizmo Colors"
-msgstr "Couleurs d'émission"
+msgstr "Couleurs des manipulateurs"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Instanced"
-msgstr "Instance"
+msgstr "Instancié"
#: editor/editor_settings.cpp modules/gltf/gltf_node.cpp
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Joint"
-msgstr "Point"
+msgstr "Jointure"
#: editor/editor_settings.cpp scene/2d/collision_shape_2d.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/touch_screen_button.cpp
@@ -5893,12 +5813,11 @@ msgstr "Point"
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
msgid "Shape"
-msgstr ""
+msgstr "Forme"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Primary Grid Steps"
-msgstr "Pas de la grille :"
+msgstr "Pas de la grille principale"
#: editor/editor_settings.cpp
msgid "Grid Size"
@@ -5906,63 +5825,55 @@ msgstr "Taille de la Grille"
#: editor/editor_settings.cpp
msgid "Grid Division Level Max"
-msgstr ""
+msgstr "Niveau maximal de division de la grille"
#: editor/editor_settings.cpp
msgid "Grid Division Level Min"
-msgstr ""
+msgstr "Niveau minimal de division de la grille"
#: editor/editor_settings.cpp
msgid "Grid Division Level Bias"
-msgstr ""
+msgstr "Niveau de biais de la division de grille"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid XZ Plane"
-msgstr "Peinture GridMap"
+msgstr "Plan XZ de la grille"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid XY Plane"
-msgstr "Peinture GridMap"
+msgstr "Plan XY de la grille"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid YZ Plane"
-msgstr "Peinture GridMap"
+msgstr "Plan YZ de la grille"
#: editor/editor_settings.cpp
msgid "Default FOV"
msgstr "FOV par défaut"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Z Near"
-msgstr "Thème par défaut"
+msgstr "Z proche par défaut"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Z Far"
-msgstr "Défaut"
+msgstr "Z distant par défaut"
#: editor/editor_settings.cpp
msgid "Lightmap Baking Number Of CPU Threads"
-msgstr ""
+msgstr "Nombre de fils CPU pour calculer les cartes de lumières"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Navigation Scheme"
-msgstr "Mode Navigation"
+msgstr "Schéma de navigation"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Invert Y Axis"
-msgstr "Modifier l'axe Y"
+msgstr "Inverser l'axe Y"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Invert X Axis"
-msgstr "Modifier l'axe X"
+msgstr "Inverser l'axe X"
#: editor/editor_settings.cpp
msgid "Zoom Style"
@@ -5970,26 +5881,23 @@ msgstr "Style de Zoom"
#: editor/editor_settings.cpp
msgid "Emulate Numpad"
-msgstr ""
+msgstr "Émuler un pavé numérique"
#: editor/editor_settings.cpp
msgid "Emulate 3 Button Mouse"
-msgstr ""
+msgstr "Émuler souris à 3 boutons"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Orbit Modifier"
-msgstr "Trier par date de modification (moins récent au plus récent)"
+msgstr "Modificateur d'orbite"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Pan Modifier"
-msgstr "Mode navigation"
+msgstr "Modificateur panoramique"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Zoom Modifier"
-msgstr "Modifié"
+msgstr "Multiplicateur de Zoom"
#: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp
msgid "Warped Mouse Panning"
@@ -6002,11 +5910,11 @@ msgstr "Mode Navigation"
#: editor/editor_settings.cpp
msgid "Orbit Sensitivity"
-msgstr ""
+msgstr "Sensibilité de l'orbite"
#: editor/editor_settings.cpp
msgid "Orbit Inertia"
-msgstr ""
+msgstr "Inertie de l'orbite"
#: editor/editor_settings.cpp
msgid "Translation Inertia"
@@ -6017,155 +5925,136 @@ msgid "Zoom Inertia"
msgstr "Inertie du Zoom"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook"
-msgstr "Vue libre haut"
+msgstr "Vue libre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Navigation Scheme"
-msgstr "Créer un maillage de navigation"
+msgstr "Schéma de navigation en vue libre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Sensitivity"
-msgstr "Vue libre gauche"
+msgstr "Sensibilité de la vue libre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Inertia"
-msgstr "Vue libre gauche"
+msgstr "Inertie de la vue libre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Base Speed"
-msgstr "Modificateur de vitesse de la vue libre"
+msgstr "Vitesse de base de la vue libre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Activation Modifier"
-msgstr "Ralentissement de la vue libre"
+msgstr "Modificateur d'activation de la vue libre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Speed Zoom Link"
-msgstr "Modificateur de vitesse de la vue libre"
+msgstr "Lien de zoom rapide de la vue libre"
#: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Grid Color"
msgstr "Couleur de la Grille"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Guides Color"
-msgstr "Prélever une couleur"
+msgstr "Couleur des guides"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Smart Snapping Line Color"
-msgstr "Magnétisme intelligent"
+msgstr "Couleur de ligne du magnétisme intelligent"
#: editor/editor_settings.cpp
msgid "Bone Width"
-msgstr ""
+msgstr "Largeur des os"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Color 1"
-msgstr "Renommer l'item de couleur"
+msgstr "Couleur d'os 1"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Color 2"
-msgstr "Renommer l'item de couleur"
+msgstr "Couleur d'os 2"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Selected Color"
-msgstr "Configurer le profil sélectionné :"
+msgstr "Couleur de l'os sélectionnée"
#: editor/editor_settings.cpp
msgid "Bone IK Color"
-msgstr ""
+msgstr "Couleur de cinématique inverse d'os"
#: editor/editor_settings.cpp
msgid "Bone Outline Color"
-msgstr ""
+msgstr "Couleur de contour d'os"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Outline Size"
-msgstr "Taille du contour :"
+msgstr "Taille du contour de l'os"
#: editor/editor_settings.cpp
msgid "Viewport Border Color"
-msgstr ""
+msgstr "Couleur de bordure de la fenêtre d'affichage"
#: editor/editor_settings.cpp
msgid "Constrain Editor View"
-msgstr ""
+msgstr "Restreindre la fenêtre d'Éditeur"
#: editor/editor_settings.cpp
msgid "Simple Panning"
-msgstr ""
+msgstr "Panoramique simple"
#: editor/editor_settings.cpp
msgid "Scroll To Pan"
-msgstr ""
+msgstr "Panoramique au défilement"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Pan Speed"
msgstr "Vitesse Panoramique"
#: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Poly Editor"
-msgstr "Éditeur UV de polygones 2D"
+msgstr "Éditeur de polygones"
#: editor/editor_settings.cpp
msgid "Point Grab Radius"
-msgstr ""
+msgstr "Rayon de saisie par point"
#: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Show Previous Outline"
-msgstr "Plan précédent"
+msgstr "Montrer le contour précédent"
#: editor/editor_settings.cpp editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Autorename Animation Tracks"
-msgstr "Renommer l'animation"
+msgstr "Renommer les pistes d'animation automatiquement"
#: editor/editor_settings.cpp
msgid "Default Create Bezier Tracks"
-msgstr ""
+msgstr "Créer pistes de Bézier par défaut"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Create Reset Tracks"
-msgstr "Créer des pistes RESET"
+msgstr "Créer pistes de réinitialisation par défaut"
#: editor/editor_settings.cpp
msgid "Onion Layers Past Color"
-msgstr ""
+msgstr "Couleur des couches d'oignon précedentes"
#: editor/editor_settings.cpp
msgid "Onion Layers Future Color"
-msgstr ""
+msgstr "Couleur des couches d'oignon suivantes"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Visual Editors"
-msgstr "Editeur de groupe"
+msgstr "Éditeurs visuels"
#: editor/editor_settings.cpp
msgid "Minimap Opacity"
-msgstr ""
+msgstr "Opacité de la mini-carte"
#: editor/editor_settings.cpp
msgid "Window Placement"
-msgstr ""
+msgstr "Placement de la fenêtre"
#: editor/editor_settings.cpp scene/2d/back_buffer_copy.cpp scene/2d/sprite.cpp
#: scene/2d/visibility_notifier_2d.cpp scene/3d/sprite_3d.cpp
@@ -6174,18 +6063,16 @@ msgid "Rect"
msgstr "Rect"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Rect Custom Position"
-msgstr "Définir la position de sortie de la courbe"
+msgstr "Position du Rect personnalisée"
#: editor/editor_settings.cpp platform/android/export/export_plugin.cpp
msgid "Screen"
-msgstr ""
+msgstr "Écran"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Auto Save"
-msgstr "Coupe automatique"
+msgstr "Sauvegarde auto"
#: editor/editor_settings.cpp
msgid "Save Before Running"
@@ -6202,28 +6089,26 @@ msgstr "Hôte distant"
#: editor/editor_settings.cpp
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Remote Port"
-msgstr "Supprimer un point"
+msgstr "Port distant"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Editor SSL Certificates"
-msgstr "Paramètres de l'éditeur"
+msgstr "Certificats SSL de l’éditeur"
#: editor/editor_settings.cpp
msgid "HTTP Proxy"
-msgstr ""
+msgstr "Proxy HTTP"
#: editor/editor_settings.cpp
msgid "Host"
-msgstr ""
+msgstr "Hôte"
#: editor/editor_settings.cpp editor/fileserver/editor_file_server.cpp
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Port"
-msgstr ""
+msgstr "Port"
#. TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects.
#: editor/editor_settings.cpp
@@ -6237,37 +6122,35 @@ msgstr "Ordre de Tri"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Symbol Color"
-msgstr ""
+msgstr "Couleur de symbole"
#: editor/editor_settings.cpp
msgid "Keyword Color"
-msgstr ""
+msgstr "Couleur des mots-clés"
#: editor/editor_settings.cpp
msgid "Control Flow Keyword Color"
-msgstr ""
+msgstr "Couleur de mot clé de contrôle de flux"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Type Color"
-msgstr "Changer le type de base"
+msgstr "Couleur de base des types"
#: editor/editor_settings.cpp
msgid "Engine Type Color"
-msgstr ""
+msgstr "Couleur de type du moteur"
#: editor/editor_settings.cpp
msgid "User Type Color"
-msgstr ""
+msgstr "Couleur de type utilisateur"
#: editor/editor_settings.cpp
msgid "Comment Color"
-msgstr ""
+msgstr "Couleur des commentaires"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "String Color"
-msgstr "Stockage du fichier :"
+msgstr "Couleur des chaînes de caractères"
#: editor/editor_settings.cpp platform/javascript/export/export.cpp
#: platform/uwp/export/export.cpp
@@ -6276,9 +6159,8 @@ msgid "Background Color"
msgstr "Couleur d’Arrière-Plan"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Completion Background Color"
-msgstr "Couleur de fond invalide."
+msgstr "Couleur d'arrière-plan de complétion"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -6306,23 +6188,20 @@ msgid "Line Number Color"
msgstr "Couleur du Numéro de Ligne"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Safe Line Number Color"
-msgstr "Numéro de ligne :"
+msgstr "Couleur des nombres des lignes sûres"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Caret Color"
-msgstr ""
+msgstr "Couleur du caret"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Caret Background Color"
-msgstr "Couleur de fond invalide."
+msgstr "Couleur d'arrière-plan de caret"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Text Selected Color"
-msgstr "Supprimer la selection"
+msgstr "Couleur de texte sélectionné"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Selection Color"
@@ -6330,7 +6209,7 @@ msgstr "Couleur de la Sélection"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Brace Mismatch Color"
-msgstr ""
+msgstr "Couleur des erreur de fermeture d'accolades"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Current Line Color"
@@ -6338,26 +6217,23 @@ msgstr "Couleur de la Ligne Actuelle"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Color"
-msgstr ""
+msgstr "Couleur du guide de longueur de ligne"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Word Highlighted Color"
-msgstr "Coloration syntaxique"
+msgstr "Couleur de surlignage des mots"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Number Color"
-msgstr ""
+msgstr "Couleur des nombres"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Function Color"
-msgstr "Fonction"
+msgstr "Couleur des fonctions"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Member Variable Color"
-msgstr "Renommer la variable"
+msgstr "Couleur des variables de membres"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -6365,32 +6241,28 @@ msgid "Mark Color"
msgstr "Prélever une couleur"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Bookmark Color"
-msgstr "Signets"
+msgstr "Couleur des signets"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Breakpoint Color"
-msgstr "Point d'arrêts"
+msgstr "Couleur des point d'arrêts"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Executing Line Color"
-msgstr ""
+msgstr "Couleur de la ligne d’exécution"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Code Folding Color"
-msgstr ""
+msgstr "Couleur du repliage de code"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Search Result Color"
-msgstr "Résultats de recherche"
+msgstr "Couleur des résultats de recherche"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Search Result Border Color"
-msgstr "Résultats de recherche"
+msgstr "Couleur de bordure des résultats de recherche"
#: editor/editor_spin_slider.cpp
msgid "Hold %s to round to integers. Hold Shift for more precise changes."
@@ -6403,9 +6275,8 @@ msgid "Flat"
msgstr "Plat"
#: editor/editor_spin_slider.cpp
-#, fuzzy
msgid "Hide Slider"
-msgstr "Mode collision"
+msgstr "Cacher la barre de défilement"
#: editor/editor_sub_scene.cpp
msgid "Select Node(s) to Import"
@@ -6704,7 +6575,7 @@ msgstr ""
#: editor/fileserver/editor_file_server.cpp
msgid "File Server"
-msgstr ""
+msgstr "Serveur de fichiers"
#: editor/fileserver/editor_file_server.cpp
#: editor/plugins/version_control_editor_plugin.cpp
@@ -7077,11 +6948,11 @@ msgstr "Gérer les groupes"
#: editor/import/editor_import_collada.cpp
msgid "Collada"
-msgstr ""
+msgstr "Collada"
#: editor/import/editor_import_collada.cpp
msgid "Use Ambient"
-msgstr ""
+msgstr "Utiliser ambiant"
#: editor/import/resource_importer_bitmask.cpp
msgid "Create From"
@@ -7090,7 +6961,7 @@ msgstr "Créer à Partir de"
#: editor/import/resource_importer_bitmask.cpp
#: servers/audio/effects/audio_effect_compressor.cpp
msgid "Threshold"
-msgstr ""
+msgstr "Seuil"
#: editor/import/resource_importer_csv_translation.cpp
#: editor/import/resource_importer_layered_texture.cpp
@@ -7102,7 +6973,7 @@ msgstr "Compresser"
#: editor/import/resource_importer_csv_translation.cpp
msgid "Delimiter"
-msgstr ""
+msgstr "Délimiteur"
#: editor/import/resource_importer_layered_texture.cpp
#, fuzzy
@@ -7111,7 +6982,7 @@ msgstr "Correction de Couleur"
#: editor/import/resource_importer_layered_texture.cpp
msgid "No BPTC If RGB"
-msgstr ""
+msgstr "Pas de BPTC si RVB"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp scene/2d/cpu_particles_2d.cpp
@@ -7119,13 +6990,13 @@ msgstr ""
#: scene/resources/material.cpp scene/resources/particles_material.cpp
#: scene/resources/texture.cpp scene/resources/visual_shader.cpp
msgid "Flags"
-msgstr ""
+msgstr "Paramètres"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp scene/animation/tween.cpp
#: scene/resources/texture.cpp
msgid "Repeat"
-msgstr ""
+msgstr "Répéter"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp scene/2d/light_2d.cpp
@@ -7135,24 +7006,22 @@ msgstr "Filtre"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Mipmaps"
-msgstr "Signaux"
+msgstr "Mipmaps"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
msgid "Anisotropic"
-msgstr ""
+msgstr "Anisotrope"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
msgid "sRGB"
-msgstr ""
+msgstr "sRGB"
#: editor/import/resource_importer_layered_texture.cpp
-#, fuzzy
msgid "Slices"
-msgstr "Coupe automatique"
+msgstr "Tranches"
#: editor/import/resource_importer_layered_texture.cpp
#: scene/gui/aspect_ratio_container.cpp scene/gui/control.cpp
@@ -7169,30 +7038,25 @@ msgid "Vertical"
msgstr "Vertical"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Generate Tangents"
-msgstr "Générer des points"
+msgstr "Générer les tangentes"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Scale Mesh"
-msgstr "Mode mise à l'échelle"
+msgstr "Échelle du maillage"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Offset Mesh"
-msgstr "Décalage :"
+msgstr "Décalage du maillage"
#: editor/import/resource_importer_obj.cpp
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Octahedral Compression"
-msgstr "Expression"
+msgstr "Compression Octaédrique"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Optimize Mesh Flags"
-msgstr "Optimiser les drapeaux de Mesh"
+msgstr "Optimiser les paramètres du maillage"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Single Scene"
@@ -7248,9 +7112,8 @@ msgid "Root Name"
msgstr "Nom de la Racine"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Scale"
-msgstr "Mode mise à l'échelle"
+msgstr "Échelle de la racine"
#: editor/import/resource_importer_scene.cpp
msgid "Custom Script"
@@ -7262,16 +7125,15 @@ msgstr "Stockage"
#: editor/import/resource_importer_scene.cpp
msgid "Use Legacy Names"
-msgstr ""
+msgstr "Utiliser les noms hérités"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
msgid "Materials"
msgstr "Matériaux"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep On Reimport"
-msgstr "Réimporter"
+msgstr "Conserver à la réimportation"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
msgid "Meshes"
@@ -7283,47 +7145,40 @@ msgid "Ensure Tangents"
msgstr "Modifier la tangente de courbes"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Light Baking"
-msgstr "Précalculer les lightmaps"
+msgstr "Pré-calculer les lumières"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Lightmap Texel Size"
-msgstr "LightMap Bake"
+msgstr "Taille des Texels dans la carte de lumières"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
msgid "Skins"
-msgstr ""
+msgstr "Enveloppes"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Use Named Skins"
-msgstr "Utiliser le magnétisme d'échelle"
+msgstr "Utiliser les enveloppes nommées"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "External Files"
-msgstr "Ouvrir un fichier"
+msgstr "Fichiers externes"
#: editor/import/resource_importer_scene.cpp
msgid "Store In Subdir"
-msgstr ""
+msgstr "Stocker dans un sous-dossier"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Filter Script"
msgstr "Filtrer les scripts"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep Custom Tracks"
-msgstr "Transformation"
+msgstr "Conserver les pistes personnalisées"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Optimizer"
-msgstr "Optimiser"
+msgstr "Optimiseur"
#: editor/import/resource_importer_scene.cpp
#: editor/plugins/item_list_editor_plugin.cpp main/main.cpp
@@ -7337,9 +7192,8 @@ msgstr "Optimiser"
#: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp
#: scene/gui/rich_text_label.cpp scene/resources/curve.cpp
#: scene/resources/environment.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Enabled"
-msgstr "Activer"
+msgstr "Activé"
#: editor/import/resource_importer_scene.cpp
msgid "Max Linear Error"
@@ -7350,17 +7204,14 @@ msgid "Max Angular Error"
msgstr "Erreur Angulaire Max"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Max Angle"
-msgstr "Valeur"
+msgstr "Angle maximal"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Remove Unused Tracks"
-msgstr "Supprimer la piste d’animation"
+msgstr "Retirer les pistes inutilisées"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Clips"
msgstr "Clips d'animation"
@@ -7417,89 +7268,90 @@ 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 : La texture a été utilisé comme carte de normales dans la 3D. Activation "
+"de la compression rouge-verte pour réduire l'utilisation de la mémoire (le "
+"canal bleu est désactivé)."
#: 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 : La texture a été détecter comme étant utilisé dans la 3D. Activation du "
+"filtrage, de la répétition, de la génération de mipmap et de la compression "
+"de la texture dans la mémoire vidéo."
#: editor/import/resource_importer_texture.cpp
msgid "2D, Detect 3D"
-msgstr ""
+msgstr "2D, Détecter la 3D"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "2D Pixel"
-msgstr "Pixels pleins"
+msgstr "Pixel 2D"
#: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp
msgid "Lossy Quality"
-msgstr ""
+msgstr "Mauvaise qualité"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "HDR Mode"
-msgstr "Mode sélection"
+msgstr "Mode HDR"
#: editor/import/resource_importer_texture.cpp
msgid "BPTC LDR"
-msgstr ""
+msgstr "BPTC LDR"
#: editor/import/resource_importer_texture.cpp
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/mesh_instance_2d.cpp scene/2d/multimesh_instance_2d.cpp
#: scene/2d/particles_2d.cpp scene/2d/sprite.cpp scene/resources/style_box.cpp
msgid "Normal Map"
-msgstr ""
+msgstr "Carte de normales"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Process"
-msgstr "Post-traitement"
+msgstr "Processus"
#: editor/import/resource_importer_texture.cpp
msgid "Fix Alpha Border"
-msgstr ""
+msgstr "Corriger la bordure alpha"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Premult Alpha"
-msgstr "Modifier le polygone"
+msgstr "Alpha pré-multiplié"
#: editor/import/resource_importer_texture.cpp
msgid "Hdr As Srgb"
-msgstr ""
+msgstr "Hdr en tant que Srgb"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Invert Color"
-msgstr "Vertex"
+msgstr "Inverser la couleur"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Normal Map Invert Y"
-msgstr "Échelle aléatoire :"
+msgstr "Inverser l'axe Y de la carte de normales"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Size Limit"
-msgstr "Limites"
+msgstr "Limite de taille"
#: editor/import/resource_importer_texture.cpp
msgid "Detect 3D"
-msgstr ""
+msgstr "Détecter la 3D"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "SVG"
-msgstr "HSV"
+msgstr "SVG"
#: editor/import/resource_importer_texture.cpp
msgid ""
"Warning, no suitable PC VRAM compression enabled in Project Settings. This "
"texture will not display correctly on PC."
msgstr ""
+"Attention, aucune compression de la mémoire vidéo qui aille sur PC n'est "
+"activé dans les paramètres du projet. Cette texture ne s'affichera pas "
+"correctement sur PC."
#: editor/import/resource_importer_texture_atlas.cpp
msgid "Atlas File"
@@ -7510,64 +7362,56 @@ msgid "Import Mode"
msgstr "Mode d'Importation"
#: editor/import/resource_importer_texture_atlas.cpp
-#, fuzzy
msgid "Crop To Region"
-msgstr "Définir la région de la tuile"
+msgstr "Rogner vers la région"
#: editor/import/resource_importer_texture_atlas.cpp
msgid "Trim Alpha Border From Region"
-msgstr ""
+msgstr "Rogner les bordures alpha de la région"
#: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp
-#, fuzzy
msgid "Force"
-msgstr "Force-pousser"
+msgstr "Force"
#: editor/import/resource_importer_wav.cpp
msgid "8 Bit"
-msgstr ""
+msgstr "8 Bit"
#: editor/import/resource_importer_wav.cpp main/main.cpp
#: modules/mono/editor/csharp_project.cpp modules/mono/mono_gd/gd_mono.cpp
msgid "Mono"
-msgstr ""
+msgstr "Mono"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate"
-msgstr "Mélanger le nœud"
+msgstr "Taux maximal"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate Hz"
-msgstr "Mélanger le nœud"
+msgstr "Taux maximal en Hz"
#: editor/import/resource_importer_wav.cpp
msgid "Trim"
-msgstr ""
+msgstr "Rogner"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Normalize"
-msgstr "Format"
+msgstr "Normaliser"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop Mode"
-msgstr "Mode déplacement"
+msgstr "Mode de bouclage"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop Begin"
-msgstr "Mode déplacement"
+msgstr "Début de la boucle"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop End"
-msgstr "Mode déplacement"
+msgstr "Fin de la boucle"
#: editor/import_defaults_editor.cpp
msgid "Select Importer"
@@ -7648,27 +7492,24 @@ msgid "Failed to load resource."
msgstr "Impossible de charger la ressource."
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Property Name Style"
-msgstr "Nom du projet :"
+msgstr "Style des noms de propriétés"
#: editor/inspector_dock.cpp scene/gui/color_picker.cpp
msgid "Raw"
msgstr "Brut"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Capitalized"
msgstr "Majuscule à chaque mot"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Localized"
-msgstr "Localisation"
+msgstr "Traduit"
#: editor/inspector_dock.cpp
msgid "Localization not available for current language."
-msgstr ""
+msgstr "La traduction n'est pas disponible pour la langue actuel."
#: editor/inspector_dock.cpp
msgid "Copy Properties"
@@ -8219,9 +8060,8 @@ msgid "New"
msgstr "Nouveau"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Paste As Reference"
-msgstr "Référence de classe %s"
+msgstr "Collé en tant que référence"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Edit Transitions..."
@@ -8473,7 +8313,7 @@ msgstr "Mélange 1 :"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
msgid "X-Fade Time (s):"
-msgstr "Durée du fondu (s) :"
+msgstr "Durée du fondu croisé (s) :"
#: editor/plugins/animation_tree_player_editor_plugin.cpp
#: editor/plugins/visual_shader_editor_plugin.cpp
@@ -8551,7 +8391,7 @@ msgstr "Filtres…"
#: editor/plugins/asset_library_editor_plugin.cpp scene/main/http_request.cpp
msgid "Use Threads"
-msgstr ""
+msgstr "Utiliser le multitâche"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Contents:"
@@ -8714,25 +8554,21 @@ msgid "Loading..."
msgstr "Chargement..."
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "First"
msgstr "Premier"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Previous"
msgstr "Précédent"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Next"
msgstr "Suivant"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Last"
msgstr "Dernier"
@@ -8783,7 +8619,7 @@ msgstr "En période de test"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed to get repository configuration."
-msgstr ""
+msgstr "N'a pas réussi à récupérer la configuration du dépôt."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Assets ZIP File"
@@ -9350,23 +9186,20 @@ msgid "View"
msgstr "Affichage"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show"
-msgstr "Afficher la grille"
+msgstr "Afficher"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show When Snapping"
-msgstr "Magnétisme intelligent"
+msgstr "Afficher lors de la magnétisation"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Hide"
-msgstr ""
+msgstr "Cacher"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Grid"
-msgstr "Basculer le mode"
+msgstr "Activer/Désactiver la grille"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/polygon_2d_editor_plugin.cpp
@@ -9718,16 +9551,15 @@ msgstr "Dégradé édité"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
msgid "Swap GradientTexture2D Fill Points"
-msgstr ""
+msgstr "Échanger les points de remplissage du GradientTexture2D"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
msgid "Swap Gradient Fill Points"
-msgstr ""
+msgstr "Échanger les points de remplissage du dégradé"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Grid Snap"
-msgstr "Basculer le mode"
+msgstr "Activer/Désactiver le magnétisme de la grille"
#: editor/plugins/item_list_editor_plugin.cpp editor/project_export.cpp
#: scene/3d/label_3d.cpp scene/gui/button.cpp scene/gui/dialogs.cpp
@@ -9746,13 +9578,12 @@ msgstr "Icône"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "ID"
-msgstr ""
+msgstr "ID"
#: editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Separator"
-msgstr "Séparation :"
+msgstr "Séparateur"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "Item %d"
@@ -9996,7 +9827,6 @@ msgstr ""
"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "MeshLibrary"
msgstr "Librairie de maillages"
@@ -10021,14 +9851,12 @@ msgid "Update from Scene"
msgstr "Mettre à jour depuis la scène"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply without Transforms"
-msgstr "Appliquer la transformation du MeshInstance"
+msgstr "Appliquer sans transformations"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply with Transforms"
-msgstr "Appliquer la transformation du MeshInstance"
+msgstr "Appliquer avec transformations"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "No mesh source specified (and no MultiMesh set in node)."
@@ -10559,7 +10387,7 @@ msgstr "Synchroniser les os avec le polygone"
#: editor/plugins/ray_cast_2d_editor_plugin.cpp
msgid "Set cast_to"
-msgstr ""
+msgstr "Définir cast_to"
#: editor/plugins/resource_preloader_editor_plugin.cpp
msgid "ERROR: Couldn't load resource!"
@@ -10890,57 +10718,51 @@ msgstr "Résultats de recherche"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Dominant Script On Scene Change"
-msgstr ""
+msgstr "Ouvrir le script principal lors du changement de scène"
#: editor/plugins/script_editor_plugin.cpp
msgid "External"
-msgstr ""
+msgstr "Externe"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Use External Editor"
-msgstr "Déboguer avec un éditeur externe"
+msgstr "Utiliser un éditeur externe"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Exec Path"
-msgstr "Chemin d'exportation"
+msgstr "Chemin d'exécution"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Script Temperature Enabled"
-msgstr "Sélectionner le fichier de modèles"
+msgstr "Température de script activée"
#: editor/plugins/script_editor_plugin.cpp
msgid "Highlight Current Script"
-msgstr ""
+msgstr "Mettre en évidence le script actuel"
#: editor/plugins/script_editor_plugin.cpp
msgid "Script Temperature History Size"
-msgstr ""
+msgstr "Taille de l'historique des températures de script"
#: editor/plugins/script_editor_plugin.cpp
msgid "Current Script Background Color"
msgstr "Couleur d'Arrière-Plan du Script Actuel"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Group Help Pages"
-msgstr "Groupe sélectionné"
+msgstr "Pages d'aide de groupe"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Sort Scripts By"
-msgstr "Créer un script"
+msgstr "Trier les scripts par"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "List Script Names As"
-msgstr "Nom du script :"
+msgstr "Lister les noms de scripts en tant que"
#: editor/plugins/script_editor_plugin.cpp
msgid "Exec Flags"
-msgstr ""
+msgstr "Paramètres d'exécution"
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Scripts"
@@ -11461,10 +11283,11 @@ msgid "(Not in GLES2)"
msgstr "(Non disponible dans GLES2)"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Debug draw modes are only available when using the GLES3 renderer, not GLES2."
-msgstr "Non disponible quand le moteur de rendu GLES2 est utilisé."
+msgstr ""
+"Les modes de rendu de débogage ne sont disponibles qu'avec le moteur GLES3, "
+"et pas GLES2."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -11760,16 +11583,15 @@ msgstr "Post"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Manipulator Gizmo Size"
-msgstr ""
+msgstr "Taille des manipulateurs"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Manipulator Gizmo Opacity"
-msgstr ""
+msgstr "Opacité des manipulateurs"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Show Viewport Rotation Gizmo"
-msgstr "Verrouiller la rotation de la vue"
+msgstr "Afficher le manipulateur de rotation dans le viewport"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Unnamed Gizmo"
@@ -11822,9 +11644,8 @@ msgid "Invalid geometry, can't replace by mesh."
msgstr "Géométrie invalide, impossible de remplacer par un maillage."
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Convert to MeshInstance2D"
-msgstr "Convertir en Mesh2D"
+msgstr "Convertir en MeshInstance2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create polygon."
@@ -11927,6 +11748,10 @@ msgid "New Animation"
msgstr "Nouvelle animation"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Filter animations"
+msgstr "Filtrer les animations"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Vitesse :"
@@ -12228,9 +12053,8 @@ msgstr ""
"Fermer tout de même ?"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Type"
-msgstr "Supprimer la tuile"
+msgstr "Supprimer le type"
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
@@ -12275,14 +12099,12 @@ msgstr ""
"thème."
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Add Theme Type"
-msgstr "Ajouter un item de type"
+msgstr "Ajouter un type de thème"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Theme Type"
-msgstr "Retirer le dépôt distant"
+msgstr "Supprimer un type de thème"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Color Item"
@@ -12399,9 +12221,8 @@ msgid "Select Another Theme Resource:"
msgstr "Sélectionnez une autre ressource Theme :"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Theme Resource"
-msgstr "Renommer une ressource"
+msgstr "Ressource de thème"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Another Theme"
@@ -12457,12 +12278,10 @@ msgid "Add Item Type"
msgstr "Ajouter un item de type"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Set Variation Base Type"
-msgstr "Définir type de variable"
+msgstr "Définir le type parent de la variation"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Set Base Type"
msgstr "Changer le type de base"
@@ -12486,12 +12305,16 @@ msgstr "Surcharge tous les items de type par défaut."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Select the variation base type from a list of available types."
msgstr ""
+"Choisissez le type parent de la variation depuis la liste des types "
+"disponibles."
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
"A type associated with a built-in class cannot be marked as a variation of "
"another type."
msgstr ""
+"Un type affilié à une classe intégrée ne peut pas être marqué comme variante "
+"d'un autre type."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Theme:"
@@ -12732,14 +12555,13 @@ msgid "Clear Transform"
msgstr "Supprimer la transformation"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Tile Map"
-msgstr "Peindre sur la TileMap"
+msgstr "Carte de Tuiles"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Palette Min Width"
-msgstr ""
+msgstr "Largeur minimale de la palette"
#: editor/plugins/tile_map_editor_plugin.cpp
#, fuzzy
@@ -12747,40 +12569,33 @@ msgid "Palette Item H Separation"
msgstr "Séparateur nommé"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Show Tile Names"
-msgstr "Afficher toutes les langues"
+msgstr "Afficher les noms des tuiles"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Show Tile Ids"
-msgstr "Afficher les règles"
+msgstr "Afficher les IDs des tuiles"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Sort Tiles By Name"
-msgstr "Trier les fichiers"
+msgstr "Trier les tuiles par nom"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill Preview"
-msgstr "Remplissage du seau"
+msgstr "Aperçu du remplissage"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Editor Side"
-msgstr "Éditeur"
+msgstr "Coté Éditeur"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Display Grid"
-msgstr "Affichage des surimpressions"
+msgstr "Afficher la grille"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Axis Color"
-msgstr "Prélever une couleur"
+msgstr "Couleur des axes"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Add Texture(s) to TileSet."
@@ -13119,7 +12934,6 @@ msgid "This property can't be changed."
msgstr "Cette propriété ne peut être changée."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Snap Options"
msgstr "Options de magnétisme"
@@ -13144,14 +12958,12 @@ msgstr "Pas"
#: editor/plugins/tile_set_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Separation"
-msgstr "Séparation :"
+msgstr "Séparation"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Tile"
-msgstr "Sélectionner"
+msgstr "Tuile sélectionné"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/light_2d.cpp scene/2d/line_2d.cpp scene/2d/mesh_instance_2d.cpp
@@ -13160,14 +12972,12 @@ msgstr "Sélectionner"
#: scene/gui/nine_patch_rect.cpp scene/gui/texture_rect.cpp
#: scene/resources/material.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Texture"
-msgstr "Texte"
+msgstr "Texture"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tex Offset"
-msgstr "Décalage d’Octet"
+msgstr "Décalage de texture"
#: editor/plugins/tile_set_editor_plugin.cpp modules/csg/csg_shape.cpp
#: scene/2d/canvas_item.cpp scene/2d/particles_2d.cpp
@@ -13177,79 +12987,64 @@ msgstr "Matériau"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/canvas_item.cpp
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Modulate"
-msgstr "Peupler"
+msgstr "Moduler"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tile Mode"
-msgstr "Basculer le mode"
+msgstr "Mode de tuile"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Autotile Bitmask Mode"
-msgstr "Mode Bitmask"
+msgstr "Mode de masque d'octet de tuile auto"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Size"
-msgstr "Taille de Contour"
+msgstr "Taille des sous-tuiles"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Spacing"
-msgstr "Bouclage de l’animation"
+msgstr "Espacement des sous-tuiles"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Occluder Offset"
-msgstr "Créer un polygone occulteur"
+msgstr "Décalage de l’occulteur"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Navigation Offset"
-msgstr "Mode Navigation"
+msgstr "Décalage de la navigation"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Shape Offset"
-msgstr "Décalage :"
+msgstr "Décalage de la forme"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Shape Transform"
-msgstr "Transformation"
+msgstr "Transformation de la forme"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision"
-msgstr "Collision"
+msgstr "Collision sélectionné"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision One Way"
-msgstr "Sélection uniquement"
+msgstr "Collision à sens unique de la sélection"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision One Way Margin"
-msgstr "Mode collision"
+msgstr "Marge de collision à sens unique de la sélection"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Navigation"
-msgstr "Navigation visible"
+msgstr "Navigation sélectionnée"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Occlusion"
-msgstr "Sélectionner"
+msgstr "Occultation de la sélection"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tileset Script"
-msgstr "Filtrer les scripts"
+msgstr "Script de palette de tuiles"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "TileSet"
@@ -14344,11 +14139,13 @@ msgstr "Exécutable"
#: editor/project_export.cpp
msgid "Export the project for all the presets defined."
-msgstr ""
+msgstr "Exporter le projet pour tous les préréglages définis."
#: editor/project_export.cpp
msgid "All presets must have an export path defined for Export All to work."
msgstr ""
+"Tous les préréglages doivent avoir un chemin d'exportation défini pour "
+"pouvoir tous les exportés."
#: editor/project_export.cpp
msgid "Delete preset '%s'?"
@@ -14461,53 +14258,48 @@ msgid ""
"Note: Encryption key needs to be stored in the binary,\n"
"you need to build the export templates from source."
msgstr ""
+"Note : La clé de cryptage doit être stocké dans le binaire,\n"
+"vous devez compiler les modèles d'exportation depuis les sources."
#: editor/project_export.cpp
-#, fuzzy
msgid "More Info..."
-msgstr "Déplacer vers…"
+msgstr "Plus d'informations..."
#: editor/project_export.cpp
-#, fuzzy
msgid "Export PCK/Zip..."
-msgstr "Exporter le PCK/ZIP"
+msgstr "Exporter le PCK/ZIP..."
#: editor/project_export.cpp
-#, fuzzy
msgid "Export Project..."
-msgstr "Exporter le projet"
+msgstr "Exporter le projet..."
#: editor/project_export.cpp
msgid "Export All"
msgstr "Tout exporter"
#: editor/project_export.cpp
-#, fuzzy
msgid "Choose an export mode:"
-msgstr "Veuillez choisir un dossier vide."
+msgstr "Choisissez un mode d'exportation :"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export All..."
-msgstr "Tout exporter"
+msgstr "Tout exporter..."
#: editor/project_export.cpp editor/project_manager.cpp
msgid "ZIP File"
msgstr "Fichier ZIP"
#: editor/project_export.cpp
-#, fuzzy
msgid "Godot Project Pack"
-msgstr "Archive Godot"
+msgstr "Pack de Projet Godot"
#: editor/project_export.cpp
msgid "Export templates for this platform are missing:"
msgstr "Modèles d'exportation manquants pour cette plateforme :"
#: editor/project_export.cpp
-#, fuzzy
msgid "Project Export"
-msgstr "Fondateurs du projet"
+msgstr "Exportation du projet"
#: editor/project_export.cpp
msgid "Manage Export Templates"
@@ -14825,7 +14617,6 @@ msgstr ""
#. TRANSLATORS: This refers to the application where users manage their Godot projects.
#: editor/project_manager.cpp
-#, fuzzy
msgctxt "Application"
msgid "Project Manager"
msgstr "Gestionnaire de projets"
@@ -15542,7 +15333,7 @@ msgstr "Supprimer le nœud \"%s\" et ses enfants ?"
#: editor/scene_tree_dock.cpp
msgid "Delete node \"%s\"?"
-msgstr "Supprimer le noeud \"%s\" ?"
+msgstr "Supprimer le nœud \"%s\" ?"
#: editor/scene_tree_dock.cpp
msgid ""
@@ -15634,17 +15425,15 @@ msgstr "Rendre local"
#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp
msgid "Another node already uses this unique name in the scene."
-msgstr ""
+msgstr "Un autre Nœud utilise ce nom unique dans la scène."
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Enable Scene Unique Name"
-msgstr "Nom unique"
+msgstr "Activer le nom unique de la scène"
#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Disable Scene Unique Name"
-msgstr "Nom unique"
+msgstr "Désactiver le nom unique de la scène"
#: editor/scene_tree_dock.cpp
msgid "New Scene Root"
@@ -15721,7 +15510,7 @@ msgstr "Ressources secondaires"
#: editor/scene_tree_dock.cpp
msgid "Access as Scene Unique Name"
-msgstr ""
+msgstr "Accéder en tant que nom unique de scène"
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
@@ -15821,18 +15610,16 @@ msgid "Clear Inheritance? (No Undo!)"
msgstr "Effacer l'héritage ? (Pas de retour en arrière !)"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Show Scene Tree Root Selection"
-msgstr "Centrer sur la sélection"
+msgstr "Afficher la sélection de la racine de la hiérarchie de la scène"
#: editor/scene_tree_dock.cpp
msgid "Derive Script Globals By Name"
-msgstr ""
+msgstr "Dériver les Globals de scripts par nom"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Use Favorites Root Selection"
-msgstr "Encadrer la sélection"
+msgstr "Utiliser la sélection racine des favoris"
#: editor/scene_tree_editor.cpp
msgid "Toggle Visible"
@@ -15860,6 +15647,9 @@ msgid ""
"with the '%s' prefix in a node path.\n"
"Click to disable this."
msgstr ""
+"Ce Nœud est accessible de n'importe où dans la scène en le préfixant de '%s' "
+"dans un chemin de Nœud.\n"
+"Cliquer pour désactiver cela."
#: editor/scene_tree_editor.cpp
msgid ""
@@ -16146,21 +15936,20 @@ msgid "Stack Frames"
msgstr "Pile des appels"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Filter stack variables"
-msgstr "Filtrer les tuiles"
+msgstr "Filtrer les variables de la pile"
#: editor/script_editor_debugger.cpp
msgid "Auto Switch To Remote Scene Tree"
-msgstr ""
+msgstr "Basculer automatiquement vers l'arborescence de scène distante"
#: editor/script_editor_debugger.cpp
msgid "Remote Scene Tree Refresh Interval"
-msgstr ""
+msgstr "Intervalle de rafraîchissement de l'arborescence distante"
#: editor/script_editor_debugger.cpp
msgid "Remote Inspect Refresh Interval"
-msgstr ""
+msgstr "Intervalle de rafraîchissement d'inspection distante"
#: editor/script_editor_debugger.cpp
msgid "Network Profiler"
@@ -16259,7 +16048,7 @@ msgstr "Changer le rayon d'une lumière"
#: editor/spatial_editor_gizmos.cpp
msgid "Stream Player 3D"
-msgstr ""
+msgstr "Émetteur de flux 3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
@@ -16269,7 +16058,7 @@ msgstr "Changer l'angle d'émission AudioStreamPlayer3D"
#: platform/osx/export/export.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Camera"
-msgstr ""
+msgstr "Caméra"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -16281,7 +16070,7 @@ msgstr "Changer la taille d'une caméra"
#: editor/spatial_editor_gizmos.cpp
msgid "Visibility Notifier"
-msgstr ""
+msgstr "Notifiant de visibilité"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Notifier AABB"
@@ -16292,23 +16081,20 @@ msgid "Change Particles AABB"
msgstr "Changer particules AABB"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Reflection Probe"
-msgstr "Sélectionnez une propriété"
+msgstr "Sonde de Réflexion"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Probe Extents"
msgstr "Changer les ampleurs de la sonde"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "GI Probe"
-msgstr "Créer sonde IG (Illumination Globale)"
+msgstr "Sonde GI"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Baked Indirect Light"
-msgstr "Éclairage indirect"
+msgstr "Éclairage indirect pré-calculé"
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
msgid "Change Sphere Shape Radius"
@@ -16339,57 +16125,52 @@ msgid "Change Ray Shape Length"
msgstr "Changer la longueur d'une forme en rayon"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Edge"
-msgstr "Mode Navigation"
+msgstr "Bord de la Navigation"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Edge Disabled"
-msgstr "Mode Navigation"
+msgstr "Bord de la Navigation Désactivé"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Solid"
-msgstr "Mode Navigation"
+msgstr "Solide de navigation"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Solid Disabled"
-msgstr "Mode Navigation"
+msgstr "Solide de navigation désactivé"
#: editor/spatial_editor_gizmos.cpp
msgid "Joint Body A"
-msgstr ""
+msgstr "Jointure Corps A"
#: editor/spatial_editor_gizmos.cpp
msgid "Joint Body B"
-msgstr ""
+msgstr "Jointure Corps B"
#: editor/spatial_editor_gizmos.cpp
msgid "Room Edge"
-msgstr ""
+msgstr "Bord de la pièce"
#: editor/spatial_editor_gizmos.cpp
msgid "Room Overlap"
-msgstr ""
+msgstr "Chevauchement de salle"
#: editor/spatial_editor_gizmos.cpp
msgid "Set Room Point Position"
msgstr "Définir la position du point de la pièce"
#: editor/spatial_editor_gizmos.cpp scene/3d/portal.cpp
-#, fuzzy
msgid "Portal Margin"
-msgstr "Définir la marge"
+msgstr "Marge du portail"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Edge"
-msgstr ""
+msgstr "Bords du portail"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Arrow"
-msgstr ""
+msgstr "Flèche de portail"
#: editor/spatial_editor_gizmos.cpp
msgid "Set Portal Point Position"
@@ -16397,18 +16178,16 @@ msgstr "Définir la position du point du Portal"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Front"
-msgstr ""
+msgstr "Avant du Portail"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Portal Back"
-msgstr "Retourner"
+msgstr "Arrière du Portail"
#: editor/spatial_editor_gizmos.cpp scene/2d/light_occluder_2d.cpp
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Occluder"
-msgstr "Mode Occlusion"
+msgstr "Occulteur"
#: editor/spatial_editor_gizmos.cpp
msgid "Set Occluder Sphere Radius"
@@ -16419,118 +16198,106 @@ msgid "Set Occluder Sphere Position"
msgstr "Définir la position de la sphère de l'occulteur"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Polygon Point Position"
-msgstr "Définir la position du point du Portal"
+msgstr "Définir la position ponctuelle du polygone occulteur"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Hole Point Position"
-msgstr "Définir la position du point de la courbe"
+msgstr "Définir la position ponctuelle du trou occulteur"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Polygon Front"
-msgstr "Créer un polygone occulteur"
+msgstr "Avant du polygone occulteur"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Polygon Back"
-msgstr "Créer un polygone occulteur"
+msgstr "Arrière du polygone occulteur"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Occluder Hole"
-msgstr "Créer un polygone occulteur"
+msgstr "Trou occulteur"
#: main/main.cpp
msgid "Godot Physics"
-msgstr ""
+msgstr "Calculs de physique de Godot"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
msgid "Use BVH"
-msgstr ""
+msgstr "Utiliser BVH"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
-#, fuzzy
msgid "BVH Collision Margin"
-msgstr "Mode collision"
+msgstr "Marge de collision BVH"
#: main/main.cpp
-#, fuzzy
msgid "Crash Handler"
-msgstr "Définir la poignée"
+msgstr "Gestionnaire de Crash"
#: main/main.cpp
-#, fuzzy
msgid "Multithreaded Server"
-msgstr "Ensemble multi-nœud"
+msgstr "Serveur à tâches parallèles"
#: main/main.cpp
msgid "RID Pool Prealloc"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Debugger stdout"
-msgstr "Débogueur"
+msgstr "Sortie standard du débogueur"
#: main/main.cpp
msgid "Max Chars Per Second"
-msgstr ""
+msgstr "Maximum de Caractères par seconde"
#: main/main.cpp
msgid "Max Messages Per Frame"
-msgstr ""
+msgstr "Maximum de messages par image"
#: main/main.cpp
msgid "Max Errors Per Second"
-msgstr ""
+msgstr "Maximum d'erreurs par seconde"
#: main/main.cpp
msgid "Max Warnings Per Second"
-msgstr ""
+msgstr "Maximum d'avertissements par secondes"
#: main/main.cpp
msgid "Flush stdout On Print"
-msgstr ""
+msgstr "Vider stdout à l'impression"
#: main/main.cpp servers/visual_server.cpp
msgid "Logging"
-msgstr ""
+msgstr "Journalisation"
#: main/main.cpp
msgid "File Logging"
-msgstr ""
+msgstr "Journalisation dans un fichier"
#: main/main.cpp
-#, fuzzy
msgid "Enable File Logging"
-msgstr "Activer le filtrage"
+msgstr "Activer la journalisation dans un fichier"
#: main/main.cpp
-#, fuzzy
msgid "Log Path"
-msgstr "Copier le chemin"
+msgstr "Chemin du Journal"
#: main/main.cpp
msgid "Max Log Files"
-msgstr ""
+msgstr "Maximum de fichiers journaux"
#: main/main.cpp
msgid "Driver"
-msgstr ""
+msgstr "Pilote"
#: main/main.cpp
-#, fuzzy
msgid "Driver Name"
-msgstr "Nom du script :"
+msgstr "Nom du Pilote"
#: main/main.cpp
msgid "Fallback To GLES2"
-msgstr ""
+msgstr "Se replier sur GLES2"
#: main/main.cpp
msgid "Use Nvidia Rect Flicker Workaround"
@@ -16538,52 +16305,47 @@ msgstr ""
#: main/main.cpp
msgid "DPI"
-msgstr ""
+msgstr "PPP"
#: main/main.cpp
msgid "Allow hiDPI"
-msgstr ""
+msgstr "Autoriser PPP élevé"
#: main/main.cpp
-#, fuzzy
msgid "V-Sync"
-msgstr "Synchroniser"
+msgstr "Synchronisation Vertical"
#: main/main.cpp
-#, fuzzy
msgid "Use V-Sync"
-msgstr "Utiliser l’aimantation"
+msgstr "Utiliser la Synchronisation Vertical"
#: main/main.cpp
msgid "Per Pixel Transparency"
-msgstr ""
+msgstr "Transparence par pixel"
#: main/main.cpp
msgid "Allowed"
-msgstr ""
+msgstr "Autorisé"
#: main/main.cpp
msgid "Intended Usage"
-msgstr ""
+msgstr "Usage prévu"
#: main/main.cpp
-#, fuzzy
msgid "Framebuffer Allocation"
-msgstr "Encadrer la sélection"
+msgstr "Allocation du tampon d'image (Framebuffer)"
#: main/main.cpp platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Energy Saving"
-msgstr "Erreur d'enregistrement"
+msgstr "Économie d'Énergie"
#: main/main.cpp
msgid "Threads"
-msgstr ""
+msgstr "Tâches Parallèles"
#: main/main.cpp servers/physics_2d/physics_2d_server_wrap_mt.h
-#, fuzzy
msgid "Thread Model"
-msgstr "Basculer le mode"
+msgstr "Modèle de Parallélisme"
#: main/main.cpp
msgid "Thread Safe BVH"
@@ -16591,29 +16353,25 @@ msgstr ""
#: main/main.cpp
msgid "Handheld"
-msgstr ""
+msgstr "Portable"
#: main/main.cpp platform/javascript/export/export.cpp
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Orientation"
-msgstr "Documentation en ligne"
+msgstr "Orientation"
#: main/main.cpp scene/gui/scroll_container.cpp scene/gui/text_edit.cpp
#: scene/main/scene_tree.cpp scene/register_scene_types.cpp
-#, fuzzy
msgid "Common"
-msgstr "Communauté"
+msgstr "Commun"
#: main/main.cpp
-#, fuzzy
msgid "Physics FPS"
-msgstr "Image physique %"
+msgstr "TPS de la physique"
#: main/main.cpp
-#, fuzzy
msgid "Force FPS"
-msgstr "Force-pousser"
+msgstr "Forces les trames par seconde"
#: main/main.cpp
msgid "Enable Pause Aware Picking"
@@ -16631,34 +16389,31 @@ msgstr ""
#: main/main.cpp
msgid "stdout"
-msgstr ""
+msgstr "Sortie Standard"
#: main/main.cpp
msgid "Print FPS"
-msgstr ""
+msgstr "Afficher les FPS"
#: main/main.cpp
msgid "Verbose stdout"
-msgstr ""
+msgstr "Détailler La Sortie Standard"
#: main/main.cpp scene/main/scene_tree.cpp scene/resources/multimesh.cpp
-#, fuzzy
msgid "Physics Interpolation"
-msgstr "Mode d’interpolation"
+msgstr "Interpolation de la physique"
#: main/main.cpp
-#, fuzzy
msgid "Enable Warnings"
-msgstr "Activer le filtrage"
+msgstr "Activer les avertissements"
#: main/main.cpp
-#, fuzzy
msgid "Frame Delay Msec"
-msgstr "Encadrer la sélection"
+msgstr "Délai des trames en millisecondes"
#: main/main.cpp
msgid "Low Processor Mode"
-msgstr ""
+msgstr "Mode Processeur Faible"
#: main/main.cpp
msgid "Delta Sync After Draw"
@@ -16666,90 +16421,81 @@ msgstr ""
#: main/main.cpp
msgid "iOS"
-msgstr ""
+msgstr "iOS"
#: main/main.cpp
msgid "Hide Home Indicator"
-msgstr ""
+msgstr "Masquer l'indicateur d’accueil"
#: main/main.cpp
-#, fuzzy
msgid "Input Devices"
-msgstr "Tous les périphérique"
+msgstr "Périphériques d'entrée"
#: main/main.cpp
-#, fuzzy
msgid "Pointing"
-msgstr "Point"
+msgstr "Pointage"
#: main/main.cpp
msgid "Touch Delay"
-msgstr ""
+msgstr "Retard d'appui"
#: main/main.cpp servers/visual_server.cpp
msgid "GLES3"
-msgstr ""
+msgstr "GLES3"
#: main/main.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Shaders"
-msgstr "Ombrage"
+msgstr "Shaders"
#: main/main.cpp
-#, fuzzy
msgid "Debug Shader Fallbacks"
-msgstr "Forcer les replis du shader"
+msgstr "Valeurs de repli du shader de débogage"
#: main/main.cpp scene/3d/baked_lightmap.cpp scene/3d/camera.cpp
#: scene/3d/world_environment.cpp scene/main/scene_tree.cpp
#: scene/resources/world.cpp
-#, fuzzy
msgid "Environment"
-msgstr "Voir environnement"
+msgstr "Environnement"
#: main/main.cpp
msgid "Default Clear Color"
-msgstr ""
+msgstr "Couleur d'effacement par défaut"
#: main/main.cpp
msgid "Boot Splash"
-msgstr ""
+msgstr "Écran de démarrage"
#: main/main.cpp
-#, fuzzy
msgid "Show Image"
-msgstr "Afficher les os"
+msgstr "Afficher l'image"
#: main/main.cpp
msgid "Image"
-msgstr ""
+msgstr "Image"
#: main/main.cpp
msgid "Fullsize"
-msgstr ""
+msgstr "Pleine taille"
#: main/main.cpp scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Use Filter"
-msgstr "Filtre :"
+msgstr "Utiliser le filtrage"
#: main/main.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "BG Color"
-msgstr "Couleurs"
+msgstr "Couleur d'arrière-plan"
#: main/main.cpp
-#, fuzzy
msgid "macOS Native Icon"
-msgstr "Définir l'icône de la tuile"
+msgstr "Icône native de macOS"
#: main/main.cpp
msgid "Windows Native Icon"
-msgstr ""
+msgstr "Icône native de Windows"
#: main/main.cpp
msgid "Buffering"
-msgstr ""
+msgstr "Mise en mémoire tampon"
#: main/main.cpp
msgid "Agile Event Flushing"
@@ -16757,40 +16503,35 @@ msgstr ""
#: main/main.cpp
msgid "Emulate Touch From Mouse"
-msgstr ""
+msgstr "Émuler le toucher tactile avec la souris"
#: main/main.cpp
msgid "Emulate Mouse From Touch"
-msgstr ""
+msgstr "Émuler la souris avec le toucher tactile"
#: main/main.cpp
-#, fuzzy
msgid "Mouse Cursor"
-msgstr "Bouton de souris"
+msgstr "Curseur de la souris"
#: main/main.cpp
-#, fuzzy
msgid "Custom Image"
-msgstr "Nœud Personnalisé"
+msgstr "Image personnalisée"
#: main/main.cpp
msgid "Custom Image Hotspot"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Tooltip Position Offset"
-msgstr "Décalage de la rotation :"
+msgstr "Décalage de la position des info-bulles"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
-#, fuzzy
msgid "Debugger Agent"
-msgstr "Débogueur"
+msgstr "Agent du débogueur"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
-#, fuzzy
msgid "Wait For Debugger"
-msgstr "Débogueur"
+msgstr "Attendre le débogueur"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
msgid "Wait Timeout"
@@ -16798,53 +16539,48 @@ msgstr "Délai d'Attente"
#: main/main.cpp
msgid "Runtime"
-msgstr ""
+msgstr "Exécution"
#: main/main.cpp
msgid "Unhandled Exception Policy"
-msgstr ""
+msgstr "Politique d'exceptions non gérées"
#: main/main.cpp
-#, fuzzy
msgid "Main Loop Type"
-msgstr "Rechercher le type de nœud"
+msgstr "Type de boucle principale"
#: main/main.cpp scene/gui/texture_progress.cpp
#: scene/gui/viewport_container.cpp
-#, fuzzy
msgid "Stretch"
-msgstr "Actualiser"
+msgstr "Étirement"
#: main/main.cpp
-#, fuzzy
msgid "Aspect"
-msgstr "Inspecteur"
+msgstr "Aspect"
#: main/main.cpp
msgid "Shrink"
-msgstr ""
+msgstr "Rétrécissement"
#: main/main.cpp scene/main/scene_tree.cpp
msgid "Auto Accept Quit"
-msgstr ""
+msgstr "Accepter automatiquement la fermeture"
#: main/main.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Quit On Go Back"
-msgstr "Retourner"
+msgstr "Quitter au retour"
#: main/main.cpp scene/main/viewport.cpp
-#, fuzzy
msgid "Snap Controls To Pixels"
-msgstr "Aimanter aux flancs du nœud"
+msgstr "Aimanter les contrôles aux pixels"
#: main/main.cpp
msgid "Dynamic Fonts"
-msgstr ""
+msgstr "Polices Dynamiques"
#: main/main.cpp
msgid "Use Oversampling"
-msgstr ""
+msgstr "Utiliser le suréchantillonnage"
#: modules/bullet/register_types.cpp modules/bullet/space_bullet.cpp
msgid "Active Soft World"
@@ -16871,35 +16607,30 @@ msgid "Change Torus Outer Radius"
msgstr "Changer le rayon extérieur de la tour"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Operation"
-msgstr "Options"
+msgstr "Opération"
#: modules/csg/csg_shape.cpp
msgid "Calculate Tangents"
-msgstr ""
+msgstr "Calculer les Tangentes"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Use Collision"
-msgstr "Collision"
+msgstr "Utiliser les collisions"
#: modules/csg/csg_shape.cpp servers/physics_2d_server.cpp
-#, fuzzy
msgid "Collision Layer"
-msgstr "Mode collision"
+msgstr "Couche des collisions"
#: modules/csg/csg_shape.cpp scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp
#: scene/3d/ray_cast.cpp scene/3d/spring_arm.cpp
#: scene/resources/navigation_mesh.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collision Mask"
-msgstr "Mode collision"
+msgstr "Masque de collisions"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Invert Faces"
-msgstr "Modifier la casse"
+msgstr "Inverses les faces"
#: modules/csg/csg_shape.cpp scene/2d/navigation_agent_2d.cpp
#: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_agent.cpp
@@ -16917,57 +16648,50 @@ msgid "Radial Segments"
msgstr "Segments radiaux"
#: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Rings"
-msgstr "Avertissements"
+msgstr "Anneaux"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Smooth Faces"
-msgstr "Progression douce"
+msgstr "Adoucir les faces"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Sides"
-msgstr "Afficher les guides"
+msgstr "Côtés"
#: modules/csg/csg_shape.cpp
msgid "Cone"
-msgstr ""
+msgstr "Cone"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Inner Radius"
-msgstr "Changer le rayon intérieur de la tour"
+msgstr "Rayon intérieur"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Outer Radius"
-msgstr "Changer le rayon extérieur de la tour"
+msgstr "Rayon extérieur"
#: modules/csg/csg_shape.cpp
msgid "Ring Sides"
-msgstr ""
+msgstr "Côtés de l'anneau"
#: modules/csg/csg_shape.cpp scene/2d/collision_polygon_2d.cpp
#: scene/2d/light_occluder_2d.cpp scene/2d/polygon_2d.cpp
#: scene/3d/collision_polygon.cpp
-#, fuzzy
msgid "Polygon"
-msgstr "Polygones"
+msgstr "Polygone"
#: modules/csg/csg_shape.cpp
msgid "Spin Degrees"
-msgstr ""
+msgstr "Degrés de tour"
#: modules/csg/csg_shape.cpp
msgid "Spin Sides"
-msgstr ""
+msgstr "Côtés du tour"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Node"
-msgstr "Coller les nœuds"
+msgstr "Noeud de chemin"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16976,106 +16700,92 @@ msgstr "Créer un vertex interne"
#: modules/csg/csg_shape.cpp
msgid "Path Interval"
-msgstr ""
+msgstr "Intervalle de chemin"
#: modules/csg/csg_shape.cpp
msgid "Path Simplify Angle"
-msgstr ""
+msgstr "Simplification d'angle de chemin"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Rotation"
-msgstr "Rotation aléatoire :"
+msgstr "Rotation du chemin"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Local"
-msgstr "Rendre local"
+msgstr "Chemin local"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Continuous U"
-msgstr "Continu"
+msgstr "Chemin Continu U"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path U Distance"
-msgstr "Choisissez distance :"
+msgstr "Distance du chemin U"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Joined"
-msgstr "Rotation aléatoire :"
+msgstr "Chemin joint"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Compression Mode"
-msgstr "Mode collision"
+msgstr "Mode de compression"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Transfer Channel"
-msgstr "Modification de la transformation"
+msgstr "Canal de transfert"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Channel Count"
-msgstr "Instance"
+msgstr "Nombre de canaux"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Always Ordered"
-msgstr "Toujours afficher la grille"
+msgstr "Toujours ordonnée"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "Server Relay"
-msgstr ""
+msgstr "Relais serveur"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "DTLS Verify"
-msgstr ""
+msgstr "Vérification DTLS"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "DTLS Hostname"
-msgstr ""
+msgstr "Nom de l'hôte DTLS"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Use DTLS"
-msgstr "Utiliser l’aimantation"
+msgstr "Utiliser DTLS"
#: modules/fbx/editor_scene_importer_fbx.cpp
msgid "FBX"
-msgstr ""
+msgstr "FBX"
#: modules/fbx/editor_scene_importer_fbx.cpp
msgid "Use FBX"
-msgstr ""
+msgstr "Utiliser FBX"
#: modules/gdnative/gdnative.cpp
msgid "Config File"
msgstr "Fichier de Configuration"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Load Once"
-msgstr "Charger une ressource"
+msgstr "Charger une fois"
#: modules/gdnative/gdnative.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Singleton"
-msgstr "Squelette"
+msgstr "Singleton"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Symbol Prefix"
-msgstr "Préfixe :"
+msgstr "Préfixe du symbole"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Reloadable"
-msgstr "Recharger"
+msgstr "Rechargeable"
#: modules/gdnative/gdnative.cpp
#: modules/gdnative/gdnative_library_singleton_editor.cpp
@@ -17136,14 +16846,12 @@ msgid "Class Name"
msgstr "Nom de la Classe"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Script Class"
-msgstr "Nom du script :"
+msgstr "Classe de Script"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Icon Path"
-msgstr "Focaliser le chemin"
+msgstr "Chemin de l'icône"
#: modules/gdnative/register_types.cpp
msgid "GDNative"
@@ -17151,34 +16859,32 @@ msgstr "GDNative"
#: modules/gdscript/editor/gdscript_highlighter.cpp
#: modules/gdscript/gdscript.cpp
-#, fuzzy
msgid "GDScript"
-msgstr "Script"
+msgstr "GDScript"
#: modules/gdscript/editor/gdscript_highlighter.cpp
msgid "Function Definition Color"
-msgstr ""
+msgstr "Couleur de définition de fonction"
#: modules/gdscript/editor/gdscript_highlighter.cpp
-#, fuzzy
msgid "Node Path Color"
-msgstr "Copier le chemin du nœud"
+msgstr "Couleur des chemins de nœud"
#: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp
msgid "Max Call Stack"
-msgstr ""
+msgstr "Maximum de la pile d'appel"
#: modules/gdscript/gdscript.cpp
msgid "Treat Warnings As Errors"
-msgstr ""
+msgstr "Traiter les avertissements comme des erreurs"
#: modules/gdscript/gdscript.cpp
msgid "Exclude Addons"
-msgstr ""
+msgstr "Exclure les extensions"
#: modules/gdscript/gdscript.cpp
msgid "Autocomplete Setters And Getters"
-msgstr ""
+msgstr "Auto-compléter les setters et les getters"
#: modules/gdscript/gdscript_functions.cpp
msgid "Step argument is zero!"
@@ -17225,17 +16931,16 @@ msgid "Language Server"
msgstr "Serveur de Langues"
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Enable Smart Resolve"
-msgstr "Impossible à résoudre"
+msgstr "Activer la résolution intelligente"
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Show Native Symbols In Editor"
-msgstr ""
+msgstr "Afficher les symboles natifs dans l'éditeur"
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Use Thread"
-msgstr ""
+msgstr "Utiliser le parallélisme"
#: modules/gltf/editor_scene_exporter_gltf_plugin.cpp
msgid "Export Mesh GLTF2"
@@ -17246,37 +16951,32 @@ msgid "Export GLTF..."
msgstr "Exporter en GLTF..."
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Buffer View"
-msgstr "Vue de derrière"
+msgstr "Vue du tampon"
#: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp
msgid "Byte Offset"
msgstr "Décalage d’Octet"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Component Type"
-msgstr "Composants"
+msgstr "Type de composant"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Normalized"
-msgstr "Format"
+msgstr "Normalisé"
#: modules/gltf/gltf_accessor.cpp
msgid "Count"
msgstr "Compte"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Min"
-msgstr "Mio"
+msgstr "Min"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Max"
-msgstr "Mixer"
+msgstr "Max"
#: modules/gltf/gltf_accessor.cpp
#, fuzzy
@@ -17292,9 +16992,8 @@ msgid "Sparse Indices Byte Offset"
msgstr ""
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Sparse Indices Component Type"
-msgstr "Analyse de la géométrie..."
+msgstr "Type de composant d'indices épars"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Values Buffer View"
@@ -17305,14 +17004,12 @@ msgid "Sparse Values Byte Offset"
msgstr ""
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Buffer"
-msgstr "Vue de derrière"
+msgstr "Tampon"
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Byte Length"
-msgstr "Thème par défaut"
+msgstr "Longueur de byte"
#: modules/gltf/gltf_buffer_view.cpp
msgid "Byte Stride"
@@ -17344,19 +17041,17 @@ msgstr "Linéaire"
#: scene/resources/environment.cpp scene/resources/material.cpp
#: scene/resources/particles_material.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp
-#, fuzzy
msgid "Color"
-msgstr "Couleurs"
+msgstr "Couleur"
#: modules/gltf/gltf_light.cpp scene/3d/reflection_probe.cpp
#: scene/resources/environment.cpp
msgid "Intensity"
-msgstr ""
+msgstr "Intensité"
#: modules/gltf/gltf_light.cpp scene/2d/light_2d.cpp scene/3d/light.cpp
-#, fuzzy
msgid "Range"
-msgstr "Changer"
+msgstr "Plage"
#: modules/gltf/gltf_light.cpp
msgid "Inner Cone Angle"
@@ -17372,14 +17067,12 @@ msgid "Blend Weights"
msgstr "Précalculer les lightmaps"
#: modules/gltf/gltf_mesh.cpp
-#, fuzzy
msgid "Instance Materials"
-msgstr "Changements de matériau :"
+msgstr "Matériaux d'instances"
#: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp
-#, fuzzy
msgid "Parent"
-msgstr "Re-parenter"
+msgstr "Parent"
#: modules/gltf/gltf_node.cpp
#, fuzzy
@@ -17388,78 +17081,71 @@ msgstr "Plateforme"
#: modules/gltf/gltf_node.cpp scene/3d/mesh_instance.cpp
msgid "Skin"
-msgstr ""
+msgstr "Enveloppe"
#: modules/gltf/gltf_node.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Translation"
-msgstr "Traductions"
+msgstr "Translation"
#: modules/gltf/gltf_node.cpp
-#, fuzzy
msgid "Children"
-msgstr "Enfants modifiables"
+msgstr "Enfants"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Joints"
-msgstr "Point"
+msgstr "Jointures"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp
msgid "Roots"
-msgstr ""
+msgstr "Racines"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_state.cpp
msgid "Unique Names"
-msgstr ""
+msgstr "Noms Uniques"
#: modules/gltf/gltf_skeleton.cpp
-#, fuzzy
msgid "Godot Bone Node"
-msgstr "Le nœud de la scène"
+msgstr "Nœud d'os de Godot"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Skin Root"
-msgstr "Nouvelle racine de scène"
+msgstr "Racine de l'enveloppe"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Joints Original"
-msgstr "Focaliser l'origine"
+msgstr "Jointure à l'original"
#: modules/gltf/gltf_skin.cpp
msgid "Inverse Binds"
-msgstr ""
+msgstr "Inverser les liens"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Non Joints"
-msgstr "Déplacer la jointure"
+msgstr "Non jointures"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Bone I"
-msgstr ""
+msgstr "Jointure I à os I"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Name"
-msgstr ""
+msgstr "Jointure I à nom"
#: modules/gltf/gltf_skin.cpp
msgid "Godot Skin"
-msgstr ""
+msgstr "Enveloppe Godot"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Img"
-msgstr ""
+msgstr "Image Diffuse"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Factor"
-msgstr ""
+msgstr "Facteur de diffusion"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Gloss Factor"
-msgstr ""
+msgstr "Facteur de brillance"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Specular Factor"
@@ -17471,96 +17157,84 @@ msgstr ""
#: modules/gltf/gltf_state.cpp
msgid "Json"
-msgstr ""
+msgstr "Json"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Major Version"
-msgstr "Version"
+msgstr "Version majeure"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Minor Version"
-msgstr "Version"
+msgstr "Version mineure"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "GLB Data"
-msgstr "Avec données"
+msgstr "Données GLB"
#: modules/gltf/gltf_state.cpp
msgid "Use Named Skin Binds"
-msgstr ""
+msgstr "Utiliser les liens d'enveloppe par nom"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Buffer Views"
-msgstr "Vue de derrière"
+msgstr "Vues tampon"
#: modules/gltf/gltf_state.cpp
msgid "Accessors"
-msgstr ""
+msgstr "Accesseurs"
#: modules/gltf/gltf_state.cpp
msgid "Scene Name"
msgstr "Nom de la Scène"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Root Nodes"
-msgstr "Nom de nœud racine"
+msgstr "Nœuds racines"
#: modules/gltf/gltf_state.cpp scene/2d/particles_2d.cpp
#: scene/gui/texture_button.cpp scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Textures"
-msgstr "Fonctionnalités"
+msgstr "Textures"
#: modules/gltf/gltf_state.cpp platform/uwp/export/export.cpp
msgid "Images"
-msgstr ""
+msgstr "Images"
#: modules/gltf/gltf_state.cpp
msgid "Cameras"
-msgstr ""
+msgstr "Caméras"
#: modules/gltf/gltf_state.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Lights"
-msgstr "Lumière"
+msgstr "Lumières"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Unique Animation Names"
-msgstr "Nom de la nouvelle animation :"
+msgstr "Noms d'animations uniques"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Skeletons"
-msgstr "Squelette"
+msgstr "Squelettes"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Skeleton To Node"
-msgstr "Sélectionner un nœud"
+msgstr "Squelette vers nœud"
#: modules/gltf/gltf_state.cpp
msgid "Animations"
msgstr "Animations"
#: modules/gltf/gltf_texture.cpp
-#, fuzzy
msgid "Src Image"
-msgstr "Afficher les os"
+msgstr "Image source"
#: modules/gridmap/grid_map.cpp
msgid "Mesh Library"
msgstr "Librairie de maillages"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Physics Material"
-msgstr "Image physique %"
+msgstr "Matériau physique"
#: modules/gridmap/grid_map.cpp scene/3d/visual_instance.cpp
#, fuzzy
@@ -17569,46 +17243,40 @@ msgstr "Précalculer les lightmaps"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
msgid "Cell"
-msgstr ""
+msgstr "Cellule"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Octant Size"
-msgstr "Vue de devant"
+msgstr "Taille d'octant"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center X"
-msgstr "Centre"
+msgstr "X du centre"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Y"
-msgstr "Centre"
+msgstr "Y du centre"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Z"
-msgstr "Centre"
+msgstr "Z du centre"
#: modules/gridmap/grid_map.cpp scene/2d/collision_object_2d.cpp
#: scene/2d/tile_map.cpp scene/3d/collision_object.cpp scene/3d/soft_body.cpp
#: scene/resources/material.cpp
msgid "Mask"
-msgstr ""
+msgstr "Masque"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
-#, fuzzy
msgid "Bake Navigation"
-msgstr "Navigation"
+msgstr "Pré-calculer la navigation"
#: modules/gridmap/grid_map.cpp scene/2d/navigation_2d.cpp
#: scene/2d/navigation_agent_2d.cpp scene/2d/navigation_polygon.cpp
#: scene/2d/tile_map.cpp scene/3d/navigation.cpp scene/3d/navigation_agent.cpp
#: scene/3d/navigation_mesh_instance.cpp
-#, fuzzy
msgid "Navigation Layers"
-msgstr "Mode Navigation"
+msgstr "Calques de navigation"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Plane"
@@ -17774,19 +17442,19 @@ msgstr "Précalculer les lightmaps"
#: modules/lightmapper_cpu/register_types.cpp
msgid "Low Quality Ray Count"
-msgstr ""
+msgstr "Nombre de rayons de basse qualité"
#: modules/lightmapper_cpu/register_types.cpp
msgid "Medium Quality Ray Count"
-msgstr ""
+msgstr "Nombre de rayons de qualité moyenne"
#: modules/lightmapper_cpu/register_types.cpp
msgid "High Quality Ray Count"
-msgstr ""
+msgstr "Nombre de rayons de haute qualité"
#: modules/lightmapper_cpu/register_types.cpp
msgid "Ultra Quality Ray Count"
-msgstr ""
+msgstr "Nombre de rayons de qualité extrême"
#: modules/minimp3/audio_stream_mp3.cpp
#: modules/minimp3/resource_importer_mp3.cpp
@@ -17797,16 +17465,15 @@ msgstr "Décalage de Boucle"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Eye Height"
-msgstr ""
+msgstr "Hauteur de l’œil"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "IOD"
msgstr ""
#: modules/mobile_vr/mobile_vr_interface.cpp
-#, fuzzy
msgid "Display Width"
-msgstr "Affichage en fil de fer"
+msgstr "Afficher la largeur"
#: modules/mobile_vr/mobile_vr_interface.cpp
#, fuzzy
@@ -17815,15 +17482,15 @@ msgstr "Afficher sans ombrage"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Oversample"
-msgstr ""
+msgstr "Suréchantillonner"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "K1"
-msgstr ""
+msgstr "K1"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "K2"
-msgstr ""
+msgstr "K2"
#: modules/mono/csharp_script.cpp
msgid "Class name can't be a reserved keyword"
@@ -17834,9 +17501,8 @@ msgid "Build Solution"
msgstr "Compiler la solution"
#: modules/mono/editor/csharp_project.cpp
-#, fuzzy
msgid "Auto Update Project"
-msgstr "Projet sans titre"
+msgstr "Mettre à jour le projet automatiquement"
#: modules/mono/mono_gd/gd_mono_utils.cpp
msgid "End of inner exception stack trace"
@@ -17911,56 +17577,51 @@ msgstr "C'est fait !"
#: modules/opensimplex/noise_texture.cpp
msgid "Seamless"
-msgstr ""
+msgstr "Sans bord"
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "As Normal Map"
-msgstr "Échelle aléatoire :"
+msgstr "En tant que carte de normales"
#: modules/opensimplex/noise_texture.cpp
msgid "Bump Strength"
-msgstr ""
+msgstr "Force du bossage"
#: modules/opensimplex/noise_texture.cpp
msgid "Noise"
-msgstr ""
+msgstr "Bruit"
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "Noise Offset"
-msgstr "Décalage de la grille :"
+msgstr "Décalage du bruit"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Octaves"
-msgstr ""
+msgstr "Octaves"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Period"
-msgstr ""
+msgstr "Période"
#: modules/opensimplex/open_simplex_noise.cpp
-#, fuzzy
msgid "Persistence"
-msgstr "Perspective"
+msgstr "Persistance"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Lacunarity"
-msgstr ""
+msgstr "Lacunarité"
#: modules/regex/regex.cpp
msgid "Subject"
-msgstr ""
+msgstr "Sujet"
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Names"
-msgstr "Nom"
+msgstr "Noms"
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Strings"
-msgstr "Paramètres :"
+msgstr "Paramètres"
#: modules/upnp/upnp.cpp
msgid "Discover Multicast If"
@@ -17968,39 +17629,35 @@ msgstr ""
#: modules/upnp/upnp.cpp
msgid "Discover Local Port"
-msgstr ""
+msgstr "Révéler le port local"
#: modules/upnp/upnp.cpp
msgid "Discover IPv6"
-msgstr ""
+msgstr "Découvrir IPv6"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Description URL"
-msgstr "Description"
+msgstr "URL de description"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "Service Type"
-msgstr "Définir type de variable"
+msgstr "Type du service"
#: modules/upnp/upnp_device.cpp
msgid "IGD Control URL"
-msgstr ""
+msgstr "URL de contrôle IGD"
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Service Type"
-msgstr "Définir type de variable"
+msgstr "Type de service IGD"
#: modules/upnp/upnp_device.cpp
msgid "IGD Our Addr"
msgstr ""
#: modules/upnp/upnp_device.cpp
-#, fuzzy
msgid "IGD Status"
-msgstr "État"
+msgstr "État IGD"
#: modules/visual_script/visual_script.cpp
msgid ""
@@ -18041,9 +17698,8 @@ msgid "Stack overflow with stack depth:"
msgstr "Débordement de pile avec profondeur de pile :"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Visual Script"
-msgstr "Rechercher VisualScript"
+msgstr "Script graphique"
#: modules/visual_script/visual_script_editor.cpp
msgid "Change Signal Arguments"
@@ -18379,9 +18035,8 @@ msgid "Return Enabled"
msgstr "Exécutable"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return Type"
-msgstr "Retour"
+msgstr "Type de retour"
#: modules/visual_script/visual_script_flow_control.cpp
#: scene/resources/visual_shader_nodes.cpp
@@ -18429,7 +18084,6 @@ msgid "in order:"
msgstr "dans l'ordre :"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Steps"
msgstr "Pas"
@@ -18451,9 +18105,8 @@ msgstr "Est-ce %s ?"
#: modules/visual_script/visual_script_flow_control.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Base Script"
-msgstr "Nouveau script"
+msgstr "Script de base"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "On %s"
@@ -18465,36 +18118,31 @@ msgstr "On Self"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Call Mode"
-msgstr "Mode mise à l'échelle"
+msgstr "Mode d'appel"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Basic Type"
-msgstr "Changer le type de base"
+msgstr "Type simple"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Node Path"
-msgstr "Copier le chemin du nœud"
+msgstr "Chemin de nœud"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Use Default Args"
-msgstr "Réinitialiser"
+msgstr "Utiliser les valeurs d'arguments par défaut"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Validate"
msgstr "Valider"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "RPC Call Mode"
-msgstr "Mode mise à l'échelle"
+msgstr "Mode d'appel RPC"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Subtract %s"
@@ -18533,14 +18181,12 @@ msgid "BitXor %s"
msgstr "Ou-exclusif par bit %s"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Set Mode"
-msgstr "Mode sélection"
+msgstr "Définir le mode"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Assign Op"
-msgstr "Assigner"
+msgstr "Opérateur d'assignation"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
@@ -18557,9 +18203,8 @@ msgid "Base object is not a Node!"
msgstr "L'objet de base n'est pas un nœud !"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Path does not lead to Node!"
-msgstr "Le chemin ne mène pas au nœud !"
+msgstr "Le chemin ne mène pas vers un nœud !"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Invalid index property name '%s' in node %s."
@@ -18575,9 +18220,8 @@ msgstr "Composer le tableau"
#: modules/visual_script/visual_script_nodes.cpp scene/resources/material.cpp
#: scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Operator"
-msgstr "Itérateur"
+msgstr "Opérateur"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Invalid argument of type:"
@@ -18592,9 +18236,8 @@ msgid "a if cond, else b"
msgstr "a if cond, else b"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Var Name"
-msgstr "Nom"
+msgstr "Nom de variable"
#: modules/visual_script/visual_script_nodes.cpp
msgid "VariableGet not found in script:"
@@ -18672,7 +18315,7 @@ msgstr "Sous-appel"
#: modules/visual_script/visual_script_nodes.cpp scene/gui/graph_node.cpp
msgid "Title"
-msgstr ""
+msgstr "Titre"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Construct %s"
@@ -18719,9 +18362,8 @@ msgid "%s sec(s)"
msgstr "%s seconde(s)"
#: modules/visual_script/visual_script_yield_nodes.cpp scene/main/timer.cpp
-#, fuzzy
msgid "Wait Time"
-msgstr "Peindre la tuile"
+msgstr "Temps d'attente"
#: modules/visual_script/visual_script_yield_nodes.cpp
msgid "WaitSignal"
@@ -18736,81 +18378,72 @@ msgid "WaitInstanceSignal"
msgstr "WaitInstanceSignal"
#: modules/webrtc/webrtc_data_channel.cpp
-#, fuzzy
msgid "Write Mode"
-msgstr "Mode prioritaire"
+msgstr "Mode écriture"
#: modules/webrtc/webrtc_data_channel.h
msgid "WebRTC"
-msgstr ""
+msgstr "WebRTC"
#: modules/webrtc/webrtc_data_channel.h
msgid "Max Channel In Buffer (KB)"
-msgstr ""
+msgstr "Maximum de canal dans le tampon (Ko)"
#: modules/websocket/websocket_client.cpp
msgid "Verify SSL"
-msgstr ""
+msgstr "Vérifier la SSL"
#: modules/websocket/websocket_client.cpp
msgid "Trusted SSL Certificate"
-msgstr ""
+msgstr "Certificat SSL Fiable"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Client"
-msgstr "Profileur réseau"
+msgstr "Client WebSocket"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "Max In Buffer (KB)"
-msgstr "Taille Maximale (KB)"
+msgstr "Maximum tampon entrant (KB)"
#: modules/websocket/websocket_macros.h
msgid "Max In Packets"
-msgstr ""
+msgstr "Maximum de paquets entrant"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "Max Out Buffer (KB)"
-msgstr "Taille Maximale (KB)"
+msgstr "Maximum tampon sortant (KB)"
#: modules/websocket/websocket_macros.h
msgid "Max Out Packets"
-msgstr ""
+msgstr "Maximum de paquets sortant"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Server"
-msgstr "Profileur réseau"
+msgstr "Server WebSocket"
#: modules/websocket/websocket_server.cpp
msgid "Bind IP"
-msgstr ""
+msgstr "Lier IP"
#: modules/websocket/websocket_server.cpp
-#, fuzzy
msgid "Private Key"
-msgstr "Chemin de la clé privée SSH"
+msgstr "Clé privée"
#: modules/websocket/websocket_server.cpp platform/javascript/export/export.cpp
msgid "SSL Certificate"
-msgstr ""
+msgstr "Certificat SSL"
#: modules/websocket/websocket_server.cpp
-#, fuzzy
msgid "CA Chain"
-msgstr "Effacer la chaîne IK"
+msgstr "Chaîne d’autorité de certificat (CA)"
#: modules/websocket/websocket_server.cpp
-#, fuzzy
msgid "Handshake Timeout"
-msgstr "Délai dépassé."
+msgstr "Délai de poignée de main expiré"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Session Mode"
-msgstr "Mode Région"
+msgstr "Mode de session"
#: modules/webxr/webxr_interface.cpp
msgid "Required Features"
@@ -18825,18 +18458,17 @@ msgid "Requested Reference Space Types"
msgstr ""
#: modules/webxr/webxr_interface.cpp
+#, fuzzy
msgid "Reference Space Type"
-msgstr ""
+msgstr "Type de référentiel spatial"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Visibility State"
-msgstr "Basculer la visibilité"
+msgstr "État de la visibilité"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Bounds Geometry"
-msgstr "Réessayer"
+msgstr "Géométrie des limites"
#: modules/webxr/webxr_interface.cpp
#, fuzzy
@@ -18845,7 +18477,7 @@ msgstr "Magnétisme intelligent"
#: platform/android/export/export.cpp
msgid "Android SDK Path"
-msgstr ""
+msgstr "Chemin du SDK Android"
#: platform/android/export/export.cpp
#, fuzzy
@@ -18862,27 +18494,27 @@ msgstr ""
#: platform/android/export/export.cpp
msgid "Force System User"
-msgstr ""
+msgstr "Forcer l'utilisateur système"
#: platform/android/export/export.cpp
msgid "Shutdown ADB On Exit"
-msgstr ""
+msgstr "Fermer ADB à la sortie"
#: platform/android/export/export_plugin.cpp
msgid "Launcher Icons"
-msgstr ""
+msgstr "Icônes du lanceur"
#: platform/android/export/export_plugin.cpp
msgid "Main 192 X 192"
-msgstr ""
+msgstr "Principal 192 X 192"
#: platform/android/export/export_plugin.cpp
msgid "Adaptive Foreground 432 X 432"
-msgstr ""
+msgstr "Avant-Plan Adaptatif 432 X 432"
#: platform/android/export/export_plugin.cpp
msgid "Adaptive Background 432 X 432"
-msgstr ""
+msgstr "Arrière-Plan Adaptatif 432 X 432"
#: platform/android/export/export_plugin.cpp
msgid "Package name is missing."
@@ -18914,18 +18546,28 @@ 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
+msgid "Custom Build"
+msgstr "Construction personnalisé"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
-msgstr ""
+msgstr "Utiliser une construction personnalisé"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Export Format"
-msgstr "Chemin d'exportation"
+msgstr "Format d'exportation"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "Min SDK"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr "SDK Cible"
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
-#, fuzzy
msgid "Architectures"
-msgstr "Ajouter une entrée architecture"
+msgstr "Architectures"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18933,60 +18575,44 @@ msgid "Keystore"
msgstr "Débogueur"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Debug User"
-msgstr "Débogueur"
+msgstr "Utilisateur de débogage"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Debug Password"
-msgstr "Mot de passe"
+msgstr "Mot de passe de débogage"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Release User"
-msgstr "Publication (release)"
+msgstr "Utilisateur de publication (release)"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Release Password"
-msgstr "Mot de passe"
+msgstr "Mot de passe de publication"
#: platform/android/export/export_plugin.cpp
msgid "One Click Deploy"
-msgstr ""
+msgstr "Déploiement en un clic"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Clear Previous Install"
-msgstr "Inspecter l'instance précédente"
+msgstr "Nettoyer l'installation précédente"
#: platform/android/export/export_plugin.cpp
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"
+msgstr "Code"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Package"
-msgstr "Empaquetage"
+msgstr "Paquetage"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Unique Name"
msgstr "Nom unique"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Signed"
-msgstr "Signaux"
+msgstr "Signé"
#: platform/android/export/export_plugin.cpp
msgid "Classify As Game"
@@ -18994,50 +18620,43 @@ msgstr "Classer En Tant Que Jeu"
#: platform/android/export/export_plugin.cpp
msgid "Retain Data On Uninstall"
-msgstr ""
+msgstr "Conserver les données lors de la désinstallation"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Exclude From Recents"
-msgstr "Supprimer des nœuds"
+msgstr "Exclure des récents"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Graphics"
-msgstr "Décalage de la grille :"
+msgstr "Graphismes"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "OpenGL Debug"
-msgstr "Ouvrir"
+msgstr "Débogage OpenGL"
#: 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
msgid "Hand Tracking"
-msgstr "Empaquetage"
+msgstr "Suivi des mains"
#: platform/android/export/export_plugin.cpp
msgid "Hand Tracking Frequency"
-msgstr ""
+msgstr "Fréquence de suivi des mains"
#: platform/android/export/export_plugin.cpp
msgid "Passthrough"
-msgstr ""
+msgstr "Relais"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Immersive Mode"
-msgstr "Mode prioritaire"
+msgstr "Mode immersif"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -19060,18 +18679,16 @@ msgid "Support Xlarge"
msgstr "Support"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "User Data Backup"
-msgstr "Interface utilisateur"
+msgstr "Sauvegarde(backup) des données utilisateur"
#: platform/android/export/export_plugin.cpp
msgid "Allow"
-msgstr ""
+msgstr "Autoriser"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Command Line"
-msgstr "Communauté"
+msgstr "Ligne de commande"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Extra Args"
@@ -19084,22 +18701,19 @@ msgstr "Expression"
#: platform/android/export/export_plugin.cpp
msgid "Salt"
-msgstr ""
+msgstr "Sel"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Public Key"
-msgstr "Chemin de la clé publique SSH"
+msgstr "Clé Publique"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Permissions"
-msgstr "Masque d'émission"
+msgstr "Permissions"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Custom Permissions"
-msgstr "Jouer une scène personnalisée"
+msgstr "Permissions Personnalisées"
#: platform/android/export/export_plugin.cpp
msgid "Select device from the list"
@@ -19219,6 +18833,11 @@ msgid ""
"Note that the singleton was also renamed from \"GodotPayments\" to "
"\"GodotGooglePlayBilling\"."
msgstr ""
+"Le module \"GodotPaymentV3\" inclus dans les paramètres du projet à "
+"\"android/modules\" est invalide (Changé dans Godot 3.2.2).\n"
+"Remplacez-le avec le plugin tiers \"GodotGooglePlayBilling\".\n"
+"Notez que ce singleton a aussi été renommé de \"GodotPayments\" en "
+"\"GodotGooglePlayBilling\"."
#: platform/android/export/export_plugin.cpp
msgid "\"Use Custom Build\" must be enabled to use the plugins."
@@ -19226,17 +18845,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,41 +18864,66 @@ 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 ""
+"\"Min SDK\" devrait être un nombre entier valide, mais \"%s\" n'est pas "
+"valide."
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+"« Min SDK » ne peut être inférieur à %d, la version requise par la libraire "
+"de Godot."
+
+#: 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 ""
-"Changer « Target Sdk » est valide uniquement lorsque l'option « Use Custom "
+"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 ""
+"« SDK Cible » devrait être un nombre entier valide, mais « %s » n'en est pas "
+"un."
+
+#: 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 ""
-"La version « Target Sdk » doit être supérieure ou égale à la version « Min "
-"Sdk »."
+"« SDK Cible » %d est plus grande que la version par défaut %d. Cela pourrait "
+"fonctionner, mais ça n'a pas été testé. Le résultat pourrait être instable."
+
+#: 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 »."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Code Signing"
-msgstr "Signaux"
+msgstr "Signature du code"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"'apksigner' could not be found. Please check that the command is available "
"in the Android SDK build-tools directory. The resulting %s is unsigned."
msgstr ""
-"Impossible de trouver 'apksigner'.\n"
-"Veuillez vérifier que la commande est disponible dans le dossier build-tools "
-"du SDK Android.\n"
-"Le paquet sortant %s est non signé."
+"Impossible de trouver 'apksigner'. Veuillez vérifier que la commande est "
+"disponible dans le dossier build-tools du SDK Android. Le %s resultant n'est "
+"pas signé."
#: platform/android/export/export_plugin.cpp
msgid "Signing debug %s..."
@@ -19295,9 +18938,8 @@ msgid "Could not find keystore, unable to export."
msgstr "Impossible de trouver le keystore, impossible d'exporter."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not start apksigner executable."
-msgstr "Impossible de démarrer le sous-processus !"
+msgstr "Impossible de le programme apksigner."
#: platform/android/export/export_plugin.cpp
msgid "'apksigner' returned with error #%d"
@@ -19334,9 +18976,8 @@ msgstr ""
"*.apk."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Unsupported export format!"
-msgstr "Format d'export non supporté !\n"
+msgstr "Format d'export non supporté !"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19348,28 +18989,24 @@ msgstr ""
"menu 'Projet'."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Android build version mismatch: Template installed: %s, Godot version: %s. "
"Please reinstall Android build template from 'Project' menu."
msgstr ""
-"La version d'Android ne correspond pas :\n"
-" Modèle installé : %s\n"
-" Version Godot : %s\n"
-"Veuillez réinstaller la version d'Android depuis le menu 'Projet'."
+"La version compilée d'Android ne correspond pas : Modèle type installé : %s, "
+"Version de Godot : %s. Veuillez réinstaller le modèle type de compilation "
+"d'Android depuis le menu 'Projet'."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Unable to overwrite res://android/build/res/*.xml files with project name."
msgstr ""
"Impossible d'écraser les fichiers res://android/build/res/*.xml avec le nom "
-"du projet"
+"du projet."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
-msgstr "Impossible d'exporter les fichiers du projet vers le projet gradle\n"
+msgstr "Impossible d'exporter les fichiers du projet vers le projet gradle."
#: platform/android/export/export_plugin.cpp
msgid "Could not write expansion package file!"
@@ -19380,15 +19017,13 @@ msgid "Building Android Project (gradle)"
msgstr "Construire le Project Android (gradle)"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Building of Android project failed, check output for the error. "
"Alternatively visit docs.godotengine.org for Android build documentation."
msgstr ""
"La construction du projet Android a échoué, vérifiez la sortie pour "
-"l'erreur.\n"
-"Sinon, visitez docs.godotengine.org pour la documentation de construction "
-"Android."
+"l'erreur. Sinon, visitez docs.godotengine.org pour la documentation de "
+"construction Android."
#: platform/android/export/export_plugin.cpp
msgid "Moving output"
@@ -19403,41 +19038,38 @@ msgstr ""
"du projet gradle pour les journaux."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Package not found: \"%s\"."
-msgstr "Paquet non trouvé : %s"
+msgstr "Paquet non trouvé : \"%s\"."
#: platform/android/export/export_plugin.cpp
msgid "Creating APK..."
msgstr "Création de l'APK..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not find template APK to export: \"%s\"."
msgstr ""
-"Impossible de trouver le modèle de l'APK à exporter :\n"
-"%s"
+"La construction du projet Android a échoué, vérifiez la sortie pour "
+"l'erreur. Sinon, visitez docs.godotengine.org pour la documentation de "
+"construction Android."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Missing libraries in the export template for the selected architectures: %s. "
"Please build a template with all required libraries, or uncheck the missing "
"architectures in the export preset."
msgstr ""
"Bibliothèques manquantes dans le modèle d'exportation pour les architectures "
-"sélectionnées : %s.\n"
-"Veuillez construire un modèle avec toutes les bibliothèques requises, ou "
-"désélectionner les architectures manquantes dans le préréglage d'exportation."
+"sélectionnées : %s. Veuillez construire un modèle avec toutes les "
+"bibliothèques requises, ou désélectionner les architectures manquantes dans "
+"le préréglage d'exportation."
#: platform/android/export/export_plugin.cpp
msgid "Adding files..."
msgstr "Ajout de fichiers..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files."
-msgstr "Impossible d'exporter les fichiers du projet"
+msgstr "Impossible d'exporter les fichiers du projet."
#: platform/android/export/export_plugin.cpp
msgid "Aligning APK..."
@@ -19461,188 +19093,176 @@ msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPhone 2436 X 1125"
-msgstr ""
+msgstr "iPhone 2436 X 1125"
#: platform/iphone/export/export.cpp
msgid "iPhone 2208 X 1242"
-msgstr ""
+msgstr "iPhone 2208 X 1242"
#: platform/iphone/export/export.cpp
msgid "iPad 1024 X 768"
-msgstr ""
+msgstr "iPad 1024 X 768"
#: platform/iphone/export/export.cpp
msgid "iPad 2048 X 1536"
-msgstr ""
+msgstr "iPad 2048 X 1536"
#: platform/iphone/export/export.cpp
msgid "Portrait Launch Screens"
-msgstr ""
+msgstr "Écrans de lancement en mode portrait"
#: platform/iphone/export/export.cpp
msgid "iPhone 640 X 960"
-msgstr ""
+msgstr "iPhone 640 X 960"
#: platform/iphone/export/export.cpp
msgid "iPhone 640 X 1136"
-msgstr ""
+msgstr "iPhone 640 X 1136"
#: platform/iphone/export/export.cpp
msgid "iPhone 750 X 1334"
-msgstr ""
+msgstr "iPhone 750 X 1334"
#: platform/iphone/export/export.cpp
msgid "iPhone 1125 X 2436"
-msgstr ""
+msgstr "iPhone 1125 X 2436"
#: platform/iphone/export/export.cpp
msgid "iPad 768 X 1024"
-msgstr ""
+msgstr "iPad 768 X 1024"
#: platform/iphone/export/export.cpp
msgid "iPad 1536 X 2048"
-msgstr ""
+msgstr "iPad 1536 X 2048"
#: platform/iphone/export/export.cpp
msgid "iPhone 1242 X 2208"
-msgstr ""
+msgstr "iPhone 1242 X 2208"
#: platform/iphone/export/export.cpp
msgid "App Store Team ID"
-msgstr ""
+msgstr "ID de groupe de l'App Store"
#: platform/iphone/export/export.cpp
msgid "Provisioning Profile UUID Debug"
-msgstr ""
+msgstr "UUID de provisionnement de profils en débogage"
#: platform/iphone/export/export.cpp
msgid "Code Sign Identity Debug"
-msgstr ""
+msgstr "Identité de signature de code en débogage"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Export Method Debug"
-msgstr "Exporter avec debug"
+msgstr "Méthode d'exportation en débogage"
#: platform/iphone/export/export.cpp
msgid "Provisioning Profile UUID Release"
-msgstr ""
+msgstr "UUID de provisionnement de profils en publication"
#: platform/iphone/export/export.cpp
msgid "Code Sign Identity Release"
-msgstr ""
+msgstr "Identité de signature de code en publication"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Export Method Release"
-msgstr "Mode d'exportation :"
+msgstr "Méthode d'exportation en publication"
#: platform/iphone/export/export.cpp
msgid "Targeted Device Family"
-msgstr ""
+msgstr "Famille de système ciblée"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
msgid "Info"
-msgstr ""
+msgstr "Info"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
msgid "Identifier"
msgstr "Identifiant"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Signature"
-msgstr "Signaux"
+msgstr "Signature"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Short Version"
-msgstr "Version"
+msgstr "Version courte"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Copyright"
-msgstr "En haut à droite"
+msgstr "Copyright"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Capabilities"
-msgstr "Coller les propriétés"
+msgstr "Capacités"
#: platform/iphone/export/export.cpp
msgid "Access Wi-Fi"
msgstr "Accès Wi-Fi"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Push Notifications"
-msgstr "Rotation aléatoire :"
+msgstr "Notifications Push"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "User Data"
-msgstr "Interface utilisateur"
+msgstr "Données Utilisateur"
#: platform/iphone/export/export.cpp
msgid "Accessible From Files App"
-msgstr ""
+msgstr "Accessible depuis l'application Files"
#: platform/iphone/export/export.cpp
msgid "Accessible From iTunes Sharing"
-msgstr ""
+msgstr "Accessible depuis le partage iTunes"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Privacy"
-msgstr "Chemin de la clé privée SSH"
+msgstr "Confidentialité"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Camera Usage Description"
-msgstr "Description"
+msgstr "Description d'utilisation de la caméra"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Microphone Usage Description"
-msgstr "Description des propriétés"
+msgstr "Description d'utilisation du microphone"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Photolibrary Usage Description"
-msgstr "Description des propriétés"
+msgstr "Description d'utilisation de la bibliothèque d'image"
#: platform/iphone/export/export.cpp
msgid "iPhone 120 X 120"
-msgstr ""
+msgstr "iPhone 120 X 120"
#: platform/iphone/export/export.cpp
msgid "iPhone 180 X 180"
-msgstr ""
+msgstr "iPhone 180 X 180"
#: platform/iphone/export/export.cpp
msgid "iPad 76 X 76"
-msgstr ""
+msgstr "iPad 76 X 76"
#: platform/iphone/export/export.cpp
msgid "iPad 152 X 152"
-msgstr ""
+msgstr "iPad 152 X 152"
#: platform/iphone/export/export.cpp
msgid "iPad 167 X 167"
-msgstr ""
+msgstr "iPad 167 X 167"
#: platform/iphone/export/export.cpp
msgid "App Store 1024 X 1024"
-msgstr ""
+msgstr "App Store 1024 X 1024"
#: platform/iphone/export/export.cpp
msgid "Spotlight 40 X 40"
-msgstr ""
+msgstr "Projecteur 40 X 40"
#: platform/iphone/export/export.cpp
msgid "Spotlight 80 X 80"
-msgstr ""
+msgstr "Projecteur 80 X 80"
#: platform/iphone/export/export.cpp
msgid "Storyboard"
@@ -19653,40 +19273,33 @@ msgid "Use Launch Screen Storyboard"
msgstr ""
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Image Scale Mode"
-msgstr "Mode mise à l'échelle"
+msgstr "Mode de mise à l'échelle d'image"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom Image @2x"
-msgstr "Nœud Personnalisé"
+msgstr "Image personnalisée @2x"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom Image @3x"
-msgstr "Nœud Personnalisé"
+msgstr "Image personnalisée @3x"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Use Custom BG Color"
-msgstr "Nœud Personnalisé"
+msgstr "Utiliser la couleur d'arrière-plan personnalisée"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Custom BG Color"
-msgstr "Nœud Personnalisé"
+msgstr "Couleur d'arrière-plan personnalisée"
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Prepare Templates"
-msgstr "Gérer les modèles"
+msgstr "Préparer les modèles"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Export template not found."
-msgstr "Modèle de version personnalisée introuvable."
+msgstr "Modèle d'exportation introuvable."
#: platform/iphone/export/export.cpp
msgid "App Store Team ID not specified - cannot configure the project."
@@ -19709,29 +19322,24 @@ msgid "Run exported HTML in the system's default browser."
msgstr "Exécutez le HTML exporté dans le navigateur par défaut du système."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not open template for export: \"%s\"."
-msgstr "Impossible d'ouvrir le modèle pour exportation :"
+msgstr "Impossible d'ouvrir le modèle pour exportation : « %s »."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Invalid export template: \"%s\"."
-msgstr "Modèle d'exportation non valide :"
+msgstr "Modèle d'exportation invalide : « %s »."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not write file: \"%s\"."
-msgstr "Impossible d'écrire le fichier :"
+msgstr "Impossible d'écrire le fichier : « %s »."
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Icon Creation"
-msgstr "Définir la marge"
+msgstr "Création de l'icône"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read file: \"%s\"."
-msgstr "Impossible de lire le fichier :"
+msgstr "Impossible de lire le fichier : «%s »."
#: platform/javascript/export/export.cpp
msgid "PWA"
@@ -19742,36 +19350,32 @@ msgid "Variant"
msgstr "Variant"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Export Type"
-msgstr "Exporter"
+msgstr "Type d'exportation"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "VRAM Texture Compression"
-msgstr "Expression"
+msgstr "Compression des textures dans la mémoire vidéo"
#: platform/javascript/export/export.cpp
msgid "For Desktop"
-msgstr ""
+msgstr "Pour PC"
#: platform/javascript/export/export.cpp
msgid "For Mobile"
-msgstr ""
+msgstr "Pour Mobile"
#: platform/javascript/export/export.cpp
msgid "HTML"
-msgstr ""
+msgstr "HTML"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Export Icon"
-msgstr "Développer tout"
+msgstr "Icône d'exportation"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Custom HTML Shell"
-msgstr "Nœud Personnalisé"
+msgstr "Shell HTML personnalisé"
#: platform/javascript/export/export.cpp
msgid "Head Include"
@@ -19779,72 +19383,67 @@ msgstr ""
#: platform/javascript/export/export.cpp
msgid "Canvas Resize Policy"
-msgstr ""
+msgstr "Politique de redimensionnement du canevas"
#: platform/javascript/export/export.cpp
msgid "Focus Canvas On Start"
msgstr ""
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Experimental Virtual Keyboard"
-msgstr "Filtrer les signaux"
+msgstr "Clavier virtuel expérimental"
#: platform/javascript/export/export.cpp
msgid "Progressive Web App"
-msgstr ""
+msgstr "Application web progressive"
#: platform/javascript/export/export.cpp
msgid "Offline Page"
-msgstr ""
+msgstr "Page hors ligne"
#: platform/javascript/export/export.cpp
msgid "Icon 144 X 144"
-msgstr ""
+msgstr "Icône 144 X 144"
#: platform/javascript/export/export.cpp
msgid "Icon 180 X 180"
-msgstr ""
+msgstr "Icône 180 X 180"
#: platform/javascript/export/export.cpp
msgid "Icon 512 X 512"
-msgstr ""
+msgstr "Icône 512 X 512"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read HTML shell: \"%s\"."
-msgstr "Impossible de lire le shell HTML :"
+msgstr "Impossible de lire le shell HTML : « %s »."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not create HTTP server directory: %s."
-msgstr "Impossible de créer le répertoire du serveur HTTP :"
+msgstr "Impossible de créer le répertoire du serveur HTTP : %s."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Error starting HTTP server: %d."
-msgstr "Erreur de démarrage du serveur HTTP :"
+msgstr "Erreur de démarrage du serveur HTTP : %d."
#: platform/javascript/export/export.cpp
msgid "Web"
-msgstr ""
+msgstr "Web"
#: platform/javascript/export/export.cpp
msgid "HTTP Host"
-msgstr ""
+msgstr "Hôte HTTP"
#: platform/javascript/export/export.cpp
msgid "HTTP Port"
-msgstr ""
+msgstr "Port HTTP"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Use SSL"
-msgstr "Utiliser l’aimantation"
+msgstr "Utiliser SSL"
#: platform/javascript/export/export.cpp
msgid "SSL Key"
-msgstr ""
+msgstr "Clé SSL"
#: platform/osx/export/codesign.cpp
msgid "Can't get filesystem access."
@@ -19872,7 +19471,7 @@ msgstr "Échec de création du sous-dossier « %s »."
#: platform/osx/export/codesign.cpp
msgid "Failed to extract thin binary."
-msgstr ""
+msgstr "Échec lors de l'extraction du binaire."
#: platform/osx/export/codesign.cpp
msgid "Invalid binary format."
@@ -19883,18 +19482,16 @@ msgid "Already signed!"
msgstr "Déjà signé !"
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Failed to process nested resources."
-msgstr "Impossible de charger la ressource."
+msgstr "Le traitement des ressources imbriquées a échoué."
#: platform/osx/export/codesign.cpp
msgid "Failed to create _CodeSignature subfolder."
-msgstr ""
+msgstr "Échec lors de la création du sous-dossier _CodeSignature."
#: platform/osx/export/codesign.cpp
-#, fuzzy
msgid "Failed to get CodeResources hash."
-msgstr "Impossible de charger la ressource."
+msgstr "La récupération du hachage de CodeResources a échouée."
#: platform/osx/export/codesign.cpp platform/osx/export/export.cpp
#, fuzzy
@@ -19907,94 +19504,84 @@ msgstr "Fichier exécutable invalide."
#: platform/osx/export/codesign.cpp
msgid "Can't resize signature load command."
-msgstr ""
+msgstr "Impossible de redimensionner la commande de chargement des signatures."
#: platform/osx/export/codesign.cpp
msgid "Failed to create fat binary."
-msgstr ""
+msgstr "Échec lors de la création du binaire."
#: platform/osx/export/codesign.cpp
msgid "Unknown bundle type."
-msgstr ""
+msgstr "Type de paquet inconnu."
#: platform/osx/export/codesign.cpp
msgid "Unknown object type."
msgstr "Type d'objet inconnu."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "App Category"
-msgstr "Catégorie :"
+msgstr "Catégorie de l'application"
#: platform/osx/export/export.cpp
msgid "High Res"
-msgstr ""
+msgstr "Haute Résolution"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Location Usage Description"
-msgstr "Description"
+msgstr "Description d'utilisation de la géolocalisation"
#: platform/osx/export/export.cpp
msgid "Address Book Usage Description"
-msgstr ""
+msgstr "Description d'utilisation du carnet d'adresse"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Calendar Usage Description"
-msgstr "Description"
+msgstr "Description d'utilisation du calendrier"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Photos Library Usage Description"
-msgstr "Description des propriétés"
+msgstr "Description d'utilisation de la bibliothèque photo"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Desktop Folder Usage Description"
-msgstr "Descriptions des méthodes"
+msgstr "Description d'utilisation du dossier Bureau"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Documents Folder Usage Description"
-msgstr "Descriptions des méthodes"
+msgstr "Description d'utilisation du dossier Documents"
#: platform/osx/export/export.cpp
msgid "Downloads Folder Usage Description"
-msgstr ""
+msgstr "Description d'utilisation du dossier Téléchargements"
#: platform/osx/export/export.cpp
msgid "Network Volumes Usage Description"
-msgstr ""
+msgstr "Description d'utilisation des disques réseau"
#: platform/osx/export/export.cpp
msgid "Removable Volumes Usage Description"
-msgstr ""
+msgstr "Description d'utilisation des disques amovibles"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Codesign"
-msgstr "Nœud"
+msgstr "Signature du code"
#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Identity"
-msgstr "Indenter vers la gauche"
+msgstr "Identité"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Timestamp"
-msgstr "Temps"
+msgstr "Horodatage"
#: platform/osx/export/export.cpp
msgid "Hardened Runtime"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Replace Existing Signature"
-msgstr "Remplacer dans les fichiers"
+msgstr "Remplacer la signature existante"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -20002,13 +19589,12 @@ msgid "Entitlements"
msgstr "Gadgets"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Custom File"
-msgstr "Nœud Personnalisé"
+msgstr "Fichier personnalisé"
#: platform/osx/export/export.cpp
msgid "Allow JIT Code Execution"
-msgstr ""
+msgstr "Autoriser l'exécution du code JIT"
#: platform/osx/export/export.cpp
msgid "Allow Unsigned Executable Memory"
@@ -20019,65 +19605,57 @@ msgid "Allow Dyld Environment Variables"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Disable Library Validation"
-msgstr "Bouton désactivé"
+msgstr "Désactiver la validation des librairies"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Audio Input"
-msgstr "Ajouter une entrée"
+msgstr "Entrée Audio"
#: platform/osx/export/export.cpp
msgid "Address Book"
-msgstr ""
+msgstr "Carnet d'Adresses"
#: platform/osx/export/export.cpp
msgid "Calendars"
-msgstr ""
+msgstr "Calendrier"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Photos Library"
-msgstr "Bibliothèque d'exportation"
+msgstr "Bibliothèque de photos"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Apple Events"
-msgstr "Ajouter évènement"
+msgstr "Événements Apple"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Debugging"
msgstr "Débogage"
#: platform/osx/export/export.cpp
msgid "App Sandbox"
-msgstr ""
+msgstr "Bac à sable de l'application"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Network Server"
-msgstr "Profileur réseau"
+msgstr "Serveur réseau"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Network Client"
-msgstr "Profileur réseau"
+msgstr "Client réseau"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Device USB"
-msgstr "Périphérique"
+msgstr "Périphérique USB"
#: platform/osx/export/export.cpp
msgid "Device Bluetooth"
-msgstr ""
+msgstr "Périphérique Bluetooth"
#: platform/osx/export/export.cpp
#, fuzzy
msgid "Files Downloads"
-msgstr "Télécharger"
+msgstr "Téléchargement de fichiers"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -20095,9 +19673,8 @@ msgid "Files Movies"
msgstr "Filtrer les tuiles"
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Custom Options"
-msgstr "Options de bus"
+msgstr "Options personnalisées"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -20106,31 +19683,27 @@ msgstr "Localisation"
#: platform/osx/export/export.cpp
msgid "Apple ID Name"
-msgstr ""
+msgstr "Nom Apple ID"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Apple ID Password"
-msgstr "Mot de passe"
+msgstr "Mot de passe Apple ID"
#: platform/osx/export/export.cpp
msgid "Apple Team ID"
msgstr "Apple Team ID"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not open icon file \"%s\"."
-msgstr "Impossible d'exporter les fichiers du projet"
+msgstr "Impossible d'ouvrir le fichier d'icône \"%s\"."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start xcrun executable."
-msgstr "Impossible de démarrer le sous-processus !"
+msgstr "Impossible de démarrer le sous-processus."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization failed."
-msgstr "Localisation"
+msgstr "Notarisation échouée."
#: platform/osx/export/export.cpp
msgid "Notarization request UUID: \"%s\""
@@ -20141,22 +19714,30 @@ msgid ""
"The notarization process generally takes less than an hour. When the process "
"is completed, you'll receive an email."
msgstr ""
+"Le processus de certification prend généralement moins d'une heure. Quand le "
+"processus sera achevé, vous recevrez un e-mail."
#: platform/osx/export/export.cpp
msgid ""
"You can check progress manually by opening a Terminal and running the "
"following command:"
msgstr ""
+"Vous pouvez contrôler la progression manuellement en ouvrant un Terminal et "
+"en exécutant la commande suivante :"
#: platform/osx/export/export.cpp
msgid ""
"Run the following command to staple the notarization ticket to the exported "
"application (optional):"
msgstr ""
+"Exécutez la commande suivante pour lier le ticket de certification avec "
+"l'application exporté (optionnel) :"
#: platform/osx/export/export.cpp
msgid "Timestamping is not compatible with ad-hoc signature, and was disabled!"
msgstr ""
+"L'horodatage n'est pas compatible avec la signature ad-hoc et a été "
+"désactivé !"
#: platform/osx/export/export.cpp
msgid ""
@@ -20169,71 +19750,73 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "Built-in CodeSign require regex module."
-msgstr ""
+msgstr "CodeSign intégré nécessite le module regex."
#: platform/osx/export/export.cpp
msgid ""
"Could not start codesign executable, make sure Xcode command line tools are "
"installed."
msgstr ""
+"Ne peut lancer l'exécutable codesign, vérifiez que les outils en ligne de "
+"commande de Xcode sont installés."
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
msgid "No identity found."
msgstr "Aucune identité trouvée."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Cannot sign file %s."
-msgstr "Erreur lors de l'enregistrement du fichier : %s"
+msgstr "Impossible de signer le fichier %s."
#: platform/osx/export/export.cpp
msgid "Relative symlinks are not supported, exported \"%s\" might be broken!"
msgstr ""
+"Les liens symboliques relatifs ne sont pas supportés, « %s » pourrait être "
+"cassé !"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "DMG Creation"
-msgstr "Directions"
+msgstr "Création du DMG"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start hdiutil executable."
-msgstr "Impossible de démarrer le sous-processus !"
+msgstr "Impossible de démarrer le programme hdiutil."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed - file exists."
-msgstr ""
+msgstr "`hdiutil create` a échoué - le fichier existe."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed."
-msgstr ""
+msgstr "`hdiutil create` a échoué."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Creating app bundle"
-msgstr "Création de l'aperçu"
+msgstr "Création du paquet d'application"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not find template app to export: \"%s\"."
-msgstr "Impossible de trouver le modèle de l'application à exporter :"
+msgstr "Impossible de trouver le modèle de l'application à exporter : \"%s\"."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Invalid export format."
-msgstr "Modèle d'exportation non valide :"
+msgstr "Format d'export invalide."
#: platform/osx/export/export.cpp
msgid ""
"Relative symlinks are not supported on this OS, the exported project might "
"be broken!"
msgstr ""
+"Les liens symboliques relatifs ne sont pas supportés sur ce système "
+"d'exploitation, le projet exporté pourrait être cassé !"
#: platform/osx/export/export.cpp
msgid ""
"Requested template binary \"%s\" not found. It might be missing from your "
"template archive."
msgstr ""
+"Le binaire modèle requis « %s » n'a pas été trouvé. Il doit être absent de "
+"votre archive de modèles."
#: platform/osx/export/export.cpp
msgid "Making PKG"
@@ -20244,10 +19827,13 @@ msgid ""
"Ad-hoc signed applications require the 'Disable Library Validation' "
"entitlement to load dynamic libraries."
msgstr ""
+"La signature d'applications ad-hoc nécessite la permission \"Désactiver la "
+"validation de bibliothèque\" pour pouvoir charger dynamiquement les "
+"bibliothèques."
#: platform/osx/export/export.cpp
msgid "Code signing bundle"
-msgstr ""
+msgstr "Paquet de signature du code"
#: platform/osx/export/export.cpp
msgid "Making DMG"
@@ -20255,7 +19841,7 @@ msgstr "Création du DMG"
#: platform/osx/export/export.cpp
msgid "Code signing DMG"
-msgstr ""
+msgstr "DMG de signature du code"
#: platform/osx/export/export.cpp
msgid "Making ZIP"
@@ -20266,20 +19852,20 @@ msgid ""
"Notarization requires the app to be archived first, select the DMG or ZIP "
"export format instead."
msgstr ""
+"La certification nécessite que l'application soit préalablement archivé. "
+"Sélectionnez le format d'exportation DMG ou ZIP à la place."
#: platform/osx/export/export.cpp
msgid "Sending archive for notarization"
-msgstr ""
+msgstr "Envoi de l'archive pour la certification"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "ZIP Creation"
-msgstr "Projet"
+msgstr "Création ZIP"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not open file to read from path \"%s\"."
-msgstr "Impossible d'exporter les fichiers du projet vers le projet gradle\n"
+msgstr "Impossible d'ouvrir le fichier à lire au chemin \"%s\"."
#: platform/osx/export/export.cpp
msgid "Invalid bundle identifier:"
@@ -20290,26 +19876,32 @@ msgid ""
"Warning: Built-in \"codesign\" is selected in the Editor Settings. Code "
"signing is limited to ad-hoc signature only."
msgstr ""
+"Attention : Le « codesign » embarqué est sélectionné dans les paramètres de "
+"l'éditeur. La signature du code se limite à la signature ad-hoc seulement."
#: platform/osx/export/export.cpp
msgid ""
"Warning: Xcode command line tools are not installed, using built-in "
"\"codesign\". Code signing is limited to ad-hoc signature only."
msgstr ""
+"Attention : Les outils en ligne de commande de Xcode ne sont pas installés, "
+"utilisation du « codesign » embarqué. La signature du code se limite à la "
+"signature ad-hoc seulement."
#: platform/osx/export/export.cpp
msgid "Notarization: Notarization with an ad-hoc signature is not supported."
msgstr ""
+"Certification : La certification avec une signature ad-hoc n'est pas "
+"supporté."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization: Code signing is required for notarization."
-msgstr "Certification : signature du code requise."
+msgstr ""
+"Notarisation : La signature du code est nécessaire pour la notarisation."
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization: Hardened runtime is required for notarization."
-msgstr "Certification : exécution renforcée requise."
+msgstr "Notarisation : exécution renforcée nécessaire pour la notarisation."
#: platform/osx/export/export.cpp
#, fuzzy
@@ -20329,12 +19921,17 @@ msgid ""
"Warning: Notarization is disabled. The exported project will be blocked by "
"Gatekeeper if it's downloaded from an unknown source."
msgstr ""
+"Attention : La certification est désactivé. Le projet exporté sera bloqué "
+"par Gatekeeper si il est téléchargé depuis une source inconnue."
#: platform/osx/export/export.cpp
msgid ""
"Code signing is disabled. The exported project will not run on Macs with "
"enabled Gatekeeper and Apple Silicon powered Macs."
msgstr ""
+"La signature du code est désactivé. Le projet exporté ne fonctionnera pas "
+"sur les Macs avec Gatekeeper activé et sous les Macs fonctionnant sous Apple "
+"Silicon."
#: platform/osx/export/export.cpp
msgid ""
@@ -20346,12 +19943,17 @@ msgstr ""
msgid ""
"Timestamping is not compatible with ad-hoc signature, and will be disabled!"
msgstr ""
+"L'horodatage n'est pas compatible avec la signature ad-hoc et a été "
+"désactivé !"
#: platform/osx/export/export.cpp
msgid ""
"Warning: Notarization is not supported from this OS. The exported project "
"will be blocked by Gatekeeper if it's downloaded from an unknown source."
msgstr ""
+"Attention : La certification n'est pas compatible avec ce système "
+"d'exploitation. Le projet exporté sera bloqué par Gatekeeper si il est "
+"téléchargé depuis une source inconnue."
#: platform/osx/export/export.cpp
msgid ""
@@ -20401,21 +20003,19 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "macOS"
-msgstr ""
+msgstr "macOS"
#: platform/osx/export/export.cpp
msgid "Force Builtin Codesign"
-msgstr ""
+msgstr "Forcer CodeSign intégré"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Architecture"
-msgstr "Ajouter une entrée architecture"
+msgstr "Architecture"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Display Name"
-msgstr "Tout afficher"
+msgstr "Afficher le nom"
#: platform/uwp/export/export.cpp
msgid "Short Name"
@@ -20423,118 +20023,107 @@ msgstr "Nom Abrégé"
#: platform/uwp/export/export.cpp
msgid "Publisher"
-msgstr ""
+msgstr "Publicateur"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Publisher Display Name"
-msgstr "Nom d'affichage d'éditeur du paquet invalide."
+msgstr "Nom d'affichage de l'éditeur du paquet"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Product GUID"
-msgstr "GUID produit invalide."
+msgstr "GUID du produit"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Publisher GUID"
-msgstr "Effacé Guides"
+msgstr "GUID du publicateur"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Signing"
-msgstr "Signaux"
+msgstr "Signature"
#: platform/uwp/export/export.cpp
msgid "Certificate"
msgstr "Certificat"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Algorithm"
-msgstr "Débogueur"
+msgstr "Algorithme"
#: platform/uwp/export/export.cpp
msgid "Major"
-msgstr ""
+msgstr "Majeur"
#: platform/uwp/export/export.cpp
msgid "Minor"
-msgstr ""
+msgstr "Mineur"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Build"
-msgstr "Mode Règle"
+msgstr "Build"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Revision"
-msgstr "Expression"
+msgstr "Révision"
#: platform/uwp/export/export.cpp
msgid "Landscape"
-msgstr ""
+msgstr "Paysage"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Portrait"
-msgstr "Retourner les Portals"
+msgstr "Portrait"
#: platform/uwp/export/export.cpp
msgid "Landscape Flipped"
-msgstr ""
+msgstr "Paysage Inversé"
#: platform/uwp/export/export.cpp
msgid "Portrait Flipped"
-msgstr ""
+msgstr "Portrait Inversé"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Store Logo"
-msgstr "Mode mise à l'échelle"
+msgstr "Logo du magasin"
#: platform/uwp/export/export.cpp
msgid "Square 44 X 44 Logo"
-msgstr ""
+msgstr "Logo 44 X 44 Carré"
#: platform/uwp/export/export.cpp
msgid "Square 71 X 71 Logo"
-msgstr ""
+msgstr "Logo 71 X 71 Carré"
#: platform/uwp/export/export.cpp
msgid "Square 150 X 150 Logo"
-msgstr ""
+msgstr "Logo 150 X 150 Carré"
#: platform/uwp/export/export.cpp
msgid "Square 310 X 310 Logo"
-msgstr ""
+msgstr "Logo 310 X 310 Carré"
#: platform/uwp/export/export.cpp
msgid "Wide 310 X 150 Logo"
-msgstr ""
+msgstr "Logo 310 X 150 Large"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Splash Screen"
-msgstr "Appels de dessin :"
+msgstr "Écran de chargement"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Tiles"
-msgstr "Fichier"
+msgstr "Tuiles"
#: platform/uwp/export/export.cpp
msgid "Show Name On Square 150 X 150"
-msgstr ""
+msgstr "Afficher le nom sur le carré 150 X 150"
#: platform/uwp/export/export.cpp
msgid "Show Name On Wide 310 X 150"
-msgstr ""
+msgstr "Afficher le nom sur le large 310 X 150"
#: platform/uwp/export/export.cpp
msgid "Show Name On Square 310 X 310"
-msgstr ""
+msgstr "Afficher le nom sur le carré 310 X 310"
#: platform/uwp/export/export.cpp
msgid "Invalid package short name."
@@ -20603,34 +20192,31 @@ msgstr ""
#: platform/uwp/export/export.cpp
msgid "UWP"
-msgstr ""
+msgstr "UWP"
#: platform/uwp/export/export.cpp platform/windows/export/export.cpp
-#, fuzzy
msgid "Signtool"
-msgstr "Signaux"
+msgstr "Signtool"
#: platform/uwp/export/export.cpp
msgid "Debug Certificate"
-msgstr ""
+msgstr "Certificat de Débogage"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Debug Algorithm"
-msgstr "Débogueur"
+msgstr "Algorithme de débogage"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Failed to rename temporary file \"%s\"."
-msgstr "Impossible de supprimer le fichier temporaire :"
+msgstr "Impossible de renommer le fichier temporaire \"%s\"."
#: platform/windows/export/export.cpp
msgid "Identity Type"
-msgstr ""
+msgstr "Type d'identité"
#: platform/windows/export/export.cpp
msgid "Timestamp Server URL"
-msgstr ""
+msgstr "URL du serveur d'horodatage"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20638,14 +20224,12 @@ msgid "Digest Algorithm"
msgstr "Débogueur"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Modify Resources"
-msgstr "Copier la ressource"
+msgstr "Modifier les ressources"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "File Version"
-msgstr "Version"
+msgstr "Version de fichier"
#: platform/windows/export/export.cpp
msgid "Product Version"
@@ -20660,18 +20244,16 @@ msgid "Product Name"
msgstr "Nom du produit"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "File Description"
-msgstr "Description"
+msgstr "Description de fichier"
#: platform/windows/export/export.cpp
msgid "Trademarks"
-msgstr ""
+msgstr "Marques Déposées"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Resources Modification"
-msgstr "Rotation aléatoire :"
+msgstr "Modification de ressources"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20686,59 +20268,52 @@ msgstr "Impossible de trouver le keystore, impossible d'exporter."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
"L'outil « rcedit » doit être configuré dans les préférences de l'éditeur "
"(Exporter > Windows > Rcedit) for modifier l'icône ou les informations de "
"l'application."
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+msgid "rcedit failed to modify executable: %s."
+msgstr "rcedit n'a pas réussi à modifier l'exécutable : %s."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Could not find signtool executable at \"%s\"."
-msgstr "Impossible de trouver le keystore, impossible d'exporter."
+msgstr "Impossible de trouver l’exécutable signtool à \"%s\"."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Could not find osslsigncode executable at \"%s\"."
-msgstr "Impossible de trouver le keystore, impossible d'exporter."
+msgstr "Impossible de trouver l’exécutable osslsigncode à \"%s\"."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Invalid identity type."
-msgstr "Identifiant invalide :"
+msgstr "Type d'identité invalide."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Invalid timestamp server."
-msgstr "Nom invalide."
+msgstr "Server d'horodatage invalide."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
"L'outil « rcedit » doit être configuré dans les préférences de l'éditeur "
"(Exporter > Windows > Rcedit) for modifier l'icône ou les informations de "
"l'application."
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+msgid "Signtool failed to sign executable: %s."
+msgstr "La signature de l’exécutable avec Signtool a échoué : %s."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Failed to remove temporary file \"%s\"."
-msgstr "Impossible de supprimer le fichier temporaire :"
+msgstr "Impossible de supprimer le fichier temporaire \"%s\"."
#: platform/windows/export/export.cpp
msgid ""
@@ -20763,7 +20338,7 @@ msgstr "Version du produit invalide :"
#: platform/windows/export/export.cpp
msgid "Windows executables cannot be >= 4 GiB."
-msgstr ""
+msgstr "Les exécutables Windows ne peuvent pas peser >= 4Gio."
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
#, fuzzy
@@ -20772,38 +20347,37 @@ msgstr "Fichier exécutable invalide."
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
msgid "Executable file header corrupted."
-msgstr ""
+msgstr "Entête du fichier exécutable corrompue."
#: platform/windows/export/export.cpp platform/x11/export/export.cpp
msgid "Executable \"pck\" section not found."
-msgstr ""
+msgstr "Section \"pck\" de l’exécutable non trouvée."
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Windows"
-msgstr "Nouvelle Fenêtre"
+msgstr "Windows"
#: platform/windows/export/export.cpp
msgid "Rcedit"
-msgstr ""
+msgstr "Rcedit"
#: platform/windows/export/export.cpp
msgid "Osslsigncode"
-msgstr ""
+msgstr "Osslsigncode"
#: platform/windows/export/export.cpp
msgid "Wine"
-msgstr ""
+msgstr "Wine"
#: platform/x11/export/export.cpp
msgid "32-bit executables cannot have embedded data >= 4 GiB."
msgstr ""
+"les exécutables 32 bits ne peuvent pas contenir de données pesant >= 4Gio."
#: scene/2d/animated_sprite.cpp scene/3d/sprite_3d.cpp
#: scene/resources/texture.cpp
-#, fuzzy
msgid "Frames"
-msgstr "Image %"
+msgstr "Trames"
#: scene/2d/animated_sprite.cpp
msgid ""
@@ -20815,71 +20389,61 @@ msgstr ""
#: scene/2d/animated_sprite.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Speed Scale"
-msgstr "Mode mise à l'échelle"
+msgstr "Échelle de vitesse"
#: scene/2d/animated_sprite.cpp scene/2d/audio_stream_player_2d.cpp
#: scene/3d/audio_stream_player_3d.cpp scene/3d/sprite_3d.cpp
#: scene/audio/audio_stream_player.cpp
-#, fuzzy
msgid "Playing"
-msgstr "Jouer"
+msgstr "En train de jouer"
#: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
-#, fuzzy
msgid "Centered"
-msgstr "Centre"
+msgstr "Centré"
#: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#: scene/gui/texture_button.cpp scene/gui/texture_rect.cpp
msgid "Flip H"
-msgstr ""
+msgstr "Miroir H"
#: scene/2d/animated_sprite.cpp scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#: scene/gui/texture_button.cpp scene/gui/texture_rect.cpp
msgid "Flip V"
-msgstr ""
+msgstr "Miroir V"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Monitoring"
-msgstr "Moniteur"
+msgstr "Observation"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Monitorable"
-msgstr "Moniteur"
+msgstr "Observable"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Physics Overrides"
-msgstr "Redéfinition"
+msgstr "Redéfinitions de physique"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Space Override"
-msgstr "Redéfinition"
+msgstr "Redéfinition d'espace"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Gravity Point"
-msgstr "Générer des points"
+msgstr "Gravité ponctuelle"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Gravity Distance Scale"
-msgstr "WaitInstanceSignal"
+msgstr "Échelle de distance de gravité"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Gravity Vec"
-msgstr "Aperçu par défaut"
+msgstr "Vecteur de gravité"
#: scene/2d/area_2d.cpp scene/2d/cpu_particles_2d.cpp scene/3d/area.cpp
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
msgid "Gravity"
-msgstr ""
+msgstr "Gravité"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
#, fuzzy
@@ -20891,38 +20455,33 @@ msgid "Angular Damp"
msgstr ""
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Audio Bus"
-msgstr "Ajouter un bus audio"
+msgstr "Bus audio"
#: scene/2d/area_2d.cpp scene/3d/area.cpp
-#, fuzzy
msgid "Override"
msgstr "Redéfinition"
#: scene/2d/audio_stream_player_2d.cpp scene/audio/audio_stream_player.cpp
#: scene/gui/video_player.cpp servers/audio/effects/audio_effect_amplify.cpp
-#, fuzzy
msgid "Volume dB"
-msgstr "Volume"
+msgstr "Volume (dB)"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp
#: servers/audio/effects/audio_effect_pitch_shift.cpp
-#, fuzzy
msgid "Pitch Scale"
-msgstr "Mode mise à l'échelle"
+msgstr "Échelle de pitch"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
-#, fuzzy
msgid "Autoplay"
-msgstr "Activer/désactiver la lecture automatique"
+msgstr "Lecture automatique"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp
msgid "Stream Paused"
-msgstr ""
+msgstr "Diffusion en pause"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/3d/light.cpp scene/3d/reflection_probe.cpp
@@ -20932,34 +20491,29 @@ msgid "Max Distance"
msgstr "Distance Maximale"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/light.cpp
-#, fuzzy
msgid "Attenuation"
-msgstr "Animation"
+msgstr "Atténuation"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
-#, fuzzy
msgid "Bus"
-msgstr "Ajouter un bus"
+msgstr "Bus"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
msgid "Area Mask"
-msgstr ""
+msgstr "Masque de zone"
#: scene/2d/back_buffer_copy.cpp
-#, fuzzy
msgid "Copy Mode"
-msgstr "Copier les nœuds"
+msgstr "Mode copie"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Anchor Mode"
-msgstr "Mode Icône"
+msgstr "Mode ancre"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Rotating"
-msgstr "Pas de la rotation :"
+msgstr "En rotation"
#: scene/2d/camera_2d.cpp scene/2d/listener_2d.cpp scene/3d/camera.cpp
#: scene/3d/listener.cpp scene/animation/animation_blend_tree.cpp
@@ -20967,16 +20521,14 @@ msgid "Current"
msgstr "Actuel"
#: scene/2d/camera_2d.cpp scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Zoom"
msgstr "Zoomer"
#: scene/2d/camera_2d.cpp scene/main/canvas_layer.cpp
-#, fuzzy
msgid "Custom Viewport"
-msgstr "1 vue"
+msgstr "Vue personnalisée"
-#: 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
@@ -20985,26 +20537,23 @@ msgstr "Mode déplacement"
#: scene/2d/camera_2d.cpp
msgid "Limit"
-msgstr ""
+msgstr "Limite"
#: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp
#: scene/resources/style_box.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Left"
-msgstr "En haut à gauche"
+msgstr "Gauche"
#: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp
#: scene/resources/style_box.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Right"
-msgstr "Lumière"
+msgstr "Droite"
#: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp
#: scene/resources/dynamic_font.cpp scene/resources/style_box.cpp
#: scene/resources/texture.cpp
-#, fuzzy
msgid "Bottom"
-msgstr "En bas à gauche"
+msgstr "Bas"
#: scene/2d/camera_2d.cpp
#, fuzzy
@@ -21012,9 +20561,8 @@ msgid "Smoothed"
msgstr "Progression douce"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Draw Margin"
-msgstr "Définir la marge"
+msgstr "Afficher les marges"
#: scene/2d/camera_2d.cpp
#, fuzzy
@@ -21033,27 +20581,24 @@ msgstr "Progression douce"
#: scene/2d/camera_2d.cpp
msgid "H"
-msgstr ""
+msgstr "H"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "V"
-msgstr "UV"
+msgstr "V"
#: scene/2d/camera_2d.cpp
#, fuzzy
msgid "Drag Margin"
-msgstr "Définir la marge"
+msgstr "Tirer la marge"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Draw Screen"
-msgstr "Appels de dessin :"
+msgstr "Afficher l'écran"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Draw Limits"
-msgstr "Appels de dessin :"
+msgstr "Afficher les limites"
#: scene/2d/camera_2d.cpp
#, fuzzy
@@ -21062,43 +20607,37 @@ msgstr "Définir la marge"
#: scene/2d/canvas_item.cpp scene/resources/environment.cpp
#: scene/resources/material.cpp
-#, fuzzy
msgid "Blend Mode"
-msgstr "Nœud Blend2"
+msgstr "Mode mélange"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Light Mode"
-msgstr "Étendu à Droite"
+msgstr "Mode de lumière"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Particles Animation"
-msgstr "Particules"
+msgstr "Animation de particules"
#: scene/2d/canvas_item.cpp
msgid "Particles Anim H Frames"
-msgstr ""
+msgstr "Trames d'animation H de particules"
#: scene/2d/canvas_item.cpp
msgid "Particles Anim V Frames"
-msgstr ""
+msgstr "Trames d'animation V de particules"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Particles Anim Loop"
-msgstr "Particules"
+msgstr "Boucle d'animation de particules"
#: scene/2d/canvas_item.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Visibility"
-msgstr "Basculer la visibilité"
+msgstr "Visibilité"
#: scene/2d/canvas_item.cpp scene/3d/spatial.cpp scene/gui/progress_bar.cpp
#: scene/gui/rich_text_effect.cpp scene/main/canvas_layer.cpp
-#, fuzzy
msgid "Visible"
-msgstr "Basculer la visibilité"
+msgstr "Visible"
#: scene/2d/canvas_item.cpp
#, fuzzy
@@ -21107,22 +20646,20 @@ msgstr "Peupler"
#: scene/2d/canvas_item.cpp
msgid "Show Behind Parent"
-msgstr ""
+msgstr "Montrer derrière le parent"
#: scene/2d/canvas_item.cpp
-#, fuzzy
msgid "Show On Top"
-msgstr "Afficher l'origine"
+msgstr "Montrer au dessus"
#: scene/2d/canvas_item.cpp scene/2d/light_occluder_2d.cpp
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Light Mask"
-msgstr "LightMap Bake"
+msgstr "Masque de lumières"
#: scene/2d/canvas_item.cpp
msgid "Use Parent Material"
-msgstr ""
+msgstr "Utiliser le matériau du parent"
#: scene/2d/canvas_modulate.cpp
msgid ""
@@ -21144,9 +20681,8 @@ msgstr ""
"qu'enfant pour définir sa forme."
#: scene/2d/collision_object_2d.cpp
-#, fuzzy
msgid "Pickable"
-msgstr "Sélectionner une tuile"
+msgstr "Déplaçable"
#: scene/2d/collision_polygon_2d.cpp
msgid ""
@@ -21178,29 +20714,27 @@ msgstr ""
msgid ""
"The One Way Collision property will be ignored when the parent is an Area2D."
msgstr ""
+"La propriété Collision à sens unique est ignorée lorsque le parent est un "
+"Area2D."
#: scene/2d/collision_polygon_2d.cpp
-#, fuzzy
msgid "Build Mode"
-msgstr "Mode Règle"
+msgstr "Mode construction"
#: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp
#: scene/3d/collision_polygon.cpp scene/3d/collision_shape.cpp
#: scene/animation/animation_node_state_machine.cpp scene/gui/base_button.cpp
#: scene/gui/texture_button.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Disabled"
-msgstr "Item désactivé"
+msgstr "Désactivé"
#: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp
-#, fuzzy
msgid "One Way Collision"
-msgstr "Créer le polygone de collision"
+msgstr "Collision à sens unique"
#: scene/2d/collision_polygon_2d.cpp scene/2d/collision_shape_2d.cpp
-#, fuzzy
msgid "One Way Collision Margin"
-msgstr "Créer le polygone de collision"
+msgstr "marge de collision à sens unique"
#: scene/2d/collision_shape_2d.cpp
msgid ""
@@ -21239,31 +20773,28 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Emitting"
-msgstr "Paramètres :"
+msgstr "Émet"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Lifetime"
-msgstr ""
+msgstr "Durée de vie"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp scene/main/timer.cpp
-#, fuzzy
msgid "One Shot"
-msgstr "Nœud one-shot"
+msgstr "Jouer une fois"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Preprocess"
-msgstr "Post-traitement"
+msgstr "Pré-traitement"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Explosiveness"
-msgstr ""
+msgstr "Explovisité"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -21273,13 +20804,12 @@ msgstr "Aléatoire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Lifetime Randomness"
-msgstr ""
+msgstr "Aléatoire de durée de vie"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Fixed FPS"
-msgstr "Voir Images par secondes"
+msgstr "FPS fixes"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -21293,20 +20823,18 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Local Coords"
-msgstr "Projets locaux"
+msgstr "Coordonnées locales"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Draw Order"
-msgstr ""
+msgstr "Ordre de rendu"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Emission Shape"
-msgstr "Masque d'émission"
+msgstr "Forme d'émission"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21319,63 +20847,55 @@ msgid "Rect Extents"
msgstr "Gadgets"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
-#, fuzzy
msgid "Normals"
-msgstr "Format"
+msgstr "Normales"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Align Y"
-msgstr "Assigner"
+msgstr "Aligner axe Y"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Direction"
-msgstr "Directions"
+msgstr "Direction"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Spread"
-msgstr ""
+msgstr "Propagation"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Initial Velocity"
-msgstr "Initialiser"
+msgstr "Vélocité initiale"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Velocity Random"
-msgstr "Vue de l'orbite vers la droite"
+msgstr "Vélocité aléatoire"
#: 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
msgid "Angular Velocity"
-msgstr ""
+msgstr "Vélocité angulaire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Velocity Curve"
-msgstr "Vue de l'orbite vers la droite"
+msgstr "Courbe de vélocité"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Orbit Velocity"
-msgstr "Vue de l'orbite vers la droite"
+msgstr "Vélocité d'orbite"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Linear Accel"
-msgstr "Linéaire"
+msgstr "Accélération linéaire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21385,23 +20905,22 @@ msgstr "Accel"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Accel Random"
-msgstr ""
+msgstr "Accélération aléatoire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Accel Curve"
-msgstr "Scinder la courbe"
+msgstr "Courbe d’accélération"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Radial Accel"
-msgstr ""
+msgstr "Accélération radiale"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Tangential Accel"
-msgstr ""
+msgstr "Accélération tangentielle"
#: scene/2d/cpu_particles_2d.cpp scene/2d/joints_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/physics_body.cpp
@@ -21409,39 +20928,37 @@ msgstr ""
#: scene/resources/particles_material.cpp
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Damping"
-msgstr ""
+msgstr "Amortissement"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Damping Random"
-msgstr ""
+msgstr "Amortissement aléatoire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Damping Curve"
-msgstr "Scinder la courbe"
+msgstr "Courbe d'amortissement"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/light.cpp
#: scene/resources/particles_material.cpp
msgid "Angle"
-msgstr ""
+msgstr "Angle"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Angle Random"
-msgstr ""
+msgstr "Angle aléatoire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Angle Curve"
-msgstr "Fermer la courbe"
+msgstr "Courbe d'angle"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#, fuzzy
msgid "Scale Amount"
-msgstr "Quantité :"
+msgstr "Valeur d'échelle"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
msgid "Scale Amount Random"
@@ -21454,14 +20971,13 @@ msgstr "Agrandir/Rétrécir à partir du curseur"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Color Ramp"
-msgstr "Couleurs"
+msgstr "Dégradé de couleurs"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
msgid "Color Initial Ramp"
-msgstr ""
+msgstr "Dégradé de couleurs initial"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21480,33 +20996,28 @@ msgstr "Variation aléatoire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Variation Curve"
-msgstr "Séparation :"
+msgstr "Courbe de variation"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Speed Random"
-msgstr "Mode mise à l'échelle"
+msgstr "Vitesse aléatoire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Speed Curve"
-msgstr "Scinder la courbe"
+msgstr "Courbe de vitesse"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Offset Random"
-msgstr "Décalage :"
+msgstr "Décalage de l'aléatoire"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Offset Curve"
-msgstr "Fermer la courbe"
+msgstr "Courbe de décalage"
#: scene/2d/joints_2d.cpp
msgid "Node A and Node B must be PhysicsBody2Ds"
@@ -21529,39 +21040,35 @@ msgid "Node A and Node B must be different PhysicsBody2Ds"
msgstr "Node A et Node B doivent être des PhysicsBody2D différents"
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Node A"
-msgstr "Nœud"
+msgstr "Nœud A"
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Node B"
-msgstr "Nœud"
+msgstr "Nœud B"
#: scene/2d/joints_2d.cpp scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/light.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
#: scene/resources/environment.cpp
msgid "Bias"
-msgstr ""
+msgstr "Biais"
#: scene/2d/joints_2d.cpp
-#, fuzzy
msgid "Disable Collision"
-msgstr "Bouton désactivé"
+msgstr "Désactiver les collisions"
#: scene/2d/joints_2d.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Softness"
-msgstr ""
+msgstr "Douceur"
#: scene/2d/joints_2d.cpp scene/resources/animation.cpp
#: scene/resources/ray_shape.cpp scene/resources/segment_shape_2d.cpp
msgid "Length"
-msgstr ""
+msgstr "Longueur"
#: scene/2d/joints_2d.cpp
-#, fuzzy
msgid "Initial Offset"
-msgstr "Initialiser"
+msgstr "Décalage initial"
#: scene/2d/joints_2d.cpp scene/3d/vehicle_body.cpp
msgid "Rest Length"
@@ -21569,7 +21076,7 @@ msgstr ""
#: scene/2d/joints_2d.cpp scene/3d/physics_joint.cpp scene/3d/vehicle_body.cpp
msgid "Stiffness"
-msgstr ""
+msgstr "Rigidité"
#: scene/2d/light_2d.cpp
msgid ""
@@ -21580,57 +21087,50 @@ msgstr ""
"« Texture »."
#: scene/2d/light_2d.cpp scene/3d/light.cpp scene/gui/reference_rect.cpp
-#, fuzzy
msgid "Editor Only"
-msgstr "Éditeur"
+msgstr "Éditeur seulement"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Texture Scale"
-msgstr "RegionDeTexture"
+msgstr "Échelle de texture"
#: scene/2d/light_2d.cpp scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/light.cpp scene/resources/environment.cpp
#: scene/resources/material.cpp scene/resources/sky.cpp
msgid "Energy"
-msgstr ""
+msgstr "Énergie"
#: scene/2d/light_2d.cpp
msgid "Z Min"
-msgstr ""
+msgstr "Minimum Z"
#: scene/2d/light_2d.cpp
msgid "Z Max"
-msgstr ""
+msgstr "Maximum Z"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Layer Min"
-msgstr "Changer la taille d'une caméra"
+msgstr "Calque min"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Layer Max"
-msgstr "Calque"
+msgstr "Calque max"
#: scene/2d/light_2d.cpp
msgid "Item Cull Mask"
msgstr ""
#: scene/2d/light_2d.cpp scene/3d/light.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Shadow"
-msgstr "Ombrage"
+msgstr "Ombre"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Buffer Size"
-msgstr "Vue de derrière"
+msgstr "Taille de tampon"
#: scene/2d/light_2d.cpp
-#, fuzzy
msgid "Gradient Length"
-msgstr "Dégradé édité"
+msgstr "Longueur du dégradé"
#: scene/2d/light_2d.cpp
#, fuzzy
@@ -21638,9 +21138,8 @@ msgid "Filter Smooth"
msgstr "Filtrer les méthodes"
#: scene/2d/light_occluder_2d.cpp
-#, fuzzy
msgid "Closed"
-msgstr "Fermer"
+msgstr "Fermé"
#: scene/2d/light_occluder_2d.cpp scene/resources/material.cpp
#, fuzzy
@@ -21661,37 +21160,32 @@ msgstr ""
"polygone."
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Width Curve"
-msgstr "Scinder la courbe"
+msgstr "Courbe de largeur"
#: scene/2d/line_2d.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Default Color"
-msgstr "Défaut"
+msgstr "Couleur par défaut"
#: scene/2d/line_2d.cpp scene/resources/texture.cpp
msgid "Fill"
-msgstr ""
+msgstr "Remplissage"
#: scene/2d/line_2d.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Gradient"
-msgstr "Dégradé édité"
+msgstr "Dégradé"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Texture Mode"
-msgstr "RegionDeTexture"
+msgstr "Mode de texture"
#: scene/2d/line_2d.cpp
msgid "Capping"
-msgstr ""
+msgstr "Capuchonnement"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "Joint Mode"
-msgstr "Mode Icône"
+msgstr "Mode de jointure"
#: scene/2d/line_2d.cpp
#, fuzzy
@@ -21699,14 +21193,12 @@ msgid "Begin Cap Mode"
msgstr "Mode Région"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "End Cap Mode"
-msgstr "Mode d'aimantation :"
+msgstr "Mode du capuchon de fin"
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Border"
-msgstr "dans l'ordre :"
+msgstr "Bordure"
#: scene/2d/line_2d.cpp
msgid "Sharp Limit"
@@ -21714,13 +21206,12 @@ msgstr ""
#: scene/2d/line_2d.cpp
msgid "Round Precision"
-msgstr ""
+msgstr "Précision de l’arrondissement"
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp
#: scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Antialiased"
-msgstr "Initialiser"
+msgstr "Anticrénelé"
#: scene/2d/multimesh_instance_2d.cpp scene/3d/multimesh_instance.cpp
#, fuzzy
@@ -21731,12 +21222,11 @@ msgstr "Multiplier %s"
#: scene/3d/navigation.cpp scene/animation/root_motion_view.cpp
#: scene/resources/world_2d.cpp servers/physics_2d/physics_2d_server_sw.cpp
msgid "Cell Size"
-msgstr ""
+msgstr "Taille des Cellules"
#: scene/2d/navigation_2d.cpp scene/3d/navigation.cpp
-#, fuzzy
msgid "Edge Connection Margin"
-msgstr "Modifier la connexion :"
+msgstr "Marge de connexion des bords"
#: scene/2d/navigation_2d.cpp
msgid ""
@@ -21744,23 +21234,42 @@ msgid ""
"will be removed in a future version. Use 'Navigation2DServer.map_get_path()' "
"instead."
msgstr ""
+"Le nœud « Navigation2D » et « Navigation2D.get_simple_path() » sont "
+"obsolètes et seront supprimés dans une future version. Utilisez « "
+"Navigation2DServer.map_get_path() » à la place."
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Pathfinding"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
-msgstr "Choisissez distance :"
+msgstr "Distance souhaitée du chemin"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Target Desired Distance"
-msgstr ""
+msgstr "Distance Désirée de la Cible"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr "Distance maximale du chemin"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Avoidance"
+msgstr "Évitement"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Avoidance Enabled"
+msgstr "Évitement activé"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
-msgstr ""
+msgstr "Distance des voisins"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Max Neighbors"
-msgstr ""
+msgstr "Maximum de voisins"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
@@ -21768,30 +21277,19 @@ msgid "Time Horizon"
msgstr "Retourner horizontalement"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
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"
+msgstr "Vitesse Max"
#: scene/2d/navigation_agent_2d.cpp
-#, fuzzy
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
-msgstr "Le NavigationAgent2D ne peut être utilisé que sous un nœud Node2D."
+msgstr ""
+"Le NavigationAgent2D ne peut être utilisé que sous un nœud dont le parent "
+"hérite de Node2D."
#: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_obstacle.cpp
-#, fuzzy
msgid "Estimate Radius"
-msgstr "Changer le rayon extérieur de la tour"
+msgstr "Estimer le rayon"
#: scene/2d/navigation_obstacle_2d.cpp
msgid ""
@@ -21812,74 +21310,65 @@ msgstr ""
#: scene/2d/navigation_polygon.cpp
msgid "Navpoly"
-msgstr ""
+msgstr "Polygone de navigation"
#: scene/2d/navigation_polygon.cpp scene/3d/navigation_mesh_instance.cpp
-#, fuzzy
msgid "Enter Cost"
-msgstr "Centrée en bas"
+msgstr "Coût d’entrée"
#: scene/2d/navigation_polygon.cpp scene/3d/navigation_mesh_instance.cpp
-#, fuzzy
msgid "Travel Cost"
-msgstr "Se déplacer"
+msgstr "Coût de déplacement"
#: scene/2d/node_2d.cpp scene/2d/polygon_2d.cpp scene/3d/spatial.cpp
#: scene/main/canvas_layer.cpp
msgid "Rotation Degrees"
msgstr "Degrés de Rotation"
-#: scene/2d/node_2d.cpp
-#, fuzzy
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
-msgstr "Constante globale"
+msgstr "Rotation Globale"
#: scene/2d/node_2d.cpp
msgid "Global Rotation Degrees"
msgstr "Degrés de Rotation Globale"
#: scene/2d/node_2d.cpp
-#, fuzzy
msgid "Global Scale"
-msgstr "Échelle aléatoire :"
+msgstr "Échelle Globale"
#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Global Transform"
-msgstr "Conserver la transformation globale"
+msgstr "Transformation Globale"
#: scene/2d/node_2d.cpp
-#, fuzzy
msgid "Z As Relative"
-msgstr "Alignement relatif"
+msgstr "Z En tant que relatif"
#: scene/2d/parallax_background.cpp scene/gui/scroll_container.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Scroll"
-msgstr ""
+msgstr "Défilement"
#: scene/2d/parallax_background.cpp
-#, fuzzy
msgid "Base Offset"
-msgstr "Décalage :"
+msgstr "Décalage de Base"
#: scene/2d/parallax_background.cpp
-#, fuzzy
msgid "Base Scale"
-msgstr "Utiliser le magnétisme d'échelle"
+msgstr "Échelle de Base"
#: scene/2d/parallax_background.cpp
msgid "Limit Begin"
-msgstr ""
+msgstr "Début de la limite"
#: scene/2d/parallax_background.cpp
-#, fuzzy
msgid "Limit End"
-msgstr "À la fin"
+msgstr "Fin de la limite"
#: scene/2d/parallax_background.cpp
msgid "Ignore Camera Zoom"
-msgstr ""
+msgstr "Ignorer le zoom de la Caméra"
#: scene/2d/parallax_layer.cpp
msgid ""
@@ -21891,14 +21380,12 @@ msgstr ""
#: scene/2d/parallax_layer.cpp scene/2d/physics_body_2d.cpp
#: scene/3d/physics_body.cpp scene/3d/vehicle_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Motion"
-msgstr "Action"
+msgstr "Déplacement"
#: scene/2d/parallax_layer.cpp
-#, fuzzy
msgid "Mirroring"
-msgstr "Miroir"
+msgstr "Effet de miroir"
#: scene/2d/particles_2d.cpp
msgid ""
@@ -21942,19 +21429,17 @@ msgstr ""
"Animation » activé."
#: scene/2d/particles_2d.cpp
-#, fuzzy
msgid "Visibility Rect"
-msgstr "Mode prioritaire"
+msgstr "Zone de Visibilité"
#: scene/2d/particles_2d.cpp scene/3d/particles.cpp
msgid "Process Material"
-msgstr ""
+msgstr "Matériau"
#: scene/2d/path_2d.cpp scene/3d/path.cpp scene/resources/sky.cpp
#: scene/resources/texture.cpp
-#, fuzzy
msgid "Curve"
-msgstr "Scinder la courbe"
+msgstr "Courbe"
#: scene/2d/path_2d.cpp
msgid "PathFollow2D only works when set as a child of a Path2D node."
@@ -21963,63 +21448,55 @@ msgstr ""
"d'un nœud de type Path2D."
#: scene/2d/path_2d.cpp scene/3d/path.cpp
-#, fuzzy
msgid "Unit Offset"
-msgstr "Décalage de la grille :"
+msgstr "Décalage d'unité"
#: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp
-#, fuzzy
msgid "H Offset"
-msgstr "Décalage :"
+msgstr "Décalage Horizontal"
#: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp
-#, fuzzy
msgid "V Offset"
-msgstr "Décalage :"
+msgstr "Décalage Vertical"
#: scene/2d/path_2d.cpp scene/3d/path.cpp
msgid "Cubic Interp"
-msgstr ""
+msgstr "Interpolation Cubique"
#: scene/2d/path_2d.cpp
msgid "Lookahead"
-msgstr ""
+msgstr "Anticipation"
#: scene/2d/physics_body_2d.cpp scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Layers"
-msgstr "Calque"
+msgstr "Calques"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Constant Linear Velocity"
-msgstr "Initialiser"
+msgstr "Vélocité Linéaire Constante"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Constant Angular Velocity"
-msgstr "Initialiser"
+msgstr "Vélocité Angulaire Constante"
#: scene/2d/physics_body_2d.cpp scene/2d/tile_map.cpp scene/3d/physics_body.cpp
#: scene/resources/physics_material.cpp
-#, fuzzy
msgid "Friction"
-msgstr "Fonction"
+msgstr "Friction"
#: scene/2d/physics_body_2d.cpp scene/2d/tile_map.cpp scene/3d/physics_body.cpp
#: scene/resources/physics_material.cpp
msgid "Bounce"
-msgstr ""
+msgstr "Rebond"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Physics Material Override"
-msgstr ""
+msgstr "Surcharge du Matériau Des Physiques"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: scene/resources/world.cpp scene/resources/world_2d.cpp
-#, fuzzy
msgid "Default Gravity"
-msgstr "Aperçu par défaut"
+msgstr "Gravité par Défaut"
#: scene/2d/physics_body_2d.cpp
msgid ""
@@ -22033,81 +21510,72 @@ msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Mass"
-msgstr ""
+msgstr "Masse"
#: scene/2d/physics_body_2d.cpp
-#, fuzzy
msgid "Inertia"
-msgstr "Vertical :"
+msgstr "Inertie"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Weight"
-msgstr "Lumière"
+msgstr "Poids"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Gravity Scale"
-msgstr ""
+msgstr "Échelle de la Gravité"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Custom Integrator"
-msgstr "Nœud Personnalisé"
+msgstr "Intégrateur personnalisé"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Continuous CD"
-msgstr "Continu"
+msgstr "Détection de collision continue"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Contacts Reported"
-msgstr ""
+msgstr "Contact Rapporté"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Contact Monitor"
-msgstr "Prélever une couleur"
+msgstr "Moniteur de Contact"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Sleeping"
-msgstr "Magnétisme intelligent"
+msgstr "Sommeil"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Can Sleep"
-msgstr "Vitesse :"
+msgstr "Peut Dormir"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Damp"
-msgstr ""
+msgstr "Atténuation"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Angular"
-msgstr ""
+msgstr "Angulaire"
#: scene/2d/physics_body_2d.cpp
msgid "Applied Forces"
-msgstr ""
+msgstr "Forces Appliquées"
#: scene/2d/physics_body_2d.cpp
msgid "Torque"
-msgstr ""
+msgstr "Torque"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Safe Margin"
-msgstr "Définir la marge"
+msgstr "Marge de sécurité"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Sync To Physics"
msgstr "Synchroniser Avec La Physique"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Moving Platform"
-msgstr "Déplacement du résultat"
+msgstr "Plateforme mobile"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Apply Velocity On Leave"
@@ -22117,71 +21585,61 @@ msgstr ""
#: scene/3d/physics_body.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
#: scene/resources/line_shape_2d.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Normal"
-msgstr "Format"
+msgstr "Normale"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Remainder"
-msgstr "Moteur de rendu :"
+msgstr "Reste"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Local Shape"
-msgstr "Localisation"
+msgstr "Forme Locale"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collider"
-msgstr "Mode collision"
+msgstr "Collisionneur"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Collider ID"
-msgstr ""
+msgstr "ID Du Collisionneur"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collider RID"
-msgstr "RID invalide"
+msgstr "RID Du Collisionneur"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collider Shape"
-msgstr "Mode collision"
+msgstr "Forme Du Collisionneur"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Collider Shape Index"
-msgstr "Mode collision"
+msgstr "Index De La Forme Du Collisionneur"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collider Velocity"
-msgstr "Vue de l'orbite vers la droite"
+msgstr "Vélocité Du Collisionneur"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Collider Metadata"
-msgstr ""
+msgstr "Méta-Données Du Collisionneur"
#: scene/2d/polygon_2d.cpp
msgid "Invert"
-msgstr ""
+msgstr "Inverser"
#: scene/2d/polygon_2d.cpp
-#, fuzzy
msgid "Vertex Colors"
-msgstr "Vertex"
+msgstr "Couleurs Des Sommets"
#: scene/2d/polygon_2d.cpp
-#, fuzzy
msgid "Internal Vertex Count"
-msgstr "Créer un vertex interne"
+msgstr "Nombre de Sommet Interne"
#: scene/2d/position_2d.cpp
#, fuzzy
@@ -22190,24 +21648,23 @@ msgstr "Gadgets"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Exclude Parent"
-msgstr ""
+msgstr "Exclure Le Parent"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
-#, fuzzy
msgid "Cast To"
-msgstr "Créer un nœud Shader"
+msgstr "Lancer vers"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Collide With"
-msgstr ""
+msgstr "Collisionne Avec"
#: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp
msgid "Areas"
-msgstr ""
+msgstr "Zones"
#: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp
msgid "Bodies"
-msgstr ""
+msgstr "Corps"
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -22216,24 +21673,20 @@ msgstr ""
"fonctionner."
#: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp
-#, fuzzy
msgid "Remote Path"
-msgstr "Supprimer un point"
+msgstr "Chemin distant"
#: scene/2d/remote_transform_2d.cpp scene/3d/remote_transform.cpp
-#, fuzzy
msgid "Use Global Coordinates"
-msgstr "Coordonnée suivante"
+msgstr "Utiliser les coordonnées globales"
#: scene/2d/skeleton_2d.cpp scene/3d/skeleton.cpp
-#, fuzzy
msgid "Rest"
-msgstr "Redémarrer"
+msgstr "Repos"
#: scene/2d/skeleton_2d.cpp
-#, fuzzy
msgid "Default Length"
-msgstr "Thème par défaut"
+msgstr "Longueur par défaut"
#: scene/2d/skeleton_2d.cpp
msgid "This Bone2D chain should end at a Skeleton2D node."
@@ -22254,16 +21707,15 @@ msgstr ""
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
msgid "Hframes"
-msgstr ""
+msgstr "Trames H"
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
msgid "Vframes"
-msgstr ""
+msgstr "Trames V"
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
-#, fuzzy
msgid "Frame Coords"
-msgstr "Image %"
+msgstr "Coordonnées de trame"
#: scene/2d/sprite.cpp scene/resources/texture.cpp
#, fuzzy
@@ -22281,14 +21733,12 @@ msgstr ""
"etc."
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Tile Set"
-msgstr "TileSet"
+msgstr "Palette de tuiles"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Quadrant Size"
-msgstr "Changer la taille d'une caméra"
+msgstr "Taille de quadrant"
#: scene/2d/tile_map.cpp
#, fuzzy
@@ -22296,66 +21746,56 @@ msgid "Custom Transform"
msgstr "Transformation"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Half Offset"
-msgstr "Initialiser"
+msgstr "Décalage de moitié"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Tile Origin"
-msgstr "Afficher l'origine"
+msgstr "Origine de la tuile"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Y Sort"
-msgstr "Trier"
+msgstr "Trier par Y"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Show Collision"
-msgstr "Collision"
+msgstr "Afficher la Collision"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Compatibility Mode"
-msgstr "Mode prioritaire"
+msgstr "Mode de Compatibilité"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Centered Textures"
-msgstr "Fonctionnalités principales :"
+msgstr "Textures Centrées"
#: scene/2d/tile_map.cpp
msgid "Cell Clip UV"
msgstr ""
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Use Parent"
-msgstr "Mode collision"
+msgstr "Utiliser le Parent"
#: scene/2d/tile_map.cpp
msgid "Use Kinematic"
-msgstr ""
+msgstr "Utiliser Kinematic"
#: scene/2d/touch_screen_button.cpp
-#, fuzzy
msgid "Shape Centered"
-msgstr "Aimanter au centre du nœud"
+msgstr "Forme Centrée"
#: scene/2d/touch_screen_button.cpp
-#, fuzzy
msgid "Shape Visible"
-msgstr "Rendre visible"
+msgstr "Forme Visible"
#: scene/2d/touch_screen_button.cpp
msgid "Passby Press"
msgstr ""
#: scene/2d/touch_screen_button.cpp
-#, fuzzy
msgid "Visibility Mode"
-msgstr "Mode prioritaire"
+msgstr "Mode de Visibilité"
#: scene/2d/visibility_notifier_2d.cpp
msgid ""
@@ -22366,41 +21806,36 @@ msgstr ""
"nœud racine de la scène éditée."
#: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp
-#, fuzzy
msgid "Pause Animations"
-msgstr "Coller l'animation"
+msgstr "Mettre les animations en pause"
#: scene/2d/visibility_notifier_2d.cpp scene/3d/visibility_notifier.cpp
msgid "Freeze Bodies"
-msgstr ""
+msgstr "Geler les corps"
#: scene/2d/visibility_notifier_2d.cpp
-#, fuzzy
msgid "Pause Particles"
-msgstr "Particules"
+msgstr "Mettre les particules en pause"
#: scene/2d/visibility_notifier_2d.cpp
-#, fuzzy
msgid "Pause Animated Sprites"
-msgstr "Coller l'animation"
+msgstr "Mettre les Sprites animés en pause"
#: scene/2d/visibility_notifier_2d.cpp
-#, fuzzy
msgid "Process Parent"
-msgstr "Activer la priorité"
+msgstr "Parent du Processus"
#: scene/2d/visibility_notifier_2d.cpp
msgid "Physics Process Parent"
-msgstr ""
+msgstr "Parent du Processus Physique"
#: scene/3d/area.cpp
msgid "Reverb Bus"
msgstr ""
#: scene/3d/area.cpp
-#, fuzzy
msgid "Uniformity"
-msgstr "Définir le nom de l'uniforme"
+msgstr "Uniformité"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRCamera must have an ARVROrigin node as its parent."
@@ -22408,11 +21843,11 @@ msgstr "ARVRCamera doit avoir un nœud ARVROrigin comme parent."
#: scene/3d/arvr_nodes.cpp
msgid "Controller ID"
-msgstr ""
+msgstr "ID Du Contrôleur"
#: scene/3d/arvr_nodes.cpp servers/arvr/arvr_positional_tracker.cpp
msgid "Rumble"
-msgstr ""
+msgstr "Vibration"
#: scene/3d/arvr_nodes.cpp
msgid "ARVRController must have an ARVROrigin node as its parent."
@@ -22448,48 +21883,44 @@ msgid "ARVROrigin requires an ARVRCamera child node."
msgstr "ARVROrigin requiert un nœud enfant ARVRCamera."
#: scene/3d/arvr_nodes.cpp servers/arvr_server.cpp
-#, fuzzy
msgid "World Scale"
-msgstr "Échelle aléatoire :"
+msgstr "Échelle du Monde"
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Attenuation Model"
-msgstr "Nœud d'animation"
+msgstr "Modèle d’atténuation"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Unit dB"
-msgstr ""
+msgstr "Unité (dB)"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Unit Size"
-msgstr ""
+msgstr "Taille d’unité"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Max dB"
-msgstr ""
+msgstr "Max (dB)"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Out Of Range Mode"
msgstr ""
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Emission Angle"
-msgstr "Couleurs d'émission"
+msgstr "Angle d’émission"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Degrees"
msgstr "Degrés"
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Filter Attenuation dB"
-msgstr "Animation"
+msgstr "Filtre d’atténuation (dB)"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Attenuation Filter"
-msgstr ""
+msgstr "Filtre d’atténuation"
#: scene/3d/audio_stream_player_3d.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
@@ -22499,14 +21930,12 @@ msgstr ""
#: scene/3d/audio_stream_player_3d.cpp
#: servers/audio/effects/audio_effect_filter.cpp
-#, fuzzy
msgid "dB"
-msgstr "o"
+msgstr "dB"
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Doppler"
-msgstr "Activer l'effet Doppler"
+msgstr "Doppler"
#: scene/3d/audio_stream_player_3d.cpp
#, fuzzy
@@ -22516,7 +21945,7 @@ msgstr "Empaquetage"
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/reflection_probe.cpp
msgid "Interior"
-msgstr ""
+msgstr "Intérieur"
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
@@ -22551,69 +21980,59 @@ msgstr "Gadgets"
#: scene/3d/baked_lightmap.cpp
msgid "Tweaks"
-msgstr ""
+msgstr "Ajustements"
#: scene/3d/baked_lightmap.cpp
msgid "Bounces"
-msgstr ""
+msgstr "Rebonds"
#: scene/3d/baked_lightmap.cpp
msgid "Bounce Indirect Energy"
-msgstr ""
+msgstr "Énergie indirecte de rebond"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Use Denoiser"
-msgstr "Filtre :"
+msgstr "Utiliser un filtre anti-bruit"
#: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp
msgid "Use HDR"
-msgstr ""
+msgstr "Utiliser HDR"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Use Color"
-msgstr "Couleurs"
+msgstr "Utiliser la couleur"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Default Texels Per Unit"
-msgstr "Thème par défaut"
+msgstr "Texels par unité par défaut"
#: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Atlas"
-msgstr "Nouvel Atlas"
+msgstr "Atlas"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generate"
-msgstr "Général"
+msgstr "Générer"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Max Size"
-msgstr "Taille :"
+msgstr "Taille maximale"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Custom Sky"
-msgstr "Nœud Personnalisé"
+msgstr "Ciel personnalisé"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Custom Sky Rotation Degrees"
-msgstr "Rotation de %s degrés."
+msgstr "Degrés de rotation du ciel personnalisé"
#: scene/3d/baked_lightmap.cpp scene/3d/ray_cast.cpp
-#, fuzzy
msgid "Custom Color"
-msgstr "Nœud Personnalisé"
+msgstr "Couleur personnalisée"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Custom Energy"
-msgstr "Déplacer effet de transport"
+msgstr "Énergie personnalisée"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22621,27 +22040,24 @@ msgid "Min Light"
msgstr "Indenter vers la droite"
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
-#, fuzzy
msgid "Propagation"
-msgstr "Navigation"
+msgstr "Propagation"
#: scene/3d/baked_lightmap.cpp
msgid "Image Path"
-msgstr ""
+msgstr "Chemin de l'image"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Light Data"
-msgstr "Avec données"
+msgstr "Données de lumière"
#: scene/3d/bone_attachment.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Bone Name"
-msgstr "Nom de nœud :"
+msgstr "Nom de l'os"
#: scene/3d/camera.cpp
msgid "Keep Aspect"
-msgstr ""
+msgstr "Garder l'aspect"
#: scene/3d/camera.cpp scene/3d/light.cpp scene/3d/reflection_probe.cpp
msgid "Cull Mask"
@@ -22653,36 +22069,32 @@ msgid "Doppler Tracking"
msgstr "Piste de propriété"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Projection"
-msgstr "Projet"
+msgstr "Projection"
#: scene/3d/camera.cpp
msgid "FOV"
-msgstr ""
+msgstr "Champ de vision"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Frustum Offset"
-msgstr "Décalage de la grille :"
+msgstr "Décalage du Tronc"
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Near"
-msgstr "Au plus proche"
+msgstr "Plan proche"
#: scene/3d/camera.cpp
msgid "Far"
-msgstr ""
+msgstr "Plan éloigné"
#: 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
#: scene/resources/shape.cpp scene/resources/style_box.cpp
#: scene/resources/texture.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
-#, fuzzy
msgid "Margin"
-msgstr "Définir la marge"
+msgstr "Marge"
#: scene/3d/camera.cpp
#, fuzzy
@@ -22772,48 +22184,40 @@ msgid "Box Extents"
msgstr "Gadgets"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Ring Radius"
-msgstr "Masque d'émission"
+msgstr "Rayon de l'anneau"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Ring Inner Radius"
-msgstr "Changer le rayon intérieur de la tour"
+msgstr "Rayon intérieur de l'anneau"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Ring Height"
-msgstr "Rotation vers la droite"
+msgstr "Hauteur de l'anneau"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Ring Axis"
-msgstr "Avertissements"
+msgstr "Axe de l'anneau"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Rotate Y"
-msgstr "Rotation"
+msgstr "Rotation Y"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
-#, fuzzy
msgid "Disable Z"
-msgstr "Item désactivé"
+msgstr "Désactiver axe Z"
#: scene/3d/cpu_particles.cpp scene/resources/particles_material.cpp
msgid "Flatness"
-msgstr ""
+msgstr "Platitude"
#: scene/3d/cull_instance.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Portals"
-msgstr "Retourner les Portals"
+msgstr "Portails"
#: scene/3d/cull_instance.cpp
-#, fuzzy
msgid "Portal Mode"
-msgstr "Mode prioritaire"
+msgstr "Mode portail"
#: scene/3d/cull_instance.cpp
msgid "Include In Bound"
@@ -22824,9 +22228,8 @@ msgid "Allow Merging"
msgstr ""
#: scene/3d/cull_instance.cpp
-#, fuzzy
msgid "Autoplace Priority"
-msgstr "Activer la priorité"
+msgstr "Priorité d’auto-placement"
#: scene/3d/gi_probe.cpp
msgid "Plotting Meshes"
@@ -22857,114 +22260,98 @@ msgstr ""
#: scene/3d/gi_probe.cpp
msgid "Subdiv"
-msgstr ""
+msgstr "Subdivision"
#: scene/3d/gi_probe.cpp
-#, fuzzy
msgid "Dynamic Range"
-msgstr "Bibliothèque dynamique"
+msgstr "Plage dynamique"
#: scene/3d/gi_probe.cpp scene/3d/light.cpp
msgid "Normal Bias"
-msgstr ""
+msgstr "Biais normal"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
#: scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Pixel Size"
-msgstr "Aimanter au pixel"
+msgstr "Taille de pixel"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Billboard"
-msgstr ""
+msgstr "Panneau(Billboard)"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
-#, fuzzy
msgid "Shaded"
-msgstr "Ombrage"
+msgstr "Ombré"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Double Sided"
-msgstr ""
+msgstr "Double face"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp
msgid "No Depth Test"
-msgstr ""
+msgstr "Pas de test de profondeur"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Fixed Size"
-msgstr "Vue de devant"
+msgstr "Taille fixe"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Alpha Cut"
-msgstr ""
+msgstr "Coupe alpha"
#: scene/3d/label_3d.cpp scene/resources/material.cpp
msgid "Alpha Scissor Threshold"
-msgstr ""
+msgstr "Seuil des ciseaux d'alpha"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Render Priority"
-msgstr "Activer la priorité"
+msgstr "Priorité de rendu"
#: scene/3d/label_3d.cpp
-#, fuzzy
msgid "Outline Render Priority"
-msgstr "Activer la priorité"
+msgstr "Priorité de rendu du contour"
#: scene/3d/label_3d.cpp
-#, fuzzy
msgid "Outline Modulate"
-msgstr "Forcer la modulation blanche"
+msgstr "Moduler le contour"
#: scene/3d/label_3d.cpp scene/resources/default_theme/default_theme.cpp
#: scene/resources/dynamic_font.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Font"
-msgstr "Polices"
+msgstr "Police"
#: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Horizontal Alignment"
-msgstr "Horizontal Activé"
+msgstr "Alignement horizontal"
#: scene/3d/label_3d.cpp
-#, fuzzy
msgid "Vertical Alignment"
-msgstr "Filtrer les signaux"
+msgstr "Alignement vertical"
#: scene/3d/label_3d.cpp scene/gui/dialogs.cpp scene/gui/label.cpp
-#, fuzzy
msgid "Autowrap"
-msgstr "AutoLoad"
+msgstr "Retour à la ligne automatique"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Indirect Energy"
-msgstr "Couleurs d'émission"
+msgstr "Énergie indirecte"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Negative"
-msgstr "GDNative"
+msgstr "Négative"
#: scene/3d/light.cpp scene/resources/material.cpp
#: scene/resources/visual_shader.cpp
-#, fuzzy
msgid "Specular"
-msgstr "Mode Règle"
+msgstr "Spéculaire"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Bake Mode"
-msgstr "Mode Bitmask"
+msgstr "Mode de pré-calcul"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Contact"
-msgstr "Prélever une couleur"
+msgstr "Contact"
#: scene/3d/light.cpp
#, fuzzy
@@ -22972,9 +22359,8 @@ msgid "Reverse Cull Face"
msgstr "Réinitialiser le volume de bus"
#: scene/3d/light.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Directional Shadow"
-msgstr "Directions"
+msgstr "Ombre directionnelle"
#: scene/3d/light.cpp
#, fuzzy
@@ -22992,9 +22378,8 @@ msgid "Split 3"
msgstr "Divisé"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Blend Splits"
-msgstr "Temps de mélange :"
+msgstr "Mélanger les écarts"
#: scene/3d/light.cpp
#, fuzzy
@@ -23002,23 +22387,20 @@ msgid "Bias Split Scale"
msgstr "Utiliser le magnétisme d'échelle"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Depth Range"
-msgstr "Profondeur"
+msgstr "Plage de profondeur"
#: scene/3d/light.cpp
msgid "Omni"
-msgstr ""
+msgstr "Omnidirectionnelle"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Shadow Mode"
-msgstr "Ombrage"
+msgstr "Mode ombre"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Shadow Detail"
-msgstr "Afficher par défaut"
+msgstr "Détails d'ombre"
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
@@ -23028,21 +22410,19 @@ msgstr ""
#: scene/3d/light.cpp
msgid "Spot"
-msgstr ""
+msgstr "Spot"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Angle Attenuation"
-msgstr "Animation"
+msgstr "Atténuation d'angle"
#: scene/3d/mesh_instance.cpp
msgid "Software Skinning"
msgstr ""
#: scene/3d/mesh_instance.cpp
-#, fuzzy
msgid "Transform Normals"
-msgstr "Transformation annulée."
+msgstr "Transformer les normales"
#: scene/3d/navigation.cpp
msgid ""
@@ -23050,45 +22430,44 @@ msgid ""
"be removed in a future version. Use 'NavigationServer.map_get_path()' "
"instead."
msgstr ""
+"Le nœud \"Navigation\" et \"Navigation.get_simple_path()\" sont obsolètes et "
+"seront retires dans une version ultérieure. Utilisez plutôt "
+"\"NavigationServer.map_get_path()\"."
#: scene/3d/navigation.cpp scene/resources/curve.cpp
-#, fuzzy
msgid "Up Vector"
-msgstr "Vecteur"
+msgstr "Vecteur Haut"
#: scene/3d/navigation.cpp
-#, fuzzy
msgid "Cell Height"
-msgstr "En période de test"
+msgstr "Hauteur de cellule"
#: scene/3d/navigation_agent.cpp
msgid "Agent Height Offset"
-msgstr ""
+msgstr "Décalage de hauteur de l'agent"
#: scene/3d/navigation_agent.cpp
-#, fuzzy
msgid "Ignore Y"
-msgstr "[Ignorer]"
+msgstr "Ignorer Y"
#: scene/3d/navigation_agent.cpp
-#, fuzzy
msgid ""
"The NavigationAgent can be used only under a Spatial inheriting parent node."
-msgstr "Le NavigationAgent ne peut être utilisé que sous un nœud spatial."
+msgstr ""
+"Le NavigationAgent ne peut être utilisé que sous un nœud parent héritant de "
+"Spatial."
#: scene/3d/navigation_mesh_instance.cpp scene/resources/mesh_library.cpp
-#, fuzzy
msgid "NavMesh"
-msgstr "Calculer le NavMesh"
+msgstr "NavMesh"
#: scene/3d/navigation_obstacle.cpp
-#, fuzzy
msgid ""
"The NavigationObstacle only serves to provide collision avoidance to a "
"Spatial inheriting parent object."
msgstr ""
-"Un NavigationObstacle ne peut éviter les collisions qu'avec les nœuds "
-"Spatial."
+"Le NavigationObstacle ne sert qu'à fournir l’évitement de collision qu'aux "
+"objets dont les parents héritent de Spatial."
#: scene/3d/occluder.cpp
msgid "No shape is set."
@@ -23139,19 +22518,16 @@ msgstr ""
"Particles » activé."
#: scene/3d/particles.cpp
-#, fuzzy
msgid "Visibility AABB"
-msgstr "Basculer la visibilité"
+msgstr "Visibilité AABB"
#: scene/3d/particles.cpp
-#, fuzzy
msgid "Draw Passes"
-msgstr "Appels de dessin :"
+msgstr "Afficher les passes"
#: scene/3d/particles.cpp
-#, fuzzy
msgid "Passes"
-msgstr "Appels de dessin :"
+msgstr "Passes"
#: scene/3d/path.cpp
msgid "PathFollow only works when set as a child of a Path node."
@@ -23168,7 +22544,6 @@ msgstr ""
"Vector » dans la ressource Curve de son parent Path."
#: scene/3d/path.cpp
-#, fuzzy
msgid "Rotation Mode"
msgstr "Mode rotation"
@@ -23183,223 +22558,189 @@ msgstr ""
"Modifiez la taille dans les formes de collision enfant à la place."
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Axis Lock"
-msgstr "Axe"
+msgstr "Verrouiller l'axe"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear X"
-msgstr "Linéaire"
+msgstr "X linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Y"
-msgstr "Linéaire"
+msgstr "Y linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Z"
-msgstr "Linéaire"
+msgstr "Z linéaire"
#: scene/3d/physics_body.cpp
msgid "Angular X"
-msgstr ""
+msgstr "X angulaire"
#: scene/3d/physics_body.cpp
msgid "Angular Y"
-msgstr ""
+msgstr "Y angulaire"
#: scene/3d/physics_body.cpp
msgid "Angular Z"
-msgstr ""
+msgstr "Z angulaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion X"
-msgstr "Action"
+msgstr "X mouvement"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion Y"
-msgstr "Action"
+msgstr "Y mouvement"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Motion Z"
-msgstr "Action"
+msgstr "Z mouvement"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Joint Constraints"
-msgstr "Constantes"
+msgstr "Restrictions de jointure"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Impulse Clamp"
-msgstr ""
+msgstr "Borner l'impulsion"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Swing Span"
-msgstr "Enregistrement de la scène"
+msgstr "Ampleur de balancement"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "Twist Span"
-msgstr ""
+msgstr "Ampleur de torsion"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Relaxation"
-msgstr "Séparation :"
+msgstr "Relaxation"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Enabled"
-msgstr "Filtrer les signaux"
+msgstr "Limite angulaire activée"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Upper"
-msgstr "Linéaire"
+msgstr "Limite angulaire haute"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Lower"
-msgstr "Erreur angulaire max. :"
+msgstr "Limite angulaire basse"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Bias"
-msgstr "Linéaire"
+msgstr "Biais de limite angulaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Softness"
-msgstr "Animation"
+msgstr "Douceur de limite angulaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Relaxation"
-msgstr "Animation"
+msgstr "Relaxation de limite angulaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Upper"
-msgstr "Linéaire"
+msgstr "Limite linéaire haute"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Lower"
-msgstr "Linéaire"
+msgstr "Limite linéaire basse"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Softness"
-msgstr "Linéaire"
+msgstr "Douceur de limite linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Restitution"
-msgstr "Linéaire"
+msgstr "Restitution de limite linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Damping"
-msgstr "Linéaire"
+msgstr "Amortissement de limite linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Restitution"
-msgstr "Animation"
+msgstr "Restitution de limite angulaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Damping"
-msgstr "Animation"
+msgstr "Amortissement de limite angulaire"
#: scene/3d/physics_body.cpp
msgid "X"
-msgstr ""
+msgstr "X"
#: scene/3d/physics_body.cpp
msgid "Y"
-msgstr ""
+msgstr "Y"
#: scene/3d/physics_body.cpp
msgid "Z"
-msgstr ""
+msgstr "Z"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Limit Enabled"
-msgstr "Linéaire"
+msgstr "Limite linéaire active"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Spring Enabled"
-msgstr "Linéaire"
+msgstr "Ressort linéaire actif"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Spring Stiffness"
-msgstr "Linéaire"
+msgstr "Raideur du ressort linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Spring Damping"
-msgstr "Linéaire"
+msgstr "Amortissement de ressort linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Equilibrium Point"
-msgstr "Linéaire"
+msgstr "Point d’équilibre linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Restitution"
-msgstr "Description"
+msgstr "Restitution linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Linear Damping"
-msgstr "Linéaire"
+msgstr "Amortissement linéaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Restitution"
-msgstr "Description"
+msgstr "Restitution angulaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Damping"
-msgstr "Animation"
+msgstr "Amortissement angulaire"
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
msgid "ERP"
msgstr ""
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Spring Enabled"
-msgstr "Filtrer les signaux"
+msgstr "Ressort angulaire actif"
#: scene/3d/physics_body.cpp
msgid "Angular Spring Stiffness"
-msgstr ""
+msgstr "Raideur de ressort angulaire"
#: scene/3d/physics_body.cpp
msgid "Angular Spring Damping"
-msgstr ""
+msgstr "Amortissement de ressort angulaire"
#: scene/3d/physics_body.cpp
msgid "Angular Equilibrium Point"
-msgstr ""
+msgstr "Point d’équilibre angulaire"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Body Offset"
-msgstr "Décalage :"
+msgstr "Décalage du corps"
#: scene/3d/physics_joint.cpp
msgid "Node A and Node B must be PhysicsBodies"
@@ -23423,183 +22764,159 @@ msgstr "Node A et Node B doivent être des PhysicsBody différents"
#: scene/3d/physics_joint.cpp
msgid "Solver"
-msgstr ""
+msgstr "Résolveur"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Exclude Nodes"
-msgstr "Supprimer des nœuds"
+msgstr "Exclure les nœuds"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Params"
-msgstr "Paramètre modifié :"
+msgstr "Paramètres"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit"
-msgstr ""
+msgstr "Limite angulaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Upper"
-msgstr "Tout en majuscule"
+msgstr "Haute"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Lower"
-msgstr "Tout en minuscule"
+msgstr "Basse"
#: scene/3d/physics_joint.cpp
msgid "Motor"
-msgstr ""
+msgstr "Moteur"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Target Velocity"
-msgstr "Vue de l'orbite vers la droite"
+msgstr "Vélocité cible"
#: scene/3d/physics_joint.cpp
msgid "Max Impulse"
msgstr "Impulsion Maximale"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Limit"
-msgstr "Linéaire"
+msgstr "Limite linéaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Upper Distance"
-msgstr "Choisissez distance :"
+msgstr "Distance haute"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Lower Distance"
-msgstr "Choisissez distance :"
+msgstr "Distance basse"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Restitution"
-msgstr "Description"
+msgstr "Restitution"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Motion"
-msgstr "Initialiser"
+msgstr "Mouvement linéaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Ortho"
-msgstr "Orthogonale arrière"
+msgstr "Ortho linéaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Upper Angle"
-msgstr "Tout en majuscule"
+msgstr "Angle supérieur"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Lower Angle"
-msgstr "Tout en minuscule"
+msgstr "Angle inférieur"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Angular Motion"
-msgstr "Animation"
+msgstr "Mouvement angulaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Angular Ortho"
-msgstr "Erreur angulaire max. :"
+msgstr "Ortho angulaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Limit X"
-msgstr "Linéaire"
+msgstr "X de la limite linéaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Motor X"
-msgstr "Initialiser"
+msgstr "X du moteur linéaire"
#: scene/3d/physics_joint.cpp
msgid "Force Limit"
msgstr "Limite de Force"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Spring X"
-msgstr "Linéaire"
+msgstr "X du ressort linéaire"
#: scene/3d/physics_joint.cpp
msgid "Equilibrium Point"
-msgstr ""
+msgstr "Point d’équilibre"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit X"
-msgstr ""
+msgstr "X de la limite angulaire"
#: scene/3d/physics_joint.cpp
msgid "Angular Motor X"
-msgstr ""
+msgstr "X du moteur angulaire"
#: scene/3d/physics_joint.cpp
msgid "Angular Spring X"
-msgstr ""
+msgstr "X du ressort angulaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Limit Y"
-msgstr "Linéaire"
+msgstr "Y de la limite linéaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Motor Y"
-msgstr "Initialiser"
+msgstr "Y du moteur linéaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Spring Y"
-msgstr "Linéaire"
+msgstr "Y du ressort linéaire"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit Y"
-msgstr ""
+msgstr "Y de la limite angulaire"
#: scene/3d/physics_joint.cpp
msgid "Angular Motor Y"
-msgstr ""
+msgstr "Y du moteur angulaire"
#: scene/3d/physics_joint.cpp
msgid "Angular Spring Y"
-msgstr ""
+msgstr "Y du ressort angulaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Limit Z"
-msgstr "Linéaire"
+msgstr "Z de la limite linéaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Motor Z"
-msgstr "Initialiser"
+msgstr "Z du moteur linéaire"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Linear Spring Z"
-msgstr "Linéaire"
+msgstr "Z du ressort linéaire"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit Z"
-msgstr ""
+msgstr "Z de la limite angulaire"
#: scene/3d/physics_joint.cpp
msgid "Angular Motor Z"
-msgstr ""
+msgstr "Z du moteur angulaire"
#: scene/3d/physics_joint.cpp
msgid "Angular Spring Z"
-msgstr ""
+msgstr "Z du ressort angulaire"
#: scene/3d/portal.cpp
msgid "The RoomManager should not be a child or grandchild of a Portal."
@@ -23619,21 +22936,19 @@ msgstr "Portail actif"
#: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp
msgid "Two Way"
-msgstr ""
+msgstr "Double sens"
#: scene/3d/portal.cpp
msgid "Linked Room"
msgstr "Salle liée"
#: scene/3d/portal.cpp
-#, fuzzy
msgid "Use Default Margin"
-msgstr "Défaut"
+msgstr "Utiliser les marges par défaut"
#: scene/3d/proximity_group.cpp
-#, fuzzy
msgid "Group Name"
-msgstr "Groupé"
+msgstr "Nom de groupe"
#: scene/3d/proximity_group.cpp
msgid "Dispatch Mode"
@@ -23644,42 +22959,36 @@ msgid "Grid Radius"
msgstr "Rayon de la Grille"
#: scene/3d/ray_cast.cpp
-#, fuzzy
msgid "Debug Shape"
-msgstr "Débogueur"
+msgstr "Forme de débogage"
#: scene/3d/ray_cast.cpp scene/resources/style_box.cpp
msgid "Thickness"
-msgstr ""
+msgstr "Épaisseur"
#: scene/3d/reflection_probe.cpp scene/main/viewport.cpp
-#, fuzzy
msgid "Update Mode"
-msgstr "Mode rotation"
+msgstr "Mode de mise à jour"
#: scene/3d/reflection_probe.cpp
msgid "Origin Offset"
msgstr "Décalage de la Grille"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Box Projection"
-msgstr "Projet"
+msgstr "Projection boîte"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Enable Shadows"
-msgstr "Activer l'alignement"
+msgstr "Activer les ombres"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Ambient Color"
-msgstr "Prélever une couleur"
+msgstr "Couleur ambiante"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Ambient Energy"
-msgstr "Couleurs d'émission"
+msgstr "Énergie ambiante"
#: scene/3d/reflection_probe.cpp
#, fuzzy
@@ -23982,6 +23291,11 @@ msgstr ""
"Modifiez les tailles dans les formes de collision enfants à la place."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Transformation Globale"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24055,9 +23369,8 @@ msgid "Use As Steering"
msgstr ""
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Wheel"
-msgstr "Molette vers le haut."
+msgstr "Molette"
#: scene/3d/vehicle_body.cpp
msgid "Roll Influence"
@@ -24093,9 +23406,8 @@ msgid "Material Override"
msgstr "Redéfinition"
#: scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Material Overlay"
-msgstr "Changements de matériau :"
+msgstr "Superposition de Matériau"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -24103,9 +23415,8 @@ msgid "Cast Shadow"
msgstr "Créer un nœud Shader"
#: scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Extra Cull Margin"
-msgstr "Arguments supplémentaires :"
+msgstr "Marge supplémentaire de détermination des faces cachées"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -24177,14 +23488,12 @@ msgid "Mix Mode"
msgstr "Mélanger le nœud"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Fadein Time"
-msgstr "Durée du fondu (s) :"
+msgstr "Durée du fondu entrant"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Fadeout Time"
-msgstr "Durée du fondu (s) :"
+msgstr "Durée du fondu sortant"
#: scene/animation/animation_blend_tree.cpp
msgid "Auto Restart"
@@ -24199,9 +23508,8 @@ msgid "Delay"
msgstr ""
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Random Delay"
-msgstr "Inclinaison aléatoire :"
+msgstr "Retard aléatoire"
#: scene/animation/animation_blend_tree.cpp
#, fuzzy
@@ -24209,9 +23517,8 @@ msgid "Add Amount"
msgstr "Quantité"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Blend Amount"
-msgstr "Quantité :"
+msgstr "Quantité de mélange"
#: scene/animation/animation_blend_tree.cpp
#, fuzzy
@@ -24225,9 +23532,8 @@ msgstr "Ajouter un port d'entrée"
#: scene/animation/animation_blend_tree.cpp
#: scene/animation/animation_node_state_machine.cpp
-#, fuzzy
msgid "Xfade Time"
-msgstr "Durée du fondu (s) :"
+msgstr "Durée du fondu croisé"
#: scene/animation/animation_node_state_machine.cpp
#, fuzzy
@@ -24639,9 +23945,8 @@ msgid "Pass On Modal Close Click"
msgstr ""
#: scene/gui/control.cpp
-#, fuzzy
msgid "Size Flags"
-msgstr "Taille :"
+msgstr "Drapeaux de Taille"
#: scene/gui/control.cpp
#, fuzzy
@@ -24693,9 +23998,8 @@ msgid "Scroll Offset"
msgstr "Décalage du Défilement"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Snap Distance"
-msgstr "Choisissez distance :"
+msgstr "Distance d'arrondissage"
#: scene/gui/graph_edit.cpp
#, fuzzy
@@ -24832,9 +24136,8 @@ msgid "Secret"
msgstr ""
#: scene/gui/line_edit.cpp
-#, fuzzy
msgid "Secret Character"
-msgstr "Caractères valides :"
+msgstr "Caractère secret"
#: scene/gui/line_edit.cpp
msgid "Expand To Text Length"
@@ -24891,7 +24194,7 @@ msgstr ""
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Caret"
-msgstr ""
+msgstr "Caret"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink"
@@ -25068,9 +24371,8 @@ msgid "Meta Underlined"
msgstr ""
#: scene/gui/rich_text_label.cpp
-#, fuzzy
msgid "Tab Size"
-msgstr "Taille :"
+msgstr "Taille de tabulation"
#: scene/gui/rich_text_label.cpp
#, fuzzy
@@ -25091,9 +24393,8 @@ msgid "Selection Enabled"
msgstr "Sélection uniquement"
#: scene/gui/rich_text_label.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Override Selected Font Color"
-msgstr "Configurer le profil sélectionné :"
+msgstr "Remplacer la couleur de police sélectionnée"
#: scene/gui/rich_text_label.cpp
#, fuzzy
@@ -25144,9 +24445,8 @@ msgid "Tick Count"
msgstr "Prélever une couleur"
#: scene/gui/slider.cpp
-#, fuzzy
msgid "Ticks On Borders"
-msgstr "dans l'ordre :"
+msgstr "Encoches aux bordures"
#: scene/gui/spin_box.cpp
msgid "Prefix"
@@ -25157,9 +24457,8 @@ msgid "Suffix"
msgstr "Suffixe"
#: scene/gui/split_container.cpp
-#, fuzzy
msgid "Split Offset"
-msgstr "Décalage de la grille :"
+msgstr "Décalage des écarts"
#: scene/gui/split_container.cpp scene/gui/tree.cpp
#, fuzzy
@@ -25176,9 +24475,8 @@ msgid "Tab Align"
msgstr ""
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
-#, fuzzy
msgid "Current Tab"
-msgstr "Actuel :"
+msgstr "Onglet actuel"
#: scene/gui/tab_container.cpp
#, fuzzy
@@ -25220,9 +24518,13 @@ msgid "Breakpoint Gutter"
msgstr "Passer les points d'arrêt"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Fold Gutter"
-msgstr "Dossier :"
+msgstr "Replier le bandeau"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Sélection uniquement"
#: scene/gui/text_edit.cpp
#, fuzzy
@@ -25319,9 +24621,8 @@ msgid "Initial Angle"
msgstr "Initialiser"
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Fill Degrees"
-msgstr "Rotation de %s degrés."
+msgstr "Degrés remplis"
#: scene/gui/texture_progress.cpp scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -25427,9 +24728,8 @@ msgid "Max Redirects"
msgstr ""
#: scene/main/http_request.cpp
-#, fuzzy
msgid "Timeout"
-msgstr "Délai dépassé."
+msgstr "Délai dépassé"
#: scene/main/node.cpp
msgid ""
@@ -25627,18 +24927,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 +24934,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 ""
@@ -25705,9 +25002,8 @@ msgid "Debug Draw"
msgstr "Débogage"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Render Target"
-msgstr "Moteur de rendu :"
+msgstr "Rendre la cible"
#: scene/main/viewport.cpp
msgid "V Flip"
@@ -25880,9 +25176,8 @@ msgid "Font Color Disabled"
msgstr "Âgrafe désactivée"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "H Separation"
-msgstr "Séparation :"
+msgstr "Séparation H"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25970,14 +25265,12 @@ msgid "Font Outline Modulate"
msgstr "Forcer la modulation blanche"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Shadow Offset X"
-msgstr "Décalage X de la grille :"
+msgstr "Décalage X de l'ombre"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Shadow Offset Y"
-msgstr "Décalage Y de la grille :"
+msgstr "Décalage Y de l'ombre"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26035,14 +25328,12 @@ msgid "Space"
msgstr "Scène principale"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Folded"
-msgstr "Dossier :"
+msgstr "Replié"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Fold"
-msgstr "Dossier :"
+msgstr "Replier"
#: scene/resources/default_theme/default_theme.cpp
msgid "Font Color Readonly"
@@ -26161,14 +25452,12 @@ msgid "Close Highlight"
msgstr "Éclairage direct"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Close H Offset"
-msgstr "Décalage de la grille :"
+msgstr "Fermer décalage H"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Close V Offset"
-msgstr "Décalage de la grille :"
+msgstr "Fermer décalage V"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26196,9 +25485,8 @@ msgid "Labeled Separator Right"
msgstr "Séparateur nommé"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Separator"
-msgstr "Opérateur de couleur."
+msgstr "Séparateur de police"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26206,14 +25494,12 @@ msgid "Font Color Accel"
msgstr "Renommer l'item de couleur"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color Separator"
-msgstr "Opérateur de couleur."
+msgstr "Séparateur de couleur de police"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "V Separation"
-msgstr "Séparation :"
+msgstr "Séparation V"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26261,9 +25547,8 @@ msgid "Title Offset"
msgstr "Décalage d’Octet"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Close Offset"
-msgstr "Décalage de la grille :"
+msgstr "Fermer de décalage"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26393,9 +25678,8 @@ msgid "Icon Margin"
msgstr "Définir la marge"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Line Separation"
-msgstr "Séparation :"
+msgstr "Séparation de line"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26455,9 +25739,8 @@ msgid "Large"
msgstr "Cible"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Folder"
-msgstr "Dossier :"
+msgstr "Dossier"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26495,9 +25778,8 @@ msgid "Label Width"
msgstr "Étendu à Gauche"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Screen Picker"
-msgstr "Opérateur d'écran."
+msgstr "Sélecteur d'écran"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26558,14 +25840,12 @@ msgid "Mono Font"
msgstr "Police Principale"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Table H Separation"
-msgstr "Séparation :"
+msgstr "Séparation H de table"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Table V Separation"
-msgstr "Séparation :"
+msgstr "Séparation V de table"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26730,7 +26010,7 @@ msgstr "Condition"
#: scene/resources/environment.cpp
msgid "Fog"
-msgstr ""
+msgstr "Brouillard"
#: scene/resources/environment.cpp
msgid "Sun Color"
@@ -26826,14 +26106,12 @@ msgid "Max Steps"
msgstr "Pas"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Fade In"
-msgstr "Fondu entrant (s) :"
+msgstr "Fondu entrant"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Fade Out"
-msgstr "Fondu sortant (s) :"
+msgstr "Fondu sortant"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26912,54 +26190,52 @@ msgstr "2"
#: scene/resources/environment.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
msgid "3"
-msgstr ""
+msgstr "3"
#: scene/resources/environment.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
msgid "4"
-msgstr ""
+msgstr "4"
#: scene/resources/environment.cpp
msgid "5"
-msgstr ""
+msgstr "5"
#: scene/resources/environment.cpp
msgid "6"
-msgstr ""
+msgstr "6"
#: scene/resources/environment.cpp
msgid "7"
-msgstr ""
+msgstr "7"
#: scene/resources/environment.cpp
msgid "Bloom"
-msgstr ""
+msgstr "Flou lumineux"
#: scene/resources/environment.cpp
msgid "HDR Threshold"
-msgstr ""
+msgstr "Seuil HDR"
#: scene/resources/environment.cpp
msgid "HDR Luminance Cap"
-msgstr ""
+msgstr "Limite de luminance HDR"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "HDR Scale"
-msgstr "Mode mise à l'échelle"
+msgstr "Échelle HDR"
#: scene/resources/environment.cpp
msgid "Bicubic Upscale"
-msgstr ""
+msgstr "Redimensionnement Bicubique"
#: scene/resources/environment.cpp
msgid "Adjustments"
-msgstr ""
+msgstr "Ajustements"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Brightness"
-msgstr "Lumière"
+msgstr "Luminosité"
#: scene/resources/environment.cpp
msgid "Saturation"
@@ -26967,22 +26243,19 @@ msgstr "Saturation"
#: scene/resources/environment.cpp
msgid "Color Correction"
-msgstr "Correction de Couleur"
+msgstr "Correction des couleurs"
#: scene/resources/font.cpp
-#, fuzzy
msgid "Ascent"
-msgstr "Récents :"
+msgstr "Inclinaison"
#: scene/resources/font.cpp
-#, fuzzy
msgid "Distance Field"
-msgstr "Mode Sans Distraction"
+msgstr "Champ de distance"
#: scene/resources/gradient.cpp
-#, fuzzy
msgid "Raw Data"
-msgstr "Profondeur"
+msgstr "Données brutes"
#: scene/resources/gradient.cpp
msgid "Offsets"
@@ -26990,62 +26263,55 @@ msgstr "Décalages"
#: scene/resources/height_map_shape.cpp
msgid "Map Width"
-msgstr ""
+msgstr "Largeur de la carte"
#: scene/resources/height_map_shape.cpp
-#, fuzzy
msgid "Map Depth"
-msgstr "Profondeur"
+msgstr "Profondeur de la carte"
#: scene/resources/height_map_shape.cpp
-#, fuzzy
msgid "Map Data"
-msgstr "Profondeur"
+msgstr "Données de la carte"
#: scene/resources/line_shape_2d.cpp
msgid "D"
-msgstr ""
+msgstr "D"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Next Pass"
-msgstr "Plan suivant"
+msgstr "Passe suivante"
#: scene/resources/material.cpp
msgid "Use Shadow To Opacity"
msgstr ""
#: scene/resources/material.cpp
-#, fuzzy
msgid "Unshaded"
-msgstr "Afficher sans ombrage"
+msgstr "Sans ombrage"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Vertex Lighting"
-msgstr "Éclairage direct"
+msgstr "Éclairage de sommet"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Use Point Size"
-msgstr "Vue de devant"
+msgstr "Utiliser la taille de point"
#: scene/resources/material.cpp
msgid "World Triplanar"
-msgstr ""
+msgstr "Monde Triplanaire"
#: scene/resources/material.cpp
msgid "Albedo Tex Force sRGB"
-msgstr ""
+msgstr "Forcer sRGB dans la texture d'albédo"
#: scene/resources/material.cpp
msgid "Do Not Receive Shadows"
-msgstr ""
+msgstr "Ne pas recevoir d'ombres"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Disable Ambient Light"
-msgstr "Indenter vers la droite"
+msgstr "Désactiver la lumière ambiante"
#: scene/resources/material.cpp
msgid "Ensure Correct Normals"
@@ -27053,72 +26319,63 @@ msgstr "Assurer des Normales Correctes"
#: scene/resources/material.cpp
msgid "Albedo Tex MSDF"
-msgstr ""
+msgstr "Texture d'albédo MSDF"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Vertex Color"
-msgstr "Vertex"
+msgstr "Couleur de sommet"
#: scene/resources/material.cpp
msgid "Use As Albedo"
-msgstr ""
+msgstr "Utiliser comme albédo"
#: scene/resources/material.cpp
msgid "Is sRGB"
-msgstr ""
+msgstr "Est sRGB"
#: scene/resources/material.cpp servers/visual_server.cpp
msgid "Parameters"
msgstr "Paramètres"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Diffuse Mode"
-msgstr "Mode navigation"
+msgstr "Mode diffus"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Specular Mode"
-msgstr "Mode Règle"
+msgstr "Mode spéculaire"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Depth Draw Mode"
-msgstr "Mode d’interpolation"
+msgstr "Mode de dessin en profondeur"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Line Width"
-msgstr "Étendu à Gauche"
+msgstr "Largeur de ligne"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Point Size"
-msgstr "Vue de devant"
+msgstr "Taille de point"
#: 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"
-msgstr ""
+msgstr "Croître"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Grow Amount"
-msgstr "Quantité :"
+msgstr "Quantité de croissance"
#: scene/resources/material.cpp
msgid "Use Alpha Scissor"
-msgstr ""
+msgstr "Utiliser la découpe alpha"
#: scene/resources/material.cpp
#, fuzzy
@@ -27137,7 +26394,7 @@ msgstr "Image %"
#: scene/resources/material.cpp
msgid "Albedo"
-msgstr ""
+msgstr "Albédo"
#: scene/resources/material.cpp
msgid "Metallic"
@@ -27163,7 +26420,7 @@ msgstr ""
#: scene/resources/material.cpp
msgid "Rim"
-msgstr "Bordure"
+msgstr "Bord"
#: scene/resources/material.cpp
#, fuzzy
@@ -27287,9 +26544,8 @@ msgid "Color Format"
msgstr "Format de Couleur"
#: scene/resources/multimesh.cpp
-#, fuzzy
msgid "Transform Format"
-msgstr "Transformation annulée."
+msgstr "Format de transformation"
#: scene/resources/multimesh.cpp
msgid "Custom Data Format"
@@ -27305,9 +26561,8 @@ msgid "Visible Instance Count"
msgstr ""
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Sampling"
-msgstr "Mise à l'échelle :"
+msgstr "Échantillonnage"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27315,9 +26570,8 @@ msgid "Partition Type"
msgstr "Définir type de variable"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Parsed Geometry Type"
-msgstr "Analyse de la géométrie..."
+msgstr "Type de la géométrie analysée"
#: scene/resources/navigation_mesh.cpp
msgid "Source Geometry Mode"
@@ -27374,9 +26628,8 @@ msgid "Details"
msgstr "Afficher par défaut"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Sample Distance"
-msgstr "Choisissez distance :"
+msgstr "Échantillonner la distance"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27447,12 +26700,10 @@ msgid "Color Modifier"
msgstr "Ralentissement de la vue libre"
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Point Texture"
-msgstr "Points d'Émission :"
+msgstr "Texture ponctuelle"
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Normal Texture"
msgstr "Texture Normale"
@@ -27484,9 +26735,8 @@ msgid "Absorbent"
msgstr ""
#: scene/resources/plane_shape.cpp
-#, fuzzy
msgid "Plane"
-msgstr "Plan :"
+msgstr "Plan"
#: scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -27560,9 +26810,8 @@ msgid "Bone"
msgstr "Os"
#: scene/resources/sky.cpp
-#, fuzzy
msgid "Radiance Size"
-msgstr "Taille du contour :"
+msgstr "Taille du rayonnement"
#: scene/resources/sky.cpp
msgid "Panorama"
@@ -27854,9 +27103,8 @@ msgid "Default Cell Height"
msgstr "En période de test"
#: scene/resources/world.cpp scene/resources/world_2d.cpp
-#, fuzzy
msgid "Default Edge Connection Margin"
-msgstr "Modifier la connexion :"
+msgstr "Marge de connexion des bords par défaut"
#: scene/resources/world_2d.cpp
msgid "Canvas"
@@ -28010,11 +27258,11 @@ msgstr "Ressource"
#: servers/audio/effects/audio_effect_limiter.cpp
msgid "Ceiling dB"
-msgstr ""
+msgstr "Plafond de dB"
#: servers/audio/effects/audio_effect_limiter.cpp
msgid "Threshold dB"
-msgstr ""
+msgstr "Seuil de dB"
#: servers/audio/effects/audio_effect_limiter.cpp
msgid "Soft Clip dB"
@@ -28026,37 +27274,36 @@ msgstr ""
#: servers/audio/effects/audio_effect_phaser.cpp
msgid "Range Min Hz"
-msgstr ""
+msgstr "Borne inférieure de la plage (Hz)"
#: servers/audio/effects/audio_effect_phaser.cpp
msgid "Range Max Hz"
-msgstr ""
+msgstr "Borne supérieure de la plage (Hz)"
#: servers/audio/effects/audio_effect_pitch_shift.cpp
msgid "Oversampling"
-msgstr ""
+msgstr "Suréchantillonnage"
#: servers/audio/effects/audio_effect_pitch_shift.cpp
#: servers/audio/effects/audio_effect_spectrum_analyzer.cpp
msgid "FFT Size"
-msgstr "Taille FFT"
+msgstr "Taille des FFTs"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Predelay"
-msgstr ""
+msgstr "Pré-retarder"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Msec"
-msgstr ""
+msgstr "Millisec"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Room Size"
-msgstr ""
+msgstr "Taille de la salle"
#: servers/audio/effects/audio_effect_reverb.cpp
-#, fuzzy
msgid "High-pass"
-msgstr "Contourner"
+msgstr "Passe-haut"
#: servers/audio/effects/audio_effect_spectrum_analyzer.cpp
msgid "Tap Back Pos"
@@ -28067,27 +27314,24 @@ msgid "Pan Pullout"
msgstr ""
#: servers/audio/effects/audio_effect_stereo_enhance.cpp
-#, fuzzy
msgid "Time Pullout (ms)"
-msgstr "Délai dépassé."
+msgstr "Temps de retrait (ms)"
#: servers/audio/effects/audio_effect_stereo_enhance.cpp
msgid "Surround"
-msgstr ""
+msgstr "Surround"
#: servers/audio_server.cpp
-#, fuzzy
msgid "Enable Audio Input"
-msgstr "Renommer le bus audio"
+msgstr "Activer l’entrée audio"
#: servers/audio_server.cpp
-#, fuzzy
msgid "Output Latency"
-msgstr "Sortie"
+msgstr "Latence de sortie"
#: servers/audio_server.cpp
msgid "Channel Disable Threshold dB"
-msgstr ""
+msgstr "Désactiver le seuil de dB du canal"
#: servers/audio_server.cpp
#, fuzzy
@@ -28096,43 +27340,39 @@ msgstr "Changer le temps de mélange"
#: servers/audio_server.cpp
msgid "Video Delay Compensation (ms)"
-msgstr ""
+msgstr "Compensation de retard vidéo (ms)"
#: servers/audio_server.cpp
-#, fuzzy
msgid "Bus Count"
-msgstr "Ajouter un port d'entrée"
+msgstr "Nombre de ports"
#: servers/audio_server.cpp
-#, fuzzy
msgid "Capture Device"
-msgstr "Capturer depuis Pixel"
+msgstr "Périphérique de capture"
#: servers/audio_server.cpp
-#, fuzzy
msgid "Global Rate Scale"
-msgstr "Variable globale"
+msgstr "Echelle de débit global"
#: servers/camera/camera_feed.cpp
msgid "Feed"
-msgstr ""
+msgstr "Flux"
#: servers/camera/camera_feed.cpp
-#, fuzzy
msgid "Is Active"
-msgstr "Perspective"
+msgstr "Est active"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Sleep Threshold Linear"
-msgstr ""
+msgstr "Seuil linéaire de veille"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Sleep Threshold Angular"
-msgstr ""
+msgstr "Seuil angulaire de veille"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Time Before Sleep"
-msgstr ""
+msgstr "Temps avant veille"
#: servers/physics_2d/physics_2d_server_sw.cpp
msgid "BP Hash Table Size"
@@ -28144,48 +27384,43 @@ msgstr ""
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Inverse Mass"
-msgstr ""
+msgstr "Masse inverse"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Inverse Inertia"
-msgstr "Vue libre gauche"
+msgstr "Inertie inverse"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Total Angular Damp"
-msgstr ""
+msgstr "Amortissage angulaire total"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Total Linear Damp"
-msgstr "Linéaire"
+msgstr "Amortissage linéaire total"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Total Gravity"
-msgstr "Aperçu par défaut"
+msgstr "Gravité totale"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Linear Velocity"
-msgstr "Initialiser"
+msgstr "Vélocité linéaire"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Exclude"
-msgstr ""
+msgstr "Exclure"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Shape RID"
-msgstr ""
+msgstr "RID de forme"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collide With Bodies"
-msgstr "Mode collision"
+msgstr "Collisions avec les corps"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Collide With Areas"
-msgstr ""
+msgstr "Collisions avec les zones"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Motion Remainder"
@@ -28427,14 +27662,12 @@ msgid "Use Software Skinning"
msgstr ""
#: servers/visual_server.cpp
-#, fuzzy
msgid "Ninepatch Mode"
-msgstr "Mode d’interpolation"
+msgstr "Mode Ninepatch"
#: servers/visual_server.cpp
-#, fuzzy
msgid "OpenGL"
-msgstr "Ouvrir"
+msgstr "OpenGL"
#: servers/visual_server.cpp
msgid "Batching Send Null"
@@ -28459,12 +27692,11 @@ msgstr "Traitement en lot"
#: servers/visual_server.cpp
msgid "Use Batching"
-msgstr ""
+msgstr "Utiliser le traitement en lot"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Use Batching In Editor"
-msgstr "Mise à jour de l'éditeur"
+msgstr "Utiliser le traitement en lot dans l'éditeur"
#: servers/visual_server.cpp
msgid "Single Rect Fallback"
@@ -28488,7 +27720,7 @@ msgstr "Nombre Maximal d'Éléments Joints"
#: servers/visual_server.cpp
msgid "Batch Buffer Size"
-msgstr ""
+msgstr "Taille de tampon des lots"
#: servers/visual_server.cpp
msgid "Item Reordering Lookahead"
@@ -28499,21 +27731,20 @@ msgid "Flash Batching"
msgstr ""
#: servers/visual_server.cpp
-#, fuzzy
msgid "Diagnose Frame"
-msgstr "Coller une image"
+msgstr "Diagnostiquer la trame"
#: servers/visual_server.cpp
msgid "GLES2"
-msgstr ""
+msgstr "GLES2"
#: servers/visual_server.cpp
msgid "Compatibility"
-msgstr ""
+msgstr "Compatibilité"
#: servers/visual_server.cpp
msgid "Disable Half Float"
-msgstr ""
+msgstr "Désactiver les demi Float"
#: servers/visual_server.cpp
#, fuzzy
@@ -28521,31 +27752,28 @@ msgid "Enable High Float"
msgstr "Activer la priorité"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Precision"
-msgstr "Expression"
+msgstr "Précision"
#: servers/visual_server.cpp
msgid "UV Contract"
-msgstr ""
+msgstr "Contraction UV"
#: servers/visual_server.cpp
msgid "UV Contract Amount"
-msgstr ""
+msgstr "Quantité de contraction UV"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Use Simple PVS"
-msgstr "Utiliser le magnétisme d'échelle"
+msgstr "Utiliser PVS simple"
#: servers/visual_server.cpp
msgid "PVS Logging"
-msgstr ""
+msgstr "Journal PVS"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Use Signals"
-msgstr "Signaux"
+msgstr "Utiliser les signaux"
#: servers/visual_server.cpp
#, fuzzy
@@ -28564,27 +27792,24 @@ msgstr "Voir la suppression de l'occlusion"
#: servers/visual_server.cpp
msgid "Max Active Spheres"
-msgstr ""
+msgstr "Nombre maximum de sphères actives"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Max Active Polygons"
-msgstr "Déplacer le polygone"
+msgstr "Nombre maximum de polygones actifs"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Shader Compilation Mode"
-msgstr "Mode d’interpolation"
+msgstr "Mode de compilation des shaders"
#: servers/visual_server.cpp
msgid "Max Simultaneous Compiles"
-msgstr ""
+msgstr "Nombre de compilations simultanées"
#: servers/visual_server.cpp
msgid "Log Active Async Compiles Count"
msgstr ""
#: servers/visual_server.cpp
-#, fuzzy
msgid "Shader Cache Size (MB)"
-msgstr "Changer la taille d'une caméra"
+msgstr "Taille du cache de shader (Mo)"
diff --git a/editor/translations/ga.po b/editor/translations/ga.po
index 04e014ed77..87e005f5f3 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
@@ -445,6 +450,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2086,14 +2095,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Cuardach:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2149,8 +2159,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2710,8 +2720,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "CrannBeochan"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5291,6 +5302,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11280,6 +11299,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "CrannBeochan"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17820,6 +17844,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 +17856,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 +17901,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 +18122,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 +18136,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
@@ -19404,14 +19453,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19432,14 +19480,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19656,7 +19703,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 +20386,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 +20398,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 ""
@@ -20410,7 +20466,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22289,6 +22345,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Athrú: "
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23391,6 +23452,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 +23818,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..29db0e8063 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
@@ -483,6 +488,10 @@ msgid "Pressure"
msgstr "Axustes de Importación"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Axuste Relativo"
@@ -2187,14 +2196,15 @@ msgstr "Favoritos:"
msgid "Recent:"
msgstr "Recente:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Buscar:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Coincidencias:"
@@ -2254,8 +2264,8 @@ msgstr "Buscar Recurso de Substitución:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2841,7 +2851,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Copiar Ruta do Nodo"
#: editor/editor_export.cpp
@@ -5642,6 +5652,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11890,6 +11909,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filtrar métodos"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Velocidade:"
@@ -18796,6 +18820,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 +18833,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 +18882,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 +19131,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 +19145,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
@@ -20501,15 +20550,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Extensión inválida."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20531,15 +20580,15 @@ msgstr "Nome inválido."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Extensión inválida."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20782,7 +20831,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 +21573,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 +21586,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 +21617,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."
@@ -21600,7 +21659,7 @@ msgstr "Viaxe"
msgid "Rotation Degrees"
msgstr "Rotando % graos."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Constante"
@@ -23667,6 +23726,11 @@ msgstr ""
"lugar."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Transformación"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24887,6 +24951,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 +25352,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 +25361,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..abaada7880 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
@@ -478,6 +483,10 @@ msgid "Pressure"
msgstr "לחץ"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "GDNative"
@@ -2158,14 +2167,15 @@ msgstr "מועדפי×:"
msgid "Recent:"
msgstr "×חרוני×:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "חיפוש:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "הת×מות:"
@@ -2225,8 +2235,8 @@ msgstr "חיפוש מש×ב חלופי:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2797,7 +2807,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "העתקת נתיב המפרק"
#: editor/editor_export.cpp
@@ -5557,6 +5567,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap מילוי הבחירה"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11945,6 +11964,11 @@ msgstr "×©× ×”× ×¤×©×” חדשה:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
#, fuzzy
+msgid "Filter animations"
+msgstr "מ×פייני פריט."
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
msgid "Speed:"
msgstr "מהירות (FPS):"
@@ -18932,6 +18956,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 +18969,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 +19019,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 +19273,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 +19288,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
@@ -20658,15 +20707,15 @@ msgstr "×œ× × ×™×ª×Ÿ לפתוח תבנית לייצו×:"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "סיומת ×œ× ×—×•×§×™×ª."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20690,15 +20739,15 @@ msgstr "×©× ×©×’×•×™."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "סיומת ×œ× ×—×•×§×™×ª."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20942,7 +20991,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 +21734,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 +21747,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 +21778,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."
@@ -21763,7 +21822,7 @@ msgstr "טיול"
msgid "Rotation Degrees"
msgstr "הטיה של %s מעלות."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "קבוע"
@@ -23845,6 +23904,11 @@ msgstr ""
"×‘×ž×§×•× ×–×ת יש לשנות ×ת גודל צורות ההתנגשות של הצ×צ××™×."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "התמרה"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25074,6 +25138,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 +25545,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 +25552,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..e5a41404d0 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
@@ -461,6 +466,10 @@ msgid "Pressure"
msgstr "पà¥à¤°à¥€à¤¸à¥‡à¤Ÿ"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2146,14 +2155,15 @@ msgstr "पसंदीदा:"
msgid "Recent:"
msgstr "हाल ही में किया:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "खोज:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "à¤à¤• जैसा:"
@@ -2213,8 +2223,8 @@ msgstr "खोज रिपà¥à¤²à¥‡à¤¸à¤®à¥‡à¤‚ट संसाधन:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2794,8 +2804,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "खंड कौपी कीजिये"
#: editor/editor_export.cpp
#, fuzzy
@@ -5562,6 +5573,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "सभी खंड"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11746,6 +11766,11 @@ msgid "New Animation"
msgstr "à¤à¤¨à¤¿à¤®à¥‡à¤¶à¤¨ लूप"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "à¤à¤¨à¤¿à¤®à¥‡à¤¶à¤¨"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18576,6 +18601,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 +18614,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 +18662,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 +18902,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 +18916,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20260,15 +20310,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "गलत फॉणà¥à¤Ÿ का आकार |"
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20290,15 +20340,15 @@ msgstr "अमानà¥à¤¯ नाम."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "गलत फॉणà¥à¤Ÿ का आकार |"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20534,7 +20584,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 +21297,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 +21310,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 ""
@@ -21318,7 +21378,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "कोनà¥à¤¸à¥à¤Ÿà¤¨à¥à¤Ÿ"
@@ -23293,6 +23353,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "à¤à¤¨à¥€à¤®à¥‡à¤¶à¤¨ परिवरà¥à¤¤à¤¨ परिणत"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24471,6 +24536,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 +24935,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..e473c6556c 100644
--- a/editor/translations/hr.po
+++ b/editor/translations/hr.po
@@ -6,12 +6,13 @@
# Patik <patrikfs5@gmail.com>, 2019.
# Nikola Bunjevac <nikola.bunjevac@gmail.com>, 2019, 2020.
# LeoClose <leoclose575@gmail.com>, 2020, 2021.
+# Filip <fhomolka@protonmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2021-08-13 19:05+0000\n"
-"Last-Translator: LeoClose <leoclose575@gmail.com>\n"
+"PO-Revision-Date: 2022-07-23 03:57+0000\n"
+"Last-Translator: Filip <fhomolka@protonmail.com>\n"
"Language-Team: Croatian <https://hosted.weblate.org/projects/godot-engine/"
"godot/hr/>\n"
"Language: hr\n"
@@ -19,11 +20,11 @@ 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.8-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
-msgstr ""
+msgstr "UpravljaÄki program za Tablet"
#: core/bind/core_bind.cpp
msgid "Clipboard"
@@ -39,73 +40,77 @@ msgid "Exit Code"
msgstr ""
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "V-Sync Enabled"
-msgstr "Omogući"
+msgstr "V-Sync Omogućen"
#: core/bind/core_bind.cpp main/main.cpp
msgid "V-Sync Via Compositor"
-msgstr ""
+msgstr "V-Sync preko Kompozitora"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Delta Smoothing"
-msgstr ""
+msgstr "Delta Ublažavanje"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode"
-msgstr ""
+msgstr "NaÄin niske upotrebe procesora"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode Sleep (µsec)"
-msgstr ""
+msgstr "Stanje mirovanja u naÄinu koriÅ¡tenja niskog procesora (μsec)"
#: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp
msgid "Keep Screen On"
-msgstr ""
+msgstr "Zadrži zaslon ukljuÄenim"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Min Window Size"
-msgstr "Glavna skripta:"
+msgstr "Min. veliÄina prozora"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Max Window Size"
-msgstr "Glavna skripta:"
+msgstr "Maks. veliÄina prozora"
#: core/bind/core_bind.cpp
msgid "Screen Orientation"
-msgstr ""
+msgstr "Orijentacija zaslona"
#: core/bind/core_bind.cpp core/project_settings.cpp main/main.cpp
#: platform/uwp/os_uwp.cpp
+#, fuzzy
msgid "Window"
-msgstr ""
+msgstr "Prozor"
#: core/bind/core_bind.cpp core/project_settings.cpp
+#, fuzzy
msgid "Borderless"
-msgstr ""
+msgstr "Bez obruba"
#: core/bind/core_bind.cpp
+#, fuzzy
msgid "Per Pixel Transparency Enabled"
-msgstr ""
+msgstr "Omogućena prozirnost po pikselu"
#: core/bind/core_bind.cpp core/project_settings.cpp
+#, fuzzy
msgid "Fullscreen"
-msgstr ""
+msgstr "Cijeli zaslon"
#: core/bind/core_bind.cpp
+#, fuzzy
msgid "Maximized"
-msgstr ""
+msgstr "Maksimiziran"
#: core/bind/core_bind.cpp
+#, fuzzy
msgid "Minimized"
-msgstr ""
+msgstr "Minimiziran"
#: core/bind/core_bind.cpp core/project_settings.cpp scene/gui/dialogs.cpp
#: scene/gui/graph_node.cpp
+#, fuzzy
msgid "Resizable"
-msgstr ""
+msgstr "Mogućnost promjene veliÄine"
#: core/bind/core_bind.cpp core/os/input_event.cpp scene/2d/node_2d.cpp
#: scene/2d/physics_body_2d.cpp scene/2d/remote_transform_2d.cpp
@@ -114,7 +119,7 @@ msgstr ""
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Position"
-msgstr "Stvori"
+msgstr "Pozicija"
#: core/bind/core_bind.cpp core/project_settings.cpp editor/editor_settings.cpp
#: main/main.cpp modules/gridmap/grid_map.cpp
@@ -125,8 +130,9 @@ msgstr "Stvori"
#: scene/resources/primitive_meshes.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp scene/resources/texture.cpp
#: scene/resources/visual_shader.cpp servers/visual_server.cpp
+#, fuzzy
msgid "Size"
-msgstr ""
+msgstr "VeliÄina"
#: core/bind/core_bind.cpp
msgid "Endian Swap"
@@ -135,25 +141,27 @@ msgstr ""
#: core/bind/core_bind.cpp
#, fuzzy
msgid "Editor Hint"
-msgstr "(Editor Onemogućen)"
+msgstr "Savjet Urednika"
#: core/bind/core_bind.cpp
+#, fuzzy
msgid "Print Error Messages"
-msgstr ""
+msgstr "Ispis poruka o pogreškama"
#: core/bind/core_bind.cpp
#, fuzzy
msgid "Iterations Per Second"
-msgstr "NaÄin Interpolacije"
+msgstr "Iteracije u sekundi"
#: core/bind/core_bind.cpp
+#, fuzzy
msgid "Target FPS"
-msgstr ""
+msgstr "Ciljani FPS"
#: core/bind/core_bind.cpp
#, fuzzy
msgid "Time Scale"
-msgstr "Dubina"
+msgstr "Vremenska skala"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Physics Jitter Fix"
@@ -408,6 +416,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
@@ -460,6 +473,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2116,14 +2133,15 @@ msgstr "Favoriti:"
msgid "Recent:"
msgstr "Nedavno:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Pretraga:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Podudaranja:"
@@ -2183,8 +2201,8 @@ msgstr "Traži zamjenu resursa:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2755,8 +2773,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Animacija"
#: editor/editor_export.cpp
#, fuzzy
@@ -5381,6 +5400,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11465,6 +11493,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Obrisati Animaciju?"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18135,6 +18168,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 +18181,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 +18227,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 +18457,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 +18471,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
@@ -19760,15 +19818,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Nevažeće ime."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -19790,15 +19848,15 @@ msgstr "Nevažeće ime."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Nevažeće ime."
#: platform/windows/export/export.cpp
msgid "Failed to remove temporary file \"%s\"."
@@ -20025,7 +20083,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 +20786,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 +20799,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 ""
@@ -20799,7 +20867,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22738,6 +22806,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Uredi Tranzicije..."
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23883,6 +23956,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 +24338,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..b35be76368 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
@@ -502,6 +507,10 @@ msgid "Pressure"
msgstr "Előre beállított"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Relatív Illesztés"
@@ -2217,14 +2226,15 @@ msgstr "Kedvencek:"
msgid "Recent:"
msgstr "Legutóbbi:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Keresés:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Egyezések:"
@@ -2284,8 +2294,8 @@ msgstr "Csere Forrás Keresése:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2862,7 +2872,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Node Útvonal Másolása"
#: editor/editor_export.cpp
@@ -5670,6 +5680,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11919,6 +11938,11 @@ msgid "New Animation"
msgstr "Új animáció"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Metódusok szűrése"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18763,6 +18787,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 +18800,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 +18849,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 +19094,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 +19108,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
@@ -20461,15 +20510,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Érvénytelen kiterjesztés."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20491,15 +20540,15 @@ msgstr "Érvénytelen név."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Érvénytelen kiterjesztés."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20740,7 +20789,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 +21525,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 +21538,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 ""
@@ -21550,7 +21609,7 @@ msgstr "Utazás"
msgid "Rotation Degrees"
msgstr "Forgatási Léptetés:"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Ãllandó"
@@ -23583,6 +23642,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Globális Transzformáció Megtartása"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24797,6 +24861,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 +25268,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..7d839357cd 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -26,7 +26,7 @@
# Ade Fikri Malihuddin <ade.fm97@gmail.com>, 2020.
# zephyroths <ridho.hikaru@gmail.com>, 2020, 2021, 2022.
# Richard Urban <redasuio1@gmail.com>, 2020.
-# yusuf afandi <afandi.yusuf.04@gmail.com>, 2020.
+# yusuf afandi <afandi.yusuf.04@gmail.com>, 2020, 2022.
# Habib Rohman <revolusi147id@gmail.com>, 2020.
# Hanz <hanzhaxors@gmail.com>, 2021.
# Reza Almanda <rezaalmanda27@gmail.com>, 2021, 2022.
@@ -39,13 +39,14 @@
# ProgrammerIndonesia 44 <elo.jhy@gmail.com>, 2022.
# Rizky Ramadhan <rizkyterm@gmail.com>, 2022.
# Primananda Kurnia <primakurnia71@gmail.com>, 2022.
+# FellowMustard <rachmawanng33@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-05-15 09:38+0000\n"
-"Last-Translator: Tsaqib Fadhlurrahman Soka <sokatsaqib@gmail.com>\n"
+"PO-Revision-Date: 2022-07-31 18:34+0000\n"
+"Last-Translator: ProgrammerIndonesia 44 <elo.jhy@gmail.com>\n"
"Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/"
"godot/id/>\n"
"Language: id\n"
@@ -53,7 +54,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -425,6 +426,10 @@ msgstr "Meta"
msgid "Command"
msgstr "Perintah"
+#: core/os/input_event.cpp
+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
@@ -476,6 +481,11 @@ msgid "Pressure"
msgstr "Tekanan"
#: core/os/input_event.cpp
+#, fuzzy
+msgid "Pen Inverted"
+msgstr "Balik"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relatif"
@@ -1196,7 +1206,7 @@ msgstr "Atur Pegangan"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
msgid "Stream"
-msgstr ""
+msgstr "Arus"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -2148,14 +2158,15 @@ msgstr "Favorit:"
msgid "Recent:"
msgstr "Saat ini:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Cari:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Kecocokan:"
@@ -2215,8 +2226,8 @@ msgstr "Cari Resource Pengganti:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2793,13 +2804,12 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Salin Lokasi Node"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Completed successfully."
-msgstr "Paket Sukses Terpasang!"
+msgstr "Sukses."
#: editor/editor_export.cpp
#, fuzzy
@@ -3278,9 +3288,8 @@ msgid "Save a File"
msgstr "Simpan sebuah File"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Access"
-msgstr "Sukses!"
+msgstr "Akses"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
#, fuzzy
@@ -5601,6 +5610,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Penampilan"
@@ -11834,6 +11852,11 @@ msgid "New Animation"
msgstr "Animasi Baru"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filter method"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Kecepatan:"
@@ -12356,9 +12379,8 @@ msgid "Available Node-based types:"
msgstr "Profil yang Tersedia:"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Type name is empty!"
-msgstr "Nama berkas kosong."
+msgstr "Nama tipe kosong!"
#: editor/plugins/theme_editor_plugin.cpp
#, fuzzy
@@ -18874,6 +18896,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 +18909,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 +18961,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 +19201,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 +19209,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 +19222,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\"."
@@ -19237,9 +19285,8 @@ msgid "Could not find keystore, unable to export."
msgstr "Tidak dapat menemukan keystore, tidak bisa ekspor."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not start apksigner executable."
-msgstr "Tidak dapat memulai subproses!"
+msgstr "Tidak dapat memulai apksigner."
#: platform/android/export/export_plugin.cpp
msgid "'apksigner' returned with error #%d"
@@ -19272,9 +19319,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension."
msgstr "Nama berkas tidak valid! APK Android memerlukan ekstensi *.apk ."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Unsupported export format!"
-msgstr "Format ekspor tidak didukung!\n"
+msgstr "Format ekspor tidak didukung!"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19285,15 +19331,12 @@ msgstr ""
"versinya. Silakan pasang ulang dari menu 'Proyek'."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Android build version mismatch: Template installed: %s, Godot version: %s. "
"Please reinstall Android build template from 'Project' menu."
msgstr ""
-"Versi build Android tidak cocok:\n"
-" Templat terpasang: %s\n"
-" Versi Godot: %s\n"
-"Silakan pasang ulang templat build Android dari menu 'Project'."
+"Versi build Android tidak cocok: Templat terpasang: %s, Versi Godot: %s. "
+"Silakan pasang ulang templat build Android dari menu 'Proyek'."
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19301,9 +19344,8 @@ msgid ""
msgstr ""
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
-msgstr "Tidak dapat menyunting proyek gradle dalam lokasi proyek\n"
+msgstr "Tidak dapat mengekspor file proyek ke dalam lokasi proyek gradle."
#: platform/android/export/export_plugin.cpp
msgid "Could not write expansion package file!"
@@ -19314,13 +19356,12 @@ msgid "Building Android Project (gradle)"
msgstr "Membangun Proyek Android (gradle)"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Building of Android project failed, check output for the error. "
"Alternatively visit docs.godotengine.org for Android build documentation."
msgstr ""
-"Pembangunan proyek Android gagal, periksa output untuk galatnya.\n"
-"Atau kunjungi docs.godotengine.org untuk dokumentasi build Android."
+"Pembangunan proyek Android gagal, periksa output untuk galatnya. Atau "
+"kunjungi docs.godotengine.org untuk dokumentasi build Android."
#: platform/android/export/export_plugin.cpp
msgid "Moving output"
@@ -19345,11 +19386,8 @@ msgid "Creating APK..."
msgstr "Membuat kontur..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not find template APK to export: \"%s\"."
-msgstr ""
-"Tidak dapat menemukan contoh APK untuk ekspor:\n"
-"%s"
+msgstr "Tidak dapat menemukan contoh APK untuk ekspor: \"%s\""
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19508,9 +19546,8 @@ msgid "Capabilities"
msgstr "Kapabilitas"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Access Wi-Fi"
-msgstr "Sukses!"
+msgstr "Akses Wi-Fi"
#: platform/iphone/export/export.cpp
#, fuzzy
@@ -20058,9 +20095,8 @@ msgid "Could not open icon file \"%s\"."
msgstr "Tidak dapat ekspor berkas proyek"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start xcrun executable."
-msgstr "Tidak dapat memulai subproses!"
+msgstr "Tidak dapat memulai subproses xcrun."
#: platform/osx/export/export.cpp
#, fuzzy
@@ -20138,9 +20174,8 @@ msgid "DMG Creation"
msgstr "Arah"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start hdiutil executable."
-msgstr "Tidak dapat memulai subproses!"
+msgstr "Tidak dapat memulai subproses hdiutil."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed - file exists."
@@ -20222,7 +20257,7 @@ msgstr "Proyeksi"
#: platform/osx/export/export.cpp
#, fuzzy
msgid "Could not open file to read from path \"%s\"."
-msgstr "Tidak dapat menyunting proyek gradle dalam lokasi proyek\n"
+msgstr "Tidak dapat membuka file untuk membaca dari jalur \"%s\"."
#: platform/osx/export/export.cpp
msgid "Invalid bundle identifier:"
@@ -20607,15 +20642,15 @@ msgstr "Tidak dapat menemukan keystore, tidak bisa ekspor."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Ekstensi tidak valid."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20639,15 +20674,15 @@ msgstr "Nama tidak sah."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Ekstensi tidak valid."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20881,7 +20916,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 +21662,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 +21675,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 +21706,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 ""
@@ -21707,7 +21752,7 @@ msgstr "Menjelajah"
msgid "Rotation Degrees"
msgstr "Derajat Putaran"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr "Rotasi Global"
@@ -23776,6 +23821,11 @@ msgstr ""
"Ubah ukurannya melalui \"collision shape\"-anaknya saja."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Transformasi Global"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr "Matriks"
@@ -24696,7 +24746,7 @@ msgstr ""
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Caret"
-msgstr ""
+msgstr "Tanda sisipan"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink"
@@ -25037,6 +25087,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"
@@ -25373,9 +25428,8 @@ msgid "Draw 2D Outlines"
msgstr "Buat Garis Tepi"
#: scene/main/scene_tree.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Reflections"
-msgstr "Arah"
+msgstr "Refleksi"
#: scene/main/scene_tree.cpp
#, fuzzy
@@ -25443,19 +25497,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 +25504,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 ""
@@ -26735,9 +26785,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/is.po b/editor/translations/is.po
index 105220c71e..512c660eef 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
@@ -453,6 +457,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2132,14 +2140,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2195,8 +2204,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2758,8 +2767,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Fjarlægja val"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5368,6 +5378,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11431,6 +11450,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Stillið breyting á:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18081,6 +18105,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 +18118,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 +18163,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 +18390,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 +18404,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
@@ -19676,14 +19725,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19704,14 +19752,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19932,7 +19979,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 +20672,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 +20684,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 ""
@@ -20696,7 +20752,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22597,6 +22653,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Breyta umbreytingu"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23706,6 +23767,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 +24143,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..2c9f7eb6fe 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -68,12 +68,15 @@
# 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.
+# Gico2006 <gradaellig@protonmail.com>, 2022.
+# ale piccia <picciatialessio2@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"
+"PO-Revision-Date: 2022-07-31 18:34+0000\n"
"Last-Translator: Mirko <miknsop@gmail.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/"
"godot/it/>\n"
@@ -82,7 +85,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -373,7 +376,6 @@ msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Byte insufficienti per decodificarli o formato non valido."
#: core/math/expression.cpp
-#, fuzzy
msgid "Invalid input %d (not passed) in expression"
msgstr "Input %d non valido (assente) nell'espressione"
@@ -419,14 +421,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 Accumulati"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
@@ -453,6 +453,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
@@ -468,6 +473,7 @@ msgid "Physical Scancode"
msgstr "Scancode Fisico"
#: core/os/input_event.cpp
+#, fuzzy
msgid "Unicode"
msgstr "Unicode"
@@ -504,6 +510,10 @@ msgid "Pressure"
msgstr "Pressione"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relativo"
@@ -663,14 +673,12 @@ msgid "Always On Top"
msgstr "Sempre In Primo Piano"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Width"
-msgstr "Larghezza Test"
+msgstr "Test Larghezza"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Height"
-msgstr "Altezza Test"
+msgstr "Test Altezza"
#: core/project_settings.cpp editor/animation_track_editor.cpp
#: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp
@@ -705,14 +713,12 @@ msgid "Script Templates Search Path"
msgstr "Percorso di Ricerca dei Template di Script"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Autoload On Startup"
-msgstr "Autocaricamento all'Avvio"
+msgstr "Caricamento automatico del controllo di versione all'avvio"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Plugin Name"
-msgstr "Controllo della versione"
+msgstr "Nome del plugin di controllo della versione"
#: core/project_settings.cpp scene/2d/collision_object_2d.cpp
#: scene/3d/collision_object.cpp scene/gui/control.cpp
@@ -895,6 +901,7 @@ msgid "Modules"
msgstr "Moduli"
#: core/register_core_types.cpp
+#, fuzzy
msgid "TCP"
msgstr "TCP"
@@ -1202,14 +1209,12 @@ msgid "Type"
msgstr "Tipo"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In Handle"
-msgstr "Imposta Maniglia"
+msgstr "In gestione"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out Handle"
-msgstr "Imposta Maniglia"
+msgstr "Non gestire"
#: editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
@@ -1237,9 +1242,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 +1357,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 +1384,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
@@ -1402,19 +1403,16 @@ msgid "Stream:"
msgstr "Stream"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start (s):"
-msgstr "Riavvia (s):"
+msgstr "inizia:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End (s):"
-msgstr "Fade In (s):"
+msgstr "finisci:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation Clip:"
-msgstr "Animazioni:"
+msgstr "clip delle animazioni:"
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
@@ -2117,6 +2115,7 @@ msgid "Are you sure you want to remove all connections from the \"%s\" signal?"
msgstr "Sei sicuro di voler rimuovere tutte le connessioni dal segnale \"%s\"?"
#: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp
+#, fuzzy
msgid "Signals"
msgstr "Segnali"
@@ -2169,14 +2168,15 @@ msgstr "Preferiti:"
msgid "Recent:"
msgstr "Recenti:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Cerca:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Corrispondenze:"
@@ -2236,8 +2236,8 @@ msgstr "Cerca risorsa di rimpiazzo:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2246,7 +2246,7 @@ msgstr "Apri"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "proprietario di: %s (Totale: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2603,9 +2603,8 @@ msgid "There is no '%s' file."
msgstr "File \"%s\" assente."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Layout:"
-msgstr "Disposizione"
+msgstr ""
#: editor/editor_audio_buses.cpp
msgid "Invalid file, not an audio bus layout."
@@ -2815,7 +2814,7 @@ msgstr "Esportazione del progetto per la piattaforma:"
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Completato con errori."
#: editor/editor_export.cpp
@@ -2846,9 +2845,8 @@ msgid "Save PCK"
msgstr "Salva PCK"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Cannot create file \"%s\"."
-msgstr "Impossibile creare la cartella."
+msgstr "impossibile creare il file \"%s\"."
#: editor/editor_export.cpp
#, fuzzy
@@ -2856,9 +2854,8 @@ msgid "Failed to export project files."
msgstr "Impossibile esportare i file del progetto"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Can't open file to read from path \"%s\"."
-msgstr "Impossibile aprire il file in scrittura:"
+msgstr "impossibile aprire file da leggere dalla path \"%s\"."
#: editor/editor_export.cpp
#, fuzzy
@@ -5573,6 +5570,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Aspetto"
@@ -6992,6 +6998,7 @@ msgstr "Anisotropico"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
+#, fuzzy
msgid "sRGB"
msgstr "sRGB"
@@ -11730,6 +11737,11 @@ msgid "New Animation"
msgstr "Nuova Animazione"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Modalità di filtraggio"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Velocità:"
@@ -16241,8 +16253,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"
@@ -18011,7 +18024,6 @@ msgid "Expression"
msgstr "Espressione"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Return"
msgstr "Ritorno"
@@ -18562,6 +18574,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 +18586,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 +18632,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"
@@ -18666,7 +18683,6 @@ msgid "Hand Tracking Frequency"
msgstr ""
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Passthrough"
msgstr "Passthrough"
@@ -18856,7 +18872,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 +18880,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 +18893,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
@@ -20302,15 +20338,15 @@ msgstr "Non è stato possibile trovare keystore, impossible esportare."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Estensione non valida."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20334,15 +20370,15 @@ msgstr "Nome non valido."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Estensione non valida."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20584,7 +20620,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 +20677,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
@@ -20889,9 +20926,8 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Fixed FPS"
-msgstr "Vedi FPS"
+msgstr "FPS fisso"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -20958,7 +20994,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 +21005,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 +21019,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 +21046,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 +21407,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 +21420,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 +21452,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."
@@ -21448,7 +21497,7 @@ msgstr "Spostamento"
msgid "Rotation Degrees"
msgstr "Rotazione in Gradi"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Costante"
@@ -21866,12 +21915,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 +22180,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 +22322,9 @@ msgid "Projection"
msgstr "Proiezione"
#: scene/3d/camera.cpp
+#, fuzzy
msgid "FOV"
-msgstr ""
+msgstr "FOV"
#: scene/3d/camera.cpp
#, fuzzy
@@ -22284,8 +22337,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 +22524,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 +22677,9 @@ msgid "Depth Range"
msgstr "Profondità"
#: scene/3d/light.cpp
+#, fuzzy
msgid "Omni"
-msgstr ""
+msgstr "Omni"
#: scene/3d/light.cpp
#, fuzzy
@@ -23363,8 +23419,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
@@ -23589,6 +23646,11 @@ msgstr ""
"Modifica invece la dimensione nelle forme di collisione figlie."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Mantieni Transform Globale"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23607,8 +23669,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 +23792,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 +24105,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 +24892,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 +25304,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 +25311,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 ""
@@ -26346,7 +26412,6 @@ msgid "Sky Contribution"
msgstr "Condizione"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Fog"
msgstr "Nebbia"
@@ -26693,7 +26758,7 @@ msgstr ""
#: scene/resources/material.cpp
msgid "Is sRGB"
-msgstr ""
+msgstr "È sRGB"
#: scene/resources/material.cpp servers/visual_server.cpp
#, fuzzy
@@ -26811,9 +26876,8 @@ msgid "Flowmap"
msgstr ""
#: scene/resources/material.cpp
-#, fuzzy
msgid "Ambient Occlusion"
-msgstr "Occlusione"
+msgstr "Occlusione ambientale"
#: scene/resources/material.cpp
msgid "Deep Parallax"
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index a699aeb597..60458e89df 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
@@ -482,6 +487,11 @@ msgid "Pressure"
msgstr "圧力"
#: core/os/input_event.cpp
+#, fuzzy
+msgid "Pen Inverted"
+msgstr "å転"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "相対的"
@@ -2170,14 +2180,15 @@ msgstr "ãŠæ°—ã«å…¥ã‚Š:"
msgid "Recent:"
msgstr "最近:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "検索:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "一致:"
@@ -2237,8 +2248,8 @@ msgstr "ç½®æ›ã™ã‚‹ãƒªã‚½ãƒ¼ã‚¹ã‚’検索:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2811,7 +2822,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "ノードã®ãƒ‘スをコピー"
#: editor/editor_export.cpp
@@ -5567,6 +5578,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap ã®é¸æŠž"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "外観"
@@ -11762,6 +11782,11 @@ msgid "New Animation"
msgstr "æ–°è¦ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "メソッドを絞り込む"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "速度:"
@@ -18661,6 +18686,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 +18699,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 +18751,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 +18998,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 +19017,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 ""
+"\"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 ""
"\"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\" ãƒãƒ¼ã‚¸ãƒ§ãƒ³ä»¥ä¸Šã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。"
@@ -20407,15 +20462,15 @@ msgstr "キーストアãŒè¦‹ã¤ã‹ã‚‰ãªã„ãŸã‚ã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "無効ãªå®Ÿè¡Œå¯èƒ½ãƒ•ァイルã§ã™ã€‚"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20439,15 +20494,15 @@ msgstr "無効ãªåå‰ã§ã™ã€‚"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "無効ãªå®Ÿè¡Œå¯èƒ½ãƒ•ァイルã§ã™ã€‚"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20681,7 +20736,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 +21496,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 +21509,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 +21541,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 ""
@@ -21523,7 +21588,7 @@ msgstr "トラベル"
msgid "Rotation Degrees"
msgstr "%s 度回転。"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "コンスタント"
@@ -23661,6 +23726,11 @@ msgstr ""
"代ã‚りã«ã€å­ã®è¡çªã‚·ã‚§ã‚¤ãƒ—ã®ã‚µã‚¤ã‚ºã‚’変更ã—ã¦ãã ã•ã„。"
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "グローãƒãƒ« ãƒˆãƒ©ãƒ³ã‚¹ãƒ•ã‚©ãƒ¼ãƒ ã‚’ä¿æŒ"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24919,6 +24989,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 +25402,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..2e6e0e70e7 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
@@ -461,6 +466,10 @@ msgid "Pressure"
msgstr "ზუმის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ–ე დáƒáƒ§áƒ”ნებáƒ"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2186,14 +2195,15 @@ msgstr "სáƒáƒ§áƒ•áƒáƒ áƒšáƒ”ბი:"
msgid "Recent:"
msgstr "ბáƒáƒšáƒ:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "ძებნáƒ:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "დáƒáƒ›áƒ—ხვევები:"
@@ -2255,8 +2265,8 @@ msgstr "ჩáƒáƒ›áƒœáƒáƒªáƒ•ლებელი რესურსის ძიá
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2837,8 +2847,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "მáƒáƒœáƒ˜áƒ¨áƒ•ნის მáƒáƒ¨áƒáƒ áƒ”ბáƒ"
#: editor/editor_export.cpp
#, fuzzy
@@ -5496,6 +5507,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "ყველრმáƒáƒœáƒ˜áƒ¨áƒœáƒ•áƒ"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11713,6 +11733,11 @@ msgid "New Animation"
msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ áƒáƒžáƒ¢áƒ˜áƒ›áƒ˜áƒ–áƒáƒªáƒ˜áƒ"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "ფუნქციები:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18503,6 +18528,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 +18541,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 +18587,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 +18821,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 +18835,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20145,15 +20195,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ ფáƒáƒœáƒ¢áƒ˜áƒ¡ ზáƒáƒ›áƒ."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20175,15 +20225,15 @@ msgstr "áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ ფáƒáƒœáƒ¢áƒ˜áƒ¡ ზáƒáƒ›áƒ."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ ფáƒáƒœáƒ¢áƒ˜áƒ¡ ზáƒáƒ›áƒ."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20411,7 +20461,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 +21169,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 +21182,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 ""
@@ -21190,7 +21250,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "მუდმივი"
@@ -23145,6 +23205,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ áƒ“áƒáƒ¥áƒ›áƒœáƒ˜áƒ¡ ცვლილებáƒ"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24305,6 +24370,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 +24757,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..522cb30363 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
@@ -436,6 +440,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2063,14 +2071,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2126,8 +2135,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2686,8 +2695,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Anim ផ្លាស់ប្ážáž¼ážš Transform"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5257,6 +5267,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11228,6 +11246,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Key(s) ដែលបានជ្រើសស្ទួន"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17719,6 +17742,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 +17754,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 +17798,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 +18016,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 +18030,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
@@ -19271,14 +19319,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19300,14 +19347,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19520,7 +19566,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 +20230,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 +20242,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
@@ -20253,7 +20307,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22076,6 +22130,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Anim ផ្លាស់ប្ážáž¼ážš Transition"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23152,6 +23211,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 +23567,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..a91450dd41 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
@@ -472,6 +477,10 @@ msgid "Pressure"
msgstr "ì••ë ¥"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "ìƒëŒ€ì "
@@ -2114,14 +2123,15 @@ msgstr "ì¦ê²¨ì°¾ê¸°:"
msgid "Recent:"
msgstr "최근 기ë¡:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "검색:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "ì¼ì¹˜í•¨:"
@@ -2181,8 +2191,8 @@ msgstr "대체 리소스 검색:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2751,7 +2761,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "íŒŒì¼ ê²½ë¡œ 완성"
#: editor/editor_export.cpp
@@ -5468,6 +5478,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "마우스 부가 버튼으로 히스토리 둘러보기"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "그리드맵 ì„ íƒ"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "모습"
@@ -11667,6 +11686,11 @@ msgid "New Animation"
msgstr "새 애니메ì´ì…˜"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "메서드 필터"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "ì†ë„:"
@@ -18634,6 +18658,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 +18671,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 +18723,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 +18969,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 +18987,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
@@ -20371,15 +20420,15 @@ msgstr "keystore를 ì°¾ì„ ìˆ˜ 없어, 내보낼 수 없었습니다."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "ìž˜ëª»ëœ í™•ìž¥ìž."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20403,15 +20452,15 @@ msgstr "올바르지 ì•Šì€ ì´ë¦„입니다."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "ìž˜ëª»ëœ í™•ìž¥ìž."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20653,7 +20702,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 +21467,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 +21480,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 +21512,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."
@@ -21497,7 +21556,7 @@ msgstr "ì§„í–‰"
msgid "Rotation Degrees"
msgstr "%së„로 회전."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "ìƒìˆ˜"
@@ -23621,6 +23680,11 @@ msgstr ""
"대신 ìžì‹ 콜리전 ëª¨ì–‘ì˜ í¬ê¸°ë¥¼ 변경하세요."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "전역 변형 유지"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24875,6 +24939,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 +25354,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..66891e3f0e 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
@@ -471,6 +476,10 @@ msgid "Pressure"
msgstr "Atstatyti PriartinimÄ…"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2169,14 +2178,15 @@ msgstr "MÄ—gstamiausi:"
msgid "Recent:"
msgstr "Naujausi:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Ieškoti:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2232,8 +2242,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2796,8 +2806,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Panaikinti pasirinkimÄ…"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5473,6 +5484,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11702,6 +11722,11 @@ msgid "New Animation"
msgstr "Animacija"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filtrai..."
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18503,6 +18528,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 +18541,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 +18587,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 +18823,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 +18837,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20166,15 +20216,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Netinkamas šrifto dydis."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20196,15 +20246,15 @@ msgstr "Netinkamas šrifto dydis."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Netinkamas šrifto dydis."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20436,7 +20486,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 +21193,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 +21206,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 ""
@@ -21214,7 +21274,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstanta"
@@ -23178,6 +23238,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Animacija: Pakeisti TransformacijÄ…"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24339,6 +24404,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 +24792,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..c00e8d1a44 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
@@ -474,6 +479,10 @@ msgid "Pressure"
msgstr "Sagatave"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2164,14 +2173,15 @@ msgstr "Favorīti:"
msgid "Recent:"
msgstr "Nesenie:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Meklēt:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Sakritības:"
@@ -2231,8 +2241,8 @@ msgstr "MeklÄ“t aizstÄjÄ“ja resursu:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2809,7 +2819,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Kopēt mezgla ceļu"
#: editor/editor_export.cpp
@@ -5544,6 +5554,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11630,6 +11649,11 @@ msgid "New Animation"
msgstr "Jauna animÄcija"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "animÄcija"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18309,6 +18333,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 +18346,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 +18395,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 +18628,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 +18642,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
@@ -19973,15 +20022,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "NederÄ«gs paplaÅ¡inÄjums."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20003,15 +20052,15 @@ msgstr "Nederīgs nosaukums."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "NederÄ«gs paplaÅ¡inÄjums."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20249,7 +20298,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 +21016,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 +21029,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 ""
@@ -21038,7 +21097,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstante"
@@ -23020,6 +23079,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "PÄreja eksistÄ“!"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24206,6 +24270,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 +24668,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..2d183ec609 100644
--- a/editor/translations/mk.po
+++ b/editor/translations/mk.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-06-29 10:04+0000\n"
+"PO-Revision-Date: 2022-07-23 03:57+0000\n"
"Last-Translator: Kristijan Fremen Velkovski <me@krisfremen.com>\n"
"Language-Team: Macedonian <https://hosted.weblate.org/projects/godot-engine/"
"godot/mk/>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n==1 || n%10==1 ? 0 : 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -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
@@ -440,6 +444,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "GDNative(ГДДомороден)"
@@ -1247,7 +1255,7 @@ msgstr ""
#: editor/animation_track_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Functions:"
-msgstr ""
+msgstr "Фукнции:"
#: editor/animation_track_editor.cpp
msgid "Audio Clips:"
@@ -1350,33 +1358,33 @@ msgstr ""
#: editor/animation_track_editor.cpp
msgid "Continuous"
-msgstr ""
+msgstr "Континуирана"
#: editor/animation_track_editor.cpp
msgid "Discrete"
-msgstr ""
+msgstr "ДиÑкретна"
#: editor/animation_track_editor.cpp
msgid "Trigger"
-msgstr ""
+msgstr "Чкрапало"
#: editor/animation_track_editor.cpp scene/3d/baked_lightmap.cpp
msgid "Capture"
-msgstr ""
+msgstr "Снимање"
#: editor/animation_track_editor.cpp
msgid "Nearest"
-msgstr ""
+msgstr "ÐајблиÑку"
#: editor/animation_track_editor.cpp editor/plugins/curve_editor_plugin.cpp
#: editor/property_editor.cpp scene/2d/physics_body_2d.cpp
#: scene/3d/physics_body.cpp
msgid "Linear"
-msgstr ""
+msgstr "Линеарна"
#: editor/animation_track_editor.cpp
msgid "Cubic"
-msgstr ""
+msgstr "Кубни"
#: editor/animation_track_editor.cpp
msgid "Clamp Loop Interp"
@@ -1454,7 +1462,7 @@ msgstr ""
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Create"
-msgstr ""
+msgstr "Создади"
#: editor/animation_track_editor.cpp
msgid "Anim Insert"
@@ -1755,7 +1763,7 @@ msgstr ""
#: editor/animation_track_editor.cpp
msgid "Clean-Up"
-msgstr ""
+msgstr "ОчиÑти"
#: editor/animation_track_editor.cpp
msgid "Scale Ratio:"
@@ -1832,7 +1840,7 @@ msgstr ""
#: editor/code_editor.cpp
msgid "Replace"
-msgstr ""
+msgstr "Замени"
#: editor/code_editor.cpp
msgid "Replace All"
@@ -1845,7 +1853,7 @@ msgstr ""
#: editor/code_editor.cpp editor/plugins/script_text_editor.cpp
#: editor/plugins/text_editor.cpp
msgid "Standard"
-msgstr ""
+msgstr "Стандардно"
#: editor/code_editor.cpp editor/plugins/script_editor_plugin.cpp
msgid "Toggle Scripts Panel"
@@ -1871,7 +1879,7 @@ msgstr ""
#: editor/code_editor.cpp modules/gdscript/gdscript.cpp
msgid "Warnings"
-msgstr ""
+msgstr "Предупредувања"
#: editor/code_editor.cpp
msgid "Line and column numbers."
@@ -1913,7 +1921,7 @@ msgstr ""
#: editor/plugins/item_list_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp
msgid "Add"
-msgstr ""
+msgstr "Додади"
#: editor/connections_dialog.cpp editor/dependency_editor.cpp
#: editor/groups_editor.cpp editor/plugins/animation_player_editor_plugin.cpp
@@ -1923,7 +1931,7 @@ msgstr ""
#: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp
#: editor/project_settings_editor.cpp
msgid "Remove"
-msgstr ""
+msgstr "Избриши"
#: editor/connections_dialog.cpp
msgid "Add Extra Call Argument:"
@@ -1940,11 +1948,11 @@ msgstr ""
#: editor/connections_dialog.cpp scene/3d/room_manager.cpp
#: servers/visual_server.cpp
msgid "Advanced"
-msgstr ""
+msgstr "Ðапредно"
#: editor/connections_dialog.cpp
msgid "Deferred"
-msgstr ""
+msgstr "Одложено"
#: editor/connections_dialog.cpp
msgid ""
@@ -2072,14 +2080,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2135,8 +2144,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2695,7 +2704,7 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr ""
#: editor/editor_export.cpp
@@ -5274,6 +5283,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11256,6 +11273,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "СвојÑтва на анимацијата."
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17759,6 +17781,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 +17792,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 +17837,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 +18057,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 +18071,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
@@ -19317,14 +19363,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19346,14 +19391,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19568,7 +19612,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 +20280,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 +20292,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
@@ -20305,7 +20357,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22135,6 +22187,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Ðнимација Промени Прелаз"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23217,6 +23274,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 +23632,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..7568bc881e 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
@@ -446,6 +450,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2082,14 +2090,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2145,8 +2154,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2706,8 +2715,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "ചലനം à´šàµà´±àµà´±àµ½"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5290,6 +5300,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11278,6 +11296,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "ചലനം à´šàµà´±àµà´±àµ½"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17788,6 +17811,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 +17824,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 +17868,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 +18088,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 +18102,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
@@ -19355,14 +19403,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19384,14 +19431,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19608,7 +19654,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 +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 ""
@@ -20287,27 +20337,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
@@ -20348,7 +20402,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22206,6 +22260,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "ചലനം à´šàµà´±àµà´±àµ½"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23295,6 +23354,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 +23713,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..4bdf5ba4fb 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
@@ -446,6 +450,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2083,14 +2091,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2146,8 +2155,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2706,8 +2715,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "अâ€à¥…निमेशन टà¥à¤°à¥€"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5280,6 +5290,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11266,6 +11284,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "अâ€à¥…निमेशन टà¥à¤°à¥€"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17787,6 +17810,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 +17822,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 +17867,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 +18089,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 +18103,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
@@ -19356,14 +19404,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19385,14 +19432,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19609,7 +19655,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 +20338,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 +20350,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 ""
@@ -20364,7 +20419,7 @@ msgstr "पà¥à¤°à¤µà¤¾à¤¸"
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22226,6 +22281,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "संकà¥à¤°à¤®à¤£: "
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23322,6 +23382,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 +23742,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..61a60ad8fe 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
@@ -446,6 +451,10 @@ msgid "Pressure"
msgstr "Tekanan"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relatif"
@@ -2092,14 +2101,15 @@ msgstr "Kegemaran:"
msgid "Recent:"
msgstr "Terkini:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Cari:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Padanan:"
@@ -2159,8 +2169,8 @@ msgstr "Cari Penggantian Sumber:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2735,8 +2745,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Salin Pilihan"
#: editor/editor_export.cpp
#, fuzzy
@@ -5537,6 +5548,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11719,6 +11739,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Padam Animasi?"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18502,6 +18527,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 +18540,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 +18588,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 +18830,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 +18844,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20177,15 +20227,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Nama kumpulan tidak sah."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20207,15 +20257,15 @@ msgstr "Nama tidak sah."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Nama kumpulan tidak sah."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20453,7 +20503,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 +21226,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 +21239,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 ""
@@ -21250,7 +21310,7 @@ msgstr "Perjalanan"
msgid "Rotation Degrees"
msgstr "Langkah Putaran:"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Pemalar"
@@ -23252,6 +23312,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Kosongkan Transformasi"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24450,6 +24515,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 +24917,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..542d5987ca 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
@@ -468,6 +473,10 @@ msgid "Pressure"
msgstr "Trykk"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relativ"
@@ -2196,14 +2205,15 @@ msgstr "Favoritter:"
msgid "Recent:"
msgstr "Nylige:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Søk:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Treff:"
@@ -2265,8 +2275,8 @@ msgstr "Søk Erstatningsressurs:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2866,7 +2876,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Kopier Node-bane"
#: editor/editor_export.cpp
@@ -5721,6 +5731,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -12201,6 +12220,11 @@ msgstr "Animasjon"
#: editor/plugins/sprite_frames_editor_plugin.cpp
#, fuzzy
+msgid "Filter animations"
+msgstr "Lim inn Noder"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
msgid "Speed:"
msgstr "Hastighet (FPS):"
@@ -19287,6 +19311,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 +19324,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 +19375,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 +19620,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 +19634,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
@@ -21000,15 +21049,15 @@ msgstr "Kunne ikke opprette mappe."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "MÃ¥ ha en gyldig filutvidelse."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21032,15 +21081,15 @@ msgstr "Ugyldig navn."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "MÃ¥ ha en gyldig filutvidelse."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21283,7 +21332,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 +22073,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 +22086,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 +22117,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."
@@ -22100,7 +22159,7 @@ msgstr "Reise"
msgid "Rotation Degrees"
msgstr "Roterer %s grader."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstant"
@@ -24145,6 +24204,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Nullstill Transformasjon"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25366,6 +25430,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 +25838,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..aaa0f38a1d 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
@@ -542,6 +547,10 @@ msgid "Pressure"
msgstr "Voorinstellingen"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Relatief kleven"
@@ -2261,14 +2270,15 @@ msgstr "Favorieten:"
msgid "Recent:"
msgstr "Onlangs:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Zoeken:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Overeenkomsten:"
@@ -2328,8 +2338,8 @@ msgstr "Bronvervanging zoeken:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2906,7 +2916,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Knooppad kopiëren"
#: editor/editor_export.cpp
@@ -5714,6 +5724,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -12054,6 +12073,11 @@ msgid "New Animation"
msgstr "Nieuwe animatie"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filter methoden"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Snelheid:"
@@ -19143,6 +19167,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 +19180,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 +19233,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 +19482,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 +19490,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 +19502,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
@@ -20887,15 +20936,15 @@ msgstr "Kon template niet openen voor export:"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Ongeldige extentie."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20919,15 +20968,15 @@ msgstr "Ongeldige naam."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Ongeldige extentie."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21172,7 +21221,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 +21993,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 +22006,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 +22038,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 ""
@@ -22024,7 +22083,7 @@ msgstr "Verplaats"
msgid "Rotation Degrees"
msgstr "Roteren %s graden."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Constante"
@@ -24139,6 +24198,11 @@ msgstr ""
"Verander in plaats daarvan de grootte van de onderliggende botsingsvormen."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Houd Globale Transformatie"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25395,6 +25459,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 +25870,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 +25878,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..3e4664c317 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -61,13 +61,15 @@
# 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.
+# kingofsponges <q.patex.q@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-05-30 16:17+0000\n"
-"Last-Translator: DK0492 <doriankaczmarek28@gmail.com>\n"
+"PO-Revision-Date: 2022-08-04 06:38+0000\n"
+"Last-Translator: kingofsponges <q.patex.q@gmail.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/"
"godot/pl/>\n"
"Language: pl\n"
@@ -76,7 +78,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.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -269,7 +271,7 @@ msgstr "Sieć"
#: core/io/file_access_network.cpp
msgid "Remote FS"
-msgstr "Zdalny System Plików"
+msgstr "Zdalny System Plików"
#: core/io/file_access_network.cpp
msgid "Page Size"
@@ -337,7 +339,7 @@ msgstr "Członek transmisji"
#: core/io/stream_peer.cpp
msgid "Big Endian"
-msgstr ""
+msgstr "Big endian"
#: core/io/stream_peer.cpp
msgid "Data Array"
@@ -367,9 +369,8 @@ msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "Niewystarczająca ilość bajtów dla bajtów dekodujących lub zły format."
#: core/math/expression.cpp
-#, fuzzy
msgid "Invalid input %d (not passed) in expression"
-msgstr "Niewłaściwe dane %i (nie przekazane) w wyrażeniu"
+msgstr "Niewłaściwe dane %d (nie przekazane) w wyrażeniu"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
@@ -414,14 +415,12 @@ msgid "Max Size (KB)"
msgstr "Maks. rozmiar (KB)"
#: core/os/input.cpp
-#, fuzzy
msgid "Mouse Mode"
-msgstr "Tryb przesuwania"
+msgstr "Tryb myszki"
#: core/os/input.cpp
-#, fuzzy
msgid "Use Accumulated Input"
-msgstr "Usuń Wejście"
+msgstr "Użyj skumulowanego wejścia"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
@@ -448,6 +447,10 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+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
@@ -496,11 +499,15 @@ msgstr "Pochylenie"
#: core/os/input_event.cpp
msgid "Pressure"
-msgstr "Ciśnienie"
+msgstr "Nacisk"
+
+#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr "Odwrócone pióro"
#: core/os/input_event.cpp
msgid "Relative"
-msgstr "Relatywny"
+msgstr "Względny"
#: core/os/input_event.cpp scene/2d/camera_2d.cpp scene/2d/cpu_particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/interpolated_camera.cpp
@@ -635,9 +642,8 @@ msgstr "Własna nazwa katalogu użytkownika"
#: core/project_settings.cpp main/main.cpp
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
#: platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Display"
-msgstr "Pokaż wszystko"
+msgstr "Wyświetlanie"
#: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp
#: modules/opensimplex/noise_texture.cpp scene/2d/line_2d.cpp
@@ -651,23 +657,20 @@ msgstr "Szerokość"
#: scene/resources/capsule_shape_2d.cpp scene/resources/cylinder_shape.cpp
#: scene/resources/font.cpp scene/resources/navigation_mesh.cpp
#: scene/resources/primitive_meshes.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Height"
-msgstr "Światło"
+msgstr "Wysokość"
#: core/project_settings.cpp
msgid "Always On Top"
msgstr "Zawsze na wierzchu"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Width"
-msgstr "RozciÄ…gnij po lewej"
+msgstr "Szerokość testowa"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Height"
-msgstr "Testowanie"
+msgstr "Wysokość testowa"
#: core/project_settings.cpp editor/animation_track_editor.cpp
#: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp
@@ -690,9 +693,8 @@ msgid "Main Run Args"
msgstr "Główne argumenty włączania"
#: core/project_settings.cpp
-#, fuzzy
msgid "Scene Naming"
-msgstr "Ścieżka sceny:"
+msgstr "Nazywanie scen"
#: core/project_settings.cpp
msgid "Search In File Extensions"
@@ -703,20 +705,17 @@ msgid "Script Templates Search Path"
msgstr "Ścieżka wyszukiwania szablonów skryptów"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Autoload On Startup"
-msgstr "Automatyczne ładowanie podczas uruchamiania"
+msgstr "Automatyczne ładowanie kontroli wersji podczas uruchamiania"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Plugin Name"
-msgstr "Kontrola wersji"
+msgstr "Nazwa wtyczki kontroli 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"
@@ -1196,7 +1195,7 @@ msgstr "Ilośc:"
#: editor/animation_track_editor.cpp main/main.cpp
#: modules/mono/mono_gd/gd_mono.cpp
msgid "Args"
-msgstr ""
+msgstr "Argumenty"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp
@@ -1220,7 +1219,7 @@ msgstr "Ustaw uchwyt"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
msgid "Stream"
-msgstr ""
+msgstr "Strumień"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -2168,14 +2167,15 @@ msgstr "Ulubione:"
msgid "Recent:"
msgstr "Ostatnie:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Szukaj:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "PasujÄ…ce:"
@@ -2235,8 +2235,8 @@ msgstr "Szukaj zastępczego zasobu:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2245,7 +2245,7 @@ msgstr "Otwórz"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "Właściciele: %s (Suma: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2805,11 +2805,11 @@ msgstr "Wybierz"
#: editor/editor_export.cpp
msgid "Project export for platform:"
-msgstr ""
+msgstr "Eksportowanie projektu dla platformy:"
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Skopiuj ścieżkę węzła"
#: editor/editor_export.cpp
@@ -2835,14 +2835,12 @@ msgid "Packing"
msgstr "Pakowanie"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Save PCK"
-msgstr "Zapisz jako"
+msgstr "Zapisz plik PCK"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Cannot create file \"%s\"."
-msgstr "Nie można utworzyć katalogu."
+msgstr "Nie można utworzyć pliku \"%s\"."
#: editor/editor_export.cpp
#, fuzzy
@@ -5500,7 +5498,7 @@ msgstr "Miniatura..."
#: editor/editor_settings.cpp
msgid "Docks"
-msgstr ""
+msgstr "Doki"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5616,6 +5614,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "WyglÄ…d"
@@ -7113,7 +7120,7 @@ msgstr ""
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
msgid "sRGB"
-msgstr ""
+msgstr "sRGB"
#: editor/import/resource_importer_layered_texture.cpp
#, fuzzy
@@ -7431,7 +7438,7 @@ msgstr ""
#: scene/2d/mesh_instance_2d.cpp scene/2d/multimesh_instance_2d.cpp
#: scene/2d/particles_2d.cpp scene/2d/sprite.cpp scene/resources/style_box.cpp
msgid "Normal Map"
-msgstr ""
+msgstr "Mapa normalnych"
#: editor/import/resource_importer_texture.cpp
#, fuzzy
@@ -9841,7 +9848,7 @@ msgstr "Utwórz obrys"
#: scene/resources/multimesh.cpp scene/resources/primitive_meshes.cpp
#: scene/resources/texture.cpp
msgid "Mesh"
-msgstr "Siatka"
+msgstr "Mesh"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Trimesh Static Body"
@@ -11889,6 +11896,11 @@ msgid "New Animation"
msgstr "Nowa animacja"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filtruj metody"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Szybkość:"
@@ -17085,9 +17097,8 @@ msgstr "GDNative"
#: modules/gdscript/editor/gdscript_highlighter.cpp
#: modules/gdscript/gdscript.cpp
-#, fuzzy
msgid "GDScript"
-msgstr "Skrypt"
+msgstr "GDScript"
#: modules/gdscript/editor/gdscript_highlighter.cpp
msgid "Function Definition Color"
@@ -18857,6 +18868,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 +18881,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 +18934,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 +19182,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 +19201,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
@@ -19264,9 +19305,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension."
msgstr "Nieprawidłowa nazwa pliku! APK Androida wymaga rozszerzenia *.apk."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Unsupported export format!"
-msgstr "Nieobsługiwany format eksportu!\n"
+msgstr "Nieobsługiwany format eksportu!"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19296,9 +19336,8 @@ msgstr ""
"projektu"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
-msgstr "Nie udało się eksportować plików projektu do projektu gradle\n"
+msgstr "Nie udało się eksportować plików projektu do projektu gradle."
#: platform/android/export/export_plugin.cpp
msgid "Could not write expansion package file!"
@@ -20227,9 +20266,8 @@ msgid "ZIP Creation"
msgstr "Projekt"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not open file to read from path \"%s\"."
-msgstr "Nie udało się eksportować plików projektu do projektu gradle\n"
+msgstr "Nie udało się otworzyć pliku do odczytu ze ścieżki \"%s\"."
#: platform/osx/export/export.cpp
msgid "Invalid bundle identifier:"
@@ -20649,17 +20687,17 @@ msgstr "Nie udało się znaleźć keystore, nie można eksportować."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
"Narzędzie rcedit musi być skonfigurowane w Ustawieniach edytora (Eksport > "
"Windows > Rcedit), aby zmienić ikonę lub dane informacji o aplikacji."
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Niepoprawny plik wykonywalny."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20684,17 +20722,17 @@ msgstr "Niewłaściwa nazwa."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
"Narzędzie rcedit musi być skonfigurowane w Ustawieniach edytora (Eksport > "
"Windows > Rcedit), aby zmienić ikonę lub dane informacji o aplikacji."
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Niepoprawny plik wykonywalny."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20938,7 +20976,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
@@ -21215,26 +21253,23 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp scene/main/timer.cpp
-#, fuzzy
msgid "One Shot"
-msgstr "Jednorazowy Węzeł"
+msgstr "Wyemituj raz"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Preprocess"
-msgstr "Przetwarzanie końcowe"
+msgstr "Przetwarzanie wstępne"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Explosiveness"
-msgstr ""
+msgstr "Wybuchowość"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Randomness"
-msgstr "Losowy restart (s):"
+msgstr "Losowość"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21717,6 +21752,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 +21765,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 +21797,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 ""
@@ -21799,7 +21844,7 @@ msgstr "Przejdź"
msgid "Rotation Degrees"
msgstr "Obracanie o %s stopni."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Stała globalna"
@@ -21913,9 +21958,8 @@ msgstr ""
"\"Particles Animation\"."
#: scene/2d/particles_2d.cpp
-#, fuzzy
msgid "Visibility Rect"
-msgstr "Tryb priorytetów"
+msgstr "Prostokąt widoczności"
#: scene/2d/particles_2d.cpp scene/3d/particles.cpp
msgid "Process Material"
@@ -23582,9 +23626,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"
@@ -23951,6 +23994,11 @@ msgstr ""
"Zamiast tego, zmień rozmiary kształtów kolizji w węzłach podrzędnych."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Zachowaj globalnÄ… transformacjÄ™"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24867,7 +24915,7 @@ msgstr ""
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Caret"
-msgstr ""
+msgstr "Karetka"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink"
@@ -25209,6 +25257,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 +25598,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 +25672,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 +25679,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 +26779,7 @@ msgstr "Warunek"
#: scene/resources/environment.cpp
msgid "Fog"
-msgstr ""
+msgstr "Mgła"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26912,9 +26961,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..4c073f8542 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
@@ -465,6 +470,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2156,14 +2165,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2219,8 +2229,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2789,7 +2799,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Forge yer Node!"
#: editor/editor_export.cpp
@@ -5460,6 +5470,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11691,6 +11710,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Paste yer Node"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18559,6 +18583,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 +18596,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 +18645,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 +18878,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 +18892,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
@@ -20214,15 +20263,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Yer Calligraphy be wrongly sized."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20244,15 +20293,15 @@ msgstr "Yer Calligraphy be wrongly sized."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Yer Calligraphy be wrongly sized."
#: platform/windows/export/export.cpp
msgid "Failed to remove temporary file \"%s\"."
@@ -20478,7 +20527,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 +21233,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 +21246,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 ""
@@ -21255,7 +21314,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Rename Variable"
@@ -23204,6 +23263,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Change yer Anim Transform"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24349,6 +24413,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 +24800,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..f284e0ece8 100644
--- a/editor/translations/pt.po
+++ b/editor/translations/pt.po
@@ -24,13 +24,15 @@
# Renu <ifpilucas@gmail.com>, 2022.
# El_ExpertPlayer <xpertnathan37@gmail.com>, 2022.
# Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>, 2022.
+# Ednaldo Pereira Confia <filat51823@storypo.com>, 2022.
+# Zé Beato Página Oficial <zebeato@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: Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>\n"
+"PO-Revision-Date: 2022-07-23 03:57+0000\n"
+"Last-Translator: Zé Beato Página Oficial <zebeato@gmail.com>\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/godot-engine/"
"godot/pt/>\n"
"Language: pt\n"
@@ -38,7 +40,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -407,6 +409,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
@@ -458,6 +465,10 @@ msgid "Pressure"
msgstr "Pressione"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relativo"
@@ -2099,14 +2110,15 @@ msgstr "Favoritos:"
msgid "Recent:"
msgstr "Recente:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Procurar:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Correspondências:"
@@ -2166,8 +2178,8 @@ msgstr "Procurar Recurso de substituição:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2288,7 +2300,6 @@ msgstr "Desenvolvedor-chefe"
#. TRANSLATORS: This refers to a job title.
#: editor/editor_about.cpp
-#, fuzzy
msgctxt "Job Title"
msgid "Project Manager"
msgstr "Gestor de Projetos"
@@ -2535,9 +2546,8 @@ msgid "There is no '%s' file."
msgstr "Não existe ficheiro '%s'."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Layout:"
-msgstr "Esquema"
+msgstr "Esquema:"
#: editor/editor_audio_buses.cpp
msgid "Invalid file, not an audio bus layout."
@@ -2586,9 +2596,8 @@ msgid "Create a new Bus Layout."
msgstr "Criar um novo Modelo de Barramento."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Audio Bus Layout"
-msgstr "Abrir Modelo de barramento de áudio"
+msgstr "Modelo de barramento de áudio"
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -2746,17 +2755,16 @@ msgstr "Exportação do projeto para plataforma:"
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
-msgstr "Copiar Caminho do Nó"
+msgid "Completed with warnings."
+msgstr "Concluído com erros."
#: editor/editor_export.cpp
msgid "Completed successfully."
-msgstr "Completado com sucesso."
+msgstr "Concluído com sucesso."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed."
-msgstr "Falhou:"
+msgstr "Falhou."
#: editor/editor_export.cpp
msgid "Storing File:"
@@ -2926,9 +2934,8 @@ msgid "The given export path doesn't exist."
msgstr "O caminho de exportação não existe:"
#: editor/editor_export.cpp platform/javascript/export/export.cpp
-#, fuzzy
msgid "Template file not found: \"%s\"."
-msgstr "Ficheiro Modelo não encontrado:"
+msgstr "Ficheiro Modelo não encontrado"
#: editor/editor_export.cpp
#, fuzzy
@@ -5528,6 +5535,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Aparência"
@@ -11711,6 +11727,11 @@ msgid "New Animation"
msgstr "Nova Animação"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Métodos de filtro"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Velocidade:"
@@ -18620,6 +18641,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 +18654,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 +18707,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 +18962,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 +18980,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 ""
+"\"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 ""
"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\"."
@@ -20358,15 +20409,15 @@ msgstr "Incapaz de encontrar keystore e exportar."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Extensão inválida."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20390,15 +20441,15 @@ msgstr "Nome inválido."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Extensão inválida."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20640,7 +20691,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 +21463,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 +21476,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 +21508,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 ""
@@ -21493,7 +21554,7 @@ msgstr "Viagem"
msgid "Rotation Degrees"
msgstr "Graus de Rotação"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Constante Global"
@@ -23631,6 +23692,11 @@ msgstr ""
"Em vez disso, mude o tamanho das formas de colisão filhas."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Manter Transformação Global"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24886,6 +24952,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 +25369,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 +25376,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..84a5ac45c3 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -127,7 +127,7 @@
# Mário Victor Ribeiro Silva <mariovictorrs@gmail.com>, 2021.
# jak3z <jose_renato06@outlook.com>, 2021.
# Henrique Darko <henridark00@gmail.com>, 2021.
-# Cearaj <pmoraisleal@gmail.com>, 2021.
+# Cearaj <pmoraisleal@gmail.com>, 2021, 2022.
# Alefy San <alefyferreiradeoliveira@outlook.com>, 2021.
# Joel Gomes da Silva <joelgomes1994@hotmail.com>, 2021, 2022.
# Orangotango De tanga <luizinho0045@gmail.com>, 2021.
@@ -141,13 +141,16 @@
# José Miranda Neto <dodimi95@gmail.com>, 2022.
# lucas rossy brasil coelho <lucasrossy270@gmail.com>, 2022.
# Kaycke <kaycke@ymail.com>, 2022.
+# Ednaldo Pereira Confia <filat51823@storypo.com>, 2022.
+# Mauricio <mauricio.fidalgo1@gmail.com>, 2022.
+# Felipe Kinoshita <kinofhek@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: 2016-05-30\n"
-"PO-Revision-Date: 2022-06-29 10:04+0000\n"
-"Last-Translator: Douglas Leão <djlsplays@gmail.com>\n"
+"PO-Revision-Date: 2022-08-04 06:38+0000\n"
+"Last-Translator: Felipe Kinoshita <kinofhek@gmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_BR/>\n"
"Language: pt_BR\n"
@@ -155,7 +158,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -360,7 +363,7 @@ msgstr "Página lida adiante"
#: core/io/http_client.cpp
msgid "Blocking Mode Enabled"
-msgstr "Modo de bloqueio ativado"
+msgstr "Modo de Bloqueio Ativado"
#: core/io/http_client.cpp
msgid "Connection"
@@ -523,6 +526,10 @@ msgstr "Meta"
msgid "Command"
msgstr "Comando"
+#: core/os/input_event.cpp
+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
@@ -574,6 +581,10 @@ msgid "Pressure"
msgstr "Pressão"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr "Caneta Invertida (\"Borracha\")"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relativo"
@@ -710,7 +721,6 @@ msgstr "Nome do Diretório de Usuário Personalizado"
#: core/project_settings.cpp main/main.cpp
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
#: platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Display"
msgstr "Exibição"
@@ -734,14 +744,12 @@ msgid "Always On Top"
msgstr "Sempre no topo"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Width"
msgstr "Largura de teste"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Height"
-msgstr "Teste de altura"
+msgstr "Altura de teste"
#: core/project_settings.cpp editor/animation_track_editor.cpp
#: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp
@@ -776,9 +784,8 @@ msgid "Script Templates Search Path"
msgstr "Caminho de Pesquisa de Modelos de Script"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Autoload On Startup"
-msgstr "Carregamento Automático na Inicialização"
+msgstr "Carregamento Automático do Controle de Versão na Inicialização"
#: core/project_settings.cpp
msgid "Version Control Plugin Name"
@@ -1086,9 +1093,8 @@ msgstr "Encaixe inteligente"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
-#, fuzzy
msgid "Use GPU Pixel Snap"
-msgstr "Usar Encaixe de Pixel"
+msgstr "Usar Encaixe de Pixels da GPU"
#: drivers/gles2/rasterizer_scene_gles2.cpp
#: drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1115,7 +1121,7 @@ msgstr "Máximo de luzes renderizáveis"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Renderable Reflections"
-msgstr "Reflexões máximas renderizáveis"
+msgstr "Máximo de Reflexões Renderizáveis"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Lights Per Object"
@@ -1273,14 +1279,12 @@ msgid "Type"
msgstr "Tipo"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In Handle"
-msgstr "Definir Manipulador"
+msgstr "Manipulador de Entrada"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out Handle"
-msgstr "Definir Manipulador"
+msgstr "Manipulador de Saída"
#: editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
@@ -1291,11 +1295,11 @@ msgstr "Fluxo"
#: editor/animation_track_editor.cpp
msgid "Start Offset"
-msgstr "Iniciar deslocamento"
+msgstr "Deslocamento Inicial"
#: editor/animation_track_editor.cpp
msgid "End Offset"
-msgstr "Terminar deslocamento"
+msgstr "Deslocamento Final"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/import/resource_importer_scene.cpp
@@ -1308,9 +1312,8 @@ msgid "Animation"
msgstr "Animação"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing"
-msgstr "Facilitar Entrada-Saída"
+msgstr "Suavização"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
@@ -1445,32 +1448,28 @@ msgid "Type:"
msgstr "Tipo:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "(Invalid, expected type: %s)"
-msgstr "Template de exportação inválido:"
+msgstr "(Inválido, tipo esperado: %s)"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing:"
-msgstr "Facilitar Entrada-Saída"
+msgstr "Suavizar:"
#: editor/animation_track_editor.cpp
msgid "In-Handle:"
-msgstr "Definir Manipulador:"
+msgstr "Manipulador de Entrada:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out-Handle:"
-msgstr "Definir Manipulador:"
+msgstr "Manipulador de Saída:"
#: editor/animation_track_editor.cpp
msgid "Stream:"
msgstr "Transmissão:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start (s):"
-msgstr "Início(s):"
+msgstr "Início (s):"
#: editor/animation_track_editor.cpp
msgid "End (s):"
@@ -1566,9 +1565,8 @@ msgid "Editors"
msgstr "Editores"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Confirm Insert Track"
-msgstr "Inserir Trilha e Chave na Anim"
+msgstr "Confirmar Inserção de Trilha"
#. TRANSLATORS: %s will be replaced by a phrase describing the target of track.
#: editor/animation_track_editor.cpp
@@ -2109,7 +2107,7 @@ msgstr ""
#: editor/connections_dialog.cpp scene/resources/texture.cpp
msgid "Oneshot"
-msgstr "Oneshot"
+msgstr "Só Uma Vez"
#: editor/connections_dialog.cpp
msgid "Disconnects the signal after its first emission."
@@ -2228,14 +2226,15 @@ msgstr "Favoritos:"
msgid "Recent:"
msgstr "Recente:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Pesquisar:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Correspondências:"
@@ -2295,8 +2294,8 @@ msgstr "Buscar Recurso para Substituição:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2419,7 +2418,7 @@ msgstr "Desenvolvedor-chefe"
#: editor/editor_about.cpp
msgctxt "Job Title"
msgid "Project Manager"
-msgstr "Gerenciador de Projeto"
+msgstr "Gestor de Projeto"
#: editor/editor_about.cpp
msgid "Developers"
@@ -2662,9 +2661,8 @@ msgid "There is no '%s' file."
msgstr "Não existe o arquivo '%s'."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Layout:"
-msgstr "Layout"
+msgstr "Layout:"
#: editor/editor_audio_buses.cpp
msgid "Invalid file, not an audio bus layout."
@@ -2713,9 +2711,8 @@ msgid "Create a new Bus Layout."
msgstr "Criar um novo Layout de Canais."
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Audio Bus Layout"
-msgstr "Abrir Layout de Canais de Ãudio"
+msgstr "Layout de Canais de Ãudio"
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -2871,7 +2868,8 @@ msgid "Project export for platform:"
msgstr "Exportação do projeto para plataforma:"
#: editor/editor_export.cpp
-msgid "Completed with errors."
+#, fuzzy
+msgid "Completed with warnings."
msgstr "Concluído com erros."
#: editor/editor_export.cpp
@@ -2895,14 +2893,12 @@ msgid "Packing"
msgstr "Empacotando"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Save PCK"
-msgstr "Salvar Como"
+msgstr "Salvar PCK"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Cannot create file \"%s\"."
-msgstr "Não foi possível criar a pasta."
+msgstr "Não foi possível criar arquivo \"%s\"."
#: editor/editor_export.cpp
msgid "Failed to export project files."
@@ -2913,9 +2909,8 @@ msgid "Can't open file to read from path \"%s\"."
msgstr "Não é possível abrir arquivo para leitura a partir do caminho \"%s\"."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Save ZIP"
-msgstr "Salvar Como"
+msgstr "Salvar ZIP"
#: editor/editor_export.cpp
msgid ""
@@ -2997,12 +2992,11 @@ msgstr "64 Bits"
#: editor/editor_export.cpp
msgid "Embed PCK"
-msgstr "Incorporar PCK"
+msgstr "PCK Incorporado"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Texture Format"
-msgstr "Região da Textura"
+msgstr "Formato da Textura"
#: editor/editor_export.cpp
msgid "BPTC"
@@ -3021,9 +3015,8 @@ msgid "ETC2"
msgstr "ETC2"
#: editor/editor_export.cpp
-#, fuzzy
msgid "No BPTC Fallbacks"
-msgstr "Forçar Fallbacks do Shader"
+msgstr "Sem Fallbacks para imagens BPTC"
#: editor/editor_export.cpp platform/android/export/export_plugin.cpp
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
@@ -3035,12 +3028,11 @@ msgstr "Modelo customizado de depuração não encontrado."
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
msgid "Custom release template not found."
-msgstr "Template customizado de release não encontrado."
+msgstr "Modelo customizado de lançamento não encontrado."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Prepare Template"
-msgstr "Gerenciar Templates"
+msgstr "Preparar Modelo"
#: editor/editor_export.cpp platform/osx/export/export.cpp
msgid "The given export path doesn't exist."
@@ -3056,9 +3048,8 @@ msgstr "Falha ao copiar o modelo de exportação."
#: editor/editor_export.cpp platform/windows/export/export.cpp
#: platform/x11/export/export.cpp
-#, fuzzy
msgid "PCK Embedding"
-msgstr "Preenchimento"
+msgstr "Incorporação de PCK"
#: editor/editor_export.cpp
msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
@@ -3273,9 +3264,8 @@ msgid "Manage Editor Feature Profiles"
msgstr "Gerenciar perfis de recurso do editor"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Default Feature Profile"
-msgstr "Perfil de funcionalidade do Godot"
+msgstr "Perfil de funcionalidade Padrão"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Select Current Folder"
@@ -3681,9 +3671,8 @@ msgid "Property:"
msgstr "Propriedade:"
#: editor/editor_inspector.cpp editor/editor_spin_slider.cpp
-#, fuzzy
msgid "Label"
-msgstr "Valor"
+msgstr "Rótulo"
#: editor/editor_inspector.cpp editor/editor_spin_slider.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -4067,18 +4056,16 @@ msgid "Quick Open Script..."
msgstr "Abrir Script Rapidamente..."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Reload"
-msgstr "Salvar e Reiniciar"
+msgstr "Salvar & Recarregar"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save changes to '%s' before reloading?"
-msgstr "Salvar alterações em '%s' antes de fechar?"
+msgstr "Salvar alterações em '%s' antes de recarregar?"
#: editor/editor_node.cpp
msgid "Save & Close"
-msgstr "Salvar e Fechar"
+msgstr "Salvar & Fechar"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
@@ -4193,9 +4180,8 @@ msgid "Open Project Manager?"
msgstr "Abrir Gerenciador de Projetos?"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save changes to the following scene(s) before reloading?"
-msgstr "Salvar alterações na(s) seguinte(s) cena(s) antes de sair?"
+msgstr "Salvar alterações na(s) seguinte(s) cena(s) antes de recarregar?"
#: editor/editor_node.cpp
msgid "Save & Quit"
@@ -4401,13 +4387,12 @@ msgid "Scene Tabs"
msgstr "Abas de Cena"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Always Show Close Button"
-msgstr "Sempre Mostrar Grade"
+msgstr "Sempre Exibir o Botão de Fechar"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Resize If Many Tabs"
-msgstr "Redimensionar se houver muitas guias"
+msgstr "Redimensionar se Houver Muitas Guias"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Minimum Width"
@@ -4418,9 +4403,8 @@ msgid "Output"
msgstr "Saída"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Always Clear Output On Play"
-msgstr "Limpar Saída"
+msgstr "Sempre limpar saída ao jogar"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Open Output On Play"
@@ -4435,19 +4419,16 @@ msgid "Save On Focus Loss"
msgstr "Salvar em caso de perda de foco"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Save Each Scene On Quit"
-msgstr "Salvar Ramo como Cena"
+msgstr "Salvar cada cena ao sair"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Quit Confirmation"
-msgstr "Visualizar Informações"
+msgstr "Confirmação de saída"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Show Update Spinner"
-msgstr "Ocultar Spinner de Atualização"
+msgstr "Mostrar Spinner de Atualização"
#: editor/editor_node.cpp
msgid "Update Continuously"
@@ -4474,18 +4455,16 @@ msgid "Inspector"
msgstr "Inspetor"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Default Property Name Style"
-msgstr "Caminho Padrão do Projeto"
+msgstr "Estilo de Nome de Propriedade Padrão"
#: editor/editor_node.cpp
msgid "Default Float Step"
msgstr "Passo de ponto flutuante padrão"
#: editor/editor_node.cpp scene/gui/tree.cpp
-#, fuzzy
msgid "Disable Folding"
-msgstr "Botão Desativado"
+msgstr "Desativar Dobragem"
#: editor/editor_node.cpp
msgid "Auto Unfold Foreign Scenes"
@@ -4497,21 +4476,19 @@ msgstr "Edição Horizontal do Vector2"
#: editor/editor_node.cpp
msgid "Horizontal Vector Types Editing"
-msgstr ""
+msgstr "Edição Horizontal de Tipos de Vetor"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Resources In Current Inspector"
-msgstr "Abrir no inspetor"
+msgstr "Abrir Recursos no Inspetor Atual"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Resources To Open In New Inspector"
-msgstr "Abrir no inspetor"
+msgstr "Recursos para abrir em Novo Inspetor"
#: editor/editor_node.cpp
msgid "Default Color Picker Mode"
-msgstr ""
+msgstr "Modo de Seletor de Cores Padrão"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Version Control"
@@ -5122,7 +5099,7 @@ msgstr "Tempo Médio (ms)"
#: editor/editor_profiler.cpp
msgid "Frame %"
-msgstr "Frame %"
+msgstr "Quadro %"
#: editor/editor_profiler.cpp
msgid "Physics Frame %"
@@ -5167,12 +5144,11 @@ msgstr "Depurador"
#: editor/editor_profiler.cpp
msgid "Profiler Frame History Size"
-msgstr ""
+msgstr "Tamanho de histórico disponível no \"Profiler\""
#: editor/editor_profiler.cpp
-#, fuzzy
msgid "Profiler Frame Max Functions"
-msgstr "Renomear Função"
+msgstr "Máximo de funções por quadro no \"Profiler\""
#: editor/editor_properties.cpp
msgid "Edit Text:"
@@ -5305,20 +5281,17 @@ msgstr "Novo %s"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Base Type"
-msgstr "Mudar Tipo Base"
+msgstr "Tipo Base"
#: editor/editor_resource_picker.cpp
-#, fuzzy
msgid "Edited Resource"
-msgstr "Adicionar Recurso"
+msgstr "Recurso Editado"
#: editor/editor_resource_picker.cpp scene/gui/line_edit.cpp
#: scene/gui/slider.cpp scene/gui/spin_box.cpp
-#, fuzzy
msgid "Editable"
-msgstr "Item Editável"
+msgstr "Editável"
#: editor/editor_resource_picker.cpp editor/property_editor.cpp
msgid "New Script"
@@ -5344,9 +5317,8 @@ msgstr ""
"predefinição existente como executável."
#: editor/editor_run_native.cpp
-#, fuzzy
msgid "Project Run"
-msgstr "Projeto"
+msgstr "Executar Projeto"
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -5373,73 +5345,68 @@ msgid "Did you forget the '_run' method?"
msgstr "Você esqueceu o método '_run'?"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Editor Language"
-msgstr "Layout do Editor"
+msgstr "Linguagem do Editor"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Display Scale"
-msgstr "Exibir Tudo"
+msgstr "Escala de Exibição"
#: editor/editor_settings.cpp
msgid "Custom Display Scale"
-msgstr ""
+msgstr "Escala de Exibição Customizada"
#: editor/editor_settings.cpp
msgid "Main Font Size"
-msgstr ""
+msgstr "Tamanho de Fonte Principal"
#: editor/editor_settings.cpp
msgid "Code Font Size"
-msgstr ""
+msgstr "Tamanho de Fonte (Tipo) no Código"
#: editor/editor_settings.cpp
msgid "Font Antialiased"
-msgstr ""
+msgstr "Fonte Com Serrilhado Suavizado"
#: editor/editor_settings.cpp
msgid "Font Hinting"
-msgstr ""
+msgstr "Suavização de Fonte"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Main Font"
-msgstr "Cena Principal"
+msgstr "Fonte Principal"
#: editor/editor_settings.cpp
msgid "Main Font Bold"
-msgstr ""
+msgstr "Fonte Principal (Negrito)"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Code Font"
-msgstr "Adicionar Ponto de Nó"
+msgstr "Fonte para Código"
#: editor/editor_settings.cpp
msgid "Dim Editor On Dialog Popup"
-msgstr ""
+msgstr "Escurecer o Editor ao Abir Janela Popup"
#: editor/editor_settings.cpp main/main.cpp
msgid "Low Processor Mode Sleep (µsec)"
-msgstr ""
+msgstr "Tempo de Espera em Modo de Hibernação (µseg)"
#: editor/editor_settings.cpp
msgid "Unfocused Low Processor Mode Sleep (µsec)"
-msgstr ""
+msgstr "Tempo de Espera em Modo de Hibernação Quando Fora de Foco (µseg)"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Separate Distraction Mode"
-msgstr "Modo Sem Distrações"
+msgstr "Modo \"Sem Distrações\" Desacoplado"
#: editor/editor_settings.cpp
msgid "Automatically Open Screenshots"
-msgstr ""
+msgstr "Abrir Capturas de Tela Automaticamente"
#: editor/editor_settings.cpp
msgid "Max Array Dictionary Items Per Page"
-msgstr ""
+msgstr "Máximo de Itens em Arrays Dicionários Por Página"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp
@@ -5453,59 +5420,51 @@ msgstr "Predefinição"
#: editor/editor_settings.cpp
msgid "Icon And Font Color"
-msgstr ""
+msgstr "Cor da Fonte e do Ãcone"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Color"
-msgstr "Cores"
+msgstr "Cor Base"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Accent Color"
-msgstr "Escolher Cor"
+msgstr "Cor de Destaque"
#: editor/editor_settings.cpp scene/resources/environment.cpp
msgid "Contrast"
-msgstr ""
+msgstr "Contraste"
#: editor/editor_settings.cpp
msgid "Relationship Line Opacity"
-msgstr ""
+msgstr "Opacidade da Linha de Relacionamento"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Highlight Tabs"
-msgstr "Salvando mapas de luz"
+msgstr "Abas de Destaque"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Border Size"
-msgstr "Pixels de Borda"
+msgstr "Tamanho da Borda"
#: editor/editor_settings.cpp
msgid "Use Graph Node Headers"
-msgstr ""
+msgstr "Utilizar Cabeçalhos de Nós para Gráficos"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Additional Spacing"
-msgstr "Loop da Animação"
+msgstr "Espaçamento Adicional"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Custom Theme"
-msgstr "Tema do Editor"
+msgstr "Tema Personalizado"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Script Button"
-msgstr "Botão direito da roda"
+msgstr "Botão de Exibir Script"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Directories"
-msgstr "Direções"
+msgstr "Diretórios"
#: editor/editor_settings.cpp
msgid "Autoscan Project Path"
@@ -5516,23 +5475,20 @@ msgid "Default Project Path"
msgstr "Caminho Padrão do Projeto"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "On Save"
-msgstr "Salvar"
+msgstr "Ao Salvar"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Compress Binary Resources"
-msgstr "Copiar Recurso"
+msgstr "Comprimir Recursos Binários"
#: editor/editor_settings.cpp
msgid "Safe Save On Backup Then Rename"
-msgstr ""
+msgstr "Salvar de Forma Segura Como Backup e Então Renomear"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "File Dialog"
-msgstr "Diálogo XForm"
+msgstr "Janela de Arquivo"
#: editor/editor_settings.cpp
msgid "Thumbnail Size"
@@ -5540,82 +5496,73 @@ msgstr "Tamanho da Miniatura"
#: editor/editor_settings.cpp
msgid "Docks"
-msgstr ""
+msgstr "Docks"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Scene Tree"
-msgstr "Edição da Ãrvore de Cena"
+msgstr "Ãrvore de Cena"
#: editor/editor_settings.cpp
msgid "Start Create Dialog Fully Expanded"
-msgstr ""
+msgstr "Iniciar Dialogo de Criação Expandido por Completo"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Always Show Folders"
-msgstr "Sempre Mostrar Grade"
+msgstr "Sempre Exibir Pastas"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Property Editor"
-msgstr "Editor de Grupos"
+msgstr "Editor de Propriedades"
#: editor/editor_settings.cpp
msgid "Auto Refresh Interval"
-msgstr ""
+msgstr "Intervalo de Atualização Automática"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Subresource Hue Tint"
-msgstr "Sub-Recursos"
+msgstr "Tom de Coloração para Sub-Recursos"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Color Theme"
-msgstr "Tema do Editor"
+msgstr "Tema de Cores"
#: editor/editor_settings.cpp scene/3d/label_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Line Spacing"
-msgstr ""
+msgstr "Espaçamento de Linha"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
#: modules/gdscript/editor/gdscript_highlighter.cpp
-#, fuzzy
msgid "Highlighting"
-msgstr "Iluminação direta"
+msgstr "Destacando"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Syntax Highlighting"
-msgstr "Realce de sintaxe"
+msgstr "Destaque de Sintaxe"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Highlight All Occurrences"
-msgstr ""
+msgstr "Destaque de Todas as Ocorrências"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Highlight Current Line"
-msgstr ""
+msgstr "Destaque da Linha Atual"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
msgid "Highlight Type Safe Lines"
-msgstr ""
+msgstr "Destaque de Linhas de Tipo Seguro"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Indent"
-msgstr "Recuar Esquerda"
+msgstr "Indentar"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
msgid "Auto Indent"
msgstr "Auto Recuar"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Convert Indent On Save"
-msgstr "Converter recuo para espaços"
+msgstr "Converter Indentação Ao Salvar"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Draw Tabs"
@@ -5634,139 +5581,139 @@ msgstr "Navegação"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Smooth Scrolling"
-msgstr ""
+msgstr "Rolagem Suave"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "V Scroll Speed"
-msgstr ""
+msgstr "Velocidade de Rolagem Vertical"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Minimap"
-msgstr "Mostrar Origem"
+msgstr "Exibir Mini-Mapa"
#: editor/editor_settings.cpp
msgid "Minimap Width"
-msgstr ""
+msgstr "Largura do Mini-Mapa"
#: editor/editor_settings.cpp
msgid "Mouse Extra Buttons Navigate History"
+msgstr "Botões Extra do Mouse Navegam o Histórico"
+
+#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr "Seleção Arrasta e Solta"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
msgstr ""
#: editor/editor_settings.cpp
msgid "Appearance"
-msgstr ""
+msgstr "Aparência"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Show Line Numbers"
msgstr "Mostrar Números de Linha"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Line Numbers Zero Padded"
-msgstr "Número da Linha:"
+msgstr "Número das Linha Tem Espaçamento Com Zeros"
#: editor/editor_settings.cpp
msgid "Show Bookmark Gutter"
-msgstr ""
+msgstr "Exibir Espaçamento de Bookmark"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Breakpoint Gutter"
-msgstr "Pular Breakpoints"
+msgstr "Exibir Espaçamento de Pontos de Quebra"
#: editor/editor_settings.cpp
msgid "Show Info Gutter"
-msgstr ""
+msgstr "Exibir Espaçamento de Informações"
#: editor/editor_settings.cpp
msgid "Code Folding"
-msgstr ""
+msgstr "Dobramento de Código (Folding)"
#: editor/editor_settings.cpp
msgid "Word Wrap"
-msgstr ""
+msgstr "Quebra de Linhas"
#: editor/editor_settings.cpp
msgid "Show Line Length Guidelines"
-msgstr ""
+msgstr "Exibir Guia de Tamanho de Linhas"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Soft Column"
-msgstr ""
+msgstr "Tamanho de Linha Guia em Coluna Suave"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Hard Column"
-msgstr ""
+msgstr "Tamanho de Linha Guia em Coluna Rígida"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Script List"
-msgstr "Editor de Script"
+msgstr "Lista de Scripts"
#: editor/editor_settings.cpp
msgid "Show Members Overview"
-msgstr ""
+msgstr "Exibir Visão Geral de Membros"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Files"
-msgstr "Arquivo"
+msgstr "Arquivos"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Trim Trailing Whitespace On Save"
-msgstr "Apagar Espaços em Branco"
+msgstr "Aparar Espaços em Branco de Fim de Linha ao Salvar"
#: editor/editor_settings.cpp
msgid "Autosave Interval Secs"
-msgstr ""
+msgstr "Intervalo de Salvamento Automático em Segundos"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
msgid "Restore Scripts On Load"
-msgstr ""
+msgstr "Restaurar Scripts ao Carregar"
#: editor/editor_settings.cpp
msgid "Auto Reload And Parse Scripts On Save"
-msgstr ""
+msgstr "Ao Salvar Recarregar e Reinterpretar Scripts Automaticamente"
#: editor/editor_settings.cpp
msgid "Auto Reload Scripts On External Change"
-msgstr ""
+msgstr "Recarregar Scripts Automaticamente em Alterações Externas"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Create Signal Callbacks"
-msgstr "Forçar Fallbacks do Shader"
+msgstr "Criar Sinal de Callback"
#: editor/editor_settings.cpp
msgid "Sort Members Outline Alphabetically"
-msgstr ""
+msgstr "Ordenar Prévia de Membros Automaticamente"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Cursor"
-msgstr ""
+msgstr "Cursor"
#: editor/editor_settings.cpp
msgid "Scroll Past End Of File"
-msgstr ""
+msgstr "Rolar Além do Fim do Arquivo"
#: editor/editor_settings.cpp
msgid "Block Caret"
-msgstr ""
+msgstr "Bloco Cursor"
#: editor/editor_settings.cpp
msgid "Caret Blink"
-msgstr ""
+msgstr "Piscar Cursor"
#: editor/editor_settings.cpp
msgid "Caret Blink Speed"
-msgstr ""
+msgstr "Velocidade de Piscar do Cursor"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Right Click Moves Caret"
-msgstr "Clique com o botão direito para adicionar o ponto"
+msgstr "Botão Direito Move o Cursor"
#: editor/editor_settings.cpp modules/gdscript/gdscript.cpp
#: modules/gdscript/gdscript_editor.cpp
@@ -5776,54 +5723,51 @@ msgstr "Conclusão"
#: editor/editor_settings.cpp
msgid "Idle Parse Delay"
-msgstr ""
+msgstr "Atraso Ocioso Para Interpretação"
#: editor/editor_settings.cpp
msgid "Auto Brace Complete"
-msgstr ""
+msgstr "Fechar Chaves Automaticamente"
#: editor/editor_settings.cpp
msgid "Code Complete Delay"
-msgstr ""
+msgstr "Atraso de Sugestão de Código"
#: editor/editor_settings.cpp
msgid "Put Callhint Tooltip Below Current Line"
-msgstr ""
+msgstr "Pôr Dica de Sugestão de Chamada na Linha Abaixo da Atual"
#: editor/editor_settings.cpp
msgid "Callhint Tooltip Offset"
-msgstr ""
+msgstr "Espaçamento de Dica de Sugestão de Chamada"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Complete File Paths"
-msgstr "Copiar Caminho do Nó"
+msgstr "Concluir Caminhos de Arquivo"
#: editor/editor_settings.cpp modules/gdscript/gdscript_editor.cpp
-#, fuzzy
msgid "Add Type Hints"
-msgstr "Adicionar Modelo"
+msgstr "Adicionar Dicas de Tipo"
#: editor/editor_settings.cpp
msgid "Use Single Quotes"
msgstr "Usar Aspas Simples"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Help Index"
-msgstr "Mostrar auxiliadores"
+msgstr "Exibir Ãndice de Ajuda"
#: editor/editor_settings.cpp
msgid "Help Font Size"
-msgstr ""
+msgstr "Tamanho da Fonte de Ajuda"
#: editor/editor_settings.cpp
msgid "Help Source Font Size"
-msgstr ""
+msgstr "Tamanho da Fonte de Ajuda Principal"
#: editor/editor_settings.cpp
msgid "Help Title Font Size"
-msgstr ""
+msgstr "Tamanho da Fonte de Ajuda para Títulos"
#: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp
msgid "Grid Map"
@@ -5834,45 +5778,39 @@ msgid "Pick Distance"
msgstr "Escolha a Distância"
#: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Preview Size"
-msgstr "Visualização"
+msgstr "Tamanho da Prévia"
#: editor/editor_settings.cpp
msgid "Primary Grid Color"
-msgstr ""
+msgstr "Cor Primária da Grade"
#: editor/editor_settings.cpp
msgid "Secondary Grid Color"
-msgstr ""
+msgstr "Cor Secundária da Grade"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Selection Box Color"
-msgstr "Selecionar Apenas"
+msgstr "Cor da Caixa de Seleção"
#: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
-#, fuzzy
msgid "3D Gizmos"
-msgstr "Gizmos"
+msgstr "Gizmos 3D"
#: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
-#, fuzzy
msgid "Gizmo Colors"
-msgstr "Cores de Emissão"
+msgstr "Cores do Gismo"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Instanced"
-msgstr "Instância"
+msgstr "Instanciado"
#: editor/editor_settings.cpp modules/gltf/gltf_node.cpp
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Joint"
-msgstr "Ponto"
+msgstr "Junção"
#: editor/editor_settings.cpp scene/2d/collision_shape_2d.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/touch_screen_button.cpp
@@ -5881,12 +5819,11 @@ msgstr "Ponto"
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
msgid "Shape"
-msgstr ""
+msgstr "Form"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Primary Grid Steps"
-msgstr "Passo de grade:"
+msgstr "Passadas para Grade Primária"
#: editor/editor_settings.cpp
msgid "Grid Size"
@@ -5894,183 +5831,155 @@ msgstr "Tamanho da Grade"
#: editor/editor_settings.cpp
msgid "Grid Division Level Max"
-msgstr ""
+msgstr "Nível Máximo de Divisão de Grade"
#: editor/editor_settings.cpp
msgid "Grid Division Level Min"
-msgstr ""
+msgstr "Nível Mínimo de Divisão da Grade"
#: editor/editor_settings.cpp
msgid "Grid Division Level Bias"
-msgstr ""
+msgstr "Tendência do Nível de Divisão da Grade"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid XZ Plane"
-msgstr "Pintura GridMap"
+msgstr "Grade do Plano XZ"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid XY Plane"
-msgstr "Pintura GridMap"
+msgstr "Grade do Plano XY"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid YZ Plane"
-msgstr "Pintura GridMap"
+msgstr "Grade do Plano YZ"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default FOV"
-msgstr "Padrão"
+msgstr "Campo de Visão (FOV) Padrão"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Z Near"
-msgstr "Tema Padrão"
+msgstr "Z Padrão Próximo"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Z Far"
-msgstr "Padrão"
+msgstr "Z Padrão Longe"
#: editor/editor_settings.cpp
msgid "Lightmap Baking Number Of CPU Threads"
-msgstr ""
+msgstr "Número de Threads de CPU para o Bake do Mapa de Luz"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Navigation Scheme"
-msgstr "Modo Navegação"
+msgstr "Esquema de Navegação"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Invert Y Axis"
-msgstr "Eduitar Eixo Y"
+msgstr "Inverter Eixo Y"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Invert X Axis"
-msgstr "Editar Eixo X"
+msgstr "Inverter Eixo X"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Zoom Style"
-msgstr "Reduzir"
+msgstr "Estilo de Zoom"
#: editor/editor_settings.cpp
msgid "Emulate Numpad"
-msgstr ""
+msgstr "Simular o Numpad"
#: editor/editor_settings.cpp
msgid "Emulate 3 Button Mouse"
-msgstr ""
+msgstr "Simular o Botão 3 Do Mouse"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Orbit Modifier"
-msgstr "Ordenar por Primeiro Modificado"
+msgstr "Modificador de Órbita"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Pan Modifier"
-msgstr "Modo Panorâmico"
+msgstr "Modificador de Panorâmica"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Zoom Modifier"
-msgstr "Modificado"
+msgstr "Modificador de Zoom"
#: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp
msgid "Warped Mouse Panning"
-msgstr ""
+msgstr "Panorização Distorcida pelo Mouse"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Navigation Feel"
-msgstr "Modo Navegação"
+msgstr "Sensação de Navegação"
#: editor/editor_settings.cpp
msgid "Orbit Sensitivity"
-msgstr ""
+msgstr "Sensitividade de Órbita"
#: editor/editor_settings.cpp
msgid "Orbit Inertia"
-msgstr ""
+msgstr "Inercia de Órbita"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Translation Inertia"
-msgstr "Traduções"
+msgstr "Inércia de Translação"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Zoom Inertia"
-msgstr "Ampliar"
+msgstr "Inércia de Zoom"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook"
-msgstr "Visão Livre em Cima"
+msgstr "Visão Livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Navigation Scheme"
-msgstr "Criar Malha de Navegação"
+msgstr "Esquema de Navegação de Visão Livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Sensitivity"
-msgstr "Visão Livre na Esquerda"
+msgstr "Sensibilidade de Visão Livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Inertia"
-msgstr "Visão Livre na Esquerda"
+msgstr "Inercia de Visão Livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Base Speed"
-msgstr "Modificador de velocidade da Visão Livre"
+msgstr "Velocidade Base de Visão Livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Activation Modifier"
-msgstr "Modificador de velocidade lenta da Visão Livre"
+msgstr "Modificador de Ativação de Visão Livre"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Speed Zoom Link"
-msgstr "Modificador de velocidade da Visão Livre"
+msgstr "Velocidade de Ligação do Visão Livre"
#: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Grid Color"
-msgstr "Escolher Cor"
+msgstr "Cor da Grade"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Guides Color"
-msgstr "Escolher Cor"
+msgstr "Cor Guia"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Smart Snapping Line Color"
-msgstr "Encaixe inteligente"
+msgstr "Cor da Linha de Encaixe Inteligente"
#: editor/editor_settings.cpp
msgid "Bone Width"
-msgstr ""
+msgstr "Largura do Osso"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Color 1"
-msgstr "Renomear Item de Cor"
+msgstr "Cor de Osso 1"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Color 2"
-msgstr "Renomear Item de Cor"
+msgstr "Cor de Osso 2"
#: editor/editor_settings.cpp
msgid "Bone Selected Color"
@@ -6078,11 +5987,11 @@ msgstr "Cor Selecionada do Osso"
#: editor/editor_settings.cpp
msgid "Bone IK Color"
-msgstr ""
+msgstr "Cor de Osso IK (cinemática inversa)"
#: editor/editor_settings.cpp
msgid "Bone Outline Color"
-msgstr ""
+msgstr "Cor de Contorno do Osso"
#: editor/editor_settings.cpp
msgid "Bone Outline Size"
@@ -6090,103 +5999,93 @@ msgstr "Tamanho do Contorno do Osso"
#: editor/editor_settings.cpp
msgid "Viewport Border Color"
-msgstr ""
+msgstr "Cor da Borda de Viewport"
#: editor/editor_settings.cpp
msgid "Constrain Editor View"
-msgstr ""
+msgstr "Restringir Visão do Editor"
#: editor/editor_settings.cpp
msgid "Simple Panning"
-msgstr ""
+msgstr "Panoramização Simples"
#: editor/editor_settings.cpp
msgid "Scroll To Pan"
-msgstr ""
+msgstr "Rolar para Panoramizar"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Pan Speed"
-msgstr "Velocidade:"
+msgstr "Velocidade da Panoramização"
#: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Poly Editor"
-msgstr "Editor UV de Polígonos 2D"
+msgstr "Editor de Polígonos"
#: editor/editor_settings.cpp
msgid "Point Grab Radius"
-msgstr ""
+msgstr "Raio de Agarro ao Ponto"
#: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Show Previous Outline"
-msgstr "Plano Anterior"
+msgstr "Exibir Prévia Anterior"
#: editor/editor_settings.cpp editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Autorename Animation Tracks"
-msgstr "Renomear Animação"
+msgstr "Renomear Automaticamente Faixa de Animação"
#: editor/editor_settings.cpp
msgid "Default Create Bezier Tracks"
-msgstr ""
+msgstr "Criar Faixa de Bezier por Padrão"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Create Reset Tracks"
-msgstr "Criar RESET Track(s)"
+msgstr "Criar Faixa RESET Por Padrão"
#: editor/editor_settings.cpp
msgid "Onion Layers Past Color"
-msgstr ""
+msgstr "Cor da Camada de Cebola Anterior"
#: editor/editor_settings.cpp
msgid "Onion Layers Future Color"
-msgstr ""
+msgstr "Cor da Camada de Cebola Posterior"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Visual Editors"
-msgstr "Editor de Grupos"
+msgstr "Editores Visuais"
#: editor/editor_settings.cpp
msgid "Minimap Opacity"
-msgstr ""
+msgstr "Opacidade do Mini-Mapa"
#: editor/editor_settings.cpp
msgid "Window Placement"
-msgstr ""
+msgstr "Colocação da Janela"
#: editor/editor_settings.cpp scene/2d/back_buffer_copy.cpp scene/2d/sprite.cpp
#: scene/2d/visibility_notifier_2d.cpp scene/3d/sprite_3d.cpp
#: scene/gui/control.cpp
-#, fuzzy
msgid "Rect"
-msgstr "Rect Completo"
+msgstr "Retângulo"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Rect Custom Position"
-msgstr "Definir Posição de Saída da Curva"
+msgstr "Posição Personalizada Do Retângulo"
#: editor/editor_settings.cpp platform/android/export/export_plugin.cpp
msgid "Screen"
-msgstr ""
+msgstr "Tela"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Auto Save"
-msgstr "Auto Fatiar"
+msgstr "Salvar Automaticamente"
#: editor/editor_settings.cpp
msgid "Save Before Running"
msgstr "Salvar Antes de Executar"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Font Size"
-msgstr "Visão Frontal"
+msgstr "Tamanho da Fonte"
#: editor/editor_settings.cpp
#: modules/gdscript/language_server/gdscript_language_server.cpp
@@ -6195,28 +6094,26 @@ msgstr "Hospedeiro Remoto"
#: editor/editor_settings.cpp
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Remote Port"
-msgstr "Remover Ponto"
+msgstr "Porta Remota"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Editor SSL Certificates"
-msgstr "Configurações do Editor"
+msgstr "Certificados SSL do Editor"
#: editor/editor_settings.cpp
msgid "HTTP Proxy"
-msgstr ""
+msgstr "Proxy HTTP"
#: editor/editor_settings.cpp
msgid "Host"
-msgstr ""
+msgstr "Hospedeiro"
#: editor/editor_settings.cpp editor/fileserver/editor_file_server.cpp
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Port"
-msgstr ""
+msgstr "Porta"
#. TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects.
#: editor/editor_settings.cpp
@@ -6230,32 +6127,31 @@ msgstr "Ordem de Classificação"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Symbol Color"
-msgstr ""
+msgstr "Cor do Simbolo"
#: editor/editor_settings.cpp
msgid "Keyword Color"
-msgstr ""
+msgstr "Cor de Palavra Chave"
#: editor/editor_settings.cpp
msgid "Control Flow Keyword Color"
-msgstr ""
+msgstr "Core de Palavra Chave de Controle de Fluxo"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Type Color"
-msgstr "Mudar Tipo Base"
+msgstr "Cor de Tipo Base"
#: editor/editor_settings.cpp
msgid "Engine Type Color"
-msgstr ""
+msgstr "Cor de Tipo da Engine"
#: editor/editor_settings.cpp
msgid "User Type Color"
-msgstr ""
+msgstr "Cor de Tipo Do Usuário"
#: editor/editor_settings.cpp
msgid "Comment Color"
-msgstr ""
+msgstr "Cor de Comentário"
#: editor/editor_settings.cpp
msgid "String Color"
@@ -6272,26 +6168,24 @@ msgid "Completion Background Color"
msgstr "Cor de Fundo de Acabamento"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Completion Selected Color"
-msgstr "Importar Selecionado"
+msgstr "Cor de Sugestão Selecionada"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Existing Color"
-msgstr ""
+msgstr "Cor de Sugestão Existente"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Scroll Color"
-msgstr ""
+msgstr "Cor da Barra de Rolagem de Sugestão"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Font Color"
-msgstr ""
+msgstr "Cor da Fonte de Sugestão"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Text Color"
-msgstr "Próximo Chão"
+msgstr "Cor do Texto"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Line Number Color"
@@ -6303,86 +6197,75 @@ msgstr "Cor do Número da Linha Segura"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Caret Color"
-msgstr ""
+msgstr "Cor do Cursor"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Caret Background Color"
msgstr "Cor de Fundo de Acentuação"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Text Selected Color"
-msgstr "Excluir Selecionados"
+msgstr "Cor do Texto Selecionado"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Selection Color"
-msgstr "Selecionar Apenas"
+msgstr "Cor da Seleção"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Brace Mismatch Color"
-msgstr ""
+msgstr "Cor de Chave Incompatível"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Current Line Color"
-msgstr "Cena Atual"
+msgstr "Cor da Linha Atual"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Color"
-msgstr ""
+msgstr "Cor do Tamanho de Linha Guia"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Word Highlighted Color"
-msgstr "Realce de sintaxe"
+msgstr "Cor da Palavra em Destaque"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Number Color"
-msgstr ""
+msgstr "Cor de Número"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Function Color"
-msgstr "Funções"
+msgstr "Cor de Função"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Member Variable Color"
-msgstr "Renomear Variável"
+msgstr "Cor de Variável Membro"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Mark Color"
-msgstr "Escolher Cor"
+msgstr "Cor de Marcação"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Bookmark Color"
-msgstr "Marcadores"
+msgstr "Cor de Bookmark"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Breakpoint Color"
-msgstr "Breakpoints"
+msgstr "Cor de Ponto de Quebra"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Executing Line Color"
-msgstr ""
+msgstr "Cor da Linha em Execução"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Code Folding Color"
-msgstr ""
+msgstr "Cor da Dobradiça de Código"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Search Result Color"
-msgstr "Pesquisar resultados"
+msgstr "Cor do Resultado de Pesquisa"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Search Result Border Color"
-msgstr "Pesquisar resultados"
+msgstr "Cor da Borda do Resultado de Pesquisa"
#: editor/editor_spin_slider.cpp
msgid "Hold %s to round to integers. Hold Shift for more precise changes."
@@ -6391,14 +6274,12 @@ msgstr ""
"mais precisas."
#: editor/editor_spin_slider.cpp scene/gui/button.cpp
-#, fuzzy
msgid "Flat"
-msgstr "Plano 0"
+msgstr "Raso"
#: editor/editor_spin_slider.cpp
-#, fuzzy
msgid "Hide Slider"
-msgstr "Modo Colisão"
+msgstr "Esconder Rolagem"
#: editor/editor_sub_scene.cpp
msgid "Select Node(s) to Import"
@@ -6698,7 +6579,7 @@ msgstr ""
#: editor/fileserver/editor_file_server.cpp
msgid "File Server"
-msgstr ""
+msgstr "Servidor de Arquivos"
#: editor/fileserver/editor_file_server.cpp
#: editor/plugins/version_control_editor_plugin.cpp
@@ -6766,6 +6647,11 @@ msgid ""
"After renaming to an unknown extension, the file won't be shown in the "
"editor anymore."
msgstr ""
+"Esta extensão de arquivo não é reconhecida pelo editor.\n"
+"Se ainda assim você deseja renomear, utilize o explorador de arquivos do seu "
+"sistema operacional.\n"
+"Após renomear para uma extensão desconhecida, este arquivo não será mais "
+"exibida pelo editor."
#: editor/filesystem_dock.cpp
msgid ""
@@ -7066,43 +6952,40 @@ msgstr "Gerenciar Grupos"
#: editor/import/editor_import_collada.cpp
msgid "Collada"
-msgstr ""
+msgstr "Collada"
#: editor/import/editor_import_collada.cpp
msgid "Use Ambient"
-msgstr ""
+msgstr "Utilizar Ambient"
#: editor/import/resource_importer_bitmask.cpp
-#, fuzzy
msgid "Create From"
-msgstr "Criar Pasta"
+msgstr "Criar à Partir de"
#: editor/import/resource_importer_bitmask.cpp
#: servers/audio/effects/audio_effect_compressor.cpp
msgid "Threshold"
-msgstr ""
+msgstr "Limite"
#: editor/import/resource_importer_csv_translation.cpp
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_scene.cpp
#: editor/import/resource_importer_texture.cpp
#: editor/import/resource_importer_wav.cpp scene/3d/gi_probe.cpp
-#, fuzzy
msgid "Compress"
-msgstr "Componentes"
+msgstr "Comprimir"
#: editor/import/resource_importer_csv_translation.cpp
msgid "Delimiter"
-msgstr ""
+msgstr "Delimitador"
#: editor/import/resource_importer_layered_texture.cpp
-#, fuzzy
msgid "ColorCorrect"
-msgstr "Correção de Cor"
+msgstr "Corrigir as Cores"
#: editor/import/resource_importer_layered_texture.cpp
msgid "No BPTC If RGB"
-msgstr ""
+msgstr "Não utilizar BPTC se for RGB"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp scene/2d/cpu_particles_2d.cpp
@@ -7110,13 +6993,13 @@ msgstr ""
#: scene/resources/material.cpp scene/resources/particles_material.cpp
#: scene/resources/texture.cpp scene/resources/visual_shader.cpp
msgid "Flags"
-msgstr ""
+msgstr "Sinalizadores"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp scene/animation/tween.cpp
#: scene/resources/texture.cpp
msgid "Repeat"
-msgstr ""
+msgstr "Repetir"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp scene/2d/light_2d.cpp
@@ -7126,24 +7009,22 @@ msgstr "Filtro"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Mipmaps"
-msgstr "Sinais"
+msgstr "Mipmaps"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
msgid "Anisotropic"
-msgstr ""
+msgstr "Anisotrópico"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
msgid "sRGB"
-msgstr ""
+msgstr "sRGB"
#: editor/import/resource_importer_layered_texture.cpp
-#, fuzzy
msgid "Slices"
-msgstr "Auto Fatiar"
+msgstr "Fatias"
#: editor/import/resource_importer_layered_texture.cpp
#: scene/gui/aspect_ratio_container.cpp scene/gui/control.cpp
@@ -7160,14 +7041,12 @@ msgid "Vertical"
msgstr "Vertical"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Generate Tangents"
-msgstr "Gerar Pontos"
+msgstr "Gerar Tangentes"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Scale Mesh"
-msgstr "Modo de Escalonamento"
+msgstr "Redimensionar Malha"
#: editor/import/resource_importer_obj.cpp
msgid "Offset Mesh"
@@ -7175,14 +7054,12 @@ msgstr "Malha de Deslocamento"
#: editor/import/resource_importer_obj.cpp
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Octahedral Compression"
-msgstr "Expressão"
+msgstr "Compressão Octaedral"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Optimize Mesh Flags"
-msgstr "Sinalizadores de Tamanho"
+msgstr "Otimizar Sinalizadores da Malha"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Single Scene"
@@ -7230,24 +7107,20 @@ msgid "Nodes"
msgstr "Nós"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Type"
-msgstr "Retornar"
+msgstr "Tipo da Raiz"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Name"
-msgstr "Nome Remoto"
+msgstr "Nome da Raiz"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Scale"
-msgstr "Escala"
+msgstr "Escala da Raiz"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Custom Script"
-msgstr "Recortar Nós"
+msgstr "Script Personalizado"
#: editor/import/resource_importer_scene.cpp scene/resources/texture.cpp
msgid "Storage"
@@ -7255,69 +7128,59 @@ msgstr "Armazenamento"
#: editor/import/resource_importer_scene.cpp
msgid "Use Legacy Names"
-msgstr ""
+msgstr "Utilizar Nomes Legados"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
msgid "Materials"
msgstr "Materiais"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep On Reimport"
-msgstr "Reimportar"
+msgstr "Manter ao Reimportar"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Meshes"
-msgstr "Malha"
+msgstr "Malhas"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Ensure Tangents"
-msgstr "Modificar Tangente da Curva"
+msgstr "Garantir Tangentes"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Light Baking"
-msgstr "Faça mapas de luz"
+msgstr "Bake de Mapa de Luz"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Lightmap Texel Size"
-msgstr "Faça mapas de luz"
+msgstr "Tamanho do Texel no Mapa de Luz"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
msgid "Skins"
-msgstr ""
+msgstr "Peles"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Use Named Skins"
-msgstr "Usar Encaixe Escalar"
+msgstr "Utilizar Peles com Nome"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "External Files"
-msgstr "Abrir um Arquivo"
+msgstr "Arquivos Externos"
#: editor/import/resource_importer_scene.cpp
msgid "Store In Subdir"
-msgstr ""
+msgstr "Salvar em Sub Diretório"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Filter Script"
-msgstr "Filtrar scripts"
+msgstr "Filtrar Script"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep Custom Tracks"
-msgstr "Transformação"
+msgstr "Manter Faixas Personalizadas"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Optimizer"
-msgstr "Otimizar"
+msgstr "Otimizador"
#: editor/import/resource_importer_scene.cpp
#: editor/plugins/item_list_editor_plugin.cpp main/main.cpp
@@ -7331,9 +7194,8 @@ msgstr "Otimizar"
#: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp
#: scene/gui/rich_text_label.cpp scene/resources/curve.cpp
#: scene/resources/environment.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Enabled"
-msgstr "Habilitar"
+msgstr "Habilitado"
#: editor/import/resource_importer_scene.cpp
msgid "Max Linear Error"
@@ -7344,19 +7206,16 @@ msgid "Max Angular Error"
msgstr "Erro Angular Máximo"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Max Angle"
-msgstr "Valor"
+msgstr "Ângulo Máximo"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Remove Unused Tracks"
-msgstr "Remover Trilha da Anim"
+msgstr "Remover Faixas não Utilizadas"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Clips"
-msgstr "Clipes de Animação"
+msgstr "Clipes"
#: editor/import/resource_importer_scene.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/particles_2d.cpp scene/3d/area.cpp scene/3d/cpu_particles.cpp
@@ -7410,30 +7269,33 @@ 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: Foi detectado que a textura está sendo utilizada como mapa normal em 3D. "
+"Habilitando a compressão vermelho/verde para reduzir o uso de memória (o "
+"canal azul é descartado)."
#: 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: Foi detectado que a textura está sendo utilizada em 3D. Habilitando a "
+"filtro, repetir, geração de mipmap e compressão de textura VRAM."
#: editor/import/resource_importer_texture.cpp
msgid "2D, Detect 3D"
-msgstr ""
+msgstr "2D, Detecte 3D"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "2D Pixel"
-msgstr "Pixels Sólidos"
+msgstr "Pixel 2D"
#: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp
msgid "Lossy Quality"
-msgstr ""
+msgstr "Com Perda de Qualidade"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "HDR Mode"
-msgstr "Modo de Seleção"
+msgstr "Modo HDR"
#: editor/import/resource_importer_texture.cpp
msgid "BPTC LDR"
@@ -7444,54 +7306,52 @@ msgstr ""
#: scene/2d/mesh_instance_2d.cpp scene/2d/multimesh_instance_2d.cpp
#: scene/2d/particles_2d.cpp scene/2d/sprite.cpp scene/resources/style_box.cpp
msgid "Normal Map"
-msgstr ""
+msgstr "Mapa Normal"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Process"
-msgstr "Pós-processamento"
+msgstr "Processar"
#: editor/import/resource_importer_texture.cpp
msgid "Fix Alpha Border"
-msgstr ""
+msgstr "Corrigir Alpha da Borda"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Premult Alpha"
-msgstr "Editar Polígono"
+msgstr ""
#: editor/import/resource_importer_texture.cpp
msgid "Hdr As Srgb"
-msgstr ""
+msgstr "HDR como SRGB"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Invert Color"
-msgstr "Vértice"
+msgstr "Inverter Cor"
#: editor/import/resource_importer_texture.cpp
msgid "Normal Map Invert Y"
msgstr "Inverter Y do Mapa Normal"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Size Limit"
-msgstr "Limites"
+msgstr "Limite de Tamanho"
#: editor/import/resource_importer_texture.cpp
msgid "Detect 3D"
-msgstr ""
+msgstr "Detectar 3D"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "SVG"
-msgstr "HSV"
+msgstr "SVG"
#: editor/import/resource_importer_texture.cpp
msgid ""
"Warning, no suitable PC VRAM compression enabled in Project Settings. This "
"texture will not display correctly on PC."
msgstr ""
+"Atenção, nenhuma forma adequada de Compressão VRAM para PC foi habilitada "
+"nas Configurações do Projeto. Esta textura não será exibida corretamente em "
+"PCs."
#: editor/import/resource_importer_texture_atlas.cpp
msgid "Atlas File"
@@ -7502,64 +7362,56 @@ msgid "Import Mode"
msgstr "Modo de Importação"
#: editor/import/resource_importer_texture_atlas.cpp
-#, fuzzy
msgid "Crop To Region"
-msgstr "Definir a região do Mosaico"
+msgstr "Recortar para Região"
#: editor/import/resource_importer_texture_atlas.cpp
msgid "Trim Alpha Border From Region"
-msgstr ""
+msgstr "Aparar Borda Alfa da Região"
#: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp
-#, fuzzy
msgid "Force"
-msgstr "Forçar Push"
+msgstr "Forçar"
#: editor/import/resource_importer_wav.cpp
msgid "8 Bit"
-msgstr ""
+msgstr "8 Bits"
#: editor/import/resource_importer_wav.cpp main/main.cpp
#: modules/mono/editor/csharp_project.cpp modules/mono/mono_gd/gd_mono.cpp
msgid "Mono"
-msgstr ""
+msgstr "Mono"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate"
-msgstr "Nó Mix"
+msgstr "Frequência Máxima"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate Hz"
-msgstr "Nó Mix"
+msgstr "Frequência Máxima Hz"
#: editor/import/resource_importer_wav.cpp
msgid "Trim"
-msgstr ""
+msgstr "Aparar"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Normalize"
-msgstr "Formato"
+msgstr "Normalizar"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop Mode"
-msgstr "Modo de Movimentação"
+msgstr "Modo de Loop"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop Begin"
-msgstr "Modo de Movimentação"
+msgstr "Inicio do Loop"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop End"
-msgstr "Modo de Movimentação"
+msgstr "Fim do Loop"
#: editor/import_defaults_editor.cpp
msgid "Select Importer"
@@ -7647,18 +7499,16 @@ msgid "Raw"
msgstr "Bruto"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Capitalized"
-msgstr "Capitalizar"
+msgstr "Capitalizado"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Localized"
-msgstr "Localizar"
+msgstr "Localizado"
#: editor/inspector_dock.cpp
msgid "Localization not available for current language."
-msgstr ""
+msgstr "Localização não disponível para linguagem atual."
#: editor/inspector_dock.cpp
msgid "Copy Properties"
@@ -8207,9 +8057,8 @@ msgid "New"
msgstr "Novo"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Paste As Reference"
-msgstr "%s Referência de Classes"
+msgstr "Colar como Referência"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Edit Transitions..."
@@ -8538,7 +8387,7 @@ msgstr "Filtros..."
#: editor/plugins/asset_library_editor_plugin.cpp scene/main/http_request.cpp
msgid "Use Threads"
-msgstr ""
+msgstr "Usar Threads"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Contents:"
@@ -8701,25 +8550,21 @@ msgid "Loading..."
msgstr "Carregando..."
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "First"
msgstr "Primeiro"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Previous"
msgstr "Anterior"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Next"
msgstr "Próximo"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Last"
msgstr "Último"
@@ -8770,7 +8615,7 @@ msgstr "Testando"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed to get repository configuration."
-msgstr ""
+msgstr "Falhou em obter o repositório de configuração."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Assets ZIP File"
@@ -8830,7 +8675,7 @@ msgstr "Faça mapas de luz"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "LightMap Bake"
-msgstr ""
+msgstr "Bake de Mapa de Luz"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Select lightmap bake file:"
@@ -9337,23 +9182,20 @@ msgid "View"
msgstr "Visualizar"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show"
-msgstr "Mostrar Grade"
+msgstr "Exibir"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show When Snapping"
-msgstr "Encaixe inteligente"
+msgstr "Exibir ao Encaixar"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Hide"
-msgstr ""
+msgstr "Esconder"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Grid"
-msgstr "Alternar Modo"
+msgstr "Alternar Grade"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/polygon_2d_editor_plugin.cpp
@@ -9637,11 +9479,11 @@ msgstr "Plano 1"
#: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp
msgid "Ease In"
-msgstr "Ease In"
+msgstr "Esmaecer de Entrada"
#: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp
msgid "Ease Out"
-msgstr "Ease Out"
+msgstr "Esmaecer de Saída"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Smoothstep"
@@ -9705,16 +9547,15 @@ msgstr "Gradiente Editado"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
msgid "Swap GradientTexture2D Fill Points"
-msgstr ""
+msgstr "Trocar Pontos de Preenchimento do GradientTexture2D"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
msgid "Swap Gradient Fill Points"
-msgstr ""
+msgstr "Trocar Pontos de Preenchimento do Degradê"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Grid Snap"
-msgstr "Alternar Modo"
+msgstr "Alternar Encaixe da Grade"
#: editor/plugins/item_list_editor_plugin.cpp editor/project_export.cpp
#: scene/3d/label_3d.cpp scene/gui/button.cpp scene/gui/dialogs.cpp
@@ -9733,13 +9574,12 @@ msgstr "Ãcone"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "ID"
-msgstr ""
+msgstr "ID"
#: editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Separator"
-msgstr "Separação:"
+msgstr "Separador"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "Item %d"
@@ -9973,7 +9813,6 @@ msgstr ""
"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "MeshLibrary"
msgstr "Biblioteca de Malhas"
@@ -9998,14 +9837,12 @@ msgid "Update from Scene"
msgstr "Atualizar a partir de Cena"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply without Transforms"
-msgstr "Aplicar transformações da MeshInstance"
+msgstr "Aplicar sem Transformações"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply with Transforms"
-msgstr "Aplicar transformações da MeshInstance"
+msgstr "Aplicar com Transformações"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "No mesh source specified (and no MultiMesh set in node)."
@@ -10497,7 +10334,7 @@ msgstr "Configurações da grade"
#: editor/plugins/polygon_2d_editor_plugin.cpp modules/csg/csg_shape.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Snap"
-msgstr "Snap"
+msgstr "Encaixe"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Enable Snap"
@@ -10533,7 +10370,7 @@ msgstr "Sincronizar Ossos ao Polígono"
#: editor/plugins/ray_cast_2d_editor_plugin.cpp
msgid "Set cast_to"
-msgstr ""
+msgstr "Definir cast_to"
#: editor/plugins/resource_preloader_editor_plugin.cpp
msgid "ERROR: Couldn't load resource!"
@@ -10864,48 +10701,43 @@ msgstr "Resultados de Pesquisa"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Dominant Script On Scene Change"
-msgstr ""
+msgstr "Abrir Script Dominante ao Mudar de Cena"
#: editor/plugins/script_editor_plugin.cpp
msgid "External"
-msgstr ""
+msgstr "Externo"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Use External Editor"
-msgstr "Depurar com o Editor Externo"
+msgstr "Utilizar Editor Externo"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Exec Path"
-msgstr "Caminho de Exportação"
+msgstr "Caminho de Execução"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Script Temperature Enabled"
-msgstr "Selecionar o Arquivo de Modelo"
+msgstr "Temperatura de Script Habilitado"
#: editor/plugins/script_editor_plugin.cpp
msgid "Highlight Current Script"
-msgstr ""
+msgstr "Destacar Script Atual"
#: editor/plugins/script_editor_plugin.cpp
msgid "Script Temperature History Size"
-msgstr ""
+msgstr "Tamanho de Histórico de Temperatura de Script"
#: editor/plugins/script_editor_plugin.cpp
msgid "Current Script Background Color"
msgstr "Cor de Fundo do Script Atual"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Group Help Pages"
-msgstr "Agrupar Selecionados"
+msgstr "Agrupar Páginas de Ajuda"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Sort Scripts By"
-msgstr "Criar Script"
+msgstr "Ordenar Scripts Por"
#: editor/plugins/script_editor_plugin.cpp
msgid "List Script Names As"
@@ -10913,7 +10745,7 @@ msgstr "Listar Nomes de Script Como"
#: editor/plugins/script_editor_plugin.cpp
msgid "Exec Flags"
-msgstr ""
+msgstr "Sinalizadores de Execução"
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Scripts"
@@ -10997,7 +10829,7 @@ msgstr "Marcadores"
#: editor/plugins/script_text_editor.cpp
msgid "Breakpoints"
-msgstr "Breakpoints"
+msgstr "Pontos de Quebra"
#: editor/plugins/script_text_editor.cpp
#: editor/plugins/shader_editor_plugin.cpp editor/plugins/text_editor.cpp
@@ -11426,13 +11258,14 @@ msgstr "Pré-visualização Cinemática"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "(Not in GLES2)"
-msgstr ""
+msgstr "(Não disponível em GLES2)"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Debug draw modes are only available when using the GLES3 renderer, not GLES2."
-msgstr "Não disponível ao usar o renderizador GLES2."
+msgstr ""
+"Modos de Debug draw só estão disponíveis para uso com o renderizador GLES3. "
+"GLES2 não suporta esta funcionalidade."
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
@@ -11727,16 +11560,15 @@ msgstr "Pós"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Manipulator Gizmo Size"
-msgstr ""
+msgstr "Tamanho do Gizmo Manipulador"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Manipulator Gizmo Opacity"
-msgstr ""
+msgstr "Opacidade do Gizmo Manipulador"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Show Viewport Rotation Gizmo"
-msgstr "Bloquear Rotação da Visão"
+msgstr "Exibir Gizmo de Rotação do Viewport"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Unnamed Gizmo"
@@ -11788,9 +11620,8 @@ msgid "Invalid geometry, can't replace by mesh."
msgstr "Geometria inválida, não é possível substituir por malha."
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Convert to MeshInstance2D"
-msgstr "Converter para Malha2D"
+msgstr "Converter para MeshInstance2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create polygon."
@@ -11893,6 +11724,11 @@ msgid "New Animation"
msgstr "Nova animação"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filtrar métodos"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Velocidade:"
@@ -12190,9 +12026,8 @@ msgstr ""
"Fechar mesmo assim?"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Type"
-msgstr "Remover Telha"
+msgstr "Remover Tipo"
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
@@ -12236,14 +12071,12 @@ msgstr ""
"Adicione mais itens manualmente ou importe de outro tema."
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Add Theme Type"
-msgstr "Adicionar Tipo de Item"
+msgstr "Adicionar Tipo de Tema"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Theme Type"
-msgstr "Remover remoto"
+msgstr "Remover Tipo de Tema"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Color Item"
@@ -12358,9 +12191,8 @@ msgid "Select Another Theme Resource:"
msgstr "Selecionar Outro Recurso de Tema:"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Theme Resource"
-msgstr "Renomear Recurso"
+msgstr "Recurso de Tema"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Another Theme"
@@ -12415,14 +12247,12 @@ msgid "Add Item Type"
msgstr "Adicionar Tipo de Item"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Set Variation Base Type"
-msgstr "Definir o Tipo da Variável"
+msgstr "Definir Tipo de Variação Base"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Set Base Type"
-msgstr "Mudar Tipo Base"
+msgstr "Definir Tipo Base"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Show Default"
@@ -12444,12 +12274,15 @@ msgstr "Substituir todos os itens do modelo padrão."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Select the variation base type from a list of available types."
msgstr ""
+"Selecione a variação do tipo base à partir da lista de tipos disponíveis."
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
"A type associated with a built-in class cannot be marked as a variation of "
"another type."
msgstr ""
+"Um tipo associado à uma classe padrão não pode ser marcada como variação de "
+"outro tipo."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Theme:"
@@ -12687,14 +12520,13 @@ msgid "Clear Transform"
msgstr "Limpar Transformação"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Tile Map"
-msgstr "Pintar TileMap"
+msgstr "Tile Map"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Palette Min Width"
-msgstr ""
+msgstr "Largura Mínima de Paleta"
#: editor/plugins/tile_map_editor_plugin.cpp
#, fuzzy
@@ -12702,24 +12534,20 @@ msgid "Palette Item H Separation"
msgstr "Separador Nomeado"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Show Tile Names"
-msgstr "Mostrar todos os Locales"
+msgstr "Mostrar Nomes dos Tiles"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Show Tile Ids"
-msgstr "Mostrar Réguas"
+msgstr "Mostrar Ids dos Tiles"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Sort Tiles By Name"
-msgstr "Ordenar arquivos"
+msgstr "Ordenar Tiles por Nome"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill Preview"
-msgstr "Preenchimento de Balde"
+msgstr "Pré-visualização do Preenchimento de Balde"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
@@ -12728,9 +12556,8 @@ msgid "Editor Side"
msgstr "Editor"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Display Grid"
-msgstr "Exibição Overdraw"
+msgstr "Mostrar Grid"
#: editor/plugins/tile_map_editor_plugin.cpp
#, fuzzy
@@ -13096,14 +12923,12 @@ msgstr "Passo"
#: editor/plugins/tile_set_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Separation"
-msgstr "Separação:"
+msgstr "Separação"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Tile"
-msgstr "Selecionar"
+msgstr "Selecionar Tile"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/light_2d.cpp scene/2d/line_2d.cpp scene/2d/mesh_instance_2d.cpp
@@ -13112,9 +12937,8 @@ msgstr "Selecionar"
#: scene/gui/nine_patch_rect.cpp scene/gui/texture_rect.cpp
#: scene/resources/material.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Texture"
-msgstr "Texto"
+msgstr "Textura"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -13134,9 +12958,8 @@ msgid "Modulate"
msgstr "Popular"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tile Mode"
-msgstr "Alternar Modo"
+msgstr "Modo de Tiles"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -13144,14 +12967,12 @@ msgid "Autotile Bitmask Mode"
msgstr "Modo Bitmask"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Size"
-msgstr "Tamanho do Contorno:"
+msgstr "Tamanho do Sub Título"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Spacing"
-msgstr "Loop da Animação"
+msgstr "Espaçamento dos Subtiles"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -13159,24 +12980,20 @@ msgid "Occluder Offset"
msgstr "Criar Polígono de Oclusão"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Navigation Offset"
-msgstr "Modo Navegação"
+msgstr "Deslocamento da Navegação"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Shape Offset"
-msgstr "Deslocamento Base"
+msgstr "Deslocamento da Forma"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Shape Transform"
-msgstr "Transformação"
+msgstr "Transformação da Forma"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision"
-msgstr "Colisão"
+msgstr "Colisão Selecionada"
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -13189,19 +13006,16 @@ msgid "Selected Collision One Way Margin"
msgstr "Modo Colisão"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Navigation"
-msgstr "Navegação Visível"
+msgstr "Navegação Selecionada"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Occlusion"
-msgstr "Selecionar"
+msgstr "Oclusão Selecionada"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tileset Script"
-msgstr "Filtrar scripts"
+msgstr "Scripts do Tileset"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "TileSet"
@@ -13280,7 +13094,7 @@ msgstr "Selecione o caminho da chave privada SSH"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "SSH Passphrase"
-msgstr "SSH Passphrase"
+msgstr "Senha SSH"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Detect new changes"
@@ -14289,11 +14103,13 @@ msgstr "Executável"
#: editor/project_export.cpp
msgid "Export the project for all the presets defined."
-msgstr ""
+msgstr "Exportar o projeto para todos os presets definidos."
#: editor/project_export.cpp
msgid "All presets must have an export path defined for Export All to work."
msgstr ""
+"Todos os presets devem ter um caminho de exportação para que a "
+"funcionalidade de Exportar Todos funcione."
#: editor/project_export.cpp
msgid "Delete preset '%s'?"
@@ -14406,11 +14222,12 @@ msgid ""
"Note: Encryption key needs to be stored in the binary,\n"
"you need to build the export templates from source."
msgstr ""
+"Nota: Chaves de encriptação têm que ser salvas com o binário,\n"
+"você precisa compilar os modelos de exportação à partir do código fonte."
#: editor/project_export.cpp
-#, fuzzy
msgid "More Info..."
-msgstr "Mover Para..."
+msgstr "Mais Informações..."
#: editor/project_export.cpp
msgid "Export PCK/Zip..."
@@ -14437,18 +14254,16 @@ msgid "ZIP File"
msgstr "Arquivo ZIP"
#: editor/project_export.cpp
-#, fuzzy
msgid "Godot Project Pack"
-msgstr "Pacote de Jogos Godot"
+msgstr "Pacote do Projeto Godot"
#: editor/project_export.cpp
msgid "Export templates for this platform are missing:"
msgstr "Modelos de exportação para esta plataforma não foram encontrados:"
#: editor/project_export.cpp
-#, fuzzy
msgid "Project Export"
-msgstr "Fundadores do Projeto"
+msgstr "Exportar Projeto"
#: editor/project_export.cpp
msgid "Manage Export Templates"
@@ -14761,7 +14576,6 @@ msgstr ""
#. TRANSLATORS: This refers to the application where users manage their Godot projects.
#: editor/project_manager.cpp
-#, fuzzy
msgctxt "Application"
msgid "Project Manager"
msgstr "Gerenciador de Projetos"
@@ -15561,7 +15375,7 @@ msgstr "Tornar Local"
#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp
msgid "Another node already uses this unique name in the scene."
-msgstr ""
+msgstr "Outro nó já está usando este nome único na cena atual."
#: editor/scene_tree_dock.cpp
#, fuzzy
@@ -15647,7 +15461,7 @@ msgstr "Sub-Recursos"
#: editor/scene_tree_dock.cpp
msgid "Access as Scene Unique Name"
-msgstr ""
+msgstr "Acessar como Nome Único de Cena"
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
@@ -15752,7 +15566,7 @@ msgstr "Seleção Central"
#: editor/scene_tree_dock.cpp
msgid "Derive Script Globals By Name"
-msgstr ""
+msgstr "Obter Globais de Script por Nome"
#: editor/scene_tree_dock.cpp
#, fuzzy
@@ -15785,6 +15599,9 @@ msgid ""
"with the '%s' prefix in a node path.\n"
"Click to disable this."
msgstr ""
+"Este nó pode ser acessado em qualquer lugar na cena adicionando o prefixo "
+"'%s' em um node path.\n"
+"Clique para desabilitar esta funcionalidade."
#: editor/scene_tree_editor.cpp
msgid ""
@@ -16077,15 +15894,15 @@ msgstr "Filtros do tile"
#: editor/script_editor_debugger.cpp
msgid "Auto Switch To Remote Scene Tree"
-msgstr ""
+msgstr "Mudar Automaticamente Para a Ãrvore de Cena Remota"
#: editor/script_editor_debugger.cpp
msgid "Remote Scene Tree Refresh Interval"
-msgstr ""
+msgstr "Intervalo de Atualização da Ãrvore Remota"
#: editor/script_editor_debugger.cpp
msgid "Remote Inspect Refresh Interval"
-msgstr ""
+msgstr "Intervalo de Atualização da Inspeção Remota"
#: editor/script_editor_debugger.cpp
msgid "Network Profiler"
@@ -16183,7 +16000,7 @@ msgstr "Alterar Raio da Luz"
#: editor/spatial_editor_gizmos.cpp
msgid "Stream Player 3D"
-msgstr ""
+msgstr "Player de Stream 3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
@@ -16193,7 +16010,7 @@ msgstr "Alterar o Ângulo de Emissão do AudioStreamPlayer3D"
#: platform/osx/export/export.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Camera"
-msgstr ""
+msgstr "Câmera"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -16205,7 +16022,7 @@ msgstr "Alterar Tamanho da Câmera"
#: editor/spatial_editor_gizmos.cpp
msgid "Visibility Notifier"
-msgstr ""
+msgstr "Notificador de Visibilidade"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Notifier AABB"
@@ -16263,9 +16080,8 @@ msgid "Change Ray Shape Length"
msgstr "Alterar o Comprimento da Forma do Raio"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Edge"
-msgstr "Modo Navegação"
+msgstr "Bordas de Navegação"
#: editor/spatial_editor_gizmos.cpp
#, fuzzy
@@ -16273,30 +16089,28 @@ msgid "Navigation Edge Disabled"
msgstr "Modo Navegação"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Solid"
-msgstr "Modo Navegação"
+msgstr "Navegação Sólida"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Solid Disabled"
-msgstr "Modo Navegação"
+msgstr "Navegação Sólida Desabilitada"
#: editor/spatial_editor_gizmos.cpp
msgid "Joint Body A"
-msgstr ""
+msgstr "Corpo de Encaixe A"
#: editor/spatial_editor_gizmos.cpp
msgid "Joint Body B"
-msgstr ""
+msgstr "Corpo de Encaixe B"
#: editor/spatial_editor_gizmos.cpp
msgid "Room Edge"
-msgstr ""
+msgstr "Canto da Sala"
#: editor/spatial_editor_gizmos.cpp
msgid "Room Overlap"
-msgstr ""
+msgstr "Intercessão de Quarto"
#: editor/spatial_editor_gizmos.cpp
msgid "Set Room Point Position"
@@ -16309,11 +16123,11 @@ msgstr "Definir Margem"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Edge"
-msgstr ""
+msgstr "Canto do Portal"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Arrow"
-msgstr ""
+msgstr "Seta do Portal"
#: editor/spatial_editor_gizmos.cpp
msgid "Set Portal Point Position"
@@ -16321,7 +16135,7 @@ msgstr "Definir Posição Do Ponto Do Portal"
#: editor/spatial_editor_gizmos.cpp
msgid "Portal Front"
-msgstr ""
+msgstr "Frente do Portal"
#: editor/spatial_editor_gizmos.cpp
#, fuzzy
@@ -16369,12 +16183,12 @@ msgstr "Criar Polígono de Oclusão"
#: main/main.cpp
msgid "Godot Physics"
-msgstr ""
+msgstr "Godot Physics"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
msgid "Use BVH"
-msgstr ""
+msgstr "Usar BVH"
#: main/main.cpp servers/physics_2d/physics_2d_server_sw.cpp
#: servers/visual/visual_server_scene.cpp
@@ -16397,37 +16211,36 @@ msgid "RID Pool Prealloc"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Debugger stdout"
-msgstr "Depurador"
+msgstr "Depurador stdout"
#: main/main.cpp
msgid "Max Chars Per Second"
-msgstr ""
+msgstr "Máximo de Caracteres por Segundo"
#: main/main.cpp
msgid "Max Messages Per Frame"
-msgstr ""
+msgstr "Máximo de Mensagens por Quadro"
#: main/main.cpp
msgid "Max Errors Per Second"
-msgstr ""
+msgstr "Máximo de Erros por Segundo"
#: main/main.cpp
msgid "Max Warnings Per Second"
-msgstr ""
+msgstr "Máximo de Alertas Por Segundo"
#: main/main.cpp
msgid "Flush stdout On Print"
-msgstr ""
+msgstr "Limpar stdout ao Fazer Print"
#: main/main.cpp servers/visual_server.cpp
msgid "Logging"
-msgstr ""
+msgstr "Registrando Log"
#: main/main.cpp
msgid "File Logging"
-msgstr ""
+msgstr "Registrando Log de Arquivos"
#: main/main.cpp
#, fuzzy
@@ -16441,11 +16254,11 @@ msgstr "Copiar Caminho"
#: main/main.cpp
msgid "Max Log Files"
-msgstr ""
+msgstr "Máximo Log de Arquivos"
#: main/main.cpp
msgid "Driver"
-msgstr ""
+msgstr "Driver"
#: main/main.cpp
msgid "Driver Name"
@@ -16453,41 +16266,39 @@ msgstr "Nome do Driver"
#: main/main.cpp
msgid "Fallback To GLES2"
-msgstr ""
+msgstr "Utilizar GLES2 Como Fallback"
#: main/main.cpp
msgid "Use Nvidia Rect Flicker Workaround"
-msgstr ""
+msgstr "Utilizar a Gambiarra \"Nvidia Rect Flicker\""
#: main/main.cpp
msgid "DPI"
-msgstr ""
+msgstr "DPI"
#: main/main.cpp
msgid "Allow hiDPI"
-msgstr ""
+msgstr "Permitir hiDPI"
#: main/main.cpp
-#, fuzzy
msgid "V-Sync"
-msgstr "Sincronizar"
+msgstr "Sincronização Vertical (V-Sync)"
#: main/main.cpp
-#, fuzzy
msgid "Use V-Sync"
-msgstr "Use Encaixar"
+msgstr "Usar Sincronização Vertical (V-Sync)"
#: main/main.cpp
msgid "Per Pixel Transparency"
-msgstr ""
+msgstr "Transparência por Pixel"
#: main/main.cpp
msgid "Allowed"
-msgstr ""
+msgstr "Permitido"
#: main/main.cpp
msgid "Intended Usage"
-msgstr ""
+msgstr "Intenção de Uso"
#: main/main.cpp
#, fuzzy
@@ -16495,13 +16306,12 @@ msgid "Framebuffer Allocation"
msgstr "Seleção de Frame"
#: main/main.cpp platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Energy Saving"
-msgstr "Erro ao salvar"
+msgstr "Economia de Energia"
#: main/main.cpp
msgid "Threads"
-msgstr ""
+msgstr "Threads"
#: main/main.cpp servers/physics_2d/physics_2d_server_wrap_mt.h
#, fuzzy
@@ -16514,19 +16324,17 @@ msgstr ""
#: main/main.cpp
msgid "Handheld"
-msgstr ""
+msgstr "Portátil (Handheld)"
#: main/main.cpp platform/javascript/export/export.cpp
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Orientation"
-msgstr "Documentação Online"
+msgstr "Orientação"
#: main/main.cpp scene/gui/scroll_container.cpp scene/gui/text_edit.cpp
#: scene/main/scene_tree.cpp scene/register_scene_types.cpp
-#, fuzzy
msgid "Common"
-msgstr "Comunidade"
+msgstr "Comum"
#: main/main.cpp
#, fuzzy
@@ -16534,35 +16342,34 @@ msgid "Physics FPS"
msgstr "Frame de Física %"
#: main/main.cpp
-#, fuzzy
msgid "Force FPS"
-msgstr "Forçar Push"
+msgstr "Forçar FPS"
#: main/main.cpp
msgid "Enable Pause Aware Picking"
-msgstr ""
+msgstr "Habilitar Escolha que é Ciente à Pausas"
#: main/main.cpp scene/gui/item_list.cpp scene/gui/popup_menu.cpp
#: scene/gui/scroll_container.cpp scene/gui/text_edit.cpp scene/gui/tree.cpp
#: scene/main/viewport.cpp scene/register_scene_types.cpp
msgid "GUI"
-msgstr ""
+msgstr "GUI (Interface Gráfica de Usuário)"
#: main/main.cpp
msgid "Drop Mouse On GUI Input Disabled"
-msgstr ""
+msgstr "Desabilitar Mouse quando GUI Input estiver Desabilitad"
#: main/main.cpp
msgid "stdout"
-msgstr ""
+msgstr "stdout"
#: main/main.cpp
msgid "Print FPS"
-msgstr ""
+msgstr "Mostrar FPS"
#: main/main.cpp
msgid "Verbose stdout"
-msgstr ""
+msgstr "stdout Verboso"
#: main/main.cpp scene/main/scene_tree.cpp scene/resources/multimesh.cpp
#, fuzzy
@@ -16570,9 +16377,8 @@ msgid "Physics Interpolation"
msgstr "Modo de Interpolação"
#: main/main.cpp
-#, fuzzy
msgid "Enable Warnings"
-msgstr "Habilitar Filtragem"
+msgstr "Habilitar Avisos"
#: main/main.cpp
#, fuzzy
@@ -16581,19 +16387,19 @@ msgstr "Seleção de Frame"
#: main/main.cpp
msgid "Low Processor Mode"
-msgstr ""
+msgstr "Modo Processamento Baixo"
#: main/main.cpp
msgid "Delta Sync After Draw"
-msgstr ""
+msgstr "Sincronizar Delta Após o Draw"
#: main/main.cpp
msgid "iOS"
-msgstr ""
+msgstr "iOS"
#: main/main.cpp
msgid "Hide Home Indicator"
-msgstr ""
+msgstr "Esconder Indicador de Home"
#: main/main.cpp
#, fuzzy
@@ -16607,16 +16413,15 @@ msgstr "Ponto"
#: main/main.cpp
msgid "Touch Delay"
-msgstr ""
+msgstr "Atraso de Touch"
#: main/main.cpp servers/visual_server.cpp
msgid "GLES3"
-msgstr ""
+msgstr "GLES3"
#: main/main.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Shaders"
-msgstr "Shader"
+msgstr "Shaders"
#: main/main.cpp
#, fuzzy
@@ -16626,30 +16431,28 @@ msgstr "Forçar Fallbacks do Shader"
#: main/main.cpp scene/3d/baked_lightmap.cpp scene/3d/camera.cpp
#: scene/3d/world_environment.cpp scene/main/scene_tree.cpp
#: scene/resources/world.cpp
-#, fuzzy
msgid "Environment"
-msgstr "Visualizar Ambiente"
+msgstr "Ambiente"
#: main/main.cpp
msgid "Default Clear Color"
-msgstr ""
+msgstr "Cor de Limpeza Padrão"
#: main/main.cpp
msgid "Boot Splash"
-msgstr ""
+msgstr "Imagem de Exibição ao Iniciar"
#: main/main.cpp
-#, fuzzy
msgid "Show Image"
-msgstr "Mostrar Ossos"
+msgstr "Mostrar Imagem"
#: main/main.cpp
msgid "Image"
-msgstr ""
+msgstr "Imagem"
#: main/main.cpp
msgid "Fullsize"
-msgstr ""
+msgstr "Tamanho Inteiro"
#: main/main.cpp scene/resources/dynamic_font.cpp
msgid "Use Filter"
@@ -16661,13 +16464,12 @@ msgid "BG Color"
msgstr "Cores"
#: main/main.cpp
-#, fuzzy
msgid "macOS Native Icon"
-msgstr "Definir ícone de telha"
+msgstr "Ãcone Nativo macOS"
#: main/main.cpp
msgid "Windows Native Icon"
-msgstr ""
+msgstr "Ãcone Windows Nativo"
#: main/main.cpp
msgid "Buffering"
@@ -16675,29 +16477,27 @@ msgstr ""
#: main/main.cpp
msgid "Agile Event Flushing"
-msgstr ""
+msgstr "Limpeza de Eventos Agil"
#: main/main.cpp
msgid "Emulate Touch From Mouse"
-msgstr ""
+msgstr "Simular Toque à Partir do Mouse"
#: main/main.cpp
msgid "Emulate Mouse From Touch"
-msgstr ""
+msgstr "Simular Mouse à Partir do Touch"
#: main/main.cpp
-#, fuzzy
msgid "Mouse Cursor"
-msgstr "Botão do Mouse"
+msgstr "Cursor do Mouse"
#: main/main.cpp
-#, fuzzy
msgid "Custom Image"
-msgstr "Recortar Nós"
+msgstr "Imagem Personalizada"
#: main/main.cpp
msgid "Custom Image Hotspot"
-msgstr ""
+msgstr "Imagem Personalizada de Hotspot"
#: main/main.cpp
msgid "Tooltip Position Offset"
@@ -16709,9 +16509,8 @@ msgid "Debugger Agent"
msgstr "Depurador"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
-#, fuzzy
msgid "Wait For Debugger"
-msgstr "Depurador"
+msgstr "Esperar pelo Depurador"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
msgid "Wait Timeout"
@@ -16719,11 +16518,11 @@ msgstr "Tempo Limite de Espera"
#: main/main.cpp
msgid "Runtime"
-msgstr ""
+msgstr "Tempo de Execução"
#: main/main.cpp
msgid "Unhandled Exception Policy"
-msgstr ""
+msgstr "Politica de Tratamento Exceções"
#: main/main.cpp
#, fuzzy
@@ -16732,22 +16531,20 @@ msgstr "Localizar Tipo de Nó"
#: main/main.cpp scene/gui/texture_progress.cpp
#: scene/gui/viewport_container.cpp
-#, fuzzy
msgid "Stretch"
-msgstr "Buscar"
+msgstr "Esticar"
#: main/main.cpp
-#, fuzzy
msgid "Aspect"
-msgstr "Inspetor"
+msgstr "Aspecto"
#: main/main.cpp
msgid "Shrink"
-msgstr ""
+msgstr "Encolher"
#: main/main.cpp scene/main/scene_tree.cpp
msgid "Auto Accept Quit"
-msgstr ""
+msgstr "Aceitar Sair Automaticamente"
#: main/main.cpp scene/main/scene_tree.cpp
#, fuzzy
@@ -16761,15 +16558,15 @@ msgstr "Encaixar nos Lados do Nó"
#: main/main.cpp
msgid "Dynamic Fonts"
-msgstr ""
+msgstr "Fontes Dinâmicas"
#: main/main.cpp
msgid "Use Oversampling"
-msgstr ""
+msgstr "Utilizar Oversampling"
#: modules/bullet/register_types.cpp modules/bullet/space_bullet.cpp
msgid "Active Soft World"
-msgstr ""
+msgstr "Ativar Mundo Macio"
#: modules/csg/csg_gizmos.cpp
msgid "CSG"
@@ -16792,35 +16589,30 @@ msgid "Change Torus Outer Radius"
msgstr "Alterar Raio Externo do Toro"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Operation"
-msgstr "Opções"
+msgstr "Operação"
#: modules/csg/csg_shape.cpp
msgid "Calculate Tangents"
-msgstr ""
+msgstr "Calcular Tangentes"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Use Collision"
-msgstr "Colisão"
+msgstr "Usar Colisão"
#: modules/csg/csg_shape.cpp servers/physics_2d_server.cpp
-#, fuzzy
msgid "Collision Layer"
-msgstr "Modo Colisão"
+msgstr "Camada de Colisão"
#: modules/csg/csg_shape.cpp scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp
#: scene/3d/ray_cast.cpp scene/3d/spring_arm.cpp
#: scene/resources/navigation_mesh.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collision Mask"
-msgstr "Modo Colisão"
+msgstr "Máscara de Colisão"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Invert Faces"
-msgstr "Converter Maíusculas/Minúsculas"
+msgstr "Inverter Faces"
#: modules/csg/csg_shape.cpp scene/2d/navigation_agent_2d.cpp
#: scene/2d/navigation_obstacle_2d.cpp scene/3d/navigation_agent.cpp
@@ -16838,14 +16630,12 @@ msgid "Radial Segments"
msgstr "Segmentos Radiais"
#: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Rings"
-msgstr "Avisos"
+msgstr "Anéis"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Smooth Faces"
-msgstr "Passo suave"
+msgstr "Suavizar Faces"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16854,7 +16644,7 @@ msgstr "Mostrar Guias"
#: modules/csg/csg_shape.cpp
msgid "Cone"
-msgstr ""
+msgstr "Cone"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16868,27 +16658,25 @@ msgstr "Alterar Raio Externo do Toro"
#: modules/csg/csg_shape.cpp
msgid "Ring Sides"
-msgstr ""
+msgstr "Lados de Anel"
#: modules/csg/csg_shape.cpp scene/2d/collision_polygon_2d.cpp
#: scene/2d/light_occluder_2d.cpp scene/2d/polygon_2d.cpp
#: scene/3d/collision_polygon.cpp
-#, fuzzy
msgid "Polygon"
-msgstr "Polígonos"
+msgstr "Polígono"
#: modules/csg/csg_shape.cpp
msgid "Spin Degrees"
-msgstr ""
+msgstr "Graus de Rotação"
#: modules/csg/csg_shape.cpp
msgid "Spin Sides"
-msgstr ""
+msgstr "Lados de Rotação"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Node"
-msgstr "Colar Nós"
+msgstr "Caminho do Nó"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16897,11 +16685,11 @@ msgstr "Criar Vertex Interno"
#: modules/csg/csg_shape.cpp
msgid "Path Interval"
-msgstr ""
+msgstr "Intervalo de Caminho"
#: modules/csg/csg_shape.cpp
msgid "Path Simplify Angle"
-msgstr ""
+msgstr "Ângulo de Simplificação de Caminho"
#: modules/csg/csg_shape.cpp
msgid "Path Rotation"
@@ -16926,58 +16714,52 @@ msgid "Path Joined"
msgstr "Caminho Unido"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Compression Mode"
-msgstr "Modo Colisão"
+msgstr "Modo de Compressão"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Transfer Channel"
-msgstr "Alteração de Transformação"
+msgstr "Transferir Canal"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Channel Count"
-msgstr "Instância"
+msgstr "Quantidade de Canais"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Always Ordered"
-msgstr "Sempre Mostrar Grade"
+msgstr "Sempre Ordenado"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "Server Relay"
-msgstr ""
+msgstr "Retransmissor de Servidor"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "DTLS Verify"
-msgstr ""
+msgstr "Virificar DTLS"
#: modules/enet/networked_multiplayer_enet.cpp
msgid "DTLS Hostname"
-msgstr ""
+msgstr "Nome de Host DTLS"
#: modules/enet/networked_multiplayer_enet.cpp
-#, fuzzy
msgid "Use DTLS"
-msgstr "Use Encaixar"
+msgstr "Usar DTLS"
#: modules/fbx/editor_scene_importer_fbx.cpp
msgid "FBX"
-msgstr ""
+msgstr "FBX"
#: modules/fbx/editor_scene_importer_fbx.cpp
msgid "Use FBX"
-msgstr ""
+msgstr "Utilizar FBX"
#: modules/gdnative/gdnative.cpp
msgid "Config File"
msgstr "Arquivo de Configuração"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Load Once"
-msgstr "Carregar Recurso"
+msgstr "Carregar Apenas uma Vez"
#: modules/gdnative/gdnative.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
@@ -16990,9 +16772,8 @@ msgid "Symbol Prefix"
msgstr "Prefixo do Símbolo"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Reloadable"
-msgstr "Recarregar"
+msgstr "Recarregável"
#: modules/gdnative/gdnative.cpp
#: modules/gdnative/gdnative_library_singleton_editor.cpp
@@ -17057,9 +16838,8 @@ msgid "Script Class"
msgstr "Classe do Script"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Icon Path"
-msgstr "Habilitar"
+msgstr "Caminho para Ãcone"
#: modules/gdnative/register_types.cpp
msgid "GDNative"
@@ -17072,7 +16852,7 @@ msgstr "GDScript"
#: modules/gdscript/editor/gdscript_highlighter.cpp
msgid "Function Definition Color"
-msgstr ""
+msgstr "Cor de Definição de Função"
#: modules/gdscript/editor/gdscript_highlighter.cpp
#, fuzzy
@@ -17081,19 +16861,19 @@ msgstr "Copiar Caminho do Nó"
#: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp
msgid "Max Call Stack"
-msgstr ""
+msgstr "Tamanho Máximo da Pilha de Chamadas de Função"
#: modules/gdscript/gdscript.cpp
msgid "Treat Warnings As Errors"
-msgstr ""
+msgstr "Trate Alertas como Erros"
#: modules/gdscript/gdscript.cpp
msgid "Exclude Addons"
-msgstr ""
+msgstr "Excluir Addons"
#: modules/gdscript/gdscript.cpp
msgid "Autocomplete Setters And Getters"
-msgstr ""
+msgstr "Auto Completar Setters e Getters"
#: modules/gdscript/gdscript_functions.cpp
msgid "Step argument is zero!"
@@ -17144,11 +16924,11 @@ msgstr "Não foi possível resolver"
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Show Native Symbols In Editor"
-msgstr ""
+msgstr "Exibir Simbolos Nativos no Editor"
#: modules/gdscript/language_server/gdscript_language_server.cpp
msgid "Use Thread"
-msgstr ""
+msgstr "Utilize Thread"
#: modules/gltf/editor_scene_exporter_gltf_plugin.cpp
msgid "Export Mesh GLTF2"
@@ -17168,9 +16948,8 @@ msgid "Byte Offset"
msgstr "Deslocamento do Byte"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Component Type"
-msgstr "Componentes"
+msgstr "Tipo do Componente"
#: modules/gltf/gltf_accessor.cpp
#, fuzzy
@@ -17182,14 +16961,12 @@ msgid "Count"
msgstr "Quantidade"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Min"
-msgstr "MiB"
+msgstr "Min"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Max"
-msgstr "Misturar"
+msgstr "Max"
#: modules/gltf/gltf_accessor.cpp
#, fuzzy
@@ -17231,9 +17008,8 @@ msgid "Byte Stride"
msgstr ""
#: modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Indices"
-msgstr "Todos os dispositivos"
+msgstr "Ãndices"
#: modules/gltf/gltf_camera.cpp
msgid "FOV Size"
@@ -17256,19 +17032,17 @@ msgstr "Linear"
#: scene/resources/environment.cpp scene/resources/material.cpp
#: scene/resources/particles_material.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp
-#, fuzzy
msgid "Color"
-msgstr "Cores"
+msgstr "Cor"
#: modules/gltf/gltf_light.cpp scene/3d/reflection_probe.cpp
#: scene/resources/environment.cpp
msgid "Intensity"
-msgstr ""
+msgstr "Intensidade"
#: modules/gltf/gltf_light.cpp scene/2d/light_2d.cpp scene/3d/light.cpp
-#, fuzzy
msgid "Range"
-msgstr "Alterar"
+msgstr "Intervalo"
#: modules/gltf/gltf_light.cpp
msgid "Inner Cone Angle"
@@ -17299,35 +17073,31 @@ msgstr "Plataforma"
#: modules/gltf/gltf_node.cpp scene/3d/mesh_instance.cpp
msgid "Skin"
-msgstr ""
+msgstr "Skin"
#: modules/gltf/gltf_node.cpp scene/3d/spatial.cpp
-#, fuzzy
msgid "Translation"
-msgstr "Traduções"
+msgstr "Tradução"
#: modules/gltf/gltf_node.cpp
-#, fuzzy
msgid "Children"
-msgstr "Filhos Editáveis"
+msgstr "Filhos"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Joints"
-msgstr "Ponto"
+msgstr "Pontos"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_skin.cpp
msgid "Roots"
-msgstr ""
+msgstr "Raízes"
#: modules/gltf/gltf_skeleton.cpp modules/gltf/gltf_state.cpp
msgid "Unique Names"
-msgstr ""
+msgstr "Nomes Únicos"
#: modules/gltf/gltf_skeleton.cpp
-#, fuzzy
msgid "Godot Bone Node"
-msgstr "Nó TimeSeek"
+msgstr "Nó de Osso Godot"
#: modules/gltf/gltf_skin.cpp
#, fuzzy
@@ -17335,9 +17105,8 @@ msgid "Skin Root"
msgstr "Nova Raiz de Cena"
#: modules/gltf/gltf_skin.cpp
-#, fuzzy
msgid "Joints Original"
-msgstr "Origem do Foco"
+msgstr "Pontos Originais"
#: modules/gltf/gltf_skin.cpp
msgid "Inverse Binds"
@@ -17382,12 +17151,11 @@ msgstr ""
#: modules/gltf/gltf_state.cpp
msgid "Json"
-msgstr ""
+msgstr "Json"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Major Version"
-msgstr "Versão"
+msgstr "Versão Importante"
#: modules/gltf/gltf_state.cpp
#, fuzzy
@@ -17417,28 +17185,25 @@ msgid "Scene Name"
msgstr "Nome da Cena"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Root Nodes"
-msgstr "Nome do nó raiz"
+msgstr "Nós Raízes"
#: modules/gltf/gltf_state.cpp scene/2d/particles_2d.cpp
#: scene/gui/texture_button.cpp scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Textures"
-msgstr "Funcionalidades"
+msgstr "Texturas"
#: modules/gltf/gltf_state.cpp platform/uwp/export/export.cpp
msgid "Images"
-msgstr ""
+msgstr "Imagens"
#: modules/gltf/gltf_state.cpp
msgid "Cameras"
-msgstr ""
+msgstr "Câmeras"
#: modules/gltf/gltf_state.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Lights"
-msgstr "Luz"
+msgstr "Luzes"
#: modules/gltf/gltf_state.cpp
msgid "Unique Animation Names"
@@ -17449,9 +17214,8 @@ msgid "Skeletons"
msgstr "Esqueletos"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Skeleton To Node"
-msgstr "Selecione um Nó"
+msgstr "Esqueleto Para Nó"
#: modules/gltf/gltf_state.cpp
msgid "Animations"
@@ -17478,7 +17242,7 @@ msgstr "Faça mapas de luz"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
msgid "Cell"
-msgstr ""
+msgstr "Célula"
#: modules/gridmap/grid_map.cpp
#, fuzzy
@@ -17486,25 +17250,22 @@ msgid "Octant Size"
msgstr "Visão Frontal"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center X"
-msgstr "Centro"
+msgstr "Centro X"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Y"
-msgstr "Centro"
+msgstr "Centro Y"
#: modules/gridmap/grid_map.cpp
-#, fuzzy
msgid "Center Z"
-msgstr "Centro"
+msgstr "Centro Z"
#: modules/gridmap/grid_map.cpp scene/2d/collision_object_2d.cpp
#: scene/2d/tile_map.cpp scene/3d/collision_object.cpp scene/3d/soft_body.cpp
#: scene/resources/material.cpp
msgid "Mask"
-msgstr ""
+msgstr "Máscara"
#: modules/gridmap/grid_map.cpp scene/2d/tile_map.cpp
#, fuzzy
@@ -17515,9 +17276,8 @@ msgstr "Navegação"
#: scene/2d/navigation_agent_2d.cpp scene/2d/navigation_polygon.cpp
#: scene/2d/tile_map.cpp scene/3d/navigation.cpp scene/3d/navigation_agent.cpp
#: scene/3d/navigation_mesh_instance.cpp
-#, fuzzy
msgid "Navigation Layers"
-msgstr "Modo Navegação"
+msgstr "Camadas da Navegação"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Plane"
@@ -17819,7 +17579,7 @@ msgstr "Pronto!"
#: modules/opensimplex/noise_texture.cpp
msgid "Seamless"
-msgstr ""
+msgstr "Sem Emenda"
#: modules/opensimplex/noise_texture.cpp
msgid "As Normal Map"
@@ -17839,7 +17599,7 @@ msgstr "Deslocamento do Ruído"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Octaves"
-msgstr ""
+msgstr "Oitavas"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Period"
@@ -17856,7 +17616,7 @@ msgstr ""
#: modules/regex/regex.cpp
msgid "Subject"
-msgstr ""
+msgstr "Sujeito"
#: modules/regex/regex.cpp
#, fuzzy
@@ -18308,7 +18068,7 @@ msgstr "Iterador"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "for (elem) in (input):"
-msgstr ""
+msgstr "para (elem) em (input):"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Input type not iterable:"
@@ -18342,7 +18102,7 @@ msgstr "Switch"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "'input' is:"
-msgstr ""
+msgstr "'input' é:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Type Cast"
@@ -18594,7 +18354,7 @@ msgstr "Chamadas"
#: modules/visual_script/visual_script_nodes.cpp scene/gui/graph_node.cpp
msgid "Title"
-msgstr ""
+msgstr "Título"
#: modules/visual_script/visual_script_nodes.cpp
#, fuzzy
@@ -18673,7 +18433,7 @@ msgstr "Modo Prioridade"
#: modules/webrtc/webrtc_data_channel.h
msgid "WebRTC"
-msgstr ""
+msgstr "WebRTC"
#: modules/webrtc/webrtc_data_channel.h
#, fuzzy
@@ -18844,6 +18604,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 +18617,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"
@@ -18893,16 +18667,7 @@ msgstr "Inspecionar a Instância Anterior"
#: platform/android/export/export_plugin.cpp
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"
+msgstr "Código"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
@@ -18995,7 +18760,7 @@ msgstr "Interface de Usuário"
#: platform/android/export/export_plugin.cpp
msgid "Allow"
-msgstr ""
+msgstr "Permitir"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
@@ -19013,7 +18778,7 @@ msgstr "Expressão"
#: platform/android/export/export_plugin.cpp
msgid "Salt"
-msgstr ""
+msgstr "Sal"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -19155,14 +18920,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 +18940,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\"."
@@ -19283,10 +19073,8 @@ msgstr ""
"do projeto"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
-msgstr ""
-"Não foi possível exportar os arquivos do projeto ao projeto do gradle\n"
+msgstr "Não foi possível exportar os arquivos do projeto ao projeto do gradle"
#: platform/android/export/export_plugin.cpp
msgid "Could not write expansion package file!"
@@ -19370,19 +19158,19 @@ msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPhone 2436 X 1125"
-msgstr ""
+msgstr "IPhone 2436 X 1125"
#: platform/iphone/export/export.cpp
msgid "iPhone 2208 X 1242"
-msgstr ""
+msgstr "iPhone 2208 X 1242"
#: platform/iphone/export/export.cpp
msgid "iPad 1024 X 768"
-msgstr ""
+msgstr "iPad 1024 X 768"
#: platform/iphone/export/export.cpp
msgid "iPad 2048 X 1536"
-msgstr ""
+msgstr "iPad 2048 X 1536"
#: platform/iphone/export/export.cpp
msgid "Portrait Launch Screens"
@@ -19390,31 +19178,31 @@ msgstr ""
#: platform/iphone/export/export.cpp
msgid "iPhone 640 X 960"
-msgstr ""
+msgstr "iPhone 640 X 960"
#: platform/iphone/export/export.cpp
msgid "iPhone 640 X 1136"
-msgstr ""
+msgstr "iPhone 640 X 1136"
#: platform/iphone/export/export.cpp
msgid "iPhone 750 X 1334"
-msgstr ""
+msgstr "iPhone 750 X 1334"
#: platform/iphone/export/export.cpp
msgid "iPhone 1125 X 2436"
-msgstr ""
+msgstr "iPhone 1125 X 2436"
#: platform/iphone/export/export.cpp
msgid "iPad 768 X 1024"
-msgstr ""
+msgstr "iPad 768 X 1024"
#: platform/iphone/export/export.cpp
msgid "iPad 1536 X 2048"
-msgstr ""
+msgstr "iPad 1536 X 2048"
#: platform/iphone/export/export.cpp
msgid "iPhone 1242 X 2208"
-msgstr ""
+msgstr "iPhone 1242 X 2208"
#: platform/iphone/export/export.cpp
msgid "App Store Team ID"
@@ -19451,7 +19239,7 @@ msgstr ""
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
msgid "Info"
-msgstr ""
+msgstr "Informação"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
msgid "Identifier"
@@ -19521,23 +19309,23 @@ msgstr "Descrições da Propriedade"
#: platform/iphone/export/export.cpp
msgid "iPhone 120 X 120"
-msgstr ""
+msgstr "iPhone 120 X 120"
#: platform/iphone/export/export.cpp
msgid "iPhone 180 X 180"
-msgstr ""
+msgstr "iPhone 180 X 180"
#: platform/iphone/export/export.cpp
msgid "iPad 76 X 76"
-msgstr ""
+msgstr "iPad 76 X 76"
#: platform/iphone/export/export.cpp
msgid "iPad 152 X 152"
-msgstr ""
+msgstr "iPad 152 X 152"
#: platform/iphone/export/export.cpp
msgid "iPad 167 X 167"
-msgstr ""
+msgstr "iPad 167 X 167"
#: platform/iphone/export/export.cpp
msgid "App Store 1024 X 1024"
@@ -19621,14 +19409,12 @@ msgid "Could not open template for export: \"%s\"."
msgstr "Não foi possível abrir o modelo para exportação: \"%s\"."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Invalid export template: \"%s\"."
-msgstr "Template de exportação inválido:"
+msgstr "Template de exportação inválido: \"%s\"."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not write file: \"%s\"."
-msgstr "Não foi possível escrever o arquivo:"
+msgstr "Não foi possível escrever o arquivo: \"%s\"."
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
#, fuzzy
@@ -19641,7 +19427,7 @@ msgstr "Não foi possível ler o arquivo: \"%s\"."
#: platform/javascript/export/export.cpp
msgid "PWA"
-msgstr ""
+msgstr "PWA"
#: platform/javascript/export/export.cpp
msgid "Variant"
@@ -19659,15 +19445,15 @@ msgstr "Expressão"
#: platform/javascript/export/export.cpp
msgid "For Desktop"
-msgstr ""
+msgstr "Para Desktop"
#: platform/javascript/export/export.cpp
msgid "For Mobile"
-msgstr ""
+msgstr "Para Mobile"
#: platform/javascript/export/export.cpp
msgid "HTML"
-msgstr ""
+msgstr "HTML"
#: platform/javascript/export/export.cpp
#, fuzzy
@@ -19688,8 +19474,9 @@ msgid "Canvas Resize Policy"
msgstr ""
#: platform/javascript/export/export.cpp
+#, fuzzy
msgid "Focus Canvas On Start"
-msgstr ""
+msgstr "Focar Canvas ao Iniciar"
#: platform/javascript/export/export.cpp
#, fuzzy
@@ -19698,11 +19485,11 @@ msgstr "Filtrar sinais"
#: platform/javascript/export/export.cpp
msgid "Progressive Web App"
-msgstr ""
+msgstr "Progressive Web App"
#: platform/javascript/export/export.cpp
msgid "Offline Page"
-msgstr ""
+msgstr "Página Offline"
#: platform/javascript/export/export.cpp
msgid "Icon 144 X 144"
@@ -19721,9 +19508,8 @@ msgid "Could not read HTML shell: \"%s\"."
msgstr "Não foi possível ler o shell HTML: \"%s\"."
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not create HTTP server directory: %s."
-msgstr "Não foi possível criar o diretório do servidor HTTP:"
+msgstr "Não foi possível criar o diretório do servidor HTTP: \"%s\"."
#: platform/javascript/export/export.cpp
msgid "Error starting HTTP server: %d."
@@ -19731,7 +19517,7 @@ msgstr "Erro ao iniciar o servidor HTTP: %d."
#: platform/javascript/export/export.cpp
msgid "Web"
-msgstr ""
+msgstr "Web"
#: platform/javascript/export/export.cpp
msgid "HTTP Host"
@@ -19748,7 +19534,7 @@ msgstr "Use Encaixar"
#: platform/javascript/export/export.cpp
msgid "SSL Key"
-msgstr ""
+msgstr "Chave SSL"
#: platform/osx/export/codesign.cpp
msgid "Can't get filesystem access."
@@ -19788,7 +19574,7 @@ msgstr "Caminho base inválido."
#: platform/osx/export/codesign.cpp
msgid "Already signed!"
-msgstr ""
+msgstr "Já assinado!"
#: platform/osx/export/codesign.cpp
#, fuzzy
@@ -19828,7 +19614,7 @@ msgstr ""
#: platform/osx/export/codesign.cpp
msgid "Unknown object type."
-msgstr ""
+msgstr "Tipo de objeto desconhecido."
#: platform/osx/export/export.cpp
msgid "App Category"
@@ -19836,7 +19622,7 @@ msgstr "Categoria do Aplicativo"
#: platform/osx/export/export.cpp
msgid "High Res"
-msgstr ""
+msgstr "Alta Resolução"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19916,7 +19702,7 @@ msgstr "Recortar Nós"
#: platform/osx/export/export.cpp
msgid "Allow JIT Code Execution"
-msgstr ""
+msgstr "Permitir Execução de Código JIT"
#: platform/osx/export/export.cpp
msgid "Allow Unsigned Executable Memory"
@@ -19938,7 +19724,7 @@ msgstr "Adicionar Entrada"
#: platform/osx/export/export.cpp
msgid "Address Book"
-msgstr ""
+msgstr "Contatos"
#: platform/osx/export/export.cpp
msgid "Calendars"
@@ -19980,7 +19766,7 @@ msgstr "Dispositivo"
#: platform/osx/export/export.cpp
msgid "Device Bluetooth"
-msgstr ""
+msgstr "Bluetooth do Dispositivo"
#: platform/osx/export/export.cpp
#, fuzzy
@@ -20052,6 +19838,8 @@ msgid ""
"You can check progress manually by opening a Terminal and running the "
"following command:"
msgstr ""
+"Você pode verificar o progresso manualmente abrindo um Terminal e rodando o "
+"seguinte comando:"
#: platform/osx/export/export.cpp
msgid ""
@@ -20081,6 +19869,8 @@ msgid ""
"Could not start codesign executable, make sure Xcode command line tools are "
"installed."
msgstr ""
+"Não foi possível iniciar o executável codesign, tenha certeza que as "
+"utilidades de linha de comando do Xcode estão instaladas."
#: platform/osx/export/export.cpp platform/windows/export/export.cpp
#, fuzzy
@@ -20141,7 +19931,7 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "Making PKG"
-msgstr ""
+msgstr "Criando PKG"
#: platform/osx/export/export.cpp
msgid ""
@@ -20155,7 +19945,7 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "Making DMG"
-msgstr ""
+msgstr "Criando DMG"
#: platform/osx/export/export.cpp
msgid "Code signing DMG"
@@ -20163,7 +19953,7 @@ msgstr ""
#: platform/osx/export/export.cpp
msgid "Making ZIP"
-msgstr ""
+msgstr "Criando ZIP"
#: platform/osx/export/export.cpp
msgid ""
@@ -20326,7 +20116,7 @@ msgstr "Nome Curto"
#: platform/uwp/export/export.cpp
msgid "Publisher"
-msgstr ""
+msgstr "Publicadora"
#: platform/uwp/export/export.cpp
msgid "Publisher Display Name"
@@ -20374,7 +20164,7 @@ msgstr "Revisão"
#: platform/uwp/export/export.cpp
msgid "Landscape"
-msgstr ""
+msgstr "Paisagem"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20383,11 +20173,11 @@ msgstr "Inverter Horizontalmente"
#: platform/uwp/export/export.cpp
msgid "Landscape Flipped"
-msgstr ""
+msgstr "Paisagem Invertido"
#: platform/uwp/export/export.cpp
msgid "Portrait Flipped"
-msgstr ""
+msgstr "Retrato Invertido"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20489,7 +20279,7 @@ msgstr "Dimensões inválidas da tela de abertura (deve ser 620x300)."
#: platform/uwp/export/export.cpp
msgid "UWP"
-msgstr ""
+msgstr "UWP"
#: platform/uwp/export/export.cpp platform/windows/export/export.cpp
#, fuzzy
@@ -20506,13 +20296,13 @@ msgid "Debug Algorithm"
msgstr "Depurador"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Failed to rename temporary file \"%s\"."
-msgstr "Não é possível remover o arquivo temporário:"
+msgstr "Falha ao renomear arquivo temporário \"%s\"."
#: platform/windows/export/export.cpp
+#, fuzzy
msgid "Identity Type"
-msgstr ""
+msgstr "Tipo de Identidade"
#: platform/windows/export/export.cpp
msgid "Timestamp Server URL"
@@ -20552,7 +20342,7 @@ msgstr "Descrição"
#: platform/windows/export/export.cpp
msgid "Trademarks"
-msgstr ""
+msgstr "Marca Registrada (Trademarks)"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20571,15 +20361,15 @@ msgstr "O keystore não foi encontrado, não foi possível exportar."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Extensão inválida."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20602,15 +20392,15 @@ msgstr "Nome Inválido."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Extensão inválida."
#: platform/windows/export/export.cpp
msgid "Failed to remove temporary file \"%s\"."
@@ -20658,7 +20448,7 @@ msgstr "Nova Janela"
#: platform/windows/export/export.cpp
msgid "Rcedit"
-msgstr ""
+msgstr "Rcedit"
#: platform/windows/export/export.cpp
msgid "Osslsigncode"
@@ -20848,7 +20638,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
@@ -20857,7 +20647,7 @@ msgstr "Modo de Movimentação"
#: scene/2d/camera_2d.cpp
msgid "Limit"
-msgstr ""
+msgstr "Limite"
#: scene/2d/camera_2d.cpp scene/gui/control.cpp scene/gui/nine_patch_rect.cpp
#: scene/resources/style_box.cpp scene/resources/texture.cpp
@@ -21157,7 +20947,7 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Drawing"
-msgstr ""
+msgstr "Desenhando"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -21168,7 +20958,7 @@ msgstr "Projetos Locais"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
msgid "Draw Order"
-msgstr ""
+msgstr "Ordem de Desenho"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21225,7 +21015,7 @@ msgstr "Velocidade"
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
msgid "Angular Velocity"
-msgstr ""
+msgstr "Velocidade Angular"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21294,7 +21084,7 @@ msgstr "Dvidir Curva"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp scene/3d/light.cpp
#: scene/resources/particles_material.cpp
msgid "Angle"
-msgstr ""
+msgstr "Ângulo"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21420,7 +21210,7 @@ msgstr ""
#: scene/2d/joints_2d.cpp scene/resources/animation.cpp
#: scene/resources/ray_shape.cpp scene/resources/segment_shape_2d.cpp
msgid "Length"
-msgstr ""
+msgstr "Comprimento"
#: scene/2d/joints_2d.cpp
#, fuzzy
@@ -21456,7 +21246,7 @@ msgstr "Região da Textura"
#: scene/3d/light.cpp scene/resources/environment.cpp
#: scene/resources/material.cpp scene/resources/sky.cpp
msgid "Energy"
-msgstr ""
+msgstr "Energia"
#: scene/2d/light_2d.cpp
msgid "Z Min"
@@ -21534,7 +21324,7 @@ msgstr "Padrão"
#: scene/2d/line_2d.cpp scene/resources/texture.cpp
msgid "Fill"
-msgstr ""
+msgstr "Preencher"
#: scene/2d/line_2d.cpp scene/resources/texture.cpp
#, fuzzy
@@ -21605,6 +21395,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 +21408,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 +21438,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."
@@ -21680,7 +21480,7 @@ msgstr "Viagem"
msgid "Rotation Degrees"
msgstr "Graus de Rotação"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr "Rotação Global"
@@ -21869,7 +21669,7 @@ msgstr ""
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Mass"
-msgstr ""
+msgstr "Massa"
#: scene/2d/physics_body_2d.cpp
msgid "Inertia"
@@ -21918,7 +21718,7 @@ msgstr "Úmido"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Angular"
-msgstr ""
+msgstr "Angular"
#: scene/2d/physics_body_2d.cpp
msgid "Applied Forces"
@@ -22031,15 +21831,15 @@ msgstr "Criar Nó Shader"
#: scene/2d/ray_cast_2d.cpp scene/3d/ray_cast.cpp
msgid "Collide With"
-msgstr ""
+msgstr "Colidir com"
#: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp
msgid "Areas"
-msgstr ""
+msgstr "Ãreas"
#: scene/2d/ray_cast_2d.cpp scene/3d/camera.cpp scene/3d/ray_cast.cpp
msgid "Bodies"
-msgstr ""
+msgstr "Corpos"
#: scene/2d/remote_transform_2d.cpp
msgid "Path property must point to a valid Node2D node to work."
@@ -22281,15 +22081,15 @@ msgstr "Nó de Animação"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Unit dB"
-msgstr ""
+msgstr "Unidade dB"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Unit Size"
-msgstr ""
+msgstr "Tamanho da Unidade"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Max dB"
-msgstr ""
+msgstr "Max dB"
#: scene/3d/audio_stream_player_3d.cpp
msgid "Out Of Range Mode"
@@ -22337,7 +22137,7 @@ msgstr "Empacotando"
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/reflection_probe.cpp
msgid "Interior"
-msgstr ""
+msgstr "Interior"
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
@@ -22388,7 +22188,7 @@ msgstr "Usar Redutor de Ruído"
#: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp
msgid "Use HDR"
-msgstr ""
+msgstr "Usar HDR"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22487,7 +22287,7 @@ msgstr "Mais próximo"
#: scene/3d/camera.cpp
msgid "Far"
-msgstr ""
+msgstr "Longe"
#: 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
@@ -22739,9 +22539,8 @@ msgid "Font"
msgstr "Fontes"
#: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Horizontal Alignment"
-msgstr "Horizontal:"
+msgstr "Alinhamento Horizontal"
#: scene/3d/label_3d.cpp
#, fuzzy
@@ -22852,6 +22651,8 @@ msgid ""
"be removed in a future version. Use 'NavigationServer.map_get_path()' "
"instead."
msgstr ""
+"O nó 'Navigation' e 'Navigation.get_simple_path()' estão depreciados e serão "
+"removidos em versões futuras. Use 'NavigationServer.map_get_path()' no lugar."
#: scene/3d/navigation.cpp scene/resources/curve.cpp
#, fuzzy
@@ -23106,15 +22907,15 @@ msgstr "Animação"
#: scene/3d/physics_body.cpp
msgid "X"
-msgstr ""
+msgstr "X"
#: scene/3d/physics_body.cpp
msgid "Y"
-msgstr ""
+msgstr "Y"
#: scene/3d/physics_body.cpp
msgid "Z"
-msgstr ""
+msgstr "Z"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23431,7 +23232,7 @@ msgstr "Depurador"
#: scene/3d/ray_cast.cpp scene/resources/style_box.cpp
msgid "Thickness"
-msgstr ""
+msgstr "Espessura"
#: scene/3d/reflection_probe.cpp scene/main/viewport.cpp
#, fuzzy
@@ -23538,7 +23339,7 @@ msgstr "Só Deve existir um RoomManager na SceneTree."
#: scene/3d/room_manager.cpp
msgid "Main"
-msgstr ""
+msgstr "Principal"
#: scene/3d/room_manager.cpp scene/animation/animation_blend_tree.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
@@ -23758,8 +23559,13 @@ msgstr ""
"Altere o tamanho em formas de colisão de crianças."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Manter Transformação Global"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
-msgstr ""
+msgstr "Matriz"
#: scene/3d/spatial.cpp
#, fuzzy
@@ -23777,7 +23583,7 @@ msgstr ""
#: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp
msgid "Opacity"
-msgstr ""
+msgstr "Opacidade"
#: scene/3d/sprite_3d.cpp scene/resources/material.cpp
msgid "Transparent"
@@ -23876,9 +23682,8 @@ msgid "Cast Shadow"
msgstr "Criar Nó Shader"
#: scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Extra Cull Margin"
-msgstr "Argumentos de Chamada Extras:"
+msgstr "Margem de Descarte Extra"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -23900,9 +23705,8 @@ msgstr ""
#: scene/3d/visual_instance.cpp scene/animation/skeleton_ik.cpp
#: scene/resources/material.cpp
-#, fuzzy
msgid "Min Distance"
-msgstr "Escolha uma Distância:"
+msgstr "Distância Mínima"
#: scene/3d/visual_instance.cpp
msgid "Min Hysteresis"
@@ -23949,33 +23753,28 @@ msgid "Mix Mode"
msgstr "Nó Mix"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Fadein Time"
-msgstr "Tempo do X-Fade (s):"
+msgstr "Tempo de Esmaecer de Entrada"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Fadeout Time"
-msgstr "Tempo do X-Fade (s):"
+msgstr "Tempo de Esmaecer de Saída"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Auto Restart"
-msgstr "Reinício Automático:"
+msgstr "Reinício Automático"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Autorestart"
-msgstr "Reinício Automático:"
+msgstr "Reinício Automático"
#: scene/animation/animation_blend_tree.cpp
msgid "Delay"
-msgstr ""
+msgstr "Atraso"
#: scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Random Delay"
-msgstr "Inclinação aleatória:"
+msgstr "Atraso Aleatório"
#: scene/animation/animation_blend_tree.cpp
#, fuzzy
@@ -23999,9 +23798,8 @@ msgstr "Adicionar porta de entrada"
#: scene/animation/animation_blend_tree.cpp
#: scene/animation/animation_node_state_machine.cpp
-#, fuzzy
msgid "Xfade Time"
-msgstr "Tempo do X-Fade (s):"
+msgstr "Tempo do Esmaecer Cruzado"
#: scene/animation/animation_node_state_machine.cpp
#, fuzzy
@@ -24034,7 +23832,7 @@ msgstr "Adicionar Animação"
#: scene/animation/animation_player.cpp
msgid "Reset On Save"
-msgstr ""
+msgstr "Redefinir ao Salvar"
#: scene/animation/animation_player.cpp
#, fuzzy
@@ -24047,9 +23845,8 @@ msgid "Current Animation Position"
msgstr "Adicionar ponto de Animação"
#: scene/animation/animation_player.cpp
-#, fuzzy
msgid "Playback Options"
-msgstr "Opções da Classe:"
+msgstr "Opções de Playback"
#: scene/animation/animation_player.cpp
#, fuzzy
@@ -24092,9 +23889,8 @@ msgid "The AnimationPlayer root node is not a valid node."
msgstr "O nó raiz do AnimationPlayer não é um nó válido."
#: scene/animation/animation_tree.cpp
-#, fuzzy
msgid "Tree Root"
-msgstr "Criar nó raiz:"
+msgstr "Nó Raiz"
#: scene/animation/animation_tree.cpp
#, fuzzy
@@ -24204,7 +24000,7 @@ msgstr "Modo de Seleção"
#: scene/gui/aspect_ratio_container.cpp scene/gui/box_container.cpp
msgid "Alignment"
-msgstr ""
+msgstr "Alinhamento"
#: scene/gui/base_button.cpp
#, fuzzy
@@ -24242,11 +24038,11 @@ msgstr "Copiar Texto"
#: scene/gui/button.cpp scene/gui/label.cpp scene/gui/line_edit.cpp
#: scene/gui/spin_box.cpp
msgid "Align"
-msgstr ""
+msgstr "Alinhar"
#: scene/gui/button.cpp
msgid "Icon Align"
-msgstr ""
+msgstr "Alinhamento do Ãcone"
#: scene/gui/button.cpp
#, fuzzy
@@ -24350,14 +24146,12 @@ msgid "Grow Direction"
msgstr "Direções"
#: scene/gui/control.cpp scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Min Size"
-msgstr "Tamanho do Contorno:"
+msgstr "Tamanho Mínimo"
#: scene/gui/control.cpp
-#, fuzzy
msgid "Pivot Offset"
-msgstr "Deslocamento da Grade:"
+msgstr "Deslocamento do Pivô"
#: scene/gui/control.cpp
#, fuzzy
@@ -24405,7 +24199,7 @@ msgstr "Anterior"
#: scene/gui/control.cpp
msgid "Mouse"
-msgstr ""
+msgstr "Mouse"
#: scene/gui/control.cpp
msgid "Default Cursor Shape"
@@ -24431,7 +24225,7 @@ msgstr "Propriedades do Tema"
#: scene/gui/dialogs.cpp
msgid "Window Title"
-msgstr ""
+msgstr "Título da Janela"
#: scene/gui/dialogs.cpp
#, fuzzy
@@ -24465,14 +24259,12 @@ msgid "Right Disconnects"
msgstr "Desconectar"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Scroll Offset"
-msgstr "Deslocamento da Grade:"
+msgstr "Deslocamento da Rolagem"
#: scene/gui/graph_edit.cpp
-#, fuzzy
msgid "Snap Distance"
-msgstr "Escolha uma Distância:"
+msgstr "Distância de Encaixe"
#: scene/gui/graph_edit.cpp
#, fuzzy
@@ -24497,7 +24289,7 @@ msgstr "Mostrar Ossos"
#: scene/gui/graph_edit.cpp scene/gui/text_edit.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Minimap"
-msgstr ""
+msgstr "Mini-Mapa"
#: scene/gui/graph_edit.cpp
msgid "Enable grid minimap."
@@ -24570,9 +24362,8 @@ msgid "Fixed Column Width"
msgstr ""
#: scene/gui/item_list.cpp
-#, fuzzy
msgid "Icon Scale"
-msgstr "Escala aleatória:"
+msgstr "Escala de Ãcone"
#: scene/gui/item_list.cpp
#, fuzzy
@@ -24585,9 +24376,8 @@ msgid "V Align"
msgstr "Atribuir"
#: scene/gui/label.cpp scene/gui/rich_text_label.cpp
-#, fuzzy
msgid "Visible Characters"
-msgstr "Caracteres válidos:"
+msgstr "Caracteres Visiveis"
#: scene/gui/label.cpp scene/gui/rich_text_label.cpp
#, fuzzy
@@ -24611,9 +24401,8 @@ msgid "Secret"
msgstr ""
#: scene/gui/line_edit.cpp
-#, fuzzy
msgid "Secret Character"
-msgstr "Caracteres válidos:"
+msgstr "Caracteres Secretos"
#: scene/gui/line_edit.cpp
msgid "Expand To Text Length"
@@ -24670,20 +24459,19 @@ msgstr ""
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Caret"
-msgstr ""
+msgstr "Circunflexo"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink"
-msgstr ""
+msgstr "Piscar"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Blink Speed"
-msgstr "Velocidade:"
+msgstr "Velocidade de Piscar"
#: scene/gui/link_button.cpp
msgid "Underline"
-msgstr ""
+msgstr "Sublinhado"
#: scene/gui/menu_button.cpp
#, fuzzy
@@ -24766,9 +24554,8 @@ msgid "Allow Search"
msgstr "Pesquisar"
#: scene/gui/progress_bar.cpp
-#, fuzzy
msgid "Percent"
-msgstr "Recente:"
+msgstr "Porcentagem"
#: scene/gui/range.cpp
msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0."
@@ -24828,9 +24615,8 @@ msgid "Absolute Index"
msgstr "Auto Recuar"
#: scene/gui/rich_text_effect.cpp
-#, fuzzy
msgid "Elapsed Time"
-msgstr "Tempos de Mistura:"
+msgstr "Tempo Decorrido"
#: scene/gui/rich_text_effect.cpp
#, fuzzy
@@ -24838,9 +24624,8 @@ msgid "Env"
msgstr "Fim"
#: scene/gui/rich_text_effect.cpp
-#, fuzzy
msgid "Character"
-msgstr "Caracteres válidos:"
+msgstr "Caractere"
#: scene/gui/rich_text_label.cpp
msgid "BBCode"
@@ -24851,9 +24636,8 @@ msgid "Meta Underlined"
msgstr ""
#: scene/gui/rich_text_label.cpp
-#, fuzzy
msgid "Tab Size"
-msgstr "Tamanho:"
+msgstr "Tamanho da Tabulação"
#: scene/gui/rich_text_label.cpp
#, fuzzy
@@ -24874,9 +24658,8 @@ msgid "Selection Enabled"
msgstr "Selecionar Apenas"
#: scene/gui/rich_text_label.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Override Selected Font Color"
-msgstr "Configurar Perfil Selecionado:"
+msgstr "Sobrescrever Cor da Fonte Selecionada"
#: scene/gui/rich_text_label.cpp
#, fuzzy
@@ -24904,9 +24687,8 @@ msgid "Follow Focus"
msgstr "Popular Superfície"
#: scene/gui/scroll_container.cpp
-#, fuzzy
msgid "Horizontal Enabled"
-msgstr "Horizontal:"
+msgstr "Horizontal Habilitado"
#: scene/gui/scroll_container.cpp
#, fuzzy
@@ -24927,24 +24709,20 @@ msgid "Tick Count"
msgstr "Escolher Cor"
#: scene/gui/slider.cpp
-#, fuzzy
msgid "Ticks On Borders"
-msgstr "Renomear pasta:"
+msgstr "Pontos Nas Bordas"
#: scene/gui/spin_box.cpp
-#, fuzzy
msgid "Prefix"
-msgstr "Prefixo:"
+msgstr "Prefixo"
#: scene/gui/spin_box.cpp
-#, fuzzy
msgid "Suffix"
-msgstr "Sufixo:"
+msgstr "Sufixo"
#: scene/gui/split_container.cpp
-#, fuzzy
msgid "Split Offset"
-msgstr "Deslocamento da Grade:"
+msgstr "Deslocamento de Divisão"
#: scene/gui/split_container.cpp scene/gui/tree.cpp
#, fuzzy
@@ -24961,9 +24739,8 @@ msgid "Tab Align"
msgstr ""
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
-#, fuzzy
msgid "Current Tab"
-msgstr "Atual:"
+msgstr "Aba Atual"
#: scene/gui/tab_container.cpp
#, fuzzy
@@ -25005,9 +24782,13 @@ msgid "Breakpoint Gutter"
msgstr "Pular Breakpoints"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Fold Gutter"
-msgstr "Pasta:"
+msgstr "Espaçamento de Dobra"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Selecionar Apenas"
#: scene/gui/text_edit.cpp
#, fuzzy
@@ -25020,19 +24801,16 @@ msgid "Wrap Enabled"
msgstr "Habilitar"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Scroll Vertical"
-msgstr "Vertical:"
+msgstr "Scroll Vertical"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Scroll Horizontal"
-msgstr "Horizontal:"
+msgstr "Scroll Horizontal"
#: scene/gui/text_edit.cpp
-#, fuzzy
msgid "Draw"
-msgstr "Chamadas de Desenho:"
+msgstr "Desenhar"
#: scene/gui/text_edit.cpp
#, fuzzy
@@ -25090,9 +24868,8 @@ msgid "Progress Offset"
msgstr ""
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Fill Mode"
-msgstr "Modo Panorâmico:"
+msgstr "Modo de Preenchimento"
#: scene/gui/texture_progress.cpp scene/resources/material.cpp
msgid "Tint"
@@ -25160,9 +24937,8 @@ msgid "Hide Folding"
msgstr "Botão Desativado"
#: scene/gui/tree.cpp
-#, fuzzy
msgid "Hide Root"
-msgstr "Criar nó raiz:"
+msgstr "Esconder Raiz"
#: scene/gui/tree.cpp
msgid "Drop Mode Flags"
@@ -25175,7 +24951,7 @@ msgstr "Adicionar Faixa"
#: scene/gui/video_player.cpp scene/main/scene_tree.cpp scene/main/timer.cpp
msgid "Paused"
-msgstr ""
+msgstr "Pausado"
#: scene/gui/video_player.cpp
#, fuzzy
@@ -25260,19 +25036,16 @@ msgid "Filename"
msgstr "Renomear"
#: scene/main/node.cpp
-#, fuzzy
msgid "Owner"
-msgstr "Donos De:"
+msgstr "Dono"
#: scene/main/node.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Multiplayer"
-msgstr "Definir Múltiplos:"
+msgstr "Multijogador"
#: scene/main/node.cpp
-#, fuzzy
msgid "Custom Multiplayer"
-msgstr "Definir Múltiplos:"
+msgstr "Multijogador Personalizado"
#: scene/main/node.cpp
#, fuzzy
@@ -25305,17 +25078,16 @@ msgstr "Nova Raiz de Cena"
#: scene/main/scene_tree.cpp
msgid "Root"
-msgstr ""
+msgstr "Raiz"
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Multiplayer Poll"
-msgstr "Definir Múltiplos:"
+msgstr ""
#: scene/main/scene_tree.cpp scene/resources/mesh_library.cpp
#: scene/resources/shape_2d.cpp
msgid "Shapes"
-msgstr ""
+msgstr "Formas"
#: scene/main/scene_tree.cpp
msgid "Shape Color"
@@ -25349,9 +25121,8 @@ msgid "Reflections"
msgstr "Reflexões"
#: scene/main/scene_tree.cpp
-#, fuzzy
msgid "Atlas Size"
-msgstr "Tamanho do Contorno:"
+msgstr "Tamanho do Atlas"
#: scene/main/scene_tree.cpp
msgid "Atlas Subdiv"
@@ -25363,7 +25134,7 @@ msgstr ""
#: scene/main/scene_tree.cpp
msgid "Use FXAA"
-msgstr ""
+msgstr "Usar FXAA"
#: scene/main/scene_tree.cpp
msgid "Use Debanding"
@@ -25371,7 +25142,7 @@ msgstr ""
#: scene/main/scene_tree.cpp scene/main/viewport.cpp
msgid "HDR"
-msgstr ""
+msgstr "HDR"
#: scene/main/scene_tree.cpp scene/main/viewport.cpp
msgid "Use 32 BPC Depth"
@@ -25409,9 +25180,8 @@ msgstr ""
"Timer para tempos de espera muito baixos."
#: scene/main/timer.cpp
-#, fuzzy
msgid "Autostart"
-msgstr "Reinício Automático:"
+msgstr "Início Automático"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25420,19 +25190,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,10 +25197,19 @@ msgstr ""
"dimensões para renderizar algo."
#: scene/main/viewport.cpp
-msgid "ARVR"
+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"
+
+#: scene/main/viewport.cpp
#, fuzzy
msgid "Size Override Stretch"
msgstr "Sobrescrever Item"
@@ -25454,11 +25220,11 @@ msgstr ""
#: scene/main/viewport.cpp scene/resources/world_2d.cpp
msgid "World"
-msgstr ""
+msgstr "Mundo"
#: scene/main/viewport.cpp
msgid "World 2D"
-msgstr ""
+msgstr "Mundo 2D"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25472,7 +25238,7 @@ msgstr "Alterar Valor da Entrada"
#: scene/main/viewport.cpp
msgid "FXAA"
-msgstr ""
+msgstr "FXAA"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25490,8 +25256,9 @@ msgid "Keep 3D Linear"
msgstr "Linear Esquerda"
#: scene/main/viewport.cpp
+#, fuzzy
msgid "Render Direct To Screen"
-msgstr ""
+msgstr "Renderizar Diretamente para a Tela"
#: scene/main/viewport.cpp
#, fuzzy
@@ -25499,9 +25266,8 @@ msgid "Debug Draw"
msgstr "Depuração"
#: scene/main/viewport.cpp
-#, fuzzy
msgid "Render Target"
-msgstr "Renderizador:"
+msgstr "Alvo do Renderizador"
#: scene/main/viewport.cpp
msgid "V Flip"
@@ -25609,7 +25375,7 @@ msgstr "Navegação"
#: scene/register_scene_types.cpp
msgid "Use hiDPI"
-msgstr ""
+msgstr "Usar hiDPI"
#: scene/register_scene_types.cpp
#, fuzzy
@@ -25629,12 +25395,11 @@ msgstr "Nó Mix"
#: scene/resources/audio_stream_sample.cpp
msgid "Stereo"
-msgstr ""
+msgstr "Stereo"
#: scene/resources/concave_polygon_shape_2d.cpp
-#, fuzzy
msgid "Segments"
-msgstr "Argumentos da Cena Principal:"
+msgstr "Segmentos"
#: scene/resources/curve.cpp
#, fuzzy
@@ -25647,7 +25412,7 @@ msgstr ""
#: scene/resources/default_theme/default_theme.cpp
msgid "Panel"
-msgstr ""
+msgstr "Painel"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25675,9 +25440,8 @@ msgid "Font Color Disabled"
msgstr "Corte Desabilitado"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "H Separation"
-msgstr "Separação:"
+msgstr "Separação Horizontal"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25686,7 +25450,7 @@ msgstr "Loop da Animação"
#: scene/resources/default_theme/default_theme.cpp
msgid "Arrow"
-msgstr ""
+msgstr "Seta"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25765,14 +25529,12 @@ msgid "Font Outline Modulate"
msgstr "Forçar Módulo Branco"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Shadow Offset X"
-msgstr "Deslocamento da Grade X:"
+msgstr "Deslocamento da Sombra em X"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Shadow Offset Y"
-msgstr "Deslocamento da Grade Y:"
+msgstr "Deslocamento da Sombra em Y"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25830,14 +25592,12 @@ msgid "Space"
msgstr "Cena Principal"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Folded"
-msgstr "Pasta:"
+msgstr "Dobrado"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Fold"
-msgstr "Pasta:"
+msgstr "Dobrar"
#: scene/resources/default_theme/default_theme.cpp
msgid "Font Color Readonly"
@@ -26005,9 +25765,8 @@ msgid "Font Color Separator"
msgstr "Separador de Cor da Fonte"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "V Separation"
-msgstr "Separação:"
+msgstr "Separação Vertical"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26060,9 +25819,8 @@ msgid "Close Offset"
msgstr "Deslocamento do Ruído"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Port Offset"
-msgstr "Deslocamento da Grade:"
+msgstr "Deslocamento de Porta"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26172,14 +25930,12 @@ msgid "Draw Guides"
msgstr "Mostrar Guias"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Scroll Border"
-msgstr "Vertical:"
+msgstr "Borda da Barra de Rolagem"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Scroll Speed"
-msgstr "Deslocamento da Grade:"
+msgstr "Velocidade de Rolagem"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26187,9 +25943,8 @@ msgid "Icon Margin"
msgstr "Definir Margem"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Line Separation"
-msgstr "Separação:"
+msgstr "Separação de Linha"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26208,7 +25963,7 @@ msgstr "Item Desativado"
#: scene/resources/default_theme/default_theme.cpp
msgid "Menu"
-msgstr ""
+msgstr "Menu"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26249,9 +26004,8 @@ msgid "Large"
msgstr "Destino"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Folder"
-msgstr "Pasta:"
+msgstr "Pasta"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26343,7 +26097,7 @@ msgstr "Cena Principal"
#: scene/resources/default_theme/default_theme.cpp
msgid "Bold Italics Font"
-msgstr ""
+msgstr "Fonte Negrito Itálica"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26351,14 +26105,12 @@ msgid "Mono Font"
msgstr "Cena Principal"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Table H Separation"
-msgstr "Separação:"
+msgstr "Separação Horizontal da Tabela"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Table V Separation"
-msgstr "Separação:"
+msgstr "Separação Vertical da Tabela"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26387,11 +26139,11 @@ msgstr "Auto Fatiar"
#: scene/resources/default_theme/default_theme.cpp
msgid "Minus"
-msgstr ""
+msgstr "Menos"
#: scene/resources/default_theme/default_theme.cpp
msgid "More"
-msgstr ""
+msgstr "Mais"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26451,9 +26203,8 @@ msgid "Font Path"
msgstr "Habilitar"
#: scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Outline Size"
-msgstr "Tamanho do Contorno:"
+msgstr "Tamanho do Contorno"
#: scene/resources/dynamic_font.cpp
#, fuzzy
@@ -26466,14 +26217,12 @@ msgid "Use Mipmaps"
msgstr "Sinais"
#: scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Extra Spacing"
-msgstr "Opções Extra:"
+msgstr "Espaçamento Extra"
#: scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Char"
-msgstr "Caracteres válidos:"
+msgstr "Caractere"
#: scene/resources/dynamic_font.cpp
#, fuzzy
@@ -26486,7 +26235,7 @@ msgstr ""
#: scene/resources/environment.cpp scene/resources/sky.cpp
msgid "Sky"
-msgstr ""
+msgstr "Céu"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26499,9 +26248,8 @@ msgid "Sky Orientation"
msgstr "Documentação Online"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sky Rotation"
-msgstr "Passo de Rotação:"
+msgstr "Rotação do Céu"
#: scene/resources/environment.cpp
msgid "Sky Rotation Degrees"
@@ -26530,14 +26278,12 @@ msgid "Fog"
msgstr "Névoa"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sun Color"
-msgstr "Armazenando Arquivo:"
+msgstr "Cor do Sol"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sun Amount"
-msgstr "Quantidade:"
+msgstr "Quantidade do Sol"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26601,7 +26347,7 @@ msgstr "Exportação"
#: scene/resources/environment.cpp
msgid "White"
-msgstr ""
+msgstr "Branco"
#: scene/resources/environment.cpp
msgid "Auto Exposure"
@@ -26626,14 +26372,12 @@ msgid "Max Steps"
msgstr "Passo"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Fade In"
-msgstr "[i]Fade In[/i](s):"
+msgstr "Esmaecer de Entrada"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Fade Out"
-msgstr "[i]Fade Out[/i](s):"
+msgstr "Esmaecer de Saída"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26646,12 +26390,11 @@ msgstr "Rugosidade"
#: scene/resources/environment.cpp
msgid "SSAO"
-msgstr ""
+msgstr "SSAO"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Radius 2"
-msgstr "Raio:"
+msgstr "Raio 2"
#: scene/resources/environment.cpp
msgid "Intensity 2"
@@ -26669,7 +26412,7 @@ msgstr "Depuração do Canal UV"
#: scene/resources/environment.cpp
msgid "Blur"
-msgstr ""
+msgstr "Blur"
#: scene/resources/environment.cpp
msgid "Edge Sharpness"
@@ -26680,9 +26423,8 @@ msgid "DOF Far Blur"
msgstr ""
#: scene/resources/environment.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Distance"
-msgstr "Escolha uma Distância:"
+msgstr "Distância"
#: scene/resources/environment.cpp
msgid "Transition"
@@ -26765,18 +26507,16 @@ msgid "Brightness"
msgstr "Luz"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Saturation"
-msgstr "Separação:"
+msgstr "Separação"
#: scene/resources/environment.cpp
msgid "Color Correction"
msgstr "Correção de Cor"
#: scene/resources/font.cpp
-#, fuzzy
msgid "Ascent"
-msgstr "Recente:"
+msgstr "Subida"
#: scene/resources/font.cpp
#, fuzzy
@@ -26789,9 +26529,8 @@ msgid "Raw Data"
msgstr "Profundidade"
#: scene/resources/gradient.cpp
-#, fuzzy
msgid "Offsets"
-msgstr "Deslocamento:"
+msgstr "Deslocamentos"
#: scene/resources/height_map_shape.cpp
msgid "Map Width"
@@ -26871,7 +26610,7 @@ msgstr ""
#: scene/resources/material.cpp
msgid "Is sRGB"
-msgstr ""
+msgstr "É sRGB"
#: scene/resources/material.cpp servers/visual_server.cpp
msgid "Parameters"
@@ -26917,9 +26656,8 @@ msgid "Grow"
msgstr "Crescer"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Grow Amount"
-msgstr "Quantidade:"
+msgstr "Quantidade de Crescimento"
#: scene/resources/material.cpp
msgid "Use Alpha Scissor"
@@ -27074,7 +26812,7 @@ msgstr "Faça mapas de luz"
#: scene/resources/mesh.cpp scene/resources/primitive_meshes.cpp
msgid "Custom AABB"
-msgstr ""
+msgstr "AABB Personalizado"
#: scene/resources/mesh_library.cpp
#, fuzzy
@@ -27108,9 +26846,8 @@ msgid "Visible Instance Count"
msgstr ""
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Sampling"
-msgstr "Escala:"
+msgstr "Mostragem"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27131,12 +26868,11 @@ msgstr "Origem do Nome do Grupo"
#: scene/resources/navigation_mesh.cpp
msgid "Cells"
-msgstr ""
+msgstr "Células"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Agents"
-msgstr "Argumentos da Cena Principal:"
+msgstr "Agentes"
#: scene/resources/navigation_mesh.cpp
msgid "Max Climb"
@@ -27158,7 +26894,7 @@ msgstr "Fundir a partir de Cena"
#: scene/resources/navigation_mesh.cpp
msgid "Edges"
-msgstr ""
+msgstr "Arestas"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27175,9 +26911,8 @@ msgid "Details"
msgstr "Detalhe"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Sample Distance"
-msgstr "Escolha uma Distância:"
+msgstr "Distância de Amostra"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27247,9 +26982,8 @@ msgid "Color Modifier"
msgstr "Modificador de velocidade lenta da Visão Livre"
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Point Texture"
-msgstr "Pontos de Emissão:"
+msgstr "Textura de Ponto"
#: scene/resources/particles_material.cpp
msgid "Normal Texture"
@@ -27266,9 +27000,8 @@ msgid "Point Count"
msgstr "Adicionar porta de entrada"
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Scale Random"
-msgstr "Razão de Escala:"
+msgstr "Randomização de Escala"
#: scene/resources/particles_material.cpp
#, fuzzy
@@ -27284,9 +27017,8 @@ msgid "Absorbent"
msgstr ""
#: scene/resources/plane_shape.cpp
-#, fuzzy
msgid "Plane"
-msgstr "Plano:"
+msgstr "Plano"
#: scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -27310,9 +27042,8 @@ msgid "Subdivide Depth"
msgstr ""
#: scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Top Radius"
-msgstr "Raio:"
+msgstr "Raio do Topo"
#: scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -27361,13 +27092,12 @@ msgid "Bone"
msgstr "Ossos"
#: scene/resources/sky.cpp
-#, fuzzy
msgid "Radiance Size"
-msgstr "Tamanho do Contorno:"
+msgstr "Tamanho da Radiância"
#: scene/resources/sky.cpp
msgid "Panorama"
-msgstr ""
+msgstr "Panorama"
#: scene/resources/sky.cpp
#, fuzzy
@@ -27375,9 +27105,8 @@ msgid "Top Color"
msgstr "Próximo Chão"
#: scene/resources/sky.cpp
-#, fuzzy
msgid "Horizon Color"
-msgstr "Armazenando Arquivo:"
+msgstr "Cor do Horizonte"
#: scene/resources/sky.cpp
#, fuzzy
@@ -27401,7 +27130,7 @@ msgstr "Substituir"
#: scene/resources/sky.cpp
msgid "Longitude"
-msgstr ""
+msgstr "Longitude"
#: scene/resources/sky.cpp
msgid "Angle Min"
@@ -27436,7 +27165,7 @@ msgstr ""
#: scene/resources/style_box.cpp
msgid "Anti Aliasing"
-msgstr ""
+msgstr "Anti Aliasing"
#: scene/resources/style_box.cpp
msgid "Grow Begin"
@@ -27486,9 +27215,8 @@ msgid "Lossy Storage Quality"
msgstr "Capturar"
#: scene/resources/texture.cpp
-#, fuzzy
msgid "From"
-msgstr "Modo Panorâmico:"
+msgstr "À Partir de"
#: scene/resources/texture.cpp
#, fuzzy
@@ -27692,9 +27420,8 @@ msgid "Audio Stream"
msgstr "Item Rádio"
#: servers/audio/audio_stream.cpp
-#, fuzzy
msgid "Random Pitch"
-msgstr "Inclinação aleatória:"
+msgstr "Timbre Aleatório"
#: servers/audio/effects/audio_effect_capture.cpp
#: servers/audio/effects/audio_effect_spectrum_analyzer.cpp
@@ -27710,21 +27437,21 @@ msgstr ""
#: servers/audio/effects/audio_effect_delay.cpp
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Dry"
-msgstr ""
+msgstr "Seco"
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Wet"
-msgstr ""
+msgstr "Molhado"
#: servers/audio/effects/audio_effect_chorus.cpp
msgid "Voice"
-msgstr ""
+msgstr "Voz"
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_delay.cpp
msgid "Delay (ms)"
-msgstr ""
+msgstr "Atraso (ms)"
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_phaser.cpp
@@ -27739,23 +27466,22 @@ msgstr "Profundidade"
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_delay.cpp
msgid "Level dB"
-msgstr ""
+msgstr "Nível dB"
#: servers/audio/effects/audio_effect_chorus.cpp
#: servers/audio/effects/audio_effect_delay.cpp
#: servers/audio/effects/audio_effect_panner.cpp
-#, fuzzy
msgid "Pan"
-msgstr "Plano:"
+msgstr "Panoramizar"
#: servers/audio/effects/audio_effect_compressor.cpp
#: servers/audio/effects/audio_effect_filter.cpp
msgid "Gain"
-msgstr ""
+msgstr "Ganho"
#: servers/audio/effects/audio_effect_compressor.cpp
msgid "Attack (µs)"
-msgstr ""
+msgstr "Ataque (µs)"
#: servers/audio/effects/audio_effect_compressor.cpp
#, fuzzy
@@ -27792,7 +27518,7 @@ msgstr "Ignorar"
#: servers/audio/effects/audio_effect_distortion.cpp
msgid "Pre Gain"
-msgstr ""
+msgstr "Pré Ganho"
#: servers/audio/effects/audio_effect_distortion.cpp
msgid "Keep Hf Hz"
@@ -27800,7 +27526,7 @@ msgstr ""
#: servers/audio/effects/audio_effect_distortion.cpp
msgid "Drive"
-msgstr ""
+msgstr "Drive"
#: servers/audio/effects/audio_effect_distortion.cpp
#, fuzzy
@@ -27842,21 +27568,20 @@ msgstr ""
#: servers/audio/effects/audio_effect_pitch_shift.cpp
#: servers/audio/effects/audio_effect_spectrum_analyzer.cpp
-#, fuzzy
msgid "FFT Size"
-msgstr "Tamanho:"
+msgstr "Tamanho FFT"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Predelay"
-msgstr ""
+msgstr "Pré Atraso"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Msec"
-msgstr ""
+msgstr "Msec"
#: servers/audio/effects/audio_effect_reverb.cpp
msgid "Room Size"
-msgstr ""
+msgstr "Tamanho da Sala"
#: servers/audio/effects/audio_effect_reverb.cpp
#, fuzzy
@@ -27939,9 +27664,8 @@ msgid "Time Before Sleep"
msgstr ""
#: servers/physics_2d/physics_2d_server_sw.cpp
-#, fuzzy
msgid "BP Hash Table Size"
-msgstr "Tamanho:"
+msgstr "Tamanho da \"BP Hash Table\""
#: servers/physics_2d/physics_2d_server_sw.cpp
msgid "Large Object Surface Threshold In Cells"
@@ -28314,7 +28038,7 @@ msgstr ""
#: servers/visual_server.cpp
msgid "Compatibility"
-msgstr ""
+msgstr "Compatibilidade"
#: servers/visual_server.cpp
msgid "Disable Half Float"
diff --git a/editor/translations/ro.po b/editor/translations/ro.po
index ddc340697c..a78712c6ba 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
@@ -472,6 +477,10 @@ msgid "Pressure"
msgstr "Presiune"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Relativ"
@@ -2177,14 +2186,15 @@ msgstr "Favorite:"
msgid "Recent:"
msgstr "Recent:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Cautați:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Potriviri:"
@@ -2244,8 +2254,8 @@ msgstr "Cautați Înlocuitor Resursă:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2826,8 +2836,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Copiază Selecția"
#: editor/editor_export.cpp
#, fuzzy
@@ -5619,6 +5630,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -12010,6 +12030,11 @@ msgid "New Animation"
msgstr "Animație"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Metode de filtrare"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18991,6 +19016,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 +19029,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 +19077,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 +19322,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 +19336,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20690,15 +20740,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Trebuie să utilizaţi o extensie valida."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20720,15 +20770,15 @@ msgstr "Nume nevalid."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Trebuie să utilizaţi o extensie valida."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20968,7 +21018,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 +21747,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 +21760,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 ""
@@ -21770,7 +21830,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr "Pas Rotație:"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Permanent"
@@ -23795,6 +23855,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Anim Schimbare transformare"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25004,6 +25069,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 +25476,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..1df1d87308 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -85,7 +85,7 @@
# kyanukovich <ianu0001@algonquinlive.com>, 2020.
# Ron788 <ustinov200511@gmail.com>, 2020.
# Daniel <dan.ef1999@gmail.com>, 2020.
-# NeoLan Qu <it.bulla@mail.ru>, 2020.
+# NeoLan Qu <it.bulla@mail.ru>, 2020, 2022.
# Nikita Epifanov <nikgreens@protonmail.com>, 2020.
# Cube Show <griiv.06@gmail.com>, 2020.
# Roman Tolkachyov <roman@tolkachyov.name>, 2020.
@@ -115,13 +115,17 @@
# 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.
+# Maksim Marchukov <mar.maksim63@gmail.com>, 2022.
+# Slava Beloglazov <slavathedeveloper@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-12 13:19+0000\n"
-"Last-Translator: FuzzMix <fmwolfiechad@gmail.com>\n"
+"PO-Revision-Date: 2022-07-26 01:55+0000\n"
+"Last-Translator: NeoLan Qu <it.bulla@mail.ru>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
"Language: ru\n"
@@ -130,7 +134,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.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -469,14 +473,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 +505,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
@@ -554,6 +561,10 @@ msgid "Pressure"
msgstr "Давление"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr "Перо Инвертировано"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "ОтноÑительный"
@@ -1234,9 +1245,8 @@ msgid "Value"
msgstr "Значение"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Arg Count"
-msgstr "КоличеÑтво"
+msgstr "КоличеÑтво Ðргументов"
#: editor/animation_track_editor.cpp main/main.cpp
#: modules/mono/mono_gd/gd_mono.cpp
@@ -1427,24 +1437,22 @@ msgid "(Invalid, expected type: %s)"
msgstr "(Ðеверный, ожидаемый тип: %s)"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing:"
-msgstr "Переход В-ИЗ"
+msgstr "Переход В-ИЗ:"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "In-Handle:"
-msgstr "Задать обработчик"
+msgstr "Обработчик Ввода:"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "Out-Handle:"
-msgstr "Задать обработчик"
+msgstr "Обработчик Вывода:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Stream:"
-msgstr "Поток"
+msgstr "Поток:"
#: editor/animation_track_editor.cpp
msgid "Start (s):"
@@ -2205,14 +2213,15 @@ msgstr "Избранное:"
msgid "Recent:"
msgstr "Ðедавнее:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "ПоиÑк:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "СовпадениÑ:"
@@ -2272,8 +2281,8 @@ msgstr "Ðайти заменÑемый реÑурÑ:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2282,7 +2291,7 @@ msgstr "Открыть"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "Владельцы: %s (Ð’Ñего: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2333,7 +2342,7 @@ msgstr "ИÑправить завиÑимоÑти"
#: editor/dependency_editor.cpp
msgid "Errors loading!"
-msgstr "Ошибки загрузки!"
+msgstr "Ошибки при загрузке!"
#: editor/dependency_editor.cpp
msgid "Permanently delete %d item(s)? (No undo!)"
@@ -2840,17 +2849,16 @@ msgstr "Выбрать"
#: editor/editor_export.cpp
msgid "Project export for platform:"
-msgstr ""
+msgstr "ЭкÑпорт проекта Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ñ‹:"
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
-msgstr "Завершать пути файлов"
+msgid "Completed with warnings."
+msgstr "Завершено Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°Ð¼Ð¸."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Completed successfully."
-msgstr "Пакет уÑпешно уÑтановлен!"
+msgstr "Завершено без ошибок."
#: editor/editor_export.cpp
#, fuzzy
@@ -2870,9 +2878,8 @@ msgid "Packing"
msgstr "Упаковывание"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Save PCK"
-msgstr "Сохранить как"
+msgstr "Сохранить PCK"
#: editor/editor_export.cpp
#, fuzzy
@@ -2899,16 +2906,16 @@ msgid ""
"Target platform requires 'ETC' texture compression for GLES2. Enable 'Import "
"Etc' in Project Settings."
msgstr ""
-"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует Ñжатие текÑтур «ETC» Ð´Ð»Ñ GLES2. Включите «Import "
-"Etc» в ÐаÑтройках проекта."
+"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует Ñжатие текÑтур «ETC» Ð´Ð»Ñ GLES2. Включите "
+"«Импортировать Etc» в ÐаÑтройках Проекта."
#: editor/editor_export.cpp
msgid ""
"Target platform requires 'ETC2' texture compression for GLES3. Enable "
"'Import Etc 2' in Project Settings."
msgstr ""
-"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует компреÑÑию текÑтур «ETC2» Ð´Ð»Ñ GLES2. Включите "
-"«Import Etc 2» в ÐаÑтройках проекта."
+"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует компреÑÑию текÑтур «ETC2» Ð´Ð»Ñ GLES3. Включите "
+"«Импортировать Etc 2» в ÐаÑтройках Проекта."
#: editor/editor_export.cpp
msgid ""
@@ -2918,8 +2925,8 @@ msgid ""
"Enabled'."
msgstr ""
"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует ÑÐ¶Ð°Ñ‚Ð¸Ñ Ñ‚ÐµÐºÑтур «ETC» Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ°Ñ‚Ð° драйвера к GLES2.\n"
-"Включите «Import Etc» в ÐаÑтройках проекта или отключите «Driver Fallback "
-"Enabled»."
+"Включите «Импортировать Etc» в ÐаÑтройках проекта или отключите «Driver "
+"Fallback Enabled»."
#: editor/editor_export.cpp
msgid ""
@@ -2935,7 +2942,8 @@ msgid ""
"Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings."
msgstr ""
"Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° требует компреÑÑию текÑтур «ETC2» или «PVRTC» Ð´Ð»Ñ GLES3. "
-"Включите «Import Etc 2» или «Import Pvrtc» в ÐаÑтройках проекта."
+"Включите «Импортировать Etc 2» или «Импортировать Pvrtc» в ÐаÑтройках "
+"Проекта."
#: editor/editor_export.cpp
msgid ""
@@ -5588,6 +5596,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "ÐÐ°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ Ð¿Ð¾ иÑтории дополнительными кнопками мыши"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Выделение Ñетки"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Внешний вид"
@@ -7241,12 +7258,17 @@ 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: Ð’Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ñ‚ÐµÐºÑтура иÑпользуетÑÑ ÐºÐ°Ðº карта нормалей в 3D. Включено краÑно-"
+"зелёное Ñжатие текÑтуры Ð´Ð»Ñ ÑƒÐ¼ÐµÐ½ÑŒÑˆÐµÐ½Ð¸Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð°Ð¼Ñти (Ñиний канал "
+"отбраÑываетÑÑ)."
#: 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: ТекÑтура иÑпользуетÑÑ Ð² 3D. Включена фильтрациÑ, повторение и Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ "
+"mipmap-карт, а также VRAM Ñжатие текÑтуры."
#: editor/import/resource_importer_texture.cpp
msgid "2D, Detect 3D"
@@ -9530,7 +9552,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
@@ -11683,6 +11705,11 @@ msgid "New Animation"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ñ"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Фильтр методов"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "СкороÑть:"
@@ -15345,7 +15372,7 @@ msgstr "Сделать локальным"
#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp
msgid "Another node already uses this unique name in the scene."
-msgstr "Ð˜Ð¼Ñ ÑƒÐ·Ð»Ð° уже иÑпользовано в Ñцене"
+msgstr "Данное уникальное Ð¸Ð¼Ñ ÑƒÐ¶Ðµ иÑпользовано у другого узла в Ñцене."
#: editor/scene_tree_dock.cpp
msgid "Enable Scene Unique Name"
@@ -15778,9 +15805,8 @@ msgid "Attach Node Script"
msgstr "Прикрепить Ñкрипт"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Remote %s:"
-msgstr "Удаленный "
+msgstr "Удаленный %s:"
#: editor/script_editor_debugger.cpp
msgid "Bytes:"
@@ -16758,7 +16784,7 @@ msgstr "Выключен GDNative Ñинглтон"
#: modules/gdnative/gdnative_library_singleton_editor.cpp
#, fuzzy
msgid "Libraries:"
-msgstr "Библиотеки: "
+msgstr "Библиотеки:"
#: modules/gdnative/nativescript/nativescript.cpp
msgid "Class Name"
@@ -17034,7 +17060,7 @@ msgstr "СфокуÑироватьÑÑ Ð½Ð° начале координат"
#: modules/gltf/gltf_skin.cpp
msgid "Inverse Binds"
-msgstr ""
+msgstr "Инвертировать СвÑзи"
#: modules/gltf/gltf_skin.cpp
#, fuzzy
@@ -17043,11 +17069,11 @@ msgstr "Передвинуть ÑуÑтав"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Bone I"
-msgstr ""
+msgstr "Узел I к КоÑти I"
#: modules/gltf/gltf_skin.cpp
msgid "Joint I To Name"
-msgstr ""
+msgstr "Узел I К Имени"
#: modules/gltf/gltf_skin.cpp
msgid "Godot Skin"
@@ -17055,7 +17081,7 @@ msgstr "Скин Godot"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Img"
-msgstr ""
+msgstr "РаÑÑеÑнное изображение"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Factor"
@@ -17063,7 +17089,7 @@ msgstr "Диффузный фактор"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Gloss Factor"
-msgstr ""
+msgstr "КоÑфф. ГлÑнца"
#: modules/gltf/gltf_spec_gloss.cpp
#, fuzzy
@@ -17612,9 +17638,8 @@ msgstr ""
"памÑти! ИÑправьте узел пожалуйÑта."
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Node returned an invalid sequence output:"
-msgstr "Узел вернул ошибочную поÑледовательноÑть: "
+msgstr "Узел вернул ошибочный вывод поÑледовательноÑти:"
#: modules/visual_script/visual_script.cpp
msgid "Found sequence bit but not the node in the stack, report bug!"
@@ -17624,7 +17649,7 @@ msgstr ""
#: modules/visual_script/visual_script.cpp
#, fuzzy
msgid "Stack overflow with stack depth:"
-msgstr "Переполнение Ñтека Ñ Ð³Ð»ÑƒÐ±Ð¸Ð½Ð¾Ð¹ Ñтека: "
+msgstr "Переполнение Ñтека Ñ Ð³Ð»ÑƒÐ±Ð¸Ð½Ð¾Ð¹ Ñтека:"
#: modules/visual_script/visual_script.cpp
msgid "Visual Script"
@@ -17993,7 +18018,7 @@ msgstr "Ð´Ð»Ñ (Ñлемент) в (вход):"
#: modules/visual_script/visual_script_flow_control.cpp
#, fuzzy
msgid "Input type not iterable:"
-msgstr "Входной тип не итерируемый: "
+msgstr "Входной тип не итерируемый:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Iterator became invalid"
@@ -18002,7 +18027,7 @@ msgstr "Итератор Ñтал недейÑтвительным"
#: modules/visual_script/visual_script_flow_control.cpp
#, fuzzy
msgid "Iterator became invalid:"
-msgstr "Итератор Ñтал недейÑтвительным: "
+msgstr "Итератор Ñтал недейÑтвительным:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Sequence"
@@ -18156,14 +18181,12 @@ msgid "Operator"
msgstr "Оператор"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Invalid argument of type:"
-msgstr ": ÐедопуÑтимый аргумент типа: "
+msgstr "ÐедопуÑтимый аргумент типа:"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Invalid arguments:"
-msgstr ": ÐедопуÑтимые аргументы: "
+msgstr "ÐедопуÑтимые аргументы:"
#: modules/visual_script/visual_script_nodes.cpp
msgid "a if cond, else b"
@@ -18174,14 +18197,13 @@ msgid "Var Name"
msgstr "Ð˜Ð¼Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "VariableGet not found in script:"
-msgstr "VariableGet не найден в Ñкрипте: "
+msgstr "VariableGet отÑутÑтвует в Ñкрипте:"
#: modules/visual_script/visual_script_nodes.cpp
#, fuzzy
msgid "VariableSet not found in script:"
-msgstr "VariableSet не найден в Ñкрипте: "
+msgstr "VariableSet не найден в Ñкрипте:"
#: modules/visual_script/visual_script_nodes.cpp
msgid "Preload"
@@ -18318,7 +18340,7 @@ msgstr "Режим запиÑи"
#: modules/webrtc/webrtc_data_channel.h
msgid "WebRTC"
-msgstr ""
+msgstr "WebRTC"
#: modules/webrtc/webrtc_data_channel.h
#, fuzzy
@@ -18334,36 +18356,32 @@ msgid "Trusted SSL Certificate"
msgstr "Доверенный SSL-Ñертификат"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Client"
-msgstr "Сетевой узел"
+msgstr "Клиент WebSocket"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "Max In Buffer (KB)"
-msgstr "МакÑимальный размер (КБ)"
+msgstr "МакÑимальный Входной Буфер (КБ)"
#: modules/websocket/websocket_macros.h
msgid "Max In Packets"
-msgstr ""
+msgstr "МакÑимальные ВходÑщие Пакеты"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "Max Out Buffer (KB)"
-msgstr "МакÑимальный размер (КБ)"
+msgstr "МакÑимальный Буфер Вывода (КБ)"
#: modules/websocket/websocket_macros.h
msgid "Max Out Packets"
-msgstr ""
+msgstr "МакÑимальный Вывод Пакетов"
#: modules/websocket/websocket_macros.h
-#, fuzzy
msgid "WebSocket Server"
-msgstr "Сетевой узел"
+msgstr "Сервер WebSocket"
#: modules/websocket/websocket_server.cpp
msgid "Bind IP"
-msgstr ""
+msgstr "ПривÑзать IP"
#: modules/websocket/websocket_server.cpp
msgid "Private Key"
@@ -18387,14 +18405,12 @@ msgid "Session Mode"
msgstr "Режим ÑеÑÑии"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Required Features"
-msgstr "Ðеобходимые функции"
+msgstr "Ðеобходимые Компоненты"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Optional Features"
-msgstr "Дополнительные функции"
+msgstr "Дополнительные Компоненты"
#: modules/webxr/webxr_interface.cpp
msgid "Requested Reference Space Types"
@@ -18405,9 +18421,8 @@ msgid "Reference Space Type"
msgstr ""
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Visibility State"
-msgstr "Переключить видимоÑть"
+msgstr "ВидимоÑть"
#: modules/webxr/webxr_interface.cpp
#, fuzzy
@@ -18415,9 +18430,8 @@ msgid "Bounds Geometry"
msgstr "Повторить"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "XR Standard Mapping"
-msgstr "Ð˜Ð½Ñ‚ÐµÐ»Ð»ÐµÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¸Ð²Ñзка"
+msgstr "Стандартный Маппинг XR"
#: platform/android/export/export.cpp
msgid "Android SDK Path"
@@ -18446,19 +18460,19 @@ msgstr "Выключение ADB при выходе"
#: platform/android/export/export_plugin.cpp
msgid "Launcher Icons"
-msgstr ""
+msgstr "Иконки Лаунчера"
#: platform/android/export/export_plugin.cpp
msgid "Main 192 X 192"
-msgstr ""
+msgstr "ОÑÐ½Ð¾Ð²Ð½Ð°Ñ 192 X 192"
#: platform/android/export/export_plugin.cpp
msgid "Adaptive Foreground 432 X 432"
-msgstr ""
+msgstr "Ðдаптивный Передний Фон 432 X 432"
#: platform/android/export/export_plugin.cpp
msgid "Adaptive Background 432 X 432"
-msgstr ""
+msgstr "Ðдаптивный Задний Фон 432 X 432"
#: platform/android/export/export_plugin.cpp
msgid "Package name is missing."
@@ -18485,24 +18499,32 @@ 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 "ИÑпользовать ÑобÑтвенную директорию данных пользователÑ"
+msgstr "ИÑпользовать ÐаÑтраиваемую Сборку"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Export Format"
-msgstr "Путь ÑкÑпорта"
+msgstr "Формат ЭкÑпорта"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "Min 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"
-msgstr "Добавить поле архитектуры"
+msgstr "Ðрхитектуры"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Keystore"
-msgstr "Отладочное хранилище ключей"
+msgstr "Хранилище ключей"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18526,41 +18548,27 @@ msgstr "Пароль"
#: platform/android/export/export_plugin.cpp
msgid "One Click Deploy"
-msgstr ""
+msgstr "Развёртывание в Один Клик"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Clear Previous Install"
-msgstr "ОÑмотреть предыдущий ÑкземплÑÑ€"
+msgstr "ОчиÑтить Предыдущую УÑтановку"
#: platform/android/export/export_plugin.cpp
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"
-msgstr "Упаковывание"
+msgstr "Пакет"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Unique Name"
-msgstr "Уникальные имена"
+msgstr "Уникальное ИмÑ"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Signed"
-msgstr "Сигнал"
+msgstr "ПодпиÑано"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18800,15 +18808,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 +18830,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
@@ -18845,14 +18878,12 @@ msgid "Code Signing"
msgstr "ПодпиÑÑŒ кода DMG"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"'apksigner' could not be found. Please check that the command is available "
"in the Android SDK build-tools directory. The resulting %s is unsigned."
msgstr ""
-"Ðе удалоÑÑŒ найти команду «apksigner».\n"
-"ПожалуйÑта, проверьте наличие программы в каталоге Android SDK build-tools.\n"
-"Результат %s не подпиÑан."
+"Ðе удалоÑÑŒ найти «apksigner». ПожалуйÑта, убедитеÑÑŒ в наличии команды в "
+"каталоге build-tools Android SDK. Результирующий %s не подпиÑан."
#: platform/android/export/export_plugin.cpp
msgid "Signing debug %s..."
@@ -18867,9 +18898,8 @@ msgid "Could not find keystore, unable to export."
msgstr "Ðе удалоÑÑŒ найти хранилище ключей, невозможно ÑкÑпортировать."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not start apksigner executable."
-msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить подпроцеÑÑ!"
+msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить иÑполнÑемый файл apksigner."
#: platform/android/export/export_plugin.cpp
msgid "'apksigner' returned with error #%d"
@@ -18900,9 +18930,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension."
msgstr "Ðеверное Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°! Android APK требует раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ *.apk."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Unsupported export format!"
-msgstr "Ðеподдерживаемый формат ÑкÑпорта!\n"
+msgstr "Ðеподдерживаемый формат ÑкÑпорта!"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -18913,15 +18942,12 @@ msgstr ""
"не ÑущеÑтвует. ПожалуйÑта, переуÑтановите из меню «Проект»."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Android build version mismatch: Template installed: %s, Godot version: %s. "
"Please reinstall Android build template from 'Project' menu."
msgstr ""
-"ÐеÑоответÑтвие верÑии Ñборки Android:\n"
-" УÑтановлен шаблон: %s\n"
-" ВерÑÐ¸Ñ Godot: %s\n"
-"ПожалуйÑта, переуÑтановите шаблон Ñборки Android из меню «Проект»."
+"ÐеÑоответÑтвие верÑии Ñборки Android: УÑтановлен шаблон: %s, верÑÐ¸Ñ Godot: "
+"%s. ПожалуйÑта, переуÑтановите шаблон Ñборки Android из меню «Проект»."
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18931,9 +18957,8 @@ msgstr ""
"Ðевозможно перезапиÑать файлы res://android/build/res/*.xml Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ проекта"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
-msgstr "Ðе удалоÑÑŒ ÑкÑпортировать файлы проекта в проект gradle\n"
+msgstr "Ðе удалоÑÑŒ ÑкÑпортировать файлы проекта в проект gradle."
#: platform/android/export/export_plugin.cpp
msgid "Could not write expansion package file!"
@@ -18944,14 +18969,13 @@ msgid "Building Android Project (gradle)"
msgstr "Сборка проекта Android (gradle)"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Building of Android project failed, check output for the error. "
"Alternatively visit docs.godotengine.org for Android build documentation."
msgstr ""
-"Сборка проекта Android не удалаÑÑŒ, проверьте вывод на ошибки.\n"
-"Также поÑетите docs.godotengine.org Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ð¸ по Ñборке "
-"Android."
+"Сборка Android проекта не удалаÑÑŒ, проверьте вывод на ошибки. Ð’Ñ‹ также "
+"можете поÑетить docs.godotengine.org Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ð¸ по Ñборке "
+"Ð´Ð»Ñ Android."
#: platform/android/export/export_plugin.cpp
msgid "Moving output"
@@ -18975,22 +18999,18 @@ msgid "Creating APK..."
msgstr "Создание APK..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not find template APK to export: \"%s\"."
-msgstr ""
-"Ðе удалоÑÑŒ найти шаблон APK Ð´Ð»Ñ ÑкÑпорта:\n"
-"%s"
+msgstr "Ðе удалоÑÑŒ найти шаблон APK Ð´Ð»Ñ ÑкÑпорта: \"%s\"."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Missing libraries in the export template for the selected architectures: %s. "
"Please build a template with all required libraries, or uncheck the missing "
"architectures in the export preset."
msgstr ""
-"Ð’ шаблоне ÑкÑпорта отÑутÑтвуют библиотеки Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… архитектур: %s.\n"
-"ПожалуйÑта, Ñоздайте шаблон Ñо вÑеми необходимыми библиотеками или Ñнимите "
-"флажки Ñ Ð¾Ñ‚ÑутÑтвующих архитектур в преÑете ÑкÑпорта."
+"Ð’ шаблоне ÑкÑпорта отÑутÑтвуют библиотеки Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… архитектур: %s. "
+"ПожалуйÑта, поÑтройте шаблон Ñо вÑеми необходимыми библиотеками или Ñнимите "
+"флажки Ñ Ð¾Ñ‚ÑутÑтвующих архитектур в предуÑтановках ÑкÑпорта."
#: platform/android/export/export_plugin.cpp
msgid "Adding files..."
@@ -19680,9 +19700,8 @@ msgid "Could not open icon file \"%s\"."
msgstr "Ðе удалоÑÑŒ ÑкÑпортировать файлы проекта"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start xcrun executable."
-msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить подпроцеÑÑ!"
+msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить иÑполнÑемый файл xcrun."
#: platform/osx/export/export.cpp
#, fuzzy
@@ -19766,9 +19785,8 @@ msgid "DMG Creation"
msgstr "Ðаправление"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start hdiutil executable."
-msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить подпроцеÑÑ!"
+msgstr "Ðе удаётÑÑ Ð·Ð°Ð¿ÑƒÑтить иÑполнÑемый файл hdiutil."
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed - file exists."
@@ -19855,9 +19873,8 @@ msgid "ZIP Creation"
msgstr "ПроекциÑ"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not open file to read from path \"%s\"."
-msgstr "Ðе удалоÑÑŒ ÑкÑпортировать файлы проекта в проект gradle\n"
+msgstr "Ðе удалоÑÑŒ открыть файл Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð¿Ð¾ пути \"%s\"."
#: platform/osx/export/export.cpp
msgid "Invalid bundle identifier:"
@@ -20264,17 +20281,17 @@ msgstr "Ðе удалоÑÑŒ найти хранилище ключей, нево
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
"ИнÑтрумент rcedit должен быть наÑтроен в ÐаÑтройках редактора (Export > "
"Windows > Rcedit) Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐºÐ° или информационных данных приложениÑ."
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "ÐедопуÑтимый иÑполнÑемый файл."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20299,17 +20316,17 @@ msgstr "ÐедопуÑтимое имÑ."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
"ИнÑтрумент rcedit должен быть наÑтроен в ÐаÑтройках редактора (Export > "
"Windows > Rcedit) Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐºÐ° или информационных данных приложениÑ."
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "ÐедопуÑтимый иÑполнÑемый файл."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20543,7 +20560,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 +21310,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 +21323,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 +21354,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 ""
@@ -21374,7 +21401,7 @@ msgstr "ПеремеÑтитÑÑ"
msgid "Rotation Degrees"
msgstr "ГрадуÑÑ‹ вращениÑ"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr "Глобальный поворот"
@@ -22884,11 +22911,11 @@ msgstr ""
#: scene/3d/physics_body.cpp
msgid "Angular Spring Damping"
-msgstr ""
+msgstr "Угловое Затухание Пружины"
#: scene/3d/physics_body.cpp
msgid "Angular Equilibrium Point"
-msgstr ""
+msgstr "Ð£Ð³Ð»Ð¾Ð²Ð°Ñ Ð¢Ð¾Ñ‡ÐºÐ° РавновеÑиÑ"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -22917,7 +22944,7 @@ msgstr "Узел Ри Узел В должны быть различными о
#: scene/3d/physics_joint.cpp
msgid "Solver"
-msgstr ""
+msgstr "Разрешитель"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -22931,7 +22958,7 @@ msgstr "Параметры"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit"
-msgstr ""
+msgstr "Угловой Предел"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -22945,7 +22972,7 @@ msgstr "нижний региÑтр"
#: scene/3d/physics_joint.cpp
msgid "Motor"
-msgstr ""
+msgstr "Мотор"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23029,11 +23056,11 @@ msgstr "МежÑтрочный интервал"
#: scene/3d/physics_joint.cpp
msgid "Equilibrium Point"
-msgstr ""
+msgstr "Точка РавновеÑиÑ"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit X"
-msgstr ""
+msgstr "X Углового Предела"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23042,7 +23069,7 @@ msgstr "Ð£Ð³Ð»Ð¾Ð²Ð°Ñ ÑкороÑть"
#: scene/3d/physics_joint.cpp
msgid "Angular Spring X"
-msgstr ""
+msgstr "X Угловой Пружины"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23061,7 +23088,7 @@ msgstr "МежÑтрочный интервал"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit Y"
-msgstr ""
+msgstr "Y Углового Предела"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23070,7 +23097,7 @@ msgstr "Ð£Ð³Ð»Ð¾Ð²Ð°Ñ ÑкороÑть"
#: scene/3d/physics_joint.cpp
msgid "Angular Spring Y"
-msgstr ""
+msgstr "Y Угловой Пружины"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23089,7 +23116,7 @@ msgstr "МежÑтрочный интервал"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit Z"
-msgstr ""
+msgstr "Z Углового Предела"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23098,7 +23125,7 @@ msgstr "Ð£Ð³Ð»Ð¾Ð²Ð°Ñ ÑкороÑть"
#: scene/3d/physics_joint.cpp
msgid "Angular Spring Z"
-msgstr ""
+msgstr "Z Угловой Пружины"
#: scene/3d/portal.cpp
msgid "The RoomManager should not be a child or grandchild of a Portal."
@@ -23118,7 +23145,7 @@ msgstr "Портал активен"
#: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp
msgid "Two Way"
-msgstr ""
+msgstr "В обе Стороны"
#: scene/3d/portal.cpp
msgid "Linked Room"
@@ -23480,6 +23507,11 @@ msgstr ""
"shapes)."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Глобальное преобразование"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24704,6 +24736,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 +25142,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 +25149,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 +26927,7 @@ msgstr "Передвинуть точки"
#: scene/resources/packed_scene.cpp
msgid "Bundled"
-msgstr ""
+msgstr "Вложенный"
#: scene/resources/particles_material.cpp
msgid "Trail"
@@ -27727,14 +27760,12 @@ msgid "Import S3TC"
msgstr "Импорт"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import ETC"
-msgstr "Импорт"
+msgstr "Импортировать ETC"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import ETC2"
-msgstr "Импорт"
+msgstr "Импортировать ETC2"
#: servers/visual_server.cpp
#, fuzzy
@@ -27947,12 +27978,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 +27998,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 +28033,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..8ce2d1d628 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
@@ -450,6 +454,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2112,14 +2120,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2175,8 +2184,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2736,8 +2745,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "à·à·Šâ€à¶»à·’à¶­:"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5333,6 +5343,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11380,6 +11398,11 @@ msgid "New Animation"
msgstr "සජීවීකරණ පුනරà·à·€à¶»à·Šà¶®à¶±à¶º"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "à·à·Šâ€à¶»à·’à¶­:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17988,6 +18011,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 +18024,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 +18069,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 +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
@@ -18280,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 ""
-"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
@@ -19573,14 +19621,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19602,14 +19649,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19828,7 +19874,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 +20561,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 +20573,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 ""
@@ -20586,7 +20641,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr ""
@@ -22497,6 +22552,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Anim පරිවර්තනය වෙනස් කරන්න"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23611,6 +23671,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 +24045,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..7cba3886ba 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
@@ -488,6 +493,10 @@ msgid "Pressure"
msgstr "Preset"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Prichytiť Relatívne"
@@ -2195,14 +2204,15 @@ msgstr "Obľúbené:"
msgid "Recent:"
msgstr "Nedávne:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Hľadať:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Zhody:"
@@ -2262,8 +2272,8 @@ msgstr "Hľadať Náhradný Zdroj:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2844,8 +2854,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Skopírovať Výber"
#: editor/editor_export.cpp
#, fuzzy
@@ -5644,6 +5655,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11949,6 +11969,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filter:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18915,6 +18940,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 +18953,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 +19001,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 +19246,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 +19260,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20613,15 +20663,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Nesprávna veľkosť písma."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20643,15 +20693,15 @@ msgstr "Neplatný Názov."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Nesprávna veľkosť písma."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20891,7 +20941,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 +21677,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 +21690,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 ""
@@ -21701,7 +21761,7 @@ msgstr "Cestovať"
msgid "Rotation Degrees"
msgstr "Krok Rotácie:"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konštant"
@@ -23726,6 +23786,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Preložiť Preloženie:"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24931,6 +24996,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 +25401,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..ceb21aa750 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
@@ -461,6 +466,10 @@ msgid "Pressure"
msgstr "Prednastavitev..."
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Pripni Relativno"
@@ -2214,14 +2223,15 @@ msgstr "Priljubljene:"
msgid "Recent:"
msgstr "Nedavni:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Iskanje:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Zadetki:"
@@ -2283,8 +2293,8 @@ msgstr "Iskanje Nadomestnih Virov:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2877,8 +2887,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Odstrani izbrano"
#: editor/editor_export.cpp
#, fuzzy
@@ -5715,6 +5726,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -12169,6 +12189,11 @@ msgid "New Animation"
msgstr "Animacija"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Lastnosti objekta."
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -19206,6 +19231,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 +19244,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 +19293,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 +19539,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 +19553,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20912,15 +20962,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Uporabiti moraš valjavno razširitev."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20942,15 +20992,15 @@ msgstr "Neveljavno ime."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Uporabiti moraš valjavno razširitev."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21190,7 +21240,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 +21972,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 +21985,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 ""
@@ -21995,7 +22055,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr "Rotacijski Korak:"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstanta"
@@ -24015,6 +24075,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Preoblikovanje"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25228,6 +25293,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 +25694,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..af72b686b9 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
@@ -473,6 +478,10 @@ msgid "Pressure"
msgstr "Ngarko Gabimet"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2153,14 +2162,15 @@ msgstr "Të Preferuarat:"
msgid "Recent:"
msgstr "Të fundit:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Kërko:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Përputhjet:"
@@ -2222,8 +2232,8 @@ msgstr "Kërko Resursin Zëvendësues:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2814,8 +2824,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Animacionet:"
#: editor/editor_export.cpp
#, fuzzy
@@ -5651,6 +5662,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11872,6 +11892,11 @@ msgid "New Animation"
msgstr "Animacionin i Ri"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Nyjet filtruese"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18698,6 +18723,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 +18736,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 +18784,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 +19028,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 +19042,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 ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+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
@@ -20383,15 +20433,15 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Duhet të perdorësh një shtesë të lejuar."
#: platform/windows/export/export.cpp
msgid "Could not find signtool executable at \"%s\"."
@@ -20413,15 +20463,15 @@ msgstr "Emër i palejuar."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Duhet të perdorësh një shtesë të lejuar."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20654,7 +20704,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 +21409,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 +21422,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 ""
@@ -21430,7 +21490,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstantet"
@@ -23380,6 +23440,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Binari i Transformimeve 3D"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24550,6 +24615,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 +25011,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..4231d62c6b 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
@@ -489,6 +494,10 @@ msgid "Pressure"
msgstr "ПоÑтавке"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "Залепи релативно"
@@ -2324,14 +2333,15 @@ msgstr "Омиљене:"
msgid "Recent:"
msgstr "ЧеÑте:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Тражи:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Подударање:"
@@ -2393,8 +2403,8 @@ msgstr "Потражи замену за реÑурÑ:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2993,7 +3003,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Копирај Путању Чвора"
#: editor/editor_export.cpp
@@ -5964,6 +5974,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "МапаМреже ИÑпуни Одабрано"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -12739,6 +12758,11 @@ msgstr "Ðнимација"
#: editor/plugins/sprite_frames_editor_plugin.cpp
#, fuzzy
+msgid "Filter animations"
+msgstr "Филтрирај методе"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
msgid "Speed:"
msgstr "Брзина (FPS):"
@@ -20554,6 +20578,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 +20591,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 +20643,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 +20905,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 +20919,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
@@ -22313,15 +22362,15 @@ msgstr "ÐеуÑпешно отварање нацрта за извоз:"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Мора Ñе кориÑтити важећа екÑтензија."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -22345,15 +22394,15 @@ msgstr "Ðеважеће име."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Мора Ñе кориÑтити важећа екÑтензија."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -22599,7 +22648,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 +23423,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 +23436,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 +23468,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."
@@ -23454,7 +23513,7 @@ msgstr "Путуј"
msgid "Rotation Degrees"
msgstr "Ротација за %s Ñтепени."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "КонÑтантан"
@@ -25603,6 +25662,11 @@ msgstr ""
"рада."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Сачувај Глобалну ТранÑформу"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -26884,6 +26948,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 +27363,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..b898108402 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
@@ -458,6 +463,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2128,14 +2137,15 @@ msgstr "Omiljeno:"
msgid "Recent:"
msgstr "Nedavno:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Pretraga:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Podudaranja:"
@@ -2195,8 +2205,8 @@ msgstr "Traži Resurs Zamene:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2759,8 +2769,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Kopiraj OznaÄeno"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5350,6 +5361,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11384,6 +11404,11 @@ msgid "New Animation"
msgstr "Nova Animacija"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Animacija"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18053,6 +18078,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 +18091,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 +18136,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 +18366,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 +18380,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
@@ -19660,14 +19710,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19689,14 +19738,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19919,7 +19967,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 +20667,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 +20680,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 ""
@@ -20690,7 +20748,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Kontanta"
@@ -22630,6 +22688,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Animacija Promjeni Transformaciju"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23771,6 +23834,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 +24215,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..9fd6b9bf67 100644
--- a/editor/translations/sv.po
+++ b/editor/translations/sv.po
@@ -14,7 +14,7 @@
# Mattias Münster <mattiasmun@gmail.com>, 2019.
# Anonymous <noreply@weblate.org>, 2020.
# Joakim Lundberg <joakim@joakimlundberg.com>, 2020.
-# Kristoffer Grundström <swedishsailfishosuser@tutanota.com>, 2020, 2021.
+# Kristoffer Grundström <swedishsailfishosuser@tutanota.com>, 2020, 2021, 2022.
# Jonas Robertsson <jonas.robertsson@posteo.net>, 2020, 2021.
# André Andersson <andre.eric.andersson@gmail.com>, 2020.
# Andreas Westrell <andreas.westrell@gmail.com>, 2020.
@@ -22,16 +22,18 @@
# Shaggy <anton_christoffersson@hotmail.com>, 2020.
# Marcus Toftedahl <marcus.toftedahl@his.se>, 2020.
# Alex25820 <Alexander_sjogren@hotmail.se>, 2021.
-# Leon <joel.lundborg@gmail.com>, 2021.
+# Leon <joel.lundborg@gmail.com>, 2021, 2022.
# Kent Jofur <kent.jofur@gmail.com>, 2021.
# Alex25820 <alexs25820@gmail.com>, 2021.
+# Björn Åkesson <bjorn.akesson@gmail.com>, 2022.
+# Kenny Andersson <kenny@ordinary.se>, 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: 2021-12-20 18:53+0000\n"
-"Last-Translator: Alex25820 <alexs25820@gmail.com>\n"
+"PO-Revision-Date: 2022-07-23 03:57+0000\n"
+"Last-Translator: Kenny Andersson <kenny@ordinary.se>\n"
"Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/"
"godot/sv/>\n"
"Language: sv\n"
@@ -39,11 +41,12 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.10\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
+#, fuzzy
msgid "Tablet Driver"
-msgstr ""
+msgstr "Drivrutin för surfplatta"
#: core/bind/core_bind.cpp
#, fuzzy
@@ -51,18 +54,16 @@ msgid "Clipboard"
msgstr "Klippbordet är tomt!"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Current Screen"
-msgstr "Nuvarande Scen"
+msgstr "Nuvarande Skärm"
#: core/bind/core_bind.cpp
msgid "Exit Code"
msgstr ""
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "V-Sync Enabled"
-msgstr "Aktivera"
+msgstr "V-Synk Aktivt"
#: core/bind/core_bind.cpp main/main.cpp
msgid "V-Sync Via Compositor"
@@ -73,9 +74,8 @@ msgid "Delta Smoothing"
msgstr ""
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Low Processor Usage Mode"
-msgstr "Exportera Projekt"
+msgstr "Läge för låg processoranvändning"
#: core/bind/core_bind.cpp
msgid "Low Processor Usage Mode Sleep (µsec)"
@@ -86,9 +86,8 @@ msgid "Keep Screen On"
msgstr ""
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Min Window Size"
-msgstr "Storlek:"
+msgstr "Minsta fönsterstorlek"
#: core/bind/core_bind.cpp
#, fuzzy
@@ -108,11 +107,11 @@ msgstr "Nytt Fönster"
#: core/bind/core_bind.cpp core/project_settings.cpp
msgid "Borderless"
-msgstr ""
+msgstr "Kantlös"
#: core/bind/core_bind.cpp
msgid "Per Pixel Transparency Enabled"
-msgstr ""
+msgstr "Genomskinlighet per pixel aktiverad"
#: core/bind/core_bind.cpp core/project_settings.cpp
#, fuzzy
@@ -121,16 +120,16 @@ msgstr "Växla Fullskärm"
#: core/bind/core_bind.cpp
msgid "Maximized"
-msgstr ""
+msgstr "Maximerad"
#: core/bind/core_bind.cpp
msgid "Minimized"
-msgstr ""
+msgstr "Minimerad"
#: core/bind/core_bind.cpp core/project_settings.cpp scene/gui/dialogs.cpp
#: scene/gui/graph_node.cpp
msgid "Resizable"
-msgstr ""
+msgstr "Anpassningsbar"
#: core/bind/core_bind.cpp core/os/input_event.cpp scene/2d/node_2d.cpp
#: scene/2d/physics_body_2d.cpp scene/2d/remote_transform_2d.cpp
@@ -150,36 +149,32 @@ msgstr "Dockposition"
#: scene/resources/primitive_meshes.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp scene/resources/texture.cpp
#: scene/resources/visual_shader.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Size"
-msgstr "Storlek:"
+msgstr "Storlek"
#: core/bind/core_bind.cpp
msgid "Endian Swap"
msgstr ""
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Editor Hint"
-msgstr "Redigera Tema"
+msgstr "Redigeringsförslag"
#: core/bind/core_bind.cpp
msgid "Print Error Messages"
-msgstr ""
+msgstr "Skriv ut felmeddelanden"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Iterations Per Second"
-msgstr "Interpolationsläge"
+msgstr "Upprepningar per sekund"
#: core/bind/core_bind.cpp
msgid "Target FPS"
-msgstr ""
+msgstr "MÃ¥l FPS"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Time Scale"
-msgstr "Skala"
+msgstr "Tidsskala"
#: core/bind/core_bind.cpp main/main.cpp
#, fuzzy
@@ -201,13 +196,12 @@ msgid "Error Line"
msgstr "Fel vid sparande"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Result"
-msgstr "Sök Hjälp"
+msgstr "Resultat"
#: core/command_queue_mt.cpp core/message_queue.cpp main/main.cpp
msgid "Memory"
-msgstr ""
+msgstr "Minne"
#: core/command_queue_mt.cpp core/message_queue.cpp
#: core/register_core_types.cpp drivers/gles2/rasterizer_canvas_base_gles2.cpp
@@ -218,7 +212,7 @@ msgstr ""
#: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h
#: servers/visual_server.cpp
msgid "Limits"
-msgstr ""
+msgstr "Begränsningar"
#: core/command_queue_mt.cpp
#, fuzzy
@@ -227,68 +221,63 @@ msgstr "Ctrl: Rotera"
#: core/command_queue_mt.cpp
msgid "Multithreading Queue Size (KB)"
-msgstr ""
+msgstr "Flertrådsköstorlek (KB)"
#: core/func_ref.cpp modules/visual_script/visual_script_builtin_funcs.cpp
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
#: scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Function"
-msgstr "Funktioner"
+msgstr "Funktion"
#: core/image.cpp core/packed_data_container.cpp scene/2d/polygon_2d.cpp
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
msgid "Data"
-msgstr ""
+msgstr "Data"
#: core/io/file_access_network.cpp core/register_core_types.cpp
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp main/main.cpp
#: modules/gdscript/language_server/gdscript_language_server.cpp
#: modules/webrtc/webrtc_data_channel.h modules/websocket/websocket_macros.h
#: scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Network"
-msgstr "Nätverksprofilerare"
+msgstr "Nätverk"
#: core/io/file_access_network.cpp
-#, fuzzy
msgid "Remote FS"
-msgstr "Ta bort"
+msgstr "Fjärr FS"
#: core/io/file_access_network.cpp
-#, fuzzy
msgid "Page Size"
-msgstr "Sida: "
+msgstr "Sidstorlek"
#: core/io/file_access_network.cpp
msgid "Page Read Ahead"
-msgstr ""
+msgstr "Sida läs framåt"
#: core/io/http_client.cpp
msgid "Blocking Mode Enabled"
-msgstr ""
+msgstr "Blockeringsläge Aktiverat"
#: core/io/http_client.cpp
-#, fuzzy
msgid "Connection"
-msgstr "Anslut"
+msgstr "Anslutning"
#: core/io/http_client.cpp
msgid "Read Chunk Size"
-msgstr ""
+msgstr "Läs segmentstorlek"
#: core/io/marshalls.cpp
msgid "Object ID"
-msgstr ""
+msgstr "Objekt ID"
#: core/io/multiplayer_api.cpp core/io/packet_peer.cpp
msgid "Allow Object Decoding"
-msgstr ""
+msgstr "Tillåt objekt avkodning"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
msgid "Refuse New Network Connections"
-msgstr ""
+msgstr "Neka nya nätverksanslutningar"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
#, fuzzy
@@ -312,36 +301,35 @@ msgstr "Transformera"
#: core/io/packet_peer.cpp
msgid "Encode Buffer Max Size"
-msgstr ""
+msgstr "Maxstorlek för kodningsbufferten"
#: core/io/packet_peer.cpp
msgid "Input Buffer Max Size"
-msgstr ""
+msgstr "Maximal storlek på inmatningsbufferten"
#: core/io/packet_peer.cpp
msgid "Output Buffer Max Size"
-msgstr ""
+msgstr "Maxstorlek för utgångsbuffert"
#: core/io/packet_peer.cpp
msgid "Stream Peer"
-msgstr ""
+msgstr "Strömningsenhet"
#: core/io/stream_peer.cpp
msgid "Big Endian"
-msgstr ""
+msgstr "Big Endian"
#: core/io/stream_peer.cpp
msgid "Data Array"
-msgstr ""
+msgstr "Datamatris"
#: core/io/stream_peer_ssl.cpp
msgid "Blocking Handshake"
-msgstr ""
+msgstr "Blockering av handskakning"
#: core/io/udp_server.cpp
-#, fuzzy
msgid "Max Pending Connections"
-msgstr "Redigera Koppling:"
+msgstr "Max väntande anslutningar"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -356,12 +344,11 @@ msgstr "Förväntade en sträng av längden 1 (ett tecken)."
#: modules/mono/glue/gd_glue.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
msgid "Not enough bytes for decoding bytes, or invalid format."
-msgstr "Inte nog med bytes för att avkoda, eller ogiltigt format."
+msgstr "Otillräckligt antal bytes för att avkoda, eller ogiltigt format."
#: core/math/expression.cpp
-#, fuzzy
msgid "Invalid input %d (not passed) in expression"
-msgstr "Ogiltig indata %i (ej överförd) i uttrycket"
+msgstr "Ogiltig inmatning %d (ej överförd) i uttrycket"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
@@ -390,7 +377,7 @@ msgstr "I anrop till '%s':"
#: core/math/random_number_generator.cpp
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Seed"
-msgstr ""
+msgstr "Seed"
#: core/math/random_number_generator.cpp
#, fuzzy
@@ -399,11 +386,11 @@ msgstr "Status"
#: core/message_queue.cpp
msgid "Message Queue"
-msgstr ""
+msgstr "Meddelandekö"
#: core/message_queue.cpp
msgid "Max Size (KB)"
-msgstr ""
+msgstr "Maxstorlek (KB)"
#: core/os/input.cpp
#, fuzzy
@@ -412,7 +399,7 @@ msgstr "Växla Läge"
#: core/os/input.cpp
msgid "Use Accumulated Input"
-msgstr ""
+msgstr "Använd ackumulerad input"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
@@ -420,13 +407,12 @@ msgid "Device"
msgstr "Enhet"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Alt"
-msgstr "Alla"
+msgstr "Alt"
#: core/os/input_event.cpp
msgid "Shift"
-msgstr ""
+msgstr "Shift"
#: core/os/input_event.cpp
#, fuzzy
@@ -435,13 +421,18 @@ msgstr "Versionshantering"
#: core/os/input_event.cpp
msgid "Meta"
-msgstr ""
+msgstr "Meta"
#: core/os/input_event.cpp
#, fuzzy
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
@@ -450,9 +441,8 @@ msgid "Pressed"
msgstr "Återställ Zoom"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Scancode"
-msgstr "Skanna"
+msgstr "Scancode"
#: core/os/input_event.cpp
msgid "Physical Scancode"
@@ -460,7 +450,7 @@ msgstr ""
#: core/os/input_event.cpp
msgid "Unicode"
-msgstr ""
+msgstr "Unicode"
#: core/os/input_event.cpp
msgid "Echo"
@@ -477,9 +467,8 @@ msgid "Global Position"
msgstr "Konstant"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Factor"
-msgstr "Vektor"
+msgstr "Faktor"
#: core/os/input_event.cpp
#, fuzzy
@@ -488,21 +477,23 @@ msgstr "Automatisk Indentering"
#: core/os/input_event.cpp
msgid "Doubleclick"
-msgstr ""
+msgstr "Dubbelklick"
#: core/os/input_event.cpp
msgid "Tilt"
msgstr ""
#: core/os/input_event.cpp
-#, fuzzy
msgid "Pressure"
-msgstr "Återställ Zoom"
+msgstr "Tryck"
+
+#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr "Invertera penna"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Relative"
-msgstr "GDNative"
+msgstr "Relativ"
#: core/os/input_event.cpp scene/2d/camera_2d.cpp scene/2d/cpu_particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/interpolated_camera.cpp
@@ -518,9 +509,8 @@ msgid "Axis"
msgstr "Axel"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Axis Value"
-msgstr "Värde"
+msgstr "Axelvärde"
#: core/os/input_event.cpp modules/visual_script/visual_script_func_nodes.cpp
#, fuzzy
@@ -536,21 +526,19 @@ msgstr "Åtgärd"
#: core/os/input_event.cpp scene/resources/environment.cpp
#: scene/resources/material.cpp
msgid "Strength"
-msgstr ""
+msgstr "Styrka"
#: core/os/input_event.cpp
msgid "Delta"
-msgstr ""
+msgstr "Delta"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Channel"
-msgstr "Ändra"
+msgstr "Kanal"
#: core/os/input_event.cpp main/main.cpp
-#, fuzzy
msgid "Message"
-msgstr "Synkronisera Skript-ändringar"
+msgstr "Meddelande"
#: core/os/input_event.cpp
#, fuzzy
@@ -561,11 +549,11 @@ msgstr "Växla"
#: scene/2d/physics_body_2d.cpp scene/3d/cpu_particles.cpp
#: scene/3d/physics_body.cpp scene/resources/particles_material.cpp
msgid "Velocity"
-msgstr ""
+msgstr "Hastighet"
#: core/os/input_event.cpp
msgid "Instrument"
-msgstr ""
+msgstr "Instrument"
#: core/os/input_event.cpp
#, fuzzy
@@ -579,13 +567,13 @@ msgstr ""
#: core/project_settings.cpp editor/editor_node.cpp main/main.cpp
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Application"
-msgstr "Åtgärd"
+msgstr "Applikation"
#: core/project_settings.cpp main/main.cpp
+#, fuzzy
msgid "Config"
-msgstr ""
+msgstr "Konfigurera"
#: core/project_settings.cpp
#, fuzzy
@@ -621,7 +609,7 @@ msgstr "Kör"
#: core/project_settings.cpp editor/editor_node.cpp
#: editor/run_settings_dialog.cpp main/main.cpp
msgid "Main Scene"
-msgstr ""
+msgstr "Huvudscen"
#: core/project_settings.cpp
#, fuzzy
@@ -635,15 +623,15 @@ msgstr "Avaktiverad"
#: core/project_settings.cpp
msgid "Use Hidden Project Data Directory"
-msgstr ""
+msgstr "Använda dold projektdatakatalog"
#: core/project_settings.cpp
msgid "Use Custom User Dir"
-msgstr ""
+msgstr "Använd anpassad användarkatalog"
#: core/project_settings.cpp
msgid "Custom User Dir Name"
-msgstr ""
+msgstr "Anpassad användarkatalognamn"
#: core/project_settings.cpp main/main.cpp
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
@@ -656,7 +644,7 @@ msgstr "Ersätt Alla"
#: modules/opensimplex/noise_texture.cpp scene/2d/line_2d.cpp
#: scene/3d/label_3d.cpp scene/gui/text_edit.cpp scene/resources/texture.cpp
msgid "Width"
-msgstr ""
+msgstr "Bredd"
#: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp
#: modules/gltf/gltf_node.cpp modules/opensimplex/noise_texture.cpp
@@ -664,13 +652,12 @@ msgstr ""
#: scene/resources/capsule_shape_2d.cpp scene/resources/cylinder_shape.cpp
#: scene/resources/font.cpp scene/resources/navigation_mesh.cpp
#: scene/resources/primitive_meshes.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Height"
-msgstr "Höger"
+msgstr "Höjd"
#: core/project_settings.cpp
msgid "Always On Top"
-msgstr ""
+msgstr "Alltid överst"
#: core/project_settings.cpp
#, fuzzy
@@ -697,11 +684,11 @@ msgstr "Ladda standard Buss-Layouten."
#: editor/editor_settings.cpp editor/script_create_dialog.cpp
#: scene/2d/camera_2d.cpp scene/3d/light.cpp scene/main/node.cpp
msgid "Editor"
-msgstr ""
+msgstr "Redigerare"
#: core/project_settings.cpp
msgid "Main Run Args"
-msgstr ""
+msgstr "Huvudkörnings arg"
#: core/project_settings.cpp
#, fuzzy
@@ -710,11 +697,12 @@ msgstr "Scen Filsökväg:"
#: core/project_settings.cpp
msgid "Search In File Extensions"
-msgstr ""
+msgstr "Sök i filändelser"
#: core/project_settings.cpp
+#, fuzzy
msgid "Script Templates Search Path"
-msgstr ""
+msgstr "Sökväg för skriptmallar"
#: core/project_settings.cpp
#, fuzzy
@@ -729,16 +717,16 @@ msgstr "Versionshantering"
#: core/project_settings.cpp scene/2d/collision_object_2d.cpp
#: scene/3d/collision_object.cpp scene/gui/control.cpp
msgid "Input"
-msgstr ""
+msgstr "Input"
#: core/project_settings.cpp
+#, fuzzy
msgid "UI Accept"
-msgstr ""
+msgstr "UI Acceptera"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Select"
-msgstr "Välj"
+msgstr "Ui Välj"
#: core/project_settings.cpp
#, fuzzy
@@ -770,9 +758,8 @@ msgid "UI Up"
msgstr ""
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Down"
-msgstr "Ladda ner"
+msgstr "UI Ner"
#: core/project_settings.cpp
#, fuzzy
@@ -781,11 +768,11 @@ msgstr "Sida: "
#: core/project_settings.cpp
msgid "UI Page Down"
-msgstr ""
+msgstr "UI sida ner"
#: core/project_settings.cpp
msgid "UI Home"
-msgstr ""
+msgstr "UI hem"
#: core/project_settings.cpp
msgid "UI End"
@@ -922,7 +909,7 @@ msgstr ""
#: core/register_core_types.cpp
msgid "TCP"
-msgstr ""
+msgstr "TCP"
#: core/register_core_types.cpp
#, fuzzy
@@ -935,11 +922,12 @@ msgstr ""
#: core/register_core_types.cpp
msgid "Max Buffer (Power of 2)"
-msgstr ""
+msgstr "Max buffer (2 potenser)"
#: core/register_core_types.cpp editor/editor_settings.cpp main/main.cpp
+#, fuzzy
msgid "SSL"
-msgstr ""
+msgstr "SSL"
#: core/register_core_types.cpp main/main.cpp
#, fuzzy
@@ -955,7 +943,7 @@ msgstr "Resurs"
#: core/resource.cpp
#, fuzzy
msgid "Local To Scene"
-msgstr "Stäng Scen"
+msgstr "Lokalt till scenen"
#: core/resource.cpp editor/dependency_editor.cpp
#: editor/editor_autoload_settings.cpp editor/plugins/path_editor_plugin.cpp
@@ -974,12 +962,13 @@ msgid "Locale"
msgstr ""
#: core/translation.cpp
+#, fuzzy
msgid "Test"
-msgstr ""
+msgstr "Test"
#: core/translation.cpp scene/resources/font.cpp
msgid "Fallback"
-msgstr ""
+msgstr "Reserv"
#: core/ustring.cpp scene/resources/segment_shape_2d.cpp
msgid "B"
@@ -1014,18 +1003,21 @@ msgstr "EiB"
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
#: drivers/gles3/rasterizer_scene_gles3.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp modules/gltf/gltf_state.cpp
+#, fuzzy
msgid "Buffers"
-msgstr ""
+msgstr "Buffertar"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
+#, fuzzy
msgid "Canvas Polygon Buffer Size (KB)"
-msgstr ""
+msgstr "Buffertstorlek för canvaspolygon (KB)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
+#, fuzzy
msgid "Canvas Polygon Index Buffer Size (KB)"
-msgstr ""
+msgstr "Buffertstorlek för Canvas Polygon Index (KB)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp editor/editor_settings.cpp
@@ -1036,8 +1028,9 @@ msgstr ""
#: servers/physics_2d/physics_2d_server_wrap_mt.h
#: servers/physics_2d/space_2d_sw.cpp servers/physics_2d_server.cpp
#: servers/visual_server.cpp
+#, fuzzy
msgid "2D"
-msgstr ""
+msgstr "2D"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
@@ -1048,42 +1041,47 @@ msgstr "Alternativ"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Use GPU Pixel Snap"
-msgstr ""
+msgstr "Använd GPU pixel vidhäftning"
#: drivers/gles2/rasterizer_scene_gles2.cpp
#: drivers/gles3/rasterizer_scene_gles3.cpp
+#, fuzzy
msgid "Immediate Buffer Size (KB)"
-msgstr ""
+msgstr "Omedelbar buffertstorlek (KB)"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
+#, fuzzy
msgid "Lightmapping"
-msgstr ""
+msgstr "Ljusmappning"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
+#, fuzzy
msgid "Use Bicubic Sampling"
-msgstr ""
+msgstr "Använd bikubisk sampling"
#: drivers/gles3/rasterizer_scene_gles3.cpp
+#, fuzzy
msgid "Max Renderable Elements"
-msgstr ""
+msgstr "Max återgivningsbara element"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Renderable Lights"
-msgstr ""
+msgstr "Max renderbara ljuskällor"
#: drivers/gles3/rasterizer_scene_gles3.cpp
+#, fuzzy
msgid "Max Renderable Reflections"
-msgstr ""
+msgstr "Max renderingsbara reflektioner"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Lights Per Object"
-msgstr ""
+msgstr "Max antal ljuskällor per objekt"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Subsurface Scattering"
-msgstr ""
+msgstr "Subsurface Scattering"
#: drivers/gles3/rasterizer_scene_gles3.cpp editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
@@ -1107,16 +1105,19 @@ msgid "Weight Samples"
msgstr ""
#: drivers/gles3/rasterizer_scene_gles3.cpp
+#, fuzzy
msgid "Voxel Cone Tracing"
-msgstr ""
+msgstr "Voxel Kon Spårning"
#: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp
+#, fuzzy
msgid "High Quality"
-msgstr ""
+msgstr "Hög kvalitet"
#: drivers/gles3/rasterizer_storage_gles3.cpp
+#, fuzzy
msgid "Blend Shape Max Buffer Size (KB)"
-msgstr ""
+msgstr "Mixform Max buffertstorlek (KB)"
#. TRANSLATORS: Adjective, refers to the mode for Bezier handles (Free, Balanced, Mirror).
#: editor/animation_bezier_editor.cpp
@@ -1169,7 +1170,7 @@ msgstr "Anim Ta Bort Nycklar"
#: editor/animation_track_editor.cpp
msgid "Anim Change Keyframe Time"
-msgstr "Anim Ändra Nyckelbildstid"
+msgstr "Anim Ändra Tidsnyckelns Tid"
#: editor/animation_track_editor.cpp
msgid "Anim Change Transition"
@@ -1227,7 +1228,7 @@ msgstr "Välj Färg"
#: editor/animation_track_editor.cpp main/main.cpp
#: modules/mono/mono_gd/gd_mono.cpp
msgid "Args"
-msgstr ""
+msgstr "Argument"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp
@@ -1238,23 +1239,25 @@ msgstr "Typ"
#: editor/animation_track_editor.cpp
msgid "In Handle"
-msgstr ""
+msgstr "Handtag in"
#: editor/animation_track_editor.cpp
+#, fuzzy
msgid "Out Handle"
-msgstr ""
+msgstr "Handtag ut"
#: editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
+#, fuzzy
msgid "Stream"
-msgstr ""
+msgstr "Ström"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "Start Offset"
-msgstr "Icon Läge"
+msgstr "Startförskjutning"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1273,7 +1276,7 @@ msgstr "Animation"
#: editor/animation_track_editor.cpp
msgid "Easing"
-msgstr ""
+msgstr "Lätta"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
@@ -1426,7 +1429,7 @@ msgstr ""
#: editor/animation_track_editor.cpp
msgid "Out-Handle:"
-msgstr ""
+msgstr "Handtag ut:"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1439,8 +1442,9 @@ msgid "Start (s):"
msgstr "Starta"
#: editor/animation_track_editor.cpp
+#, fuzzy
msgid "End (s):"
-msgstr ""
+msgstr "Slut (s):"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1500,7 +1504,7 @@ msgstr "Duplicera Nycklar"
#: editor/animation_track_editor.cpp
msgid "Add RESET Value(s)"
-msgstr ""
+msgstr "Lägg till RESET-värde(n)"
#: editor/animation_track_editor.cpp
msgid "Delete Key(s)"
@@ -1582,7 +1586,7 @@ msgstr ""
#. TRANSLATORS: This describes the target of new animation track, will be inserted into another string.
#: editor/animation_track_editor.cpp
msgid "property '%s'"
-msgstr "egenskapen '%s'"
+msgstr "egenskap '%s'"
#: editor/animation_track_editor.cpp
msgid "Anim Create & Insert"
@@ -1815,9 +1819,8 @@ msgid "Go to Previous Step"
msgstr "Gå till Föregående Steg"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Apply Reset"
-msgstr "Återställ Zoom"
+msgstr "Verkställ återställning"
#: editor/animation_track_editor.cpp
msgid "Optimize Animation"
@@ -2200,14 +2203,15 @@ msgstr "Favoriter:"
msgid "Recent:"
msgstr "Senaste:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Sök:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Matchar:"
@@ -2267,8 +2271,8 @@ msgstr "Sök Ersättningsresurs:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2277,17 +2281,17 @@ msgstr "Öppna"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "Ägare av: %s (Totalt: %d)"
#: editor/dependency_editor.cpp
-#, fuzzy
msgid ""
"Remove the selected files from the project? (Cannot be undone.)\n"
"Depending on your filesystem configuration, the files will either be moved "
"to the system trash or deleted permanently."
msgstr ""
-"Ta bort valda filer från projektet? (Kan ej återställas)\n"
-"Du kan hitta de borttagna filerna i systemets papperskorg."
+"Ta bort de valda filerna från projektet? (Kan ej ångras.)\n"
+"Beroende på hur ditt filsystem är konfigurerat så kommer filerna antingen "
+"flyttas till systemets papperskorg eller tas bort permanent."
#: editor/dependency_editor.cpp
msgid ""
@@ -2372,7 +2376,7 @@ msgstr "Tack från Godot-gemenskapen!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr "Klicka för att kopiera."
+msgstr "Klicka för att kopiera"
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2470,30 +2474,32 @@ msgid "Licenses"
msgstr "Licenser"
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Error opening asset file for \"%s\" (not in ZIP format)."
-msgstr "Fel vid öppning av paketetfil, inte i zip-format."
+msgstr "Fel vid öppning av tillgångsfilen för \"%s\" (inte i ZIP-format)."
#: editor/editor_asset_installer.cpp
msgid "%s (already exists)"
msgstr "%s (existerar redan)"
#: editor/editor_asset_installer.cpp
+#, fuzzy
msgid "Contents of asset \"%s\" - %d file(s) conflict with your project:"
msgstr ""
+"Innehållet i resursen \"%s\" - %d fil(er) står i konflikt med ditt projekt:"
#: editor/editor_asset_installer.cpp
+#, fuzzy
msgid "Contents of asset \"%s\" - No files conflict with your project:"
msgstr ""
+"Innehållet i resursen \"%s\" - Inga filer står i konflikt med ditt projekt:"
#: editor/editor_asset_installer.cpp
msgid "Uncompressing Assets"
msgstr "Dekomprimerar Tillgångar"
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "The following files failed extraction from asset \"%s\":"
-msgstr "Följande filer misslyckades att packas upp från paketet:"
+msgstr "Följande filer misslyckades att packas upp från paketet \"%s\":"
#: editor/editor_asset_installer.cpp
msgid "(and %s more files)"
@@ -2501,7 +2507,7 @@ msgstr "(och %s fler filer)"
#: editor/editor_asset_installer.cpp
msgid "Asset \"%s\" installed successfully!"
-msgstr "Paketet \"%s\" har installerats!"
+msgstr "Installation av tillgången \"%s\" lyckades!"
#: editor/editor_asset_installer.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -2513,9 +2519,8 @@ msgid "Install"
msgstr "Installera"
#: editor/editor_asset_installer.cpp
-#, fuzzy
msgid "Asset Installer"
-msgstr "Paketinstallerare"
+msgstr "Tillgångsinstallerare"
#: editor/editor_audio_buses.cpp
msgid "Speakers"
@@ -2696,8 +2701,9 @@ msgid "Invalid name."
msgstr "Ogiltigt namn."
#: editor/editor_autoload_settings.cpp
+#, fuzzy
msgid "Cannot begin with a digit."
-msgstr ""
+msgstr "Kan inte börja med en siffra."
#: editor/editor_autoload_settings.cpp
msgid "Valid characters:"
@@ -2762,7 +2768,7 @@ msgstr "%s är en ogiltig genväg. Filen existerar inte."
#: editor/editor_autoload_settings.cpp
msgid "%s is an invalid path. Not in resource path (res://)."
-msgstr ""
+msgstr "%s är en ogiltig genväg. Inte i resurs-genväg (res://)."
#: editor/editor_autoload_settings.cpp
msgid "Add AutoLoad"
@@ -2842,11 +2848,11 @@ msgstr "Välj"
#: editor/editor_export.cpp
msgid "Project export for platform:"
-msgstr ""
+msgstr "Projektexport för plattformen:"
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Kopiera Nod-Sökväg"
#: editor/editor_export.cpp
@@ -2929,8 +2935,8 @@ msgid ""
"Target platform requires 'PVRTC' texture compression for GLES2. Enable "
"'Import Pvrtc' in Project Settings."
msgstr ""
-"Målplattformen kräver 'PVRTC'-texturkomprimering för GLES2. Aktivera 'Import "
-"Pvrtc' i projektinställningarna."
+"Målplattformen kräver 'PVRTC' texturkomprimering för GLES2. Aktivera "
+"'Importera Pvrtc' i Projektinställningarna."
#: editor/editor_export.cpp
msgid ""
@@ -2962,7 +2968,7 @@ msgstr "Redigera Tema"
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
#: platform/uwp/export/export.cpp
msgid "Release"
-msgstr ""
+msgstr "Släpp"
#: editor/editor_export.cpp
#, fuzzy
@@ -2971,11 +2977,12 @@ msgstr "Färg enhetlig."
#: editor/editor_export.cpp
msgid "64 Bits"
-msgstr ""
+msgstr "64 bitar"
#: editor/editor_export.cpp
+#, fuzzy
msgid "Embed PCK"
-msgstr ""
+msgstr "Bädda in PCK"
#: editor/editor_export.cpp platform/osx/export/export.cpp
#, fuzzy
@@ -3037,7 +3044,7 @@ msgstr "Hantera exportmallar..."
#: editor/editor_export.cpp platform/windows/export/export.cpp
#: platform/x11/export/export.cpp
msgid "PCK Embedding"
-msgstr ""
+msgstr "PCK Inbäddning"
#: editor/editor_export.cpp
msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
@@ -3045,7 +3052,7 @@ msgstr "Den inbäddade PCK får inte vara större än 4 GiB på 32 bitars export
#: editor/editor_export.cpp
msgid "Convert Text Resources To Binary On Export"
-msgstr ""
+msgstr "Konvertera textresurser till binära vid export"
#: editor/editor_feature_profile.cpp
msgid "3D Editor"
@@ -3074,9 +3081,8 @@ msgid "FileSystem Dock"
msgstr "FilSystem"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Import Dock"
-msgstr "Importera"
+msgstr "Importera Brygga"
#: editor/editor_feature_profile.cpp
msgid "Allows to view and edit 3D scenes."
@@ -3088,17 +3094,19 @@ msgstr "Tillåter att redigera skript via den integrerade skript-redigeraren."
#: editor/editor_feature_profile.cpp
msgid "Provides built-in access to the Asset Library."
-msgstr ""
+msgstr "Ger inbyggd tillgång till tillgångsbiblioteket."
#: editor/editor_feature_profile.cpp
+#, fuzzy
msgid "Allows editing the node hierarchy in the Scene dock."
-msgstr ""
+msgstr "Tillåter redigering av nodhierarkin i scendockan."
#: editor/editor_feature_profile.cpp
msgid ""
"Allows to work with signals and groups of the node selected in the Scene "
"dock."
msgstr ""
+"Tillåter arbete med signaler och grupper av noden som valts i Scendockan."
#: editor/editor_feature_profile.cpp
msgid "Allows to browse the local file system via a dedicated dock."
@@ -3136,19 +3144,16 @@ msgid "(Editor Disabled, Properties Disabled)"
msgstr "(Editor inaktiverad, Egenskaper inaktiverad)"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "(Properties Disabled)"
-msgstr "Egenskaper"
+msgstr "(Egenskaper avstängda)"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "(Editor Disabled)"
-msgstr "Redigera Variabel"
+msgstr "(Redigeraren är avstängd)"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Class Options:"
-msgstr "Beskrivning:"
+msgstr "Klassalternativ:"
#: editor/editor_feature_profile.cpp
msgid "Enable Contextual Editor"
@@ -3185,9 +3190,8 @@ msgid "Error saving profile to path: '%s'."
msgstr "Fel vid laddning av mall '%s'."
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Reset to Default"
-msgstr "Ladda Standard"
+msgstr "Återställ till Standard"
#: editor/editor_feature_profile.cpp
msgid "Current Profile:"
@@ -3240,18 +3244,16 @@ msgid "Create or import a profile to edit available classes and properties."
msgstr ""
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "New profile name:"
-msgstr "Nytt namn:"
+msgstr "Nytt profilnamn:"
#: editor/editor_feature_profile.cpp
msgid "Godot Feature Profile"
msgstr "Godot funktions profil"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Import Profile(s)"
-msgstr "%d fler filer"
+msgstr "Importera profil(er)"
#: editor/editor_feature_profile.cpp
#, fuzzy
@@ -3285,9 +3287,8 @@ msgid "Copy Path"
msgstr "Kopiera Sökväg"
#: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp
-#, fuzzy
msgid "Open in File Manager"
-msgstr "Visa I Filhanteraren"
+msgstr "Öppna i filhanteraren"
#: editor/editor_file_dialog.cpp editor/editor_node.cpp
#: editor/filesystem_dock.cpp editor/project_manager.cpp
@@ -5547,7 +5548,7 @@ msgstr "Miniatyr..."
#: editor/editor_settings.cpp
msgid "Docks"
-msgstr ""
+msgstr "Anslutningar"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5660,6 +5661,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11287,7 +11297,7 @@ msgstr "Spela"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orthogonal"
-msgstr ""
+msgstr "Ortogonal"
#: editor/plugins/spatial_editor_plugin.cpp modules/gltf/gltf_camera.cpp
msgid "Perspective"
@@ -11454,7 +11464,7 @@ msgstr "Partiklar"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "FPS: %d (%s ms)"
-msgstr ""
+msgstr "FPS: %d (%s ms)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Top View."
@@ -12035,6 +12045,11 @@ msgid "New Animation"
msgstr "Animation"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Filtrera noder"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18984,6 +18999,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 +19012,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 +19060,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 +19304,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 +19318,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
@@ -20683,15 +20723,15 @@ msgstr "Det gick inte att hitta nyckellager, det gick inte att exportera."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Måste använda en giltigt filändelse."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20715,15 +20755,15 @@ msgstr "Ogiltigt namn."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Måste använda en giltigt filändelse."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20964,7 +21004,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 +21736,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 +21749,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 ""
@@ -21769,7 +21819,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr "Roterar %s grader."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Konstant"
@@ -23803,6 +23853,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Transformera"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24684,8 +24739,9 @@ msgid "Alpha"
msgstr ""
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
+#, fuzzy
msgid "Caret"
-msgstr ""
+msgstr "Markör"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink"
@@ -25008,6 +25064,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"
@@ -25338,9 +25399,8 @@ msgid "Draw 2D Outlines"
msgstr ""
#: scene/main/scene_tree.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Reflections"
-msgstr "Riktningar"
+msgstr "Reflektioner"
#: scene/main/scene_tree.cpp
msgid "Atlas Size"
@@ -25405,16 +25465,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
@@ -28272,12 +28333,13 @@ msgid "UV Contract Amount"
msgstr ""
#: servers/visual_server.cpp
+#, fuzzy
msgid "Use Simple PVS"
-msgstr ""
+msgstr "Använd enkel PVS"
#: servers/visual_server.cpp
msgid "PVS Logging"
-msgstr ""
+msgstr "PVS loggning"
#: servers/visual_server.cpp
#, fuzzy
@@ -28290,8 +28352,9 @@ msgid "Remove Danglers"
msgstr "Ta Bort Mall"
#: servers/visual_server.cpp
+#, fuzzy
msgid "Flip Imported Portals"
-msgstr ""
+msgstr "Vänd importerade portaler"
#: servers/visual_server.cpp
#, fuzzy
@@ -28299,8 +28362,9 @@ msgid "Occlusion Culling"
msgstr "Redigera Polygon"
#: servers/visual_server.cpp
+#, fuzzy
msgid "Max Active Spheres"
-msgstr ""
+msgstr "Max aktiva sfärer"
#: servers/visual_server.cpp
#, fuzzy
@@ -28313,13 +28377,15 @@ msgid "Shader Compilation Mode"
msgstr "Interpolationsläge"
#: servers/visual_server.cpp
+#, fuzzy
msgid "Max Simultaneous Compiles"
-msgstr ""
+msgstr "Max samtidiga kompileringar"
#: servers/visual_server.cpp
msgid "Log Active Async Compiles Count"
msgstr ""
#: servers/visual_server.cpp
+#, fuzzy
msgid "Shader Cache Size (MB)"
-msgstr ""
+msgstr "Shader Cache Storlek (MB)"
diff --git a/editor/translations/te.po b/editor/translations/te.po
index 431febd63c..af4c65f062 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
@@ -440,6 +444,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2066,14 +2074,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2129,8 +2138,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2689,8 +2698,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "సంఘం"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5259,6 +5269,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11220,6 +11238,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "గణనలà±"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -17717,6 +17740,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 +17751,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 +17796,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 +18015,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 +18029,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
@@ -19278,14 +19325,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19306,14 +19352,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19527,7 +19572,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 +20241,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 +20254,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
@@ -20265,7 +20319,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "à°¸à±à°¥à°¿à°°à°¾à°‚కాలà±"
@@ -22105,6 +22159,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "గణనలà±"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -23184,6 +23243,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 +23603,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..f1eb8b716f 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
@@ -496,6 +501,10 @@ msgid "Pressure"
msgstr "พรีเซ็ต"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "จำà¸à¸±à¸”โดยใช้ตำà¹à¸«à¸™à¹ˆà¸‡à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™"
@@ -2214,14 +2223,15 @@ msgstr "ที่ชื่นชอบ:"
msgid "Recent:"
msgstr "ล่าสุด:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "ค้นหา:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "พบ:"
@@ -2282,8 +2292,8 @@ msgstr "ค้นหาทรัพยาà¸à¸£à¸¡à¸²à¹à¸—นที่:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2865,7 +2875,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "คัดลอà¸à¸•ำà¹à¸«à¸™à¹ˆà¸‡à¹‚หนด"
#: editor/editor_export.cpp
@@ -5639,6 +5649,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "เติมที่เลือà¸à¹ƒà¸™ GridMap"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11933,6 +11952,11 @@ msgid "New Animation"
msgstr "à¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™à¹ƒà¸«à¸¡à¹ˆ"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "วิธีà¸à¸²à¸£à¸à¸£à¸­à¸‡"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "ความเร็ว:"
@@ -18936,6 +18960,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 +18973,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 +19025,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 +19271,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 +19287,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
@@ -20661,15 +20710,15 @@ msgstr "เปิดเทมเพลตเพื่อส่งออà¸à¹„ม
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "นามสà¸à¸¸à¸¥à¹„ม่ถูà¸à¸•้อง"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20693,15 +20742,15 @@ msgstr "ชื่อผิดพลาด"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "นามสà¸à¸¸à¸¥à¹„ม่ถูà¸à¸•้อง"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20946,7 +20995,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 +21756,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 +21769,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 +21801,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."
@@ -21785,7 +21844,7 @@ msgstr "à¸à¸²à¸£à¹€à¸„ลื่อนที่"
msgid "Rotation Degrees"
msgstr "หมุน %s องศา"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "คงที่"
@@ -23873,6 +23932,11 @@ msgstr ""
"เปลี่ยนขนาดของขอบเขตà¸à¸²à¸£à¸Šà¸™à¸¥à¸¹à¸à¹à¸—น"
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "เà¸à¹‡à¸š Global Transform"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25117,6 +25181,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 +25592,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 +25599,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..fec7766383 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
@@ -471,6 +476,10 @@ msgid "Pressure"
msgstr "Preset"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
#, fuzzy
msgid "Relative"
msgstr "GDNative"
@@ -2166,14 +2175,15 @@ msgstr "Mga Paborito:"
msgid "Recent:"
msgstr "Kamakailan:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Maghanap:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Mga Tugma:"
@@ -2233,8 +2243,8 @@ msgstr "Maghanap ng Pangpalit na Resource:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2804,8 +2814,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr "Kopyahin Ang Pinagpipilian"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5453,6 +5464,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11559,6 +11579,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Salain ang mga method"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Bilis:"
@@ -18258,6 +18283,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 +18296,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 +18344,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 +18582,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 +18596,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
@@ -19931,14 +19981,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -19961,14 +20010,13 @@ msgstr "Di-wastong pangalan."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -20201,7 +20249,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 +20966,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 +20979,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 +21009,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."
@@ -20990,7 +21048,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Constant"
@@ -22987,6 +23045,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Transisyon: "
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24179,6 +24242,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 +24638,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 +24645,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..ab58a87c36 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -73,13 +73,18 @@
# inci <incialien@gmail.com>, 2022.
# Ramazan Aslan <legendraslan@gmail.com>, 2022.
# paledega <paledega@yandex.ru>, 2022.
+# Yekez <yasintonge@gmail.com>, 2022.
+# Deleted User <noreply+46833@weblate.org>, 2022.
+# Emre <mr.inkaya@gmail.com>, 2022.
+# Deleted User <noreply+46858@weblate.org>, 2022.
+# Ümid Quliyev <lucifer25x@protonmail.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-08-05 01:04+0000\n"
+"Last-Translator: Ümid Quliyev <lucifer25x@protonmail.com>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/"
"godot/tr/>\n"
"Language: tr\n"
@@ -87,11 +92,11 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: 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 +104,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 +112,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"
@@ -332,15 +337,15 @@ msgstr "Transfer Modu"
#: core/io/packet_peer.cpp
msgid "Encode Buffer Max Size"
-msgstr ""
+msgstr "Kodlama ArabelleÄŸi Maksimum Boyutu"
#: core/io/packet_peer.cpp
msgid "Input Buffer Max Size"
-msgstr ""
+msgstr "GiriÅŸ ArabelleÄŸi Maksimum Boyutu"
#: core/io/packet_peer.cpp
msgid "Output Buffer Max Size"
-msgstr ""
+msgstr "Çıkış Arabelleği Maksimum Boyutu"
#: core/io/packet_peer.cpp
msgid "Stream Peer"
@@ -348,15 +353,15 @@ msgstr ""
#: core/io/stream_peer.cpp
msgid "Big Endian"
-msgstr ""
+msgstr "big-endian"
#: core/io/stream_peer.cpp
msgid "Data Array"
-msgstr ""
+msgstr "Veri Dizisi"
#: core/io/stream_peer_ssl.cpp
msgid "Blocking Handshake"
-msgstr ""
+msgstr "Tokalaşmayı blokla"
#: core/io/udp_server.cpp
msgid "Max Pending Connections"
@@ -382,12 +387,10 @@ msgid "Invalid input %d (not passed) in expression"
msgstr "İfadede geçersiz giriş %d"
#: core/math/expression.cpp
-#, fuzzy
msgid "self can't be used because instance is null (not passed)"
msgstr "self kullanılamaz çünkü örnek boş (geçilmedi)"
#: core/math/expression.cpp
-#, fuzzy
msgid "Invalid operands to operator %s, %s and %s."
msgstr "\"%s\" işlecinde geçersiz terimler, '%s' ve '%s'."
@@ -410,7 +413,7 @@ msgstr "'%s' çağrıldığında:"
#: core/math/random_number_generator.cpp
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Seed"
-msgstr ""
+msgstr "Tohum"
#: core/math/random_number_generator.cpp
msgid "State"
@@ -425,14 +428,12 @@ msgid "Max Size (KB)"
msgstr "En Büyük Boyut (KB)"
#: core/os/input.cpp
-#, fuzzy
msgid "Mouse Mode"
-msgstr "Biçimi Taşı"
+msgstr "Fare Modu"
#: core/os/input.cpp
-#, fuzzy
msgid "Use Accumulated Input"
-msgstr "GiriÅŸi Sil"
+msgstr "BirikmiÅŸ Girdiyi Kullan"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
@@ -448,12 +449,10 @@ msgid "Shift"
msgstr "Shift"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Control"
-msgstr "Ctrl"
+msgstr "Kontrol TuÅŸu"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Meta"
msgstr "Meta"
@@ -461,6 +460,10 @@ msgstr "Meta"
msgid "Command"
msgstr "Komut"
+#: core/os/input_event.cpp
+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
@@ -468,7 +471,6 @@ msgid "Pressed"
msgstr "Basılmış"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Scancode"
msgstr "Tarama kodu"
@@ -477,14 +479,12 @@ msgid "Physical Scancode"
msgstr "Fiziksel TuÅŸ Kodu"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Unicode"
-msgstr "Unicode"
+msgstr "Evrensel Kod"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Echo"
-msgstr "Eko"
+msgstr "Yankı"
#: core/os/input_event.cpp scene/gui/base_button.cpp
msgid "Button Mask"
@@ -495,9 +495,8 @@ msgid "Global Position"
msgstr "Global Pozisyon"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Factor"
-msgstr "Vektör"
+msgstr "Etken"
#: core/os/input_event.cpp
msgid "Button Index"
@@ -516,6 +515,11 @@ msgid "Pressure"
msgstr "Baskı"
#: core/os/input_event.cpp
+#, fuzzy
+msgid "Pen Inverted"
+msgstr "Ters Kalem"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Göreceli"
@@ -574,18 +578,16 @@ msgid "Velocity"
msgstr "Hız"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Instrument"
msgstr "Alet"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Controller Number"
-msgstr "Satır Numarası:"
+msgstr "Denetleyici Numarası"
#: core/os/input_event.cpp
msgid "Controller Value"
-msgstr ""
+msgstr "Denetleyici DeÄŸeri"
#: core/project_settings.cpp editor/editor_node.cpp main/main.cpp
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
@@ -709,7 +711,7 @@ msgstr "Ana Sahne DeÄŸiÅŸtirgenleri:"
#: core/project_settings.cpp
#, fuzzy
msgid "Scene Naming"
-msgstr "Sahne Yolu:"
+msgstr "Sahne Adlandırma"
#: core/project_settings.cpp
msgid "Search In File Extensions"
@@ -722,12 +724,12 @@ msgstr "Script Dosyalarını Aramak İçin Dosya Yolu"
#: core/project_settings.cpp
#, fuzzy
msgid "Version Control Autoload On Startup"
-msgstr "Başlangıçta Otomatik Yükleme"
+msgstr "Başlangıçta Otomatik Sürüm Kontrolü"
#: core/project_settings.cpp
#, fuzzy
msgid "Version Control Plugin Name"
-msgstr "Sürüm Kontrol"
+msgstr "Sürüm Denetimi Eklenti Adı"
#: core/project_settings.cpp scene/2d/collision_object_2d.cpp
#: scene/3d/collision_object.cpp scene/gui/control.cpp
@@ -911,7 +913,6 @@ msgid "Modules"
msgstr "Modüller"
#: core/register_core_types.cpp
-#, fuzzy
msgid "TCP"
msgstr "TCP"
@@ -920,8 +921,9 @@ msgid "Connect Timeout Seconds"
msgstr "Bağlanma Zaman Aşımı Süresi(Saniye)"
#: core/register_core_types.cpp
+#, fuzzy
msgid "Packet Peer Stream"
-msgstr ""
+msgstr "Paket Eş Akışı"
#: core/register_core_types.cpp
msgid "Max Buffer (Power of 2)"
@@ -967,7 +969,7 @@ msgstr "Deneme"
#: core/translation.cpp scene/resources/font.cpp
msgid "Fallback"
-msgstr ""
+msgstr "Geri Dönüş"
#: core/ustring.cpp scene/resources/segment_shape_2d.cpp
msgid "B"
@@ -1008,12 +1010,12 @@ msgstr "Arabellek"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Canvas Polygon Buffer Size (KB)"
-msgstr ""
+msgstr "Tuval Çokgen Arabellek Boyutu (KB)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
msgid "Canvas Polygon Index Buffer Size (KB)"
-msgstr ""
+msgstr "Tuval Çokgen Dizini Arabellek Boyutu (KB)"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp editor/editor_settings.cpp
@@ -1029,36 +1031,33 @@ msgstr "2D"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
-#, fuzzy
msgid "Snapping"
msgstr "Akıllı Hizalama"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
-#, fuzzy
msgid "Use GPU Pixel Snap"
msgstr "Piksel Yapışması Kullan"
#: drivers/gles2/rasterizer_scene_gles2.cpp
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Immediate Buffer Size (KB)"
-msgstr ""
+msgstr "Anlık Arabellek Boyutu (KB)"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
-#, fuzzy
msgid "Lightmapping"
-msgstr "Işık-Haritalarını Pişir"
+msgstr "Işık Haritalama"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
+#, fuzzy
msgid "Use Bicubic Sampling"
-msgstr ""
+msgstr "Bicubic Örneklemeyi Kullanın"
#: drivers/gles3/rasterizer_scene_gles3.cpp
-#, fuzzy
msgid "Max Renderable Elements"
-msgstr "Maks. Renderlanabilinecek Ögeler"
+msgstr "Maksimum İşlenebilir Öğeler"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Max Renderable Lights"
@@ -1095,11 +1094,12 @@ msgstr "Yüzeyi Takip Et"
#: drivers/gles3/rasterizer_scene_gles3.cpp
msgid "Weight Samples"
-msgstr ""
+msgstr "Ağırlık Örnekleri"
#: drivers/gles3/rasterizer_scene_gles3.cpp
+#, fuzzy
msgid "Voxel Cone Tracing"
-msgstr ""
+msgstr "Işın İzleme"
#: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp
msgid "High Quality"
@@ -1107,7 +1107,7 @@ msgstr "Yüksek Kalite"
#: drivers/gles3/rasterizer_storage_gles3.cpp
msgid "Blend Shape Max Buffer Size (KB)"
-msgstr ""
+msgstr "Karışım Şekli Maksimum Arabellek Boyutu (KB)"
#. TRANSLATORS: Adjective, refers to the mode for Bezier handles (Free, Balanced, Mirror).
#: editor/animation_bezier_editor.cpp
@@ -1181,9 +1181,8 @@ msgstr "Animasyon Değişikliği Çağrısı"
#: editor/animation_track_editor.cpp scene/2d/animated_sprite.cpp
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Frame"
-msgstr "Kare %"
+msgstr "Kare"
#: editor/animation_track_editor.cpp editor/editor_profiler.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
@@ -1238,8 +1237,9 @@ msgstr "Tutamacı Ayarla"
#: editor/import/resource_importer_texture.cpp
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
+#, fuzzy
msgid "Stream"
-msgstr ""
+msgstr "Aktarım"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -1400,7 +1400,7 @@ msgstr "Tür:"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "(Invalid, expected type: %s)"
-msgstr "Geçersiz Dışa Aktarım Şablonu:"
+msgstr "(Geçersiz Dışa Aktarım Şablonu: %s)"
#: editor/animation_track_editor.cpp
msgid "Easing:"
@@ -1419,22 +1419,22 @@ msgstr "Tutamacı Ayarla"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "Stream:"
-msgstr "Radyo Ögesi"
+msgstr "Aktarım:"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "Start (s):"
-msgstr "Yeniden BaÅŸlat (sn):"
+msgstr "Başlangıç (lar):"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "End (s):"
-msgstr "Açılma (sn):"
+msgstr "BitiÅŸ (ler):"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "Animation Clip:"
-msgstr "Animasyonlar:"
+msgstr "Animasyon Klibi:"
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
@@ -1525,7 +1525,7 @@ msgstr "Düzenleyici"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#, fuzzy
msgid "Confirm Insert Track"
-msgstr "Animasyon İz & Anahtar Ekle"
+msgstr "Parça Eklemeyi Onayla"
#. TRANSLATORS: %s will be replaced by a phrase describing the target of track.
#: editor/animation_track_editor.cpp
@@ -1652,7 +1652,7 @@ msgstr "Yöntem İz Anahtarı Ekle"
#: editor/animation_track_editor.cpp
#, fuzzy
msgid "Method not found in object:"
-msgstr "Metot, nesne içinde bulunamadı: "
+msgstr "Metot, nesne içinde bulunamadı:"
#: editor/animation_track_editor.cpp
msgid "Anim Move Keys"
@@ -2185,14 +2185,15 @@ msgstr "BeÄŸeniler:"
msgid "Recent:"
msgstr "Yakın zamanda:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Ara:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "EÅŸleÅŸmeler:"
@@ -2252,8 +2253,8 @@ msgstr "Yerine Geçecek Kaynak Ara:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2261,8 +2262,9 @@ msgid "Open"
msgstr "Aç"
#: editor/dependency_editor.cpp
+#, fuzzy
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "Sahipleri: %s (Toplam: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2621,7 +2623,7 @@ msgstr "'%s' dosyası bulunamadı."
#: editor/editor_audio_buses.cpp
#, fuzzy
msgid "Layout:"
-msgstr "Yerleşim Düzeni"
+msgstr "Yerleşim Düzeni:"
#: editor/editor_audio_buses.cpp
msgid "Invalid file, not an audio bus layout."
@@ -2672,7 +2674,7 @@ msgstr "Yeni bir Bus Yerleşim Düzeni oluştur."
#: editor/editor_audio_buses.cpp
#, fuzzy
msgid "Audio Bus Layout"
-msgstr "Audio Bus Yerleşim Düzenini Aç"
+msgstr "Ses Veri Yolu Düzeni"
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -2824,23 +2826,24 @@ msgid "Choose"
msgstr "Seç"
#: editor/editor_export.cpp
+#, fuzzy
msgid "Project export for platform:"
-msgstr ""
+msgstr "Platform için proje dışa aktarımı:"
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
-msgstr "Düğüm Yolunu Kopyala"
+msgid "Completed with warnings."
+msgstr "Hatalarla tamamlandı."
#: editor/editor_export.cpp
#, fuzzy
msgid "Completed successfully."
-msgstr "Paket Başarı ile Kuruldu!"
+msgstr "Başarıyla tamamlandı."
#: editor/editor_export.cpp
#, fuzzy
msgid "Failed."
-msgstr "Başarısız:"
+msgstr "Başarısız."
#: editor/editor_export.cpp
msgid "Storing File:"
@@ -2857,27 +2860,27 @@ msgstr "Çıkınla"
#: editor/editor_export.cpp
#, fuzzy
msgid "Save PCK"
-msgstr "Farklı Kaydet"
+msgstr "PCK'yi kaydet"
#: editor/editor_export.cpp
#, fuzzy
msgid "Cannot create file \"%s\"."
-msgstr "Klasör oluşturulamadı."
+msgstr "\"%s\" dosyası oluşturulamıyor."
#: editor/editor_export.cpp
#, fuzzy
msgid "Failed to export project files."
-msgstr "Proje dosyaları dışa aktarılamadı"
+msgstr "Proje dosyaları dışa aktarılamadı."
#: editor/editor_export.cpp
#, fuzzy
msgid "Can't open file to read from path \"%s\"."
-msgstr "Dosya yazmak için açılamıyor:"
+msgstr "\"%s\" yolundan okunacak dosya açılamıyor."
#: editor/editor_export.cpp
#, fuzzy
msgid "Save ZIP"
-msgstr "Farklı Kaydet"
+msgstr "ZIP dosyasını kaydet"
#: editor/editor_export.cpp
msgid ""
@@ -2940,7 +2943,7 @@ msgstr ""
#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Custom Template"
-msgstr "Editör Teması"
+msgstr "Özel Şablon"
#: editor/editor_export.cpp editor/project_export.cpp
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
@@ -2952,36 +2955,42 @@ msgstr "Yayınlamak"
#: editor/editor_export.cpp
#, fuzzy
msgid "Binary Format"
-msgstr "Renk operatörü."
+msgstr "Çift Biçim"
#: editor/editor_export.cpp
+#, fuzzy
msgid "64 Bits"
-msgstr ""
+msgstr "64 Bit"
#: editor/editor_export.cpp
+#, fuzzy
msgid "Embed PCK"
-msgstr ""
+msgstr "PCK'yı yerleştirin"
#: editor/editor_export.cpp platform/osx/export/export.cpp
#, fuzzy
msgid "Texture Format"
-msgstr "DokuBölgesi"
+msgstr "Doku Biçimi"
#: editor/editor_export.cpp
+#, fuzzy
msgid "BPTC"
-msgstr ""
+msgstr "BPTC"
#: editor/editor_export.cpp platform/osx/export/export.cpp
+#, fuzzy
msgid "S3TC"
-msgstr ""
+msgstr "S3TC"
#: editor/editor_export.cpp platform/osx/export/export.cpp
+#, fuzzy
msgid "ETC"
-msgstr ""
+msgstr "ETC"
#: editor/editor_export.cpp platform/osx/export/export.cpp
+#, fuzzy
msgid "ETC2"
-msgstr ""
+msgstr "ETC2"
#: editor/editor_export.cpp
#, fuzzy
@@ -3003,7 +3012,7 @@ msgstr "Özel yayınlama şablonu bulunamadı."
#: editor/editor_export.cpp
#, fuzzy
msgid "Prepare Template"
-msgstr "Şablonlarını Yönet"
+msgstr "Şablon Hazırla"
#: editor/editor_export.cpp platform/osx/export/export.cpp
#, fuzzy
@@ -3013,12 +3022,12 @@ msgstr "Belirtilen Dışa aktarım yolu mevcut değil:"
#: editor/editor_export.cpp platform/javascript/export/export.cpp
#, fuzzy
msgid "Template file not found: \"%s\"."
-msgstr "Şablon dosyası bulunamadı:"
+msgstr "Şablon dosyası bulunamadı: \"%s\"."
#: editor/editor_export.cpp
#, fuzzy
msgid "Failed to copy export template."
-msgstr "Geçersiz Dışa Aktarım Şablonu:"
+msgstr "Dışa aktarma şablonu kopyalanamadı."
#: editor/editor_export.cpp platform/windows/export/export.cpp
#: platform/x11/export/export.cpp
@@ -3031,8 +3040,9 @@ msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
msgstr "32-bit dışa aktarımlarda gömülü PCK 4GiB'tan büyük olamaz."
#: editor/editor_export.cpp
+#, fuzzy
msgid "Convert Text Resources To Binary On Export"
-msgstr ""
+msgstr "Dışa Aktarmada Metin Kaynaklarını İkili Dosyaya Dönüştür"
#: editor/editor_feature_profile.cpp
msgid "3D Editor"
@@ -3243,7 +3253,7 @@ msgstr "Dışa Aktarım Şablonlarını Yönet"
#: editor/editor_feature_profile.cpp
#, fuzzy
msgid "Default Feature Profile"
-msgstr "Godot Özellik Profili"
+msgstr "Varsayılan Özellik Profili"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Select Current Folder"
@@ -3317,12 +3327,12 @@ msgstr "Bir Dosya Kaydet"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
#, fuzzy
msgid "Access"
-msgstr "Başarılı!"
+msgstr "EriÅŸim"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
#, fuzzy
msgid "Display Mode"
-msgstr "Oynatma Modu:"
+msgstr "Ekran Modu"
#: editor/editor_file_dialog.cpp
#: editor/import/resource_importer_layered_texture.cpp
@@ -3337,32 +3347,33 @@ msgstr "Oynatma Modu:"
#: servers/audio/effects/audio_effect_distortion.cpp
#, fuzzy
msgid "Mode"
-msgstr "Kaydırma Biçimi"
+msgstr "Mod"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
#, fuzzy
msgid "Current Dir"
-msgstr "Geçerli:"
+msgstr "Geçerli Dizin"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
#, fuzzy
msgid "Current File"
-msgstr "Åžu Anki Profil:"
+msgstr "Geçerli Dosya"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
#, fuzzy
msgid "Current Path"
-msgstr "Geçerli:"
+msgstr "Geçerli Yol"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
#: scene/gui/file_dialog.cpp
#, fuzzy
msgid "Show Hidden Files"
-msgstr "Gizli Dosyalari Aç / Kapat"
+msgstr "Gizli Dosyaları Göster"
#: editor/editor_file_dialog.cpp
+#, fuzzy
msgid "Disable Overwrite Warning"
-msgstr ""
+msgstr "Üzerine Yazma Uyarısını Devre Dışı Bırak"
#: editor/editor_file_dialog.cpp
msgid "Go Back"
@@ -3464,8 +3475,9 @@ msgid "(Re)Importing Assets"
msgstr "Varlıklar Yeniden-İçe Aktarılıyor"
#: editor/editor_file_system.cpp
+#, fuzzy
msgid "Reimport Missing Imported Files"
-msgstr ""
+msgstr "İçe Aktarılan Eksik Dosyaları Yeniden İçe Aktar"
#: editor/editor_help.cpp scene/2d/camera_2d.cpp scene/gui/control.cpp
#: scene/gui/nine_patch_rect.cpp scene/resources/dynamic_font.cpp
@@ -3497,7 +3509,7 @@ msgstr "Özellikler"
#: editor/editor_help.cpp
#, fuzzy
msgid "overrides %s:"
-msgstr "% üzerine yazılmışlar:"
+msgstr "%s'yi geçersiz kılar:"
#: editor/editor_help.cpp
msgid "default:"
@@ -3569,7 +3581,7 @@ msgstr ""
#: modules/gdscript/gdscript_editor.cpp
#, fuzzy
msgid "Text Editor"
-msgstr "Düzenleyiciyi Aç"
+msgstr "Metin Düzenleyici"
#: editor/editor_help.cpp editor/editor_node.cpp editor/editor_settings.cpp
#: editor/plugins/shader_editor_plugin.cpp
@@ -3577,8 +3589,9 @@ msgid "Help"
msgstr "Yardım"
#: editor/editor_help.cpp
+#, fuzzy
msgid "Sort Functions Alphabetically"
-msgstr ""
+msgstr "Fonksiyonları Alfabetik Olarak Sırala"
#: editor/editor_help_search.cpp editor/editor_node.cpp
#: editor/plugins/script_editor_plugin.cpp
@@ -3660,34 +3673,34 @@ msgstr "Özellik:"
#: editor/editor_inspector.cpp editor/editor_spin_slider.cpp
#, fuzzy
msgid "Label"
-msgstr "DeÄŸer"
+msgstr "Etiket"
#: editor/editor_inspector.cpp editor/editor_spin_slider.cpp
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Read Only"
-msgstr "Sadece Metotlar"
+msgstr "Sadece Okunur"
#: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp
#, fuzzy
msgid "Checkable"
-msgstr "Öğeyi Denetle"
+msgstr "Kontrol edilebilir"
#: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
msgid "Checked"
-msgstr "Denetlenen Öğe"
+msgstr "Kontrol edildi"
#: editor/editor_inspector.cpp
#, fuzzy
msgid "Draw Red"
-msgstr "Çizim Çağrıları:"
+msgstr "Kırmızı Çiz"
#: editor/editor_inspector.cpp
#, fuzzy
msgid "Keying"
-msgstr "Oynat"
+msgstr "Anahtarlama"
#: editor/editor_inspector.cpp
msgid "Pin value"
@@ -4052,12 +4065,12 @@ msgstr "Betiği Hızlı Aç..."
#: editor/editor_node.cpp
#, fuzzy
msgid "Save & Reload"
-msgstr "Kaydet ve BaÅŸtan BaÅŸlat"
+msgstr "Kaydet ve Yeniden Yükle"
#: editor/editor_node.cpp
#, fuzzy
msgid "Save changes to '%s' before reloading?"
-msgstr "Kapatmadan önce değişklikler buraya '%s' kaydedilsin mi?"
+msgstr "Çıkmadan önce değişiklikler '%s' ‘ye kaydedilsin mi?"
#: editor/editor_node.cpp
msgid "Save & Close"
@@ -4178,7 +4191,7 @@ msgstr "Proje Yöneticisi Açılsın Mı?"
#: editor/editor_node.cpp
#, fuzzy
msgid "Save changes to the following scene(s) before reloading?"
-msgstr "Çıkmadan önce değişiklikler aşağıdaki sahne(ler)e kaydedilsin mi?"
+msgstr "Çıkmadan önce değişiklikler sahne(ler)e kaydedilsin mi?"
#: editor/editor_node.cpp
msgid "Save & Quit"
@@ -4362,54 +4375,53 @@ msgid "%d more files"
msgstr "%d daha fazla dosyalar"
#: editor/editor_node.cpp
+#, fuzzy
msgid ""
"Unable to write to file '%s', file in use, locked or lacking permissions."
msgstr ""
+"'%s' dosyasına yazılamıyor, dosya kullanımda, kilitli veya izinler eksik."
#: editor/editor_node.cpp editor/editor_settings.cpp editor/scene_tree_dock.cpp
#: servers/arvr/arvr_interface.cpp
-#, fuzzy
msgid "Interface"
-msgstr "Kullanıcı Arayüzü"
+msgstr "Arayüz"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Scene Tabs"
-msgstr "Sahne Sekmesine Geç"
+msgstr "Sahne Sekmeleri"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Always Show Close Button"
-msgstr "Daima Izgarayı Göster"
+msgstr "Daima Kapatma Düğmesini Göster"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Resize If Many Tabs"
-msgstr ""
+msgstr "Çok Sayıda Sekme Varsa Yeniden Boyutlandır"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Minimum Width"
-msgstr ""
+msgstr "Minimum GeniÅŸlik"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Output"
msgstr "Çıktı"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Always Clear Output On Play"
-msgstr "Çıktıyı Temizle"
+msgstr "Oynatıldığında Çıktıyı Daima Temizle"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Open Output On Play"
-msgstr ""
+msgstr "Oynatıldığında Çıktıyı Daima Aç"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Close Output On Stop"
-msgstr ""
+msgstr "Durdurulduğunda Çıktıyı Daima Kapat"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Save On Focus Loss"
-msgstr ""
+msgstr "Odak Kaybından Tasarruf Edin"
#: editor/editor_node.cpp editor/editor_settings.cpp
#, fuzzy
@@ -4446,8 +4458,9 @@ msgid "Restore Scenes On Load"
msgstr "Sahne Düğümünü Al"
#: editor/editor_node.cpp editor/editor_settings.cpp
+#, fuzzy
msgid "Show Thumbnail On Hover"
-msgstr ""
+msgstr "Fareyle üzerine gelindiğinde  küçük resmi  göster"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Inspector"
@@ -4473,11 +4486,11 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Horizontal Vector2 Editing"
-msgstr ""
+msgstr "Yatay Vector2 Düzenleme"
#: editor/editor_node.cpp
msgid "Horizontal Vector Types Editing"
-msgstr ""
+msgstr "Yatay Vector tipleri düzenleme"
#: editor/editor_node.cpp
#, fuzzy
@@ -4490,8 +4503,9 @@ msgid "Resources To Open In New Inspector"
msgstr "Gözetmen Bölümünde Aç"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Default Color Picker Mode"
-msgstr ""
+msgstr "Varsayılan renk seçme modu"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "Version Control"
@@ -5225,9 +5239,8 @@ msgid "Size:"
msgstr "Boyut:"
#: editor/editor_properties_array_dict.cpp
-#, fuzzy
msgid "Page:"
-msgstr "Sayfa: "
+msgstr "Sayfa:"
#: editor/editor_properties_array_dict.cpp
#: editor/plugins/theme_editor_plugin.cpp
@@ -5368,19 +5381,19 @@ msgstr "Hepsini Görüntüle"
#: editor/editor_settings.cpp
msgid "Custom Display Scale"
-msgstr ""
+msgstr "Özel Ekran Ölçeği"
#: editor/editor_settings.cpp
msgid "Main Font Size"
-msgstr ""
+msgstr "Ana font ölçüsü"
#: editor/editor_settings.cpp
msgid "Code Font Size"
-msgstr ""
+msgstr "Kod font'u ölçüsü"
#: editor/editor_settings.cpp
msgid "Font Antialiased"
-msgstr ""
+msgstr "Kenarı yumuşatılmış font"
#: editor/editor_settings.cpp
msgid "Font Hinting"
@@ -5393,7 +5406,7 @@ msgstr "Ana Sahne"
#: editor/editor_settings.cpp
msgid "Main Font Bold"
-msgstr ""
+msgstr "Ana font kalınlığı"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5401,8 +5414,9 @@ msgid "Code Font"
msgstr "Düğüm Noktası Ekle"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Dim Editor On Dialog Popup"
-msgstr ""
+msgstr "İletişim penceresinde Dim Editörü"
#: editor/editor_settings.cpp main/main.cpp
msgid "Low Processor Mode Sleep (µsec)"
@@ -5419,11 +5433,12 @@ msgstr "Dikkat Dağıtmayan Kip"
#: editor/editor_settings.cpp
msgid "Automatically Open Screenshots"
-msgstr ""
+msgstr "Otomatik olarak ekran görüntülerini aç"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Max Array Dictionary Items Per Page"
-msgstr ""
+msgstr "Her sayfada maks dizi sözlüğü öğesi"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp
@@ -5437,7 +5452,7 @@ msgstr "Ön ayar"
#: editor/editor_settings.cpp
msgid "Icon And Font Color"
-msgstr ""
+msgstr "Simge ve Font rengi"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5451,7 +5466,7 @@ msgstr "Renk Seç"
#: editor/editor_settings.cpp scene/resources/environment.cpp
msgid "Contrast"
-msgstr ""
+msgstr "Kontrast"
#: editor/editor_settings.cpp
msgid "Relationship Line Opacity"
@@ -5527,7 +5542,7 @@ msgstr "Küçük Resim..."
#: editor/editor_settings.cpp
msgid "Docks"
-msgstr ""
+msgstr "Eklentiler"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5549,8 +5564,9 @@ msgid "Property Editor"
msgstr "Grup Düzenleyici"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Auto Refresh Interval"
-msgstr ""
+msgstr "Otomatik yenileme intervalı"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5565,7 +5581,7 @@ msgstr "Editör Teması"
#: editor/editor_settings.cpp scene/3d/label_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Line Spacing"
-msgstr ""
+msgstr "Satır aralığı"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
#: modules/gdscript/editor/gdscript_highlighter.cpp
@@ -5584,7 +5600,7 @@ msgstr ""
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Highlight Current Line"
-msgstr ""
+msgstr "Geçerli satırı vurgula"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
msgid "Highlight Type Safe Lines"
@@ -5623,11 +5639,11 @@ msgstr "Gezinim"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Smooth Scrolling"
-msgstr ""
+msgstr "Pürüzsüz kaydırma"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "V Scroll Speed"
-msgstr ""
+msgstr "V kaydırma hızı"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5636,15 +5652,25 @@ msgstr "Başlatımı Göster"
#: editor/editor_settings.cpp
msgid "Minimap Width"
-msgstr ""
+msgstr "Küçük Harita Genişliği"
#: editor/editor_settings.cpp
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
+#, fuzzy
+msgid "Stay In Script Editor On Node Selected"
+msgstr "Seçilmiş Düğümde Script Editöründe Kal"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
-msgstr ""
+msgstr "Dış görünüş"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
#, fuzzy
@@ -5670,12 +5696,14 @@ msgid "Show Info Gutter"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Code Folding"
-msgstr ""
+msgstr "Kod katlama"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Word Wrap"
-msgstr ""
+msgstr "Kelime Paketle"
#: editor/editor_settings.cpp
msgid "Show Line Length Guidelines"
@@ -5696,7 +5724,7 @@ msgstr "Kod Düzenleyici"
#: editor/editor_settings.cpp
msgid "Show Members Overview"
-msgstr ""
+msgstr "Üyelerin Genel Bakışını Göster"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
#, fuzzy
@@ -5713,16 +5741,19 @@ msgid "Autosave Interval Secs"
msgstr ""
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
+#, fuzzy
msgid "Restore Scripts On Load"
-msgstr ""
+msgstr "Script'leri Yüklemede Eski Haline Getir"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Auto Reload And Parse Scripts On Save"
-msgstr ""
+msgstr "Kaydederken Script'leri Otomatik Tekrar yükle ve Ayrıştır"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Auto Reload Scripts On External Change"
-msgstr ""
+msgstr "Dış Değişiklikte Otomatik Olarak Script'i Geri Yükle"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5735,11 +5766,11 @@ msgstr ""
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Cursor"
-msgstr ""
+msgstr "İmleç"
#: editor/editor_settings.cpp
msgid "Scroll Past End Of File"
-msgstr ""
+msgstr "Dosyanın Sonunu Kaydır"
#: editor/editor_settings.cpp
msgid "Block Caret"
@@ -5775,7 +5806,7 @@ msgstr ""
#: editor/editor_settings.cpp
msgid "Code Complete Delay"
-msgstr ""
+msgstr "Kod Tamamlama Gecikme Süresi"
#: editor/editor_settings.cpp
msgid "Put Callhint Tooltip Below Current Line"
@@ -5832,12 +5863,14 @@ msgid "Preview Size"
msgstr "Önizleme"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Primary Grid Color"
-msgstr ""
+msgstr "Birincil Izgara Rengi"
#: editor/editor_settings.cpp
+#, fuzzy
msgid "Secondary Grid Color"
-msgstr ""
+msgstr "İkincil Izgara Rengi"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5874,7 +5907,7 @@ msgstr "Nokta"
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
msgid "Shape"
-msgstr ""
+msgstr "Åžekil"
#: editor/editor_settings.cpp
#, fuzzy
@@ -5986,7 +6019,7 @@ msgstr "Gezinim Kipi"
#: editor/editor_settings.cpp
msgid "Orbit Sensitivity"
-msgstr ""
+msgstr "Yörünge Hassasiyeti"
#: editor/editor_settings.cpp
msgid "Orbit Inertia"
@@ -6189,7 +6222,7 @@ msgstr "Önden Görünüm"
#: modules/gdscript/language_server/gdscript_language_server.cpp
#, fuzzy
msgid "Remote Host"
-msgstr "Uzak "
+msgstr "Uzak Ana Bilgisayar"
#: editor/editor_settings.cpp
#: modules/gdscript/language_server/gdscript_language_server.cpp
@@ -7184,7 +7217,7 @@ msgstr "İfade"
#: editor/import/resource_importer_obj.cpp
#, fuzzy
msgid "Optimize Mesh Flags"
-msgstr "Boyut: "
+msgstr "Boyut:"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Single Scene"
@@ -7388,7 +7421,7 @@ msgstr "Işık-haritaları Üretiliyor"
#: editor/import/resource_importer_scene.cpp
#, fuzzy
msgid "Generating for Mesh:"
-msgstr "Örüntü için Üretiliyor: "
+msgstr "Örüntü için Üretiliyor:"
#: editor/import/resource_importer_scene.cpp
msgid "Running Custom Script..."
@@ -7488,7 +7521,7 @@ msgstr "Rastgele Ölçek:"
#: editor/import/resource_importer_texture.cpp
#, fuzzy
msgid "Size Limit"
-msgstr "Boyut: "
+msgstr "Boyut Limiti"
#: editor/import/resource_importer_texture.cpp
msgid "Detect 3D"
@@ -8411,7 +8444,7 @@ msgstr ""
#: editor/plugins/animation_state_machine_editor.cpp
#, fuzzy
msgid "Transition:"
-msgstr "Geçiş: "
+msgstr "Geçiş:"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Play Mode:"
@@ -10180,7 +10213,7 @@ msgstr "Oylum"
#: editor/plugins/particles_editor_plugin.cpp
#, fuzzy
msgid "Emission Source:"
-msgstr "Emisyon Kaynağı: "
+msgstr "Emisyon Kaynağı:"
#: editor/plugins/particles_editor_plugin.cpp
msgid "A processor material of type 'ParticlesMaterial' is required."
@@ -11278,15 +11311,13 @@ msgstr "Çevir"
#. TRANSLATORS: Refers to changing the scale of a node in the 3D editor.
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Scaling:"
-msgstr "Ölçekleniyor: "
+msgstr "Ölçekleniyor:"
#. TRANSLATORS: Refers to changing the position of a node in the 3D editor.
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Translating:"
-msgstr "Çeviriliyor: "
+msgstr "Çevriliyor:"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
@@ -11828,19 +11859,17 @@ msgid "Sprite"
msgstr "HayaliÇizimlik"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Simplification:"
-msgstr "SadeleÅŸtirme: "
+msgstr "SadeleÅŸtirme:"
#: editor/plugins/sprite_editor_plugin.cpp
#, fuzzy
msgid "Shrink (Pixels):"
-msgstr "Sıkıştır (Pikselleri): "
+msgstr "Sıkıştır (Pikselleri):"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Grow (Pixels):"
-msgstr "Büyüt (Pikselleri): "
+msgstr "Büyüt (Piksel):"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Update Preview"
@@ -11903,6 +11932,11 @@ msgid "New Animation"
msgstr "Yeni Animasyon"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Metotları filtrele"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Hız:"
@@ -13293,7 +13327,6 @@ msgid "Select SSH private key path"
msgstr "SSH özel anahtar yolu seç"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "SSH Passphrase"
msgstr "SSH Parolası"
@@ -16002,7 +16035,7 @@ msgstr "Düğüm Betiği İliştir"
#: editor/script_editor_debugger.cpp
#, fuzzy
msgid "Remote %s:"
-msgstr "Uzak "
+msgstr "Uzak %s:"
#: editor/script_editor_debugger.cpp
msgid "Bytes:"
@@ -17062,9 +17095,8 @@ msgid "Disabled GDNative Singleton"
msgstr "GDNative İskeleti Pasifleştirildi"
#: modules/gdnative/gdnative_library_singleton_editor.cpp
-#, fuzzy
msgid "Libraries:"
-msgstr "Kütüphaneler: "
+msgstr "Kütüphaneler:"
#: modules/gdnative/nativescript/nativescript.cpp
#, fuzzy
@@ -17968,7 +18000,7 @@ msgstr ""
#: modules/visual_script/visual_script.cpp
#, fuzzy
msgid "Node returned an invalid sequence output:"
-msgstr "Düğüm geçersiz bir dizi çıktısı döndürdü: "
+msgstr "Düğüm geçersiz bir dizi çıktısı döndürdü:"
#: modules/visual_script/visual_script.cpp
msgid "Found sequence bit but not the node in the stack, report bug!"
@@ -18330,8 +18362,9 @@ msgid "if (cond) is:"
msgstr ""
#: modules/visual_script/visual_script_flow_control.cpp
+#, fuzzy
msgid "While"
-msgstr "While"
+msgstr "Sürece"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "while (cond):"
@@ -18860,6 +18893,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 +18906,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 +18959,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 +19208,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 +19228,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 ""
+"\"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 ""
"\"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."
@@ -20609,15 +20672,15 @@ msgstr "Anahtar deposu bulunamadı, dışa aktarılamadı."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Geçersiz uzantı."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20641,15 +20704,15 @@ msgstr "Geçersiz ad."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Geçersiz uzantı."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20894,7 +20957,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 +21730,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 +21743,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 +21775,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 ""
@@ -21748,7 +21821,7 @@ msgstr "Seyahat"
msgid "Rotation Degrees"
msgstr "%s Düzey Dönüyor."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Genel Sabit"
@@ -22016,7 +22089,7 @@ msgstr "Kenar BoÅŸluk Belirle"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#, fuzzy
msgid "Sync To Physics"
-msgstr " (Fiziksel)"
+msgstr "FiziÄŸe Senkronize Et"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#, fuzzy
@@ -23520,7 +23593,7 @@ msgstr "Bir RoomGroup, bir Portal'ın çocuğu veya torunu olmamalıdır."
#: scene/3d/portal.cpp
#, fuzzy
msgid "Portal Active"
-msgstr " [portallar aktif]"
+msgstr "Portal Aktif"
#: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp
msgid "Two Way"
@@ -23887,6 +23960,11 @@ msgstr ""
"Bunun yerine alt düğümlerde çarpışma şekillerindeki boyutu değiştirin."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Bütünsel Dönüşümü Tut"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24806,7 +24884,7 @@ msgstr ""
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Caret"
-msgstr ""
+msgstr "Karet"
#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp
msgid "Blink"
@@ -25148,6 +25226,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 +25642,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 +25649,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 ""
@@ -25726,14 +25806,12 @@ msgid "3D Render"
msgstr "OluÅŸturucu:"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "2D Physics"
-msgstr " (Fiziksel)"
+msgstr "2B Fizik"
#: scene/register_scene_types.cpp
-#, fuzzy
msgid "3D Physics"
-msgstr " (Fiziksel)"
+msgstr "3B Fizik"
#: scene/register_scene_types.cpp
#, fuzzy
diff --git a/editor/translations/uk.po b/editor/translations/uk.po
index 719dc29d7a..d87aa168d7 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-26 01:55+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.14-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
@@ -463,6 +467,11 @@ msgid "Pressure"
msgstr "ТиÑк"
#: core/os/input_event.cpp
+#, fuzzy
+msgid "Pen Inverted"
+msgstr "Інвертувати"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "ВідноÑний"
@@ -662,14 +671,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
@@ -2109,14 +2116,15 @@ msgstr "Вибране:"
msgid "Recent:"
msgstr "Ðещодавні:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Пошук:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Збіги:"
@@ -2176,8 +2184,8 @@ msgstr "Знайти замінний реÑурÑ:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2186,7 +2194,7 @@ msgstr "Відкрити"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "ВлаÑник: %s (Загалом: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2746,22 +2754,20 @@ msgstr "Оберіть"
#: editor/editor_export.cpp
msgid "Project export for platform:"
-msgstr ""
+msgstr "ЕкÑÐ¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð¸:"
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
-msgstr "Повні шлÑхи до файлів"
+msgid "Completed with warnings."
+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 +2782,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 +2919,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 +5212,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 +5497,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Додаткові кнопки миші Ð´Ð»Ñ Ð½Ð°Ð²Ñ–Ð³Ð°Ñ†Ñ–Ñ— журналом"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Вибір GridMap"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "ВиглÑд"
@@ -7156,12 +7160,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 +11514,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."
@@ -11609,6 +11618,11 @@ msgid "New Animation"
msgstr "Ðова анімаціÑ"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Фільтрувати методи"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "ШвидкіÑть:"
@@ -12875,14 +12889,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 +14154,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 +16716,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 +16826,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 +18373,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 +18385,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 +18430,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 +18667,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 +18689,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»."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19029,7 +19070,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 +19390,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 +19471,7 @@ msgstr "Календарі"
#: platform/osx/export/export.cpp
msgid "Photos Library"
-msgstr "Бібліотека фотографій"
+msgstr "Бібліотека Ñвітлин"
#: platform/osx/export/export.cpp
msgid "Apple Events"
@@ -19815,7 +19856,7 @@ msgid ""
"Privacy: Photo library access is enabled, but usage description is not "
"specified."
msgstr ""
-"КонфіденційніÑть: увімкнено доÑтуп до бібліотеки фотографій, але Ð¾Ð¿Ð¸Ñ "
+"КонфіденційніÑть: увімкнено доÑтуп до бібліотеки Ñвітлин, але Ð¾Ð¿Ð¸Ñ "
"викориÑÑ‚Ð°Ð½Ð½Ñ Ð½Ðµ вказано."
#: platform/osx/export/export.cpp
@@ -20083,18 +20124,18 @@ msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ Ñховище ключів. Ðемож
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
"Щоб мати змогу змінювати піктограму або дані щодо програми, має бути "
"налаштовано інÑтрумент rcedit у параметрах редактора (ЕкÑпорт > Windows > "
"Rcedit)."
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Ðекоректний виконуваний файл."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20119,18 +20160,18 @@ msgstr "Ðекоректна назва."
#: platform/windows/export/export.cpp
#, fuzzy
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
"Щоб мати змогу змінювати піктограму або дані щодо програми, має бути "
"налаштовано інÑтрумент rcedit у параметрах редактора (ЕкÑпорт > Windows > "
"Rcedit)."
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Ðекоректний виконуваний файл."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20348,7 +20389,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 +21077,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 +21090,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 +21119,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 ""
@@ -21114,7 +21165,7 @@ msgstr "Подорож"
msgid "Rotation Degrees"
msgstr "ГрудуÑи обертаннÑ"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr "Загальна Ñтала"
@@ -23074,6 +23125,11 @@ msgstr ""
"ЗаміÑть цієї зміни, вам варто змінити розміри дочірніх форм зіткненнÑ."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Зберегти загальне перетвореннÑ"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr "МатрицÑ"
@@ -24180,6 +24236,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 +24599,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 +24606,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"
@@ -25841,11 +25899,11 @@ msgstr "Розмір крапки"
#: scene/resources/material.cpp
msgid "Billboard Mode"
-msgstr "Режим афіші"
+msgstr "Режим розголоÑника"
#: scene/resources/material.cpp
msgid "Billboard Keep Scale"
-msgstr "Зберегти маÑштаб афіші"
+msgstr "Зберегти маÑштаб розголоÑника"
#: scene/resources/material.cpp
msgid "Grow"
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index 76cd6b6495..a428250cc7 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
@@ -460,6 +465,10 @@ msgid "Pressure"
msgstr ""
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2123,14 +2132,15 @@ msgstr ""
msgid "Recent:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr ""
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr ""
@@ -2186,8 +2196,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2754,8 +2764,9 @@ msgid "Project export for platform:"
msgstr ""
#: editor/editor_export.cpp
-msgid "Completed with errors."
-msgstr ""
+#, fuzzy
+msgid "Completed with warnings."
+msgstr ".تمام کا انتخاب"
#: editor/editor_export.cpp
msgid "Completed successfully."
@@ -5407,6 +5418,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr ".تمام کا انتخاب"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -11585,6 +11605,11 @@ msgid "New Animation"
msgstr ""
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "سب سکریپشن بنائیں"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -18373,6 +18398,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 +18411,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 +18457,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 +18693,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 +18707,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
@@ -20013,14 +20063,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+msgid "rcedit failed to modify executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -20042,14 +20091,13 @@ msgstr ""
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+msgid "Signtool failed to sign executable: %s."
msgstr ""
#: platform/windows/export/export.cpp
@@ -20272,7 +20320,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 +21020,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 +21033,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 ""
@@ -21043,7 +21101,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "مستقل"
@@ -22967,6 +23025,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "سب سکریپشن بنائیں"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24102,6 +24165,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 +24549,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..0a6885872f 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
@@ -465,6 +470,10 @@ msgid "Pressure"
msgstr "Ãp lá»±c"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "Tương đối"
@@ -2140,14 +2149,15 @@ msgstr "Ưa thích:"
msgid "Recent:"
msgstr "Gần đây:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "Tìm kiếm:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "Phù hợp:"
@@ -2207,8 +2217,8 @@ msgstr "Tìm kiếm tài nguyên thay thế:"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2787,7 +2797,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "Sao chép đưá»ng dẫn nút"
#: editor/editor_export.cpp
@@ -5492,6 +5502,15 @@ 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 "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Ngoại hình"
@@ -11774,6 +11793,11 @@ msgid "New Animation"
msgstr "Hoạt hình mới"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "Lá»c phương thức"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "Tốc độ:"
@@ -18786,6 +18810,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 +18823,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 +18875,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 +19121,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 +19129,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 +19142,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
@@ -20525,15 +20574,15 @@ msgstr "Không thể mở bản mẫu để xuất:"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "Tên đuôi không hợp lệ."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20557,15 +20606,15 @@ msgstr "Tên không hợp lệ."
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "Tên đuôi không hợp lệ."
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20810,7 +20859,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 +21617,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 +21630,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 +21661,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."
@@ -21646,7 +21705,7 @@ msgstr "Di chuyển"
msgid "Rotation Degrees"
msgstr "Xoay %s độ."
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "Hằng số"
@@ -23733,6 +23792,11 @@ msgstr ""
"Hãy sửa kích cỡ khối va chạm của nút con ý."
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "Xóa biến đổi"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -24954,6 +25018,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 +25427,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..f25a372128 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-07-29 01:36+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"
@@ -98,7 +98,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.13.1-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -466,6 +466,10 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: 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
@@ -517,6 +521,10 @@ msgid "Pressure"
msgstr "压力"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr "笔触翻转"
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr "相对"
@@ -2148,14 +2156,15 @@ msgstr "æ”¶è—:"
msgid "Recent:"
msgstr "最近使用:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "æœç´¢ï¼š"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "匹é…项:"
@@ -2215,8 +2224,8 @@ msgstr "查找替æ¢èµ„æºï¼š"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2782,7 +2791,8 @@ msgid "Project export for platform:"
msgstr "针对平å°å¯¼å‡ºé¡¹ç›®ï¼š"
#: editor/editor_export.cpp
-msgid "Completed with errors."
+#, fuzzy
+msgid "Completed with warnings."
msgstr "已完æˆï¼Œå­˜åœ¨é”™è¯¯ã€‚"
#: editor/editor_export.cpp
@@ -5431,6 +5441,14 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "使用专门鼠标按键查看历å²"
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr "拖放选中内容"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr "é€‰ä¸­èŠ‚ç‚¹æ—¶ä¿æŒè„šæœ¬ç¼–è¾‘å™¨"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "外观"
@@ -5662,7 +5680,7 @@ msgstr "网格细分级别下é™"
#: editor/editor_settings.cpp
msgid "Grid Division Level Bias"
-msgstr "网格细分级别å倚"
+msgstr "网格细分级别åç½®"
#: editor/editor_settings.cpp
msgid "Grid XZ Plane"
@@ -10687,7 +10705,7 @@ msgid ""
"This shader has been modified on on disk.\n"
"What action should be taken?"
msgstr ""
-"æ­¤ç€è‰²å™¨å·²åœ¨ç£ç›˜ä¸Šä¿®æ”¹ã€‚\n"
+"这个ç€è‰²å™¨å·²åœ¨ç£ç›˜ä¸Šä¿®æ”¹ã€‚\n"
"应该采å–什么行动?"
#: editor/plugins/shader_editor_plugin.cpp scene/resources/material.cpp
@@ -11453,6 +11471,10 @@ msgid "New Animation"
msgstr "新建动画"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Filter animations"
+msgstr "筛选动画"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "速度:"
@@ -14170,7 +14192,7 @@ msgid ""
"Please edit the project and set the main scene in the Project Settings under "
"the \"Application\" category."
msgstr ""
-"无法è¿è¡Œé¡¹ç›®ï¼šæœªå®šä¹‰ä¸»åœºæ™¯ã€‚ \n"
+"无法è¿è¡Œé¡¹ç›®ï¼šæœªå®šä¹‰ä¸»åœºæ™¯ã€‚\n"
"请编辑项目并在 “项目设置†的 “Application†类别下设置主场景。"
#: editor/project_manager.cpp
@@ -18065,6 +18087,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 "使用自定义构建"
@@ -18072,6 +18098,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 +18142,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,33 +18363,54 @@ 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â€æ—¶æ‰æœ‰æ•ˆã€‚"
+msgstr "“手势跟踪â€åªæœ‰åœ¨å½““XR 模å¼â€æ˜¯â€œ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 "“穿é€â€åªæœ‰åœ¨å½““XR Modeâ€æ˜¯â€œOpenXRâ€æ—¶æ‰æœ‰æ•ˆã€‚"
#: platform/android/export/export_plugin.cpp
msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
-msgstr "“Export AABâ€åªæœ‰åœ¨å½“å¯ç”¨â€œUse Custom Buildâ€æ—¶æ‰æœ‰æ•ˆã€‚"
+msgstr "“Export AABâ€åªæœ‰åœ¨å½“å¯ç”¨â€œä½¿ç”¨è‡ªå®šä¹‰æž„å»ºâ€æ—¶æ‰æœ‰æ•ˆã€‚"
#: 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 "ä¿®æ”¹â€œæœ€å° SDKâ€åªæœ‰åœ¨å½“å¯ç”¨â€œä½¿ç”¨è‡ªå®šä¹‰æž„å»ºâ€æ—¶æ‰æœ‰æ•ˆã€‚"
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr "â€œæœ€å° SDKâ€åº”当为有效的整数,但获得了无效的“%sâ€ã€‚"
#: 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 "â€œæœ€å° SDKâ€ä¸èƒ½ä½ŽäºŽ %d,这是 Godot 库所需è¦çš„版本。"
#: 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 "修改“目标 SDKâ€åªæœ‰åœ¨å½“å¯ç”¨â€œä½¿ç”¨è‡ªå®šä¹‰æž„å»ºâ€æ—¶æ‰æœ‰æ•ˆã€‚"
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr "“目标 SDKâ€åº”当为有效的整数,但获得了无效的“%sâ€ã€‚"
+
+#: 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 ""
+"“目标 SDKâ€%d 比默认版本 %d è¦é«˜ã€‚这样åšä¹Ÿè®¸å¯è¡Œï¼Œä½†å¹¶æ²¡æœ‰ç»è¿‡æµ‹è¯•,å¯èƒ½ä¸ç¨³"
+"定。"
+
+#: platform/android/export/export_plugin.cpp
+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
#: platform/windows/export/export.cpp
@@ -19634,17 +19681,18 @@ msgid "Could not find wine executable at \"%s\"."
msgstr "无法在“%sâ€æ‰¾åˆ° wine 坿‰§è¡Œæ–‡ä»¶ã€‚"
#: platform/windows/export/export.cpp
+#, fuzzy
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
"无法å¯åЍ rcedit 坿‰§è¡Œæ–‡ä»¶ï¼Œè¯·åœ¨ç¼–辑器设置中é…ç½® rcedit 路径(导出 > Windows "
"> Rcedit)。"
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
msgstr ""
"rcedit ä¿®æ”¹å¯æ‰§è¡Œæ–‡ä»¶å¤±è´¥ï¼š\n"
"%s"
@@ -19666,17 +19714,18 @@ msgid "Invalid timestamp server."
msgstr "时间戳æœåŠ¡å™¨æ— æ•ˆã€‚"
#: platform/windows/export/export.cpp
+#, fuzzy
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
"无法å¯åЍ signtool 坿‰§è¡Œæ–‡ä»¶ï¼Œè¯·åœ¨ç¼–辑器设置中é…ç½® signtool 路径(导出 > "
"Windows > Signtool)。"
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
msgstr ""
"Signtool ç­¾å坿‰§è¡Œæ–‡ä»¶å¤±è´¥ï¼š\n"
"%s"
@@ -19690,8 +19739,8 @@ msgid ""
"The rcedit tool must be configured in the Editor Settings (Export > Windows "
"> Rcedit) to change the icon or app information data."
msgstr ""
-"必须在编辑器设置中é…ç½® rcedit 工具(Export > Windows > Rcedit)æ‰èƒ½ä¿®æ”¹å›¾æ ‡æˆ–"
-"åº”ç”¨ä¿¡æ¯æ•°æ®ã€‚"
+"必须在编辑器设置中é…ç½® rcedit 工具(导出 > Windows > Rcedit)æ‰èƒ½ä¿®æ”¹å›¾æ ‡æˆ–应"
+"ç”¨ä¿¡æ¯æ•°æ®ã€‚"
#: platform/windows/export/export.cpp
msgid "Invalid icon path:"
@@ -19894,7 +19943,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"
@@ -20394,7 +20443,7 @@ msgstr "节点 B"
#: scene/3d/light.cpp scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
#: scene/resources/environment.cpp
msgid "Bias"
-msgstr "å倚"
+msgstr "åç½®"
#: scene/2d/joints_2d.cpp
msgid "Disable Collision"
@@ -20567,17 +20616,34 @@ 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
+msgid "Pathfinding"
+msgstr "寻路"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
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
+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 +20659,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."
@@ -20640,7 +20698,7 @@ msgstr "移动消耗"
msgid "Rotation Degrees"
msgstr "旋转角度"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
msgid "Global Rotation"
msgstr "全局旋转"
@@ -21544,7 +21602,7 @@ msgstr "动æ€èŒƒå›´"
#: scene/3d/gi_probe.cpp scene/3d/light.cpp
msgid "Normal Bias"
-msgstr "法线å倚"
+msgstr "法线åç½®"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
#: scene/resources/primitive_meshes.cpp
@@ -21655,7 +21713,7 @@ msgstr "æ··åˆæ‹†åˆ†"
#: scene/3d/light.cpp
msgid "Bias Split Scale"
-msgstr "å倚拆分缩放"
+msgstr "å置拆分缩放"
#: scene/3d/light.cpp
msgid "Depth Range"
@@ -21699,6 +21757,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"
@@ -21887,7 +21947,7 @@ msgstr "角度下é™"
#: scene/3d/physics_body.cpp
msgid "Angular Limit Bias"
-msgstr "角度é™åˆ¶å倚"
+msgstr "角度é™åˆ¶åç½®"
#: scene/3d/physics_body.cpp
msgid "Angular Limit Softness"
@@ -22513,6 +22573,10 @@ msgstr ""
"建议修改å­èŠ‚ç‚¹çš„ç¢°æ’žä½“å½¢çŠ¶å°ºå¯¸ã€‚"
#: scene/3d/spatial.cpp
+msgid "Global Translation"
+msgstr "全局平移"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr "矩阵"
@@ -23603,6 +23667,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 "å¯ç”¨éšè—"
@@ -23959,22 +24027,23 @@ 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 ""
+"这个 Viewport å¯ç”¨äº† HDR,但其 Usage 为 2D 或 2D No-Sampling。\n"
+"HDR 仅在 Usage 为 3D 或 3D No-Effects çš„ Viewport 中支æŒã€‚\n"
+"这个 Viewport å°†ç¦ç”¨ HDR。"
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr "ARVR"
@@ -25482,14 +25551,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"
@@ -25613,7 +25680,7 @@ msgstr "A"
#: scene/resources/shape_2d.cpp
msgid "Custom Solver Bias"
-msgstr "自定义求解器å倚"
+msgstr "自定义求解器åç½®"
#: scene/resources/skin.cpp
msgid "Bind Count"
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index 114f6b0a45..79760d0de7 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
@@ -474,6 +479,10 @@ msgid "Pressure"
msgstr "é‡è¨­ç¸®æ”¾æ¯”例"
#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr ""
+
+#: core/os/input_event.cpp
msgid "Relative"
msgstr ""
@@ -2219,14 +2228,15 @@ msgstr "最愛:"
msgid "Recent:"
msgstr "最近:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "æœå°‹ï¼š"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "å»åˆï¼š"
@@ -2282,8 +2292,8 @@ msgstr ""
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2881,7 +2891,7 @@ msgstr ""
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
+msgid "Completed with warnings."
msgstr "複製路徑"
#: editor/editor_export.cpp
@@ -5663,6 +5673,15 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "刪除é¸ä¸­æª”案"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -12102,6 +12121,11 @@ msgid "New Animation"
msgstr "新的動畫å稱:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+#, fuzzy
+msgid "Filter animations"
+msgstr "篩é¸:"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr ""
@@ -19119,6 +19143,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 +19156,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 +19204,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 +19448,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 +19462,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
@@ -20818,15 +20867,15 @@ msgstr "無法新增資料夾"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "無效副檔å"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20850,15 +20899,15 @@ msgstr "無效å稱。"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "無效副檔å"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -21095,7 +21144,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 +21859,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 +21872,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 ""
@@ -21881,7 +21940,7 @@ msgstr ""
msgid "Rotation Degrees"
msgstr ""
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "常數"
@@ -23874,6 +23933,11 @@ msgid ""
msgstr ""
#: scene/3d/spatial.cpp
+#, fuzzy
+msgid "Global Translation"
+msgstr "翻譯"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
@@ -25061,6 +25125,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 +25523,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 +25530,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..8ad86d4b2a 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -23,7 +23,7 @@
# binotaliu <binota@protonmail.ch>, 2020.
# Allen H. <w84miracle@gmail.com>, 2020.
# BinotaLIU <binota@protonmail.ch>, 2020.
-# BinotaLIU <me@binota.org>, 2020, 2021.
+# BinotaLIU <me@binota.org>, 2020, 2021, 2022.
# MintSoda <lionlxh@qq.com>, 2020.
# meowmeowmeowcat <meowmeowcat1211@gmail.com>, 2021.
# anthonychen <anton1554970211@126.com>, 2021.
@@ -33,13 +33,16 @@
# Haoyu Qiu <timothyqiu32@gmail.com>, 2022.
# Otis Kao <momoslim@gmail.com>, 2022.
# YuChiang Chang <chiang.c.tw@gmail.com>, 2022.
+# è˜è˜ <rrt467778@gmail.com>, 2022.
+# marktwtn <marktwtn@gmail.com>, 2022.
+# Shi-Xun Hong <jimmy3421@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-05-30 16:17+0000\n"
-"Last-Translator: YuChiang Chang <chiang.c.tw@gmail.com>\n"
+"PO-Revision-Date: 2022-07-31 18:34+0000\n"
+"Last-Translator: BinotaLIU <me@binota.org>\n"
"Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/"
"godot-engine/godot/zh_Hant/>\n"
"Language: zh_TW\n"
@@ -47,7 +50,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.14-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -70,27 +73,22 @@ msgid "V-Sync Enabled"
msgstr "å•Ÿç”¨åž‚ç›´åŒæ­¥"
#: core/bind/core_bind.cpp main/main.cpp
-#, fuzzy
msgid "V-Sync Via Compositor"
msgstr "é€éŽåˆæˆå™¨åž‚ç›´åŒæ­¥"
#: core/bind/core_bind.cpp main/main.cpp
-#, fuzzy
msgid "Delta Smoothing"
-msgstr "變é‡å¹³æ»‘"
+msgstr "å·®é‡å¹³æ»‘"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Low Processor Usage Mode"
msgstr "低處ç†å™¨ä½¿ç”¨çŽ‡æ¨¡å¼"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Low Processor Usage Mode Sleep (µsec)"
msgstr "低處ç†å™¨ä½¿ç”¨çŽ‡æ¨¡å¼ç¡çœ ï¼ˆå¾®ç§’)"
#: core/bind/core_bind.cpp main/main.cpp platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Keep Screen On"
msgstr "ä¿æŒèž¢å¹•開啟"
@@ -157,9 +155,8 @@ msgid "Size"
msgstr "大å°"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Endian Swap"
-msgstr "切æ›ç«¯åº"
+msgstr "切æ›å­—節åº"
#: core/bind/core_bind.cpp
msgid "Editor Hint"
@@ -178,9 +175,8 @@ msgid "Target FPS"
msgstr "標準FPS"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Time Scale"
-msgstr "TimeScale 節點"
+msgstr "時間縮放"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Physics Jitter Fix"
@@ -199,9 +195,8 @@ msgid "Error Line"
msgstr "發生錯誤之行數"
#: core/bind/core_bind.cpp
-#, fuzzy
msgid "Result"
-msgstr "æœå°‹çµæžœ"
+msgstr "çµæžœ"
#: core/command_queue_mt.cpp core/message_queue.cpp main/main.cpp
msgid "Memory"
@@ -230,7 +225,6 @@ msgstr "多執行緒佇列大å°(KB)"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
#: scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Function"
msgstr "函å¼"
@@ -260,17 +254,14 @@ msgid "Page Read Ahead"
msgstr "é å…ˆè®€å–é æ•¸"
#: core/io/http_client.cpp
-#, fuzzy
msgid "Blocking Mode Enabled"
-msgstr "啟用阻礙模å¼"
+msgstr "啟用阻塞模å¼"
#: core/io/http_client.cpp
-#, fuzzy
msgid "Connection"
msgstr "連接"
#: core/io/http_client.cpp
-#, fuzzy
msgid "Read Chunk Size"
msgstr "讀å–å€å¡Šå¤§å°"
@@ -287,12 +278,10 @@ msgid "Refuse New Network Connections"
msgstr "拒絕新網路連接"
#: core/io/multiplayer_api.cpp scene/main/scene_tree.cpp
-#, fuzzy
msgid "Network Peer"
-msgstr "å°ç­‰ç¶²è·¯ä½¿ç”¨è€…"
+msgstr "å°ç­‰ç¶²è·¯"
#: core/io/multiplayer_api.cpp scene/animation/animation_player.cpp
-#, fuzzy
msgid "Root Node"
msgstr "根節點"
@@ -301,9 +290,8 @@ msgid "Refuse New Connections"
msgstr "拒絕新網路連接"
#: core/io/networked_multiplayer_peer.cpp
-#, fuzzy
msgid "Transfer Mode"
-msgstr "轉æ›é¡žåž‹"
+msgstr "傳輸模å¼"
#: core/io/packet_peer.cpp
msgid "Encode Buffer Max Size"
@@ -353,9 +341,8 @@ msgid "Not enough bytes for decoding bytes, or invalid format."
msgstr "ä½å…ƒçµ„長度ä¸è¶³ä»¥é€²è¡Œè§£ç¢¼æˆ–或格å¼ç„¡æ•ˆã€‚"
#: core/math/expression.cpp
-#, fuzzy
msgid "Invalid input %d (not passed) in expression"
-msgstr "é‹ç®—å¼ä¸­çš„輸入 %i 無效 (未傳éžï¼‰"
+msgstr "é‹ç®—å¼çš„輸入%d 無效(未傳éžï¼‰"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
@@ -387,7 +374,6 @@ msgid "Seed"
msgstr "種å­"
#: core/math/random_number_generator.cpp
-#, fuzzy
msgid "State"
msgstr "狀態"
@@ -400,14 +386,12 @@ msgid "Max Size (KB)"
msgstr "最大大å°ï¼ˆKB)"
#: 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
@@ -434,10 +418,13 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: 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
-#, fuzzy
msgid "Pressed"
msgstr "按下"
@@ -446,21 +433,18 @@ msgid "Scancode"
msgstr "éµç›¤æŽƒæç¢¼"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Physical Scancode"
-msgstr "實體éµç›¤æŽƒæç¢¼"
+msgstr "ç‰©ç†æŽƒæç¢¼"
#: core/os/input_event.cpp
msgid "Unicode"
msgstr "Unicode"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Echo"
-msgstr "Echo"
+msgstr "回è²"
#: core/os/input_event.cpp scene/gui/base_button.cpp
-#, fuzzy
msgid "Button Mask"
msgstr "按éµé®ç½©"
@@ -469,7 +453,6 @@ msgid "Global Position"
msgstr "全域ä½ç½®"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Factor"
msgstr "å› ç´ "
@@ -486,12 +469,14 @@ msgid "Tilt"
msgstr "傾斜"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Pressure"
-msgstr "按壓"
+msgstr "壓力"
+
+#: core/os/input_event.cpp
+msgid "Pen Inverted"
+msgstr "å轉筆觸"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Relative"
msgstr "相å°"
@@ -527,12 +512,10 @@ msgid "Strength"
msgstr "強度"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Delta"
-msgstr "變é‡"
+msgstr "å·®é‡"
#: core/os/input_event.cpp
-#, fuzzy
msgid "Channel"
msgstr "é »é“"
@@ -608,14 +591,12 @@ msgid "Main Scene"
msgstr "主場景"
#: core/project_settings.cpp
-#, fuzzy
msgid "Disable stdout"
-msgstr "ç¦ç”¨è‡ªå‹•圖塊"
+msgstr "åœç”¨æ¨™æº–輸出"
#: core/project_settings.cpp
-#, fuzzy
msgid "Disable stderr"
-msgstr "å·²åœç”¨çš„é …ç›®"
+msgstr "åœç”¨æ¨™æº–錯誤輸出"
#: core/project_settings.cpp
msgid "Use Hidden Project Data Directory"
@@ -632,15 +613,14 @@ msgstr "自訂使用者目錄å稱"
#: core/project_settings.cpp main/main.cpp
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
#: platform/uwp/os_uwp.cpp
-#, fuzzy
msgid "Display"
-msgstr "全部顯示"
+msgstr "顯示"
#: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp
#: modules/opensimplex/noise_texture.cpp scene/2d/line_2d.cpp
#: scene/3d/label_3d.cpp scene/gui/text_edit.cpp scene/resources/texture.cpp
msgid "Width"
-msgstr ""
+msgstr "寬"
#: core/project_settings.cpp main/main.cpp modules/csg/csg_shape.cpp
#: modules/gltf/gltf_node.cpp modules/opensimplex/noise_texture.cpp
@@ -648,23 +628,20 @@ msgstr ""
#: scene/resources/capsule_shape_2d.cpp scene/resources/cylinder_shape.cpp
#: scene/resources/font.cpp scene/resources/navigation_mesh.cpp
#: scene/resources/primitive_meshes.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Height"
-msgstr "燈光"
+msgstr "高度"
#: core/project_settings.cpp
msgid "Always On Top"
-msgstr ""
+msgstr "置頂"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Width"
-msgstr "左延展"
+msgstr "測試寬度"
#: core/project_settings.cpp
-#, fuzzy
msgid "Test Height"
-msgstr "測試"
+msgstr "測試高度"
#: core/project_settings.cpp editor/animation_track_editor.cpp
#: editor/editor_audio_buses.cpp main/main.cpp servers/audio_server.cpp
@@ -683,33 +660,28 @@ msgid "Editor"
msgstr "編輯器"
#: core/project_settings.cpp
-#, fuzzy
msgid "Main Run Args"
msgstr "主執行引數"
#: core/project_settings.cpp
-#, fuzzy
msgid "Scene Naming"
-msgstr "場景路徑:"
+msgstr "場景命å"
#: core/project_settings.cpp
-#, fuzzy
msgid "Search In File Extensions"
-msgstr "ä»¥å‰¯æª”åæœå°‹"
+msgstr "ä»¥æª”æ¡ˆå‰¯æª”åæœå°‹"
#: core/project_settings.cpp
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
@@ -717,9 +689,8 @@ msgid "Input"
msgstr "輸入"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Accept"
-msgstr "UI確定"
+msgstr "確定 (UI)"
#: core/project_settings.cpp
msgid "UI Select"
@@ -730,43 +701,36 @@ msgid "UI Cancel"
msgstr "UIå–æ¶ˆ"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Focus Next"
-msgstr "èšç„¦è·¯å¾‘"
+msgstr "èšç„¦ä¸‹ä¸€å€‹ (UI)"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Focus Prev"
-msgstr "èšç„¦è·¯å¾‘"
+msgstr "èšç„¦ä¸Šä¸€å€‹ (UI)"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Left"
-msgstr "左上"
+msgstr "å·¦ (UI)"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Right"
-msgstr "å³ä¸Š"
+msgstr "å³ (UI)"
#: core/project_settings.cpp
msgid "UI Up"
msgstr "UI上"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Down"
-msgstr "UI下"
+msgstr "下 (UI)"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Page Up"
-msgstr "UIé é¢å‘上滾動"
+msgstr "é é¢ä¸Šæ»¾ (UI)"
#: core/project_settings.cpp
-#, fuzzy
msgid "UI Page Down"
-msgstr "UIé é¢å‘下滾動"
+msgstr "é é¢ä¸‹æ»¾ (UI)"
#: core/project_settings.cpp
msgid "UI Home"
@@ -798,7 +762,6 @@ msgid "3D"
msgstr "3D"
#: core/project_settings.cpp
-#, fuzzy
msgid "Smooth Trimesh Collision"
msgstr "平滑三角網格碰撞"
@@ -827,12 +790,10 @@ msgstr "å“質"
#: core/project_settings.cpp scene/gui/file_dialog.cpp
#: scene/main/scene_tree.cpp scene/resources/navigation_mesh.cpp
#: servers/visual_server.cpp
-#, fuzzy
msgid "Filters"
msgstr "篩é¸å™¨"
#: core/project_settings.cpp scene/main/viewport.cpp
-#, fuzzy
msgid "Sharpen Intensity"
msgstr "銳化強度"
@@ -859,9 +820,8 @@ msgid "Profiler"
msgstr "分æžå·¥å…·"
#: core/project_settings.cpp
-#, fuzzy
msgid "Max Functions"
-msgstr "最大值函å¼"
+msgstr "æœ€å¤§å‡½å¼æ•¸"
#: core/project_settings.cpp scene/3d/vehicle_body.cpp
msgid "Compression"
@@ -876,18 +836,16 @@ msgid "Zstd"
msgstr "Zstd"
#: core/project_settings.cpp
-#, fuzzy
msgid "Long Distance Matching"
-msgstr "é•·è·é…å°"
+msgstr "é•·è·é›¢åŒ¹é…"
#: core/project_settings.cpp
msgid "Compression Level"
msgstr "壓縮等級"
#: core/project_settings.cpp
-#, fuzzy
msgid "Window Log Size"
-msgstr "視窗日誌大å°"
+msgstr "è¦–çª—å°æ•¸å¤§å°"
#: core/project_settings.cpp
msgid "Zlib"
@@ -910,14 +868,12 @@ msgid "TCP"
msgstr "TCP"
#: core/register_core_types.cpp
-#, fuzzy
msgid "Connect Timeout Seconds"
-msgstr "連接逾時秒數"
+msgstr "連線逾時秒數"
#: core/register_core_types.cpp
-#, fuzzy
msgid "Packet Peer Stream"
-msgstr "å°åŒ…å°ç­‰ä¸²æµ"
+msgstr "å°åŒ…å°ç­‰æµ"
#: core/register_core_types.cpp
msgid "Max Buffer (Power of 2)"
@@ -928,7 +884,6 @@ msgid "SSL"
msgstr "SSL"
#: core/register_core_types.cpp main/main.cpp
-#, fuzzy
msgid "Certificates"
msgstr "憑證"
@@ -939,9 +894,8 @@ msgid "Resource"
msgstr "資æº"
#: core/resource.cpp
-#, fuzzy
msgid "Local To Scene"
-msgstr "關閉場景"
+msgstr "åƒ…é™æœ¬å ´æ™¯"
#: core/resource.cpp editor/dependency_editor.cpp
#: editor/editor_autoload_settings.cpp editor/plugins/path_editor_plugin.cpp
@@ -959,14 +913,12 @@ msgid "Locale"
msgstr "地å€"
#: core/translation.cpp
-#, fuzzy
msgid "Test"
msgstr "測試"
#: core/translation.cpp scene/resources/font.cpp
-#, fuzzy
msgid "Fallback"
-msgstr "éžè£œ"
+msgstr "後備語言"
#: core/ustring.cpp scene/resources/segment_shape_2d.cpp
msgid "B"
@@ -1028,27 +980,23 @@ msgstr "2D"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
-#, fuzzy
msgid "Snapping"
msgstr "å¸é™„"
#: drivers/gles2/rasterizer_canvas_base_gles2.cpp
#: drivers/gles3/rasterizer_canvas_base_gles3.cpp
-#, fuzzy
msgid "Use GPU Pixel Snap"
-msgstr "使用GPUåƒç´ å¸é™„"
+msgstr "使用 GPU åƒç´ å¸é™„"
#: drivers/gles2/rasterizer_scene_gles2.cpp
#: drivers/gles3/rasterizer_scene_gles3.cpp
-#, fuzzy
msgid "Immediate Buffer Size (KB)"
msgstr "峿™‚ç·©è¡å€å¤§å°ï¼ˆKB)"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
-#, fuzzy
msgid "Lightmapping"
-msgstr "烘焙光照圖"
+msgstr "光照貼圖"
#: drivers/gles2/rasterizer_storage_gles2.cpp
#: drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1097,9 +1045,8 @@ msgid "Weight Samples"
msgstr "æ¬Šé‡æŽ¡æ¨£"
#: drivers/gles3/rasterizer_scene_gles3.cpp
-#, fuzzy
msgid "Voxel Cone Tracing"
-msgstr "é«”ç´ æ¤Žé«”ææ‘¹"
+msgstr "體素éŒè¿½è¸ª"
#: drivers/gles3/rasterizer_scene_gles3.cpp scene/resources/environment.cpp
msgid "High Quality"
@@ -1181,9 +1128,8 @@ msgstr "更改動畫呼å«"
#: editor/animation_track_editor.cpp scene/2d/animated_sprite.cpp
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Frame"
-msgstr "影格 %"
+msgstr "影格"
#: editor/animation_track_editor.cpp editor/editor_profiler.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
@@ -1194,16 +1140,14 @@ msgstr "時間"
#: editor/animation_track_editor.cpp editor/import/resource_importer_scene.cpp
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Location"
-msgstr "本地化"
+msgstr "ä½ç½®"
#: editor/animation_track_editor.cpp modules/gltf/gltf_node.cpp
#: scene/2d/polygon_2d.cpp scene/2d/remote_transform_2d.cpp
#: scene/3d/remote_transform.cpp scene/3d/spatial.cpp scene/gui/control.cpp
-#, fuzzy
msgid "Rotation"
-msgstr "旋轉步長:"
+msgstr "旋轉"
#: editor/animation_track_editor.cpp editor/script_editor_debugger.cpp
#: modules/visual_script/visual_script_nodes.cpp scene/gui/range.cpp
@@ -1211,14 +1155,13 @@ msgid "Value"
msgstr "數值"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Arg Count"
-msgstr "數é‡ï¼š"
+msgstr "引數數é‡"
#: editor/animation_track_editor.cpp main/main.cpp
#: modules/mono/mono_gd/gd_mono.cpp
msgid "Args"
-msgstr ""
+msgstr "åƒæ•¸"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/script_editor_debugger.cpp modules/gltf/gltf_accessor.cpp
@@ -1228,31 +1171,27 @@ msgid "Type"
msgstr "型別"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In Handle"
-msgstr "設定處ç†ç¨‹å¼"
+msgstr "進入控點"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out Handle"
-msgstr "設定處ç†ç¨‹å¼"
+msgstr "離開控點"
#: editor/animation_track_editor.cpp
#: editor/import/resource_importer_texture.cpp
#: scene/2d/audio_stream_player_2d.cpp scene/3d/audio_stream_player_3d.cpp
#: scene/audio/audio_stream_player.cpp scene/gui/video_player.cpp
msgid "Stream"
-msgstr ""
+msgstr "æµ"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start Offset"
-msgstr "網格åç§»é‡ï¼š"
+msgstr "起點åç§»"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End Offset"
-msgstr "å移:"
+msgstr "終點åç§»"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
#: editor/import/resource_importer_scene.cpp
@@ -1265,7 +1204,6 @@ msgid "Animation"
msgstr "å‹•ç•«"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing"
msgstr "緩入緩出"
@@ -1376,19 +1314,16 @@ msgid "Remove this track."
msgstr "移除該動畫軌。"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Time (s):"
-msgstr "時間(秒) : "
+msgstr "時間(秒):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Position:"
-msgstr "ä½ç½®"
+msgstr "ä½ç½®ï¼š"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Rotation:"
-msgstr "旋轉步長:"
+msgstr "旋轉:"
#: editor/animation_track_editor.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -1405,44 +1340,36 @@ msgid "Type:"
msgstr "型別:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "(Invalid, expected type: %s)"
-msgstr "無效的輸出樣æ¿ï¼š"
+msgstr "ï¼ˆç„¡æ•ˆï¼Œé æœŸåž‹åˆ¥ï¼š%s)"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing:"
-msgstr "緩入緩出"
+msgstr "緩入緩出:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "In-Handle:"
-msgstr "設定處ç†ç¨‹å¼"
+msgstr "進入控點:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Out-Handle:"
-msgstr "設定處ç†ç¨‹å¼"
+msgstr "離開控點:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Stream:"
-msgstr "串æµä½¿ç”¨è€…"
+msgstr "æµï¼š"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Start (s):"
-msgstr "釿–°é–‹å§‹ï¼ˆç§’):"
+msgstr "開始(秒):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "End (s):"
-msgstr "淡入(秒):"
+msgstr "çµæŸï¼ˆç§’):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Animation Clip:"
-msgstr "動畫:"
+msgstr "動畫片段:"
#: editor/animation_track_editor.cpp
msgid "Toggle Track Enabled"
@@ -1496,9 +1423,8 @@ msgid "Duplicate Key(s)"
msgstr "é‡è¤‡é—œéµç•«æ ¼"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Add RESET Value(s)"
-msgstr "新增 %d 個影格"
+msgstr "新增 RESET 值"
#: editor/animation_track_editor.cpp
msgid "Delete Key(s)"
@@ -1527,14 +1453,12 @@ msgstr "刪除動畫軌"
#: editor/plugins/tile_map_editor_plugin.cpp editor/scene_tree_dock.cpp
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Editors"
msgstr "編輯器"
#: editor/animation_track_editor.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Confirm Insert Track"
-msgstr "新增動畫軌é“與關éµç•«æ ¼"
+msgstr "ç¢ºèªæ’入軌é“"
#. TRANSLATORS: %s will be replaced by a phrase describing the target of track.
#: editor/animation_track_editor.cpp
@@ -1658,9 +1582,8 @@ msgid "Add Method Track Key"
msgstr "新增方法軌é“é—œéµç•«æ ¼"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Method not found in object:"
-msgstr "在物件中找ä¸åˆ°æ–¹æ³•: "
+msgstr "在物件中找ä¸åˆ°è©²æ–¹æ³•:"
#: editor/animation_track_editor.cpp
msgid "Anim Move Keys"
@@ -1701,9 +1624,8 @@ msgid ""
msgstr "該é¸é …ä¸é©ç”¨è²èŒ²æ›²ç·šç·¨è¼¯ï¼Œå› æ›²ç·šåƒ…有單一軌é“。"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Anim Add RESET Keys"
-msgstr "動畫縮放關éµå½±æ ¼"
+msgstr "新增動畫 RESET éµ"
#: editor/animation_track_editor.cpp
msgid ""
@@ -1717,7 +1639,7 @@ msgid ""
"Alternatively, use an import preset that imports animations to separate "
"files."
msgstr ""
-"該動畫屬於外部匯入之場景,套用於匯入軌é“çš„ä¿®æ”¹å°‡ä¸æœƒè¢«ä¿å­˜ã€‚\n"
+"該動畫屬於外部匯入之場景,套用於匯入軌é“çš„ä¿®æ”¹å°‡ä¸æœƒè¢«å„²å­˜ã€‚\n"
"\n"
"è‹¥è¦é–‹å•Ÿã€ŒåŠ å…¥å®¢åˆ¶è»Œã€çš„功能,請在場景在匯入設定中將 [Animation] -> "
"[Storage] 設定為\n"
@@ -2186,14 +2108,15 @@ msgstr "我的最愛:"
msgid "Recent:"
msgstr "最近存å–:"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp editor/rename_dialog.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
+#: editor/rename_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Search:"
msgstr "æœå°‹ï¼š"
-#: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/create_dialog.cpp editor/editor_quick_open.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: modules/visual_script/visual_script_property_selector.cpp
msgid "Matches:"
msgstr "ç¬¦åˆæ¢ä»¶ï¼š"
@@ -2253,8 +2176,8 @@ msgstr "æœå°‹ä¸¦å–代資æºï¼š"
#: editor/dependency_editor.cpp editor/editor_file_dialog.cpp
#: editor/editor_help_search.cpp editor/editor_node.cpp
-#: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp
-#: editor/property_selector.cpp editor/quick_open.cpp
+#: editor/editor_quick_open.cpp editor/filesystem_dock.cpp
+#: editor/plugins/script_editor_plugin.cpp editor/property_selector.cpp
#: editor/script_create_dialog.cpp
#: modules/visual_script/visual_script_property_selector.cpp
#: scene/gui/file_dialog.cpp
@@ -2263,7 +2186,7 @@ msgstr "開啟"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "%s 的所有者(總計:%d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2372,7 +2295,6 @@ msgstr "主è¦é–‹ç™¼è€…"
#. TRANSLATORS: This refers to a job title.
#: editor/editor_about.cpp
-#, fuzzy
msgctxt "Job Title"
msgid "Project Manager"
msgstr "專案管ç†å“¡"
@@ -2614,9 +2536,8 @@ msgid "There is no '%s' file."
msgstr "檔案「%sã€ä¸å­˜åœ¨ã€‚"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Layout:"
-msgstr "ç•«é¢é…ç½®"
+msgstr "佈局:"
#: editor/editor_audio_buses.cpp
msgid "Invalid file, not an audio bus layout."
@@ -2650,7 +2571,7 @@ msgstr "å¦å­˜æ–°æª”"
#: editor/editor_audio_buses.cpp
msgid "Save this Bus Layout to a file."
-msgstr "å°‡è©²åŒ¯æµæŽ’é…ç½®ä¿å­˜è‡³æª”案。"
+msgstr "å°‡è©²åŒ¯æµæŽ’é…置儲存至檔案。"
#: editor/editor_audio_buses.cpp editor/import_dock.cpp
msgid "Load Default"
@@ -2665,9 +2586,8 @@ msgid "Create a new Bus Layout."
msgstr "å»ºç«‹æ–°åŒ¯æµæŽ’é…置。"
#: editor/editor_audio_buses.cpp
-#, fuzzy
msgid "Audio Bus Layout"
-msgstr "é–‹å•ŸéŸ³è¨ŠåŒ¯æµæŽ’é…ç½®"
+msgstr "éŸ³è¨ŠåŒ¯æµæŽ’ä½ˆå±€"
#: editor/editor_autoload_settings.cpp
msgid "Invalid name."
@@ -2785,7 +2705,7 @@ msgstr "[空]"
#: editor/plugins/text_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "[unsaved]"
-msgstr "[未ä¿å­˜]"
+msgstr "[未儲存]"
#: editor/editor_dir_dialog.cpp
msgid "Please select a base directory first."
@@ -2820,22 +2740,20 @@ msgstr "鏿“‡"
#: editor/editor_export.cpp
msgid "Project export for platform:"
-msgstr ""
+msgstr "專案匯出平å°ï¼š"
#: editor/editor_export.cpp
#, fuzzy
-msgid "Completed with errors."
-msgstr "複製節點路徑"
+msgid "Completed with warnings."
+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:"
@@ -2850,29 +2768,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 ""
@@ -2897,7 +2810,7 @@ msgid ""
"Enable 'Import Etc' in Project Settings, or disable 'Driver Fallback "
"Enabled'."
msgstr ""
-"目標平å°ä¸Šçš„ GLES2 回退驅動器功能必須使用「ETCã€ç´‹ç†å£“縮。\n"
+"目標平å°ä¸Šçš„ GLES2 後備驅動器功能必須使用「ETCã€ç´‹ç†å£“縮。\n"
"請在專案設定中啟用「Import Etcã€æˆ–是ç¦ç”¨ã€ŒDriver Fallback Enabledã€ã€‚"
#: editor/editor_export.cpp
@@ -2923,15 +2836,14 @@ msgid ""
"Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback "
"Enabled'."
msgstr ""
-"目標平å°ä¸Šçš„ GLES2 回退驅動器功能必須使用「PVRTCã€ç´‹ç†å£“縮。\n"
+"目標平å°ä¸Šçš„ GLES2 後備驅動器功能必須使用「PVRTCã€ç´‹ç†å£“縮。\n"
"請在專案設定中啟用「Import Pvrtcã€æˆ–是ç¦ç”¨ã€ŒDriver Fallback Enabledã€ã€‚"
#: editor/editor_export.cpp platform/android/export/export_plugin.cpp
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
#: platform/osx/export/export.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Custom Template"
-msgstr "編輯器主題"
+msgstr "自訂模æ¿"
#: editor/editor_export.cpp editor/project_export.cpp
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
@@ -2941,9 +2853,8 @@ msgid "Release"
msgstr "發行"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Binary Format"
-msgstr "色彩é‹ç®—å­ã€‚"
+msgstr "äºŒé€²ä½æ ¼å¼"
#: editor/editor_export.cpp
msgid "64 Bits"
@@ -2954,9 +2865,8 @@ msgid "Embed PCK"
msgstr "內嵌PCK"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Texture Format"
-msgstr "ç´‹ç†è²¼åœ–å€åŸŸ"
+msgstr "ç´‹ç†è²¼åœ–æ ¼å¼"
#: editor/editor_export.cpp
msgid "BPTC"
@@ -2975,9 +2885,8 @@ msgid "ETC2"
msgstr "ETC2"
#: editor/editor_export.cpp
-#, fuzzy
msgid "No BPTC Fallbacks"
-msgstr "ç„¡BPTC回è½"
+msgstr "無 BPTC 後備"
#: editor/editor_export.cpp platform/android/export/export_plugin.cpp
#: platform/iphone/export/export.cpp platform/javascript/export/export.cpp
@@ -2992,30 +2901,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."
@@ -3223,9 +3127,8 @@ msgid "Manage Editor Feature Profiles"
msgstr "管ç†ç·¨è¼¯å™¨åŠŸèƒ½è¨­å®šæª”"
#: editor/editor_feature_profile.cpp
-#, fuzzy
msgid "Default Feature Profile"
-msgstr "Godot 功能設定檔"
+msgstr "é è¨­åŠŸèƒ½è¨­å®šæª”"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Select Current Folder"
@@ -3290,21 +3193,19 @@ msgstr "開啟檔案或資料夾"
#: editor/plugins/script_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp scene/gui/file_dialog.cpp
msgid "Save"
-msgstr "ä¿å­˜"
+msgstr "儲存"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
msgid "Save a File"
-msgstr "ä¿å­˜æª”案"
+msgstr "儲存檔案"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Access"
-msgstr "æˆåŠŸï¼"
+msgstr "å­˜å–"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Display Mode"
-msgstr "播放模å¼ï¼š"
+msgstr "顯示模å¼"
#: editor/editor_file_dialog.cpp
#: editor/import/resource_importer_layered_texture.cpp
@@ -3317,30 +3218,25 @@ msgstr "播放模å¼ï¼š"
#: scene/resources/environment.cpp scene/resources/material.cpp
#: scene/resources/visual_shader.cpp
#: servers/audio/effects/audio_effect_distortion.cpp
-#, fuzzy
msgid "Mode"
-msgstr "平移模å¼"
+msgstr "模å¼"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Current Dir"
-msgstr "ç›®å‰ï¼š"
+msgstr "ç›®å‰ç›®éŒ„"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Current File"
-msgstr "ç›®å‰è¨­å®šæª”:"
+msgstr "所在檔案"
#: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Current Path"
-msgstr "ç›®å‰ï¼š"
+msgstr "所在目錄"
#: editor/editor_file_dialog.cpp editor/editor_settings.cpp
#: scene/gui/file_dialog.cpp
-#, fuzzy
msgid "Show Hidden Files"
-msgstr "顯示ï¼å–æ¶ˆé¡¯ç¤ºéš±è—æª”案"
+msgstr "顯示隱è—的檔案"
#: editor/editor_file_dialog.cpp
msgid "Disable Overwrite Warning"
@@ -3475,9 +3371,8 @@ msgid "Properties"
msgstr "屬性"
#: editor/editor_help.cpp
-#, fuzzy
msgid "overrides %s:"
-msgstr "複寫:"
+msgstr "覆蓋 %s:"
#: editor/editor_help.cpp
msgid "default:"
@@ -3635,46 +3530,39 @@ msgid "Property:"
msgstr "屬性:"
#: editor/editor_inspector.cpp editor/editor_spin_slider.cpp
-#, fuzzy
msgid "Label"
-msgstr "數值"
+msgstr "標籤"
#: editor/editor_inspector.cpp editor/editor_spin_slider.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Read Only"
-msgstr "僅顯示方法"
+msgstr "åªè®€"
#: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp
-#, fuzzy
msgid "Checkable"
-msgstr "檢查項目"
+msgstr "å¯å‹¾é¸"
#: editor/editor_inspector.cpp editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Checked"
-msgstr "已檢查的項目"
+msgstr "已勾é¸"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Draw Red"
-msgstr "繪製呼å«ï¼š"
+msgstr "繪製紅色"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Keying"
-msgstr "執行"
+msgstr "輸入"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Pin value"
-msgstr "(數值)"
+msgstr "固定值"
#: editor/editor_inspector.cpp
msgid ""
"Pinning a value forces it to be saved even if it's equal to the default."
-msgstr "釘é¸çš„æ•¸å€¼å°‡è¢«è¿«ä¿å­˜ï¼Œå³ä½¿å…¶å€¼èˆ‡é è¨­å€¼ç›¸åŒã€‚"
+msgstr "釘é¸çš„æ•¸å€¼å°‡è¢«è¿«å„²å­˜ï¼Œå³ä½¿å…¶å€¼èˆ‡é è¨­å€¼ç›¸åŒã€‚"
#: editor/editor_inspector.cpp
msgid "Pin value [Disabled because '%s' is editor-only]"
@@ -3702,19 +3590,16 @@ msgid "Unpinned %s"
msgstr "已解除釘é¸%s"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Copy Property"
msgstr "複製屬性"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Paste Property"
msgstr "貼上屬性"
#: editor/editor_inspector.cpp
-#, fuzzy
msgid "Copy Property Path"
-msgstr "複製腳本路徑"
+msgstr "複製屬性路徑"
#: editor/editor_log.cpp
msgid "Output:"
@@ -3804,7 +3689,7 @@ msgstr "ç·¨è¼¯å™¨è¦–çª—é‡æ–°ç¹ªè£½æ™‚旋轉。"
#: editor/editor_node.cpp
msgid "Imported resources can't be saved."
-msgstr "匯入的資æºç„¡æ³•ä¿å­˜ã€‚"
+msgstr "匯入的資æºç„¡æ³•儲存。"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp
@@ -3820,7 +3705,7 @@ msgstr "ä¿å­˜è³‡æºæ™‚發生錯誤ï¼"
msgid ""
"This resource can't be saved because it does not belong to the edited scene. "
"Make it unique first."
-msgstr "由於該資æºä¸å±¬æ–¼å·²ç·¨è¼¯çš„場景,無法ä¿å­˜è©²è³‡æºã€‚請先使其ç¨ç«‹åŒ–。"
+msgstr "由於該資æºä¸å±¬æ–¼å·²ç·¨è¼¯çš„場景,無法儲存該資æºã€‚請先使其ç¨ç«‹åŒ–。"
#: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp
msgid "Save Resource As..."
@@ -3879,22 +3764,22 @@ msgid ""
"This scene can't be saved because there is a cyclic instancing inclusion.\n"
"Please resolve it and then attempt to save again."
msgstr ""
-"該場景有循環性實體化å•題,無法ä¿å­˜ã€‚\n"
+"該場景有循環性實體化å•題,無法儲存。\n"
"請先解決此å•題後å†è©¦ä¸€æ¬¡ã€‚"
#: editor/editor_node.cpp
msgid ""
"Couldn't save scene. Likely dependencies (instances or inheritance) couldn't "
"be satisfied."
-msgstr "無法ä¿å­˜å ´æ™¯ã€‚å¯èƒ½æ˜¯ç”±æ–¼ç›¸ä¾æ€§ï¼ˆå¯¦é«”或繼承)無法滿足。"
+msgstr "無法儲存場景。å¯èƒ½æ˜¯ç”±æ–¼ç›¸ä¾æ€§ï¼ˆå¯¦é«”或繼承)無法滿足。"
#: editor/editor_node.cpp
msgid "Could not save one or more scenes!"
-msgstr "無法ä¿å­˜ä¸€æˆ–多個場景ï¼"
+msgstr "無法儲存一或多個場景ï¼"
#: editor/editor_node.cpp
msgid "Save All Scenes"
-msgstr "ä¿å­˜æ‰€æœ‰å ´æ™¯"
+msgstr "儲存所有場景"
#: editor/editor_node.cpp editor/scene_tree_dock.cpp
msgid "Can't overwrite scene that is still open!"
@@ -3921,7 +3806,7 @@ msgid ""
"An error occurred while trying to save the editor layout.\n"
"Make sure the editor's user data path is writable."
msgstr ""
-"ä¿å­˜ç·¨è¼¯å™¨ç•«é¢é…置時發生錯誤。\n"
+"儲存編輯器畫é¢é…置時發生錯誤。\n"
"請確èªç·¨è¼¯å™¨çš„使用者資料路徑是å¦å¯å¯«å…¥ã€‚"
#: editor/editor_node.cpp
@@ -3990,7 +3875,7 @@ msgstr "未定義欲執行之場景。"
#: editor/editor_node.cpp
msgid "Save scene before running..."
-msgstr "執行å‰å…ˆä¿å­˜å ´æ™¯..."
+msgstr "執行å‰å…ˆå„²å­˜å ´æ™¯..."
#: editor/editor_node.cpp
msgid "Could not start subprocess!"
@@ -4017,38 +3902,36 @@ msgid "Quick Open Script..."
msgstr "快速開啟腳本…"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save & Reload"
-msgstr "ä¿å­˜ä¸¦é‡æ–°å•Ÿå‹•"
+msgstr "å„²å­˜ä¸¦é‡æ–°è¼‰å…¥"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save changes to '%s' before reloading?"
-msgstr "é—œé–‰å‰æ˜¯å¦ä¿å­˜å°ã€Œ%sã€çš„æ›´æ”¹ï¼Ÿ"
+msgstr "是å¦åœ¨é‡æ–°è¼‰å…¥å‰å„²å­˜å°ã€Œ%sã€çš„變更?"
#: editor/editor_node.cpp
msgid "Save & Close"
-msgstr "ä¿å­˜ä¸¦é—œé–‰"
+msgstr "儲存並關閉"
#: editor/editor_node.cpp
msgid "Save changes to '%s' before closing?"
-msgstr "é—œé–‰å‰æ˜¯å¦ä¿å­˜å°ã€Œ%sã€çš„æ›´æ”¹ï¼Ÿ"
+msgstr "é—œé–‰å‰æ˜¯å¦å„²å­˜å°ã€Œ%sã€çš„æ›´æ”¹ï¼Ÿ"
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
-msgstr "%sä¸å­˜åœ¨ï¼è«‹æŒ‡å®šæ–°çš„ä¿å­˜ä½ç½®ã€‚"
+msgstr "%sä¸å­˜åœ¨ï¼è«‹æŒ‡å®šæ–°çš„儲存ä½ç½®ã€‚"
#: editor/editor_node.cpp
msgid ""
"The current scene has no root node, but %d modified external resource(s) "
"were saved anyway."
-msgstr "ç›®å‰çš„場景無根節點,但%d個被更改的外部資æºå·²è¢«ä¿å­˜ã€‚"
+msgstr "ç›®å‰çš„場景無根節點,但%d個被更改的外部資æºå·²è¢«å„²å­˜ã€‚"
#: editor/editor_node.cpp
msgid ""
"A root node is required to save the scene. You can add a root node using the "
"Scene tree dock."
-msgstr "必須有根節點æ‰å¯ä¿å­˜å ´æ™¯ã€‚您å¯ä½¿ç”¨å ´æ™¯åœä½‡åˆ—以加入一個根節點。"
+msgstr "必須有根節點æ‰å¯å„²å­˜å ´æ™¯ã€‚您å¯ä½¿ç”¨å ´æ™¯åœä½‡åˆ—以加入一個根節點。"
#: editor/editor_node.cpp
msgid "Save Scene As..."
@@ -4076,7 +3959,7 @@ msgstr "è«‹å…ˆé¸æ“‡ç¯€é»žä»¥åŸ·è¡Œè©²æ“作。"
#: editor/editor_node.cpp
msgid "Current scene not saved. Open anyway?"
-msgstr "尚未ä¿å­˜ç›®å‰å ´æ™¯ã€‚ä»ç„¶è¦é–‹å•Ÿå—Žï¼Ÿ"
+msgstr "尚未儲存目å‰å ´æ™¯ã€‚ä»ç„¶è¦é–‹å•Ÿå—Žï¼Ÿ"
#: editor/editor_node.cpp
msgid "Can't undo while mouse buttons are pressed."
@@ -4104,18 +3987,18 @@ msgstr "å–æ¶ˆå¾©åŽŸï¼š%s"
#: editor/editor_node.cpp
msgid "Can't reload a scene that was never saved."
-msgstr "ç„¡æ³•é‡æ–°è¼‰å…¥å¾žæœªä¿å­˜éŽçš„場景。"
+msgstr "ç„¡æ³•é‡æ–°è¼‰å…¥å¾žæœªå„²å­˜éŽçš„場景。"
#: editor/editor_node.cpp
msgid "Reload Saved Scene"
-msgstr "釿–°è¼‰å…¥å·²ä¿å­˜çš„場景"
+msgstr "釿–°è¼‰å…¥å·²å„²å­˜çš„場景"
#: editor/editor_node.cpp
msgid ""
"The current scene has unsaved changes.\n"
"Reload the saved scene anyway? This action cannot be undone."
msgstr ""
-"ç›®å‰å ´æ™¯æœ‰æœªä¿å­˜çš„æ”¹å‹•。\n"
+"ç›®å‰å ´æ™¯æœ‰æœªå„²å­˜çš„æ”¹å‹•。\n"
"ä»è¦é‡æ–°è¼‰å…¥å ´æ™¯å—Žï¼Ÿæ­¤æ“作將無法復原。"
#: editor/editor_node.cpp
@@ -4139,21 +4022,20 @@ msgid "Open Project Manager?"
msgstr "è¦é–‹å•Ÿå°ˆæ¡ˆç®¡ç†å“¡å—Žï¼Ÿ"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Save changes to the following scene(s) before reloading?"
-msgstr "退出å‰è¦å…ˆä¿å­˜ä¸‹åˆ—場景嗎?"
+msgstr "釿–°è¼‰å…¥å‰è¦å„²å­˜ä¸‹åˆ—場景的變更嗎?"
#: editor/editor_node.cpp
msgid "Save & Quit"
-msgstr "ä¿å­˜ä¸¦é€€å‡º"
+msgstr "儲存並退出"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before quitting?"
-msgstr "退出å‰è¦å…ˆä¿å­˜ä¸‹åˆ—場景嗎?"
+msgstr "退出å‰è¦å…ˆå„²å­˜ä¸‹åˆ—場景嗎?"
#: editor/editor_node.cpp
msgid "Save changes to the following scene(s) before opening Project Manager?"
-msgstr "開啟專案管ç†å“¡å‰è¦å…ˆä¿å­˜ä»¥ä¸‹å ´æ™¯å—Žï¼Ÿ"
+msgstr "開啟專案管ç†å“¡å‰è¦å…ˆå„²å­˜ä»¥ä¸‹å ´æ™¯å—Žï¼Ÿ"
#: editor/editor_node.cpp
msgid ""
@@ -4217,7 +4099,7 @@ msgid ""
"open the scene, then save it inside the project path."
msgstr ""
"載入場景時發生錯誤,場景必須置於專案路徑內。請使用 [匯入] 來開啟該場景,並將"
-"å…¶ä¿å­˜æ–¼å°ˆæ¡ˆè·¯å¾‘內。"
+"其儲存於專案路徑內。"
#: editor/editor_node.cpp
msgid "Scene '%s' has broken dependencies:"
@@ -4319,19 +4201,16 @@ msgstr "無法寫入檔案'%s',該檔案正被使用ã€éŽ–å®šæˆ–å› æ¬Šé™ä¸è¶
#: editor/editor_node.cpp editor/editor_settings.cpp editor/scene_tree_dock.cpp
#: servers/arvr/arvr_interface.cpp
-#, fuzzy
msgid "Interface"
-msgstr "使用者界é¢"
+msgstr "界é¢"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Scene Tabs"
-msgstr "切æ›å ´æ™¯åˆ†é "
+msgstr "場景分é "
#: editor/editor_node.cpp
-#, fuzzy
msgid "Always Show Close Button"
-msgstr "æ°¸é é¡¯ç¤ºç¶²æ ¼"
+msgstr "æ°¸é é¡¯ç¤ºé—œé–‰æŒ‰éˆ•"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Resize If Many Tabs"
@@ -4346,14 +4225,12 @@ msgid "Output"
msgstr "輸出"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Always Clear Output On Play"
-msgstr "清除輸出"
+msgstr "åŸ·è¡Œæ™‚æ°¸é æ¸…除輸出"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Always Open Output On Play"
-msgstr "播放時永é é–‹å•Ÿè¼¸å‡º"
+msgstr "執行時永é é–‹å•Ÿè¼¸å‡º"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Always Close Output On Stop"
@@ -4361,41 +4238,35 @@ msgstr "åœæ­¢æ™‚æ°¸é é—œé–‰è¼¸å‡º"
#: editor/editor_node.cpp
msgid "Save On Focus Loss"
-msgstr "失去焦點時ä¿å­˜"
+msgstr "失去焦點時儲存"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Save Each Scene On Quit"
-msgstr "ä¿å­˜åˆ†æ”¯ç‚ºå ´æ™¯"
+msgstr "退出時儲存å„場景"
#: editor/editor_node.cpp editor/editor_settings.cpp
-#, fuzzy
msgid "Quit Confirmation"
-msgstr "檢視資訊"
+msgstr "退出確èª"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Show Update Spinner"
-msgstr "éš±è—æ›´æ–°æ—‹è½‰åœ–"
+msgstr "顯示更新旋轉圖"
#: editor/editor_node.cpp
msgid "Update Continuously"
msgstr "æŒçºŒæ›´æ–°"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Update Vital Only"
-msgstr "æè³ªè®Šæ›´ï¼š"
+msgstr "僅更新 Vital"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Localize Settings"
-msgstr "本地化"
+msgstr "在地化設定"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Restore Scenes On Load"
-msgstr "TimeSeek 節點"
+msgstr "載入時æ¢å¾©å ´æ™¯"
#: editor/editor_node.cpp editor/editor_settings.cpp
msgid "Show Thumbnail On Hover"
@@ -4406,23 +4277,20 @@ msgid "Inspector"
msgstr "å±¬æ€§é¢æ¿"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Default Property Name Style"
-msgstr "專案路徑:"
+msgstr "é è¨­å±¬æ€§å稱樣å¼"
#: editor/editor_node.cpp
msgid "Default Float Step"
msgstr "é è¨­æµ®é»žæ•¸é–“éš”"
#: editor/editor_node.cpp scene/gui/tree.cpp
-#, fuzzy
msgid "Disable Folding"
-msgstr "å·²åœç”¨çš„æŒ‰éˆ•"
+msgstr "åœç”¨æŠ˜ç–Š"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Auto Unfold Foreign Scenes"
-msgstr "自動展開å°å¤–場景"
+msgstr "自動展開場景"
#: editor/editor_node.cpp
msgid "Horizontal Vector2 Editing"
@@ -4433,14 +4301,12 @@ msgid "Horizontal Vector Types Editing"
msgstr "水平Vector類別編輯"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open Resources In Current Inspector"
-msgstr "åœ¨å±¬æ€§é¢æ¿ä¸­é–‹å•Ÿ"
+msgstr "在目å‰çš„å±¬æ€§é¢æ¿æ‰“開資æº"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Resources To Open In New Inspector"
-msgstr "åœ¨å±¬æ€§é¢æ¿ä¸­é–‹å•Ÿ"
+msgstr "åœ¨æ–°çš„å±¬æ€§é¢æ¿é–‹å•Ÿè³‡æº"
#: editor/editor_node.cpp
msgid "Default Color Picker Mode"
@@ -4451,9 +4317,8 @@ msgid "Version Control"
msgstr "版本控制"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Username"
-msgstr "釿–°å‘½å"
+msgstr "使用者å稱"
#: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp
msgid "SSH Public Key Path"
@@ -4525,7 +4390,7 @@ msgstr "最近開啟的場景"
#: editor/editor_node.cpp
msgid "Save Scene"
-msgstr "ä¿å­˜å ´æ™¯"
+msgstr "儲存場景"
#: editor/editor_node.cpp
msgid "Convert To..."
@@ -4579,9 +4444,8 @@ msgid "Install Android Build Template..."
msgstr "å®‰è£ Android 建置樣æ¿..."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Open User Data Folder"
-msgstr "開啟編輯器資料目錄"
+msgstr "打開使用者資料資料夾"
#: editor/editor_node.cpp editor/editor_settings.cpp
#: editor/plugins/tile_set_editor_plugin.cpp
@@ -4657,12 +4521,10 @@ msgid ""
msgstr "開啟該é¸é …後,導航網格與多邊形將在專案執行時å¯è¦‹ã€‚"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Force Shader Fallbacks"
-msgstr "強制著色器回è½"
+msgstr "強制著色器後備"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"When this option is enabled, shaders will be used in their fallback form "
"(either visible via an ubershader or hidden) during all the run time.\n"
@@ -4671,10 +4533,10 @@ msgid ""
"Asynchronous shader compilation must be enabled in the project settings for "
"this option to make a difference."
msgstr ""
-"當該é¸é …啟用時,著色器將以回è½çš„形弿–¼åŸ·è¡Œæ™‚作用(é€éŽUbershader顯示或隱"
+"啟用該é¸é …時,著色器在é‹è¡Œæ™‚會使用其後備形å¼ï¼ˆé€éŽ ubershader 顯示或隱"
"è—)。\n"
-"å¯ç”¨æ–¼é©—證回è½çš„å¤–è§€å’Œæ•ˆèƒ½ï¼Œå…¶åœ¨æ­£å¸¸çš„æƒ…å½¢ä¸‹åªæœƒçŸ­æš«åœ°é¡¯ç¤ºã€‚\n"
-"需啟用專案設定中的éžåŒæ­¥è‘—色器編譯以使該é¸é …ç™¼æ®æ•ˆæžœã€‚"
+"å¯ç”¨æ–¼é©—證後備外觀和效能,正常情æ³ä¸‹åªæœƒçŸ­æš«é¡¯ç¤ºã€‚\n"
+"必須在專案設定中啟用éžåŒæ­¥è‘—色器編譯,該é¸é …æ‰æœƒæœ‰æ•ˆæžœã€‚"
#: editor/editor_node.cpp
msgid "Synchronize Scene Changes"
@@ -4701,7 +4563,7 @@ msgid ""
"When used remotely on a device, this is more efficient when the network "
"filesystem option is enabled."
msgstr ""
-"開啟該é¸é …後,ä¿å­˜è…³æœ¬æ™‚æœƒæ–¼åŸ·è¡Œä¸­çš„éŠæˆ²å…§é‡æ–°è¼‰å…¥è…³æœ¬ã€‚\n"
+"開啟該é¸é …å¾Œï¼Œå„²å­˜è…³æœ¬æ™‚æœƒæ–¼åŸ·è¡Œä¸­çš„éŠæˆ²å…§é‡æ–°è¼‰å…¥è…³æœ¬ã€‚\n"
"若在é ç«¯è£ç½®ä¸Šä½¿ç”¨ï¼Œå¯ä½¿ç”¨ç¶²è·¯æª”案系統 NFS 以ç²å¾—最佳效能。"
#: editor/editor_node.cpp
@@ -4819,17 +4681,15 @@ msgstr "更改視訊驅動程å¼éœ€è¦é‡æ–°å•Ÿå‹•編輯器。"
#: editor/editor_node.cpp editor/project_settings_editor.cpp
#: editor/settings_config_dialog.cpp
msgid "Save & Restart"
-msgstr "ä¿å­˜ä¸¦é‡æ–°å•Ÿå‹•"
+msgstr "å„²å­˜ä¸¦é‡æ–°å•Ÿå‹•"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Update All Changes"
-msgstr "更改時更新"
+msgstr "更新所有變更"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Update Vital Changes"
-msgstr "æè³ªè®Šæ›´ï¼š"
+msgstr "æ›´æ–° Vital æ›´å‹•"
#: editor/editor_node.cpp
msgid "Hide Update Spinner"
@@ -4847,7 +4707,7 @@ msgstr "å±•é–‹åº•éƒ¨é¢æ¿"
#: editor/editor_node.cpp
msgid "Don't Save"
-msgstr "ä¸ä¿å­˜"
+msgstr "ä¸å„²å­˜"
#: editor/editor_node.cpp
msgid "Android build template is missing, please install relevant templates."
@@ -4933,7 +4793,7 @@ msgstr "釿–°è¼‰å…¥"
#: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/shader_editor_plugin.cpp
msgid "Resave"
-msgstr "釿–°ä¿å­˜"
+msgstr "釿–°å„²å­˜"
#: editor/editor_node.cpp
msgid "New Inherited"
@@ -5085,14 +4945,12 @@ msgid "Debugger"
msgstr "除錯工具"
#: editor/editor_profiler.cpp
-#, fuzzy
msgid "Profiler Frame History Size"
-msgstr "效能分æžå·¥å…·å¹€æ•¸æ­·å²æ—¥èªŒå¤§å°"
+msgstr "分æžå·¥å…·å½±æ ¼æ­·å²å¤§å°"
#: editor/editor_profiler.cpp
-#, fuzzy
msgid "Profiler Frame Max Functions"
-msgstr "釿–°å‘½å函å¼"
+msgstr "分æžå·¥å…·å½±æ ¼æœ€å¤§å‡½å¼æ•¸"
#: editor/editor_properties.cpp
msgid "Edit Text:"
@@ -5131,7 +4989,7 @@ msgid ""
"Can't create a ViewportTexture on resources saved as a file.\n"
"Resource needs to belong to a scene."
msgstr ""
-"無法為欲ä¿å­˜æˆæª”案之資æºå»ºç«‹ ViewportTexture。\n"
+"ç„¡æ³•ç‚ºæ¬²å„²å­˜æˆæª”案之資æºå»ºç«‹ ViewportTexture。\n"
"資æºå¿…須屬於一個場景。"
#: editor/editor_properties.cpp
@@ -5159,9 +5017,8 @@ msgid "Size:"
msgstr "大å°ï¼š"
#: editor/editor_properties_array_dict.cpp
-#, fuzzy
msgid "Page:"
-msgstr "é ï¼š "
+msgstr "é ï¼š"
#: editor/editor_properties_array_dict.cpp
#: editor/plugins/theme_editor_plugin.cpp
@@ -5221,20 +5078,17 @@ msgstr "新增 %s"
#: modules/visual_script/visual_script_func_nodes.cpp
#: modules/visual_script/visual_script_nodes.cpp
#: modules/visual_script/visual_script_yield_nodes.cpp
-#, fuzzy
msgid "Base Type"
-msgstr "更改基礎型別"
+msgstr "基礎型別"
#: editor/editor_resource_picker.cpp
-#, fuzzy
msgid "Edited Resource"
-msgstr "新增資æº"
+msgstr "已經編輯資"
#: editor/editor_resource_picker.cpp scene/gui/line_edit.cpp
#: scene/gui/slider.cpp scene/gui/spin_box.cpp
-#, fuzzy
msgid "Editable"
-msgstr "å¯ç·¨è¼¯çš„é …ç›®"
+msgstr "å¯ç·¨è¼¯"
#: editor/editor_resource_picker.cpp editor/property_editor.cpp
msgid "New Script"
@@ -5245,9 +5099,8 @@ msgid "Extend Script"
msgstr "擴充腳本"
#: editor/editor_resource_picker.cpp
-#, fuzzy
msgid "Script Owner"
-msgstr "腳本å稱:"
+msgstr "腳本所有者"
#: editor/editor_run_native.cpp
msgid ""
@@ -5259,9 +5112,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."
@@ -5288,21 +5140,18 @@ msgid "Did you forget the '_run' method?"
msgstr "æ˜¯å¦æœªæ–°å¢žã€Œ_runã€æ–¹æ³•?"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Editor Language"
-msgstr "編輯器é…ç½®"
+msgstr "編輯器語言"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Display Scale"
-msgstr "全部顯示"
+msgstr "顯示縮放"
#: editor/editor_settings.cpp
msgid "Custom Display Scale"
msgstr "自訂顯示縮放"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Main Font Size"
msgstr "主è¦å­—體大å°"
@@ -5319,46 +5168,40 @@ msgid "Font Hinting"
msgstr "字體微調"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Main Font"
-msgstr "主場景"
+msgstr "主è¦å­—é«”"
#: editor/editor_settings.cpp
msgid "Main Font Bold"
msgstr "主è¦å­—體粗體"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Code Font"
-msgstr "新增節點頂點"
+msgstr "程å¼ç¢¼å­—é«”"
#: editor/editor_settings.cpp
msgid "Dim Editor On Dialog Popup"
msgstr "å°è©±æ¡†å½ˆå‡ºæ™‚使編輯器變暗"
#: editor/editor_settings.cpp main/main.cpp
-#, fuzzy
msgid "Low Processor Mode Sleep (µsec)"
-msgstr "低處ç†å™¨ä½¿ç”¨æ¨¡å¼ç¡çœ ï¼ˆå¾®ç§’)"
+msgstr "低處ç†å™¨ç¡çœ æ¨¡å¼ï¼ˆå¾®ç§’)"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Unfocused Low Processor Mode Sleep (µsec)"
-msgstr "éžèšç„¦ä½Žè™•ç†å™¨ä½¿ç”¨æ¨¡å¼ç¡çœ ï¼ˆå¾®ç§’)"
+msgstr "未èšç„¦ä½Žè™•ç†å™¨ç¡çœ æ¨¡å¼ï¼ˆå¾®ç§’)"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Separate Distraction Mode"
-msgstr "專注模å¼"
+msgstr "ç¨ç«‹å°ˆæ³¨æ¨¡å¼"
#: editor/editor_settings.cpp
msgid "Automatically Open Screenshots"
msgstr "自動開啟截圖"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Max Array Dictionary Items Per Page"
-msgstr "æ¯é æœ€å¤§é™£åˆ—字典項目數"
+msgstr "æ¯é æœ€å¤§é™£åˆ—å­—å…¸ç‰©å“æ•¸"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
#: editor/plugins/theme_editor_plugin.cpp scene/gui/control.cpp
@@ -5375,131 +5218,108 @@ msgid "Icon And Font Color"
msgstr "圖標åŠå­—é«”é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Color"
-msgstr "é¡è‰²"
+msgstr "基礎é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Accent Color"
-msgstr "鏿“‡é¡è‰²"
+msgstr "強調é¡è‰²"
#: editor/editor_settings.cpp scene/resources/environment.cpp
msgid "Contrast"
msgstr "å°æ¯”"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Relationship Line Opacity"
msgstr "關係線ä¸é€æ˜Žåº¦"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Highlight Tabs"
-msgstr "正在ä¿å­˜å…‰ç…§åœ–"
+msgstr "çªé¡¯é¸é …å¡"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Border Size"
-msgstr "邊界åƒç´ "
+msgstr "邊框大å°"
#: editor/editor_settings.cpp
msgid "Use Graph Node Headers"
msgstr "使用圖形節點標題"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Additional Spacing"
-msgstr "é‡è¤‡å‹•ç•«"
+msgstr "é¡å¤–é–“è·"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Custom Theme"
-msgstr "編輯器主題"
+msgstr "自訂主題"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Script Button"
-msgstr "滾輪å‘峿Œ‰éµ"
+msgstr "顯示腳本按鈕"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Directories"
msgstr "æ–¹å‘"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Autoscan Project Path"
-msgstr "專案路徑:"
+msgstr "自動掃æå°ˆæ¡ˆè·¯å¾‘"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Project Path"
-msgstr "專案路徑:"
+msgstr "é è¨­å°ˆæ¡ˆè·¯å¾‘"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "On Save"
-msgstr "ä¿å­˜"
+msgstr "儲存時"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Compress Binary Resources"
-msgstr "複製資æº"
+msgstr "壓縮二進ä½è³‡æº"
#: editor/editor_settings.cpp
msgid "Safe Save On Backup Then Rename"
-msgstr "備份時安全ä¿å­˜å¾Œé‡æ–°å‘½å"
+msgstr "å‚™ä»½æ™‚å®‰å…¨å„²å­˜å¾Œé‡æ–°å‘½å"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "File Dialog"
-msgstr "XForm å°è©±æ¡†"
+msgstr "檔案å°è©±æ¡†"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Thumbnail Size"
-msgstr "縮圖…"
+msgstr "縮圖大å°"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Docks"
-msgstr "功能介é¢"
+msgstr "颿¿"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Scene Tree"
-msgstr "正在編輯場景樹"
+msgstr "場景樹"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Start Create Dialog Fully Expanded"
-msgstr "開始新建完全展開å°è©±"
+msgstr "é è¨­å®Œå…¨å±•開建立å°è©±æ¡†"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Always Show Folders"
-msgstr "æ°¸é é¡¯ç¤ºç¶²æ ¼"
+msgstr "æ°¸é é¡¯ç¤ºè³‡æ–™å¤¾"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Property Editor"
-msgstr "群組編輯器"
+msgstr "屬性編輯器"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Auto Refresh Interval"
-msgstr "自動刷新間隔"
+msgstr "自動更新頻率"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Subresource Hue Tint"
-msgstr "å­è³‡æº"
+msgstr "å­è³‡æºå½©è‰²é¡¯ç¤º"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Color Theme"
-msgstr "編輯器主題"
+msgstr "é¡è‰²ä¸»é¡Œ"
#: editor/editor_settings.cpp scene/3d/label_3d.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5508,52 +5328,44 @@ msgstr "行間è·"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
#: modules/gdscript/editor/gdscript_highlighter.cpp
-#, fuzzy
msgid "Highlighting"
-msgstr "呿€§å…‰ç…§"
+msgstr "çªå‡ºé¡¯ç¤º"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Syntax Highlighting"
-msgstr "高亮顯示語法"
+msgstr "語法çªå‡ºé¡¯ç¤º"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
msgid "Highlight All Occurrences"
msgstr "凸顯所有符åˆé …ç›®"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Highlight Current Line"
-msgstr "凸顯目å‰è¡Œ"
+msgstr "çªé¡¯ç›®å‰è¡Œ"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Highlight Type Safe Lines"
msgstr "凸顯型別安全的行"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Indent"
-msgstr "å‘左縮排"
+msgstr "縮排"
#: editor/editor_settings.cpp editor/plugins/script_text_editor.cpp
msgid "Auto Indent"
msgstr "自動縮排"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Convert Indent On Save"
-msgstr "轉æ›ç¸®æŽ’為空白"
+msgstr "儲存時轉æ›ç¸®æŽ’"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Draw Tabs"
-msgstr "繪製呼å«ï¼š"
+msgstr "繪製分é "
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Draw Spaces"
-msgstr "繪製呼å«ï¼š"
+msgstr "繪製空格"
#: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/tile_map.cpp
@@ -5571,93 +5383,88 @@ msgid "V Scroll Speed"
msgstr "垂直滾動速度"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Minimap"
-msgstr "顯示原點"
+msgstr "顯示迷你地圖"
#: editor/editor_settings.cpp
msgid "Minimap Width"
msgstr "迷你地圖寬度"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Mouse Extra Buttons Navigate History"
-msgstr "滑鼠é¡å¤–æŒ‰éµæ“作歷å²ç´€éŒ„"
+msgstr "使用é¡å¤–æ»‘é¼ æŒ‰éµæŸ¥çœ‹æ­·å²"
+
+#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr "æ‹–ç§»é¸æ“‡çš„æª”案"
+
+#: editor/editor_settings.cpp
+msgid "Stay In Script Editor On Node Selected"
+msgstr "鏿“‡ç¯€é»žæ™‚ä¿ç•™åœ¨è…³æœ¬ç·¨è¼¯å™¨ä¸­"
#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "外觀"
#: editor/editor_settings.cpp scene/gui/text_edit.cpp
-#, fuzzy
msgid "Show Line Numbers"
-msgstr "行號:"
+msgstr "顯示行號"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Line Numbers Zero Padded"
-msgstr "行號:"
+msgstr "行號歸零"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Bookmark Gutter"
-msgstr "顯示書籤欄ä½"
+msgstr "顯示書籤欄"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Breakpoint Gutter"
-msgstr "è·³éŽä¸­æ–·é»ž"
+msgstr "顯示中斷點欄"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Info Gutter"
-msgstr "顯示資訊欄ä½"
+msgstr "顯示資訊欄"
#: editor/editor_settings.cpp
msgid "Code Folding"
msgstr "程å¼ç¢¼æŠ˜ç–Š"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Word Wrap"
-msgstr "æ›è¡Œ"
+msgstr "自動æ›è¡Œ"
#: editor/editor_settings.cpp
msgid "Show Line Length Guidelines"
msgstr "顯示行長度åƒè€ƒç·š"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Line Length Guideline Soft Column"
-msgstr "行長度åƒè€ƒç·šè»Ÿåˆ—"
+msgstr "行長度åƒè€ƒç·šè»Ÿåˆ—數"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Line Length Guideline Hard Column"
-msgstr "行長度åƒè€ƒç·šç¡¬åˆ—"
+msgstr "行長度åƒè€ƒç·šç¡¬åˆ—數"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Script List"
-msgstr "腳本編輯器"
+msgstr "腳本列表"
#: editor/editor_settings.cpp
msgid "Show Members Overview"
msgstr "顯示æˆå“¡æ¦‚è¦"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Files"
msgstr "檔案"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Trim Trailing Whitespace On Save"
-msgstr "移除後方空白字元"
+msgstr "ä¿å­˜æ™‚移除後方空白字元"
#: editor/editor_settings.cpp
msgid "Autosave Interval Secs"
-msgstr "自動ä¿å­˜é–“隔秒數"
+msgstr "自動儲存間隔秒數"
#: editor/editor_settings.cpp editor/plugins/script_editor_plugin.cpp
msgid "Restore Scripts On Load"
@@ -5665,11 +5472,11 @@ msgstr "載入時æ¢å¾©è…³æœ¬"
#: editor/editor_settings.cpp
msgid "Auto Reload And Parse Scripts On Save"
-msgstr ""
+msgstr "å„²å­˜æ™‚è‡ªå‹•é‡æ–°è¼‰å…¥èˆ‡è§£æžè…³æœ¬"
#: editor/editor_settings.cpp
msgid "Auto Reload Scripts On External Change"
-msgstr ""
+msgstr "å¾žå¤–éƒ¨æ›´æ”¹æ™‚è‡ªå‹•é‡æ–°è¼‰å…¥è…³æœ¬"
#: editor/editor_settings.cpp
msgid "Create Signal Callbacks"
@@ -5684,14 +5491,12 @@ msgid "Cursor"
msgstr "游標"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Scroll Past End Of File"
-msgstr "æ»¾å‹•è¶…éŽæª”案çµå°¾"
+msgstr "æ»¾å‹•è¶…éŽæª”案末尾"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Block Caret"
-msgstr "方形æ’入符"
+msgstr "方形 Caret"
#: editor/editor_settings.cpp
msgid "Caret Blink"
@@ -5702,14 +5507,12 @@ msgid "Caret Blink Speed"
msgstr "æ’入符閃çˆé€Ÿåº¦"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Right Click Moves Caret"
-msgstr "å³éµé»žæ“Šä»¥æ–°å¢žæŽ§åˆ¶é»ž"
+msgstr "按一下å³éµä¾†ç§»å‹•éŠæ¨™"
#: editor/editor_settings.cpp modules/gdscript/gdscript.cpp
#: modules/gdscript/gdscript_editor.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Completion"
msgstr "自動完æˆ"
@@ -5718,103 +5521,91 @@ msgid "Idle Parse Delay"
msgstr "閒置解æžå»¶é²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Auto Brace Complete"
msgstr "自動補齊括號"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Code Complete Delay"
-msgstr "程å¼ç¢¼å®Œæˆå»¶é²"
+msgstr "程å¼ç¢¼è‡ªå‹•完æˆå»¶é²"
#: editor/editor_settings.cpp
msgid "Put Callhint Tooltip Below Current Line"
-msgstr ""
+msgstr "å°‡å‘¼å«æç¤ºå·¥å…·æç¤ºæ¡†ç½®æ–¼ç•¶å‰è¡Œä¹‹ä¸‹"
#: editor/editor_settings.cpp
msgid "Callhint Tooltip Offset"
-msgstr ""
+msgstr "å‘¼å«æç¤ºå·¥å…·æç¤ºæ¡†åç§»é‡"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Complete File Paths"
-msgstr "複製節點路徑"
+msgstr "補全檔案路徑"
#: editor/editor_settings.cpp modules/gdscript/gdscript_editor.cpp
-#, fuzzy
msgid "Add Type Hints"
-msgstr "新增類別"
+msgstr "新增類別æç¤º"
#: editor/editor_settings.cpp
msgid "Use Single Quotes"
msgstr "使用單引號"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Show Help Index"
-msgstr "顯示輔助資訊"
+msgstr "顯示輔助索引"
#: editor/editor_settings.cpp
msgid "Help Font Size"
-msgstr ""
+msgstr "幫助字體大å°"
#: editor/editor_settings.cpp
msgid "Help Source Font Size"
-msgstr ""
+msgstr "幫助æºå­—體大å°"
#: editor/editor_settings.cpp
msgid "Help Title Font Size"
-msgstr ""
+msgstr "幫助標題字體大å°"
#: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp
msgid "Grid Map"
msgstr "網格地圖"
#: editor/editor_settings.cpp modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Pick Distance"
-msgstr "鏿“‡è·é›¢ï¼š"
+msgstr "拾å–è·é›¢"
#: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Preview Size"
-msgstr "é è¦½"
+msgstr "é è¦½å¤§å°"
#: editor/editor_settings.cpp
msgid "Primary Grid Color"
-msgstr ""
+msgstr "主è¦ç¶²æ ¼é¡è‰²"
#: editor/editor_settings.cpp
msgid "Secondary Grid Color"
-msgstr ""
+msgstr "次è¦ç¶²æ ¼é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Selection Box Color"
-msgstr "僅æœå°‹æ‰€é¸å€åŸŸ"
+msgstr "所é¸å€åŸŸé¡è‰²"
#: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
-#, fuzzy
msgid "3D Gizmos"
-msgstr "Gizmo"
+msgstr "3D 控制項"
#: editor/editor_settings.cpp editor/plugins/path_editor_plugin.cpp
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
-#, fuzzy
msgid "Gizmo Colors"
-msgstr "發射色彩"
+msgstr "控制項é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Instanced"
-msgstr "實體"
+msgstr "已實體化"
#: editor/editor_settings.cpp modules/gltf/gltf_node.cpp
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Joint"
-msgstr "點"
+msgstr "交點"
#: editor/editor_settings.cpp scene/2d/collision_shape_2d.cpp
#: scene/2d/cpu_particles_2d.cpp scene/2d/touch_screen_button.cpp
@@ -5823,347 +5614,301 @@ msgstr "點"
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
msgid "Shape"
-msgstr ""
+msgstr "形狀"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Primary Grid Steps"
-msgstr "網格大å°ï¼š"
+msgstr "主網格步長"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid Size"
-msgstr "網格大å°ï¼š"
+msgstr "網格大å°"
#: editor/editor_settings.cpp
msgid "Grid Division Level Max"
-msgstr ""
+msgstr "網格劃分級別最大值"
#: editor/editor_settings.cpp
msgid "Grid Division Level Min"
-msgstr ""
+msgstr "網格劃分級別最å°å€¼"
#: editor/editor_settings.cpp
msgid "Grid Division Level Bias"
-msgstr ""
+msgstr "網格劃分級別å差值"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid XZ Plane"
-msgstr "網格地圖繪圖"
+msgstr "網格XZå¹³é¢"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid XY Plane"
-msgstr "網格地圖繪圖"
+msgstr "網格XYå¹³é¢"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Grid YZ Plane"
-msgstr "網格地圖繪圖"
+msgstr "網格YZå¹³é¢"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default FOV"
-msgstr "é è¨­"
+msgstr "é è¨­FOV"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Z Near"
-msgstr "é è¨­ä¸»é¡Œ"
+msgstr "é è¨­Z近處"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Z Far"
-msgstr "é è¨­"
+msgstr "é è¨­Zé è™•"
#: editor/editor_settings.cpp
msgid "Lightmap Baking Number Of CPU Threads"
-msgstr ""
+msgstr "光照圖烘焙中央處ç†å™¨ç·šç¨‹æ•¸"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Navigation Scheme"
-msgstr "導航模å¼"
+msgstr "導引模å¼"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Invert Y Axis"
-msgstr "編輯 Y 軸"
+msgstr "翻轉 Y 軸"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Invert X Axis"
-msgstr "編輯 X 軸"
+msgstr "翻轉 X 軸"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Zoom Style"
-msgstr "縮å°"
+msgstr "縮放樣å¼"
#: editor/editor_settings.cpp
msgid "Emulate Numpad"
-msgstr ""
+msgstr "模擬數字éµç›¤"
#: editor/editor_settings.cpp
msgid "Emulate 3 Button Mouse"
-msgstr ""
+msgstr "æ¨¡æ“¬ä¸‰éµæ»‘é¼ "
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Orbit Modifier"
-msgstr "按最早修改時間排åº"
+msgstr "軌é“修改器"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Pan Modifier"
-msgstr "平移模å¼"
+msgstr "平移修改器"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Zoom Modifier"
-msgstr "已修改"
+msgstr "縮放修改器"
#: editor/editor_settings.cpp editor/plugins/spatial_editor_plugin.cpp
msgid "Warped Mouse Panning"
-msgstr ""
+msgstr "彎曲滑鼠平移"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Navigation Feel"
-msgstr "導航模å¼"
+msgstr "導航風格"
#: editor/editor_settings.cpp
msgid "Orbit Sensitivity"
-msgstr ""
+msgstr "軌é“éˆæ•度"
#: editor/editor_settings.cpp
msgid "Orbit Inertia"
-msgstr ""
+msgstr "è»Œé“æ…£æ€§"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Translation Inertia"
-msgstr "翻譯"
+msgstr "平移慣性"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Zoom Inertia"
-msgstr "放大"
+msgstr "變焦慣性"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook"
-msgstr "自由視圖 上"
+msgstr "自由觀看"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Navigation Scheme"
-msgstr "建立導航網格"
+msgstr "自由觀看ç€è¦½æ¨¡å¼"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Sensitivity"
-msgstr "自由視圖 左"
+msgstr "è‡ªç”±è§€çœ‹éˆæ•度"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Inertia"
-msgstr "自由視圖 左"
+msgstr "自由觀看慣性"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Base Speed"
-msgstr "加速自由視圖速度"
+msgstr "自由觀看基本速度"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Activation Modifier"
-msgstr "放慢自由視圖速度"
+msgstr "自由觀看啟動修飾符"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Freelook Speed Zoom Link"
-msgstr "加速自由視圖速度"
+msgstr "自由觀看速度縮放連çµ"
#: editor/editor_settings.cpp editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Grid Color"
-msgstr "鏿“‡é¡è‰²"
+msgstr "網格é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Guides Color"
-msgstr "鏿“‡é¡è‰²"
+msgstr "åƒè€ƒç·šé¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Smart Snapping Line Color"
-msgstr "智慧型å¸é™„"
+msgstr "æ™ºæ…§æ•æ‰ç·šé¡è‰²"
#: editor/editor_settings.cpp
msgid "Bone Width"
-msgstr ""
+msgstr "骨骼寬度"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Color 1"
-msgstr "釿–°å‘½åé¡è‰²é …ç›®"
+msgstr "骨骼é¡è‰²1"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Color 2"
-msgstr "釿–°å‘½åé¡è‰²é …ç›®"
+msgstr "骨骼é¡è‰²2"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Selected Color"
-msgstr "設定所é¸ä¹‹è¨­å®šæª”:"
+msgstr "所é¸ä¹‹éª¨éª¼é¡è‰²"
#: editor/editor_settings.cpp
msgid "Bone IK Color"
-msgstr ""
+msgstr "骨骼IKé¡è‰²"
#: editor/editor_settings.cpp
msgid "Bone Outline Color"
-msgstr ""
+msgstr "骨骼輪廓é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Bone Outline Size"
-msgstr "輪廓尺寸:"
+msgstr "骨骼輪廓大å°"
#: editor/editor_settings.cpp
msgid "Viewport Border Color"
-msgstr ""
+msgstr "檢視å€é‚Šæ¡†é¡è‰²"
#: editor/editor_settings.cpp
msgid "Constrain Editor View"
-msgstr ""
+msgstr "é™åˆ¶ç·¨è¼¯å™¨è¦–圖"
#: editor/editor_settings.cpp
msgid "Simple Panning"
-msgstr ""
+msgstr "簡易平移"
#: editor/editor_settings.cpp
msgid "Scroll To Pan"
-msgstr ""
+msgstr "滾動以平移"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Pan Speed"
-msgstr "速度:"
+msgstr "平移速度"
#: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Poly Editor"
-msgstr "Polygon2D UV 編輯器"
+msgstr "多邊形編輯器"
#: editor/editor_settings.cpp
msgid "Point Grab Radius"
-msgstr ""
+msgstr "點抓å–åŠå¾‘"
#: editor/editor_settings.cpp editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Show Previous Outline"
-msgstr "上一個平é¢"
+msgstr "顯示上一個大綱"
#: editor/editor_settings.cpp editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Autorename Animation Tracks"
-msgstr "釿–°å‘½åå‹•ç•«"
+msgstr "è‡ªå‹•é‡æ–°å‘½å動畫軌é“"
#: editor/editor_settings.cpp
msgid "Default Create Bezier Tracks"
-msgstr ""
+msgstr "é è¨­å»ºç«‹è²èŒ²è»Œé“"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Default Create Reset Tracks"
-msgstr "貼上關éµç•«æ ¼"
+msgstr "é è¨­å»ºç«‹é‡ç½®è»Œé“"
#: editor/editor_settings.cpp
msgid "Onion Layers Past Color"
-msgstr ""
+msgstr "洋蔥層先å‰é¡è‰²"
#: editor/editor_settings.cpp
msgid "Onion Layers Future Color"
-msgstr ""
+msgstr "洋蔥層未來é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Visual Editors"
-msgstr "群組編輯器"
+msgstr "視覺化編輯器"
#: editor/editor_settings.cpp
msgid "Minimap Opacity"
-msgstr ""
+msgstr "迷你地圖ä¸é€æ˜Žåº¦"
#: editor/editor_settings.cpp
msgid "Window Placement"
-msgstr ""
+msgstr "視窗擺放"
#: editor/editor_settings.cpp scene/2d/back_buffer_copy.cpp scene/2d/sprite.cpp
#: scene/2d/visibility_notifier_2d.cpp scene/3d/sprite_3d.cpp
#: scene/gui/control.cpp
-#, fuzzy
msgid "Rect"
-msgstr "全矩形"
+msgstr "矩形"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Rect Custom Position"
-msgstr "設定曲線外控制點ä½ç½®"
+msgstr "矩形自定義ä½ç½®"
#: editor/editor_settings.cpp platform/android/export/export_plugin.cpp
msgid "Screen"
-msgstr ""
+msgstr "螢幕"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Auto Save"
-msgstr "自動剪è£"
+msgstr "自動ä¿å­˜"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Save Before Running"
-msgstr "執行å‰å…ˆä¿å­˜å ´æ™¯..."
+msgstr "執行å‰å„²å­˜"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Font Size"
-msgstr "å‰è¦–圖"
+msgstr "字體大å°"
#: editor/editor_settings.cpp
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Remote Host"
-msgstr "é ç«¯ "
+msgstr "é ç«¯ä¸»æ©Ÿ"
#: editor/editor_settings.cpp
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Remote Port"
-msgstr "移除控制點"
+msgstr "é ç«¯é˜œ"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Editor SSL Certificates"
-msgstr "編輯器設定"
+msgstr "編輯SSLèªè­‰"
#: editor/editor_settings.cpp
msgid "HTTP Proxy"
-msgstr ""
+msgstr "HTTP 代ç†ç¨‹å¼"
#: editor/editor_settings.cpp
msgid "Host"
-msgstr ""
+msgstr "主機"
#: editor/editor_settings.cpp editor/fileserver/editor_file_server.cpp
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Port"
-msgstr ""
+msgstr "連接埠"
#. TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects.
#: editor/editor_settings.cpp
@@ -6172,185 +5917,162 @@ msgstr "專案管ç†å“¡"
#. TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects.
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Sorting Order"
-msgstr "釿–°å‘½å資料夾:"
+msgstr "æŽ’åºæ–¹å¼"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Symbol Color"
-msgstr ""
+msgstr "符號é¡è‰²"
#: editor/editor_settings.cpp
msgid "Keyword Color"
-msgstr ""
+msgstr "é—œéµå­—é¡è‰²"
#: editor/editor_settings.cpp
msgid "Control Flow Keyword Color"
-msgstr ""
+msgstr "控制æµé—œéµå­—é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Base Type Color"
-msgstr "更改基礎型別"
+msgstr "基礎型別é¡è‰²"
#: editor/editor_settings.cpp
msgid "Engine Type Color"
-msgstr ""
+msgstr "引擎類別é¡è‰²"
#: editor/editor_settings.cpp
msgid "User Type Color"
-msgstr ""
+msgstr "使用者類別é¡è‰²"
#: editor/editor_settings.cpp
msgid "Comment Color"
-msgstr ""
+msgstr "註解é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "String Color"
-msgstr "儲存檔案:"
+msgstr "字串é¡è‰²"
#: editor/editor_settings.cpp platform/javascript/export/export.cpp
#: platform/uwp/export/export.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Background Color"
-msgstr "無效的背景é¡è‰²ã€‚"
+msgstr "背景é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Completion Background Color"
-msgstr "無效的背景é¡è‰²ã€‚"
+msgstr "自動補全背景é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Completion Selected Color"
-msgstr "匯入所é¸"
+msgstr "自動補全所é¸é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Existing Color"
-msgstr ""
+msgstr "è‡ªå‹•è£œå…¨ç¾æœ‰é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Scroll Color"
-msgstr ""
+msgstr "自動補全æ²è»¸é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Completion Font Color"
-msgstr ""
+msgstr "自動補全字型é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Text Color"
-msgstr "下一個地æ¿"
+msgstr "文字é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Line Number Color"
-msgstr "行號:"
+msgstr "行號é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Safe Line Number Color"
-msgstr "行號:"
+msgstr "安全行號é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Caret Color"
-msgstr ""
+msgstr "跳脫字元é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Caret Background Color"
-msgstr "無效的背景é¡è‰²ã€‚"
+msgstr "跳脫字元背景é¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Text Selected Color"
-msgstr "刪除所é¸"
+msgstr "æ‰€é¸æ–‡å­—é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Selection Color"
-msgstr "僅æœå°‹æ‰€é¸å€åŸŸ"
+msgstr "所é¸é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Brace Mismatch Color"
-msgstr ""
+msgstr "大括號ä¸å°ç¨±é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Current Line Color"
-msgstr "ç›®å‰å ´æ™¯"
+msgstr "ç›®å‰è¡Œé¡è‰²"
#: editor/editor_settings.cpp
msgid "Line Length Guideline Color"
-msgstr ""
+msgstr "線長導引é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Word Highlighted Color"
-msgstr "高亮顯示語法"
+msgstr "單字醒目顯示é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Number Color"
-msgstr ""
+msgstr "數字é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Function Color"
-msgstr "函å¼"
+msgstr "函å¼é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Member Variable Color"
-msgstr "釿–°å‘½å變數"
+msgstr "æˆå“¡è®Šæ•¸é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Mark Color"
-msgstr "鏿“‡é¡è‰²"
+msgstr "標記é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Bookmark Color"
-msgstr "書籤"
+msgstr "書籤é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Breakpoint Color"
-msgstr "中斷點"
+msgstr "中斷點é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Executing Line Color"
-msgstr ""
+msgstr "執行列é¡è‰²"
#: editor/editor_settings.cpp scene/resources/default_theme/default_theme.cpp
msgid "Code Folding Color"
-msgstr ""
+msgstr "程å¼ç¢¼æ‘ºç–Šé¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Search Result Color"
-msgstr "æœå°‹çµæžœ"
+msgstr "æœå°‹çµæžœé¡è‰²"
#: editor/editor_settings.cpp
-#, fuzzy
msgid "Search Result Border Color"
-msgstr "æœå°‹çµæžœ"
+msgstr "æœå°‹çµæžœé‚Šç•Œé¡è‰²"
#: editor/editor_spin_slider.cpp
msgid "Hold %s to round to integers. Hold Shift for more precise changes."
msgstr "æŒ‰ä½ %s 以喿•´æ•¸ã€‚æŒ‰ä½ Shift 以進行更精確的更動。"
#: editor/editor_spin_slider.cpp scene/gui/button.cpp
-#, fuzzy
msgid "Flat"
-msgstr "å¹³é¢0"
+msgstr "å¹³é¢"
#: editor/editor_spin_slider.cpp
-#, fuzzy
msgid "Hide Slider"
-msgstr "碰撞模å¼"
+msgstr "éš±è—æ‹–曳æ¢"
#: editor/editor_sub_scene.cpp
msgid "Select Node(s) to Import"
@@ -6370,9 +6092,8 @@ msgstr "自節點中匯入:"
#. TRANSLATORS: %s refers to the name of a version control system (e.g. "Git").
#: editor/editor_vcs_interface.cpp
-#, fuzzy
msgid "%s Error"
-msgstr "錯誤"
+msgstr "%s 錯誤"
#: editor/export_template_manager.cpp
msgid "Open the folder containing these templates."
@@ -6636,13 +6357,13 @@ msgstr ""
#: editor/fileserver/editor_file_server.cpp
msgid "File Server"
-msgstr ""
+msgstr "檔案伺æœå™¨"
#: editor/fileserver/editor_file_server.cpp
#: editor/plugins/version_control_editor_plugin.cpp
#: platform/uwp/export/export.cpp platform/windows/export/export.cpp
msgid "Password"
-msgstr ""
+msgstr "密碼"
#: editor/filesystem_dock.cpp
msgid "Favorites"
@@ -6700,6 +6421,9 @@ msgid ""
"After renaming to an unknown extension, the file won't be shown in the "
"editor anymore."
msgstr ""
+"編輯器無法辨識該檔案副檔å。\n"
+"如果你ä»è¦é‡æ–°å‘½å,請使用系統的檔案管ç†å“¡ã€‚\n"
+"釿–°å‘½å為未知副檔åå¾Œï¼Œè©²æª”æ¡ˆä¸æœƒåœ¨ç·¨è¼¯å™¨ä¸­é¡¯ç¤ºã€‚"
#: editor/filesystem_dock.cpp
msgid ""
@@ -6919,14 +6643,12 @@ msgid "Replace..."
msgstr "å–代..."
#: editor/find_in_files.cpp editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Replace in Files"
-msgstr "å–代全部"
+msgstr "在檔案中å–代"
#: editor/find_in_files.cpp
-#, fuzzy
msgid "Replace All (NO UNDO)"
-msgstr "å–代全部"
+msgstr "å–代全部(ä¸å¯å¾©åŽŸï¼‰"
#: editor/find_in_files.cpp
msgid "Searching..."
@@ -6999,43 +6721,40 @@ msgstr "管ç†ç¾¤çµ„"
#: editor/import/editor_import_collada.cpp
msgid "Collada"
-msgstr ""
+msgstr "Collada"
#: editor/import/editor_import_collada.cpp
msgid "Use Ambient"
-msgstr ""
+msgstr "使用環境通é“"
#: editor/import/resource_importer_bitmask.cpp
-#, fuzzy
msgid "Create From"
-msgstr "建立資料夾"
+msgstr "建立自"
#: editor/import/resource_importer_bitmask.cpp
#: servers/audio/effects/audio_effect_compressor.cpp
msgid "Threshold"
-msgstr ""
+msgstr "臨界值"
#: editor/import/resource_importer_csv_translation.cpp
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_scene.cpp
#: editor/import/resource_importer_texture.cpp
#: editor/import/resource_importer_wav.cpp scene/3d/gi_probe.cpp
-#, fuzzy
msgid "Compress"
-msgstr "元件"
+msgstr "壓縮"
#: editor/import/resource_importer_csv_translation.cpp
msgid "Delimiter"
-msgstr ""
+msgstr "分隔符號"
#: editor/import/resource_importer_layered_texture.cpp
-#, fuzzy
msgid "ColorCorrect"
-msgstr "é¡è‰²å‡½å¼ã€‚"
+msgstr "é¡è‰²æ ¡æ­£"
#: editor/import/resource_importer_layered_texture.cpp
msgid "No BPTC If RGB"
-msgstr ""
+msgstr "å‡è¨­æ˜¯RGBä¸ä½¿ç”¨BPTC"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp scene/2d/cpu_particles_2d.cpp
@@ -7043,83 +6762,73 @@ msgstr ""
#: scene/resources/material.cpp scene/resources/particles_material.cpp
#: scene/resources/texture.cpp scene/resources/visual_shader.cpp
msgid "Flags"
-msgstr ""
+msgstr "旗標"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp scene/animation/tween.cpp
#: scene/resources/texture.cpp
msgid "Repeat"
-msgstr ""
+msgstr "é‡è¦†"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp scene/2d/light_2d.cpp
#: scene/gui/control.cpp
-#, fuzzy
msgid "Filter"
-msgstr "篩é¸ï¼š"
+msgstr "篩é¸"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Mipmaps"
-msgstr "訊號"
+msgstr "Mipmap"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
msgid "Anisotropic"
-msgstr ""
+msgstr "ç•°å‘æ€§"
#: editor/import/resource_importer_layered_texture.cpp
#: editor/import/resource_importer_texture.cpp
msgid "sRGB"
-msgstr ""
+msgstr "sRGB"
#: editor/import/resource_importer_layered_texture.cpp
-#, fuzzy
msgid "Slices"
-msgstr "自動剪è£"
+msgstr "切片"
#: editor/import/resource_importer_layered_texture.cpp
#: scene/gui/aspect_ratio_container.cpp scene/gui/control.cpp
#: scene/gui/nine_patch_rect.cpp scene/gui/scroll_container.cpp
#: scene/resources/style_box.cpp
-#, fuzzy
msgid "Horizontal"
-msgstr "水平:"
+msgstr "æ°´å¹³"
#: editor/import/resource_importer_layered_texture.cpp
#: scene/gui/aspect_ratio_container.cpp scene/gui/control.cpp
#: scene/gui/nine_patch_rect.cpp scene/gui/scroll_container.cpp
#: scene/resources/style_box.cpp
-#, fuzzy
msgid "Vertical"
-msgstr "垂直:"
+msgstr "垂直"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Generate Tangents"
-msgstr "產生點"
+msgstr "產生切線"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Scale Mesh"
-msgstr "縮放模å¼"
+msgstr "縮放網格"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Offset Mesh"
-msgstr "å移:"
+msgstr "Mesh åç§»"
#: editor/import/resource_importer_obj.cpp
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Octahedral Compression"
-msgstr "設定表示å¼"
+msgstr "å…«é¢é«”壓縮"
#: editor/import/resource_importer_obj.cpp
-#, fuzzy
msgid "Optimize Mesh Flags"
-msgstr "大å°ï¼š "
+msgstr "優化 Mesh 標誌"
#: editor/import/resource_importer_scene.cpp
msgid "Import as Single Scene"
@@ -7163,101 +6872,84 @@ msgstr "匯入為多個場景 + ç´ æ"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Nodes"
msgstr "節點"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Type"
-msgstr "æˆå“¡åž‹åˆ¥"
+msgstr "根型別"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Name"
-msgstr "é ç«¯ "
+msgstr "æ ¹å稱"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Root Scale"
-msgstr "縮放"
+msgstr "根縮放"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Custom Script"
-msgstr "剪下節點"
+msgstr "自訂腳本"
#: editor/import/resource_importer_scene.cpp scene/resources/texture.cpp
-#, fuzzy
msgid "Storage"
-msgstr "儲存檔案:"
+msgstr "儲存"
#: editor/import/resource_importer_scene.cpp
msgid "Use Legacy Names"
-msgstr ""
+msgstr "使用既有å稱"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Materials"
-msgstr "æè³ªè®Šæ›´ï¼š"
+msgstr "æè³ª"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep On Reimport"
-msgstr "釿–°åŒ¯å…¥"
+msgstr "ä¿æŒæˆ–釿–°åŒ¯å…¥"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Meshes"
msgstr "網格"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Ensure Tangents"
-msgstr "修改曲線切線"
+msgstr "確ä¿åˆ‡ç·š"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Light Baking"
-msgstr "烘焙光照圖"
+msgstr "光照烘焙"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Lightmap Texel Size"
-msgstr "烘焙光照圖"
+msgstr "光照圖紋ç†å…ƒç´ å¤§å°"
#: editor/import/resource_importer_scene.cpp modules/gltf/gltf_state.cpp
msgid "Skins"
-msgstr ""
+msgstr "Skin"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Use Named Skins"
-msgstr "使用縮放å¸é™„"
+msgstr "使用命å Skin"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "External Files"
-msgstr "開啟檔案"
+msgstr "é¡å¤–檔案"
#: editor/import/resource_importer_scene.cpp
msgid "Store In Subdir"
-msgstr ""
+msgstr "儲存於å­ç›®éŒ„"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Filter Script"
msgstr "篩é¸è…³æœ¬"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Keep Custom Tracks"
-msgstr "變æ›"
+msgstr "ä¿ç•™è‡ªå®šè»Œé“"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Optimizer"
-msgstr "最佳化"
+msgstr "最佳化器"
#: editor/import/resource_importer_scene.cpp
#: editor/plugins/item_list_editor_plugin.cpp main/main.cpp
@@ -7271,41 +6963,34 @@ msgstr "最佳化"
#: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp
#: scene/gui/rich_text_label.cpp scene/resources/curve.cpp
#: scene/resources/environment.cpp scene/resources/material.cpp
-#, fuzzy
msgid "Enabled"
-msgstr "啟用"
+msgstr "已啟用"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Max Linear Error"
-msgstr "最大線性誤差:"
+msgstr "最大線性誤差"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Max Angular Error"
-msgstr "最大角度誤差:"
+msgstr "最大角度誤差"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Max Angle"
-msgstr "數值"
+msgstr "最大角度"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Remove Unused Tracks"
-msgstr "刪除動畫軌"
+msgstr "移除未使用的動畫軌"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Clips"
msgstr "動畫片段"
#: editor/import/resource_importer_scene.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/particles_2d.cpp scene/3d/area.cpp scene/3d/cpu_particles.cpp
#: scene/3d/particles.cpp scene/resources/environment.cpp
-#, fuzzy
msgid "Amount"
-msgstr "數é‡ï¼š"
+msgstr "數é‡"
#: editor/import/resource_importer_scene.cpp
#: editor/plugins/mesh_library_editor_plugin.cpp
@@ -7321,9 +7006,8 @@ msgid "Generating Lightmaps"
msgstr "正在產生光照圖"
#: editor/import/resource_importer_scene.cpp
-#, fuzzy
msgid "Generating for Mesh:"
-msgstr "正在產生網格: "
+msgstr "ç”Ÿæˆ Mesh 中:"
#: editor/import/resource_importer_scene.cpp
msgid "Running Custom Script..."
@@ -7354,159 +7038,144 @@ 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: 嵿¸¬åˆ°ä½¿ç”¨åœ¨3D上的法線貼圖。啟用紅-ç¶ æè³ªå£“縮來減少記憶體用é‡(è—色通é“å·²"
+"è¢«æ¨æ£„)。"
#: editor/import/resource_importer_texture.cpp
msgid ""
"%s: Texture detected as used in 3D. Enabling filter, repeat, mipmap "
"generation and VRAM texture compression."
-msgstr ""
+msgstr "%s: 嵿¸¬åˆ°ä½¿ç”¨åœ¨3D上的æè³ªã€‚啟用濾é¡ã€é‡è¦†ã€Mipmap產生和VRAMæè³ªå£“縮。"
#: editor/import/resource_importer_texture.cpp
msgid "2D, Detect 3D"
-msgstr ""
+msgstr "2Dï¼Œåµæ¸¬3D"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "2D Pixel"
-msgstr "實體åƒç´ "
+msgstr "2Dåƒç´ "
#: editor/import/resource_importer_texture.cpp scene/resources/texture.cpp
msgid "Lossy Quality"
-msgstr ""
+msgstr "低å“質"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "HDR Mode"
-msgstr "鏿“‡æ¨¡å¼"
+msgstr "HDR模å¼"
#: editor/import/resource_importer_texture.cpp
msgid "BPTC LDR"
-msgstr ""
+msgstr "BPTC LDR"
#: editor/import/resource_importer_texture.cpp
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/mesh_instance_2d.cpp scene/2d/multimesh_instance_2d.cpp
#: scene/2d/particles_2d.cpp scene/2d/sprite.cpp scene/resources/style_box.cpp
msgid "Normal Map"
-msgstr ""
+msgstr "法線貼圖"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Process"
-msgstr "後處ç†"
+msgstr "處ç†"
#: editor/import/resource_importer_texture.cpp
msgid "Fix Alpha Border"
-msgstr ""
+msgstr "修正Alpha邊界"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Premult Alpha"
-msgstr "編輯多邊形"
+msgstr "é ä¹˜ Alpha"
#: editor/import/resource_importer_texture.cpp
msgid "Hdr As Srgb"
-msgstr ""
+msgstr "Hdr作為SRGB"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Invert Color"
-msgstr "頂點"
+msgstr "翻轉é¡è‰²"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Normal Map Invert Y"
-msgstr "隨機縮放:"
+msgstr "法線貼圖å轉 Y"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "Size Limit"
-msgstr "大å°ï¼š "
+msgstr "大å°é™åˆ¶"
#: editor/import/resource_importer_texture.cpp
msgid "Detect 3D"
-msgstr ""
+msgstr "嵿¸¬3D"
#: editor/import/resource_importer_texture.cpp
-#, fuzzy
msgid "SVG"
-msgstr "HSV"
+msgstr "SVG"
#: editor/import/resource_importer_texture.cpp
msgid ""
"Warning, no suitable PC VRAM compression enabled in Project Settings. This "
"texture will not display correctly on PC."
msgstr ""
+"注æ„,專案設定內啟用了éžé©åˆçš„PC VRAM壓縮。此æè³ªå°‡ç„¡æ³•在PC上正確顯示。"
#: editor/import/resource_importer_texture_atlas.cpp
-#, fuzzy
msgid "Atlas File"
-msgstr "輪廓尺寸:"
+msgstr "åˆé›†æª”案"
#: editor/import/resource_importer_texture_atlas.cpp
-#, fuzzy
msgid "Import Mode"
-msgstr "匯出模å¼ï¼š"
+msgstr "匯入模å¼"
#: editor/import/resource_importer_texture_atlas.cpp
-#, fuzzy
msgid "Crop To Region"
-msgstr "鏿“‡åœ–塊å€åŸŸ"
+msgstr "è£å‰ªè‡³å€åŸŸ"
#: editor/import/resource_importer_texture_atlas.cpp
msgid "Trim Alpha Border From Region"
-msgstr ""
+msgstr "從å€åŸŸç°¡åŒ–Alpha邊界"
#: editor/import/resource_importer_wav.cpp scene/2d/physics_body_2d.cpp
-#, fuzzy
msgid "Force"
-msgstr "來æºç¶²æ ¼ï¼š"
+msgstr "強制"
#: editor/import/resource_importer_wav.cpp
msgid "8 Bit"
-msgstr ""
+msgstr "8ä½å…ƒçµ„"
#: editor/import/resource_importer_wav.cpp main/main.cpp
#: modules/mono/editor/csharp_project.cpp modules/mono/mono_gd/gd_mono.cpp
msgid "Mono"
-msgstr ""
+msgstr "Mono"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate"
-msgstr "Mix 節點"
+msgstr "最大頻率"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Max Rate Hz"
-msgstr "Mix 節點"
+msgstr "最大頻率Hz"
#: editor/import/resource_importer_wav.cpp
msgid "Trim"
-msgstr ""
+msgstr "簡化"
#: editor/import/resource_importer_wav.cpp
-#, fuzzy
msgid "Normalize"
-msgstr "æ ¼å¼"
+msgstr "æ­£è¦åŒ–"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop Mode"
-msgstr "移動模å¼"
+msgstr "é‡è¦†æ¨¡å¼"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop Begin"
-msgstr "移動模å¼"
+msgstr "é–‹å§‹é‡è¦†"
#: editor/import/resource_importer_wav.cpp
#: scene/resources/audio_stream_sample.cpp
-#, fuzzy
msgid "Loop End"
-msgstr "移動模å¼"
+msgstr "çµæŸé‡è¦†"
#: editor/import_defaults_editor.cpp
msgid "Select Importer"
@@ -7557,7 +7226,7 @@ msgstr "匯入為:"
#: editor/import_dock.cpp
msgid "Save Scenes, Re-Import, and Restart"
-msgstr "ä¿å­˜å ´æ™¯ã€é‡æ–°åŒ¯å…¥ã€ä¸¦é‡æ–°å•Ÿå‹•"
+msgstr "儲存場景ã€é‡æ–°åŒ¯å…¥ã€ä¸¦é‡æ–°å•Ÿå‹•"
#: editor/import_dock.cpp
msgid "Changing the type of an imported file requires editor restart."
@@ -7572,34 +7241,31 @@ msgstr "警告:有素æä½¿ç”¨è©²è³‡æºï¼Œå°‡ç„¡æ³•正確加載。"
msgid ""
"Select a resource file in the filesystem or in the inspector to adjust "
"import settings."
-msgstr ""
+msgstr "å¾žæª”æ¡ˆç³»çµ±ä¸­é¸æ“‡è³‡æºæª”ï¼Œæˆ–æ˜¯åœ¨é¢æ¿ä¸Šèª¿æ•´åŒ¯å…¥è¨­å®šã€‚"
#: editor/inspector_dock.cpp
msgid "Failed to load resource."
msgstr "加載資æºå¤±æ•—。"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Property Name Style"
-msgstr "專案å稱:"
+msgstr "屬性å稱樣å¼"
#: editor/inspector_dock.cpp scene/gui/color_picker.cpp
msgid "Raw"
msgstr "原始"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Capitalized"
msgstr "首字æ¯å¤§å¯«"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Localized"
-msgstr "地å€"
+msgstr "已本地化"
#: editor/inspector_dock.cpp
msgid "Localization not available for current language."
-msgstr ""
+msgstr "ç›®å‰çš„èªžè¨€ä¸æ”¯æ´æœ¬åœ°åŒ–。"
#: editor/inspector_dock.cpp
msgid "Copy Properties"
@@ -7623,7 +7289,7 @@ msgstr "從ç£ç¢Ÿä¸­è¼‰å…¥ç¾æœ‰çš„資æºä¸¦ç·¨è¼¯ã€‚"
#: editor/inspector_dock.cpp
msgid "Save the currently edited resource."
-msgstr "ä¿å­˜ç›®å‰ç·¨è¼¯çš„資æºã€‚"
+msgstr "儲存目å‰ç·¨è¼¯çš„資æºã€‚"
#: editor/inspector_dock.cpp editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/script_editor_plugin.cpp
@@ -8136,9 +7802,8 @@ msgid "New"
msgstr "新增"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Paste As Reference"
-msgstr "%s 類別åƒç…§"
+msgstr "複製為åƒç…§"
#: editor/plugins/animation_player_editor_plugin.cpp
msgid "Edit Transitions..."
@@ -8327,9 +7992,8 @@ msgid "Set the end animation. This is useful for sub-transitions."
msgstr "設定çµå°¾å‹•畫。é©ç”¨æ–¼å­è½‰å ´ã€‚"
#: editor/plugins/animation_state_machine_editor.cpp
-#, fuzzy
msgid "Transition:"
-msgstr "轉場: "
+msgstr "轉場效果:"
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Play Mode:"
@@ -8466,7 +8130,7 @@ msgstr "篩é¸..."
#: editor/plugins/asset_library_editor_plugin.cpp scene/main/http_request.cpp
msgid "Use Threads"
-msgstr ""
+msgstr "使用執行緒"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Contents:"
@@ -8514,7 +8178,7 @@ msgstr "è¦æ±‚失敗,回傳代碼:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Cannot save response to:"
-msgstr "無法ä¿å­˜å›žè¦†è‡³ï¼š"
+msgstr "無法儲存回覆至:"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Write error."
@@ -8593,9 +8257,8 @@ msgid "Download Error"
msgstr "下載錯誤"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Available URLs"
-msgstr "å¯ç”¨è¨­å®šæª”:"
+msgstr "å¯ç”¨ URL"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Download for this asset is already in progress!"
@@ -8630,28 +8293,24 @@ msgid "Loading..."
msgstr "正在載入..."
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "First"
-msgstr "首é "
+msgstr "第一個"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Previous"
-msgstr "上一é "
+msgstr "上一個"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Next"
-msgstr "下一é "
+msgstr "下一個"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgctxt "Pagination"
msgid "Last"
-msgstr "最後"
+msgstr "最後一個"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "All"
@@ -8699,7 +8358,7 @@ msgstr "測試"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed to get repository configuration."
-msgstr ""
+msgstr "無法å–得倉儲設定。"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Assets ZIP File"
@@ -8714,8 +8373,8 @@ msgid ""
"Can't determine a save path for lightmap images.\n"
"Save your scene and try again."
msgstr ""
-"無法判斷光照圖的ä¿å­˜è·¯å¾‘。\n"
-"è«‹ä¿å­˜å ´æ™¯ä¸¦é‡è©¦ã€‚"
+"無法判斷光照圖的儲存路徑。\n"
+"請儲存場景並é‡è©¦ã€‚"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
@@ -8750,7 +8409,7 @@ msgstr "烘焙光照圖"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "LightMap Bake"
-msgstr ""
+msgstr "光照貼圖烘培"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Select lightmap bake file:"
@@ -9059,9 +8718,8 @@ msgid "Alt+Drag: Move selected node."
msgstr "Alt+拖移:移動所é¸çš„節點。"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Alt+Drag: Scale selected node."
-msgstr "Alt+拖移:移動所é¸çš„節點。"
+msgstr "Alt+拖曳:縮放所é¸çš„節點。"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "V: Set selected node's pivot position."
@@ -9093,7 +8751,7 @@ msgstr "縮放模å¼"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Shift: Scale proportionally."
-msgstr ""
+msgstr "Shift:按比例縮放。"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -9192,9 +8850,8 @@ msgstr "在其ä½ç½®ä¸ŠéŽ–å®šæ‰€é¸ç‰©ä»¶ï¼ˆç„¡æ³•移動)。"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Lock Selected Node(s)"
-msgstr "鎖定所é¸"
+msgstr "鎖定所é¸çš„節點"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -9203,9 +8860,8 @@ msgstr "解鎖所é¸ç‰©ä»¶ï¼ˆå¯ç§»å‹•)。"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Unlock Selected Node(s)"
-msgstr "å–æ¶ˆéŽ–å®šæ‰€é¸"
+msgstr "å–æ¶ˆéŽ–å®šæ‰€é¸çš„節點"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -9214,9 +8870,8 @@ msgstr "確ä¿ç‰©ä»¶çš„å­ç´šé …ç›®ç„¡æ³•è¢«é¸æ“‡ã€‚"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Group Selected Node(s)"
-msgstr "為所é¸çš„項目建立群組"
+msgstr "為所é¸çš„節點建立群組"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -9225,9 +8880,8 @@ msgstr "æ¢å¾©è®“物件的å­ç´šé …ç›®å¯é¸æ“‡ã€‚"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Ungroup Selected Node(s)"
-msgstr "移除所é¸é …目的群組"
+msgstr "å–æ¶ˆæ‰€é¸ç¯€é»žçš„群組"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Skeleton Options"
@@ -9252,23 +8906,20 @@ msgid "View"
msgstr "檢視"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show"
-msgstr "顯示網格"
+msgstr "顯示"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Show When Snapping"
-msgstr "智慧型å¸é™„"
+msgstr "ç•¶å¸é™„時顯示"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Hide"
-msgstr ""
+msgstr "éš±è—"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Grid"
-msgstr "åˆ‡æ›æ¨¡å¼"
+msgstr "切æ›ç¶²æ ¼"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/polygon_2d_editor_plugin.cpp
@@ -9546,7 +9197,7 @@ msgstr "å¹³é¢0"
#: editor/plugins/curve_editor_plugin.cpp
msgid "Flat 1"
-msgstr ""
+msgstr "å¹³é¢ 1"
#: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp
msgid "Ease In"
@@ -9618,16 +9269,15 @@ msgstr "漸層編輯"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
msgid "Swap GradientTexture2D Fill Points"
-msgstr ""
+msgstr "äº¤æ› GradientTexture2D 的填充點"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
msgid "Swap Gradient Fill Points"
-msgstr ""
+msgstr "äº¤æ› Gradient 填充點"
#: editor/plugins/gradient_texture_2d_editor_plugin.cpp
-#, fuzzy
msgid "Toggle Grid Snap"
-msgstr "åˆ‡æ›æ¨¡å¼"
+msgstr "切æ›ç¶²æ ¼å¸é™„"
#: editor/plugins/item_list_editor_plugin.cpp editor/project_export.cpp
#: scene/3d/label_3d.cpp scene/gui/button.cpp scene/gui/dialogs.cpp
@@ -9646,13 +9296,12 @@ msgstr "圖示"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "ID"
-msgstr ""
+msgstr "ID"
#: editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Separator"
-msgstr "分隔:"
+msgstr "分隔線"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "Item %d"
@@ -9881,9 +9530,8 @@ msgstr ""
"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "MeshLibrary"
-msgstr "網格庫"
+msgstr "網格資æºåº«"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Add Item"
@@ -9906,14 +9554,12 @@ msgid "Update from Scene"
msgstr "自場景更新"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply without Transforms"
-msgstr "套用MeshInstance變æ›"
+msgstr "ä¸åŒ…å«è®Šæ›çš„套用"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Apply with Transforms"
-msgstr "套用MeshInstance變æ›"
+msgstr "包å«è®Šæ›çš„套用"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "No mesh source specified (and no MultiMesh set in node)."
@@ -10079,9 +9725,8 @@ msgid "Volume"
msgstr "é«”ç©"
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Emission Source:"
-msgstr "發射æºï¼š "
+msgstr "發射æºï¼š"
#: editor/plugins/particles_editor_plugin.cpp
msgid "A processor material of type 'ParticlesMaterial' is required."
@@ -10433,7 +10078,7 @@ msgstr "åŒæ­¥éª¨éª¼åˆ°å¤šé‚Šå½¢"
#: editor/plugins/ray_cast_2d_editor_plugin.cpp
msgid "Set cast_to"
-msgstr ""
+msgstr "設定 cast_to"
#: editor/plugins/resource_preloader_editor_plugin.cpp
msgid "ERROR: Couldn't load resource!"
@@ -10512,7 +10157,7 @@ msgstr "清除最近的檔案"
#: editor/plugins/script_editor_plugin.cpp
msgid "Close and save changes?"
-msgstr "關閉並ä¿å­˜ä¿®æ”¹å—Žï¼Ÿ"
+msgstr "關閉並儲存修改嗎?"
#: editor/plugins/script_editor_plugin.cpp
msgid "Error writing TextFile:"
@@ -10585,7 +10230,7 @@ msgstr "ä¿å­˜éŒ¯èª¤"
#: editor/plugins/script_editor_plugin.cpp
msgid "Save Theme As..."
-msgstr "ä¿å­˜ä¸»é¡Œç‚º..."
+msgstr "儲存主題為..."
#: editor/plugins/script_editor_plugin.cpp
msgid "%s Class Reference"
@@ -10652,7 +10297,7 @@ msgstr "釿–°æ‰“開關閉的腳本"
#: editor/plugins/script_editor_plugin.cpp
msgid "Save All"
-msgstr "全部ä¿å­˜"
+msgstr "全部儲存"
#: editor/plugins/script_editor_plugin.cpp
msgid "Soft Reload Script"
@@ -10680,7 +10325,7 @@ msgstr "釿–°è¼‰å…¥ä¸»é¡Œ"
#: editor/plugins/script_editor_plugin.cpp
msgid "Save Theme"
-msgstr "ä¿å­˜ä¸»é¡Œ"
+msgstr "儲存主題"
#: editor/plugins/script_editor_plugin.cpp
msgid "Close All"
@@ -10762,58 +10407,51 @@ msgstr "æœå°‹çµæžœ"
#: editor/plugins/script_editor_plugin.cpp
msgid "Open Dominant Script On Scene Change"
-msgstr ""
+msgstr "場景更改時開啟主腳本"
#: editor/plugins/script_editor_plugin.cpp
msgid "External"
-msgstr ""
+msgstr "é¡å¤–çš„"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Use External Editor"
-msgstr "使用外部編輯器進行除錯"
+msgstr "使用外部編輯器"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Exec Path"
-msgstr "匯出路徑"
+msgstr "執行路徑"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Script Temperature Enabled"
-msgstr "鏿“‡æ¨£æ¿æª”案"
+msgstr "啟用腳本樣å¼"
#: editor/plugins/script_editor_plugin.cpp
msgid "Highlight Current Script"
-msgstr ""
+msgstr "強調顯示目å‰çš„腳本"
#: editor/plugins/script_editor_plugin.cpp
msgid "Script Temperature History Size"
-msgstr ""
+msgstr "腳本溫度歷å²å¤§å°"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Current Script Background Color"
-msgstr "無效的背景é¡è‰²ã€‚"
+msgstr "ç›®å‰è…³æœ¬èƒŒæ™¯é¡è‰²"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Group Help Pages"
-msgstr "為所é¸çš„項目建立群組"
+msgstr "幫助é åˆ†çµ„"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Sort Scripts By"
-msgstr "建立腳本"
+msgstr "排åºè…³æœ¬æ ¹æ“š"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "List Script Names As"
-msgstr "腳本å稱:"
+msgstr "將腳本å稱列為"
#: editor/plugins/script_editor_plugin.cpp
msgid "Exec Flags"
-msgstr ""
+msgstr "執行旗標"
#: editor/plugins/script_editor_plugin.cpp
msgid "Clear Recent Scripts"
@@ -10966,9 +10604,8 @@ msgid "Find in Files..."
msgstr "在檔案中æœå°‹..."
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Replace in Files..."
-msgstr "å–代..."
+msgstr "在檔案中å–代..."
#: editor/plugins/script_text_editor.cpp
msgid "Contextual Help"
@@ -11172,15 +10809,13 @@ msgstr "移動"
#. TRANSLATORS: Refers to changing the scale of a node in the 3D editor.
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Scaling:"
-msgstr "縮放: "
+msgstr "縮放:"
#. TRANSLATORS: Refers to changing the position of a node in the 3D editor.
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Translating:"
-msgstr "移動: "
+msgstr "移動:"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rotating %s degrees."
@@ -11228,7 +10863,7 @@ msgstr "頂點:"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "FPS: %d (%s ms)"
-msgstr ""
+msgstr "FPS: %d (%s 毫秒)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Top View."
@@ -11328,49 +10963,48 @@ msgstr "效果é è¦½"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "(Not in GLES2)"
-msgstr ""
+msgstr "(ä¸åœ¨GLES2中)"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Debug draw modes are only available when using the GLES3 renderer, not GLES2."
-msgstr "使用 GLES2 算繪引擎時無法使用。"
+msgstr "除錯繪製模å¼åƒ…å¯åœ¨ GLES3 算繪引擎下使用,無法在 GLES2 下使用。"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Left"
-msgstr "自由視圖 左"
+msgstr "自由觀看 左"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Right"
-msgstr "自由視圖 å³"
+msgstr "自由觀看 å³"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Forward"
-msgstr "自由視圖 å‰"
+msgstr "自由觀看 å‰"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Backwards"
-msgstr "自由視圖 後"
+msgstr "自由觀看 後"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Up"
-msgstr "自由視圖 上"
+msgstr "自由觀看 上"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Down"
-msgstr "自由視圖 下"
+msgstr "自由觀看 下"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Speed Modifier"
-msgstr "加速自由視圖速度"
+msgstr "自由觀看速度調整"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Freelook Slow Modifier"
-msgstr "放慢自由視圖速度"
+msgstr "自由觀看減速調整"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Toggle Camera Preview"
-msgstr "切æ›ç›¸æ©Ÿé è¦½é–‹é—œ"
+msgstr "開啟ï¼é—œé–‰ç›¸æ©Ÿé è¦½"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "View Rotation Locked"
@@ -11379,7 +11013,7 @@ msgstr "視圖旋轉已鎖定"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
"To zoom further, change the camera's clipping planes (View -> Settings...)"
-msgstr "è‹¥è¦å†ç¹¼çºŒæ”¾å¤§ï¼Œè«‹è‡³ 檢視 -> 設定... 修改æ”影機的剪è£å¹³é¢"
+msgstr "è‹¥è¦å†ç¹¼çºŒæ”¾å¤§ï¼Œè«‹è‡³ [檢視] -> [設定...] 修改æ”影機的剪è£å¹³é¢"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
@@ -11497,16 +11131,15 @@ msgstr "開啟ï¼é—œé–‰è‡ªç”±è¦–圖"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Decrease Field of View"
-msgstr ""
+msgstr "減少å¯è¦–範åœ"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Increase Field of View"
-msgstr ""
+msgstr "增加å¯è¦–範åœ"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Reset Field of View to Default"
-msgstr "é‡è¨­ç‚ºé è¨­å€¼"
+msgstr "é‡è¨­ç‚ºé è¨­è¦–野"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Snap Object to Floor"
@@ -11627,16 +11260,15 @@ msgstr "後置"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Manipulator Gizmo Size"
-msgstr ""
+msgstr "æ“縱器控制項大å°"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Manipulator Gizmo Opacity"
-msgstr ""
+msgstr "æ“縱器控制項ä¸é€æ˜Žåº¦"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Show Viewport Rotation Gizmo"
-msgstr "鎖定視角旋轉"
+msgstr "顯示檢視å€çš„æ—‹è½‰æŽ§åˆ¶å™¨"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Unnamed Gizmo"
@@ -11687,9 +11319,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."
@@ -11720,19 +11351,16 @@ msgid "Sprite"
msgstr "拼åˆåœ–"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Simplification:"
-msgstr "簡化: "
+msgstr "簡化:"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Shrink (Pixels):"
-msgstr "收縮(åƒç´ ï¼‰ï¼š "
+msgstr "收縮(åƒç´ ï¼‰ï¼š"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Grow (Pixels):"
-msgstr "擴展(åƒç´ ï¼‰ï¼š "
+msgstr "擴展(åƒç´ ï¼‰ï¼š"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Update Preview"
@@ -11795,6 +11423,10 @@ msgid "New Animation"
msgstr "新增動畫"
#: editor/plugins/sprite_frames_editor_plugin.cpp
+msgid "Filter animations"
+msgstr "篩é¸å‹•ç•«"
+
+#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Speed:"
msgstr "速度:"
@@ -12089,9 +11721,8 @@ msgstr ""
"確定è¦é—œé–‰å—Žï¼Ÿ"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Type"
-msgstr "移除圖塊"
+msgstr "移除型別"
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
@@ -12134,14 +11765,12 @@ msgstr ""
"手動加入更多項目於其中或從å¦ä¸€å€‹ä¸»é¡ŒåŒ¯å…¥ã€‚"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Add Theme Type"
-msgstr "新增項目類型"
+msgstr "新增主題型別"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Remove Theme Type"
-msgstr "移除項目"
+msgstr "移除主題型別"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Add Color Item"
@@ -12256,9 +11885,8 @@ msgid "Select Another Theme Resource:"
msgstr "鏿“‡å…¶ä»–主題資æºï¼š"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Theme Resource"
-msgstr "釿–°å‘½å資æº"
+msgstr "主題資æº"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Another Theme"
@@ -12270,22 +11898,19 @@ msgstr "新增類別"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Filter the list of types or create a new custom type:"
-msgstr ""
+msgstr "篩é¸åž‹åˆ¥åˆ—表,或是建立新的自定型別:"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Available Node-based types:"
-msgstr "å¯ç”¨è¨­å®šæª”:"
+msgstr "å¯ç”¨ä¹‹åŸºæ–¼ç¯€é»žçš„型別:"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Type name is empty!"
-msgstr "檔案å稱為空。"
+msgstr "型別å稱為空ï¼"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Are you sure you want to create an empty type?"
-msgstr "ç¢ºå®šè¦æ‰“開多個專案嗎?"
+msgstr "確定è¦å»ºç«‹ç©ºåž‹åˆ¥å—Žï¼Ÿ"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Confirm Item Rename"
@@ -12315,14 +11940,12 @@ msgid "Add Item Type"
msgstr "新增項目類型"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Set Variation Base Type"
-msgstr "設定變數型別"
+msgstr "設定變化基礎型別"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Set Base Type"
-msgstr "更改基礎型別"
+msgstr "設定基礎型別"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Show Default"
@@ -12342,13 +11965,13 @@ msgstr "複寫所有é è¨­é¡žåˆ¥é …目。"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Select the variation base type from a list of available types."
-msgstr ""
+msgstr "從å¯ç”¨çš„åž‹åˆ¥åˆ—è¡¨ä¸­é¸æ“‡åŸºç¤Žåž‹åˆ¥çš„變化。"
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
"A type associated with a built-in class cannot be marked as a variation of "
"another type."
-msgstr ""
+msgstr "與內建型別相關è¯çš„型別無法被標記為å¦ä¸€å€‹åž‹åˆ¥çš„變化。"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Theme:"
@@ -12583,55 +12206,46 @@ msgid "Clear Transform"
msgstr "清除變æ›"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Tile Map"
-msgstr "繪製圖塊地圖"
+msgstr "圖塊地圖"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Palette Min Width"
-msgstr ""
+msgstr "調色盤最å°å¯¬åº¦"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Palette Item H Separation"
-msgstr "帶å稱的分隔線"
+msgstr "調色盤項目的水平分隔線"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Show Tile Names"
-msgstr "顯示所有地å€"
+msgstr "顯示圖塊å稱"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Show Tile Ids"
-msgstr "顯示尺è¦"
+msgstr "顯示圖塊 ID"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Sort Tiles By Name"
-msgstr "檔案排åº"
+msgstr "以å稱排åºåœ–塊"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Bucket Fill Preview"
-msgstr "油漆桶填滿"
+msgstr "油漆桶填充é è¦½"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "Editor Side"
-msgstr "編輯器"
+msgstr "ç·¨è¼¯å™¨å´æ¬„"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Display Grid"
-msgstr "顯示éŽåº¦ç¹ªåœ–"
+msgstr "顯示柵欄"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Axis Color"
-msgstr "鏿“‡é¡è‰²"
+msgstr "座標軸é¡è‰²"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Add Texture(s) to TileSet."
@@ -12964,7 +12578,6 @@ msgid "This property can't be changed."
msgstr "該屬性無法修改。"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Snap Options"
msgstr "å¸é™„é¸é …"
@@ -12977,9 +12590,8 @@ msgstr "å¸é™„é¸é …"
#: scene/gui/graph_node.cpp scene/gui/rich_text_effect.cpp
#: scene/main/canvas_layer.cpp scene/resources/material.cpp
#: scene/resources/particles_material.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Offset"
-msgstr "å移:"
+msgstr "åç§»"
#: editor/plugins/tile_set_editor_plugin.cpp editor/rename_dialog.cpp
#: scene/gui/range.cpp scene/resources/animation.cpp
@@ -12990,14 +12602,12 @@ msgstr "步長"
#: editor/plugins/tile_set_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Separation"
-msgstr "分隔:"
+msgstr "é–“è·"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Tile"
-msgstr "鏿“‡"
+msgstr "所é¸åœ–塊"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/cpu_particles_2d.cpp
#: scene/2d/light_2d.cpp scene/2d/line_2d.cpp scene/2d/mesh_instance_2d.cpp
@@ -13006,158 +12616,132 @@ msgstr "鏿“‡"
#: scene/gui/nine_patch_rect.cpp scene/gui/texture_rect.cpp
#: scene/resources/material.cpp scene/resources/sky.cpp
#: scene/resources/style_box.cpp scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Texture"
-msgstr "純文字"
+msgstr "ç´‹ç†è²¼åœ–"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tex Offset"
-msgstr "網格åç§»é‡ï¼š"
+msgstr "ç´‹ç†åç§»"
#: editor/plugins/tile_set_editor_plugin.cpp modules/csg/csg_shape.cpp
#: scene/2d/canvas_item.cpp scene/2d/particles_2d.cpp
#: scene/3d/mesh_instance.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Material"
-msgstr "æè³ªè®Šæ›´ï¼š"
+msgstr "æè³ª"
#: editor/plugins/tile_set_editor_plugin.cpp scene/2d/canvas_item.cpp
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Modulate"
-msgstr "å¡«å……"
+msgstr "調變"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tile Mode"
-msgstr "åˆ‡æ›æ¨¡å¼"
+msgstr "圖塊模å¼"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Autotile Bitmask Mode"
-msgstr "優先模å¼"
+msgstr "自動圖塊的ä½å…ƒé®ç½©æ¨¡å¼"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Size"
-msgstr "輪廓尺寸:"
+msgstr "å­åœ–塊大å°"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Subtile Spacing"
-msgstr "行間è·"
+msgstr "自圖塊間è·"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Occluder Offset"
-msgstr "建立é®å…‰å¤šé‚Šå½¢"
+msgstr "é®å…‰åç§»"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Navigation Offset"
-msgstr "導航模å¼"
+msgstr "導航åç§»"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Shape Offset"
-msgstr "å移:"
+msgstr "形狀åç§»"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Shape Transform"
-msgstr "變æ›"
+msgstr "形狀變æ›"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision"
-msgstr "碰撞"
+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 "碰撞模å¼"
+msgstr "所é¸ç¢°æ’žå–®å‘外邊è·"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Navigation"
-msgstr "顯示導航"
+msgstr "所é¸å°Žèˆª"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Occlusion"
-msgstr "鏿“‡"
+msgstr "所é¸é®æ“‹"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Tileset Script"
-msgstr "篩é¸è…³æœ¬"
+msgstr "圖塊集腳本"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "TileSet"
msgstr "圖塊集"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "No VCS plugins are available."
-msgstr "ç„¡å¯ç”¨çš„版本控制 (VCS) 擴充功能。"
+msgstr "ç„¡å¯ç”¨çš„版本控制 (VCS) 外掛。"
#: editor/plugins/version_control_editor_plugin.cpp
msgid ""
"Remote settings are empty. VCS features that use the network may not work."
-msgstr ""
+msgstr "é ç«¯è¨­å®šæ˜¯ç©ºçš„。使用網路的VCS功能æç„¡æ³•é‹ä½œã€‚"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "No commit message was provided."
-msgstr "未æä¾›å稱。"
+msgstr "未æä¾›èªå¯ (Commit) 訊æ¯ã€‚"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Commit"
msgstr "æäº¤"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Staged Changes"
-msgstr "著色器變更:"
+msgstr "暫存變更"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Unstaged Changes"
-msgstr "著色器變更:"
+msgstr "未暫存變更"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Commit:"
-msgstr "æäº¤"
+msgstr "æäº¤ï¼š"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Date:"
-msgstr ""
+msgstr "日期:"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Subtitle:"
-msgstr "å­æ¨¹"
+msgstr "副標題:"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Do you want to remove the %s branch?"
-msgstr ""
+msgstr "你確定è¦ç§»é™¤ %s 分支?"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Do you want to remove the %s remote?"
-msgstr "ç¢ºå®šè¦æ‰“開多個專案嗎?"
+msgstr "確定è¦ç§»é™¤é ç«¯ã€Œ%sã€ï¼Ÿ"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Apply"
-msgstr "套用é‡è¨­"
+msgstr "套用"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Version Control System"
@@ -13168,123 +12752,108 @@ msgid "Initialize"
msgstr "åˆå§‹åŒ–"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Remote Login"
-msgstr "移除控制點"
+msgstr "é ç«¯ç™»å…¥"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Select SSH public key path"
-msgstr ""
+msgstr "鏿“‡SSH公鑰的路徑"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Select SSH private key path"
-msgstr ""
+msgstr "鏿“‡SSHç§é‘°çš„路徑"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "SSH Passphrase"
-msgstr ""
+msgstr "SSH 通關片段"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Detect new changes"
msgstr "嵿¸¬æ–°æ”¹å‹•"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Discard all changes"
-msgstr "關閉並ä¿å­˜ä¿®æ”¹å—Žï¼Ÿ"
+msgstr "æ¨æ£„所有變更"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Stage all changes"
-msgstr "正在儲存變更..."
+msgstr "é å­˜æ‰€æœ‰è®Šæ›´"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Unstage all changes"
-msgstr "æè³ªè®Šæ›´ï¼š"
+msgstr "撤銷暫存所有變更"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Commit Message"
-msgstr "æäº¤æ”¹å‹•"
+msgstr "èªå¯ (Commit) 訊æ¯"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Commit Changes"
msgstr "æäº¤æ”¹å‹•"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Commit List"
-msgstr "æäº¤"
+msgstr "èªå¯åˆ—表"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Commit list size"
-msgstr ""
+msgstr "èªå¯åˆ—表大å°"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Branches"
-msgstr "ç¬¦åˆæ¢ä»¶ï¼š"
+msgstr "分支"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Create New Branch"
-msgstr "建立新專案"
+msgstr "建立分支"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Remove Branch"
-msgstr "刪除動畫軌"
+msgstr "移除分支"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Branch Name"
-msgstr ""
+msgstr "分支å稱"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Remotes"
msgstr "é ç«¯"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Create New Remote"
-msgstr "建立新專案"
+msgstr "建立é ç«¯"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Remove Remote"
-msgstr "移除項目"
+msgstr "移除é ç«¯"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Remote Name"
-msgstr "é ç«¯ "
+msgstr "é ç«¯å稱"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Remote URL"
-msgstr "é ç«¯ "
+msgstr "é ç«¯ç¶²å€"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Fetch"
-msgstr ""
+msgstr "æˆªå– (Fetch)"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Pull"
-msgstr ""
+msgstr "æå– (Pull)"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Push"
-msgstr ""
+msgstr "æŽ¨é€ (Push)"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Force Push"
-msgstr "來æºç¶²æ ¼ï¼š"
+msgstr "強制推é€"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Modified"
-msgstr "已修改"
+msgstr "修改"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Renamed"
@@ -13292,30 +12861,27 @@ msgstr "釿–°å‘½å"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Deleted"
-msgstr "已刪除"
+msgstr "刪除"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Typechange"
-msgstr "æ ¼å¼æ›´æ”¹"
+msgstr "更改型別"
#: editor/plugins/version_control_editor_plugin.cpp
msgid "Unmerged"
-msgstr ""
+msgstr "未åˆä½µ"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "View:"
-msgstr "檢視"
+msgstr "檢視:"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Split"
-msgstr "拆分路徑"
+msgstr "分割"
#: editor/plugins/version_control_editor_plugin.cpp
-#, fuzzy
msgid "Unified"
-msgstr "已修改"
+msgstr "åˆä½µ"
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "(GLES3 only)"
@@ -14172,11 +13738,11 @@ msgstr "å¯åŸ·è¡Œ"
#: editor/project_export.cpp
msgid "Export the project for all the presets defined."
-msgstr ""
+msgstr "使用æ¯å€‹å·²å®šç¾©çš„é è¨­è¨­å®šä¾†åŒ¯å‡ºè©²å°ˆæ¡ˆã€‚"
#: editor/project_export.cpp
msgid "All presets must have an export path defined for Export All to work."
-msgstr ""
+msgstr "所有é è¨­è¨­å®šéƒ½å¿…須定義好匯出路徑,æ‰å¯ä½¿ç”¨ [匯出全部] 功能。"
#: editor/project_export.cpp
msgid "Delete preset '%s'?"
@@ -14287,53 +13853,48 @@ msgid ""
"Note: Encryption key needs to be stored in the binary,\n"
"you need to build the export templates from source."
msgstr ""
+"注æ„:加密金鑰必須以二進ä½å½¢å¼ä¿å­˜ï¼Œ\n"
+"必須從原始碼來編譯匯出樣æ¿ã€‚"
#: editor/project_export.cpp
-#, fuzzy
msgid "More Info..."
-msgstr "移動至..."
+msgstr "更多資訊..."
#: editor/project_export.cpp
-#, fuzzy
msgid "Export PCK/Zip..."
-msgstr "匯出 PCK/ZIP"
+msgstr "匯出 PCK/ZIP..."
#: editor/project_export.cpp
-#, fuzzy
msgid "Export Project..."
-msgstr "匯出專案"
+msgstr "匯出專案..."
#: editor/project_export.cpp
msgid "Export All"
msgstr "全部匯出"
#: editor/project_export.cpp
-#, fuzzy
msgid "Choose an export mode:"
-msgstr "è«‹é¸æ“‡ä¸€å€‹ç©ºè³‡æ–™å¤¾ã€‚"
+msgstr "鏿“‡åŒ¯å‡ºæ¨¡å¼ï¼š"
#: editor/project_export.cpp
-#, fuzzy
msgid "Export All..."
-msgstr "全部匯出"
+msgstr "全部匯出..."
#: editor/project_export.cpp editor/project_manager.cpp
msgid "ZIP File"
msgstr "ZIP 檔案"
#: editor/project_export.cpp
-#, fuzzy
msgid "Godot Project Pack"
-msgstr "Godot éŠæˆ²åŒ…"
+msgstr "Godot 專案包"
#: editor/project_export.cpp
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"
@@ -14620,8 +14181,8 @@ msgid ""
"Language changed.\n"
"The interface will update after restarting the editor or project manager."
msgstr ""
-"語言已更改。\n"
-"界é¢å°‡æœƒåœ¨é‡æ–°å•Ÿå‹•編輯器或專案管ç†å“¡å¾Œæ›´æ–°ã€‚"
+"語言已變更。\n"
+"釿–°å•Ÿå‹•編輯器或專案管ç†å“¡å¾Œå°‡æœƒå¥—ç”¨ç•Œé¢æ›´æ–°ã€‚"
#: editor/project_manager.cpp
msgid ""
@@ -14633,7 +14194,6 @@ msgstr ""
#. TRANSLATORS: This refers to the application where users manage their Godot projects.
#: editor/project_manager.cpp
-#, fuzzy
msgctxt "Application"
msgid "Project Manager"
msgstr "專案管ç†å“¡"
@@ -14898,7 +14458,7 @@ msgstr "ä¿å­˜è¨­å®šæ™‚發生錯誤。"
#: editor/project_settings_editor.cpp
msgid "Settings saved OK."
-msgstr "設定ä¿å­˜æˆåŠŸã€‚"
+msgstr "設定儲存æˆåŠŸã€‚"
#: editor/project_settings_editor.cpp
msgid "Moved Input Action Event"
@@ -14982,7 +14542,7 @@ msgstr "索引:"
#: editor/project_settings_editor.cpp
msgid "Localization"
-msgstr "本地化"
+msgstr "在地化"
#: editor/project_settings_editor.cpp
msgid "Translations"
@@ -15357,7 +14917,7 @@ msgid ""
"FileSystem dock context menu\n"
"or create an inherited scene using Scene > New Inherited Scene... instead."
msgstr ""
-"無法ä¿å­˜ä½œç‚ºå¯¦é«”化場景的根節點分支。\n"
+"無法儲存作為實體化場景的根節點分支。\n"
"請使用檔案系統åœä½‡åˆ—çš„å³éµé¸å–®ä¾†è¤‡è£½å®ƒï¼Œä»¥æ‹·è²ç›®å‰å ´æ™¯åŠ ä»¥ç·¨è¼¯ã€‚\n"
"或是使用場景 > 新增繼承場景...以建立一個繼承場景。"
@@ -15367,7 +14927,7 @@ msgid ""
"To create a variation of a scene, you can make an inherited scene based on "
"the instanced scene using Scene > New Inherited Scene... instead."
msgstr ""
-"無法ä¿å­˜å·²å¯¦é«”化場景的分支。\n"
+"無法儲存已實體化場景的分支。\n"
"è‹¥è¦å»ºç«‹å ´æ™¯è®Šé«”,您å¯ä½¿ç”¨å ´æ™¯ > 新增繼承場景...根據實體化的場景建立一個繼承"
"場景。"
@@ -15377,6 +14937,9 @@ msgid ""
"To save this branch into its own scene, open the original scene, right click "
"on this branch, and select \"Save Branch as Scene\"."
msgstr ""
+"無法ä¿å­˜åˆ†æ”¯ï¼Œè©²åˆ†æ”¯æ˜¯å·²å¯¦é«”化場景的å­é …目。\n"
+"è‹¥è¦å°‡è©²åˆ†æ”¯ä¿å­˜é€²ç¨ç«‹çš„場景中,請開啟原始場景,並在該分支上點擊å³éµï¼Œç„¶å¾Œé¸"
+"擇 [將分支ä¿å­˜ç‚ºå ´æ™¯]。"
#: editor/scene_tree_dock.cpp
msgid ""
@@ -15384,6 +14947,9 @@ msgid ""
"To save this branch into its own scene, open the original scene, right click "
"on this branch, and select \"Save Branch as Scene\"."
msgstr ""
+"無法ä¿å­˜åˆ†æ”¯ï¼Œè©²åˆ†æ”¯æ˜¯ç¹¼æ‰¿å ´æ™¯çš„一部分。\n"
+"è‹¥è¦å°‡è©²åˆ†æ”¯ä¿å­˜ç‚ºç¨ç«‹çš„場景,請開啟原始場景,並在該分支上點擊å³éµï¼Œç„¶å¾Œé¸æ“‡ "
+"[將分支ä¿å­˜ç‚ºå ´æ™¯]。"
#: editor/scene_tree_dock.cpp
msgid "Save New Scene As..."
@@ -15409,17 +14975,15 @@ msgstr "轉為本地"
#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp
msgid "Another node already uses this unique name in the scene."
-msgstr ""
+msgstr "å¦ä¸€å€‹ç¯€é»žå·²åœ¨è©²å ´æ™¯ä¸­ä½¿ç”¨äº†é€™å€‹ä¸å¯é‡è¤‡çš„å稱。"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Enable Scene Unique Name"
-msgstr "節點å稱:"
+msgstr "啟用場景ç¨ç«‹å稱"
#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp
-#, fuzzy
msgid "Disable Scene Unique Name"
-msgstr "節點å稱:"
+msgstr "åœç”¨å ´æ™¯ç¨ç«‹å稱"
#: editor/scene_tree_dock.cpp
msgid "New Scene Root"
@@ -15477,7 +15041,7 @@ msgstr "更改節點的型別"
msgid ""
"Couldn't save new scene. Likely dependencies (instances) couldn't be "
"satisfied."
-msgstr "無法ä¿å­˜æ–°å ´æ™¯ã€‚å¯èƒ½æ˜¯ç”±æ–¼ç„¡æ³•滿足其ä¾è³´æ€§ï¼ˆå¯¦é«”)。"
+msgstr "無法儲存新場景。å¯èƒ½æ˜¯ç”±æ–¼ç„¡æ³•滿足其ä¾è³´æ€§ï¼ˆå¯¦é«”)。"
#: editor/scene_tree_dock.cpp
msgid "Error saving scene."
@@ -15485,7 +15049,7 @@ msgstr "ä¿å­˜å ´æ™¯æ™‚發生錯誤。"
#: editor/scene_tree_dock.cpp
msgid "Error duplicating scene to save it."
-msgstr "複製場景以進行ä¿å­˜æ™‚發生錯誤。"
+msgstr "複製場景以進行儲存時發生錯誤。"
#: editor/scene_tree_dock.cpp
msgid "Sub-Resources"
@@ -15493,7 +15057,7 @@ msgstr "å­è³‡æº"
#: editor/scene_tree_dock.cpp
msgid "Access as Scene Unique Name"
-msgstr ""
+msgstr "以ä¸é‡è¤‡çš„場景å稱來存å–"
#: editor/scene_tree_dock.cpp
msgid "Clear Inheritance"
@@ -15542,7 +15106,7 @@ msgstr "åˆä½µè‡ªå ´æ™¯"
#: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp
msgid "Save Branch as Scene"
-msgstr "ä¿å­˜åˆ†æ”¯ç‚ºå ´æ™¯"
+msgstr "儲存分支為場景"
#: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp
msgid "Copy Node Path"
@@ -15588,18 +15152,16 @@ msgid "Clear Inheritance? (No Undo!)"
msgstr "ç¢ºå®šè¦æ¸…除繼承嗎?(無法復原ï¼ï¼‰"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Show Scene Tree Root Selection"
-msgstr "置中所é¸"
+msgstr "é¡¯ç¤ºå ´æ™¯æ¨¹çš„æ ¹é¸æ“‡"
#: editor/scene_tree_dock.cpp
msgid "Derive Script Globals By Name"
-msgstr ""
+msgstr "ä¾ç…§å稱來推斷腳本的全域變數"
#: editor/scene_tree_dock.cpp
-#, fuzzy
msgid "Use Favorites Root Selection"
-msgstr "完整顯示所é¸"
+msgstr "ä½¿ç”¨æˆ‘çš„æœ€æ„›æ ¹é¸æ“‡"
#: editor/scene_tree_editor.cpp
msgid "Toggle Visible"
@@ -15627,6 +15189,8 @@ msgid ""
"with the '%s' prefix in a node path.\n"
"Click to disable this."
msgstr ""
+"該節點å¯åœ¨æ­¤å ´æ™¯ä¸­çš„任何地方通éŽåœ¨ç¯€é»žè·¯å¾‘剿–¹åŠ ä¸Šã€Œ%sã€å‰ç½®è©žä¾†å­˜å–。\n"
+"點擊以ç¦ç”¨ã€‚"
#: editor/scene_tree_editor.cpp
msgid ""
@@ -15833,9 +15397,8 @@ msgid "Attach Node Script"
msgstr "附加節點腳本"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Remote %s:"
-msgstr "é ç«¯ "
+msgstr "é ç«¯ %s:"
#: editor/script_editor_debugger.cpp
msgid "Bytes:"
@@ -15910,21 +15473,20 @@ msgid "Stack Frames"
msgstr "堆疊框"
#: editor/script_editor_debugger.cpp
-#, fuzzy
msgid "Filter stack variables"
-msgstr "篩é¸åœ–塊"
+msgstr "篩é¸å †ç–Šè®Šæ•¸"
#: editor/script_editor_debugger.cpp
msgid "Auto Switch To Remote Scene Tree"
-msgstr ""
+msgstr "自動切æ›è‡³é ç«¯å ´æ™¯æ¨¹"
#: editor/script_editor_debugger.cpp
msgid "Remote Scene Tree Refresh Interval"
-msgstr ""
+msgstr "é ç«¯å ´æ™¯æ¨¹é‡æ–°æ•´ç†é–“éš”"
#: editor/script_editor_debugger.cpp
msgid "Remote Inspect Refresh Interval"
-msgstr ""
+msgstr "é ç«¯æª¢æŸ¥é‡æ–°æ•´ç†é–“éš”"
#: editor/script_editor_debugger.cpp
msgid "Network Profiler"
@@ -16022,7 +15584,7 @@ msgstr "更改光照åŠå¾‘"
#: editor/spatial_editor_gizmos.cpp
msgid "Stream Player 3D"
-msgstr ""
+msgstr "StreamPlayer3D"
#: editor/spatial_editor_gizmos.cpp
msgid "Change AudioStreamPlayer3D Emission Angle"
@@ -16032,7 +15594,7 @@ msgstr "更改 AudioStreamPlayer3D 發射角"
#: platform/osx/export/export.cpp
#: scene/resources/default_theme/default_theme.cpp
msgid "Camera"
-msgstr ""
+msgstr "相機"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Camera FOV"
@@ -16044,7 +15606,7 @@ msgstr "更改相機尺寸"
#: editor/spatial_editor_gizmos.cpp
msgid "Visibility Notifier"
-msgstr ""
+msgstr "VisibilityNotifier"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Notifier AABB"
@@ -16055,23 +15617,20 @@ msgid "Change Particles AABB"
msgstr "æ›´æ”¹ç²’å­ AABB"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Reflection Probe"
-msgstr "鏿“‡å±¬æ€§"
+msgstr "å射探查"
#: editor/spatial_editor_gizmos.cpp
msgid "Change Probe Extents"
msgstr "更改探查範åœ"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "GI Probe"
-msgstr "烘焙 GI 探查"
+msgstr "GI 探查"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Baked Indirect Light"
-msgstr "éžå‘性光照"
+msgstr "烘焙間接光照"
#: editor/spatial_editor_gizmos.cpp modules/csg/csg_gizmos.cpp
msgid "Change Sphere Shape Radius"
@@ -16102,14 +15661,12 @@ msgid "Change Ray Shape Length"
msgstr "更改射線形長度"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Edge"
-msgstr "導航模å¼"
+msgstr "導航邊界"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Navigation Edge Disabled"
-msgstr "導航模å¼"
+msgstr "å·²ç¦ç”¨å°Žèˆªé‚Šç•Œ"
#: editor/spatial_editor_gizmos.cpp
#, fuzzy
@@ -16287,9 +15844,8 @@ msgid "Driver"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Driver Name"
-msgstr "腳本å稱:"
+msgstr "é©…å‹•å稱"
#: main/main.cpp
msgid "Fallback To GLES2"
@@ -16374,9 +15930,8 @@ msgid "Physics FPS"
msgstr "物ç†å½±æ ¼ %"
#: main/main.cpp
-#, fuzzy
msgid "Force FPS"
-msgstr "來æºç¶²æ ¼ï¼š"
+msgstr "強制 FPS"
#: main/main.cpp
msgid "Enable Pause Aware Picking"
@@ -16490,9 +16045,8 @@ msgid "Fullsize"
msgstr ""
#: main/main.cpp scene/resources/dynamic_font.cpp
-#, fuzzy
msgid "Use Filter"
-msgstr "篩é¸ï¼š"
+msgstr "使用篩é¸å™¨"
#: main/main.cpp scene/resources/style_box.cpp
#, fuzzy
@@ -16539,9 +16093,8 @@ msgid "Custom Image Hotspot"
msgstr ""
#: main/main.cpp
-#, fuzzy
msgid "Tooltip Position Offset"
-msgstr "旋轉åç§»é‡ï¼š"
+msgstr "工具æç¤ºä½ç½®åç§»"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
#, fuzzy
@@ -16554,9 +16107,8 @@ msgid "Wait For Debugger"
msgstr "除錯工具"
#: main/main.cpp modules/mono/mono_gd/gd_mono.cpp
-#, fuzzy
msgid "Wait Timeout"
-msgstr "逾時。"
+msgstr "等待逾時"
#: main/main.cpp
msgid "Runtime"
@@ -16670,14 +16222,12 @@ msgstr "轉æ›å¤§å°å¯«"
#: scene/resources/cylinder_shape.cpp scene/resources/environment.cpp
#: scene/resources/navigation_mesh.cpp scene/resources/primitive_meshes.cpp
#: scene/resources/sphere_shape.cpp
-#, fuzzy
msgid "Radius"
-msgstr "åŠå¾‘:"
+msgstr "åŠå¾‘"
#: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Radial Segments"
-msgstr "主場景引數:"
+msgstr "徑呿®µæ•¸"
#: modules/csg/csg_shape.cpp scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -16746,9 +16296,8 @@ msgid "Path Simplify Angle"
msgstr ""
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Rotation"
-msgstr "隨機旋轉:"
+msgstr "路徑旋轉"
#: modules/csg/csg_shape.cpp
#, fuzzy
@@ -16761,14 +16310,12 @@ msgid "Path Continuous U"
msgstr "連續"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path U Distance"
-msgstr "鏿“‡è·é›¢ï¼š"
+msgstr "路徑 U è·é›¢"
#: modules/csg/csg_shape.cpp
-#, fuzzy
msgid "Path Joined"
-msgstr "隨機旋轉:"
+msgstr "路徑接åˆ"
#: modules/enet/networked_multiplayer_enet.cpp
#, fuzzy
@@ -16816,9 +16363,8 @@ msgid "Use FBX"
msgstr ""
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Config File"
-msgstr "儲存檔案:"
+msgstr "組態檔案"
#: modules/gdnative/gdnative.cpp
#, fuzzy
@@ -16832,9 +16378,8 @@ msgid "Singleton"
msgstr "骨架"
#: modules/gdnative/gdnative.cpp
-#, fuzzy
msgid "Symbol Prefix"
-msgstr "å‰ç½®ï¼š"
+msgstr "符號å‰ç¶´"
#: modules/gdnative/gdnative.cpp
#, fuzzy
@@ -16892,19 +16437,16 @@ msgid "Disabled GDNative Singleton"
msgstr "ç¦ç”¨ GDNative 單例"
#: modules/gdnative/gdnative_library_singleton_editor.cpp
-#, fuzzy
msgid "Libraries:"
-msgstr "函å¼åº«ï¼š "
+msgstr "函å¼åº«ï¼š"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Class Name"
-msgstr "類別å稱:"
+msgstr "類別å稱"
#: modules/gdnative/nativescript/nativescript.cpp
-#, fuzzy
msgid "Script Class"
-msgstr "腳本å稱:"
+msgstr "腳本類別"
#: modules/gdnative/nativescript/nativescript.cpp
#, fuzzy
@@ -16983,9 +16525,8 @@ msgid "Object can't provide a length."
msgstr "物件無法æä¾›é•·åº¦ã€‚"
#: modules/gdscript/language_server/gdscript_language_server.cpp
-#, fuzzy
msgid "Language Server"
-msgstr "語言:"
+msgstr "語言伺æœå™¨"
#: modules/gdscript/language_server/gdscript_language_server.cpp
#, fuzzy
@@ -17014,9 +16555,8 @@ msgid "Buffer View"
msgstr "後視圖"
#: modules/gltf/gltf_accessor.cpp modules/gltf/gltf_buffer_view.cpp
-#, fuzzy
msgid "Byte Offset"
-msgstr "網格åç§»é‡ï¼š"
+msgstr "字節åç§»"
#: modules/gltf/gltf_accessor.cpp
#, fuzzy
@@ -17029,9 +16569,8 @@ msgid "Normalized"
msgstr "æ ¼å¼"
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Count"
-msgstr "數é‡ï¼š"
+msgstr "數é‡"
#: modules/gltf/gltf_accessor.cpp scene/resources/visual_shader_nodes.cpp
#, fuzzy
@@ -17057,9 +16596,8 @@ msgid "Sparse Indices Byte Offset"
msgstr ""
#: modules/gltf/gltf_accessor.cpp
-#, fuzzy
msgid "Sparse Indices Component Type"
-msgstr "正在解æžå¤šé‚Šå½¢..."
+msgstr "稀ç–頂點元件型別"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Values Buffer View"
@@ -17089,9 +16627,8 @@ msgid "Indices"
msgstr "所有è£ç½®"
#: modules/gltf/gltf_camera.cpp
-#, fuzzy
msgid "FOV Size"
-msgstr "大å°ï¼š"
+msgstr "FOV 大å°"
#: modules/gltf/gltf_camera.cpp
msgid "Zfar"
@@ -17138,9 +16675,8 @@ msgid "Blend Weights"
msgstr "烘焙光照圖"
#: modules/gltf/gltf_mesh.cpp
-#, fuzzy
msgid "Instance Materials"
-msgstr "æè³ªè®Šæ›´ï¼š"
+msgstr "實體æè³ª"
#: modules/gltf/gltf_node.cpp scene/3d/skeleton.cpp
#, fuzzy
@@ -17228,9 +16764,8 @@ msgid "Gloss Factor"
msgstr ""
#: modules/gltf/gltf_spec_gloss.cpp
-#, fuzzy
msgid "Specular Factor"
-msgstr "ç´”é‡é‹ç®—å­ã€‚"
+msgstr "é¡é¢å射係數"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Spec Gloss Img"
@@ -17269,9 +16804,8 @@ msgid "Accessors"
msgstr ""
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Scene Name"
-msgstr "場景路徑:"
+msgstr "場景å稱"
#: modules/gltf/gltf_state.cpp
#, fuzzy
@@ -17298,9 +16832,8 @@ msgid "Lights"
msgstr "燈光"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Unique Animation Names"
-msgstr "新增動畫å稱:"
+msgstr "ç¨ç«‹å‹•ç•«å稱"
#: modules/gltf/gltf_state.cpp
#, fuzzy
@@ -17313,9 +16846,8 @@ msgid "Skeleton To Node"
msgstr "鏿“‡ä¸€å€‹ç¯€é»ž"
#: modules/gltf/gltf_state.cpp
-#, fuzzy
msgid "Animations"
-msgstr "動畫:"
+msgstr "å‹•ç•«"
#: modules/gltf/gltf_texture.cpp
#, fuzzy
@@ -17560,9 +17092,8 @@ msgstr ""
#: modules/minimp3/resource_importer_mp3.cpp
#: modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
#: modules/stb_vorbis/resource_importer_ogg_vorbis.cpp
-#, fuzzy
msgid "Loop Offset"
-msgstr "å移:"
+msgstr "循環åç§»"
#: modules/mobile_vr/mobile_vr_interface.cpp
msgid "Eye Height"
@@ -17681,9 +17212,8 @@ msgid "Seamless"
msgstr ""
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "As Normal Map"
-msgstr "隨機縮放:"
+msgstr "作為法線貼圖"
#: modules/opensimplex/noise_texture.cpp
msgid "Bump Strength"
@@ -17694,9 +17224,8 @@ msgid "Noise"
msgstr ""
#: modules/opensimplex/noise_texture.cpp
-#, fuzzy
msgid "Noise Offset"
-msgstr "網格åç§»é‡ï¼š"
+msgstr "噪è²åç§»"
#: modules/opensimplex/open_simplex_noise.cpp
msgid "Octaves"
@@ -17725,9 +17254,8 @@ msgid "Names"
msgstr "å稱"
#: modules/regex/regex.cpp
-#, fuzzy
msgid "Strings"
-msgstr "設定:"
+msgstr "字串"
#: modules/upnp/upnp.cpp
msgid "Discover Multicast If"
@@ -17788,18 +17316,16 @@ msgid ""
msgstr "回傳值需被指定為é‹ç®—記憶體節點的第一個元素ï¼è«‹ä¿®æ­£è©²ç¯€é»žã€‚"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Node returned an invalid sequence output:"
-msgstr "節點回傳了一個無效的連續輸出: "
+msgstr "節點回傳了一個無效的åºåˆ—輸出:"
#: modules/visual_script/visual_script.cpp
msgid "Found sequence bit but not the node in the stack, report bug!"
msgstr "發ç¾äº†é€£çºŒä½å…ƒ (Sequance Bit) 但並éžåœ¨å †ç–Šä¸­çš„節點,請回報該錯誤ï¼"
#: modules/visual_script/visual_script.cpp
-#, fuzzy
msgid "Stack overflow with stack depth:"
-msgstr "堆疊深度的堆疊溢出: "
+msgstr "堆疊深度的堆疊溢出:"
#: modules/visual_script/visual_script.cpp
#, fuzzy
@@ -18166,18 +17692,16 @@ msgid "for (elem) in (input):"
msgstr ""
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Input type not iterable:"
-msgstr "輸入型別éžå¯è¿­ä»£åž‹åˆ¥ï¼š "
+msgstr "輸入型別éžå¯è¿­ä»£åž‹åˆ¥ï¼š"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Iterator became invalid"
msgstr "迭代器已ä¸å¯ç”¨"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Iterator became invalid:"
-msgstr "迭代器已ä¸å¯ç”¨ï¼š "
+msgstr "迭代器無效:"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Sequence"
@@ -18194,18 +17718,16 @@ msgid "Steps"
msgstr "步長"
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Switch"
-msgstr "仰角:"
+msgstr "切æ›"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "'input' is:"
msgstr ""
#: modules/visual_script/visual_script_flow_control.cpp
-#, fuzzy
msgid "Type Cast"
-msgstr "類別:"
+msgstr "型別轉æ›"
#: modules/visual_script/visual_script_flow_control.cpp
msgid "Is %s?"
@@ -18251,9 +17773,8 @@ msgid "Use Default Args"
msgstr "é‡è¨­ç‚ºé è¨­"
#: modules/visual_script/visual_script_func_nodes.cpp
-#, fuzzy
msgid "Validate"
-msgstr "å¯ä½¿ç”¨çš„字元:"
+msgstr "é©—è­‰"
#: modules/visual_script/visual_script_func_nodes.cpp
#, fuzzy
@@ -18345,19 +17866,16 @@ msgstr "調整陣列大å°"
#: modules/visual_script/visual_script_nodes.cpp scene/resources/material.cpp
#: scene/resources/visual_shader_nodes.cpp
-#, fuzzy
msgid "Operator"
-msgstr "疊加é‹ç®—å­ã€‚"
+msgstr "é‹ç®—å­"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Invalid argument of type:"
-msgstr ": 無效的引數型別: "
+msgstr "無效的引數型別:"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "Invalid arguments:"
-msgstr ": 無效的引數: "
+msgstr "無效的引數:"
#: modules/visual_script/visual_script_nodes.cpp
msgid "a if cond, else b"
@@ -18369,14 +17887,12 @@ msgid "Var Name"
msgstr "å稱"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "VariableGet not found in script:"
-msgstr "腳本中未找到 VariableGet(å–得變數): "
+msgstr "腳本中未找到 VariableGet(å–得變數):"
#: modules/visual_script/visual_script_nodes.cpp
-#, fuzzy
msgid "VariableSet not found in script:"
-msgstr "腳本中未找到 VariableSet(設定變數): "
+msgstr "腳本中未找到 VariableSet(設定變數):"
#: modules/visual_script/visual_script_nodes.cpp
#, fuzzy
@@ -18491,7 +18007,7 @@ msgstr "產生"
#: modules/visual_script/visual_script_yield_nodes.cpp
msgid "Wait"
-msgstr ""
+msgstr "等待"
#: modules/visual_script/visual_script_yield_nodes.cpp
#, fuzzy
@@ -18596,9 +18112,8 @@ msgid "CA Chain"
msgstr "清除 IK éˆ"
#: modules/websocket/websocket_server.cpp
-#, fuzzy
msgid "Handshake Timeout"
-msgstr "逾時。"
+msgstr "Handshake 逾時"
#: modules/webxr/webxr_interface.cpp
#, fuzzy
@@ -18606,14 +18121,12 @@ msgid "Session Mode"
msgstr "å€åŸŸæ¨¡å¼"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Required Features"
-msgstr "主è¦åŠŸèƒ½ï¼š"
+msgstr "å¿…è¦ç‰¹æ€§"
#: modules/webxr/webxr_interface.cpp
-#, fuzzy
msgid "Optional Features"
-msgstr "主è¦åŠŸèƒ½ï¼š"
+msgstr "å¯é¸ç‰¹æ€§"
#: modules/webxr/webxr_interface.cpp
msgid "Requested Reference Space Types"
@@ -18704,6 +18217,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 +18230,15 @@ msgstr ""
msgid "Export Format"
msgstr "匯出路徑"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "æœ€å° SDK"
+
+#: 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,25 +18281,14 @@ 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"
msgstr "正在打包"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Unique Name"
-msgstr "節點å稱:"
+msgstr "ç¨ç«‹å稱"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18780,9 +18296,8 @@ msgid "Signed"
msgstr "訊號"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Classify As Game"
-msgstr "類別å稱:"
+msgstr "åˆ†é¡žç‚ºéŠæˆ²"
#: platform/android/export/export_plugin.cpp
msgid "Retain Data On Uninstall"
@@ -18794,9 +18309,8 @@ msgid "Exclude From Recents"
msgstr "刪除節點"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Graphics"
-msgstr "網格åç§»é‡ï¼š"
+msgstr "圖形"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -18866,9 +18380,8 @@ msgid "Command Line"
msgstr "社群"
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
-#, fuzzy
msgid "Extra Args"
-msgstr "é¡å¤–呼å«å¼•數:"
+msgstr "é¡å¤–引數"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -19003,15 +18516,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 +18534,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
@@ -19040,14 +18578,12 @@ msgid "Code Signing"
msgstr "訊號"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"'apksigner' could not be found. Please check that the command is available "
"in the Android SDK build-tools directory. The resulting %s is unsigned."
msgstr ""
-"找ä¸åˆ°ã€Œapksigner'ã€ã€‚\n"
-"è«‹ç¢ºèªæ­¤å‘½ä»¤å¯ç”¨æ–¼Android SDK build-tools的目錄。\n"
-"%s 未簽署。"
+"找ä¸åˆ°ã€Œapksignerã€ã€‚請檢查 Android SDK çš„ build-tools è³‡æ–™å¤¾ä¸­æ˜¯å¦æœ‰æ­¤æŒ‡ä»¤ã€‚"
+"「%sã€æœªç°½ç½²ã€‚"
#: platform/android/export/export_plugin.cpp
msgid "Signing debug %s..."
@@ -19062,9 +18598,8 @@ msgid "Could not find keystore, unable to export."
msgstr "找ä¸åˆ°é‡‘鑰儲存å€ï¼Œç„¡æ³•匯出。"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not start apksigner executable."
-msgstr "無法啟動å­è™•ç†ç¨‹åºï¼"
+msgstr "無法啟動 apksigner å¯åŸ·è¡Œæª”案。"
#: platform/android/export/export_plugin.cpp
msgid "'apksigner' returned with error #%d"
@@ -19095,9 +18630,8 @@ msgid "Invalid filename! Android APK requires the *.apk extension."
msgstr "無效的檔案å稱ï¼Android APK å¿…é ˆè¦æœ‰ *.apk 副檔å。"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Unsupported export format!"
-msgstr "䏿”¯æ´çš„匯出格å¼ï¼\n"
+msgstr "䏿”¯æ´çš„匯出格å¼ï¼"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -19107,26 +18641,21 @@ msgstr ""
"嘗試自自定建置樣æ¿é€²è¡Œå»ºç½®ï¼Œä½†ç„¡ç‰ˆæœ¬è³‡è¨Šå¯ç”¨ã€‚請自「專案ã€é¸å–®ä¸­é‡æ–°å®‰è£ã€‚"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Android build version mismatch: Template installed: %s, Godot version: %s. "
"Please reinstall Android build template from 'Project' menu."
msgstr ""
-"Android 建置版本ä¸ç¬¦åˆï¼š\n"
-" 已安è£çš„æ¨£æ¿ï¼š%s\n"
-" Godot 版本:%s\n"
-"請自「專案ã€ç›®éŒ„䏭釿–°å®‰è£ Android 建置樣æ¿ã€‚"
+"Android 建構版本ä¸åŒ¹é…ï¼šå·²å®‰è£æ¨¡æ¿ï¼š %s,Godot 版本:%s。請從專案é¸å–®é‡æ–°å®‰"
+"è£ Android 構建模æ¿ã€‚"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Unable to overwrite res://android/build/res/*.xml files with project name."
-msgstr "無法以專案å稱覆蓋檔案res://android/build/res/*.xml"
+msgstr "無法以專案å稱覆蓋 res://android/build/res/*.xml 檔案。"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project."
-msgstr "無法匯出專案檔至Gradle專案。\n"
+msgstr "無法匯出專案檔至 Gradle 專案。"
#: platform/android/export/export_plugin.cpp
msgid "Could not write expansion package file!"
@@ -19137,13 +18666,12 @@ msgid "Building Android Project (gradle)"
msgstr "建置 Android 專案(Gradle)"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Building of Android project failed, check output for the error. "
"Alternatively visit docs.godotengine.org for Android build documentation."
msgstr ""
-"建置 Android 專案失敗,請檢查輸出以確èªéŒ¯èª¤ã€‚\n"
-"也å¯ä»¥ç€è¦½ docs.godotengine.org 以ç€è¦½ Android 建置說明文件。"
+"建置 Android 專案失敗,請檢查輸出以確èªéŒ¯èª¤ã€‚也å¯ä»¥ç€è¦½ docs.godotengine.org "
+"檢視 Android 建置說明文件。"
#: platform/android/export/export_plugin.cpp
msgid "Moving output"
@@ -19156,39 +18684,33 @@ msgid ""
msgstr "無法複製並更å匯出的檔案,請於 Gradle 專案資料夾內確èªè¼¸å‡ºã€‚"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Package not found: \"%s\"."
-msgstr "未找到套件:「%sã€"
+msgstr "未找到套件:「%sã€ã€‚"
#: platform/android/export/export_plugin.cpp
msgid "Creating APK..."
msgstr "正在建立APK……"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not find template APK to export: \"%s\"."
-msgstr ""
-"找ä¸åˆ°æ¨£æ¿APK以匯出:\n"
-"%s"
+msgstr "找ä¸åˆ° APK 模æ¿ä»¥åŒ¯å‡ºï¼šã€Œ%sã€ã€‚"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Missing libraries in the export template for the selected architectures: %s. "
"Please build a template with all required libraries, or uncheck the missing "
"architectures in the export preset."
msgstr ""
-"éºå¤±æ‰€é¸å–架構(%s)的匯出樣æ¿å‡½å¼åº«ã€‚\n"
-"請使用所有必è¦çš„函å¼åº«å»ºæ§‹æ¨£æ¿ï¼Œæˆ–在匯出é è¨­è¨­å®šä¸­å–消勾é¸éºå¤±çš„æž¶æ§‹ã€‚"
+"éºå¤±æ‰€é¸æž¶æ§‹ï¼ˆ%s)的匯出模æ¿å‡½å¼åº«ã€‚請使用所有必è¦çš„函å¼åº«å»ºæ§‹æ¨¡æ¿ï¼Œæˆ–在匯出"
+"é è¨­è¨­å®šä¸­å–消勾é¸éºå¤±çš„æž¶æ§‹ã€‚"
#: platform/android/export/export_plugin.cpp
msgid "Adding files..."
msgstr "正在加入檔案 %s……"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files."
-msgstr "無法匯出專案檔案"
+msgstr "無法匯出專案檔。"
#: platform/android/export/export_plugin.cpp
msgid "Aligning APK..."
@@ -19284,9 +18806,8 @@ msgid "Code Sign Identity Release"
msgstr ""
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Export Method Release"
-msgstr "匯出模å¼ï¼š"
+msgstr "發行匯出模å¼"
#: platform/iphone/export/export.cpp
msgid "Targeted Device Family"
@@ -19297,9 +18818,8 @@ msgid "Info"
msgstr ""
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "Identifier"
-msgstr "無效的識別符:"
+msgstr "標識符"
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
#, fuzzy
@@ -19323,14 +18843,12 @@ msgid "Capabilities"
msgstr "貼上屬性"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Access Wi-Fi"
-msgstr "æˆåŠŸï¼"
+msgstr "å­˜å– Wi-Fi"
#: platform/iphone/export/export.cpp
-#, fuzzy
msgid "Push Notifications"
-msgstr "隨機旋轉:"
+msgstr "推é€é€šçŸ¥"
#: platform/iphone/export/export.cpp
#, fuzzy
@@ -19462,19 +18980,16 @@ msgid "Run exported HTML in the system's default browser."
msgstr "在系統的é è¨­ç€è¦½å™¨ä¸­åŸ·è¡Œå·²åŒ¯å‡ºçš„ HTML。"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not open template for export: \"%s\"."
-msgstr "無法開啟樣æ¿ä»¥è¼¸å‡ºï¼š"
+msgstr "無法開啟模æ¿ä»¥åŒ¯å‡ºï¼šã€Œ%sã€ã€‚"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Invalid export template: \"%s\"."
-msgstr "無效的輸出樣æ¿ï¼š"
+msgstr "無效的匯出模æ¿ï¼šã€Œ%sã€ã€‚"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not write file: \"%s\"."
-msgstr "無法寫入檔案:"
+msgstr "無法寫入檔案:「%sã€ã€‚"
#: platform/javascript/export/export.cpp platform/osx/export/export.cpp
#, fuzzy
@@ -19482,18 +18997,16 @@ msgid "Icon Creation"
msgstr "設定外邊è·"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read file: \"%s\"."
-msgstr "ç„¡æ³•è®€å–æª”案:"
+msgstr "ç„¡æ³•è®€å–æª”案:「%sã€ã€‚"
#: platform/javascript/export/export.cpp
msgid "PWA"
msgstr ""
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Variant"
-msgstr "分隔:"
+msgstr "變體"
#: platform/javascript/export/export.cpp
#, fuzzy
@@ -19565,19 +19078,16 @@ msgid "Icon 512 X 512"
msgstr ""
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read HTML shell: \"%s\"."
-msgstr "無法讀å–HTML殼層:"
+msgstr "ç„¡æ³•è®€å– HTML 殼層:「%sã€ã€‚"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not create HTTP server directory: %s."
-msgstr "無法建立HTTP伺æœå™¨ç›®éŒ„:"
+msgstr "無法建立 HTTP 伺æœå™¨ç›®éŒ„:%s。"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Error starting HTTP server: %d."
-msgstr "啟動HTTP伺æœå™¨æ™‚發生錯誤:"
+msgstr "啟動 HTTP 伺æœå™¨æ™‚發生錯誤:%d。"
#: platform/javascript/export/export.cpp
msgid "Web"
@@ -19681,9 +19191,8 @@ msgid "Unknown object type."
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "App Category"
-msgstr "分類:"
+msgstr "App 分類"
#: platform/osx/export/export.cpp
msgid "High Res"
@@ -19859,9 +19368,8 @@ msgid "Custom Options"
msgstr "åŒ¯æµæŽ’é¸é …"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization"
-msgstr "本地化"
+msgstr "公證"
#: platform/osx/export/export.cpp
msgid "Apple ID Name"
@@ -19876,19 +19384,16 @@ msgid "Apple Team ID"
msgstr ""
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not open icon file \"%s\"."
-msgstr "無法匯出專案檔案"
+msgstr "無法開啟符號檔 「%sã€ã€‚"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start xcrun executable."
-msgstr "無法啟動å­è™•ç†ç¨‹åºï¼"
+msgstr "無法啟動 xcrun å¯åŸ·è¡Œæª”案。"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Notarization failed."
-msgstr "本地化"
+msgstr "公證失敗。"
#: platform/osx/export/export.cpp
msgid "Notarization request UUID: \"%s\""
@@ -19941,9 +19446,8 @@ msgid "No identity found."
msgstr "未發ç¾ä»»ä½•圖示。"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Cannot sign file %s."
-msgstr "無法ä¿å­˜æª”案:%s"
+msgstr "無法簽署檔案 %s。"
#: platform/osx/export/export.cpp
msgid "Relative symlinks are not supported, exported \"%s\" might be broken!"
@@ -19955,9 +19459,8 @@ msgid "DMG Creation"
msgstr "æ–¹å‘"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not start hdiutil executable."
-msgstr "無法啟動å­è™•ç†ç¨‹åºï¼"
+msgstr "無法啟動 hdiutil å¯åŸ·è¡Œæª”案。"
#: platform/osx/export/export.cpp
msgid "`hdiutil create` failed - file exists."
@@ -19973,16 +19476,12 @@ msgid "Creating app bundle"
msgstr "正在建立縮圖"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not find template app to export: \"%s\"."
-msgstr ""
-"找ä¸åˆ°æ¨£æ¿APK以匯出:\n"
-"%s"
+msgstr "找ä¸åˆ° app 模æ¿ä»¥åŒ¯å‡ºï¼šã€Œ%sã€ã€‚"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Invalid export format."
-msgstr "無效的輸出樣æ¿ï¼š"
+msgstr "無效的匯出格å¼ã€‚"
#: platform/osx/export/export.cpp
msgid ""
@@ -20038,9 +19537,8 @@ msgid "ZIP Creation"
msgstr "專案"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Could not open file to read from path \"%s\"."
-msgstr "無法匯出專案檔至Gradle專案。\n"
+msgstr "ç„¡æ³•æ‰“é–‹ä½æ–¼ã€Œ%sã€çš„æª”案進行讀å–。"
#: platform/osx/export/export.cpp
msgid "Invalid bundle identifier:"
@@ -20167,23 +19665,20 @@ msgid "Display Name"
msgstr "全部顯示"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Short Name"
-msgstr "腳本å稱:"
+msgstr "短å稱"
#: platform/uwp/export/export.cpp
msgid "Publisher"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Publisher Display Name"
-msgstr "無效的套件發佈者顯示å稱。"
+msgstr "發布者顯示å稱"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Product GUID"
-msgstr "ç„¡æ•ˆçš„ç”¢å“ GUID。"
+msgstr "ç”¢å“ GUID"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20196,9 +19691,8 @@ msgid "Signing"
msgstr "訊號"
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Certificate"
-msgstr "頂點:"
+msgstr "憑證"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20266,9 +19760,8 @@ msgid "Wide 310 X 150 Logo"
msgstr ""
#: platform/uwp/export/export.cpp
-#, fuzzy
msgid "Splash Screen"
-msgstr "繪製呼å«ï¼š"
+msgstr "啟動畫é¢"
#: platform/uwp/export/export.cpp
#, fuzzy
@@ -20358,9 +19851,8 @@ msgid "Debug Algorithm"
msgstr "除錯工具"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Failed to rename temporary file \"%s\"."
-msgstr "無法移除臨時檔案:"
+msgstr "ç„¡æ³•é‡æ–°å‘½åæ¨¡æ¿æª”案 「%sã€ã€‚"
#: platform/windows/export/export.cpp
msgid "Identity Type"
@@ -20386,19 +19878,16 @@ msgid "File Version"
msgstr "版本"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Product Version"
-msgstr "ç„¡æ•ˆçš„ç”¢å“ GUID。"
+msgstr "產å“版本"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Company Name"
-msgstr "節點å稱:"
+msgstr "å…¬å¸å稱"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Product Name"
-msgstr "專案å稱:"
+msgstr "產å“å稱"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20410,9 +19899,8 @@ msgid "Trademarks"
msgstr ""
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Resources Modification"
-msgstr "隨機旋轉:"
+msgstr "資æºä¿®æ”¹"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20426,15 +19914,15 @@ msgstr "找ä¸åˆ°é‡‘鑰儲存å€ï¼Œç„¡æ³•匯出。"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start rcedit executable, configure rcedit path in the Editor "
-"Settings (Export > Windows > Rcedit)."
+"Could not start rcedit executable. Configure rcedit path in the Editor "
+"Settings (Export > Windows > Rcedit), or disable \"Application > Modify "
+"Resources\" in the export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"rcedit failed to modify executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "rcedit failed to modify executable: %s."
+msgstr "無效的副檔å。"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20447,9 +19935,8 @@ msgid "Could not find osslsigncode executable at \"%s\"."
msgstr "找ä¸åˆ°é‡‘鑰儲存å€ï¼Œç„¡æ³•匯出。"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Invalid identity type."
-msgstr "無效的識別符:"
+msgstr "身份類型無效。"
#: platform/windows/export/export.cpp
#, fuzzy
@@ -20458,20 +19945,19 @@ msgstr "無效的å稱。"
#: platform/windows/export/export.cpp
msgid ""
-"Could not start signtool executable, configure signtool path in the Editor "
-"Settings (Export > Windows > Signtool)."
+"Could not start signtool executable. Configure signtool path in the Editor "
+"Settings (Export > Windows > Signtool), or disable \"Codesign\" in the "
+"export preset."
msgstr ""
#: platform/windows/export/export.cpp
-msgid ""
-"Signtool failed to sign executable:\n"
-"%s"
-msgstr ""
+#, fuzzy
+msgid "Signtool failed to sign executable: %s."
+msgstr "無效的副檔å。"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Failed to remove temporary file \"%s\"."
-msgstr "無法移除臨時檔案:"
+msgstr "ç„¡æ³•ç§»é™¤æ¨¡æ¿æª”案 「%sã€ã€‚"
#: platform/windows/export/export.cpp
msgid ""
@@ -20480,19 +19966,16 @@ msgid ""
msgstr ""
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Invalid icon path:"
-msgstr "無效的路徑。"
+msgstr "無效符號路徑:"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Invalid file version:"
-msgstr "無效的副檔å。"
+msgstr "無效的檔案版本:"
#: platform/windows/export/export.cpp
-#, fuzzy
msgid "Invalid product version:"
-msgstr "ç„¡æ•ˆçš„ç”¢å“ GUID。"
+msgstr "無效的產å“版本:"
#: platform/windows/export/export.cpp
msgid "Windows executables cannot be >= 4 GiB."
@@ -20661,9 +20144,8 @@ msgstr ""
#: scene/3d/light.cpp scene/3d/reflection_probe.cpp
#: scene/3d/visibility_notifier.cpp scene/3d/visual_instance.cpp
#: scene/resources/material.cpp
-#, fuzzy
msgid "Max Distance"
-msgstr "鏿“‡è·é›¢ï¼š"
+msgstr "最大è·é›¢"
#: scene/2d/audio_stream_player_2d.cpp scene/3d/light.cpp
#, fuzzy
@@ -20691,15 +20173,13 @@ msgid "Anchor Mode"
msgstr "圖示模å¼"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Rotating"
-msgstr "旋轉步長:"
+msgstr "旋轉"
#: scene/2d/camera_2d.cpp scene/2d/listener_2d.cpp scene/3d/camera.cpp
#: scene/3d/listener.cpp scene/animation/animation_blend_tree.cpp
-#, fuzzy
msgid "Current"
-msgstr "ç›®å‰ï¼š"
+msgstr "ç›®å‰"
#: scene/2d/camera_2d.cpp scene/gui/graph_edit.cpp
#, fuzzy
@@ -20711,7 +20191,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
@@ -20781,14 +20261,12 @@ msgid "Drag Margin"
msgstr "設定外邊è·"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Draw Screen"
-msgstr "繪製呼å«ï¼š"
+msgstr "繪製螢幕"
#: scene/2d/camera_2d.cpp
-#, fuzzy
msgid "Draw Limits"
-msgstr "繪製呼å«ï¼š"
+msgstr "繪製é™åˆ¶"
#: scene/2d/camera_2d.cpp
#, fuzzy
@@ -20965,9 +20443,8 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Emitting"
-msgstr "設定:"
+msgstr "發射"
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
@@ -20993,9 +20470,8 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/2d/particles_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/particles.cpp
-#, fuzzy
msgid "Randomness"
-msgstr "éš¨æ©Ÿé‡æ–°é–‹å§‹ï¼ˆç§’):"
+msgstr "隨機性"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21037,9 +20513,8 @@ msgstr "發射é®ç½©"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Sphere Radius"
-msgstr "發射æºï¼š "
+msgstr "çƒé«”åŠå¾‘"
#: scene/2d/cpu_particles_2d.cpp
#, fuzzy
@@ -21107,9 +20582,8 @@ msgstr "線性"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Accel"
-msgstr "æˆåŠŸï¼"
+msgstr "加速度"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21168,9 +20642,8 @@ msgid "Angle Curve"
msgstr "關閉曲線"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
-#, fuzzy
msgid "Scale Amount"
-msgstr "數é‡ï¼š"
+msgstr "縮放é‡"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
msgid "Scale Amount Random"
@@ -21194,27 +20667,23 @@ msgstr ""
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Hue Variation"
-msgstr "分隔:"
+msgstr "色相變化"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Variation"
-msgstr "分隔:"
+msgstr "變化"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Variation Random"
-msgstr "分隔:"
+msgstr "隨機變化"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Variation Curve"
-msgstr "分隔:"
+msgstr "變化曲線"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21230,9 +20699,8 @@ msgstr "拆分控制點"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Offset Random"
-msgstr "å移:"
+msgstr "隨機åç§»"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21425,14 +20893,12 @@ msgid "Begin Cap Mode"
msgstr "å€åŸŸæ¨¡å¼"
#: scene/2d/line_2d.cpp
-#, fuzzy
msgid "End Cap Mode"
-msgstr "å¸é™„模å¼ï¼š"
+msgstr "尾端模å¼"
#: scene/2d/line_2d.cpp scene/2d/polygon_2d.cpp scene/resources/style_box.cpp
-#, fuzzy
msgid "Border"
-msgstr "釿–°å‘½å資料夾:"
+msgstr "邊框"
#: scene/2d/line_2d.cpp
msgid "Sharp Limit"
@@ -21459,9 +20925,8 @@ msgid "Cell Size"
msgstr ""
#: scene/2d/navigation_2d.cpp scene/3d/navigation.cpp
-#, fuzzy
msgid "Edge Connection Margin"
-msgstr "編輯連接內容:"
+msgstr "邊界連接邊è·"
#: scene/2d/navigation_2d.cpp
msgid ""
@@ -21472,14 +20937,32 @@ 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 "鏿“‡è·é›¢ï¼š"
+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
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "啟用"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21493,19 +20976,8 @@ msgid "Time Horizon"
msgstr "水平翻轉"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
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 "啟用"
+msgstr "最大速度"
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -21547,24 +21019,21 @@ msgstr "行程"
#: scene/2d/node_2d.cpp scene/2d/polygon_2d.cpp scene/3d/spatial.cpp
#: scene/main/canvas_layer.cpp
-#, fuzzy
msgid "Rotation Degrees"
-msgstr "旋轉 %s 度。"
+msgstr "旋轉角度"
-#: scene/2d/node_2d.cpp
+#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
msgid "Global Rotation"
msgstr "常數"
#: scene/2d/node_2d.cpp
-#, fuzzy
msgid "Global Rotation Degrees"
-msgstr "旋轉 %s 度。"
+msgstr "全域旋轉角度"
#: scene/2d/node_2d.cpp
-#, fuzzy
msgid "Global Scale"
-msgstr "隨機縮放:"
+msgstr "全域縮放"
#: scene/2d/node_2d.cpp scene/3d/spatial.cpp
#, fuzzy
@@ -21582,9 +21051,8 @@ msgid "Scroll"
msgstr ""
#: scene/2d/parallax_background.cpp
-#, fuzzy
msgid "Base Offset"
-msgstr "å移:"
+msgstr "基礎åç§»"
#: scene/2d/parallax_background.cpp
#, fuzzy
@@ -21674,19 +21142,16 @@ msgid "PathFollow2D only works when set as a child of a Path2D node."
msgstr "PathFollow2D 僅在其為 Path2D çš„å­ç¯€é»žæ™‚有效。"
#: scene/2d/path_2d.cpp scene/3d/path.cpp
-#, fuzzy
msgid "Unit Offset"
-msgstr "網格åç§»é‡ï¼š"
+msgstr "å–®ä½åç§»"
#: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp
-#, fuzzy
msgid "H Offset"
-msgstr "å移:"
+msgstr "H åç§»"
#: scene/2d/path_2d.cpp scene/3d/camera.cpp scene/3d/path.cpp
-#, fuzzy
msgid "V Offset"
-msgstr "å移:"
+msgstr "V åç§»"
#: scene/2d/path_2d.cpp scene/3d/path.cpp
msgid "Cubic Interp"
@@ -21747,9 +21212,8 @@ msgid "Mass"
msgstr ""
#: scene/2d/physics_body_2d.cpp
-#, fuzzy
msgid "Inertia"
-msgstr "垂直:"
+msgstr "慣性"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#, fuzzy
@@ -21786,9 +21250,8 @@ msgid "Sleeping"
msgstr "智慧型å¸é™„"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Can Sleep"
-msgstr "速度:"
+msgstr "å¯ä»¥ç¡çœ "
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
msgid "Damp"
@@ -21812,9 +21275,8 @@ msgid "Safe Margin"
msgstr "設定外邊è·"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Sync To Physics"
-msgstr " (物ç†ï¼‰"
+msgstr "與物ç†åŒæ­¥"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#, fuzzy
@@ -21834,9 +21296,8 @@ msgid "Normal"
msgstr "æ ¼å¼"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Remainder"
-msgstr "算繪引擎:"
+msgstr "餘é‡"
#: scene/2d/physics_body_2d.cpp scene/3d/physics_body.cpp
#, fuzzy
@@ -22026,9 +21487,8 @@ msgid "Compatibility Mode"
msgstr "優先模å¼"
#: scene/2d/tile_map.cpp
-#, fuzzy
msgid "Centered Textures"
-msgstr "主è¦åŠŸèƒ½ï¼š"
+msgstr "ç´‹ç†å±…中"
#: scene/2d/tile_map.cpp
msgid "Cell Clip UV"
@@ -22147,9 +21607,8 @@ msgid "ARVROrigin requires an ARVRCamera child node."
msgstr "ARVROrigin 必須有一個 ARVRCamera å­ç¯€é»žã€‚"
#: scene/3d/arvr_nodes.cpp servers/arvr_server.cpp
-#, fuzzy
msgid "World Scale"
-msgstr "隨機縮放:"
+msgstr "世界縮放"
#: scene/3d/audio_stream_player_3d.cpp
#, fuzzy
@@ -22178,9 +21637,8 @@ msgid "Emission Angle"
msgstr "發射色彩"
#: scene/3d/audio_stream_player_3d.cpp
-#, fuzzy
msgid "Degrees"
-msgstr "旋轉 %s 度。"
+msgstr "角度"
#: scene/3d/audio_stream_player_3d.cpp
#, fuzzy
@@ -22262,9 +21720,8 @@ msgid "Bounce Indirect Energy"
msgstr ""
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Use Denoiser"
-msgstr "篩é¸ï¼š"
+msgstr "使用é™å™ªå™¨"
#: scene/3d/baked_lightmap.cpp scene/resources/texture.cpp
msgid "Use HDR"
@@ -22291,9 +21748,8 @@ msgid "Generate"
msgstr "一般"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Max Size"
-msgstr "大å°ï¼š"
+msgstr "最大大å°"
#: scene/3d/baked_lightmap.cpp
#, fuzzy
@@ -22301,9 +21757,8 @@ msgid "Custom Sky"
msgstr "剪下節點"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Custom Sky Rotation Degrees"
-msgstr "旋轉 %s 度。"
+msgstr "自定義天空旋轉角度"
#: scene/3d/baked_lightmap.cpp scene/3d/ray_cast.cpp
#, fuzzy
@@ -22335,9 +21790,8 @@ msgid "Light Data"
msgstr "åŒ…å«æ•¸æ“š"
#: scene/3d/bone_attachment.cpp scene/3d/physics_body.cpp
-#, fuzzy
msgid "Bone Name"
-msgstr "節點å稱:"
+msgstr "骨骼å稱"
#: scene/3d/camera.cpp
msgid "Keep Aspect"
@@ -22362,9 +21816,8 @@ msgid "FOV"
msgstr ""
#: scene/3d/camera.cpp
-#, fuzzy
msgid "Frustum Offset"
-msgstr "網格åç§»é‡ï¼š"
+msgstr "視éŒåç§»"
#: scene/3d/camera.cpp
#, fuzzy
@@ -22616,9 +22069,8 @@ msgid "Font"
msgstr "å­—é«”"
#: scene/3d/label_3d.cpp scene/resources/primitive_meshes.cpp
-#, fuzzy
msgid "Horizontal Alignment"
-msgstr "水平:"
+msgstr "æ°´å¹³å°é½Š"
#: scene/3d/label_3d.cpp
#, fuzzy
@@ -22682,9 +22134,8 @@ msgid "Split 3"
msgstr "拆分路徑"
#: scene/3d/light.cpp
-#, fuzzy
msgid "Blend Splits"
-msgstr "æ··åˆæ™‚間:"
+msgstr "æ··åˆæ‹†åˆ†"
#: scene/3d/light.cpp
#, fuzzy
@@ -22728,9 +22179,8 @@ msgid "Software Skinning"
msgstr ""
#: scene/3d/mesh_instance.cpp
-#, fuzzy
msgid "Transform Normals"
-msgstr "已中止變æ›ã€‚"
+msgstr "è®Šæ›æ³•ç·š"
#: scene/3d/navigation.cpp
msgid ""
@@ -22819,14 +22269,12 @@ msgid "Visibility AABB"
msgstr "切æ›å¯è¦‹ï¼éš±è—"
#: scene/3d/particles.cpp
-#, fuzzy
msgid "Draw Passes"
-msgstr "繪製呼å«ï¼š"
+msgstr "繪製階段"
#: scene/3d/particles.cpp
-#, fuzzy
msgid "Passes"
-msgstr "繪製呼å«ï¼š"
+msgstr "階段"
#: scene/3d/path.cpp
msgid "PathFollow only works when set as a child of a Path node."
@@ -22922,9 +22370,8 @@ msgstr ""
#: scene/3d/physics_body.cpp scene/3d/physics_joint.cpp
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Relaxation"
-msgstr "分隔:"
+msgstr "鬆弛"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -22937,9 +22384,8 @@ msgid "Angular Limit Upper"
msgstr "線性"
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Angular Limit Lower"
-msgstr "最大角度誤差:"
+msgstr "角度下é™"
#: scene/3d/physics_body.cpp
#, fuzzy
@@ -23070,9 +22516,8 @@ msgid "Angular Equilibrium Point"
msgstr ""
#: scene/3d/physics_body.cpp
-#, fuzzy
msgid "Body Offset"
-msgstr "å移:"
+msgstr "形體åç§»"
#: scene/3d/physics_joint.cpp
msgid "Node A and Node B must be PhysicsBodies"
@@ -23104,9 +22549,8 @@ msgid "Exclude Nodes"
msgstr "刪除節點"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Params"
-msgstr "å·²æ›´æ”¹åƒæ•¸ï¼š"
+msgstr "引數"
#: scene/3d/physics_joint.cpp
msgid "Angular Limit"
@@ -23132,9 +22576,8 @@ msgid "Target Velocity"
msgstr "å‘å³ç’°è¦–"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Max Impulse"
-msgstr "速度:"
+msgstr "最大è¡é‡"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23142,14 +22585,12 @@ msgid "Linear Limit"
msgstr "線性"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Upper Distance"
-msgstr "鏿“‡è·é›¢ï¼š"
+msgstr "è·é›¢ä¸Šé™"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Lower Distance"
-msgstr "鏿“‡è·é›¢ï¼š"
+msgstr "è·é›¢ä¸‹é™"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23182,9 +22623,8 @@ msgid "Angular Motion"
msgstr "å‹•ç•«"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Angular Ortho"
-msgstr "最大角度誤差:"
+msgstr "角度正交"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23197,9 +22637,8 @@ msgid "Linear Motor X"
msgstr "åˆå§‹åŒ–"
#: scene/3d/physics_joint.cpp
-#, fuzzy
msgid "Force Limit"
-msgstr "繪製呼å«ï¼š"
+msgstr "力度é™åˆ¶"
#: scene/3d/physics_joint.cpp
#, fuzzy
@@ -23297,9 +22736,8 @@ msgid "Two Way"
msgstr ""
#: scene/3d/portal.cpp
-#, fuzzy
msgid "Linked Room"
-msgstr "峿™‚編輯根節點:"
+msgstr "連接房間"
#: scene/3d/portal.cpp
#, fuzzy
@@ -23316,9 +22754,8 @@ msgid "Dispatch Mode"
msgstr ""
#: scene/3d/proximity_group.cpp
-#, fuzzy
msgid "Grid Radius"
-msgstr "åŠå¾‘:"
+msgstr "網格åŠå¾‘"
#: scene/3d/ray_cast.cpp
#, fuzzy
@@ -23335,9 +22772,8 @@ msgid "Update Mode"
msgstr "旋轉模å¼"
#: scene/3d/reflection_probe.cpp
-#, fuzzy
msgid "Origin Offset"
-msgstr "網格åç§»é‡ï¼š"
+msgstr "原點åç§»"
#: scene/3d/reflection_probe.cpp
#, fuzzy
@@ -23599,14 +23035,12 @@ msgid "Parent Collision Ignore"
msgstr "建立碰撞多邊形"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Simulation Precision"
-msgstr "無效的動畫樹。"
+msgstr "模擬精度"
#: scene/3d/soft_body.cpp
-#, fuzzy
msgid "Total Mass"
-msgstr "總計:"
+msgstr "總質é‡"
#: scene/3d/soft_body.cpp
msgid "Linear Stiffness"
@@ -23650,13 +23084,16 @@ msgstr ""
"請改為修改其å­ç¯€é»žçš„碰撞形狀之大å°ã€‚"
#: scene/3d/spatial.cpp
+msgid "Global Translation"
+msgstr "全域變æ›"
+
+#: scene/3d/spatial.cpp
msgid "Matrix"
msgstr ""
#: scene/3d/spatial.cpp
-#, fuzzy
msgid "Gizmo"
-msgstr "Gizmo"
+msgstr "控制器"
#: scene/3d/spatial_velocity_tracker.cpp
#, fuzzy
@@ -23715,18 +23152,16 @@ msgid "VehicleBody Motion"
msgstr ""
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Use As Traction"
-msgstr "分隔:"
+msgstr "用作牽引"
#: scene/3d/vehicle_body.cpp
msgid "Use As Steering"
msgstr ""
#: scene/3d/vehicle_body.cpp
-#, fuzzy
msgid "Wheel"
-msgstr "滾輪å‘上。"
+msgstr "車輪"
#: scene/3d/vehicle_body.cpp
msgid "Roll Influence"
@@ -23762,9 +23197,8 @@ msgid "Material Override"
msgstr "複寫"
#: scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Material Overlay"
-msgstr "æè³ªè®Šæ›´ï¼š"
+msgstr "æè³ªè¦†è“‹å±¤"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -23772,9 +23206,8 @@ msgid "Cast Shadow"
msgstr "建立著色器節點"
#: scene/3d/visual_instance.cpp
-#, fuzzy
msgid "Extra Cull Margin"
-msgstr "é¡å¤–呼å«å¼•數:"
+msgstr "é¡å¤–剔除邊è·"
#: scene/3d/visual_instance.cpp
#, fuzzy
@@ -23796,9 +23229,8 @@ msgstr ""
#: scene/3d/visual_instance.cpp scene/animation/skeleton_ik.cpp
#: scene/resources/material.cpp
-#, fuzzy
msgid "Min Distance"
-msgstr "鏿“‡è·é›¢ï¼š"
+msgstr "最å°è·é›¢"
#: scene/3d/visual_instance.cpp
msgid "Min Hysteresis"
@@ -24299,18 +23731,16 @@ msgid "Mouse"
msgstr ""
#: scene/gui/control.cpp
-#, fuzzy
msgid "Default Cursor Shape"
-msgstr "載入é è¨­åŒ¯æµæŽ’é…置。"
+msgstr "é è¨­æ¸¸æ¨™å½¢ç‹€"
#: scene/gui/control.cpp
msgid "Pass On Modal Close Click"
msgstr ""
#: scene/gui/control.cpp
-#, fuzzy
msgid "Size Flags"
-msgstr "大å°ï¼š "
+msgstr "å¤§å° Flag:"
#: scene/gui/control.cpp
#, fuzzy
@@ -24676,9 +24106,8 @@ msgid "Max Value"
msgstr "數值"
#: scene/gui/range.cpp
-#, fuzzy
msgid "Page"
-msgstr "é ï¼š "
+msgstr "é "
#: scene/gui/range.cpp
#, fuzzy
@@ -24866,9 +24295,8 @@ msgid "All Tabs In Front"
msgstr ""
#: scene/gui/tab_container.cpp scene/gui/tabs.cpp
-#, fuzzy
msgid "Drag To Rearrange Enabled"
-msgstr "æ‹–æ”¾ä»¥é‡æ–°æŽ’列。"
+msgstr "å•Ÿç”¨æ‹–ç§»é‡æ–°æŽ’列"
#: scene/gui/tab_container.cpp
msgid "Use Hidden Tabs For Min Size"
@@ -24903,6 +24331,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 "啟用"
@@ -25000,9 +24433,8 @@ msgid "Initial Angle"
msgstr "åˆå§‹åŒ–"
#: scene/gui/texture_progress.cpp
-#, fuzzy
msgid "Fill Degrees"
-msgstr "旋轉 %s 度。"
+msgstr "填充角度"
#: scene/gui/texture_progress.cpp scene/resources/primitive_meshes.cpp
#, fuzzy
@@ -25109,9 +24541,8 @@ msgid "Max Redirects"
msgstr ""
#: scene/main/http_request.cpp
-#, fuzzy
msgid "Timeout"
-msgstr "逾時。"
+msgstr "逾時"
#: scene/main/node.cpp
msgid ""
@@ -25239,9 +24670,8 @@ msgid "Draw 2D Outlines"
msgstr "建立輪廓"
#: scene/main/scene_tree.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Reflections"
-msgstr "æ–¹å‘"
+msgstr "åå°„"
#: scene/main/scene_tree.cpp
#, fuzzy
@@ -25313,22 +24743,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 ""
@@ -25880,9 +25308,8 @@ msgid "Labeled Separator Right"
msgstr "帶å稱的分隔線"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Separator"
-msgstr "色彩é‹ç®—å­ã€‚"
+msgstr "分隔線字體"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -25890,9 +25317,8 @@ msgid "Font Color Accel"
msgstr "釿–°å‘½åé¡è‰²é …ç›®"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Font Color Separator"
-msgstr "色彩é‹ç®—å­ã€‚"
+msgstr "分隔線字體é¡è‰²"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26180,9 +25606,8 @@ msgid "Label Width"
msgstr "左延展"
#: scene/resources/default_theme/default_theme.cpp
-#, fuzzy
msgid "Screen Picker"
-msgstr "濾色é‹ç®—å­ã€‚"
+msgstr "å±å¹•å–色器"
#: scene/resources/default_theme/default_theme.cpp
#, fuzzy
@@ -26397,9 +25822,8 @@ msgid "Sky Rotation"
msgstr "旋轉步長:"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Sky Rotation Degrees"
-msgstr "旋轉 %s 度。"
+msgstr "天空旋轉角度"
#: scene/resources/environment.cpp
msgid "Canvas Max Layer"
@@ -26579,9 +26003,8 @@ msgid "Distance"
msgstr "鏿“‡è·é›¢ï¼š"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Transition"
-msgstr "轉場: "
+msgstr "轉場效果"
#: scene/resources/environment.cpp
msgid "DOF Near Blur"
@@ -26664,9 +26087,8 @@ msgid "Saturation"
msgstr "分隔:"
#: scene/resources/environment.cpp
-#, fuzzy
msgid "Color Correction"
-msgstr "é¡è‰²å‡½å¼ã€‚"
+msgstr "é¡è‰²æ ¡æ­£"
#: scene/resources/font.cpp
#, fuzzy
@@ -26748,9 +26170,8 @@ msgid "Disable Ambient Light"
msgstr "å‘å³ç¸®æŽ’"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Ensure Correct Normals"
-msgstr "已中止變æ›ã€‚"
+msgstr "ç¢ºä¿æ­£ç¢ºæ³•ç·š"
#: scene/resources/material.cpp
msgid "Albedo Tex MSDF"
@@ -26917,9 +26338,8 @@ msgid "Subsurf Scatter"
msgstr ""
#: scene/resources/material.cpp
-#, fuzzy
msgid "Transmission"
-msgstr "轉場: "
+msgstr "轉場"
#: scene/resources/material.cpp
#, fuzzy
@@ -26987,14 +26407,12 @@ msgid "NavMesh Transform"
msgstr "清除變æ›"
#: scene/resources/multimesh.cpp
-#, fuzzy
msgid "Color Format"
-msgstr "色彩é‹ç®—å­ã€‚"
+msgstr "é¡è‰²æ ¼å¼"
#: scene/resources/multimesh.cpp
-#, fuzzy
msgid "Transform Format"
-msgstr "已中止變æ›ã€‚"
+msgstr "è®Šæ›æ ¼å¼"
#: scene/resources/multimesh.cpp
msgid "Custom Data Format"
@@ -27010,9 +26428,8 @@ msgid "Visible Instance Count"
msgstr ""
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Sampling"
-msgstr "縮放: "
+msgstr "縮放:"
#: scene/resources/navigation_mesh.cpp
#, fuzzy
@@ -27020,9 +26437,8 @@ msgid "Partition Type"
msgstr "設定變數型別"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Parsed Geometry Type"
-msgstr "正在解æžå¤šé‚Šå½¢..."
+msgstr "è§£æžå¹¾ä½•體類型"
#: scene/resources/navigation_mesh.cpp
msgid "Source Geometry Mode"
@@ -27156,14 +26572,12 @@ msgid "Point Texture"
msgstr "發射點:"
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Normal Texture"
-msgstr "發射æºï¼š "
+msgstr "法線紋ç†è²¼åœ–"
#: scene/resources/particles_material.cpp
-#, fuzzy
msgid "Color Texture"
-msgstr "編輯器主題"
+msgstr "é¡è‰²ç´‹ç†è²¼åœ–"
#: scene/resources/particles_material.cpp
#, fuzzy
@@ -27362,9 +26776,8 @@ msgid "Base Texture"
msgstr "移除紋ç†"
#: scene/resources/texture.cpp
-#, fuzzy
msgid "Image Size"
-msgstr "é ï¼š "
+msgstr "圖片大å°"
#: scene/resources/texture.cpp
#, fuzzy
@@ -27776,9 +27189,8 @@ msgid "Pan Pullout"
msgstr ""
#: servers/audio/effects/audio_effect_stereo_enhance.cpp
-#, fuzzy
msgid "Time Pullout (ms)"
-msgstr "逾時。"
+msgstr "撤離時間(毫秒)"
#: servers/audio/effects/audio_effect_stereo_enhance.cpp
msgid "Surround"
@@ -27833,119 +27245,105 @@ msgstr "é€è¦–"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Sleep Threshold Linear"
-msgstr ""
+msgstr "線性ç¡çœ é€Ÿåº¦é–¾å€¼"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Sleep Threshold Angular"
-msgstr ""
+msgstr "ç¡çœ è§’速度閾值"
#: servers/physics/space_sw.cpp servers/physics_2d/space_2d_sw.cpp
msgid "Time Before Sleep"
-msgstr ""
+msgstr "ç¡çœ å‰æ™‚é–“"
#: servers/physics_2d/physics_2d_server_sw.cpp
-#, fuzzy
msgid "BP Hash Table Size"
-msgstr "大å°ï¼š"
+msgstr "BP 雜湊表大å°"
#: servers/physics_2d/physics_2d_server_sw.cpp
msgid "Large Object Surface Threshold In Cells"
-msgstr ""
+msgstr "大物件表é¢å–®ä½æ ¼é–¾å€¼"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Inverse Mass"
-msgstr ""
+msgstr "逆質é‡"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Inverse Inertia"
-msgstr "自由視圖 左"
+msgstr "逆慣性"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Total Angular Damp"
-msgstr ""
+msgstr "總角速度減幅"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Total Linear Damp"
-msgstr "線性"
+msgstr "總線性速度減幅"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Total Gravity"
-msgstr "é è¨­é è¦½"
+msgstr "總é‡åŠ›"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Linear Velocity"
-msgstr "åˆå§‹åŒ–"
+msgstr "線性速度"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Exclude"
-msgstr ""
+msgstr "排除"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Shape RID"
-msgstr ""
+msgstr "形狀RID"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collide With Bodies"
-msgstr "碰撞模å¼"
+msgstr "形體間碰撞"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Collide With Areas"
-msgstr ""
+msgstr "å€åŸŸé–“碰撞"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
msgid "Motion Remainder"
-msgstr ""
+msgstr "é‹å‹•剩餘é‡"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collision Point"
-msgstr "碰撞模å¼"
+msgstr "碰撞點"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collision Normal"
-msgstr "碰撞模å¼"
+msgstr "碰撞法線"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collision Depth"
-msgstr "碰撞模å¼"
+msgstr "碰撞深度"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collision Safe Fraction"
-msgstr "碰撞模å¼"
+msgstr "碰撞安全比值"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Collision Unsafe Fraction"
-msgstr "碰撞模å¼"
+msgstr "碰撞éžå®‰å…¨æ¯”值"
#: servers/physics_2d_server.cpp servers/physics_server.cpp
-#, fuzzy
msgid "Physics Engine"
-msgstr "物ç†å½±æ ¼ %"
+msgstr "物ç†å¼•擎"
#: servers/physics_server.cpp
-#, fuzzy
msgid "Center Of Mass"
-msgstr "中左"
+msgstr "質é‡ä¸­å¿ƒ"
#: servers/physics_server.cpp
msgid "Principal Inertia Axes"
-msgstr ""
+msgstr "主慣性軸"
#: servers/visual/shader_language.cpp
msgid "Varying may not be assigned in the '%s' function."
-msgstr "Varying 變數ä¸å¯åœ¨å‡½å¼ã€Œ%sã€ä¸­è¢«æŒ‡æ´¾ã€‚"
+msgstr "Varying變數ä¸å¯åœ¨ã€Œ%sã€å‡½å¼ä¸­è¢«æŒ‡æ´¾ã€‚"
#: servers/visual/shader_language.cpp
-#, fuzzy
msgid ""
"Varyings which were assigned in 'vertex' function may not be reassigned in "
"'fragment' or 'light'."
@@ -27954,7 +27352,6 @@ msgstr ""
"指派。"
#: servers/visual/shader_language.cpp
-#, fuzzy
msgid ""
"Varyings which were assigned in 'fragment' function may not be reassigned in "
"'vertex' or 'light'."
@@ -27975,39 +27372,32 @@ msgid "Constants cannot be modified."
msgstr "ä¸å¯ä¿®æ”¹å¸¸æ•¸ã€‚"
#: servers/visual/visual_server_scene.cpp
-#, fuzzy
msgid "Spatial Partitioning"
-msgstr "正在分割..."
+msgstr "空間分割"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Render Loop Enabled"
-msgstr "篩é¸è¨Šè™Ÿ"
+msgstr "啟用算繪迴圈"
#: servers/visual_server.cpp
-#, fuzzy
msgid "VRAM Compression"
-msgstr "設定表示å¼"
+msgstr "VRAM壓縮"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import BPTC"
-msgstr "匯入"
+msgstr "匯入BPTC"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import S3TC"
-msgstr "匯入"
+msgstr "匯入S3TC"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import ETC"
-msgstr "匯入"
+msgstr "匯入ETC"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Import ETC2"
-msgstr "匯入"
+msgstr "匯入ETC2"
#: servers/visual_server.cpp
#, fuzzy
@@ -28019,9 +27409,8 @@ msgid "Lossless Compression"
msgstr ""
#: servers/visual_server.cpp
-#, fuzzy
msgid "Force PNG"
-msgstr "來æºç¶²æ ¼ï¼š"
+msgstr "強制 PNG"
#: servers/visual_server.cpp
msgid "WebP Compression Level"
@@ -28065,7 +27454,7 @@ msgstr "篩é¸ç¯€é»ž"
#: servers/visual_server.cpp
#, fuzzy
msgid "Texture Array Reflections"
-msgstr "置中所é¸"
+msgstr "ç´‹ç†è²¼åœ–陣列åå°„"
#: servers/visual_server.cpp
msgid "High Quality GGX"
@@ -28122,20 +27511,24 @@ msgid "Use Nearest Mipmap Filter"
msgstr ""
#: servers/visual_server.cpp
+#, fuzzy
msgid "Skinning"
-msgstr ""
+msgstr "外觀變更"
#: servers/visual_server.cpp
+#, fuzzy
msgid "Software Skinning Fallback"
-msgstr ""
+msgstr "軟體外觀變更後備"
#: servers/visual_server.cpp
+#, fuzzy
msgid "Force Software Skinning"
-msgstr ""
+msgstr "強制軟體外觀變更"
#: servers/visual_server.cpp
+#, fuzzy
msgid "Use Software Skinning"
-msgstr ""
+msgstr "使用軟體外觀變更"
#: servers/visual_server.cpp
#, fuzzy
@@ -28165,9 +27558,8 @@ msgid "Legacy Stream"
msgstr ""
#: servers/visual_server.cpp
-#, fuzzy
msgid "Batching"
-msgstr "正在æœå°‹..."
+msgstr "分批"
#: servers/visual_server.cpp
msgid "Use Batching"
@@ -28197,7 +27589,7 @@ msgstr ""
#: servers/visual_server.cpp
#, fuzzy
msgid "Max Join Items"
-msgstr "管ç†é …目……"
+msgstr "最大加入項目數"
#: servers/visual_server.cpp
msgid "Batch Buffer Size"
@@ -28253,7 +27645,7 @@ msgstr "使用縮放å¸é™„"
#: servers/visual_server.cpp
msgid "PVS Logging"
-msgstr ""
+msgstr "PVS 日誌"
#: servers/visual_server.cpp
#, fuzzy
@@ -28285,9 +27677,8 @@ msgid "Max Active Polygons"
msgstr "移動多邊形"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Shader Compilation Mode"
-msgstr "æ’值模å¼"
+msgstr "著色器編譯模å¼"
#: servers/visual_server.cpp
msgid "Max Simultaneous Compiles"
@@ -28298,6 +27689,5 @@ msgid "Log Active Async Compiles Count"
msgstr ""
#: servers/visual_server.cpp
-#, fuzzy
msgid "Shader Cache Size (MB)"
-msgstr "更改相機尺寸"
+msgstr "著色器快å–å¤§å° ï¼ˆMB)"
diff --git a/gles3_builders.py b/gles3_builders.py
index 6b2d315603..a9fabd93ce 100644
--- a/gles3_builders.py
+++ b/gles3_builders.py
@@ -436,7 +436,7 @@ def build_gles3_header(filename, include, class_suffix, output_attribs):
)
fd.write(
- """_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix,RID p_version,ShaderVariant p_variant"""
+ """_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Projection& p_matrix,RID p_version,ShaderVariant p_variant"""
+ defvariant
+ """,uint64_t p_specialization="""
+ str(defspec)
diff --git a/main/main.cpp b/main/main.cpp
index f3c56c7205..4c4377a174 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -31,6 +31,7 @@
#include "main.h"
#include "core/config/project_settings.h"
+#include "core/core_globals.h"
#include "core/core_string_names.h"
#include "core/crypto/crypto.h"
#include "core/debugger/engine_debugger.h"
@@ -148,7 +149,7 @@ static bool cmdline_tool = false;
static String locale;
static bool show_help = false;
static bool auto_quit = false;
-static OS::ProcessID allow_focus_steal_pid = 0;
+static OS::ProcessID editor_pid = 0;
#ifdef TOOLS_ENABLED
static bool auto_build_solutions = false;
static String debug_server_uri;
@@ -181,7 +182,6 @@ static bool debug_navigation = false;
static int frame_delay = 0;
static bool disable_render_loop = false;
static int fixed_fps = -1;
-static String write_movie_path;
static MovieWriter *movie_writer = nullptr;
static bool disable_vsync = false;
static bool print_fps = false;
@@ -286,6 +286,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Run options:\n");
+ OS::get_singleton()->print(" -- Separator for user-provided arguments. Following arguments are not used by the engine, but can be read from `OS.get_cmdline_user_args()`.\n");
#ifdef TOOLS_ENABLED
OS::get_singleton()->print(" -e, --editor Start the editor instead of running the scene.\n");
OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n");
@@ -344,6 +345,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n");
OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n");
OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
+ OS::get_singleton()->print(" --xr-mode <mode> Select XR mode (default/off/on).\n");
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Debug options:\n");
@@ -410,6 +412,8 @@ Error Main::test_setup() {
String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2);
+ register_core_settings(); //here globals are present
+
translation_server = memnew(TranslationServer);
tsman = memnew(TextServerManager);
@@ -427,6 +431,7 @@ Error Main::test_setup() {
/** INITIALIZE SERVERS **/
register_server_types();
+ XRServer::set_xr_mode(XRServer::XRMODE_OFF); // Skip in tests.
initialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
@@ -621,11 +626,20 @@ 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> user_args;
+ bool adding_user_args = false;
+ 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) {
@@ -673,9 +687,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
packed_data->add_pack_source(zip_packed_data);
#endif
+ // Default exit code, can be modified for certain errors.
+ Error exit_code = ERR_INVALID_PARAMETER;
+
I = args.front();
while (I) {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
// Ignore the process serial number argument passed by macOS Gatekeeper.
// Otherwise, Godot would try to open a non-existent project on the first start and abort.
if (I->get().begins_with("-psn_")) {
@@ -683,15 +700,20 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
continue;
}
#endif
+
List<String>::Element *N = I->next();
- if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help
+ if (adding_user_args) {
+ user_args.push_back(I->get());
+ } else if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help
show_help = true;
+ 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 = 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
@@ -1032,10 +1054,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (I->next()) {
String p = I->next()->get();
- if (OS::get_singleton()->set_cwd(p) == OK) {
- //nothing
- } else {
- project_path = I->next()->get(); //use project_path instead
+ if (OS::get_singleton()->set_cwd(p) != OK) {
+ OS::get_singleton()->print("Invalid project path specified: \"%s\", aborting.\n", p.utf8().get_data());
+ goto error;
}
N = I->next()->next();
} else {
@@ -1129,9 +1150,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->print("Missing remote debug host address, aborting.\n");
goto error;
}
- } else if (I->get() == "--allow_focus_steal_pid") { // not exposed to user
+ } else if (I->get() == "--editor-pid") { // not exposed to user
if (I->next()) {
- allow_focus_steal_pid = I->next()->get().to_int();
+ editor_pid = I->next()->get().to_int();
N = I->next()->next();
} else {
OS::get_singleton()->print("Missing editor PID argument, aborting.\n");
@@ -1149,7 +1170,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
} else if (I->get() == "--write-movie") {
if (I->next()) {
- write_movie_path = I->next()->get();
+ Engine::get_singleton()->set_write_movie_path(I->next()->get());
N = I->next()->next();
if (fixed_fps == -1) {
fixed_fps = 60;
@@ -1169,6 +1190,26 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->disable_crash_handler();
} else if (I->get() == "--skip-breakpoints") {
skip_breakpoints = true;
+ } else if (I->get() == "--xr-mode") {
+ if (I->next()) {
+ String xr_mode = I->next()->get().to_lower();
+ N = I->next()->next();
+ if (xr_mode == "default") {
+ XRServer::set_xr_mode(XRServer::XRMODE_DEFAULT);
+ } else if (xr_mode == "off") {
+ XRServer::set_xr_mode(XRServer::XRMODE_OFF);
+ } else if (xr_mode == "on") {
+ XRServer::set_xr_mode(XRServer::XRMODE_ON);
+ } else {
+ OS::get_singleton()->print("Unknown --xr-mode argument \"%s\", aborting.\n", xr_mode.ascii().get_data());
+ goto error;
+ }
+ } else {
+ OS::get_singleton()->print("Missing --xr-mode argument, aborting.\n");
+ goto error;
+ }
+ } else if (I->get() == "--") {
+ adding_user_args = true;
} else {
main_args.push_back(I->get());
}
@@ -1261,7 +1302,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
PROPERTY_HINT_RANGE,
"0, 200, 1, or_greater"));
- EngineDebugger::initialize(debug_uri, skip_breakpoints, breakpoints);
+ EngineDebugger::initialize(debug_uri, skip_breakpoints, breakpoints, []() {
+ if (editor_pid) {
+ DisplayServer::get_singleton()->enable_for_stealing_focus(editor_pid);
+ }
+ });
#ifdef TOOLS_ENABLED
if (editor) {
@@ -1332,16 +1377,16 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
quiet_stdout = true;
}
if (bool(ProjectSettings::get_singleton()->get("application/run/disable_stderr"))) {
- _print_error_enabled = false;
+ CoreGlobals::print_error_enabled = false;
};
if (quiet_stdout) {
- _print_line_enabled = false;
+ CoreGlobals::print_line_enabled = false;
}
Logger::set_flush_stdout_on_print(ProjectSettings::get_singleton()->get("application/run/flush_stdout_on_print"));
- OS::get_singleton()->set_cmdline(execpath, main_args);
+ OS::get_singleton()->set_cmdline(execpath, main_args, user_args);
// possibly be worth changing the default from vulkan to something lower spec,
// for the project manager, depending on how smooth the fallback is.
@@ -1419,7 +1464,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
}
- GLOBAL_DEF("internationalization/rendering/force_right_to_left_layout_direction", false);
+ GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false);
GLOBAL_DEF("internationalization/locale/include_text_server_data", false);
OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", true);
@@ -1455,11 +1500,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;
@@ -1467,6 +1511,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;
}
@@ -1479,6 +1525,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;
@@ -1487,10 +1535,12 @@ 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()) {
+ if (Engine::get_singleton()->get_write_movie_path() != String()) {
// Always use dummy driver for audio driver (which is last), also in no threaded mode.
audio_driver_idx = AudioDriverManager::get_driver_count() - 1;
AudioDriverDummy::get_dummy_singleton()->set_use_threads(false);
@@ -1587,7 +1637,7 @@ error:
display_driver = "";
audio_driver = "";
tablet_driver = "";
- write_movie_path = "";
+ Engine::get_singleton()->set_write_movie_path(String());
project_path = "";
args.clear();
@@ -1629,6 +1679,7 @@ error:
unregister_core_types();
OS::get_singleton()->_cmdline.clear();
+ OS::get_singleton()->_user_args.clear();
if (message_queue) {
memdelete(message_queue);
@@ -1636,7 +1687,7 @@ error:
OS::get_singleton()->finalize_core();
locale = String();
- return ERR_INVALID_PARAMETER;
+ return exit_code;
}
Error Main::setup2(Thread::ID p_main_tid_override) {
@@ -1680,10 +1731,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) {
@@ -1760,11 +1813,11 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
rendering_server->set_print_gpu_profile(true);
}
- if (write_movie_path != String()) {
- movie_writer = MovieWriter::find_writer_for_file(write_movie_path);
+ if (Engine::get_singleton()->get_write_movie_path() != String()) {
+ movie_writer = MovieWriter::find_writer_for_file(Engine::get_singleton()->get_write_movie_path());
if (movie_writer == nullptr) {
- ERR_PRINT("Can't find movie writer for file type, aborting: " + write_movie_path);
- write_movie_path = String();
+ ERR_PRINT("Can't find movie writer for file type, aborting: " + Engine::get_singleton()->get_write_movie_path());
+ Engine::get_singleton()->set_write_movie_path(String());
}
}
@@ -1819,10 +1872,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
DisplayServer::get_singleton()->window_set_flag(DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP, true);
}
- if (allow_focus_steal_pid) {
- DisplayServer::get_singleton()->enable_for_stealing_focus(allow_focus_steal_pid);
- }
-
MAIN_PRINT("Main: Load Boot Image");
Color clear = GLOBAL_DEF_BASIC("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3));
@@ -1946,7 +1995,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
MAIN_PRINT("Main: Load TextServer");
/* Enum text drivers */
- GLOBAL_DEF("internationalization/rendering/text_driver", "");
+ GLOBAL_DEF_RST("internationalization/rendering/text_driver", "");
String text_driver_options;
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
if (i > 0) {
@@ -2059,7 +2108,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
// able to load resources, load the global shader variables.
// If running on editor, don't load the textures because the editor
// may want to import them first. Editor will reload those later.
- rendering_server->global_variables_load_settings(!editor);
+ rendering_server->global_shader_uniforms_load_settings(!editor);
}
_start_success = true;
@@ -2179,6 +2228,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
@@ -2384,6 +2440,8 @@ bool Main::start() {
}
if (debug_navigation) {
sml->set_debug_navigation_hint(true);
+ NavigationServer3D::get_singleton()->set_active(true);
+ NavigationServer3D::get_singleton_mut()->set_debug_enabled(true);
}
#endif
@@ -2549,7 +2607,7 @@ bool Main::start() {
PropertyInfo(Variant::FLOAT,
"display/window/stretch/scale",
PROPERTY_HINT_RANGE,
- "1.0,8.0,0.1"));
+ "0.5,8.0,0.01"));
sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true));
sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true));
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
@@ -2643,7 +2701,7 @@ bool Main::start() {
ERR_FAIL_COND_V_MSG(!scene, false, "Failed loading scene: " + local_game_path);
sml->add_current_scene(scene);
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
String mac_iconpath = GLOBAL_DEF("application/config/macos_native_icon", "Variant()");
if (!mac_iconpath.is_empty()) {
DisplayServer::get_singleton()->set_native_icon(mac_iconpath);
@@ -2697,8 +2755,17 @@ bool Main::start() {
OS::get_singleton()->set_main_loop(main_loop);
if (movie_writer) {
- movie_writer->begin(DisplayServer::get_singleton()->window_get_size(), fixed_fps, write_movie_path);
+ movie_writer->begin(DisplayServer::get_singleton()->window_get_size(), fixed_fps, Engine::get_singleton()->get_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;
}
@@ -2944,6 +3011,7 @@ void Main::cleanup(bool p_force) {
OS::get_singleton()->delete_main_loop();
OS::get_singleton()->_cmdline.clear();
+ OS::get_singleton()->_user_args.clear();
OS::get_singleton()->_execpath = "";
OS::get_singleton()->_local_clipboard = "";
@@ -2956,7 +3024,7 @@ void Main::cleanup(bool p_force) {
RenderingServer::get_singleton()->sync();
//clear global shader variables before scene and other graphics stuff are deinitialized.
- rendering_server->global_variables_clear();
+ rendering_server->global_shader_uniforms_clear();
if (xr_server) {
// Now that we're unregistering properly in plugins we need to keep access to xr_server for a little longer
diff --git a/main/performance.cpp b/main/performance.cpp
index 25659b999f..0de525134e 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -283,7 +283,7 @@ Variant Performance::MonitorCall::call(bool &r_error, String &r_error_message) {
int argc = _arguments.size();
Variant return_value;
Callable::CallError error;
- _callable.call(args, argc, return_value, error);
+ _callable.callp(args, argc, return_value, error);
r_error = (error.error != Callable::CallError::CALL_OK);
if (r_error) {
r_error_message = Variant::get_callable_error_text(_callable, args, argc, error);
diff --git a/methods.py b/methods.py
index b4a55cab79..82c19f09e3 100644
--- a/methods.py
+++ b/methods.py
@@ -1,5 +1,6 @@
import os
import re
+import sys
import glob
import subprocess
from collections import OrderedDict
@@ -125,9 +126,21 @@ def update_version(module_version_string=""):
if os.path.isfile(os.path.join(gitfolder, "HEAD")):
head = open(os.path.join(gitfolder, "HEAD"), "r", encoding="utf8").readline().strip()
if head.startswith("ref: "):
- head = os.path.join(gitfolder, head[5:])
+ ref = head[5:]
+ head = os.path.join(gitfolder, ref)
+ packedrefs = os.path.join(gitfolder, "packed-refs")
if os.path.isfile(head):
githash = open(head, "r").readline().strip()
+ elif os.path.isfile(packedrefs):
+ # Git may pack refs into a single file. This code searches .git/packed-refs file for the current ref's hash.
+ # https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-pack-refs.html
+ for line in open(packedrefs, "r").read().splitlines():
+ if line.startswith("#"):
+ continue
+ (line_hash, line_ref) = line.split(" ")
+ if ref == line_ref:
+ githash = line_hash
+ break
else:
githash = head
@@ -324,7 +337,20 @@ def disable_module(self):
self.disabled_modules.append(self.current_module)
-def module_check_dependencies(self, module, dependencies, silent=False):
+def module_add_dependencies(self, module, dependencies, optional=False):
+ """
+ Adds dependencies for a given module.
+ Meant to be used in module `can_build` methods.
+ """
+ if module not in self.module_dependencies:
+ self.module_dependencies[module] = [[], []]
+ if optional:
+ self.module_dependencies[module][1].extend(dependencies)
+ else:
+ self.module_dependencies[module][0].extend(dependencies)
+
+
+def module_check_dependencies(self, module):
"""
Checks if module dependencies are enabled for a given module,
and prints a warning if they aren't.
@@ -332,23 +358,41 @@ def module_check_dependencies(self, module, dependencies, silent=False):
Returns a boolean (True if dependencies are satisfied).
"""
missing_deps = []
- for dep in dependencies:
+ required_deps = self.module_dependencies[module][0] if module in self.module_dependencies else []
+ for dep in required_deps:
opt = "module_{}_enabled".format(dep)
if not opt in self or not self[opt]:
missing_deps.append(dep)
if missing_deps != []:
- if not silent:
- print(
- "Disabling '{}' module as the following dependencies are not satisfied: {}".format(
- module, ", ".join(missing_deps)
- )
+ print(
+ "Disabling '{}' module as the following dependencies are not satisfied: {}".format(
+ module, ", ".join(missing_deps)
)
+ )
return False
else:
return True
+def sort_module_list(env):
+ out = OrderedDict()
+ deps = {k: v[0] + list(filter(lambda x: x in env.module_list, v[1])) for k, v in env.module_dependencies.items()}
+
+ frontier = list(env.module_list.keys())
+ explored = []
+ while len(frontier):
+ cur = frontier.pop()
+ deps_list = deps[cur] if cur in deps else []
+ if len(deps_list) and any([d not in explored for d in deps_list]):
+ # Will explore later, after its dependencies
+ frontier.insert(0, cur)
+ continue
+ explored.append(cur)
+ for k in explored:
+ env.module_list.move_to_end(k)
+
+
def use_windows_spawn_fix(self, platform=None):
if os.name != "nt":
@@ -595,8 +639,18 @@ def find_visual_c_batch_file(env):
find_batch_file,
)
+ # Syntax changed in SCons 4.4.0.
+ from SCons import __version__ as scons_raw_version
+
+ scons_ver = env._get_major_minor_revision(scons_raw_version)
+
version = get_default_version(env)
- (host_platform, target_platform, _) = get_host_target(env)
+
+ if scons_ver >= (4, 4, 0):
+ (host_platform, target_platform, _) = get_host_target(env, version)
+ else:
+ (host_platform, target_platform, _) = get_host_target(env)
+
return find_batch_file(env, version, host_platform, target_platform)[0]
@@ -833,15 +887,15 @@ def Run(env, function, short_message, subprocess=True):
def detect_darwin_sdk_path(platform, env):
sdk_name = ""
- if platform == "osx":
+ if platform == "macos":
sdk_name = "macosx"
var_name = "MACOS_SDK_PATH"
- elif platform == "iphone":
+ elif platform == "ios":
sdk_name = "iphoneos"
- var_name = "IPHONESDK"
- elif platform == "iphonesimulator":
+ var_name = "IOS_SDK_PATH"
+ elif platform == "iossimulator":
sdk_name = "iphonesimulator"
- var_name = "IPHONESDK"
+ var_name = "IOS_SDK_PATH"
else:
raise Exception("Invalid platform argument passed to detect_darwin_sdk_path")
diff --git a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/Info.plist b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/Info.plist
index 846533594f..846533594f 100644
--- a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/Info.plist
+++ b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/Info.plist
diff --git a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64/empty b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64/empty
index bd3e894333..bd3e894333 100644
--- a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64/empty
+++ b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64/empty
diff --git a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64_x86_64-simulator/empty b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/empty
index bd3e894333..bd3e894333 100644
--- a/misc/dist/ios_xcode/libgodot.iphone.debug.xcframework/ios-arm64_x86_64-simulator/empty
+++ b/misc/dist/ios_xcode/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/empty
diff --git a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/Info.plist b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/Info.plist
index 846533594f..846533594f 100644
--- a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/Info.plist
+++ b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/Info.plist
diff --git a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64/empty b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64/empty
index bd3e894333..bd3e894333 100644
--- a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64/empty
+++ b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64/empty
diff --git a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64_x86_64-simulator/empty b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64_x86_64-simulator/empty
index bd3e894333..bd3e894333 100644
--- a/misc/dist/ios_xcode/libgodot.iphone.release.xcframework/ios-arm64_x86_64-simulator/empty
+++ b/misc/dist/ios_xcode/libgodot.ios.release.xcframework/ios-arm64_x86_64-simulator/empty
diff --git a/misc/dist/osx/editor.entitlements b/misc/dist/macos/editor.entitlements
index d0137910a3..d0137910a3 100644
--- a/misc/dist/osx/editor.entitlements
+++ b/misc/dist/macos/editor.entitlements
diff --git a/misc/dist/osx_template.app/Contents/Info.plist b/misc/dist/macos_template.app/Contents/Info.plist
index 542146cdb8..542146cdb8 100644
--- a/misc/dist/osx_template.app/Contents/Info.plist
+++ b/misc/dist/macos_template.app/Contents/Info.plist
diff --git a/misc/dist/osx_template.app/Contents/PkgInfo b/misc/dist/macos_template.app/Contents/PkgInfo
index 6f749b0f37..6f749b0f37 100644
--- a/misc/dist/osx_template.app/Contents/PkgInfo
+++ b/misc/dist/macos_template.app/Contents/PkgInfo
diff --git a/misc/dist/osx_template.app/Contents/Resources/icon.icns b/misc/dist/macos_template.app/Contents/Resources/icon.icns
index be9254630c..be9254630c 100644
--- a/misc/dist/osx_template.app/Contents/Resources/icon.icns
+++ b/misc/dist/macos_template.app/Contents/Resources/icon.icns
Binary files differ
diff --git a/misc/dist/osx_tools.app/Contents/Info.plist b/misc/dist/macos_tools.app/Contents/Info.plist
index 886df87cc6..886df87cc6 100644
--- a/misc/dist/osx_tools.app/Contents/Info.plist
+++ b/misc/dist/macos_tools.app/Contents/Info.plist
diff --git a/misc/dist/osx_tools.app/Contents/PkgInfo b/misc/dist/macos_tools.app/Contents/PkgInfo
index 6f749b0f37..6f749b0f37 100644
--- a/misc/dist/osx_tools.app/Contents/PkgInfo
+++ b/misc/dist/macos_tools.app/Contents/PkgInfo
diff --git a/misc/dist/osx_tools.app/Contents/Resources/GDScript.icns b/misc/dist/macos_tools.app/Contents/Resources/GDScript.icns
index b08e8df339..b08e8df339 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/GDScript.icns
+++ b/misc/dist/macos_tools.app/Contents/Resources/GDScript.icns
Binary files differ
diff --git a/misc/dist/osx_tools.app/Contents/Resources/Godot.icns b/misc/dist/macos_tools.app/Contents/Resources/Godot.icns
index 61697976c6..61697976c6 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/Godot.icns
+++ b/misc/dist/macos_tools.app/Contents/Resources/Godot.icns
Binary files differ
diff --git a/misc/dist/osx_tools.app/Contents/Resources/Project.icns b/misc/dist/macos_tools.app/Contents/Resources/Project.icns
index 10e31528e4..10e31528e4 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/Project.icns
+++ b/misc/dist/macos_tools.app/Contents/Resources/Project.icns
Binary files differ
diff --git a/misc/dist/osx_tools.app/Contents/Resources/Resource.icns b/misc/dist/macos_tools.app/Contents/Resources/Resource.icns
index 9648cb616e..9648cb616e 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/Resource.icns
+++ b/misc/dist/macos_tools.app/Contents/Resources/Resource.icns
Binary files differ
diff --git a/misc/dist/osx_tools.app/Contents/Resources/Scene.icns b/misc/dist/macos_tools.app/Contents/Resources/Scene.icns
index c8c3dee07e..c8c3dee07e 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/Scene.icns
+++ b/misc/dist/macos_tools.app/Contents/Resources/Scene.icns
Binary files differ
diff --git a/misc/dist/osx_tools.app/Contents/Resources/Shader.icns b/misc/dist/macos_tools.app/Contents/Resources/Shader.icns
index a76e648a1a..a76e648a1a 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/Shader.icns
+++ b/misc/dist/macos_tools.app/Contents/Resources/Shader.icns
Binary files differ
diff --git a/misc/dist/osx_tools.app/Contents/Resources/af.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/af.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/af.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/af.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ar.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/az.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/az.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/az.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/az.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/bg.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/bn.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/br.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/br.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/br.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/br.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ca.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/cs.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/da.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/da.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/da.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/da.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/de.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/de.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/de.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/de.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/el.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/el.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/el.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/el.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/en.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/en.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/en.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/en.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/eo.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/es.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/es.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/es.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/es.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/es_AR.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/et.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/et.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/et.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/et.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/eu.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/fa.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/fi.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/fil.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/fr.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ga.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/gl.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/he.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/he.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/he.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/he.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/hi.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/hr.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/hu.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/id.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/id.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/id.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/id.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/is.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/is.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/is.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/is.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/it.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/it.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/it.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/it.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ja.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ka.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/km.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/km.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/km.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/km.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ko.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/lt.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/lv.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/mi.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/mk.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ml.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/mr.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ms.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/nb.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/nl.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/or.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/or.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/or.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/or.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/pl.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/pt.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/pt_BR.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ro.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ru.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/si.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/si.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/si.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/si.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/sk.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/sl.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/sq.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/sr-Cyrl.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/sr-Latn.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/sv.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ta.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/te.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/te.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/te.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/te.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/th.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/th.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/th.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/th.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/tr.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/tt.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/tzm.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/uk.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/ur_PK.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/vi.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/zh_CN.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/zh_HK.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings b/misc/dist/macos_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings
index e69de29bb2..e69de29bb2 100644
--- a/misc/dist/osx_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings
+++ b/misc/dist/macos_tools.app/Contents/Resources/zh_TW.lproj/InfoPlist.strings
diff --git a/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json b/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json
deleted file mode 100644
index c4f8f71d0e..0000000000
--- a/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "file_format_version" : "1.0.0",
- "ICD": {
- "library_path": "../../../Frameworks/libMoltenVK.dylib",
- "api_version" : "1.1.0"
- }
-}
diff --git a/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json b/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json
deleted file mode 100644
index c4f8f71d0e..0000000000
--- a/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "file_format_version" : "1.0.0",
- "ICD": {
- "library_path": "../../../Frameworks/libMoltenVK.dylib",
- "api_version" : "1.1.0"
- }
-}
diff --git a/misc/scripts/file_format.sh b/misc/scripts/file_format.sh
index c767d3f8a0..731b3ee005 100755
--- a/misc/scripts/file_format.sh
+++ b/misc/scripts/file_format.sh
@@ -37,6 +37,8 @@ while IFS= read -rd '' f; do
continue
elif [[ "$f" == *"-so_wrap."* ]]; then
continue
+ elif [[ "$f" == *".test.txt" ]]; then
+ continue
fi
# Ensure that files are UTF-8 formatted.
recode UTF-8 "$f" 2> /dev/null
diff --git a/misc/scripts/header_guards.sh b/misc/scripts/header_guards.sh
new file mode 100755
index 0000000000..9a830f3ad2
--- /dev/null
+++ b/misc/scripts/header_guards.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+if [ ! -f "version.py" ]; then
+ echo "Warning: This script is intended to be run from the root of the Godot repository."
+ echo "Some of the paths checks may not work as intended from a different folder."
+fi
+
+for file in $(find -name "thirdparty" -prune -o -name "*.h" -print); do
+ # Skip *.gen.h and *-so_wrap.h, they're generated.
+ if [[ "$file" == *".gen.h" || "$file" == *"-so_wrap.h" ]]; then continue; fi
+ # Has important define before normal header guards.
+ if [[ "$file" == *"thread.h" || "$file" == *"platform_config.h" ]]; then continue; fi
+
+ bname=$(basename $file .h)
+
+ # Add custom prefix or suffix for generic filenames with a well-defined namespace.
+
+ prefix=
+ if [[ "$file" == "./modules/"*"/register_types.h" ]]; then
+ module=$(echo $file | sed "s@.*modules/\([^/]*\).*@\1@")
+ prefix="${module^^}_"
+ fi
+ if [[ "$file" == "./platform/"*"/api/api.h" || "$file" == "./platform/"*"/export/"* ]]; then
+ platform=$(echo $file | sed "s@.*platform/\([^/]*\).*@\1@")
+ prefix="${platform^^}_"
+ fi
+ if [[ "$file" == "./modules/mono/utils/"* && "$bname" != *"mono"* ]]; then prefix="MONO_"; fi
+ if [[ "$file" == "./servers/rendering/storage/utilities.h" ]]; then prefix="RENDERER_"; fi
+
+ suffix=
+ if [[ "$file" == *"dummy"* && "$bname" != *"dummy"* ]]; then suffix="_DUMMY"; fi
+ if [[ "$file" == *"gles3"* && "$bname" != *"gles3"* ]]; then suffix="_GLES3"; fi
+ if [[ "$file" == *"renderer_rd"* && "$bname" != *"rd"* ]]; then suffix="_RD"; fi
+ if [[ "$file" == *"ustring.h" ]]; then suffix="_GODOT"; fi
+
+ # ^^ is bash builtin for UPPERCASE.
+ guard="${prefix}${bname^^}${suffix}_H"
+
+ # Replaces guards to use computed name.
+ # We also add some \n to make sure there's a proper separation.
+ sed -i $file -e "0,/ifndef/s/#ifndef.*/\n#ifndef $guard/"
+ sed -i $file -e "0,/define/s/#define.*/#define $guard\n/"
+ sed -i $file -e "$ s/#endif.*/\n#endif \/\/ $guard/"
+ # Removes redundant \n added before, if they weren't needed.
+ sed -i $file -e "/^$/N;/^\n$/D"
+done
+
+diff=$(git diff --color)
+
+# If no diff has been generated all is OK, clean up, and exit.
+if [ -z "$diff" ] ; then
+ printf "Files in this commit comply with the header guards formatting rules.\n"
+ exit 0
+fi
+
+# A diff has been created, notify the user, clean up, and exit.
+printf "\n*** The following differences were found between the code "
+printf "and the header guards formatting rules:\n\n"
+echo "$diff"
+printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
+exit 1
diff --git a/misc/scripts/install_vulkan_sdk_macos.sh b/misc/scripts/install_vulkan_sdk_macos.sh
new file mode 100755
index 0000000000..d78659fa9f
--- /dev/null
+++ b/misc/scripts/install_vulkan_sdk_macos.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env sh
+
+set -euo pipefail
+IFS=$'\n\t'
+
+# Download and install the Vulkan SDK.
+curl -L "https://sdk.lunarg.com/sdk/download/latest/mac/vulkan-sdk.dmg" -o /tmp/vulkan-sdk.dmg
+hdiutil attach /tmp/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
+rm -f /tmp/vulkan-sdk.dmg
+
+echo 'Vulkan SDK installed successfully! You can now build Godot by running "scons".'
diff --git a/modules/bmp/SCsub b/modules/bmp/SCsub
index 4f3405ff28..9d317887c3 100644
--- a/modules/bmp/SCsub
+++ b/modules/bmp/SCsub
@@ -5,5 +5,5 @@ Import("env_modules")
env_bmp = env_modules.Clone()
-# Godot's own source files
+# Godot source files
env_bmp.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/camera/SCsub b/modules/camera/SCsub
index de97724d09..9a6147d433 100644
--- a/modules/camera/SCsub
+++ b/modules/camera/SCsub
@@ -9,6 +9,6 @@ if env["platform"] == "windows":
env_camera.add_source_files(env.modules_sources, "register_types.cpp")
env_camera.add_source_files(env.modules_sources, "camera_win.cpp")
-elif env["platform"] == "osx":
+elif env["platform"] == "macos":
env_camera.add_source_files(env.modules_sources, "register_types.cpp")
- env_camera.add_source_files(env.modules_sources, "camera_osx.mm")
+ env_camera.add_source_files(env.modules_sources, "camera_macos.mm")
diff --git a/modules/camera/camera_osx.h b/modules/camera/camera_macos.h
index b0db844599..903eda51bf 100644
--- a/modules/camera/camera_osx.h
+++ b/modules/camera/camera_macos.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* camera_osx.h */
+/* camera_macos.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,19 +28,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CAMERAOSX_H
-#define CAMERAOSX_H
+#ifndef CAMERA_MACOS_H
+#define CAMERA_MACOS_H
///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimize code duplication!!!!
// If you fix something here, make sure you fix it there as well!
#include "servers/camera_server.h"
-class CameraOSX : public CameraServer {
+class CameraMacOS : public CameraServer {
public:
- CameraOSX();
+ CameraMacOS();
void update_feeds();
};
-#endif /* CAMERAOSX_H */
+#endif // CAMERA_MACOS_H
diff --git a/modules/camera/camera_osx.mm b/modules/camera/camera_macos.mm
index d199c31b2f..0b9696a3e9 100644
--- a/modules/camera/camera_osx.mm
+++ b/modules/camera/camera_macos.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* camera_osx.mm */
+/* camera_macos.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -31,7 +31,7 @@
///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimize code duplication!!!!
// If you fix something here, make sure you fix it there as well!
-#include "camera_osx.h"
+#include "camera_macos.h"
#include "servers/camera/camera_feed.h"
#import <AVFoundation/AVFoundation.h>
@@ -191,9 +191,9 @@
@end
//////////////////////////////////////////////////////////////////////////
-// CameraFeedOSX - Subclass for camera feeds in OSX
+// CameraFeedMacOS - Subclass for camera feeds in macOS
-class CameraFeedOSX : public CameraFeed {
+class CameraFeedMacOS : public CameraFeed {
private:
AVCaptureDevice *device;
MyCaptureSession *capture_session;
@@ -201,7 +201,7 @@ private:
public:
AVCaptureDevice *get_device() const;
- CameraFeedOSX();
+ CameraFeedMacOS();
void set_device(AVCaptureDevice *p_device);
@@ -209,16 +209,16 @@ public:
void deactivate_feed();
};
-AVCaptureDevice *CameraFeedOSX::get_device() const {
+AVCaptureDevice *CameraFeedMacOS::get_device() const {
return device;
};
-CameraFeedOSX::CameraFeedOSX() {
+CameraFeedMacOS::CameraFeedMacOS() {
device = nullptr;
capture_session = nullptr;
};
-void CameraFeedOSX::set_device(AVCaptureDevice *p_device) {
+void CameraFeedMacOS::set_device(AVCaptureDevice *p_device) {
device = p_device;
// get some info
@@ -232,7 +232,7 @@ void CameraFeedOSX::set_device(AVCaptureDevice *p_device) {
};
};
-bool CameraFeedOSX::activate_feed() {
+bool CameraFeedMacOS::activate_feed() {
if (capture_session) {
// Already recording!
} else {
@@ -258,7 +258,7 @@ bool CameraFeedOSX::activate_feed() {
return true;
};
-void CameraFeedOSX::deactivate_feed() {
+void CameraFeedMacOS::deactivate_feed() {
// end camera capture if we have one
if (capture_session) {
[capture_session cleanup];
@@ -271,7 +271,7 @@ void CameraFeedOSX::deactivate_feed() {
// when devices are connected/disconnected
@interface MyDeviceNotifications : NSObject {
- CameraOSX *camera_server;
+ CameraMacOS *camera_server;
}
@end
@@ -282,7 +282,7 @@ void CameraFeedOSX::deactivate_feed() {
camera_server->update_feeds();
}
-- (id)initForServer:(CameraOSX *)p_server {
+- (id)initForServer:(CameraMacOS *)p_server {
if (self = [super init]) {
camera_server = p_server;
@@ -303,9 +303,9 @@ void CameraFeedOSX::deactivate_feed() {
MyDeviceNotifications *device_notifications = nil;
//////////////////////////////////////////////////////////////////////////
-// CameraOSX - Subclass for our camera server on OSX
+// CameraMacOS - Subclass for our camera server on macOS
-void CameraOSX::update_feeds() {
+void CameraMacOS::update_feeds() {
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101500
AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:[NSArray arrayWithObjects:AVCaptureDeviceTypeExternalUnknown, AVCaptureDeviceTypeBuiltInWideAngleCamera, nil] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
NSArray *devices = session.devices;
@@ -315,7 +315,7 @@ void CameraOSX::update_feeds() {
// remove devices that are gone..
for (int i = feeds.size() - 1; i >= 0; i--) {
- Ref<CameraFeedOSX> feed = (Ref<CameraFeedOSX>)feeds[i];
+ Ref<CameraFeedMacOS> feed = (Ref<CameraFeedMacOS>)feeds[i];
if (![devices containsObject:feed->get_device()]) {
// remove it from our array, this will also destroy it ;)
@@ -326,14 +326,14 @@ void CameraOSX::update_feeds() {
for (AVCaptureDevice *device in devices) {
bool found = false;
for (int i = 0; i < feeds.size() && !found; i++) {
- Ref<CameraFeedOSX> feed = (Ref<CameraFeedOSX>)feeds[i];
+ Ref<CameraFeedMacOS> feed = (Ref<CameraFeedMacOS>)feeds[i];
if (feed->get_device() == device) {
found = true;
};
};
if (!found) {
- Ref<CameraFeedOSX> newfeed;
+ Ref<CameraFeedMacOS> newfeed;
newfeed.instantiate();
newfeed->set_device(device);
@@ -346,7 +346,7 @@ void CameraOSX::update_feeds() {
};
};
-CameraOSX::CameraOSX() {
+CameraMacOS::CameraMacOS() {
// Find available cameras we have at this time
update_feeds();
diff --git a/modules/camera/camera_win.h b/modules/camera/camera_win.h
index 9563326acb..ebfc117190 100644
--- a/modules/camera/camera_win.h
+++ b/modules/camera/camera_win.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CAMERAWIN_H
-#define CAMERAWIN_H
+#ifndef CAMERA_WIN_H
+#define CAMERA_WIN_H
#include "servers/camera/camera_feed.h"
#include "servers/camera_server.h"
@@ -43,4 +43,4 @@ public:
~CameraWindows() {}
};
-#endif /* CAMERAWIN_H */
+#endif // CAMERA_WIN_H
diff --git a/modules/camera/config.py b/modules/camera/config.py
index 8a22751aa7..d2b2542dd9 100644
--- a/modules/camera/config.py
+++ b/modules/camera/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return platform == "osx" or platform == "windows"
+ return platform == "macos" or platform == "windows"
def configure(env):
diff --git a/modules/camera/register_types.cpp b/modules/camera/register_types.cpp
index 98a4b5ca1a..40e2224d6b 100644
--- a/modules/camera/register_types.cpp
+++ b/modules/camera/register_types.cpp
@@ -33,8 +33,8 @@
#if defined(WINDOWS_ENABLED)
#include "camera_win.h"
#endif
-#if defined(OSX_ENABLED)
-#include "camera_osx.h"
+#if defined(MACOS_ENABLED)
+#include "camera_macos.h"
#endif
void initialize_camera_module(ModuleInitializationLevel p_level) {
@@ -45,8 +45,8 @@ void initialize_camera_module(ModuleInitializationLevel p_level) {
#if defined(WINDOWS_ENABLED)
CameraServer::make_default<CameraWindows>();
#endif
-#if defined(OSX_ENABLED)
- CameraServer::make_default<CameraOSX>();
+#if defined(MACOS_ENABLED)
+ CameraServer::make_default<CameraMacOS>();
#endif
}
diff --git a/modules/csg/SCsub b/modules/csg/SCsub
index c7307ddefd..55f859db11 100644
--- a/modules/csg/SCsub
+++ b/modules/csg/SCsub
@@ -3,10 +3,9 @@
Import("env")
Import("env_modules")
-# Godot's own source files
env_csg = env_modules.Clone()
-# Godot's own source files
+# Godot source files
env_csg.add_source_files(env.modules_sources, "*.cpp")
if env["tools"]:
env_csg.add_source_files(env.modules_sources, "editor/*.cpp")
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 93533e1690..6b05c146e6 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -729,7 +729,7 @@ void CSGBrushOperation::MeshMerge::mark_inside_faces() {
}
}
-void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[], const Vector2 p_uvs[], bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) {
+void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[3], const Vector2 p_uvs[3], bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) {
int indices[3];
for (int i = 0; i < 3; i++) {
VertexKey vk;
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 0f09eb2020..56be4e65f0 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -1858,7 +1858,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
}
Transform3D facing = Transform3D().looking_at(direction, current_up);
- current_xform = base_xform.translated(current_point) * facing;
+ current_xform = base_xform.translated_local(current_point) * facing;
}
// Create the mesh.
@@ -1897,7 +1897,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
switch (mode) {
case MODE_DEPTH: {
- current_xform.translate(Vector3(0, 0, -depth));
+ current_xform.translate_local(Vector3(0, 0, -depth));
} break;
case MODE_SPIN: {
current_xform.rotate(Vector3(0, 1, 0), spin_step);
@@ -1945,7 +1945,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
}
Transform3D facing = Transform3D().looking_at(direction, current_up);
- current_xform = base_xform.translated(current_point) * facing;
+ current_xform = base_xform.translated_local(current_point) * facing;
} break;
}
diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp
index a7cfcaa262..3322ff0a1b 100644
--- a/modules/cvtt/image_compress_cvtt.cpp
+++ b/modules/cvtt/image_compress_cvtt.cpp
@@ -129,14 +129,6 @@ static void _digest_row_task(const CVTTCompressionJobParams &p_job_params, const
}
}
-static void _digest_job_queue(void *p_job_queue) {
- CVTTCompressionJobQueue *job_queue = static_cast<CVTTCompressionJobQueue *>(p_job_queue);
-
- for (uint32_t next_task = job_queue->current_task.increment(); next_task <= job_queue->num_tasks; next_task = job_queue->current_task.increment()) {
- _digest_row_task(job_queue->job_params, job_queue->job_tasks[next_task - 1]);
- }
-}
-
void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChannels p_channels) {
if (p_image->get_format() >= Image::FORMAT_BPTC_RGBA) {
return; //do not compress, already compressed
@@ -202,7 +194,6 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann
job_queue.job_params.bytes_per_pixel = is_hdr ? 6 : 4;
cvtt::Kernels::ConfigureBC7EncodingPlanFromQuality(job_queue.job_params.bc7_plan, 5);
- int num_job_threads = 0;
// Amdahl's law (Wikipedia)
// If a program needs 20 hours to complete using a single thread, but a one-hour portion of the program cannot be parallelized,
// therefore only the remaining 19 hours (p = 0.95) of execution time can be parallelized, then regardless of how many threads are devoted
@@ -229,11 +220,7 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann
row_task.in_mm_bytes = in_bytes;
row_task.out_mm_bytes = out_bytes;
- if (num_job_threads > 0) {
- tasks.push_back(row_task);
- } else {
- _digest_row_task(job_queue.job_params, row_task);
- }
+ _digest_row_task(job_queue.job_params, row_task);
out_bytes += 16 * (bw / 4);
}
@@ -243,29 +230,6 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann
h = MAX(h / 2, 1);
}
- if (num_job_threads > 0) {
- Vector<Thread *> threads;
- threads.resize(num_job_threads);
-
- Thread **threads_wb = threads.ptrw();
-
- const CVTTCompressionRowTask *tasks_rb = tasks.ptr();
-
- job_queue.job_tasks = &tasks_rb[0];
- job_queue.current_task.set(0);
- job_queue.num_tasks = static_cast<uint32_t>(tasks.size());
-
- for (int i = 0; i < num_job_threads; i++) {
- threads_wb[i] = memnew(Thread);
- threads_wb[i]->start(_digest_job_queue, &job_queue);
- }
- _digest_job_queue(&job_queue);
-
- for (int i = 0; i < num_job_threads; i++) {
- threads_wb[i]->wait_to_finish();
- memdelete(threads_wb[i]);
- }
- }
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
}
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/denoise/config.py b/modules/denoise/config.py
index 3aa840acb0..521115dae5 100644
--- a/modules/denoise/config.py
+++ b/modules/denoise/config.py
@@ -4,7 +4,7 @@ def can_build(env, platform):
# It's also only relevant for tools build and desktop platforms,
# as doing lightmap generation and denoising on Android or HTML5
# would be a bit far-fetched.
- desktop_platforms = ["linuxbsd", "osx", "windows"]
+ desktop_platforms = ["linuxbsd", "macos", "windows"]
supported_arch = env["bits"] == "64"
if env["arch"] == "arm64":
supported_arch = False
diff --git a/modules/enet/enet_multiplayer_peer.cpp b/modules/enet/enet_multiplayer_peer.cpp
index cd94cc9425..dfdd08c9f4 100644
--- a/modules/enet/enet_multiplayer_peer.cpp
+++ b/modules/enet/enet_multiplayer_peer.cpp
@@ -441,15 +441,15 @@ Error ENetMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size
channel = SYSCH_MAX + transfer_channel - 1;
} else {
switch (get_transfer_mode()) {
- case Multiplayer::TRANSFER_MODE_UNRELIABLE: {
+ case TRANSFER_MODE_UNRELIABLE: {
packet_flags = ENET_PACKET_FLAG_UNSEQUENCED | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
channel = SYSCH_UNRELIABLE;
} break;
- case Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED: {
+ case TRANSFER_MODE_UNRELIABLE_ORDERED: {
packet_flags = ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
channel = SYSCH_UNRELIABLE;
} break;
- case Multiplayer::TRANSFER_MODE_RELIABLE: {
+ case TRANSFER_MODE_RELIABLE: {
packet_flags = ENET_PACKET_FLAG_RELIABLE;
channel = SYSCH_RELIABLE;
} break;
diff --git a/modules/enet/enet_multiplayer_peer.h b/modules/enet/enet_multiplayer_peer.h
index 18eca18e51..3152068d46 100644
--- a/modules/enet/enet_multiplayer_peer.h
+++ b/modules/enet/enet_multiplayer_peer.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NETWORKED_MULTIPLAYER_ENET_H
-#define NETWORKED_MULTIPLAYER_ENET_H
+#ifndef ENET_MULTIPLAYER_PEER_H
+#define ENET_MULTIPLAYER_PEER_H
#include "core/crypto/crypto.h"
-#include "core/multiplayer/multiplayer_peer.h"
+#include "scene/main/multiplayer_peer.h"
#include "enet_connection.h"
#include <enet/enet.h>
@@ -135,4 +135,4 @@ public:
~ENetMultiplayerPeer();
};
-#endif // NETWORKED_MULTIPLAYER_ENET_H
+#endif // ENET_MULTIPLAYER_PEER_H
diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub
index 4b2ea6faa5..8efcd72fb6 100644
--- a/modules/freetype/SCsub
+++ b/modules/freetype/SCsub
@@ -58,22 +58,23 @@ if env["builtin_freetype"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- thirdparty_brotli_dir = "#thirdparty/brotli/"
- thirdparty_brotli_sources = [
- "common/constants.c",
- "common/context.c",
- "common/dictionary.c",
- "common/platform.c",
- "common/shared_dictionary.c",
- "common/transform.c",
- "dec/bit_reader.c",
- "dec/decode.c",
- "dec/huffman.c",
- "dec/state.c",
- ]
- thirdparty_sources += [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
- env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
- env_freetype.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
+ if env["brotli"]:
+ thirdparty_brotli_dir = "#thirdparty/brotli/"
+ thirdparty_brotli_sources = [
+ "common/constants.c",
+ "common/context.c",
+ "common/dictionary.c",
+ "common/platform.c",
+ "common/shared_dictionary.c",
+ "common/transform.c",
+ "dec/bit_reader.c",
+ "dec/decode.c",
+ "dec/huffman.c",
+ "dec/state.c",
+ ]
+ thirdparty_sources += [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
+ env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
+ env_freetype.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
if env.get("use_ubsan") or env.get("use_asan") or env.get("use_tsan") or env.get("use_lsan") or env.get("use_msan"):
env_freetype.Append(CPPDEFINES=["BROTLI_BUILD_PORTABLE"])
diff --git a/modules/freetype/config.py b/modules/freetype/config.py
index d22f9454ed..c0586d5536 100644
--- a/modules/freetype/config.py
+++ b/modules/freetype/config.py
@@ -2,5 +2,13 @@ def can_build(env, platform):
return True
+def get_opts(platform):
+ from SCons.Variables import BoolVariable
+
+ return [
+ BoolVariable("brotli", "Enable Brotli decompressor for WOFF2 fonts support", True),
+ ]
+
+
def configure(env):
pass
diff --git a/modules/freetype/uwpdef.h b/modules/freetype/uwpdef.h
index 05aaae61b5..f85f293171 100644
--- a/modules/freetype/uwpdef.h
+++ b/modules/freetype/uwpdef.h
@@ -28,6 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef UWPDEF_H
+#define UWPDEF_H
+
// "generic" is a reserved keyword in C++/CX code
// this avoids the errors in the variable name from Freetype code
#define generic freetype_generic
+
+#endif // UWPDEF_H
diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py
index 61ce6185a5..a7d5c406e9 100644
--- a/modules/gdscript/config.py
+++ b/modules/gdscript/config.py
@@ -1,4 +1,5 @@
def can_build(env, platform):
+ env.module_add_dependencies("gdscript", ["jsonrpc", "websocket"], True)
return True
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 70151c4d21..10cf783e73 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -144,6 +144,7 @@
[/codeblock]
[b]Important:[/b] The path must be absolute, a local path will just return [code]null[/code].
This method is a simplified version of [method ResourceLoader.load], which can be used for more advanced scenarios.
+ [b]Note:[/b] You have to import the files into the engine first to load them using [method load]. If you want to load [Image]s at run-time, you may use [method Image.load]. If you want to import audio files, you can use the snippet described in [member AudioStreamMP3.data].
</description>
</method>
<method name="preload">
@@ -257,4 +258,162 @@
[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" qualifiers="vararg">
+ <return type="void" />
+ <argument index="0" name="hints" type="String" default="&quot;&quot;" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_file" qualifiers="vararg">
+ <return type="void" />
+ <argument index="0" name="filter" type="String" default="&quot;&quot;" />
+ <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="&quot;&quot;" />
+ <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="&quot;&quot;" />
+ <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="&quot;&quot;" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_placeholder">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_range" qualifiers="vararg">
+ <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="1.0" />
+ <argument index="3" name="extra_hints" type="String" default="&quot;&quot;" />
+ <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="&quot;&quot;" />
+ <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="&quot;&quot;" />
+ <argument index="1" name="sync" type="String" default="&quot;&quot;" />
+ <argument index="2" name="transfer_mode" type="String" default="&quot;&quot;" />
+ <argument index="3" name="transfer_channel" type="int" default="0" />
+ <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/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index b86e9b386d..a23f19de85 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -55,7 +55,9 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
bool in_function_args = false;
bool in_member_variable = false;
bool in_node_path = false;
+ bool in_node_ref = false;
bool in_annotation = false;
+ bool in_string_name = false;
bool is_hex_notation = false;
bool is_bin_notation = false;
bool expect_type = false;
@@ -165,6 +167,12 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
if (in_node_path && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) {
region_color = node_path_color;
}
+ if (in_node_ref && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) {
+ region_color = node_ref_color;
+ }
+ if (in_string_name && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) {
+ region_color = string_name_color;
+ }
prev_color = region_color;
highlighter_info["color"] = region_color;
@@ -387,24 +395,42 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
in_member_variable = false;
}
- if (!in_node_path && in_region == -1 && (str[j] == '$' || str[j] == '%')) {
+ if (!in_node_path && in_region == -1 && (str[j] == '^')) {
in_node_path = true;
} else if (in_region != -1 || (is_a_symbol && str[j] != '/' && str[j] != '%')) {
in_node_path = false;
}
+ if (!in_node_ref && in_region == -1 && (str[j] == '$' || str[j] == '%')) {
+ in_node_ref = true;
+ } else if (in_region != -1 || (is_a_symbol && str[j] != '/' && str[j] != '%')) {
+ in_node_ref = false;
+ }
+
if (!in_annotation && in_region == -1 && str[j] == '@') {
in_annotation = true;
} else if (in_region != -1 || is_a_symbol) {
in_annotation = false;
}
+ if (!in_string_name && in_region == -1 && str[j] == '&') {
+ in_string_name = true;
+ } else if (in_region != -1 || is_a_symbol) {
+ in_string_name = false;
+ }
+
if (in_node_path) {
next_type = NODE_PATH;
color = node_path_color;
+ } else if (in_node_ref) {
+ next_type = NODE_REF;
+ color = node_ref_color;
} else if (in_annotation) {
next_type = ANNOTATION;
color = annotation_color;
+ } else if (in_string_name) {
+ next_type = STRING_NAME;
+ color = string_name_color;
} else if (in_keyword) {
next_type = KEYWORD;
color = keyword_color;
@@ -592,17 +618,23 @@ void GDScriptSyntaxHighlighter::_update_cache() {
if (godot_2_theme || EditorSettings::get_singleton()->is_dark_theme()) {
function_definition_color = Color(0.4, 0.9, 1.0);
- node_path_color = Color(0.39, 0.76, 0.35);
+ node_path_color = Color(0.72, 0.77, 0.49);
+ node_ref_color = Color(0.39, 0.76, 0.35);
annotation_color = Color(1.0, 0.7, 0.45);
+ string_name_color = Color(1.0, 0.66, 0.72);
} else {
- function_definition_color = Color(0.0, 0.65, 0.73);
- node_path_color = Color(0.32, 0.55, 0.29);
- annotation_color = Color(0.8, 0.5, 0.25);
+ function_definition_color = Color(0, 0.6, 0.6);
+ node_path_color = Color(0.18, 0.55, 0);
+ node_ref_color = Color(0.0, 0.5, 0);
+ annotation_color = Color(0.8, 0.37, 0);
+ string_name_color = Color(0.8, 0.46, 0.52);
}
EDITOR_DEF("text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color);
EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_path_color", node_path_color);
+ EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_reference_color", node_ref_color);
EDITOR_DEF("text_editor/theme/highlighting/gdscript/annotation_color", annotation_color);
+ EDITOR_DEF("text_editor/theme/highlighting/gdscript/string_name_color", string_name_color);
if (text_edit_color_theme == "Default" || godot_2_theme) {
EditorSettings::get_singleton()->set_initial_value(
"text_editor/theme/highlighting/gdscript/function_definition_color",
@@ -613,14 +645,24 @@ void GDScriptSyntaxHighlighter::_update_cache() {
node_path_color,
true);
EditorSettings::get_singleton()->set_initial_value(
+ "text_editor/theme/highlighting/gdscript/node_reference_color",
+ node_ref_color,
+ true);
+ EditorSettings::get_singleton()->set_initial_value(
"text_editor/theme/highlighting/gdscript/annotation_color",
annotation_color,
true);
+ EditorSettings::get_singleton()->set_initial_value(
+ "text_editor/theme/highlighting/gdscript/string_name_color",
+ string_name_color,
+ true);
}
function_definition_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/function_definition_color");
node_path_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_path_color");
+ node_ref_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_reference_color");
annotation_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/annotation_color");
+ string_name_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/string_name_color");
type_color = EDITOR_GET("text_editor/theme/highlighting/base_type_color");
}
diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h
index 92764e3891..7987582f07 100644
--- a/modules/gdscript/editor/gdscript_highlighter.h
+++ b/modules/gdscript/editor/gdscript_highlighter.h
@@ -54,7 +54,9 @@ private:
NONE,
REGION,
NODE_PATH,
+ NODE_REF,
ANNOTATION,
+ STRING_NAME,
SYMBOL,
NUMBER,
FUNCTION,
@@ -74,7 +76,9 @@ private:
Color number_color;
Color member_color;
Color node_path_color;
+ Color node_ref_color;
Color annotation_color;
+ Color string_name_color;
Color type_color;
void add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false);
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index e6aeef2fd1..dc6bfbb034 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -51,7 +51,7 @@
#endif
#ifdef TOOLS_ENABLED
-#include "editor/editor_settings.h"
+#include "editor/editor_paths.h"
#endif
///////////////////////////
@@ -278,6 +278,11 @@ void GDScript::_get_script_method_list(List<MethodInfo> *r_list, bool p_include_
GDScriptFunction *func = E.value;
MethodInfo mi;
mi.name = E.key;
+
+ if (func->is_static()) {
+ mi.flags |= METHOD_FLAG_STATIC;
+ }
+
for (int i = 0; i < func->get_argument_count(); i++) {
PropertyInfo arginfo = func->get_argument_type(i);
#ifdef TOOLS_ENABLED
@@ -320,16 +325,23 @@ void GDScript::_get_script_property_list(List<PropertyInfo> *r_list, bool p_incl
for (int i = 0; i < msort.size(); i++) {
props.push_front(sptr->member_info[msort[i].name]);
}
+
+#ifdef TOOLS_ENABLED
+ r_list->push_back(sptr->get_class_category());
+#endif // TOOLS_ENABLED
+
+ for (const PropertyInfo &E : props) {
+ r_list->push_back(E);
+ }
+
+ props.clear();
+
if (!p_include_base) {
break;
}
sptr = sptr->_base;
}
-
- for (const PropertyInfo &E : props) {
- r_list->push_back(E);
- }
}
void GDScript::get_script_property_list(List<PropertyInfo> *r_list) const {
@@ -429,10 +441,6 @@ void GDScript::set_source_code(const String &p_code) {
#ifdef TOOLS_ENABLED
void GDScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) {
- if (base_cache.is_valid()) {
- base_cache->_update_exports_values(values, propnames);
- }
-
for (const KeyValue<StringName, Variant> &E : member_default_values_cache) {
values[E.key] = E.value;
}
@@ -440,6 +448,10 @@ void GDScript::_update_exports_values(HashMap<StringName, Variant> &values, List
for (const PropertyInfo &E : members_cache) {
propnames.push_back(E);
}
+
+ if (base_cache.is_valid()) {
+ base_cache->_update_exports_values(values, propnames);
+ }
}
void GDScript::_add_doc(const DocData::ClassDoc &p_inner_class) {
@@ -536,6 +548,9 @@ void GDScript::_update_doc() {
List<PropertyInfo> props;
_get_script_property_list(&props, false);
for (int i = 0; i < props.size(); i++) {
+ if (props[i].usage & PROPERTY_USAGE_CATEGORY || props[i].usage & PROPERTY_USAGE_GROUP || props[i].usage & PROPERTY_USAGE_SUBGROUP) {
+ continue;
+ }
ScriptMemberInfo scr_member_info;
scr_member_info.propinfo = props[i];
scr_member_info.propinfo.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
@@ -695,6 +710,8 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
member_default_values_cache.clear();
_signals.clear();
+ members_cache.push_back(get_class_category());
+
for (int i = 0; i < c->members.size(); i++) {
const GDScriptParser::ClassNode::Member &member = c->members[i];
@@ -720,6 +737,9 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
}
_signals[member.signal->identifier->name] = parameters_names;
} break;
+ case GDScriptParser::ClassNode::Member::GROUP: {
+ members_cache.push_back(member.annotation->export_info);
+ } break;
default:
break; // Nothing.
}
@@ -840,7 +860,7 @@ Error GDScript::reload(bool p_keep_state) {
// Loading a template, don't parse.
#ifdef TOOLS_ENABLED
- if (EditorSettings::get_singleton() && basedir.begins_with(EditorSettings::get_singleton()->get_project_script_templates_dir())) {
+ if (EditorPaths::get_singleton() && basedir.begins_with(EditorPaths::get_singleton()->get_project_script_templates_dir())) {
return OK;
}
#endif
@@ -867,7 +887,7 @@ Error GDScript::reload(bool p_keep_state) {
}
// TODO: Show all error messages.
_err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_errors().front()->get().line, ("Parse Error: " + parser.get_errors().front()->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT);
- ERR_FAIL_V(ERR_PARSE_ERROR);
+ return ERR_PARSE_ERROR;
}
GDScriptAnalyzer analyzer(&parser);
@@ -883,7 +903,7 @@ Error GDScript::reload(bool p_keep_state) {
_err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), e->get().line, ("Parse Error: " + e->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT);
e = e->next();
}
- ERR_FAIL_V(ERR_PARSE_ERROR);
+ return ERR_PARSE_ERROR;
}
bool can_run = ScriptServer::is_scripting_enabled() || parser.is_tool();
@@ -901,7 +921,7 @@ Error GDScript::reload(bool p_keep_state) {
GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error());
}
_err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), false, ERR_HANDLER_SCRIPT);
- ERR_FAIL_V(ERR_COMPILATION_FAILED);
+ return ERR_COMPILATION_FAILED;
} else {
return err;
}
@@ -946,8 +966,8 @@ void GDScript::get_members(HashSet<StringName> *p_members) {
}
}
-const Vector<Multiplayer::RPCConfig> GDScript::get_rpc_methods() const {
- return rpc_functions;
+const Variant GDScript::get_rpc_config() const {
+ return rpc_config;
}
Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
@@ -1050,7 +1070,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.");
}
@@ -1204,9 +1224,9 @@ void GDScript::_save_orphaned_subclasses() {
void GDScript::_init_rpc_methods_properties() {
// Copy the base rpc methods so we don't mask their IDs.
- rpc_functions.clear();
+ rpc_config.clear();
if (base.is_valid()) {
- rpc_functions = base->rpc_functions;
+ rpc_config = base->rpc_config.duplicate();
}
GDScript *cscript = this;
@@ -1214,12 +1234,9 @@ void GDScript::_init_rpc_methods_properties() {
while (cscript) {
// RPC Methods
for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) {
- Multiplayer::RPCConfig config = E.value->get_rpc_config();
- if (config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) {
- config.name = E.value->get_name();
- if (rpc_functions.find(config) == -1) {
- rpc_functions.push_back(config);
- }
+ Variant config = E.value->get_rpc_config();
+ if (config.get_type() != Variant::NIL) {
+ rpc_config[E.value->get_name()] = config;
}
}
@@ -1233,9 +1250,6 @@ void GDScript::_init_rpc_methods_properties() {
cscript = nullptr;
}
}
-
- // Sort so we are 100% that they are always the same.
- rpc_functions.sort_custom<Multiplayer::SortRPCConfig>();
}
GDScript::~GDScript() {
@@ -1400,9 +1414,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
while (sl) {
HashMap<StringName, GDScriptFunction *>::ConstIterator E = sl->member_functions.find(p_name);
if (E) {
- Multiplayer::RPCConfig config;
- config.name = p_name;
- if (sptr->rpc_functions.find(config) != -1) {
+ if (sptr->rpc_config.has(p_name)) {
r_ret = Callable(memnew(GDScriptRPCCallable(this->owner, E->key)));
} else {
r_ret = Callable(this->owner, E->key);
@@ -1510,11 +1522,17 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const
props.push_front(sptr->member_info[msort[i].name]);
}
- sptr = sptr->_base;
- }
+#ifdef TOOLS_ENABLED
+ p_properties->push_back(sptr->get_class_category());
+#endif // TOOLS_ENABLED
+
+ for (const PropertyInfo &prop : props) {
+ p_properties->push_back(prop);
+ }
- for (const PropertyInfo &E : props) {
- p_properties->push_back(E);
+ props.clear();
+
+ sptr = sptr->_base;
}
}
@@ -1524,7 +1542,6 @@ void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
for (const KeyValue<StringName, GDScriptFunction *> &E : sptr->member_functions) {
MethodInfo mi;
mi.name = E.key;
- mi.flags |= METHOD_FLAG_FROM_SCRIPT;
for (int i = 0; i < E.value->get_argument_count(); i++) {
mi.arguments.push_back(PropertyInfo(Variant::NIL, "arg" + itos(i)));
}
@@ -1622,15 +1639,13 @@ ScriptLanguage *GDScriptInstance::get_language() {
return GDScriptLanguage::get_singleton();
}
-const Vector<Multiplayer::RPCConfig> GDScriptInstance::get_rpc_methods() const {
- return script->get_rpc_methods();
+const Variant GDScriptInstance::get_rpc_config() const {
+ return script->get_rpc_config();
}
void GDScriptInstance::reload_members() {
#ifdef DEBUG_ENABLED
- members.resize(script->member_indices.size()); //resize
-
Vector<Variant> new_members;
new_members.resize(script->member_indices.size());
@@ -1642,6 +1657,8 @@ void GDScriptInstance::reload_members() {
}
}
+ members.resize(new_members.size()); //resize
+
//apply
members = new_members;
@@ -2381,7 +2398,7 @@ void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<S
}
}
-Error ResourceFormatSaverGDScript::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaverGDScript::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Ref<GDScript> sqscr = p_resource;
ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER);
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index feb0a237df..5123cccddd 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -87,7 +87,7 @@ class GDScript : public Script {
HashMap<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script.
HashMap<StringName, Ref<GDScript>> subclasses;
HashMap<StringName, Vector<StringName>> _signals;
- Vector<Multiplayer::RPCConfig> rpc_functions;
+ Dictionary rpc_config;
#ifdef TOOLS_ENABLED
@@ -250,7 +250,7 @@ public:
virtual void get_constants(HashMap<StringName, Variant> *p_constants) override;
virtual void get_members(HashSet<StringName> *p_members) override;
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
+ virtual const Variant get_rpc_config() const override;
#ifdef TOOLS_ENABLED
virtual bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@@ -304,7 +304,7 @@ public:
void reload_members();
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const;
+ virtual const Variant get_rpc_config() const;
GDScriptInstance();
~GDScriptInstance();
@@ -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;
@@ -523,7 +524,7 @@ public:
class ResourceFormatSaverGDScript : public ResourceFormatSaver {
public:
- virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
virtual bool recognize(const Ref<Resource> &p_resource) const;
};
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index ea994654bf..a07d4855f3 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;
@@ -3235,12 +3238,12 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid);
if (!valid) {
push_error(vformat(R"(Cannot get member "%s" from "%s".)", p_subscript->attribute->name, p_subscript->base->reduced_value), p_subscript->index);
+ result_type.kind = GDScriptParser::DataType::VARIANT;
} else {
p_subscript->is_constant = true;
p_subscript->reduced_value = value;
result_type = type_from_variant(value, p_subscript);
}
- result_type.kind = GDScriptParser::DataType::VARIANT;
} else {
GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
@@ -3326,8 +3329,11 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
case Variant::VECTOR2I:
case Variant::VECTOR3:
case Variant::VECTOR3I:
+ case Variant::VECTOR4:
+ case Variant::VECTOR4I:
case Variant::TRANSFORM2D:
case Variant::TRANSFORM3D:
+ case Variant::PROJECTION:
error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT &&
index_type.builtin_type != Variant::STRING;
break;
@@ -3390,6 +3396,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
case Variant::PACKED_INT64_ARRAY:
case Variant::VECTOR2I:
case Variant::VECTOR3I:
+ case Variant::VECTOR4I:
result_type.builtin_type = Variant::INT;
break;
// Return float.
@@ -3397,6 +3404,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
case Variant::PACKED_FLOAT64_ARRAY:
case Variant::VECTOR2:
case Variant::VECTOR3:
+ case Variant::VECTOR4:
case Variant::QUATERNION:
result_type.builtin_type = Variant::FLOAT;
break;
@@ -3427,6 +3435,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
break;
// Depends on the index.
case Variant::TRANSFORM3D:
+ case Variant::PROJECTION:
case Variant::PLANE:
case Variant::COLOR:
case Variant::DICTIONARY:
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index 6a1effd680..fa158591fd 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -84,11 +84,14 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type
case Variant::VECTOR3:
case Variant::VECTOR3I:
case Variant::TRANSFORM2D:
+ case Variant::VECTOR4:
+ case Variant::VECTOR4I:
case Variant::PLANE:
case Variant::QUATERNION:
case Variant::AABB:
case Variant::BASIS:
case Variant::TRANSFORM3D:
+ case Variant::PROJECTION:
case Variant::COLOR:
case Variant::STRING_NAME:
case Variant::NODE_PATH:
@@ -155,7 +158,7 @@ void GDScriptByteCodeGenerator::end_parameters() {
function->default_arguments.reverse();
}
-void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) {
+void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) {
function = memnew(GDScriptFunction);
debug_stack = EngineDebugger::is_active();
@@ -453,6 +456,12 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia
case Variant::TRANSFORM2D:
append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM2D, 1);
break;
+ case Variant::VECTOR4:
+ append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3, 1);
+ break;
+ case Variant::VECTOR4I:
+ append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3I, 1);
+ break;
case Variant::PLANE:
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PLANE, 1);
break;
@@ -468,6 +477,9 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia
case Variant::TRANSFORM3D:
append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM3D, 1);
break;
+ case Variant::PROJECTION:
+ append(GDScriptFunction::OPCODE_TYPE_ADJUST_PROJECTION, 1);
+ break;
case Variant::COLOR:
append(GDScriptFunction::OPCODE_TYPE_ADJUST_COLOR, 1);
break;
@@ -1596,7 +1608,7 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
// Typed array.
const GDScriptDataType &element_type = function->return_type.get_container_element_type();
- Variant script = function->return_type.script_type;
+ Variant script = element_type.script_type;
int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2);
diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h
index f4b402fc96..7dd51845df 100644
--- a/modules/gdscript/gdscript_byte_codegen.h
+++ b/modules/gdscript/gdscript_byte_codegen.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GDSCRIPT_BYTE_CODEGEN
-#define GDSCRIPT_BYTE_CODEGEN
+#ifndef GDSCRIPT_BYTE_CODEGEN_H
+#define GDSCRIPT_BYTE_CODEGEN_H
#include "gdscript_codegen.h"
@@ -419,7 +419,7 @@ public:
virtual void start_block() override;
virtual void end_block() override;
- virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) override;
+ virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) override;
virtual GDScriptFunction *write_end() override;
#ifdef DEBUG_ENABLED
@@ -502,4 +502,4 @@ public:
virtual ~GDScriptByteCodeGenerator();
};
-#endif // GDSCRIPT_BYTE_CODEGEN
+#endif // GDSCRIPT_BYTE_CODEGEN_H
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_codegen.h b/modules/gdscript/gdscript_codegen.h
index 81fa265aca..5972481c3a 100644
--- a/modules/gdscript/gdscript_codegen.h
+++ b/modules/gdscript/gdscript_codegen.h
@@ -28,10 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GDSCRIPT_CODEGEN
-#define GDSCRIPT_CODEGEN
+#ifndef GDSCRIPT_CODEGEN_H
+#define GDSCRIPT_CODEGEN_H
-#include "core/multiplayer/multiplayer.h"
#include "core/string/string_name.h"
#include "core/variant/variant.h"
#include "gdscript_function.h"
@@ -80,7 +79,7 @@ public:
virtual void start_block() = 0;
virtual void end_block() = 0;
- virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Multiplayer::RPCConfig p_rpc_config, const GDScriptDataType &p_return_type) = 0;
+ virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) = 0;
virtual GDScriptFunction *write_end() = 0;
#ifdef DEBUG_ENABLED
@@ -163,4 +162,4 @@ public:
virtual ~GDScriptCodeGenerator() {}
};
-#endif // GDSCRIPT_CODEGEN
+#endif // GDSCRIPT_CODEGEN_H
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 6055d3df33..00e8223b9a 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -43,7 +43,7 @@ bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringN
return false;
}
- if (codegen.locals.has(p_name)) {
+ if (codegen.parameters.has(p_name) || codegen.locals.has(p_name)) {
return false; //shadowed
}
@@ -1975,7 +1975,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
StringName func_name;
bool is_static = false;
- Multiplayer::RPCConfig rpc_config;
+ Variant rpc_config;
GDScriptDataType return_type;
return_type.has_type = true;
return_type.kind = GDScriptDataType::BUILTIN;
@@ -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_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp
index 726f0efe2b..b38c7c6699 100644
--- a/modules/gdscript/gdscript_disassembler.cpp
+++ b/modules/gdscript/gdscript_disassembler.cpp
@@ -639,10 +639,13 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
DISASSEMBLE_PTRCALL(VECTOR3);
DISASSEMBLE_PTRCALL(VECTOR3I);
DISASSEMBLE_PTRCALL(TRANSFORM2D);
+ DISASSEMBLE_PTRCALL(VECTOR4);
+ DISASSEMBLE_PTRCALL(VECTOR4I);
DISASSEMBLE_PTRCALL(PLANE);
DISASSEMBLE_PTRCALL(AABB);
DISASSEMBLE_PTRCALL(BASIS);
DISASSEMBLE_PTRCALL(TRANSFORM3D);
+ DISASSEMBLE_PTRCALL(PROJECTION);
DISASSEMBLE_PTRCALL(COLOR);
DISASSEMBLE_PTRCALL(STRING_NAME);
DISASSEMBLE_PTRCALL(NODE_PATH);
@@ -1013,11 +1016,14 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
DISASSEMBLE_TYPE_ADJUST(VECTOR3);
DISASSEMBLE_TYPE_ADJUST(VECTOR3I);
DISASSEMBLE_TYPE_ADJUST(TRANSFORM2D);
+ DISASSEMBLE_TYPE_ADJUST(VECTOR4);
+ DISASSEMBLE_TYPE_ADJUST(VECTOR4I);
DISASSEMBLE_TYPE_ADJUST(PLANE);
DISASSEMBLE_TYPE_ADJUST(QUATERNION);
DISASSEMBLE_TYPE_ADJUST(AABB);
DISASSEMBLE_TYPE_ADJUST(BASIS);
DISASSEMBLE_TYPE_ADJUST(TRANSFORM3D);
+ DISASSEMBLE_TYPE_ADJUST(PROJECTION);
DISASSEMBLE_TYPE_ADJUST(COLOR);
DISASSEMBLE_TYPE_ADJUST(STRING_NAME);
DISASSEMBLE_TYPE_ADJUST(NODE_PATH);
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 474c8094f2..d943974ce4 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;
}
@@ -1461,11 +1473,16 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
if (callee_type == GDScriptParser::Node::IDENTIFIER || call->is_super) {
// Simple call, so base is 'self'.
if (p_context.current_class) {
- base.type.kind = GDScriptParser::DataType::CLASS;
- base.type.type_source = GDScriptParser::DataType::INFERRED;
- base.type.is_constant = true;
- base.type.class_type = p_context.current_class;
- base.value = p_context.base;
+ if (call->is_super) {
+ base.type = p_context.current_class->base_type;
+ base.value = p_context.base;
+ } else {
+ base.type.kind = GDScriptParser::DataType::CLASS;
+ base.type.type_source = GDScriptParser::DataType::INFERRED;
+ base.type.is_constant = true;
+ base.type.class_type = p_context.current_class;
+ base.value = p_context.base;
+ }
} else {
break;
}
@@ -1843,7 +1860,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 +1908,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;
@@ -1992,8 +2009,8 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
return false;
}
- // Check autoloads.
- if (ProjectSettings::get_singleton()->has_autoload(p_identifier)) {
+ // Check global variables (including autoloads).
+ if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(p_identifier)) {
r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[p_identifier]);
return true;
}
@@ -2028,7 +2045,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 +2070,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 +2099,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 +2426,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 +3395,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_function.h b/modules/gdscript/gdscript_function.h
index 3f1265679b..e44038d6da 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -273,11 +273,14 @@ public:
OPCODE_CALL_PTRCALL_VECTOR3,
OPCODE_CALL_PTRCALL_VECTOR3I,
OPCODE_CALL_PTRCALL_TRANSFORM2D,
+ OPCODE_CALL_PTRCALL_VECTOR4,
+ OPCODE_CALL_PTRCALL_VECTOR4I,
OPCODE_CALL_PTRCALL_PLANE,
OPCODE_CALL_PTRCALL_QUATERNION,
OPCODE_CALL_PTRCALL_AABB,
OPCODE_CALL_PTRCALL_BASIS,
OPCODE_CALL_PTRCALL_TRANSFORM3D,
+ OPCODE_CALL_PTRCALL_PROJECTION,
OPCODE_CALL_PTRCALL_COLOR,
OPCODE_CALL_PTRCALL_STRING_NAME,
OPCODE_CALL_PTRCALL_NODE_PATH,
@@ -363,11 +366,14 @@ public:
OPCODE_TYPE_ADJUST_VECTOR3,
OPCODE_TYPE_ADJUST_VECTOR3I,
OPCODE_TYPE_ADJUST_TRANSFORM2D,
+ OPCODE_TYPE_ADJUST_VECTOR4,
+ OPCODE_TYPE_ADJUST_VECTOR4I,
OPCODE_TYPE_ADJUST_PLANE,
OPCODE_TYPE_ADJUST_QUATERNION,
OPCODE_TYPE_ADJUST_AABB,
OPCODE_TYPE_ADJUST_BASIS,
OPCODE_TYPE_ADJUST_TRANSFORM3D,
+ OPCODE_TYPE_ADJUST_PROJECTION,
OPCODE_TYPE_ADJUST_COLOR,
OPCODE_TYPE_ADJUST_STRING_NAME,
OPCODE_TYPE_ADJUST_NODE_PATH,
@@ -471,7 +477,7 @@ private:
int _initial_line = 0;
bool _static = false;
- Multiplayer::RPCConfig rpc_config;
+ Variant rpc_config;
GDScript *_script = nullptr;
@@ -593,7 +599,7 @@ public:
void disassemble(const Vector<String> &p_code_lines) const;
#endif
- _FORCE_INLINE_ Multiplayer::RPCConfig get_rpc_config() const { return rpc_config; }
+ _FORCE_INLINE_ const Variant get_rpc_config() const { return rpc_config; }
GDScriptFunction();
~GDScriptFunction();
};
diff --git a/modules/gdscript/gdscript_lambda_callable.h b/modules/gdscript/gdscript_lambda_callable.h
index 248176e32c..1954089983 100644
--- a/modules/gdscript/gdscript_lambda_callable.h
+++ b/modules/gdscript/gdscript_lambda_callable.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GDSCRIPT_LAMBDA_CALLABLE
-#define GDSCRIPT_LAMBDA_CALLABLE
+#ifndef GDSCRIPT_LAMBDA_CALLABLE_H
+#define GDSCRIPT_LAMBDA_CALLABLE_H
#include "core/object/ref_counted.h"
#include "core/templates/vector.h"
@@ -87,4 +87,4 @@ public:
virtual ~GDScriptLambdaSelfCallable() = default;
};
-#endif // GDSCRIPT_LAMBDA_CALLABLE
+#endif // GDSCRIPT_LAMBDA_CALLABLE_H
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index ca430b0f72..6f5397e1a3 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -35,6 +35,7 @@
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
#include "gdscript.h"
+#include "scene/main/multiplayer_api.h"
#ifdef DEBUG_ENABLED
#include "core/os/os.h"
@@ -60,11 +61,14 @@ Variant::Type GDScriptParser::get_builtin_type(const StringName &p_type) {
builtin_types["Transform2D"] = Variant::TRANSFORM2D;
builtin_types["Vector3"] = Variant::VECTOR3;
builtin_types["Vector3i"] = Variant::VECTOR3I;
+ builtin_types["Vector4"] = Variant::VECTOR4;
+ builtin_types["Vector4i"] = Variant::VECTOR4I;
builtin_types["AABB"] = Variant::AABB;
builtin_types["Plane"] = Variant::PLANE;
builtin_types["Quaternion"] = Variant::QUATERNION;
builtin_types["Basis"] = Variant::BASIS;
builtin_types["Transform3D"] = Variant::TRANSFORM3D;
+ builtin_types["Projection"] = Variant::PROJECTION;
builtin_types["Color"] = Variant::COLOR;
builtin_types["RID"] = Variant::RID;
builtin_types["Object"] = Variant::OBJECT;
@@ -105,6 +109,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?
@@ -113,27 +121,32 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@onready"), AnnotationInfo::VARIABLE, &GDScriptParser::onready_annotation);
// Export annotations.
register_annotation(MethodInfo("@export"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>);
- register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::INT>, 0, true);
- register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, 1, true);
+ register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::INT>, varray(), true);
+ register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, varray(""), true);
register_annotation(MethodInfo("@export_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_DIR, Variant::STRING>);
- register_annotation(MethodInfo("@export_global_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_GLOBAL_FILE, Variant::STRING>, 1, true);
+ register_annotation(MethodInfo("@export_global_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_GLOBAL_FILE, Variant::STRING>, varray(""), true);
register_annotation(MethodInfo("@export_global_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_GLOBAL_DIR, Variant::STRING>);
register_annotation(MethodInfo("@export_multiline"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_MULTILINE_TEXT, Variant::STRING>);
register_annotation(MethodInfo("@export_placeholder"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_PLACEHOLDER_TEXT, Variant::STRING>);
- register_annotation(MethodInfo("@export_range", PropertyInfo(Variant::FLOAT, "min"), PropertyInfo(Variant::FLOAT, "max"), PropertyInfo(Variant::FLOAT, "step"), PropertyInfo(Variant::STRING, "slider1"), PropertyInfo(Variant::STRING, "slider2"), PropertyInfo(Variant::STRING, "slider3")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_RANGE, Variant::FLOAT>, 4);
- register_annotation(MethodInfo("@export_exp_easing", PropertyInfo(Variant::STRING, "hint1"), PropertyInfo(Variant::STRING, "hint2")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_EXP_EASING, Variant::FLOAT>, 2);
+ register_annotation(MethodInfo("@export_range", PropertyInfo(Variant::FLOAT, "min"), PropertyInfo(Variant::FLOAT, "max"), PropertyInfo(Variant::FLOAT, "step"), PropertyInfo(Variant::STRING, "extra_hints")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_RANGE, Variant::FLOAT>, varray(1.0, ""), true);
+ register_annotation(MethodInfo("@export_exp_easing", PropertyInfo(Variant::STRING, "hints")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_EXP_EASING, Variant::FLOAT>, varray(""), true);
register_annotation(MethodInfo("@export_color_no_alpha"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_COLOR_NO_ALPHA, Variant::COLOR>);
- register_annotation(MethodInfo("@export_node_path", PropertyInfo(Variant::STRING, "type")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NODE_PATH_VALID_TYPES, Variant::NODE_PATH>, 1, true);
- register_annotation(MethodInfo("@export_flags", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FLAGS, Variant::INT>, 0, true);
+ register_annotation(MethodInfo("@export_node_path", PropertyInfo(Variant::STRING, "type")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NODE_PATH_VALID_TYPES, Variant::NODE_PATH>, varray(""), true);
+ register_annotation(MethodInfo("@export_flags", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FLAGS, Variant::INT>, varray(), true);
register_annotation(MethodInfo("@export_flags_2d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_RENDER, Variant::INT>);
register_annotation(MethodInfo("@export_flags_2d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_PHYSICS, Variant::INT>);
register_annotation(MethodInfo("@export_flags_2d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_NAVIGATION, Variant::INT>);
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>);
- 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);
+ // 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>, varray(""));
+ register_annotation(MethodInfo("@export_subgroup", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_SUBGROUP>, varray(""));
+ // 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, varray(), 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);
+ 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::rpc_annotation, varray("", "", "", 0), true);
}
GDScriptParser::~GDScriptParser() {
@@ -153,6 +166,7 @@ void GDScriptParser::clear() {
for_completion = false;
errors.clear();
multiline_stack.clear();
+ nodes_in_progress.clear();
}
void GDScriptParser::push_error(const String &p_message, const Node *p_origin) {
@@ -404,6 +418,9 @@ GDScriptTokenizer::Token GDScriptParser::advance() {
push_error(current.literal);
current = tokenizer.scan();
}
+ for (Node *n : nodes_in_progress) {
+ update_extents(n);
+ }
return previous;
}
@@ -519,9 +536,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 +552,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 +569,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 +580,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 +602,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 {
@@ -589,6 +617,7 @@ void GDScriptParser::parse_program() {
}
parse_class_body(true);
+ complete_extents(head);
#ifdef TOOLS_ENABLED
for (const KeyValue<int, GDScriptTokenizer::CommentData> &E : tokenizer.get_comments()) {
@@ -629,6 +658,7 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
if (multiline && !consume(GDScriptTokenizer::Token::INDENT, R"(Expected indented block after class declaration.)")) {
current_class = previous_class;
+ complete_extents(n_class);
return n_class;
}
@@ -641,6 +671,7 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
}
parse_class_body(multiline);
+ complete_extents(n_class);
if (multiline) {
consume(GDScriptTokenizer::Token::DEDENT, R"(Missing unindent at the end of the class body.)");
@@ -807,9 +838,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;
}
@@ -841,11 +881,13 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable() {
}
GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_property) {
+ VariableNode *variable = alloc_node<VariableNode>();
+
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected variable name after "var".)")) {
+ complete_extents(variable);
return nullptr;
}
- VariableNode *variable = alloc_node<VariableNode>();
variable->identifier = parse_identifier();
variable->export_info.name = variable->identifier->name;
@@ -853,10 +895,10 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper
if (check(GDScriptTokenizer::Token::NEWLINE)) {
if (p_allow_property) {
advance();
-
return parse_property(variable, true);
} else {
push_error(R"(Expected type after ":")");
+ complete_extents(variable);
return nullptr;
}
} else if (check((GDScriptTokenizer::Token::EQUAL))) {
@@ -895,6 +937,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper
}
}
+ complete_extents(variable);
end_statement("variable declaration");
return variable;
@@ -903,6 +946,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper
GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_variable, bool p_need_indent) {
if (p_need_indent) {
if (!consume(GDScriptTokenizer::Token::INDENT, R"(Expected indented block for property after ":".)")) {
+ complete_extents(p_variable);
return nullptr;
}
}
@@ -912,6 +956,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var
make_completion_context(COMPLETION_PROPERTY_DECLARATION, property);
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected "get" or "set" for property declaration.)")) {
+ complete_extents(p_variable);
return nullptr;
}
@@ -968,6 +1013,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var
}
function = parse_identifier();
}
+ complete_extents(p_variable);
if (p_variable->property == VariableNode::PROP_SETGET) {
end_statement("property declaration");
@@ -982,37 +1028,37 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var
void GDScriptParser::parse_property_setter(VariableNode *p_variable) {
switch (p_variable->property) {
case VariableNode::PROP_INLINE: {
- consume(GDScriptTokenizer::Token::PARENTHESIS_OPEN, R"(Expected "(" after "set".)");
- if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected parameter name after "(".)")) {
- p_variable->setter_parameter = parse_identifier();
- }
- consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after parameter name.)*");
- consume(GDScriptTokenizer::Token::COLON, R"*(Expected ":" after ")".)*");
-
+ FunctionNode *function = alloc_node<FunctionNode>();
IdentifierNode *identifier = alloc_node<IdentifierNode>();
+ complete_extents(identifier);
identifier->name = "@" + p_variable->identifier->name + "_setter";
-
- FunctionNode *function = alloc_node<FunctionNode>();
function->identifier = identifier;
- FunctionNode *previous_function = current_function;
- current_function = function;
+ consume(GDScriptTokenizer::Token::PARENTHESIS_OPEN, R"(Expected "(" after "set".)");
ParameterNode *parameter = alloc_node<ParameterNode>();
- parameter->identifier = p_variable->setter_parameter;
-
- if (parameter->identifier != nullptr) {
+ if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected parameter name after "(".)")) {
+ reset_extents(parameter, previous);
+ p_variable->setter_parameter = parse_identifier();
+ parameter->identifier = p_variable->setter_parameter;
function->parameters_indices[parameter->identifier->name] = 0;
function->parameters.push_back(parameter);
+ }
+ complete_extents(parameter);
+
+ consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after parameter name.)*");
+ consume(GDScriptTokenizer::Token::COLON, R"*(Expected ":" after ")".)*");
+ FunctionNode *previous_function = current_function;
+ current_function = function;
+ if (p_variable->setter_parameter != nullptr) {
SuiteNode *body = alloc_node<SuiteNode>();
body->add_local(parameter, function);
-
function->body = parse_suite("setter declaration", body);
p_variable->setter = function;
}
-
current_function = previous_function;
+ complete_extents(function);
break;
}
case VariableNode::PROP_SETGET:
@@ -1030,12 +1076,13 @@ void GDScriptParser::parse_property_setter(VariableNode *p_variable) {
void GDScriptParser::parse_property_getter(VariableNode *p_variable) {
switch (p_variable->property) {
case VariableNode::PROP_INLINE: {
+ FunctionNode *function = alloc_node<FunctionNode>();
+
consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "get".)");
IdentifierNode *identifier = alloc_node<IdentifierNode>();
+ complete_extents(identifier);
identifier->name = "@" + p_variable->identifier->name + "_getter";
-
- FunctionNode *function = alloc_node<FunctionNode>();
function->identifier = identifier;
FunctionNode *previous_function = current_function;
@@ -1043,9 +1090,10 @@ void GDScriptParser::parse_property_getter(VariableNode *p_variable) {
SuiteNode *body = alloc_node<SuiteNode>();
function->body = parse_suite("getter declaration", body);
-
p_variable->getter = function;
+
current_function = previous_function;
+ complete_extents(function);
break;
}
case VariableNode::PROP_SETGET:
@@ -1061,11 +1109,12 @@ void GDScriptParser::parse_property_getter(VariableNode *p_variable) {
}
GDScriptParser::ConstantNode *GDScriptParser::parse_constant() {
+ ConstantNode *constant = alloc_node<ConstantNode>();
+
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected constant name after "const".)")) {
return nullptr;
}
- ConstantNode *constant = alloc_node<ConstantNode>();
constant->identifier = parse_identifier();
if (match(GDScriptTokenizer::Token::COLON)) {
@@ -1084,12 +1133,15 @@ GDScriptParser::ConstantNode *GDScriptParser::parse_constant() {
if (constant->initializer == nullptr) {
push_error(R"(Expected initializer expression for constant.)");
+ complete_extents(constant);
return nullptr;
}
} else {
+ complete_extents(constant);
return nullptr;
}
+ complete_extents(constant);
end_statement("constant declaration");
return constant;
@@ -1119,15 +1171,18 @@ GDScriptParser::ParameterNode *GDScriptParser::parse_parameter() {
parameter->default_value = parse_expression(false);
}
+ complete_extents(parameter);
return parameter;
}
GDScriptParser::SignalNode *GDScriptParser::parse_signal() {
+ SignalNode *signal = alloc_node<SignalNode>();
+
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected signal name after "signal".)")) {
+ complete_extents(signal);
return nullptr;
}
- SignalNode *signal = alloc_node<SignalNode>();
signal->identifier = parse_identifier();
if (check(GDScriptTokenizer::Token::PARENTHESIS_OPEN)) {
@@ -1159,6 +1214,7 @@ GDScriptParser::SignalNode *GDScriptParser::parse_signal() {
consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected closing ")" after signal parameters.)*");
}
+ complete_extents(signal);
end_statement("signal declaration");
return signal;
@@ -1270,6 +1326,7 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() {
}
#endif // TOOLS_ENABLED
+ complete_extents(enum_node);
end_statement("enum");
return enum_node;
@@ -1321,19 +1378,22 @@ void GDScriptParser::parse_function_signature(FunctionNode *p_function, SuiteNod
}
GDScriptParser::FunctionNode *GDScriptParser::parse_function() {
+ FunctionNode *function = alloc_node<FunctionNode>();
+
bool _static = false;
if (previous.type == GDScriptTokenizer::Token::STATIC) {
// TODO: Improve message if user uses "static" with "var" or "const"
if (!consume(GDScriptTokenizer::Token::FUNC, R"(Expected "func" after "static".)")) {
+ complete_extents(function);
return nullptr;
}
_static = true;
}
- FunctionNode *function = alloc_node<FunctionNode>();
make_completion_context(COMPLETION_OVERRIDE_METHOD, function);
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected function name after "func".)")) {
+ complete_extents(function);
return nullptr;
}
@@ -1355,6 +1415,7 @@ GDScriptParser::FunctionNode *GDScriptParser::parse_function() {
function->body = parse_suite("function declaration", body);
current_function = previous_function;
+ complete_extents(function);
return function;
}
@@ -1402,6 +1463,7 @@ GDScriptParser::AnnotationNode *GDScriptParser::parse_annotation(uint32_t p_vali
}
pop_completion_call();
}
+ complete_extents(annotation);
match(GDScriptTokenizer::Token::NEWLINE); // Newline after annotation is optional.
@@ -1420,12 +1482,12 @@ void GDScriptParser::clear_unused_annotations() {
annotation_stack.clear();
}
-bool GDScriptParser::register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, int p_optional_arguments, bool p_is_vararg) {
+bool GDScriptParser::register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments, bool p_is_vararg) {
ERR_FAIL_COND_V_MSG(valid_annotations.has(p_info.name), false, vformat(R"(Annotation "%s" already registered.)", p_info.name));
AnnotationInfo new_annotation;
new_annotation.info = p_info;
- new_annotation.info.default_arguments.resize(p_optional_arguments);
+ new_annotation.info.default_arguments = p_default_arguments;
if (p_is_vararg) {
new_annotation.info.flags |= METHOD_FLAG_VARARG;
}
@@ -1451,9 +1513,11 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
if (multiline) {
if (!consume(GDScriptTokenizer::Token::INDENT, vformat(R"(Expected indented block after %s.)", p_context))) {
current_suite = suite->parent_block;
+ complete_extents(suite);
return suite;
}
}
+ reset_extents(suite, current);
int error_count = 0;
@@ -1503,6 +1567,8 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
} while ((multiline || previous.type == GDScriptTokenizer::Token::SEMICOLON) && !check(GDScriptTokenizer::Token::DEDENT) && !lambda_ended && !is_at_end());
+ complete_extents(suite);
+
if (multiline) {
if (!lambda_ended) {
consume(GDScriptTokenizer::Token::DEDENT, vformat(R"(Missing unindent at the end of %s.)", p_context));
@@ -1533,6 +1599,7 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
case GDScriptTokenizer::Token::PASS:
advance();
result = alloc_node<PassNode>();
+ complete_extents(result);
end_statement(R"("pass")");
break;
case GDScriptTokenizer::Token::VAR:
@@ -1580,6 +1647,7 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
// If this fails the expression will be nullptr, but that's the same as no return, so it's fine.
n_return->return_value = parse_expression(false);
}
+ complete_extents(n_return);
result = n_return;
current_suite->has_return = true;
@@ -1590,6 +1658,7 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
case GDScriptTokenizer::Token::BREAKPOINT:
advance();
result = alloc_node<BreakpointNode>();
+ complete_extents(result);
end_statement(R"("breakpoint")");
break;
case GDScriptTokenizer::Token::ASSERT:
@@ -1615,10 +1684,12 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
lambda_ended = true;
has_ended_lambda = true;
} else {
+ advance();
push_error(vformat(R"(Expected statement, found "%s" instead.)", previous.get_name()));
}
+ } else {
+ end_statement("expression");
}
- end_statement("expression");
lambda_ended = lambda_ended || has_ended_lambda;
result = expression;
@@ -1681,6 +1752,7 @@ GDScriptParser::AssertNode *GDScriptParser::parse_assert() {
assert->condition = parse_expression(false);
if (assert->condition == nullptr) {
push_error("Expected expression to assert.");
+ complete_extents(assert);
return nullptr;
}
@@ -1689,12 +1761,14 @@ GDScriptParser::AssertNode *GDScriptParser::parse_assert() {
assert->message = parse_expression(false);
if (assert->message == nullptr) {
push_error(R"(Expected error message for assert after ",".)");
+ complete_extents(assert);
return nullptr;
}
}
consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after assert expression.)*");
+ complete_extents(assert);
end_statement(R"("assert")");
return assert;
@@ -1704,8 +1778,10 @@ GDScriptParser::BreakNode *GDScriptParser::parse_break() {
if (!can_break) {
push_error(R"(Cannot use "break" outside of a loop.)");
}
+ BreakNode *break_node = alloc_node<BreakNode>();
+ complete_extents(break_node);
end_statement(R"("break")");
- return alloc_node<BreakNode>();
+ return break_node;
}
GDScriptParser::ContinueNode *GDScriptParser::parse_continue() {
@@ -1713,9 +1789,10 @@ GDScriptParser::ContinueNode *GDScriptParser::parse_continue() {
push_error(R"(Cannot use "continue" outside of a loop or pattern matching block.)");
}
current_suite->has_continue = true;
- end_statement(R"("continue")");
ContinueNode *cont = alloc_node<ContinueNode>();
cont->is_for_match = is_continue_match;
+ complete_extents(cont);
+ end_statement(R"("continue")");
return cont;
}
@@ -1748,11 +1825,16 @@ 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;
n_for->loop = parse_suite(R"("for" block)", suite);
+ complete_extents(n_for);
// Reset break/continue state.
can_break = could_break;
@@ -1780,15 +1862,16 @@ GDScriptParser::IfNode *GDScriptParser::parse_if(const String &p_token) {
}
if (match(GDScriptTokenizer::Token::ELIF)) {
- IfNode *elif = parse_if("elif");
-
SuiteNode *else_block = alloc_node<SuiteNode>();
+ IfNode *elif = parse_if("elif");
else_block->statements.push_back(elif);
+ complete_extents(else_block);
n_if->false_block = else_block;
} else if (match(GDScriptTokenizer::Token::ELSE)) {
consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "else".)");
n_if->false_block = parse_suite(R"("else" block)");
}
+ complete_extents(n_if);
if (n_if->false_block != nullptr && n_if->false_block->has_return && n_if->true_block->has_return) {
current_suite->has_return = true;
@@ -1812,6 +1895,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
consume(GDScriptTokenizer::Token::NEWLINE, R"(Expected a newline after "match" statement.)");
if (!consume(GDScriptTokenizer::Token::INDENT, R"(Expected an indented block after "match" statement.)")) {
+ complete_extents(match);
return match;
}
@@ -1829,7 +1913,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
}
#ifdef DEBUG_ENABLED
- if (have_wildcard_without_continue) {
+ if (have_wildcard_without_continue && !branch->patterns.is_empty()) {
push_warning(branch->patterns[0], GDScriptWarning::UNREACHABLE_PATTERN);
}
@@ -1845,6 +1929,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
#endif
match->branches.push_back(branch);
}
+ complete_extents(match);
consume(GDScriptTokenizer::Token::DEDENT, R"(Expected an indented block after "match" statement.)");
@@ -1859,6 +1944,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
MatchBranchNode *branch = alloc_node<MatchBranchNode>();
+ reset_extents(branch, current);
bool has_bind = false;
@@ -1886,6 +1972,7 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
}
if (!consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "match" patterns.)")) {
+ complete_extents(branch);
return nullptr;
}
@@ -1906,6 +1993,7 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
}
branch->block = parse_suite("match pattern block", suite);
+ complete_extents(branch);
// Restore continue state.
can_continue = could_continue;
@@ -1916,12 +2004,14 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_root_pattern) {
PatternNode *pattern = alloc_node<PatternNode>();
+ reset_extents(pattern, current);
switch (current.type) {
case GDScriptTokenizer::Token::VAR: {
// Bind.
advance();
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected bind name after "var".)")) {
+ complete_extents(pattern);
return nullptr;
}
pattern->pattern_type = PatternNode::PT_BIND;
@@ -1932,12 +2022,14 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_
if (p_root_pattern != nullptr) {
if (p_root_pattern->has_bind(pattern->bind->name)) {
push_error(vformat(R"(Bind variable name "%s" was already used in this pattern.)", pattern->bind->name));
+ complete_extents(pattern);
return nullptr;
}
}
if (current_suite->has_local(pattern->bind->name)) {
push_error(vformat(R"(There's already a %s named "%s" in this scope.)", current_suite->get_local(pattern->bind->name).get_name(), pattern->bind->name));
+ complete_extents(pattern);
return nullptr;
}
@@ -1990,6 +2082,7 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_
push_error(R"(The ".." pattern must be the last element in the pattern dictionary.)");
} else {
PatternNode *sub_pattern = alloc_node<PatternNode>();
+ complete_extents(sub_pattern);
sub_pattern->pattern_type = PatternNode::PT_REST;
pattern->dictionary.push_back({ nullptr, sub_pattern });
pattern->rest_used = true;
@@ -2038,6 +2131,7 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_
break;
}
}
+ complete_extents(pattern);
return pattern;
}
@@ -2071,6 +2165,7 @@ GDScriptParser::WhileNode *GDScriptParser::parse_while() {
is_continue_match = false;
n_while->loop = parse_suite(R"("while" block)");
+ complete_extents(n_while);
// Reset break/continue state.
can_break = could_break;
@@ -2143,6 +2238,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_identifier(ExpressionNode
ERR_FAIL_V_MSG(nullptr, "Parser bug: parsing literal node without literal token.");
}
IdentifierNode *identifier = alloc_node<IdentifierNode>();
+ complete_extents(identifier);
identifier->name = previous.get_identifier();
if (current_suite != nullptr && current_suite->has_local(identifier->name)) {
@@ -2194,6 +2290,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_literal(ExpressionNode *p_
}
LiteralNode *literal = alloc_node<LiteralNode>();
+ complete_extents(literal);
literal->value = previous.literal;
return literal;
}
@@ -2203,6 +2300,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_self(ExpressionNode *p_pre
push_error(R"(Cannot use "self" inside a static function.)");
}
SelfNode *self = alloc_node<SelfNode>();
+ complete_extents(self);
self->current_class = current_class;
return self;
}
@@ -2210,6 +2308,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_self(ExpressionNode *p_pre
GDScriptParser::ExpressionNode *GDScriptParser::parse_builtin_constant(ExpressionNode *p_previous_operand, bool p_can_assign) {
GDScriptTokenizer::Token::Type op_type = previous.type;
LiteralNode *constant = alloc_node<LiteralNode>();
+ complete_extents(constant);
switch (op_type) {
case GDScriptTokenizer::Token::CONST_PI:
@@ -2270,30 +2369,38 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_unary_operator(ExpressionN
}
break;
default:
+ complete_extents(operation);
return nullptr; // Unreachable.
}
+ complete_extents(operation);
return operation;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_not_in_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
// check that NOT is followed by IN by consuming it before calling parse_binary_operator which will only receive a plain IN
+ UnaryOpNode *operation = alloc_node<UnaryOpNode>();
+ reset_extents(operation, p_previous_operand);
+ update_extents(operation);
consume(GDScriptTokenizer::Token::IN, R"(Expected "in" after "not" in content-test operator.)");
ExpressionNode *in_operation = parse_binary_operator(p_previous_operand, p_can_assign);
- UnaryOpNode *operation = alloc_node<UnaryOpNode>();
operation->operation = UnaryOpNode::OP_LOGIC_NOT;
operation->variant_op = Variant::OP_NOT;
operation->operand = in_operation;
+ complete_extents(operation);
return operation;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
GDScriptTokenizer::Token op = previous;
BinaryOpNode *operation = alloc_node<BinaryOpNode>();
+ reset_extents(operation, p_previous_operand);
+ update_extents(operation);
Precedence precedence = (Precedence)(get_rule(op.type)->precedence + 1);
operation->left_operand = p_previous_operand;
operation->right_operand = parse_precedence(precedence, false);
+ complete_extents(operation);
if (operation->right_operand == nullptr) {
push_error(vformat(R"(Expected expression after "%s" operator.")", op.get_name()));
@@ -2396,8 +2503,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(Expression
GDScriptParser::ExpressionNode *GDScriptParser::parse_ternary_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
// Only one ternary operation exists, so no abstraction here.
TernaryOpNode *operation = alloc_node<TernaryOpNode>();
- operation->true_expr = p_previous_operand;
+ reset_extents(operation, p_previous_operand);
+ update_extents(operation);
+ operation->true_expr = p_previous_operand;
operation->condition = parse_precedence(PREC_TERNARY, false);
if (operation->condition == nullptr) {
@@ -2412,6 +2521,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_ternary_operator(Expressio
push_error(R"(Expected expression after "else".)");
}
+ complete_extents(operation);
return operation;
}
@@ -2464,6 +2574,9 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode
}
AssignmentNode *assignment = alloc_node<AssignmentNode>();
+ reset_extents(assignment, p_previous_operand);
+ update_extents(assignment);
+
make_completion_context(COMPLETION_ASSIGN, assignment);
#ifdef DEBUG_ENABLED
bool has_operator = true;
@@ -2528,6 +2641,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode
if (assignment->assigned_value == nullptr) {
push_error(R"(Expected an expression after "=".)");
}
+ complete_extents(assignment);
#ifdef DEBUG_ENABLED
if (source_variable != nullptr) {
@@ -2549,6 +2663,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_await(ExpressionNode *p_pr
push_error(R"(Expected signal or coroutine after "await".)");
}
await->to_await = element;
+ complete_extents(await);
if (current_function) { // Might be null in a getter or setter.
current_function->is_coroutine = true;
@@ -2577,6 +2692,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_array(ExpressionNode *p_pr
}
pop_multiline();
consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected closing "]" after array elements.)");
+ complete_extents(array);
return array;
}
@@ -2668,6 +2784,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode
}
pop_multiline();
consume(GDScriptTokenizer::Token::BRACE_CLOSE, R"(Expected closing "}" after dictionary elements.)");
+ complete_extents(dictionary);
return dictionary;
}
@@ -2685,6 +2802,8 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_grouping(ExpressionNode *p
GDScriptParser::ExpressionNode *GDScriptParser::parse_attribute(ExpressionNode *p_previous_operand, bool p_can_assign) {
SubscriptNode *attribute = alloc_node<SubscriptNode>();
+ reset_extents(attribute, p_previous_operand);
+ update_extents(attribute);
if (for_completion) {
bool is_builtin = false;
@@ -2704,17 +2823,21 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_attribute(ExpressionNode *
attribute->base = p_previous_operand;
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier after "." for attribute access.)")) {
+ complete_extents(attribute);
return attribute;
}
attribute->is_attribute = true;
attribute->attribute = parse_identifier();
+ complete_extents(attribute);
return attribute;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_subscript(ExpressionNode *p_previous_operand, bool p_can_assign) {
SubscriptNode *subscript = alloc_node<SubscriptNode>();
+ reset_extents(subscript, p_previous_operand);
+ update_extents(subscript);
make_completion_context(COMPLETION_SUBSCRIPT, subscript);
@@ -2727,15 +2850,19 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_subscript(ExpressionNode *
pop_multiline();
consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected "]" after subscription index.)");
+ complete_extents(subscript);
return subscript;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_cast(ExpressionNode *p_previous_operand, bool p_can_assign) {
CastNode *cast = alloc_node<CastNode>();
+ reset_extents(cast, p_previous_operand);
+ update_extents(cast);
cast->operand = p_previous_operand;
cast->cast_type = parse_type();
+ complete_extents(cast);
if (cast->cast_type == nullptr) {
push_error(R"(Expected type specifier after "as".)");
@@ -2747,6 +2874,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_cast(ExpressionNode *p_pre
GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_previous_operand, bool p_can_assign) {
CallNode *call = alloc_node<CallNode>();
+ reset_extents(call, p_previous_operand);
if (previous.type == GDScriptTokenizer::Token::SUPER) {
// Super call.
@@ -2757,6 +2885,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
if (current_function == nullptr) {
push_error(R"(Cannot use implicit "super" call outside of a function.)");
pop_multiline();
+ complete_extents(call);
return nullptr;
}
if (current_function->identifier) {
@@ -2769,6 +2898,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
make_completion_context(COMPLETION_SUPER_METHOD, call, true);
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected function name after ".".)")) {
pop_multiline();
+ complete_extents(call);
return nullptr;
}
IdentifierNode *identifier = parse_identifier();
@@ -2825,6 +2955,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
pop_multiline();
consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected closing ")" after call arguments.)*");
+ complete_extents(call);
return call;
}
@@ -2868,6 +2999,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p
if (previous.type == GDScriptTokenizer::Token::PERCENT) {
if (path_state != PATH_STATE_START && path_state != PATH_STATE_SLASH) {
push_error(R"("%" is only valid in the beginning of a node name (either after "$" or after "/"))");
+ complete_extents(get_node);
return nullptr;
}
get_node->full_path += "%";
@@ -2876,6 +3008,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p
} else if (previous.type == GDScriptTokenizer::Token::SLASH) {
if (path_state != PATH_STATE_START && path_state != PATH_STATE_NODE_NAME) {
push_error(R"("/" is only valid at the beginning of the path or after a node name.)");
+ complete_extents(get_node);
return nullptr;
}
@@ -2903,6 +3036,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p
break;
}
push_error(vformat(R"(Expected node path as string or identifier after "%s".)", previous_token));
+ complete_extents(get_node);
return nullptr;
}
@@ -2916,10 +3050,12 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p
path_state = PATH_STATE_NODE_NAME;
} else if (!check(GDScriptTokenizer::Token::SLASH) && !check(GDScriptTokenizer::Token::PERCENT)) {
push_error(vformat(R"(Unexpected "%s" in node path.)", current.get_name()));
+ complete_extents(get_node);
return nullptr;
}
} while (match(GDScriptTokenizer::Token::SLASH) || match(GDScriptTokenizer::Token::PERCENT));
+ complete_extents(get_node);
return get_node;
}
@@ -2943,6 +3079,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_preload(ExpressionNode *p_
pop_multiline();
consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after preload path.)*");
+ complete_extents(preload);
return preload;
}
@@ -2992,6 +3129,8 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_lambda(ExpressionNode *p_p
in_lambda = true;
function->body = parse_suite("lambda declaration", body, true);
+ complete_extents(function);
+ complete_extents(lambda);
pop_multiline();
@@ -3036,13 +3175,15 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) {
if (!match(GDScriptTokenizer::Token::IDENTIFIER)) {
if (match(GDScriptTokenizer::Token::VOID)) {
if (p_allow_void) {
- TypeNode *void_type = alloc_node<TypeNode>();
+ complete_extents(type);
+ TypeNode *void_type = type;
return void_type;
} else {
push_error(R"("void" is only allowed for a function return type.)");
}
}
// Leave error message to the caller who knows the context.
+ complete_extents(type);
return nullptr;
}
@@ -3055,11 +3196,15 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) {
type->container_type = parse_type(false); // Don't allow void for array element type.
if (type->container_type == nullptr) {
push_error(R"(Expected type for collection after "[".)");
+ complete_extents(type);
type = nullptr;
} else if (type->container_type->container_type != nullptr) {
push_error("Nested typed collections are not supported.");
}
consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected closing "]" after collection type.)");
+ if (type != nullptr) {
+ complete_extents(type);
+ }
return type;
}
@@ -3072,6 +3217,7 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) {
}
}
+ complete_extents(type);
return type;
}
@@ -3280,7 +3426,16 @@ void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &
p_tutorials.append(Pair<String, String>(title, link));
break;
case DONE:
- return;
+ break;
+ }
+ }
+ if (current_class->members.size() > 0) {
+ const ClassNode::Member &m = current_class->members[0];
+ int first_member_line = m.get_line();
+ if (first_member_line == line) {
+ p_brief = "";
+ p_desc = "";
+ p_tutorials.clear();
}
}
}
@@ -3662,6 +3817,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;
@@ -3683,16 +3868,21 @@ bool GDScriptParser::warning_annotations(const AnnotationNode *p_annotation, Nod
#endif // DEBUG_ENABLED
}
-template <Multiplayer::RPCMode t_mode>
-bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Node *p_node) {
- ERR_FAIL_COND_V_MSG(p_node->type != Node::VARIABLE && p_node->type != Node::FUNCTION, false, vformat(R"("%s" annotation can only be applied to variables and functions.)", p_annotation->name));
+bool GDScriptParser::rpc_annotation(const AnnotationNode *p_annotation, Node *p_node) {
+ ERR_FAIL_COND_V_MSG(p_node->type != Node::FUNCTION, false, vformat(R"("%s" annotation can only be applied to functions.)", p_annotation->name));
+
+ FunctionNode *function = static_cast<FunctionNode *>(p_node);
+ if (function->rpc_config.get_type() != Variant::NIL) {
+ push_error(R"(RPC annotations can only be used once per function.)", p_annotation);
+ return false;
+ }
- Multiplayer::RPCConfig rpc_config;
- rpc_config.rpc_mode = t_mode;
+ Dictionary rpc_config;
+ rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
if (p_annotation->resolved_arguments.size()) {
int last = p_annotation->resolved_arguments.size() - 1;
if (p_annotation->resolved_arguments[last].get_type() == Variant::INT) {
- rpc_config.channel = p_annotation->resolved_arguments[last].operator int();
+ rpc_config["channel"] = p_annotation->resolved_arguments[last].operator int();
last -= 1;
}
if (last > 3) {
@@ -3702,37 +3892,25 @@ bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Nod
for (int i = last; i >= 0; i--) {
String mode = p_annotation->resolved_arguments[i].operator String();
if (mode == "any_peer") {
- rpc_config.rpc_mode = Multiplayer::RPC_MODE_ANY_PEER;
+ rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_ANY_PEER;
} else if (mode == "authority") {
- rpc_config.rpc_mode = Multiplayer::RPC_MODE_AUTHORITY;
+ rpc_config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
} else if (mode == "call_local") {
- rpc_config.call_local = true;
+ rpc_config["call_local"] = true;
} else if (mode == "call_remote") {
- rpc_config.call_local = false;
+ rpc_config["call_local"] = false;
} else if (mode == "reliable") {
- rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
+ rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
} else if (mode == "unreliable") {
- rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_UNRELIABLE;
+ rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE;
} else if (mode == "unreliable_ordered") {
- rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED;
+ rpc_config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_UNRELIABLE_ORDERED;
} else {
push_error(R"(Invalid RPC argument. Must be one of: 'call_local'/'call_remote' (local calls), 'any_peer'/'authority' (permission), 'reliable'/'unreliable'/'unreliable_ordered' (transfer mode).)", p_annotation);
}
}
}
- switch (p_node->type) {
- case Node::FUNCTION: {
- FunctionNode *function = static_cast<FunctionNode *>(p_node);
- if (function->rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) {
- push_error(R"(RPC annotations can only be used once per function.)", p_annotation);
- return false;
- }
- function->rpc_config = rpc_config;
- break;
- }
- default:
- return false; // Unreachable.
- }
+ function->rpc_config = rpc_config;
return true;
}
@@ -3859,6 +4037,46 @@ GDScriptParser::DataType GDScriptParser::DataType::get_typed_container_type() co
return type;
}
+void GDScriptParser::complete_extents(Node *p_node) {
+ while (!nodes_in_progress.is_empty() && nodes_in_progress.back()->get() != p_node) {
+ ERR_PRINT("Parser bug: Mismatch in extents tracking stack.");
+ nodes_in_progress.pop_back();
+ }
+ if (nodes_in_progress.is_empty()) {
+ ERR_PRINT("Parser bug: Extents tracking stack is empty.");
+ } else {
+ nodes_in_progress.pop_back();
+ }
+}
+
+void GDScriptParser::update_extents(Node *p_node) {
+ p_node->end_line = previous.end_line;
+ p_node->end_column = previous.end_column;
+ p_node->leftmost_column = MIN(p_node->leftmost_column, previous.leftmost_column);
+ p_node->rightmost_column = MAX(p_node->rightmost_column, previous.rightmost_column);
+}
+
+void GDScriptParser::reset_extents(Node *p_node, GDScriptTokenizer::Token p_token) {
+ p_node->start_line = p_token.start_line;
+ p_node->end_line = p_token.end_line;
+ p_node->start_column = p_token.start_column;
+ p_node->end_column = p_token.end_column;
+ p_node->leftmost_column = p_token.leftmost_column;
+ p_node->rightmost_column = p_token.rightmost_column;
+}
+
+void GDScriptParser::reset_extents(Node *p_node, Node *p_from) {
+ if (p_from == nullptr) {
+ return;
+ }
+ p_node->start_line = p_from->start_line;
+ p_node->end_line = p_from->end_line;
+ p_node->start_column = p_from->start_column;
+ p_node->end_column = p_from->end_column;
+ p_node->leftmost_column = p_from->leftmost_column;
+ p_node->rightmost_column = p_from->rightmost_column;
+}
+
/*---------- PRETTY PRINT FOR DEBUG ----------*/
#ifdef DEBUG_ENABLED
@@ -4145,6 +4363,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..d4efab173b 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -32,7 +32,6 @@
#define GDSCRIPT_PARSER_H
#include "core/io/resource.h"
-#include "core/multiplayer/multiplayer.h"
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
#include "core/string/string_name.h"
@@ -325,6 +324,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 +500,7 @@ public:
VARIABLE,
ENUM,
ENUM_VALUE, // For unnamed enums.
+ GROUP, // For member grouping.
};
Type type = UNDEFINED;
@@ -511,6 +512,7 @@ public:
SignalNode *signal;
VariableNode *variable;
EnumNode *m_enum;
+ AnnotationNode *annotation;
};
EnumNode::Value enum_value;
@@ -532,6 +534,8 @@ public:
return "enum";
case ENUM_VALUE:
return "enum value";
+ case GROUP:
+ return "group";
}
return "";
}
@@ -552,6 +556,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 +592,9 @@ public:
// TODO: Add parameter info.
return type;
}
+ case GROUP: {
+ return DataType();
+ }
case UNDEFINED:
return DataType();
}
@@ -622,6 +631,10 @@ public:
type = ENUM_VALUE;
enum_value = p_enum_value;
}
+ Member(AnnotationNode *p_annotation) {
+ type = GROUP;
+ annotation = p_annotation;
+ }
};
IdentifierNode *identifier = nullptr;
@@ -668,6 +681,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;
@@ -732,7 +749,7 @@ public:
SuiteNode *body = nullptr;
bool is_static = false;
bool is_coroutine = false;
- Multiplayer::RPCConfig rpc_config;
+ Variant rpc_config;
MethodInfo info;
LambdaNode *source_lambda = nullptr;
#ifdef TOOLS_ENABLED
@@ -1238,6 +1255,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.
@@ -1282,6 +1300,12 @@ private:
};
static ParseRule *get_rule(GDScriptTokenizer::Token::Type p_token_type);
+ List<Node *> nodes_in_progress;
+ void complete_extents(Node *p_node);
+ void update_extents(Node *p_node);
+ void reset_extents(Node *p_node, GDScriptTokenizer::Token p_token);
+ void reset_extents(Node *p_node, Node *p_from);
+
template <class T>
T *alloc_node() {
T *node = memnew(T);
@@ -1289,13 +1313,8 @@ private:
node->next = list;
list = node;
- // TODO: Properly set positions for all nodes.
- node->start_line = previous.start_line;
- node->end_line = previous.end_line;
- node->start_column = previous.start_column;
- node->end_column = previous.end_column;
- node->leftmost_column = previous.leftmost_column;
- node->rightmost_column = previous.rightmost_column;
+ reset_extents(node, previous);
+ nodes_in_progress.push_back(node);
return node;
}
@@ -1340,7 +1359,7 @@ private:
SuiteNode *parse_suite(const String &p_context, SuiteNode *p_suite = nullptr, bool p_for_lambda = false);
// Annotations
AnnotationNode *parse_annotation(uint32_t p_valid_targets);
- bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, int p_optional_arguments = 0, bool p_is_vararg = false);
+ bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments = Vector<Variant>(), bool p_is_vararg = false);
bool validate_annotation_arguments(AnnotationNode *p_annotation);
void clear_unused_annotations();
bool tool_annotation(const AnnotationNode *p_annotation, Node *p_target);
@@ -1348,9 +1367,10 @@ 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);
+ bool rpc_annotation(const AnnotationNode *p_annotation, Node *p_target);
// Statements.
Node *parse_statement();
VariableNode *parse_variable();
@@ -1413,6 +1433,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/gdscript_rpc_callable.cpp b/modules/gdscript/gdscript_rpc_callable.cpp
index 63ebd8acf5..4e12419357 100644
--- a/modules/gdscript/gdscript_rpc_callable.cpp
+++ b/modules/gdscript/gdscript_rpc_callable.cpp
@@ -76,11 +76,11 @@ GDScriptRPCCallable::GDScriptRPCCallable(Object *p_object, const StringName &p_m
ERR_FAIL_COND_MSG(!node, "RPC can only be defined on class that extends Node.");
}
-void GDScriptRPCCallable::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
+Error GDScriptRPCCallable::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const {
if (unlikely(!node)) {
r_call_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
- return;
+ return ERR_UNCONFIGURED;
}
r_call_error.error = Callable::CallError::CALL_OK;
- node->rpcp(p_peer_id, method, p_arguments, p_argcount);
+ return node->rpcp(p_peer_id, method, p_arguments, p_argcount);
}
diff --git a/modules/gdscript/gdscript_rpc_callable.h b/modules/gdscript/gdscript_rpc_callable.h
index 2c8734a74b..83b9c7e2df 100644
--- a/modules/gdscript/gdscript_rpc_callable.h
+++ b/modules/gdscript/gdscript_rpc_callable.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GDSCRIPT_RPC_CALLABLE
-#define GDSCRIPT_RPC_CALLABLE
+#ifndef GDSCRIPT_RPC_CALLABLE_H
+#define GDSCRIPT_RPC_CALLABLE_H
#include "core/variant/callable.h"
#include "core/variant/variant.h"
@@ -52,10 +52,10 @@ public:
CompareLessFunc get_compare_less_func() const override;
ObjectID get_object() const override;
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
- void rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
+ Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
GDScriptRPCCallable(Object *p_object, const StringName &p_method);
virtual ~GDScriptRPCCallable() = default;
};
-#endif // GDSCRIPT_RPC_CALLABLE
+#endif // GDSCRIPT_RPC_CALLABLE_H
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index 7fb715f2c8..68b2c6eb1c 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -273,4 +273,4 @@ public:
GDScriptTokenizer();
};
-#endif
+#endif // GDSCRIPT_TOKENIZER_H
diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp
index a914374985..4b97486cb3 100644
--- a/modules/gdscript/gdscript_utility_functions.cpp
+++ b/modules/gdscript/gdscript_utility_functions.cpp
@@ -115,6 +115,7 @@ struct GDScriptUtilityFunctionsDefinitions {
if (p_arg_count < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
+ r_error.expected = 1;
*r_ret = Variant();
return;
}
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 1d56dae982..61e2c61abc 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -199,11 +199,14 @@ void (*type_init_function_table[])(Variant *) = {
&VariantInitializer<Vector3>::init, // VECTOR3.
&VariantInitializer<Vector3i>::init, // VECTOR3I.
&VariantInitializer<Transform2D>::init, // TRANSFORM2D.
+ &VariantInitializer<Vector4>::init, // VECTOR4.
+ &VariantInitializer<Vector4i>::init, // VECTOR4I.
&VariantInitializer<Plane>::init, // PLANE.
&VariantInitializer<Quaternion>::init, // QUATERNION.
&VariantInitializer<AABB>::init, // AABB.
&VariantInitializer<Basis>::init, // BASIS.
&VariantInitializer<Transform3D>::init, // TRANSFORM3D.
+ &VariantInitializer<Projection>::init, // PROJECTION.
&VariantInitializer<Color>::init, // COLOR.
&VariantInitializer<StringName>::init, // STRING_NAME.
&VariantInitializer<NodePath>::init, // NODE_PATH.
@@ -282,11 +285,14 @@ void (*type_init_function_table[])(Variant *) = {
&&OPCODE_CALL_PTRCALL_VECTOR3, \
&&OPCODE_CALL_PTRCALL_VECTOR3I, \
&&OPCODE_CALL_PTRCALL_TRANSFORM2D, \
+ &&OPCODE_CALL_PTRCALL_VECTOR4, \
+ &&OPCODE_CALL_PTRCALL_VECTOR4I, \
&&OPCODE_CALL_PTRCALL_PLANE, \
&&OPCODE_CALL_PTRCALL_QUATERNION, \
&&OPCODE_CALL_PTRCALL_AABB, \
&&OPCODE_CALL_PTRCALL_BASIS, \
&&OPCODE_CALL_PTRCALL_TRANSFORM3D, \
+ &&OPCODE_CALL_PTRCALL_PROJECTION, \
&&OPCODE_CALL_PTRCALL_COLOR, \
&&OPCODE_CALL_PTRCALL_STRING_NAME, \
&&OPCODE_CALL_PTRCALL_NODE_PATH, \
@@ -372,11 +378,14 @@ void (*type_init_function_table[])(Variant *) = {
&&OPCODE_TYPE_ADJUST_VECTOR3, \
&&OPCODE_TYPE_ADJUST_VECTOR3I, \
&&OPCODE_TYPE_ADJUST_TRANSFORM2D, \
+ &&OPCODE_TYPE_ADJUST_VECTOR4, \
+ &&OPCODE_TYPE_ADJUST_VECTOR4I, \
&&OPCODE_TYPE_ADJUST_PLANE, \
&&OPCODE_TYPE_ADJUST_QUATERNION, \
&&OPCODE_TYPE_ADJUST_AABB, \
&&OPCODE_TYPE_ADJUST_BASIS, \
&&OPCODE_TYPE_ADJUST_TRANSFORM3D, \
+ &&OPCODE_TYPE_ADJUST_PROJECTION, \
&&OPCODE_TYPE_ADJUST_COLOR, \
&&OPCODE_TYPE_ADJUST_STRING_NAME, \
&&OPCODE_TYPE_ADJUST_NODE_PATH, \
@@ -435,6 +444,8 @@ void (*type_init_function_table[])(Variant *) = {
#define OP_GET_VECTOR3 get_vector3
#define OP_GET_VECTOR3I get_vector3i
#define OP_GET_RECT2 get_rect2
+#define OP_GET_VECTOR4 get_vector4
+#define OP_GET_VECTOR4I get_vector4i
#define OP_GET_RECT2I get_rect2i
#define OP_GET_QUATERNION get_quaternion
#define OP_GET_COLOR get_color
@@ -456,6 +467,7 @@ void (*type_init_function_table[])(Variant *) = {
#define OP_GET_PACKED_COLOR_ARRAY get_color_array
#define OP_GET_TRANSFORM3D get_transform
#define OP_GET_TRANSFORM2D get_transform2d
+#define OP_GET_PROJECTION get_projection
#define OP_GET_PLANE get_plane
#define OP_GET_AABB get_aabb
#define OP_GET_BASIS get_basis
@@ -1032,11 +1044,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
#ifdef DEBUG_ENABLED
if (!valid) {
- if (src->has_method(*index)) {
- err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' or funcref(obj, \"" + index->operator String() + "\") ?";
- } else {
- err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "').";
- }
+ err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "').";
OPCODE_BREAK;
}
*dst = ret;
@@ -1831,11 +1839,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_CALL_PTR(VECTOR3);
OPCODE_CALL_PTR(VECTOR3I);
OPCODE_CALL_PTR(TRANSFORM2D);
+ OPCODE_CALL_PTR(VECTOR4);
+ OPCODE_CALL_PTR(VECTOR4I);
OPCODE_CALL_PTR(PLANE);
OPCODE_CALL_PTR(QUATERNION);
OPCODE_CALL_PTR(AABB);
OPCODE_CALL_PTR(BASIS);
OPCODE_CALL_PTR(TRANSFORM3D);
+ OPCODE_CALL_PTR(PROJECTION);
OPCODE_CALL_PTR(COLOR);
OPCODE_CALL_PTR(STRING_NAME);
OPCODE_CALL_PTR(NODE_PATH);
@@ -2223,7 +2234,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
retvalue = gdfs;
- Error err = sig.connect(callable_bind(Callable(gdfs.ptr(), "_signal_callback"), retvalue), Object::CONNECT_ONESHOT);
+ Error err = sig.connect(Callable(gdfs.ptr(), "_signal_callback").bind(retvalue), Object::CONNECT_ONESHOT);
if (err != OK) {
err_text = "Error connecting to signal: " + sig.get_name() + " during await.";
OPCODE_BREAK;
@@ -3284,6 +3295,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
int globalname_idx = _code_ptr[ip + 2];
GD_ERR_BREAK(globalname_idx < 0 || globalname_idx >= _global_names_count);
const StringName *globalname = &_global_names_ptr[globalname_idx];
+ GD_ERR_BREAK(!GDScriptLanguage::get_singleton()->get_named_globals_map().has(*globalname));
GET_INSTRUCTION_ARG(dst, 0);
*dst = GDScriptLanguage::get_singleton()->get_named_globals_map()[*globalname];
@@ -3312,11 +3324,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_TYPE_ADJUST(VECTOR3, Vector3);
OPCODE_TYPE_ADJUST(VECTOR3I, Vector3i);
OPCODE_TYPE_ADJUST(TRANSFORM2D, Transform2D);
+ OPCODE_TYPE_ADJUST(VECTOR4, Vector4);
+ OPCODE_TYPE_ADJUST(VECTOR4I, Vector4i);
OPCODE_TYPE_ADJUST(PLANE, Plane);
OPCODE_TYPE_ADJUST(QUATERNION, Quaternion);
OPCODE_TYPE_ADJUST(AABB, AABB);
OPCODE_TYPE_ADJUST(BASIS, Basis);
OPCODE_TYPE_ADJUST(TRANSFORM3D, Transform3D);
+ OPCODE_TYPE_ADJUST(PROJECTION, Projection);
OPCODE_TYPE_ADJUST(COLOR, Color);
OPCODE_TYPE_ADJUST(STRING_NAME, StringName);
OPCODE_TYPE_ADJUST(NODE_PATH, NodePath);
diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h
index f47f31aedf..a639e7b44e 100644
--- a/modules/gdscript/gdscript_warning.h
+++ b/modules/gdscript/gdscript_warning.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GDSCRIPT_WARNINGS
-#define GDSCRIPT_WARNINGS
+#ifndef GDSCRIPT_WARNING_H
+#define GDSCRIPT_WARNING_H
#ifdef DEBUG_ENABLED
@@ -97,4 +97,4 @@ public:
#endif // DEBUG_ENABLED
-#endif // GDSCRIPT_WARNINGS
+#endif // GDSCRIPT_WARNING_H
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index d3c5fed95a..46a9b33eb0 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.
}
@@ -688,9 +690,7 @@ Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::Functio
ERR_FAIL_NULL_V(p_func, func);
func["name"] = p_func->identifier->name;
func["return_type"] = p_func->get_datatype().to_string();
- func["rpc_mode"] = p_func->rpc_config.rpc_mode;
- func["rpc_transfer_mode"] = p_func->rpc_config.transfer_mode;
- func["rpc_transfer_channel"] = p_func->rpc_config.channel;
+ func["rpc_config"] = p_func->rpc_config;
Array parameters;
for (int i = 0; i < p_func->parameters.size(); i++) {
Dictionary arg;
@@ -815,6 +815,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/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h
index 99b0bf45d0..08bba4a2d4 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.h
+++ b/modules/gdscript/language_server/gdscript_extend_parser.h
@@ -33,7 +33,7 @@
#include "../gdscript_parser.h"
#include "core/variant/variant.h"
-#include "lsp.hpp"
+#include "godot_lsp.h"
#ifndef LINE_NUMBER_TO_INDEX
#define LINE_NUMBER_TO_INDEX(p_line) ((p_line)-1)
@@ -99,4 +99,4 @@ public:
Error parse(const String &p_code, const String &p_path);
};
-#endif
+#endif // GDSCRIPT_EXTEND_PARSER_H
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index 7460f8edff..c0d5856be5 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -34,6 +34,7 @@
#include "editor/doc_tools.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
GDScriptLanguageProtocol *GDScriptLanguageProtocol::singleton = nullptr;
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h
index 0fed8597f9..3c9cfe512f 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.h
+++ b/modules/gdscript/language_server/gdscript_language_protocol.h
@@ -36,7 +36,7 @@
#include "core/io/tcp_server.h"
#include "gdscript_text_document.h"
#include "gdscript_workspace.h"
-#include "lsp.hpp"
+#include "godot_lsp.h"
#include "modules/modules_enabled.gen.h" // For jsonrpc.
#ifdef MODULE_JSONRPC_ENABLED
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index 14337e87da..ead4ef1987 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -34,6 +34,7 @@
#include "core/os/os.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
GDScriptLanguageServer::GDScriptLanguageServer() {
_EDITOR_DEF("network/language_server/remote_host", host);
diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h
index 9732765f34..87bc08a34e 100644
--- a/modules/gdscript/language_server/gdscript_text_document.h
+++ b/modules/gdscript/language_server/gdscript_text_document.h
@@ -33,7 +33,7 @@
#include "core/io/file_access.h"
#include "core/object/ref_counted.h"
-#include "lsp.hpp"
+#include "godot_lsp.h"
class GDScriptTextDocument : public RefCounted {
GDCLASS(GDScriptTextDocument, RefCounted)
@@ -77,4 +77,4 @@ public:
GDScriptTextDocument();
};
-#endif
+#endif // GDSCRIPT_TEXT_DOCUMENT_H
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index 8d484a43b3..ded2a7b4d4 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -38,6 +38,7 @@
#include "editor/editor_file_system.h"
#include "editor/editor_help.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
#include "gdscript_language_protocol.h"
#include "scene/resources/packed_scene.h"
@@ -499,7 +500,9 @@ Error GDScriptWorkspace::parse_local_script(const String &p_path) {
String GDScriptWorkspace::get_file_path(const String &p_uri) const {
String path = p_uri;
- path = path.replace(root_uri + "/", "res://");
+ path = path.replace("///", "//");
+ path = path.replace("%3A", ":");
+ path = path.replacen(root_uri + "/", "res://");
path = path.uri_decode();
return path;
}
diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h
index 7bff5db81f..88f3aaf957 100644
--- a/modules/gdscript/language_server/gdscript_workspace.h
+++ b/modules/gdscript/language_server/gdscript_workspace.h
@@ -35,7 +35,7 @@
#include "core/variant/variant.h"
#include "editor/editor_file_system.h"
#include "gdscript_extend_parser.h"
-#include "lsp.hpp"
+#include "godot_lsp.h"
class GDScriptWorkspace : public RefCounted {
GDCLASS(GDScriptWorkspace, RefCounted);
@@ -100,4 +100,4 @@ public:
~GDScriptWorkspace();
};
-#endif
+#endif // GDSCRIPT_WORKSPACE_H
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/godot_lsp.h
index 1c9349097f..fbd40796c4 100644
--- a/modules/gdscript/language_server/lsp.hpp
+++ b/modules/gdscript/language_server/godot_lsp.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* lsp.hpp */
+/* godot_lsp.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -1975,4 +1975,4 @@ static String marked_documentation(const String &p_bbcode) {
}
} // namespace lsp
-#endif
+#endif // GODOT_LSP_H
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index b230c6ba36..059ca703ab 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -52,10 +52,10 @@ GDScriptCache *gdscript_cache = nullptr;
#ifdef TOOLS_ENABLED
-#include "editor/editor_export.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/editor_translation_parser.h"
+#include "editor/export/editor_export.h"
#include "editor/gdscript_highlighter.h"
#include "editor/gdscript_translation_parser_plugin.h"
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index ff4832bde0..e3b956369d 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -36,6 +36,7 @@
#include "../gdscript_parser.h"
#include "core/config/project_settings.h"
+#include "core/core_globals.h"
#include "core/core_string_names.h"
#include "core/io/dir_access.h"
#include "core/io/file_access_pack.h"
@@ -142,8 +143,8 @@ GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_l
#endif
// Enable printing to show results
- _print_line_enabled = true;
- _print_error_enabled = true;
+ CoreGlobals::print_line_enabled = true;
+ CoreGlobals::print_error_enabled = true;
}
GDScriptTestRunner::~GDScriptTestRunner() {
diff --git a/modules/gdscript/tests/gdscript_test_runner.h b/modules/gdscript/tests/gdscript_test_runner.h
index ee21afd9c9..033d2fcad1 100644
--- a/modules/gdscript/tests/gdscript_test_runner.h
+++ b/modules/gdscript/tests/gdscript_test_runner.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GDSCRIPT_TEST_H
-#define GDSCRIPT_TEST_H
+#ifndef GDSCRIPT_TEST_RUNNER_H
+#define GDSCRIPT_TEST_RUNNER_H
#include "../gdscript.h"
#include "core/error/error_macros.h"
@@ -123,4 +123,4 @@ public:
} // namespace GDScriptTests
-#endif // GDSCRIPT_TEST_H
+#endif // GDSCRIPT_TEST_RUNNER_H
diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd
index fb0ace6a90..ea744e3027 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd
@@ -1,3 +1,5 @@
+const A := 42
+
func test():
pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd
new file mode 100644
index 0000000000..276875dd5a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd
@@ -0,0 +1,6 @@
+const Constants = preload("gdscript_to_preload.gd")
+
+func test():
+ var a := Constants.A
+ print(a)
+
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.out b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.out
new file mode 100644
index 0000000000..0982f3718c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+42
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/glslang/register_types.cpp b/modules/glslang/register_types.cpp
index 64891d9ee8..b1c2140039 100644
--- a/modules/glslang/register_types.cpp
+++ b/modules/glslang/register_types.cpp
@@ -38,7 +38,8 @@
#include <glslang/Public/ShaderLang.h>
#include <glslang/SPIRV/GlslangToSpv.h>
-static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error, const RenderingDevice::Capabilities *p_capabilities) {
+static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device) {
+ const RD::Capabilities *capabilities = p_render_device->get_device_capabilities();
Vector<uint8_t> ret;
ERR_FAIL_COND_V(p_language == RenderingDevice::SHADER_LANGUAGE_HLSL, ret);
@@ -58,12 +59,12 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_5;
glslang::TShader::ForbidIncluder includer;
- if (p_capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) {
- if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 0) {
+ if (capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) {
+ if (capabilities->version_major == 1 && capabilities->version_minor == 0) {
ClientVersion = glslang::EShTargetVulkan_1_0;
TargetVersion = glslang::EShTargetSpv_1_0;
check_subgroup_support = false; // subgroups are not supported in Vulkan 1.0
- } else if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 1) {
+ } else if (capabilities->version_major == 1 && capabilities->version_minor == 1) {
ClientVersion = glslang::EShTargetVulkan_1_1;
TargetVersion = glslang::EShTargetSpv_1_3;
} else {
@@ -90,34 +91,36 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
if (check_subgroup_support) {
uint32_t stage_bit = 1 << p_stage;
- if ((p_capabilities->subgroup_in_shaders & stage_bit) == stage_bit) {
+ uint32_t subgroup_in_shaders = uint32_t(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS));
+ uint32_t subgroup_operations = uint32_t(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS));
+ if ((subgroup_in_shaders & stage_bit) == stage_bit) {
// stage supports subgroups
preamble += "#define has_GL_KHR_shader_subgroup_basic 1\n";
- if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_VOTE_BIT) {
+ if (subgroup_operations & RenderingDevice::SUBGROUP_VOTE_BIT) {
preamble += "#define has_GL_KHR_shader_subgroup_vote 1\n";
}
- if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_ARITHMETIC_BIT) {
+ if (subgroup_operations & RenderingDevice::SUBGROUP_ARITHMETIC_BIT) {
preamble += "#define has_GL_KHR_shader_subgroup_arithmetic 1\n";
}
- if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_BALLOT_BIT) {
+ if (subgroup_operations & RenderingDevice::SUBGROUP_BALLOT_BIT) {
preamble += "#define has_GL_KHR_shader_subgroup_ballot 1\n";
}
- if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_BIT) {
+ if (subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_BIT) {
preamble += "#define has_GL_KHR_shader_subgroup_shuffle 1\n";
}
- if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_RELATIVE_BIT) {
+ if (subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_RELATIVE_BIT) {
preamble += "#define has_GL_KHR_shader_subgroup_shuffle_relative 1\n";
}
- if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_CLUSTERED_BIT) {
+ if (subgroup_operations & RenderingDevice::SUBGROUP_CLUSTERED_BIT) {
preamble += "#define has_GL_KHR_shader_subgroup_clustered 1\n";
}
- if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_QUAD_BIT) {
+ if (subgroup_operations & RenderingDevice::SUBGROUP_QUAD_BIT) {
preamble += "#define has_GL_KHR_shader_subgroup_quad 1\n";
}
}
}
- if (p_capabilities->supports_multiview) {
+ if (p_render_device->has_feature(RD::SUPPORTS_MULTIVIEW)) {
preamble += "#define has_VK_KHR_multiview 1\n";
}
@@ -184,9 +187,10 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
return ret;
}
-static String _get_cache_key_function_glsl(const RenderingDevice::Capabilities *p_capabilities) {
+static String _get_cache_key_function_glsl(const RenderingDevice *p_render_device) {
+ const RD::Capabilities *capabilities = p_render_device->get_device_capabilities();
String version;
- version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(p_capabilities->version_major) + ", minor=" + itos(p_capabilities->version_minor) + " , subgroup_size=" + itos(p_capabilities->subgroup_operations) + " , subgroup_ops=" + itos(p_capabilities->subgroup_operations) + " , subgroup_in_shaders=" + itos(p_capabilities->subgroup_in_shaders);
+ version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(capabilities->version_major) + ", minor=" + itos(capabilities->version_minor) + " , subgroup_size=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_SIZE)) + " , subgroup_ops=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)) + " , subgroup_in_shaders=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS));
return version;
}
diff --git a/modules/gltf/README.md b/modules/gltf/README.md
new file mode 100644
index 0000000000..5d8966b201
--- /dev/null
+++ b/modules/gltf/README.md
@@ -0,0 +1,11 @@
+# Godot GLTF import and export module
+
+In a nutshell, the GLTF module works like this:
+
+* The [`structures/`](structures/) folder contains GLTF structures, the
+ small pieces that make up a GLTF file, represented as C++ classes.
+* The [`extensions/`](extensions/) folder contains GLTF extensions, which
+ are optional features that build on top of the base GLTF spec.
+* [`GLTFState`](gltf_state.h) holds collections of structures and extensions.
+* [`GLTFDocument`](gltf_document.h) operates on GLTFState and its elements.
+* The [`editor/`](editor/) folder uses GLTFDocument to import and export 3D models.
diff --git a/modules/gltf/SCsub b/modules/gltf/SCsub
index 3379404a00..71f3ba58d9 100644
--- a/modules/gltf/SCsub
+++ b/modules/gltf/SCsub
@@ -5,7 +5,9 @@ Import("env_modules")
env_gltf = env_modules.Clone()
-# Godot's own source files
+# Godot source files
env_gltf.add_source_files(env.modules_sources, "*.cpp")
+env_gltf.add_source_files(env.modules_sources, "extensions/*.cpp")
+env_gltf.add_source_files(env.modules_sources, "structures/*.cpp")
if env["tools"]:
env_gltf.add_source_files(env.modules_sources, "editor/*.cpp")
diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp
index 676862ea5a..8002c185c7 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -292,7 +292,7 @@ static bool _test_blender_path(const String &p_path, String *r_err = nullptr) {
path = path.plus_file("blender");
#endif
-#if defined(OSX_ENABLED)
+#if defined(MACOS_ENABLED)
if (!FileAccess::exists(path)) {
path = path.plus_file("Blender");
}
@@ -449,8 +449,8 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() {
EditorNode::get_singleton()->get_gui_base()->add_child(configure_blender_dialog);
- configure_blender_dialog->get_ok_button()->set_text(TTR("Confirm Path"));
- configure_blender_dialog->get_cancel_button()->set_text(TTR("Disable '.blend' Import"));
+ configure_blender_dialog->set_ok_button_text(TTR("Confirm Path"));
+ configure_blender_dialog->set_cancel_button_text(TTR("Disable '.blend' Import"));
configure_blender_dialog->get_cancel_button()->set_tooltip(TTR("Disables Blender '.blend' files import for this project. Can be re-enabled in Project Settings."));
configure_blender_dialog->connect("confirmed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_path_confirmed));
@@ -468,7 +468,7 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() {
// Autodetect
auto_detected_path = "";
-#if defined(OSX_ENABLED)
+#if defined(MACOS_ENABLED)
{
Vector<String> mdfind_paths;
diff --git a/modules/gltf/gltf_light.cpp b/modules/gltf/extensions/gltf_light.cpp
index af21a4e804..af21a4e804 100644
--- a/modules/gltf/gltf_light.cpp
+++ b/modules/gltf/extensions/gltf_light.cpp
diff --git a/modules/gltf/gltf_light.h b/modules/gltf/extensions/gltf_light.h
index 25e0835a33..58fa299dfd 100644
--- a/modules/gltf/gltf_light.h
+++ b/modules/gltf/extensions/gltf_light.h
@@ -33,6 +33,7 @@
#include "core/config/engine.h"
#include "core/io/resource.h"
+#include "scene/3d/light_3d.h"
class GLTFLight : public Resource {
GDCLASS(GLTFLight, Resource)
diff --git a/modules/gltf/gltf_spec_gloss.cpp b/modules/gltf/extensions/gltf_spec_gloss.cpp
index 83af91bfcc..83af91bfcc 100644
--- a/modules/gltf/gltf_spec_gloss.cpp
+++ b/modules/gltf/extensions/gltf_spec_gloss.cpp
diff --git a/modules/gltf/gltf_spec_gloss.h b/modules/gltf/extensions/gltf_spec_gloss.h
index f8a431bdce..a45fa4296c 100644
--- a/modules/gltf/gltf_spec_gloss.h
+++ b/modules/gltf/extensions/gltf_spec_gloss.h
@@ -64,4 +64,5 @@ public:
Ref<Image> get_spec_gloss_img();
void set_spec_gloss_img(Ref<Image> p_spec_gloss_img);
};
+
#endif // GLTF_SPEC_GLOSS_H
diff --git a/modules/gltf/gltf_defines.h b/modules/gltf/gltf_defines.h
new file mode 100644
index 0000000000..c20c87f798
--- /dev/null
+++ b/modules/gltf/gltf_defines.h
@@ -0,0 +1,87 @@
+/*************************************************************************/
+/* gltf_defines.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 GLTF_DEFINES_H
+#define GLTF_DEFINES_H
+
+// This file should only be included by other headers.
+
+// Godot classes used by GLTF headers.
+class BoneAttachment3D;
+class CSGShape3D;
+class DirectionalLight3D;
+class GridMap;
+class Light3D;
+class MultiMeshInstance3D;
+class Skeleton3D;
+class Skin;
+
+// GLTF classes.
+struct GLTFAccessor;
+class GLTFAnimation;
+class GLTFBufferView;
+class GLTFCamera;
+class GLTFDocument;
+class GLTFDocumentExtension;
+class GLTFLight;
+class GLTFMesh;
+class GLTFNode;
+class GLTFSkeleton;
+class GLTFSkin;
+class GLTFSpecGloss;
+class GLTFState;
+class GLTFTexture;
+
+// GLTF index aliases.
+using GLTFAccessorIndex = int;
+using GLTFAnimationIndex = int;
+using GLTFBufferIndex = int;
+using GLTFBufferViewIndex = int;
+using GLTFCameraIndex = int;
+using GLTFImageIndex = int;
+using GLTFMaterialIndex = int;
+using GLTFMeshIndex = int;
+using GLTFLightIndex = int;
+using GLTFNodeIndex = int;
+using GLTFSkeletonIndex = int;
+using GLTFSkinIndex = int;
+using GLTFTextureIndex = int;
+
+enum GLTFType {
+ TYPE_SCALAR,
+ TYPE_VEC2,
+ TYPE_VEC3,
+ TYPE_VEC4,
+ TYPE_MAT2,
+ TYPE_MAT3,
+ TYPE_MAT4,
+};
+
+#endif // GLTF_DEFINES_H
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 2017355717..7e90f198f6 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -30,19 +30,10 @@
#include "gltf_document.h"
-#include "gltf_accessor.h"
-#include "gltf_animation.h"
-#include "gltf_camera.h"
+#include "extensions/gltf_spec_gloss.h"
#include "gltf_document_extension.h"
#include "gltf_document_extension_convert_importer_mesh.h"
-#include "gltf_light.h"
-#include "gltf_mesh.h"
-#include "gltf_node.h"
-#include "gltf_skeleton.h"
-#include "gltf_skin.h"
-#include "gltf_spec_gloss.h"
#include "gltf_state.h"
-#include "gltf_texture.h"
#include "core/crypto/crypto_core.h"
#include "core/error/error_macros.h"
@@ -230,15 +221,21 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) {
}
Error GLTFDocument::_serialize_extensions(Ref<GLTFState> state) const {
- const String texture_transform = "KHR_texture_transform";
- const String punctual_lights = "KHR_lights_punctual";
Array extensions_used;
- extensions_used.push_back(punctual_lights);
- extensions_used.push_back(texture_transform);
- state->json["extensionsUsed"] = extensions_used;
Array extensions_required;
- extensions_required.push_back(texture_transform);
- state->json["extensionsRequired"] = extensions_required;
+ if (!state->lights.is_empty()) {
+ extensions_used.push_back("KHR_lights_punctual");
+ }
+ if (state->use_khr_texture_transform) {
+ extensions_used.push_back("KHR_texture_transform");
+ extensions_required.push_back("KHR_texture_transform");
+ }
+ if (!extensions_used.is_empty()) {
+ state->json["extensionsUsed"] = extensions_used;
+ }
+ if (!extensions_required.is_empty()) {
+ state->json["extensionsRequired"] = extensions_required;
+ }
return OK;
}
@@ -934,58 +931,58 @@ Error GLTFDocument::_encode_accessors(Ref<GLTFState> state) {
return OK;
}
-String GLTFDocument::_get_accessor_type_name(const GLTFDocument::GLTFType p_type) {
- if (p_type == GLTFDocument::TYPE_SCALAR) {
+String GLTFDocument::_get_accessor_type_name(const GLTFType p_type) {
+ if (p_type == GLTFType::TYPE_SCALAR) {
return "SCALAR";
}
- if (p_type == GLTFDocument::TYPE_VEC2) {
+ if (p_type == GLTFType::TYPE_VEC2) {
return "VEC2";
}
- if (p_type == GLTFDocument::TYPE_VEC3) {
+ if (p_type == GLTFType::TYPE_VEC3) {
return "VEC3";
}
- if (p_type == GLTFDocument::TYPE_VEC4) {
+ if (p_type == GLTFType::TYPE_VEC4) {
return "VEC4";
}
- if (p_type == GLTFDocument::TYPE_MAT2) {
+ if (p_type == GLTFType::TYPE_MAT2) {
return "MAT2";
}
- if (p_type == GLTFDocument::TYPE_MAT3) {
+ if (p_type == GLTFType::TYPE_MAT3) {
return "MAT3";
}
- if (p_type == GLTFDocument::TYPE_MAT4) {
+ if (p_type == GLTFType::TYPE_MAT4) {
return "MAT4";
}
ERR_FAIL_V("SCALAR");
}
-GLTFDocument::GLTFType GLTFDocument::_get_type_from_str(const String &p_string) {
+GLTFType GLTFDocument::_get_type_from_str(const String &p_string) {
if (p_string == "SCALAR") {
- return GLTFDocument::TYPE_SCALAR;
+ return GLTFType::TYPE_SCALAR;
}
if (p_string == "VEC2") {
- return GLTFDocument::TYPE_VEC2;
+ return GLTFType::TYPE_VEC2;
}
if (p_string == "VEC3") {
- return GLTFDocument::TYPE_VEC3;
+ return GLTFType::TYPE_VEC3;
}
if (p_string == "VEC4") {
- return GLTFDocument::TYPE_VEC4;
+ return GLTFType::TYPE_VEC4;
}
if (p_string == "MAT2") {
- return GLTFDocument::TYPE_MAT2;
+ return GLTFType::TYPE_MAT2;
}
if (p_string == "MAT3") {
- return GLTFDocument::TYPE_MAT3;
+ return GLTFType::TYPE_MAT3;
}
if (p_string == "MAT4") {
- return GLTFDocument::TYPE_MAT4;
+ return GLTFType::TYPE_MAT4;
}
- ERR_FAIL_V(GLTFDocument::TYPE_SCALAR);
+ ERR_FAIL_V(GLTFType::TYPE_SCALAR);
}
Error GLTFDocument::_parse_accessors(Ref<GLTFState> state) {
@@ -1536,7 +1533,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, c
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
int64_t size = state->buffers[0].size();
- const GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR;
+ const GLTFType type = GLTFType::TYPE_SCALAR;
const int component_type = GLTFDocument::COMPONENT_TYPE_INT;
accessor->max = type_max;
@@ -1620,7 +1617,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, c
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
int64_t size = state->buffers[0].size();
- const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC2;
+ const GLTFType type = GLTFType::TYPE_VEC2;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
accessor->max = type_max;
@@ -1669,7 +1666,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state,
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
int64_t size = state->buffers[0].size();
- const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4;
+ const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
accessor->max = type_max;
@@ -1734,7 +1731,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
int64_t size = state->buffers[0].size();
- const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4;
+ const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
accessor->max = type_max;
@@ -1781,7 +1778,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state,
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
int64_t size = state->buffers[0].size();
- const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4;
+ const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT;
accessor->max = type_max;
@@ -1830,7 +1827,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> s
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
int64_t size = state->buffers[0].size();
- const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4;
+ const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
accessor->max = type_max;
@@ -1895,7 +1892,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> state,
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
int64_t size = state->buffers[0].size();
- const GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR;
+ const GLTFType type = GLTFType::TYPE_SCALAR;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
accessor->max = type_max;
@@ -1941,7 +1938,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, c
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
int64_t size = state->buffers[0].size();
- const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC3;
+ const GLTFType type = GLTFType::TYPE_VEC3;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
accessor->max = type_max;
@@ -2009,7 +2006,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state,
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
int64_t size = state->buffers[0].size();
- const GLTFDocument::GLTFType type = GLTFDocument::TYPE_MAT4;
+ const GLTFType type = GLTFType::TYPE_MAT4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
accessor->max = type_max;
@@ -3080,9 +3077,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 +3199,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()));
@@ -3310,7 +3302,11 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
}
if (gltf_texture_index != -1) {
bct["index"] = gltf_texture_index;
- bct["extensions"] = _serialize_texture_transform_uv1(material);
+ Dictionary extensions = _serialize_texture_transform_uv1(material);
+ if (!extensions.is_empty()) {
+ bct["extensions"] = extensions;
+ state->use_khr_texture_transform = true;
+ }
mr["baseColorTexture"] = bct;
}
}
@@ -3428,7 +3424,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");
@@ -3441,7 +3437,11 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
}
if (has_roughness || has_metalness) {
mrt["index"] = orm_texture_index;
- mrt["extensions"] = _serialize_texture_transform_uv1(material);
+ Dictionary extensions = _serialize_texture_transform_uv1(material);
+ if (!extensions.is_empty()) {
+ mrt["extensions"] = extensions;
+ state->use_khr_texture_transform = true;
+ }
mr["metallicRoughnessTexture"] = mrt;
}
}
@@ -3476,7 +3476,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 +3784,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);
@@ -4535,6 +4530,9 @@ void GLTFDocument::_remove_duplicate_skins(Ref<GLTFState> state) {
}
Error GLTFDocument::_serialize_lights(Ref<GLTFState> state) {
+ if (state->lights.is_empty()) {
+ return OK;
+ }
Array lights;
for (GLTFLightIndex i = 0; i < state->lights.size(); i++) {
Dictionary d;
@@ -4561,10 +4559,6 @@ Error GLTFDocument::_serialize_lights(Ref<GLTFState> state) {
lights.push_back(d);
}
- if (!state->lights.size()) {
- return OK;
- }
-
Dictionary extensions;
if (state->json.has("extensions")) {
extensions = state->json["extensions"];
@@ -4944,7 +4938,8 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) {
if (d.has("name")) {
const String name = d["name"];
- if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
+ const String name_lower = name.to_lower();
+ if (name_lower.begins_with("loop") || name_lower.ends_with("loop") || name_lower.begins_with("cycle") || name_lower.ends_with("cycle")) {
animation->set_loop(true);
}
animation->set_name(_gen_unique_animation_name(state, name));
@@ -5176,19 +5171,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);
@@ -5227,7 +5219,7 @@ GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> state, Camera3D *p_
Ref<GLTFCamera> c;
c.instantiate();
- if (p_camera->get_projection() == Camera3D::Projection::PROJECTION_PERSPECTIVE) {
+ if (p_camera->get_projection() == Camera3D::ProjectionType::PROJECTION_PERSPECTIVE) {
c->set_perspective(true);
}
c->set_fov_size(p_camera->get_fov());
@@ -5253,14 +5245,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).
@@ -6666,45 +6656,48 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess>
return OK;
}
-Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material) {
- Dictionary extension;
- Ref<BaseMaterial3D> mat = p_material;
- if (mat.is_valid()) {
- Dictionary texture_transform;
+Dictionary _serialize_texture_transform_uv(Vector2 p_offset, Vector2 p_scale) {
+ Dictionary texture_transform;
+ bool is_offset = p_offset != Vector2(0.0, 0.0);
+ if (is_offset) {
Array offset;
offset.resize(2);
- offset[0] = mat->get_uv2_offset().x;
- offset[1] = mat->get_uv2_offset().y;
+ offset[0] = p_offset.x;
+ offset[1] = p_offset.y;
texture_transform["offset"] = offset;
+ }
+ bool is_scaled = p_scale != Vector2(1.0, 1.0);
+ if (is_scaled) {
Array scale;
scale.resize(2);
- scale[0] = mat->get_uv2_scale().x;
- scale[1] = mat->get_uv2_scale().y;
+ scale[0] = p_scale.x;
+ scale[1] = p_scale.y;
texture_transform["scale"] = scale;
- // Godot doesn't support texture rotation
+ }
+ Dictionary extension;
+ // Note: Godot doesn't support texture rotation.
+ if (is_offset || is_scaled) {
extension["KHR_texture_transform"] = texture_transform;
}
return extension;
}
Dictionary GLTFDocument::_serialize_texture_transform_uv1(Ref<BaseMaterial3D> p_material) {
- Dictionary extension;
if (p_material.is_valid()) {
- Dictionary texture_transform;
- Array offset;
- offset.resize(2);
- offset[0] = p_material->get_uv1_offset().x;
- offset[1] = p_material->get_uv1_offset().y;
- texture_transform["offset"] = offset;
- Array scale;
- scale.resize(2);
- scale[0] = p_material->get_uv1_scale().x;
- scale[1] = p_material->get_uv1_scale().y;
- texture_transform["scale"] = scale;
- // Godot doesn't support texture rotation
- extension["KHR_texture_transform"] = texture_transform;
+ Vector3 offset = p_material->get_uv1_offset();
+ Vector3 scale = p_material->get_uv1_scale();
+ return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y));
}
- return extension;
+ return Dictionary();
+}
+
+Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material) {
+ if (p_material.is_valid()) {
+ Vector3 offset = p_material->get_uv2_offset();
+ Vector3 scale = p_material->get_uv2_scale();
+ return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y));
+ }
+ return Dictionary();
}
Error GLTFDocument::_serialize_version(Ref<GLTFState> state) {
@@ -6944,15 +6937,6 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32
state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
- _convert_scene_node(state, p_node, -1, -1);
- if (!state->buffers.size()) {
- state->buffers.push_back(Vector<uint8_t>());
- }
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
- ERR_CONTINUE(ext.is_null());
- }
-
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
ERR_CONTINUE(ext.is_null());
@@ -6963,7 +6947,6 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32
if (!state->buffers.size()) {
state->buffers.push_back(Vector<uint8_t>());
}
-
return OK;
}
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index 2f61210ff9..36a2f94a4e 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -31,48 +31,19 @@
#ifndef GLTF_DOCUMENT_H
#define GLTF_DOCUMENT_H
-#include "gltf_animation.h"
+#include "gltf_defines.h"
+#include "structures/gltf_animation.h"
#include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
-#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/material.h"
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
-#include <cstdint>
-
-class GLTFState;
-class GLTFSkin;
-class GLTFNode;
-class GLTFSpecGloss;
-class GLTFSkeleton;
-class CSGShape3D;
-class GridMap;
-class MultiMeshInstance3D;
-class GLTFDocumentExtension;
-
-using GLTFAccessorIndex = int;
-using GLTFAnimationIndex = int;
-using GLTFBufferIndex = int;
-using GLTFBufferViewIndex = int;
-using GLTFCameraIndex = int;
-using GLTFImageIndex = int;
-using GLTFMaterialIndex = int;
-using GLTFMeshIndex = int;
-using GLTFLightIndex = int;
-using GLTFNodeIndex = int;
-using GLTFSkeletonIndex = int;
-using GLTFSkinIndex = int;
-using GLTFTextureIndex = int;
-
class GLTFDocument : public Resource {
GDCLASS(GLTFDocument, Resource);
- friend class GLTFState;
- friend class GLTFSkin;
- friend class GLTFSkeleton;
TypedArray<GLTFDocumentExtension> document_extensions;
private:
@@ -81,15 +52,6 @@ private:
public:
GLTFDocument();
const int32_t JOINT_GROUP_SIZE = 4;
- enum GLTFType {
- TYPE_SCALAR,
- TYPE_VEC2,
- TYPE_VEC3,
- TYPE_VEC4,
- TYPE_MAT2,
- TYPE_MAT3,
- TYPE_MAT4,
- };
enum {
ARRAY_BUFFER = 34962,
@@ -118,58 +80,6 @@ public:
TypedArray<GLTFDocumentExtension> get_extensions() const;
private:
- template <class T>
- static Array to_array(const Vector<T> &p_inp) {
- Array ret;
- for (int i = 0; i < p_inp.size(); i++) {
- ret.push_back(p_inp[i]);
- }
- return ret;
- }
-
- template <class T>
- static Array to_array(const HashSet<T> &p_inp) {
- Array ret;
- typename HashSet<T>::Iterator elem = p_inp.begin();
- while (elem) {
- ret.push_back(*elem);
- ++elem;
- }
- return ret;
- }
-
- template <class T>
- static void set_from_array(Vector<T> &r_out, const Array &p_inp) {
- r_out.clear();
- for (int i = 0; i < p_inp.size(); i++) {
- r_out.push_back(p_inp[i]);
- }
- }
-
- template <class T>
- static void set_from_array(HashSet<T> &r_out, const Array &p_inp) {
- r_out.clear();
- for (int i = 0; i < p_inp.size(); i++) {
- r_out.insert(p_inp[i]);
- }
- }
- template <class K, class V>
- static Dictionary to_dict(const HashMap<K, V> &p_inp) {
- Dictionary ret;
- for (const KeyValue<K, V> &E : p_inp) {
- ret[E.key] = E.value;
- }
- return ret;
- }
-
- template <class K, class V>
- static void set_from_dict(HashMap<K, V> &r_out, const Dictionary &p_inp) {
- r_out.clear();
- Array keys = p_inp.keys();
- for (int i = 0; i < keys.size(); i++) {
- r_out[keys[i]] = p_inp[keys[i]];
- }
- }
void _build_parent_hierachy(Ref<GLTFState> state);
double _filter_number(double p_float);
String _get_component_type_name(const uint32_t p_component);
@@ -177,7 +87,7 @@ private:
Error _parse_scenes(Ref<GLTFState> state);
Error _parse_nodes(Ref<GLTFState> state);
String _get_type_name(const GLTFType p_component);
- String _get_accessor_type_name(const GLTFDocument::GLTFType p_type);
+ String _get_accessor_type_name(const GLTFType p_type);
String _gen_unique_name(Ref<GLTFState> state, const String &p_name);
String _sanitize_animation_name(const String &name);
String _gen_unique_animation_name(Ref<GLTFState> state, const String &p_name);
diff --git a/modules/gltf/gltf_document_extension.h b/modules/gltf/gltf_document_extension.h
index 556f79e887..0ef9109584 100644
--- a/modules/gltf/gltf_document_extension.h
+++ b/modules/gltf/gltf_document_extension.h
@@ -31,9 +31,8 @@
#ifndef GLTF_DOCUMENT_EXTENSION_H
#define GLTF_DOCUMENT_EXTENSION_H
-#include "gltf_accessor.h"
-#include "gltf_node.h"
#include "gltf_state.h"
+#include "structures/gltf_node.h"
class GLTFDocumentExtension : public Resource {
GDCLASS(GLTFDocumentExtension, Resource);
diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.h b/modules/gltf/gltf_document_extension_convert_importer_mesh.h
index 4c9e42a00f..00e664e73f 100644
--- a/modules/gltf/gltf_document_extension_convert_importer_mesh.h
+++ b/modules/gltf/gltf_document_extension_convert_importer_mesh.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GLTF_EXTENSION_EDITOR_H
-#define GLTF_EXTENSION_EDITOR_H
+#ifndef GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H
+#define GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H
#include "gltf_document_extension.h"
@@ -37,8 +37,6 @@
#include "scene/3d/mesh_instance_3d.h"
#include "scene/resources/importer_mesh.h"
-class GLTFDocumentExtension;
-class GLTFDocument;
class GLTFDocumentExtensionConvertImporterMesh : public GLTFDocumentExtension {
GDCLASS(GLTFDocumentExtensionConvertImporterMesh, GLTFDocumentExtension);
@@ -48,4 +46,5 @@ protected:
public:
Error import_post(Ref<GLTFState> p_state, Node *p_root) override;
};
-#endif // GLTF_EXTENSION_EDITOR_H
+
+#endif // GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H
diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp
index 989fa476c2..a5f7bcf9d6 100644
--- a/modules/gltf/gltf_state.cpp
+++ b/modules/gltf/gltf_state.cpp
@@ -150,51 +150,51 @@ void GLTFState::set_use_named_skin_binds(bool p_use_named_skin_binds) {
}
Array GLTFState::get_nodes() {
- return GLTFDocument::to_array(nodes);
+ return GLTFTemplateConvert::to_array(nodes);
}
void GLTFState::set_nodes(Array p_nodes) {
- GLTFDocument::set_from_array(nodes, p_nodes);
+ GLTFTemplateConvert::set_from_array(nodes, p_nodes);
}
Array GLTFState::get_buffers() {
- return GLTFDocument::to_array(buffers);
+ return GLTFTemplateConvert::to_array(buffers);
}
void GLTFState::set_buffers(Array p_buffers) {
- GLTFDocument::set_from_array(buffers, p_buffers);
+ GLTFTemplateConvert::set_from_array(buffers, p_buffers);
}
Array GLTFState::get_buffer_views() {
- return GLTFDocument::to_array(buffer_views);
+ return GLTFTemplateConvert::to_array(buffer_views);
}
void GLTFState::set_buffer_views(Array p_buffer_views) {
- GLTFDocument::set_from_array(buffer_views, p_buffer_views);
+ GLTFTemplateConvert::set_from_array(buffer_views, p_buffer_views);
}
Array GLTFState::get_accessors() {
- return GLTFDocument::to_array(accessors);
+ return GLTFTemplateConvert::to_array(accessors);
}
void GLTFState::set_accessors(Array p_accessors) {
- GLTFDocument::set_from_array(accessors, p_accessors);
+ GLTFTemplateConvert::set_from_array(accessors, p_accessors);
}
Array GLTFState::get_meshes() {
- return GLTFDocument::to_array(meshes);
+ return GLTFTemplateConvert::to_array(meshes);
}
void GLTFState::set_meshes(Array p_meshes) {
- GLTFDocument::set_from_array(meshes, p_meshes);
+ GLTFTemplateConvert::set_from_array(meshes, p_meshes);
}
Array GLTFState::get_materials() {
- return GLTFDocument::to_array(materials);
+ return GLTFTemplateConvert::to_array(materials);
}
void GLTFState::set_materials(Array p_materials) {
- GLTFDocument::set_from_array(materials, p_materials);
+ GLTFTemplateConvert::set_from_array(materials, p_materials);
}
String GLTFState::get_scene_name() {
@@ -206,91 +206,91 @@ void GLTFState::set_scene_name(String p_scene_name) {
}
Array GLTFState::get_root_nodes() {
- return GLTFDocument::to_array(root_nodes);
+ return GLTFTemplateConvert::to_array(root_nodes);
}
void GLTFState::set_root_nodes(Array p_root_nodes) {
- GLTFDocument::set_from_array(root_nodes, p_root_nodes);
+ GLTFTemplateConvert::set_from_array(root_nodes, p_root_nodes);
}
Array GLTFState::get_textures() {
- return GLTFDocument::to_array(textures);
+ return GLTFTemplateConvert::to_array(textures);
}
void GLTFState::set_textures(Array p_textures) {
- GLTFDocument::set_from_array(textures, p_textures);
+ GLTFTemplateConvert::set_from_array(textures, p_textures);
}
Array GLTFState::get_images() {
- return GLTFDocument::to_array(images);
+ return GLTFTemplateConvert::to_array(images);
}
void GLTFState::set_images(Array p_images) {
- GLTFDocument::set_from_array(images, p_images);
+ GLTFTemplateConvert::set_from_array(images, p_images);
}
Array GLTFState::get_skins() {
- return GLTFDocument::to_array(skins);
+ return GLTFTemplateConvert::to_array(skins);
}
void GLTFState::set_skins(Array p_skins) {
- GLTFDocument::set_from_array(skins, p_skins);
+ GLTFTemplateConvert::set_from_array(skins, p_skins);
}
Array GLTFState::get_cameras() {
- return GLTFDocument::to_array(cameras);
+ return GLTFTemplateConvert::to_array(cameras);
}
void GLTFState::set_cameras(Array p_cameras) {
- GLTFDocument::set_from_array(cameras, p_cameras);
+ GLTFTemplateConvert::set_from_array(cameras, p_cameras);
}
Array GLTFState::get_lights() {
- return GLTFDocument::to_array(lights);
+ return GLTFTemplateConvert::to_array(lights);
}
void GLTFState::set_lights(Array p_lights) {
- GLTFDocument::set_from_array(lights, p_lights);
+ GLTFTemplateConvert::set_from_array(lights, p_lights);
}
Array GLTFState::get_unique_names() {
- return GLTFDocument::to_array(unique_names);
+ return GLTFTemplateConvert::to_array(unique_names);
}
void GLTFState::set_unique_names(Array p_unique_names) {
- GLTFDocument::set_from_array(unique_names, p_unique_names);
+ GLTFTemplateConvert::set_from_array(unique_names, p_unique_names);
}
Array GLTFState::get_unique_animation_names() {
- return GLTFDocument::to_array(unique_animation_names);
+ return GLTFTemplateConvert::to_array(unique_animation_names);
}
void GLTFState::set_unique_animation_names(Array p_unique_animation_names) {
- GLTFDocument::set_from_array(unique_animation_names, p_unique_animation_names);
+ GLTFTemplateConvert::set_from_array(unique_animation_names, p_unique_animation_names);
}
Array GLTFState::get_skeletons() {
- return GLTFDocument::to_array(skeletons);
+ return GLTFTemplateConvert::to_array(skeletons);
}
void GLTFState::set_skeletons(Array p_skeletons) {
- GLTFDocument::set_from_array(skeletons, p_skeletons);
+ GLTFTemplateConvert::set_from_array(skeletons, p_skeletons);
}
Dictionary GLTFState::get_skeleton_to_node() {
- return GLTFDocument::to_dict(skeleton_to_node);
+ return GLTFTemplateConvert::to_dict(skeleton_to_node);
}
void GLTFState::set_skeleton_to_node(Dictionary p_skeleton_to_node) {
- GLTFDocument::set_from_dict(skeleton_to_node, p_skeleton_to_node);
+ GLTFTemplateConvert::set_from_dict(skeleton_to_node, p_skeleton_to_node);
}
Array GLTFState::get_animations() {
- return GLTFDocument::to_array(animations);
+ return GLTFTemplateConvert::to_array(animations);
}
void GLTFState::set_animations(Array p_animations) {
- GLTFDocument::set_from_array(animations, p_animations);
+ GLTFTemplateConvert::set_from_array(animations, p_animations);
}
Node *GLTFState::get_scene_node(GLTFNodeIndex idx) {
diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h
index 2fdef19038..d2a4948f06 100644
--- a/modules/gltf/gltf_state.h
+++ b/modules/gltf/gltf_state.h
@@ -31,18 +31,17 @@
#ifndef GLTF_STATE_H
#define GLTF_STATE_H
-#include "gltf_accessor.h"
-#include "gltf_animation.h"
-#include "gltf_buffer_view.h"
-#include "gltf_camera.h"
-#include "gltf_document.h"
-#include "gltf_document_extension.h"
-#include "gltf_light.h"
-#include "gltf_mesh.h"
-#include "gltf_node.h"
-#include "gltf_skeleton.h"
-#include "gltf_skin.h"
-#include "gltf_texture.h"
+#include "extensions/gltf_light.h"
+#include "gltf_template_convert.h"
+#include "structures/gltf_accessor.h"
+#include "structures/gltf_animation.h"
+#include "structures/gltf_buffer_view.h"
+#include "structures/gltf_camera.h"
+#include "structures/gltf_mesh.h"
+#include "structures/gltf_node.h"
+#include "structures/gltf_skeleton.h"
+#include "structures/gltf_skin.h"
+#include "structures/gltf_texture.h"
#include "core/templates/rb_map.h"
#include "scene/animation/animation_player.h"
@@ -60,6 +59,7 @@ class GLTFState : public Resource {
Vector<uint8_t> glb_data;
bool use_named_skin_binds = false;
+ bool use_khr_texture_transform = false;
bool discard_meshes_and_materials = false;
Vector<Ref<GLTFNode>> nodes;
@@ -192,4 +192,5 @@ public:
// this->material_cache = p_material_cache;
//}
};
+
#endif // GLTF_STATE_H
diff --git a/modules/gltf/gltf_template_convert.h b/modules/gltf/gltf_template_convert.h
new file mode 100644
index 0000000000..c915d3deb0
--- /dev/null
+++ b/modules/gltf/gltf_template_convert.h
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* gltf_template_convert.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 GLTF_TEMPLATE_CONVERT_H
+#define GLTF_TEMPLATE_CONVERT_H
+
+#include "core/templates/hash_set.h"
+#include "core/variant/array.h"
+#include "core/variant/dictionary.h"
+
+namespace GLTFTemplateConvert {
+template <class T>
+static Array to_array(const Vector<T> &p_inp) {
+ Array ret;
+ for (int i = 0; i < p_inp.size(); i++) {
+ ret.push_back(p_inp[i]);
+ }
+ return ret;
+}
+
+template <class T>
+static Array to_array(const HashSet<T> &p_inp) {
+ Array ret;
+ typename HashSet<T>::Iterator elem = p_inp.begin();
+ while (elem) {
+ ret.push_back(*elem);
+ ++elem;
+ }
+ return ret;
+}
+
+template <class T>
+static void set_from_array(Vector<T> &r_out, const Array &p_inp) {
+ r_out.clear();
+ for (int i = 0; i < p_inp.size(); i++) {
+ r_out.push_back(p_inp[i]);
+ }
+}
+
+template <class T>
+static void set_from_array(HashSet<T> &r_out, const Array &p_inp) {
+ r_out.clear();
+ for (int i = 0; i < p_inp.size(); i++) {
+ r_out.insert(p_inp[i]);
+ }
+}
+
+template <class K, class V>
+static Dictionary to_dict(const HashMap<K, V> &p_inp) {
+ Dictionary ret;
+ for (const KeyValue<K, V> &E : p_inp) {
+ ret[E.key] = E.value;
+ }
+ return ret;
+}
+
+template <class K, class V>
+static void set_from_dict(HashMap<K, V> &r_out, const Dictionary &p_inp) {
+ r_out.clear();
+ Array keys = p_inp.keys();
+ for (int i = 0; i < keys.size(); i++) {
+ r_out[keys[i]] = p_inp[keys[i]];
+ }
+}
+} //namespace GLTFTemplateConvert
+
+#endif // GLTF_TEMPLATE_CONVERT_H
diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp
index b8bac79584..1e1204aa57 100644
--- a/modules/gltf/register_types.cpp
+++ b/modules/gltf/register_types.cpp
@@ -32,21 +32,21 @@
#ifndef _3D_DISABLED
-#include "gltf_accessor.h"
-#include "gltf_animation.h"
-#include "gltf_buffer_view.h"
-#include "gltf_camera.h"
+#include "extensions/gltf_light.h"
+#include "extensions/gltf_spec_gloss.h"
#include "gltf_document.h"
#include "gltf_document_extension.h"
#include "gltf_document_extension_convert_importer_mesh.h"
-#include "gltf_light.h"
-#include "gltf_mesh.h"
-#include "gltf_node.h"
-#include "gltf_skeleton.h"
-#include "gltf_skin.h"
-#include "gltf_spec_gloss.h"
#include "gltf_state.h"
-#include "gltf_texture.h"
+#include "structures/gltf_accessor.h"
+#include "structures/gltf_animation.h"
+#include "structures/gltf_buffer_view.h"
+#include "structures/gltf_camera.h"
+#include "structures/gltf_mesh.h"
+#include "structures/gltf_node.h"
+#include "structures/gltf_skeleton.h"
+#include "structures/gltf_skin.h"
+#include "structures/gltf_texture.h"
#ifdef TOOLS_ENABLED
#include "core/config/project_settings.h"
diff --git a/modules/gltf/gltf_accessor.cpp b/modules/gltf/structures/gltf_accessor.cpp
index 1daf2f90a7..1b8911fe72 100644
--- a/modules/gltf/gltf_accessor.cpp
+++ b/modules/gltf/structures/gltf_accessor.cpp
@@ -30,8 +30,6 @@
#include "gltf_accessor.h"
-#include "gltf_document_extension.h"
-
void GLTFAccessor::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer_view"), &GLTFAccessor::get_buffer_view);
ClassDB::bind_method(D_METHOD("set_buffer_view", "buffer_view"), &GLTFAccessor::set_buffer_view);
@@ -67,7 +65,7 @@ void GLTFAccessor::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "component_type"), "set_component_type", "get_component_type"); // int
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "normalized"), "set_normalized", "get_normalized"); // bool
ADD_PROPERTY(PropertyInfo(Variant::INT, "count"), "set_count", "get_count"); // int
- ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_type", "get_type"); // GLTFDocument::GLTFType
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_type", "get_type"); // GLTFType
ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT64_ARRAY, "min"), "set_min", "get_min"); // Vector<real_t>
ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT64_ARRAY, "max"), "set_max", "get_max"); // Vector<real_t>
ADD_PROPERTY(PropertyInfo(Variant::INT, "sparse_count"), "set_sparse_count", "get_sparse_count"); // int
@@ -123,7 +121,7 @@ int GLTFAccessor::get_type() {
}
void GLTFAccessor::set_type(int p_type) {
- type = (GLTFDocument::GLTFType)p_type; // TODO: Register enum
+ type = (GLTFType)p_type; // TODO: Register enum
}
Vector<double> GLTFAccessor::get_min() {
diff --git a/modules/gltf/gltf_accessor.h b/modules/gltf/structures/gltf_accessor.h
index f412dc2c7f..bfb71d57fe 100644
--- a/modules/gltf/gltf_accessor.h
+++ b/modules/gltf/structures/gltf_accessor.h
@@ -33,7 +33,7 @@
#include "core/io/resource.h"
-#include "gltf_document.h"
+#include "../gltf_defines.h"
struct GLTFAccessor : public Resource {
GDCLASS(GLTFAccessor, Resource);
@@ -45,7 +45,7 @@ private:
int component_type = 0;
bool normalized = false;
int count = 0;
- GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR;
+ GLTFType type = GLTFType::TYPE_SCALAR;
Vector<double> min;
Vector<double> max;
int sparse_count = 0;
@@ -101,4 +101,5 @@ public:
int get_sparse_values_byte_offset();
void set_sparse_values_byte_offset(int p_sparse_values_byte_offset);
};
+
#endif // GLTF_ACCESSOR_H
diff --git a/modules/gltf/gltf_animation.cpp b/modules/gltf/structures/gltf_animation.cpp
index e598c870ab..e598c870ab 100644
--- a/modules/gltf/gltf_animation.cpp
+++ b/modules/gltf/structures/gltf_animation.cpp
diff --git a/modules/gltf/gltf_animation.h b/modules/gltf/structures/gltf_animation.h
index 8688ddb937..3777f579f6 100644
--- a/modules/gltf/gltf_animation.h
+++ b/modules/gltf/structures/gltf_animation.h
@@ -71,4 +71,5 @@ private:
bool loop = false;
HashMap<int, Track> tracks;
};
+
#endif // GLTF_ANIMATION_H
diff --git a/modules/gltf/gltf_buffer_view.cpp b/modules/gltf/structures/gltf_buffer_view.cpp
index fc467367c6..ba19ed8628 100644
--- a/modules/gltf/gltf_buffer_view.cpp
+++ b/modules/gltf/structures/gltf_buffer_view.cpp
@@ -30,7 +30,7 @@
#include "gltf_buffer_view.h"
-#include "gltf_document_extension.h"
+#include "../gltf_document_extension.h"
void GLTFBufferView::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer);
diff --git a/modules/gltf/gltf_buffer_view.h b/modules/gltf/structures/gltf_buffer_view.h
index 560d56f35c..b1f500de25 100644
--- a/modules/gltf/gltf_buffer_view.h
+++ b/modules/gltf/structures/gltf_buffer_view.h
@@ -31,8 +31,8 @@
#ifndef GLTF_BUFFER_VIEW_H
#define GLTF_BUFFER_VIEW_H
+#include "../gltf_defines.h"
#include "core/io/resource.h"
-#include "gltf_document.h"
class GLTFBufferView : public Resource {
GDCLASS(GLTFBufferView, Resource);
@@ -65,4 +65,5 @@ public:
void set_indices(bool p_indices);
// matrices need to be transformed to this
};
+
#endif // GLTF_BUFFER_VIEW_H
diff --git a/modules/gltf/gltf_camera.cpp b/modules/gltf/structures/gltf_camera.cpp
index f3ea6a1c4c..f3ea6a1c4c 100644
--- a/modules/gltf/gltf_camera.cpp
+++ b/modules/gltf/structures/gltf_camera.cpp
diff --git a/modules/gltf/gltf_camera.h b/modules/gltf/structures/gltf_camera.h
index c696d4cc6b..b7df741825 100644
--- a/modules/gltf/gltf_camera.h
+++ b/modules/gltf/structures/gltf_camera.h
@@ -55,4 +55,5 @@ public:
float get_depth_near() const { return depth_near; }
void set_depth_near(float p_val) { depth_near = p_val; }
};
+
#endif // GLTF_CAMERA_H
diff --git a/modules/gltf/gltf_mesh.cpp b/modules/gltf/structures/gltf_mesh.cpp
index 3add8304b1..3add8304b1 100644
--- a/modules/gltf/gltf_mesh.cpp
+++ b/modules/gltf/structures/gltf_mesh.cpp
diff --git a/modules/gltf/gltf_mesh.h b/modules/gltf/structures/gltf_mesh.h
index dc26120b48..dc26120b48 100644
--- a/modules/gltf/gltf_mesh.h
+++ b/modules/gltf/structures/gltf_mesh.h
diff --git a/modules/gltf/gltf_node.cpp b/modules/gltf/structures/gltf_node.cpp
index 86280603fa..86280603fa 100644
--- a/modules/gltf/gltf_node.cpp
+++ b/modules/gltf/structures/gltf_node.cpp
diff --git a/modules/gltf/gltf_node.h b/modules/gltf/structures/gltf_node.h
index 929ad3eca0..1a57ea32e2 100644
--- a/modules/gltf/gltf_node.h
+++ b/modules/gltf/structures/gltf_node.h
@@ -31,8 +31,8 @@
#ifndef GLTF_NODE_H
#define GLTF_NODE_H
+#include "../gltf_defines.h"
#include "core/io/resource.h"
-#include "gltf_document.h"
class GLTFNode : public Resource {
GDCLASS(GLTFNode, Resource);
@@ -97,4 +97,5 @@ public:
GLTFLightIndex get_light();
void set_light(GLTFLightIndex p_light);
};
+
#endif // GLTF_NODE_H
diff --git a/modules/gltf/gltf_skeleton.cpp b/modules/gltf/structures/gltf_skeleton.cpp
index b813f39a27..90a6b0f50f 100644
--- a/modules/gltf/gltf_skeleton.cpp
+++ b/modules/gltf/structures/gltf_skeleton.cpp
@@ -30,6 +30,9 @@
#include "gltf_skeleton.h"
+#include "../gltf_template_convert.h"
+#include "scene/3d/bone_attachment_3d.h"
+
void GLTFSkeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_joints"), &GLTFSkeleton::get_joints);
ClassDB::bind_method(D_METHOD("set_joints", "joints"), &GLTFSkeleton::set_joints);
@@ -70,19 +73,19 @@ Skeleton3D *GLTFSkeleton::get_godot_skeleton() {
}
Array GLTFSkeleton::get_unique_names() {
- return GLTFDocument::to_array(unique_names);
+ return GLTFTemplateConvert::to_array(unique_names);
}
void GLTFSkeleton::set_unique_names(Array p_unique_names) {
- GLTFDocument::set_from_array(unique_names, p_unique_names);
+ GLTFTemplateConvert::set_from_array(unique_names, p_unique_names);
}
Dictionary GLTFSkeleton::get_godot_bone_node() {
- return GLTFDocument::to_dict(godot_bone_node);
+ return GLTFTemplateConvert::to_dict(godot_bone_node);
}
void GLTFSkeleton::set_godot_bone_node(Dictionary p_indict) {
- GLTFDocument::set_from_dict(godot_bone_node, p_indict);
+ GLTFTemplateConvert::set_from_dict(godot_bone_node, p_indict);
}
BoneAttachment3D *GLTFSkeleton::get_bone_attachment(int idx) {
diff --git a/modules/gltf/gltf_skeleton.h b/modules/gltf/structures/gltf_skeleton.h
index 92ee6e6234..db88623213 100644
--- a/modules/gltf/gltf_skeleton.h
+++ b/modules/gltf/structures/gltf_skeleton.h
@@ -31,8 +31,8 @@
#ifndef GLTF_SKELETON_H
#define GLTF_SKELETON_H
+#include "../gltf_defines.h"
#include "core/io/resource.h"
-#include "gltf_document.h"
class GLTFSkeleton : public Resource {
GDCLASS(GLTFSkeleton, Resource);
@@ -98,4 +98,5 @@ public:
int32_t get_bone_attachment_count();
};
+
#endif // GLTF_SKELETON_H
diff --git a/modules/gltf/gltf_skin.cpp b/modules/gltf/structures/gltf_skin.cpp
index e8005aa0c1..2e46ee3be2 100644
--- a/modules/gltf/gltf_skin.cpp
+++ b/modules/gltf/structures/gltf_skin.cpp
@@ -30,6 +30,9 @@
#include "gltf_skin.h"
+#include "../gltf_template_convert.h"
+#include "scene/resources/skin.h"
+
void GLTFSkin::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_skin_root"), &GLTFSkin::get_skin_root);
ClassDB::bind_method(D_METHOD("set_skin_root", "skin_root"), &GLTFSkin::set_skin_root);
@@ -81,11 +84,11 @@ void GLTFSkin::set_joints_original(Vector<GLTFNodeIndex> p_joints_original) {
}
Array GLTFSkin::get_inverse_binds() {
- return GLTFDocument::to_array(inverse_binds);
+ return GLTFTemplateConvert::to_array(inverse_binds);
}
void GLTFSkin::set_inverse_binds(Array p_inverse_binds) {
- GLTFDocument::set_from_array(inverse_binds, p_inverse_binds);
+ GLTFTemplateConvert::set_from_array(inverse_binds, p_inverse_binds);
}
Vector<GLTFNodeIndex> GLTFSkin::get_joints() {
@@ -121,11 +124,11 @@ void GLTFSkin::set_skeleton(int p_skeleton) {
}
Dictionary GLTFSkin::get_joint_i_to_bone_i() {
- return GLTFDocument::to_dict(joint_i_to_bone_i);
+ return GLTFTemplateConvert::to_dict(joint_i_to_bone_i);
}
void GLTFSkin::set_joint_i_to_bone_i(Dictionary p_joint_i_to_bone_i) {
- GLTFDocument::set_from_dict(joint_i_to_bone_i, p_joint_i_to_bone_i);
+ GLTFTemplateConvert::set_from_dict(joint_i_to_bone_i, p_joint_i_to_bone_i);
}
Dictionary GLTFSkin::get_joint_i_to_name() {
diff --git a/modules/gltf/gltf_skin.h b/modules/gltf/structures/gltf_skin.h
index d946324756..59b6a300ac 100644
--- a/modules/gltf/gltf_skin.h
+++ b/modules/gltf/structures/gltf_skin.h
@@ -31,8 +31,8 @@
#ifndef GLTF_SKIN_H
#define GLTF_SKIN_H
+#include "../gltf_defines.h"
#include "core/io/resource.h"
-#include "gltf_document.h"
class GLTFSkin : public Resource {
GDCLASS(GLTFSkin, Resource);
@@ -106,4 +106,5 @@ public:
Ref<Skin> get_godot_skin();
void set_godot_skin(Ref<Skin> p_godot_skin);
};
+
#endif // GLTF_SKIN_H
diff --git a/modules/gltf/gltf_texture.cpp b/modules/gltf/structures/gltf_texture.cpp
index 2a21cb3df8..2a21cb3df8 100644
--- a/modules/gltf/gltf_texture.cpp
+++ b/modules/gltf/structures/gltf_texture.cpp
diff --git a/modules/gltf/gltf_texture.h b/modules/gltf/structures/gltf_texture.h
index 54dd61f9a5..b1d12dddfa 100644
--- a/modules/gltf/gltf_texture.h
+++ b/modules/gltf/structures/gltf_texture.h
@@ -31,8 +31,8 @@
#ifndef GLTF_TEXTURE_H
#define GLTF_TEXTURE_H
+#include "../gltf_defines.h"
#include "core/io/resource.h"
-#include "gltf_document.h"
class GLTFTexture : public Resource {
GDCLASS(GLTFTexture, Resource);
diff --git a/modules/gridmap/SCsub b/modules/gridmap/SCsub
index 52777235b8..da3f7d4dd9 100644
--- a/modules/gridmap/SCsub
+++ b/modules/gridmap/SCsub
@@ -5,7 +5,7 @@ Import("env_modules")
env_gridmap = env_modules.Clone()
-# Godot's own source files
+# Godot source files
env_gridmap.add_source_files(env.modules_sources, "*.cpp")
if env["tools"]:
env_gridmap.add_source_files(env.modules_sources, "editor/*.cpp")
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp
index b694c109e1..09f0ff32f0 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp
@@ -545,7 +545,7 @@ void GridMapEditor::_update_paste_indicator() {
Basis rot;
rot.set_orthogonal_index(paste_indicator.orientation);
xf.basis = rot * xf.basis;
- xf.translate((-center * node->get_cell_size()) / scale);
+ xf.translate_local((-center * node->get_cell_size()) / scale);
RenderingServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf);
@@ -553,7 +553,7 @@ void GridMapEditor::_update_paste_indicator() {
xf = Transform3D();
xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size();
xf.basis = rot * xf.basis;
- xf.translate(item.grid_offset * node->get_cell_size());
+ xf.translate_local(item.grid_offset * node->get_cell_size());
Basis item_rot;
item_rot.set_orthogonal_index(item.orientation);
@@ -1231,14 +1231,14 @@ GridMapEditor::GridMapEditor() {
mode_thumbnail->set_toggle_mode(true);
mode_thumbnail->set_pressed(true);
hb->add_child(mode_thumbnail);
- mode_thumbnail->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_THUMBNAIL));
+ mode_thumbnail->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode).bind(DISPLAY_THUMBNAIL));
mode_list = memnew(Button);
mode_list->set_flat(true);
mode_list->set_toggle_mode(true);
mode_list->set_pressed(false);
hb->add_child(mode_list);
- mode_list->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_LIST));
+ mode_list->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode).bind(DISPLAY_LIST));
size_slider = memnew(HSlider);
size_slider->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1262,7 +1262,7 @@ GridMapEditor::GridMapEditor() {
info_message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
info_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ info_message->set_anchors_and_offsets_preset(PRESET_FULL_RECT, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
mesh_library_palette->add_child(info_message);
edit_axis = Vector3::AXIS_Y;
diff --git a/modules/hdr/SCsub b/modules/hdr/SCsub
index a709397c9a..10629bda3c 100644
--- a/modules/hdr/SCsub
+++ b/modules/hdr/SCsub
@@ -5,5 +5,5 @@ Import("env_modules")
env_hdr = env_modules.Clone()
-# Godot's own source files
+# Godot source files
env_hdr.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/hdr/image_loader_hdr.h b/modules/hdr/image_loader_hdr.h
index f2d53cc206..16c0816562 100644
--- a/modules/hdr/image_loader_hdr.h
+++ b/modules/hdr/image_loader_hdr.h
@@ -40,4 +40,4 @@ public:
ImageLoaderHDR();
};
-#endif
+#endif // IMAGE_LOADER_HDR_H
diff --git a/modules/jpg/image_loader_jpegd.h b/modules/jpg/image_loader_jpegd.h
index de9700faec..6d631446e7 100644
--- a/modules/jpg/image_loader_jpegd.h
+++ b/modules/jpg/image_loader_jpegd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef IMAGE_LOADER_JPG_H
-#define IMAGE_LOADER_JPG_H
+#ifndef IMAGE_LOADER_JPEGD_H
+#define IMAGE_LOADER_JPEGD_H
#include "core/io/image_loader.h"
@@ -40,4 +40,4 @@ public:
ImageLoaderJPG();
};
-#endif
+#endif // IMAGE_LOADER_JPEGD_H
diff --git a/modules/jsonrpc/jsonrpc.h b/modules/jsonrpc/jsonrpc.h
index f57d6aef42..1d9f2771b2 100644
--- a/modules/jsonrpc/jsonrpc.h
+++ b/modules/jsonrpc/jsonrpc.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_JSON_RPC_H
-#define GODOT_JSON_RPC_H
+#ifndef JSONRPC_H
+#define JSONRPC_H
#include "core/object/class_db.h"
#include "core/variant/variant.h"
@@ -67,4 +67,4 @@ public:
VARIANT_ENUM_CAST(JSONRPC::ErrorCode);
-#endif
+#endif // JSONRPC_H
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/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp
index 2ce3715bea..83ac478a97 100644
--- a/modules/lightmapper_rd/lightmapper_rd.cpp
+++ b/modules/lightmapper_rd/lightmapper_rd.cpp
@@ -271,8 +271,8 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_
mi.offset.x = best_atlas_offsets[m_i].x;
mi.offset.y = best_atlas_offsets[m_i].y;
mi.slice = best_atlas_offsets[m_i].z;
- albedo_images.write[mi.slice]->blit_rect(mi.data.albedo_on_uv2, Rect2(Vector2(), Size2i(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height())), mi.offset);
- emission_images.write[mi.slice]->blit_rect(mi.data.emission_on_uv2, Rect2(Vector2(), Size2i(mi.data.emission_on_uv2->get_width(), mi.data.emission_on_uv2->get_height())), mi.offset);
+ albedo_images.write[mi.slice]->blit_rect(mi.data.albedo_on_uv2, Rect2i(Vector2i(), mi.data.albedo_on_uv2->get_size()), mi.offset);
+ emission_images.write[mi.slice]->blit_rect(mi.data.emission_on_uv2, Rect2(Vector2i(), mi.data.emission_on_uv2->get_size()), mi.offset);
}
return BAKE_OK;
@@ -1420,7 +1420,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
img2.instantiate();
img2->create(2, 2, false, Image::FORMAT_RGBAF, s);
img2->convert(Image::FORMAT_RGB8);
- img->blit_rect(img2, Rect2(0, 0, 2, 2), Point2((j % 3) * 2, (j / 3) * 2));
+ img->blit_rect(img2, Rect2i(0, 0, 2, 2), Point2i((j % 3) * 2, (j / 3) * 2));
}
img->save_png("res://3_light_probe_" + itos(i) + ".png");
}
diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h
index 8cb4b58a18..bf6b4399ca 100644
--- a/modules/lightmapper_rd/lightmapper_rd.h
+++ b/modules/lightmapper_rd/lightmapper_rd.h
@@ -183,7 +183,7 @@ class LightmapperRD : public Lightmapper {
}
};
- void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size);
+ void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[3], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size);
struct RasterPushConstant {
float atlas_size[2] = {};
@@ -256,4 +256,4 @@ public:
LightmapperRD();
};
-#endif // LIGHTMAPPER_H
+#endif // LIGHTMAPPER_RD_H
diff --git a/modules/lightmapper_rd/register_types.h b/modules/lightmapper_rd/register_types.h
index 42e0ebbf77..9b72ff45d7 100644
--- a/modules/lightmapper_rd/register_types.h
+++ b/modules/lightmapper_rd/register_types.h
@@ -36,4 +36,4 @@
void initialize_lightmapper_rd_module(ModuleInitializationLevel p_level);
void uninitialize_lightmapper_rd_module(ModuleInitializationLevel p_level);
-#endif // XATLAS_UNWRAP_REGISTER_TYPES_H
+#endif // LIGHTMAPPER_RD_REGISTER_TYPES_H
diff --git a/modules/mbedtls/dtls_server_mbedtls.h b/modules/mbedtls/dtls_server_mbedtls.h
index 29370062c4..a6626c9f65 100644
--- a/modules/mbedtls/dtls_server_mbedtls.h
+++ b/modules/mbedtls/dtls_server_mbedtls.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef MBED_DTLS_SERVER_H
-#define MBED_DTLS_SERVER_H
+#ifndef DTLS_SERVER_MBEDTLS_H
+#define DTLS_SERVER_MBEDTLS_H
#include "core/io/dtls_server.h"
#include "ssl_context_mbedtls.h"
@@ -54,4 +54,4 @@ public:
~DTLSServerMbedTLS();
};
-#endif // MBED_DTLS_SERVER_H
+#endif // DTLS_SERVER_MBEDTLS_H
diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/ssl_context_mbedtls.h
index dd49792abd..5883388311 100644
--- a/modules/mbedtls/ssl_context_mbedtls.h
+++ b/modules/mbedtls/ssl_context_mbedtls.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SSL_CONTEXT_MBED_TLS_H
-#define SSL_CONTEXT_MBED_TLS_H
+#ifndef SSL_CONTEXT_MBEDTLS_H
+#define SSL_CONTEXT_MBEDTLS_H
#include "crypto_mbedtls.h"
@@ -90,4 +90,4 @@ public:
~SSLContextMbedTLS();
};
-#endif // SSL_CONTEXT_MBED_TLS_H
+#endif // SSL_CONTEXT_MBEDTLS_H
diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h
index 7660410e04..68b07feea9 100644
--- a/modules/mbedtls/stream_peer_mbedtls.h
+++ b/modules/mbedtls/stream_peer_mbedtls.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef STREAM_PEER_OPEN_SSL_H
-#define STREAM_PEER_OPEN_SSL_H
+#ifndef STREAM_PEER_MBEDTLS_H
+#define STREAM_PEER_MBEDTLS_H
#include "core/io/stream_peer_ssl.h"
#include "ssl_context_mbedtls.h"
@@ -76,4 +76,4 @@ public:
~StreamPeerMbedTLS();
};
-#endif // STREAM_PEER_SSL_H
+#endif // STREAM_PEER_MBEDTLS_H
diff --git a/modules/meshoptimizer/register_types.h b/modules/meshoptimizer/register_types.h
index 99c71efceb..3a84aab7bc 100644
--- a/modules/meshoptimizer/register_types.h
+++ b/modules/meshoptimizer/register_types.h
@@ -36,4 +36,4 @@
void initialize_meshoptimizer_module(ModuleInitializationLevel p_level);
void uninitialize_meshoptimizer_module(ModuleInitializationLevel p_level);
-#endif // PVR_REGISTER_TYPES_H
+#endif // MESHOPTIMIZER_REGISTER_TYPES_H
diff --git a/modules/minimp3/SCsub b/modules/minimp3/SCsub
index f4d1605d55..20e3165f38 100644
--- a/modules/minimp3/SCsub
+++ b/modules/minimp3/SCsub
@@ -13,5 +13,5 @@ if not env.msvc:
else:
env_minimp3.Prepend(CPPPATH=[thirdparty_dir])
-# Godot's own source files
+# Godot source files
env_minimp3.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp
index c37bea519f..98bcdea8f4 100644
--- a/modules/minimp3/audio_stream_mp3.cpp
+++ b/modules/minimp3/audio_stream_mp3.cpp
@@ -46,6 +46,12 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {
int frames_mixed_this_step = p_frames;
+ int beat_length_frames = -1;
+ bool beat_loop = mp3_stream->has_loop() && mp3_stream->get_bpm() > 0 && mp3_stream->get_beat_count() > 0;
+ if (beat_loop) {
+ beat_length_frames = mp3_stream->get_beat_count() * mp3_stream->sample_rate * 60 / mp3_stream->get_bpm();
+ }
+
while (todo && active) {
mp3dec_frame_info_t frame_info;
mp3d_sample_t *buf_frame = nullptr;
@@ -54,8 +60,25 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) {
if (samples_mixed) {
p_buffer[p_frames - todo] = AudioFrame(buf_frame[0], buf_frame[samples_mixed - 1]);
+ if (loop_fade_remaining < FADE_SIZE) {
+ p_buffer[p_frames - todo] += loop_fade[loop_fade_remaining] * (float(FADE_SIZE - loop_fade_remaining) / float(FADE_SIZE));
+ loop_fade_remaining++;
+ }
--todo;
++frames_mixed;
+
+ if (beat_loop && (int)frames_mixed >= beat_length_frames) {
+ for (int i = 0; i < FADE_SIZE; i++) {
+ samples_mixed = mp3dec_ex_read_frame(mp3d, &buf_frame, &frame_info, mp3_stream->channels);
+ loop_fade[i] = AudioFrame(buf_frame[0], buf_frame[samples_mixed - 1]);
+ if (!samples_mixed) {
+ break;
+ }
+ }
+ loop_fade_remaining = 0;
+ seek(mp3_stream->loop_offset);
+ loops++;
+ }
}
else {
@@ -117,6 +140,10 @@ void AudioStreamPlaybackMP3::seek(float p_time) {
mp3dec_ex_seek(mp3d, (uint64_t)frames_mixed * mp3_stream->channels);
}
+void AudioStreamPlaybackMP3::tag_used_streams() {
+ mp3_stream->tag_used(get_playback_position());
+}
+
AudioStreamPlaybackMP3::~AudioStreamPlaybackMP3() {
if (mp3d) {
mp3dec_ex_close(mp3d);
@@ -124,7 +151,7 @@ AudioStreamPlaybackMP3::~AudioStreamPlaybackMP3() {
}
}
-Ref<AudioStreamPlayback> AudioStreamMP3::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamMP3::instantiate_playback() {
Ref<AudioStreamPlaybackMP3> mp3s;
ERR_FAIL_COND_V_MSG(data.is_empty(), mp3s,
@@ -206,6 +233,36 @@ bool AudioStreamMP3::is_monophonic() const {
return false;
}
+void AudioStreamMP3::set_bpm(double p_bpm) {
+ ERR_FAIL_COND(p_bpm < 0);
+ bpm = p_bpm;
+ emit_changed();
+}
+
+double AudioStreamMP3::get_bpm() const {
+ return bpm;
+}
+
+void AudioStreamMP3::set_beat_count(int p_beat_count) {
+ ERR_FAIL_COND(p_beat_count < 0);
+ beat_count = p_beat_count;
+ emit_changed();
+}
+
+int AudioStreamMP3::get_beat_count() const {
+ return beat_count;
+}
+
+void AudioStreamMP3::set_bar_beats(int p_bar_beats) {
+ ERR_FAIL_COND(p_bar_beats < 0);
+ bar_beats = p_bar_beats;
+ emit_changed();
+}
+
+int AudioStreamMP3::get_bar_beats() const {
+ return bar_beats;
+}
+
void AudioStreamMP3::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamMP3::set_data);
ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamMP3::get_data);
@@ -216,7 +273,19 @@ void AudioStreamMP3::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamMP3::set_loop_offset);
ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamMP3::get_loop_offset);
+ ClassDB::bind_method(D_METHOD("set_bpm", "bpm"), &AudioStreamMP3::set_bpm);
+ ClassDB::bind_method(D_METHOD("get_bpm"), &AudioStreamMP3::get_bpm);
+
+ ClassDB::bind_method(D_METHOD("set_beat_count", "count"), &AudioStreamMP3::set_beat_count);
+ ClassDB::bind_method(D_METHOD("get_beat_count"), &AudioStreamMP3::get_beat_count);
+
+ ClassDB::bind_method(D_METHOD("set_bar_beats", "count"), &AudioStreamMP3::set_bar_beats);
+ ClassDB::bind_method(D_METHOD("get_bar_beats"), &AudioStreamMP3::get_bar_beats);
+
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), "set_bpm", "get_bpm");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,1,or_greater"), "set_beat_count", "get_beat_count");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,1,or_greater"), "set_bar_beats", "get_bar_beats");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset"), "set_loop_offset", "get_loop_offset");
}
diff --git a/modules/minimp3/audio_stream_mp3.h b/modules/minimp3/audio_stream_mp3.h
index c1a60ddccb..428ac1240e 100644
--- a/modules/minimp3/audio_stream_mp3.h
+++ b/modules/minimp3/audio_stream_mp3.h
@@ -41,6 +41,12 @@ class AudioStreamMP3;
class AudioStreamPlaybackMP3 : public AudioStreamPlaybackResampled {
GDCLASS(AudioStreamPlaybackMP3, AudioStreamPlaybackResampled);
+ enum {
+ FADE_SIZE = 256
+ };
+ AudioFrame loop_fade[FADE_SIZE];
+ int loop_fade_remaining = FADE_SIZE;
+
mp3dec_ex_t *mp3d = nullptr;
uint32_t frames_mixed = 0;
bool active = false;
@@ -64,6 +70,8 @@ public:
virtual float get_playback_position() const override;
virtual void seek(float p_time) override;
+ virtual void tag_used_streams() override;
+
AudioStreamPlaybackMP3() {}
~AudioStreamPlaybackMP3();
};
@@ -85,17 +93,30 @@ class AudioStreamMP3 : public AudioStream {
float loop_offset = 0.0;
void clear_data();
+ double bpm = 0;
+ int beat_count = 0;
+ int bar_beats = 4;
+
protected:
static void _bind_methods();
public:
void set_loop(bool p_enable);
- bool has_loop() const;
+ virtual bool has_loop() const override;
void set_loop_offset(float p_seconds);
float get_loop_offset() const;
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ void set_bpm(double p_bpm);
+ virtual double get_bpm() const override;
+
+ void set_beat_count(int p_beat_count);
+ virtual int get_beat_count() const override;
+
+ void set_bar_beats(int p_bar_beats);
+ virtual int get_bar_beats() const override;
+
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
void set_data(const Vector<uint8_t> &p_data);
diff --git a/modules/minimp3/doc_classes/AudioStreamMP3.xml b/modules/minimp3/doc_classes/AudioStreamMP3.xml
index f5f7d3ef17..8f03681c06 100644
--- a/modules/minimp3/doc_classes/AudioStreamMP3.xml
+++ b/modules/minimp3/doc_classes/AudioStreamMP3.xml
@@ -4,13 +4,42 @@
MP3 audio stream driver.
</brief_description>
<description>
- MP3 audio stream driver.
+ MP3 audio stream driver. See [member data] if you want to load an MP3 file at run-time.
</description>
<tutorials>
</tutorials>
<members>
+ <member name="bar_beats" type="int" setter="set_bar_beats" getter="get_bar_beats" default="4">
+ </member>
+ <member name="beat_count" type="int" setter="set_beat_count" getter="get_beat_count" default="0">
+ </member>
+ <member name="bpm" type="float" setter="set_bpm" getter="get_bpm" default="0.0">
+ </member>
<member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()">
Contains the audio data in bytes.
+ You can load a file without having to import it beforehand using the code snippet below. Keep in mind that this snippet loads the whole file into memory and may not be ideal for huge files (hundreds of megabytes or more).
+ [codeblocks]
+ [gdscript]
+ func load_mp3(path):
+ var file = File.new()
+ file.open(path, File.READ)
+ var sound = AudioStreamMP3.new()
+ sound.data = file.get_buffer(file.get_length())
+ file.close()
+ return sound
+ [/gdscript]
+ [csharp]
+ public AudioStreamMP3 LoadMP3(string path)
+ {
+ var file = new File();
+ file.Open(path, File.READ);
+ var sound = new AudioStreamMP3();
+ sound.Data = file.GetBuffer(file.GetLength());
+ file.Close();
+ return sound;
+ }
+ [/csharp]
+ [/codeblocks]
</member>
<member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false">
If [code]true[/code], the stream will automatically loop when it reaches the end.
diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp
index e03940f963..7492533094 100644
--- a/modules/minimp3/resource_importer_mp3.cpp
+++ b/modules/minimp3/resource_importer_mp3.cpp
@@ -34,6 +34,10 @@
#include "core/io/resource_saver.h"
#include "scene/resources/texture.h"
+#ifdef TOOLS_ENABLED
+#include "editor/import/audio_stream_import_settings.h"
+#endif
+
String ResourceImporterMP3::get_importer_name() const {
return "mp3";
}
@@ -69,14 +73,26 @@ String ResourceImporterMP3::get_preset_name(int p_idx) const {
void ResourceImporterMP3::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,or_greater"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,or_greater"), 4));
}
-Error ResourceImporterMP3::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) {
- bool loop = p_options["loop"];
- float loop_offset = p_options["loop_offset"];
+#ifdef TOOLS_ENABLED
+bool ResourceImporterMP3::has_advanced_options() const {
+ return true;
+}
+void ResourceImporterMP3::show_advanced_options(const String &p_path) {
+ Ref<AudioStreamMP3> mp3_stream = import_mp3(p_path);
+ if (mp3_stream.is_valid()) {
+ AudioStreamImportSettings::get_singleton()->edit(p_path, "mp3", mp3_stream);
+ }
+}
+#endif
- Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ);
- ERR_FAIL_COND_V(f.is_null(), ERR_CANT_OPEN);
+Ref<AudioStreamMP3> ResourceImporterMP3::import_mp3(const String &p_path) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V(f.is_null(), Ref<AudioStreamMP3>());
uint64_t len = f->get_length();
@@ -90,11 +106,29 @@ Error ResourceImporterMP3::import(const String &p_source_file, const String &p_s
mp3_stream.instantiate();
mp3_stream->set_data(data);
- ERR_FAIL_COND_V(!mp3_stream->get_data().size(), ERR_FILE_CORRUPT);
+ ERR_FAIL_COND_V(!mp3_stream->get_data().size(), Ref<AudioStreamMP3>());
+
+ return mp3_stream;
+}
+
+Error ResourceImporterMP3::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) {
+ bool loop = p_options["loop"];
+ float loop_offset = p_options["loop_offset"];
+ double bpm = p_options["bpm"];
+ float beat_count = p_options["beat_count"];
+ float bar_beats = p_options["bar_beats"];
+
+ Ref<AudioStreamMP3> mp3_stream = import_mp3(p_source_file);
+ if (mp3_stream.is_null()) {
+ return ERR_CANT_OPEN;
+ }
mp3_stream->set_loop(loop);
mp3_stream->set_loop_offset(loop_offset);
+ mp3_stream->set_bpm(bpm);
+ mp3_stream->set_beat_count(beat_count);
+ mp3_stream->set_bar_beats(bar_beats);
- return ResourceSaver::save(p_save_path + ".mp3str", mp3_stream);
+ return ResourceSaver::save(mp3_stream, p_save_path + ".mp3str");
}
ResourceImporterMP3::ResourceImporterMP3() {
diff --git a/modules/minimp3/resource_importer_mp3.h b/modules/minimp3/resource_importer_mp3.h
index 678a3773bb..38729d68f8 100644
--- a/modules/minimp3/resource_importer_mp3.h
+++ b/modules/minimp3/resource_importer_mp3.h
@@ -50,6 +50,12 @@ public:
virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override;
virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override;
+#ifdef TOOLS_ENABLED
+ virtual bool has_advanced_options() const override;
+ virtual void show_advanced_options(const String &p_path) override;
+#endif
+ static Ref<AudioStreamMP3> import_mp3(const String &p_path);
+
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;
ResourceImporterMP3();
diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp
index 5876b6cbf3..b14f5f469c 100644
--- a/modules/mobile_vr/mobile_vr_interface.cpp
+++ b/modules/mobile_vr/mobile_vr_interface.cpp
@@ -45,7 +45,7 @@ uint32_t MobileVRInterface::get_capabilities() const {
Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) {
// Our magnetometer doesn't give us nice clean data.
- // Well it may on Mac OS X because we're getting a calibrated value in the current implementation but Android we're getting raw data.
+ // Well it may on macOS because we're getting a calibrated value in the current implementation but Android we're getting raw data.
// This is a fairly simple adjustment we can do to correct for the magnetometer data being elliptical
Vector3 mag_raw = p_magnetometer;
@@ -452,10 +452,10 @@ Transform3D MobileVRInterface::get_transform_for_view(uint32_t p_view, const Tra
return transform_for_eye;
};
-CameraMatrix MobileVRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
+Projection MobileVRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
_THREAD_SAFE_METHOD_
- CameraMatrix eye;
+ Projection eye;
aspect = p_aspect;
eye.set_for_hmd(p_view + 1, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far);
diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h
index 8ecca3a2ae..b934a09dd3 100644
--- a/modules/mobile_vr/mobile_vr_interface.h
+++ b/modules/mobile_vr/mobile_vr_interface.h
@@ -150,7 +150,7 @@ public:
virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
- virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
+ virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void process() override;
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index 3bafa351a9..d10ebc7b47 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -55,7 +55,7 @@ env_mono.add_source_files(env.modules_sources, "utils/*.cpp")
env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.cpp")
-if env["platform"] in ["osx", "iphone"]:
+if env["platform"] in ["macos", "ios"]:
env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.mm")
env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.m")
elif env["platform"] == "android":
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/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index 8e441e7e07..e69904c54b 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -63,15 +63,15 @@ def copy_file(src_dir, dst_dir, src_name, dst_name=""):
def is_desktop(platform):
- return platform in ["windows", "osx", "linuxbsd", "server", "uwp", "haiku"]
+ return platform in ["windows", "macos", "linuxbsd", "server", "uwp", "haiku"]
def is_unix_like(platform):
- return platform in ["osx", "linuxbsd", "server", "android", "haiku", "iphone"]
+ return platform in ["macos", "linuxbsd", "server", "android", "haiku", "ios"]
def module_supports_tools_on(platform):
- return platform not in ["android", "javascript", "iphone"]
+ return platform not in ["android", "javascript", "ios"]
def find_wasm_src_dir(mono_root):
@@ -89,7 +89,7 @@ def configure(env, env_mono):
bits = env["bits"]
is_android = env["platform"] == "android"
is_javascript = env["platform"] == "javascript"
- is_ios = env["platform"] == "iphone"
+ is_ios = env["platform"] == "ios"
is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"]
tools_enabled = env["tools"]
@@ -206,7 +206,7 @@ def configure(env, env_mono):
copy_file(mono_bin_path, "#bin", mono_dll_file)
else:
- is_apple = env["platform"] in ["osx", "iphone"]
+ is_apple = env["platform"] in ["macos", "ios"]
is_macos = is_apple and not is_ios
sharedlib_ext = ".dylib" if is_apple else ".so"
@@ -221,7 +221,7 @@ def configure(env, env_mono):
)
if not mono_root and is_macos:
- # Try with some known directories under OSX
+ # Try with some known directories under macOS
hint_dirs = ["/Library/Frameworks/Mono.framework/Versions/Current", "/usr/local/var/homebrew/linked/mono"]
for hint_dir in hint_dirs:
if os.path.isdir(hint_dir):
@@ -270,7 +270,7 @@ def configure(env, env_mono):
def copy_mono_lib(libname_wo_ext):
copy_file(
- mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.iphone.%s.a" % (libname_wo_ext, arch)
+ mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.ios.%s.a" % (libname_wo_ext, arch)
)
# Copy Mono libraries to the output folder. These are meant to be bundled with
@@ -539,7 +539,7 @@ def copy_mono_shared_libs(env, mono_root, target_mono_root_dir):
os.makedirs(target_mono_lib_dir)
lib_file_names = []
- if platform == "osx":
+ if platform == "macos":
lib_file_names = [
lib_name + ".dylib"
for lib_name in ["libmono-btls-shared", "libmono-native-compat", "libMonoPosixHelper"]
diff --git a/modules/mono/config.py b/modules/mono/config.py
index df02d9a309..d895d2d92d 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -1,56 +1,48 @@
-supported_platforms = ["windows", "osx", "linuxbsd", "server", "android", "haiku", "javascript", "iphone"]
+supported_platforms = ["windows", "macos", "linuxbsd", "server", "android", "haiku", "javascript", "ios"]
def can_build(env, platform):
return not env["arch"].startswith("rv")
-def configure(env):
- platform = env["platform"]
-
- if platform not in supported_platforms:
- raise RuntimeError("This module does not currently support building for this platform")
+def get_opts(platform):
+ from SCons.Variables import BoolVariable, PathVariable
- env.add_module_version_string("mono")
-
- from SCons.Script import BoolVariable, PathVariable, Variables, Help
-
- default_mono_static = platform in ["iphone", "javascript"]
+ default_mono_static = platform in ["ios", "javascript"]
default_mono_bundles_zlib = platform in ["javascript"]
- envvars = Variables()
- envvars.Add(
+ return [
PathVariable(
"mono_prefix",
"Path to the Mono installation directory for the target platform and architecture",
"",
PathVariable.PathAccept,
- )
- )
- envvars.Add(
+ ),
PathVariable(
"mono_bcl",
"Path to a custom Mono BCL (Base Class Library) directory for the target platform",
"",
PathVariable.PathAccept,
- )
- )
- envvars.Add(BoolVariable("mono_static", "Statically link Mono", default_mono_static))
- envvars.Add(BoolVariable("mono_glue", "Build with the Mono glue sources", True))
- envvars.Add(BoolVariable("build_cil", "Build C# solutions", True))
- envvars.Add(
- BoolVariable("copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True)
- )
-
- # TODO: It would be great if this could be detected automatically instead
- envvars.Add(
+ ),
+ BoolVariable("mono_static", "Statically link Mono", default_mono_static),
+ BoolVariable("mono_glue", "Build with the Mono glue sources", True),
+ BoolVariable("build_cil", "Build C# solutions", True),
+ BoolVariable(
+ "copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True
+ ),
BoolVariable(
"mono_bundles_zlib", "Specify if the Mono runtime was built with bundled zlib", default_mono_bundles_zlib
- )
- )
+ ),
+ ]
+
+
+def configure(env):
+ platform = env["platform"]
- envvars.Update(env)
- Help(envvars.GenerateHelpText(env))
+ if platform not in supported_platforms:
+ raise RuntimeError("This module does not currently support building for this platform")
+
+ env.add_module_version_string("mono")
if env["mono_bundles_zlib"]:
# Mono may come with zlib bundled for WASM or on newer version when built with MinGW.
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 622838b308..475b483d6c 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -481,11 +481,14 @@ static String variant_type_to_managed_name(const String &p_var_type_name) {
Variant::VECTOR3,
Variant::VECTOR3I,
Variant::TRANSFORM2D,
+ Variant::VECTOR4,
+ Variant::VECTOR4I,
Variant::PLANE,
Variant::QUATERNION,
Variant::AABB,
Variant::BASIS,
Variant::TRANSFORM3D,
+ Variant::PROJECTION,
Variant::COLOR,
Variant::STRING_NAME,
Variant::NODE_PATH,
@@ -1798,9 +1801,7 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName,
void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
List<PropertyInfo> props;
- for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) {
- props.push_front(E.value);
- }
+ script->get_script_property_list(&props);
// Call _get_property_list
@@ -2138,8 +2139,8 @@ bool CSharpInstance::refcount_decremented() {
return ref_dying;
}
-const Vector<Multiplayer::RPCConfig> CSharpInstance::get_rpc_methods() const {
- return script->get_rpc_methods();
+const Variant CSharpInstance::get_rpc_config() const {
+ return script->get_rpc_config();
}
void CSharpInstance::notification(int p_notification) {
@@ -2332,10 +2333,6 @@ void CSharpScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder)
#ifdef TOOLS_ENABLED
void CSharpScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) {
- if (base_cache.is_valid()) {
- base_cache->_update_exports_values(values, propnames);
- }
-
for (const KeyValue<StringName, Variant> &E : exported_members_defval_cache) {
values[E.key] = E.value;
}
@@ -2343,6 +2340,10 @@ void CSharpScript::_update_exports_values(HashMap<StringName, Variant> &values,
for (const PropertyInfo &prop_info : exported_members_cache) {
propnames.push_back(prop_info);
}
+
+ if (base_cache.is_valid()) {
+ base_cache->_update_exports_values(values, propnames);
+ }
}
void CSharpScript::_update_member_info_no_exports() {
@@ -2354,6 +2355,7 @@ void CSharpScript::_update_member_info_no_exports() {
member_info.clear();
GDMonoClass *top = script_class;
+ List<PropertyInfo> props;
while (top && top != native) {
PropertyInfo prop_info;
@@ -2368,7 +2370,7 @@ void CSharpScript::_update_member_info_no_exports() {
StringName member_name = field->get_name();
member_info[member_name] = prop_info;
- exported_members_cache.push_front(prop_info);
+ props.push_front(prop_info);
exported_members_defval_cache[member_name] = Variant();
}
}
@@ -2382,11 +2384,18 @@ void CSharpScript::_update_member_info_no_exports() {
StringName member_name = property->get_name();
member_info[member_name] = prop_info;
- exported_members_cache.push_front(prop_info);
+ props.push_front(prop_info);
exported_members_defval_cache[member_name] = Variant();
}
}
+ exported_members_cache.push_back(PropertyInfo(Variant::NIL, top->get_name(), PROPERTY_HINT_NONE, get_path(), PROPERTY_USAGE_CATEGORY));
+ for (const PropertyInfo &E : props) {
+ exported_members_cache.push_back(E);
+ }
+
+ props.clear();
+
top = top->get_parent_class();
}
}
@@ -2461,6 +2470,7 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda
#endif
GDMonoClass *top = script_class;
+ List<PropertyInfo> props;
while (top && top != native) {
PropertyInfo prop_info;
@@ -2479,7 +2489,7 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda
if (exported) {
#ifdef TOOLS_ENABLED
if (is_editor) {
- exported_members_cache.push_front(prop_info);
+ props.push_front(prop_info);
if (tmp_object) {
exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object));
@@ -2507,7 +2517,7 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda
if (exported) {
#ifdef TOOLS_ENABLED
if (is_editor) {
- exported_members_cache.push_front(prop_info);
+ props.push_front(prop_info);
if (tmp_object) {
MonoException *exc = nullptr;
MonoObject *ret = property->get_value(tmp_object, &exc);
@@ -2528,6 +2538,16 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda
}
}
+#ifdef TOOLS_ENABLED
+ exported_members_cache.push_back(PropertyInfo(Variant::NIL, top->get_name(), PROPERTY_HINT_NONE, get_path(), PROPERTY_USAGE_CATEGORY));
+
+ for (const PropertyInfo &E : props) {
+ exported_members_cache.push_back(E);
+ }
+
+ props.clear();
+#endif // TOOLS_ENABLED
+
top = top->get_parent_class();
}
@@ -2866,6 +2886,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
@@ -3051,7 +3077,7 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
- p_script->rpc_functions.clear();
+ p_script->rpc_config.clear();
GDMonoClass *top = p_script->script_class;
while (top && top != p_script->native) {
@@ -3063,17 +3089,9 @@ 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);
- }
+ const Variant rpc_config = p_script->_member_get_rpc_config(methods[i]);
+ if (rpc_config.get_type() != Variant::NIL) {
+ p_script->rpc_config[methods[i]->get_name()] = rpc_config;
}
}
}
@@ -3082,9 +3100,6 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
top = top->get_parent_class();
}
- // Sort so we are 100% that they are always the same.
- p_script->rpc_functions.sort_custom<Multiplayer::SortRPCConfig>();
-
p_script->load_script_signals(p_script->script_class, p_script->native);
}
@@ -3493,9 +3508,15 @@ Ref<Script> CSharpScript::get_base_script() const {
void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const {
List<PropertyInfo> props;
+#ifdef TOOLS_ENABLED
+ for (const PropertyInfo &E : exported_members_cache) {
+ props.push_back(E);
+ }
+#else
for (const KeyValue<StringName, PropertyInfo> &E : member_info) {
props.push_front(E.value);
}
+#endif // TOOLS_ENABLED
for (const PropertyInfo &prop : props) {
r_list->push_back(prop);
@@ -3507,19 +3528,24 @@ 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;
+Variant CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const {
+ Variant out;
+
+ MonoObject *rpc_attribute = p_member->get_attribute(CACHED_CLASS(RPCAttribute));
+ if (rpc_attribute != nullptr) {
+ Dictionary rpc_config;
+ rpc_config["rpc_mode"] = 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"] = CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute);
+ rpc_config["channel"] = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute);
+ out = rpc_config;
}
- return Multiplayer::RPC_MODE_DISABLED;
+ return out;
}
-const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const {
- return rpc_functions;
+const Variant CSharpScript::get_rpc_config() const {
+ return rpc_config;
}
Error CSharpScript::load_source_code(const String &p_path) {
@@ -3627,7 +3653,7 @@ String ResourceFormatLoaderCSharpScript::get_resource_type(const String &p_path)
return p_path.get_extension().to_lower() == "cs" ? CSharpLanguage::get_singleton()->get_type() : "";
}
-Error ResourceFormatSaverCSharpScript::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaverCSharpScript::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Ref<CSharpScript> sqscr = p_resource;
ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER);
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 69bd8703aa..48129e69cb 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -136,7 +136,7 @@ private:
HashMap<StringName, EventSignal> event_signals;
bool signals_invalidated = true;
- Vector<Multiplayer::RPCConfig> rpc_functions;
+ Dictionary rpc_config;
#ifdef TOOLS_ENABLED
List<PropertyInfo> exported_members_cache; // members_cache
@@ -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;
+ Variant _member_get_rpc_config(IMonoClassMember *p_member) const;
protected:
static void _bind_methods();
@@ -234,7 +234,7 @@ public:
int get_member_line(const StringName &p_member) const override;
- const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
+ const Variant get_rpc_config() const override;
#ifdef TOOLS_ENABLED
bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@@ -311,7 +311,7 @@ public:
void refcount_incremented() override;
bool refcount_decremented() override;
- const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
+ const Variant get_rpc_config() const override;
void notification(int p_notification) override;
void _call_notification(int p_notification);
@@ -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;
@@ -542,7 +543,7 @@ public:
class ResourceFormatSaverCSharpScript : public ResourceFormatSaver {
public:
- Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0) override;
+ Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
bool recognize(const Ref<Resource> &p_resource) const override;
};
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props
index 0128f5c706..5a499742e9 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props
@@ -57,7 +57,7 @@
<PropertyGroup Condition=" '$(GodotTargetPlatform)' == '' ">
<GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(Linux))' ">linuxbsd</GodotTargetPlatform>
<GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(FreeBSD))' ">linuxbsd</GodotTargetPlatform>
- <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(OSX))' ">osx</GodotTargetPlatform>
+ <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(OSX))' ">macos</GodotTargetPlatform>
<GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(Windows))' ">windows</GodotTargetPlatform>
</PropertyGroup>
@@ -76,12 +76,12 @@
-->
<GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'windows' ">GODOT_WINDOWS;GODOT_PC</GodotPlatformConstants>
<GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'linuxbsd' ">GODOT_LINUXBSD;GODOT_PC</GodotPlatformConstants>
- <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'osx' ">GODOT_OSX;GODOT_MACOS;GODOT_PC</GodotPlatformConstants>
+ <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'macos' ">GODOT_OSX;GODOT_MACOS;GODOT_PC</GodotPlatformConstants>
<GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'server' ">GODOT_SERVER;GODOT_PC</GodotPlatformConstants>
<GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'uwp' ">GODOT_UWP;GODOT_PC</GodotPlatformConstants>
<GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'haiku' ">GODOT_HAIKU;GODOT_PC</GodotPlatformConstants>
<GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'android' ">GODOT_ANDROID;GODOT_MOBILE</GodotPlatformConstants>
- <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'iphone' ">GODOT_IPHONE;GODOT_IOS;GODOT_MOBILE</GodotPlatformConstants>
+ <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'ios' ">GODOT_IPHONE;GODOT_IOS;GODOT_MOBILE</GodotPlatformConstants>
<GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'javascript' ">GODOT_JAVASCRIPT;GODOT_HTML5;GODOT_WASM;GODOT_WEB</GodotPlatformConstants>
<GodotDefineConstants>$(GodotDefineConstants);$(GodotPlatformConstants)</GodotDefineConstants>
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/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
index e2f4d2f5fd..e9718cc82c 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
@@ -336,10 +336,10 @@ MONO_AOT_MODE_LAST = 1000,
// Add the required Mono libraries to the Xcode project
- string MonoLibFile(string libFileName) => libFileName + ".iphone.fat.a";
+ string MonoLibFile(string libFileName) => libFileName + ".ios.fat.a";
string MonoLibFromTemplate(string libFileName) =>
- Path.Combine(Internal.FullTemplatesDir, "iphone-mono-libs", MonoLibFile(libFileName));
+ Path.Combine(Internal.FullExportTemplatesDir, "ios-mono-libs", MonoLibFile(libFileName));
exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmonosgen-2.0"));
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
index 3e46a89b7c..cca18a2a1f 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
@@ -337,7 +337,7 @@ namespace GodotTools.Export
string TemplateDirName() => $"data.mono.{platform}.{bits}.{target}";
- string templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName());
+ string templateDirPath = Path.Combine(Internal.FullExportTemplatesDir, TemplateDirName());
bool validTemplatePathFound = true;
if (!Directory.Exists(templateDirPath))
@@ -347,7 +347,7 @@ namespace GodotTools.Export
if (isDebug)
{
target = "debug"; // Support both 'release_debug' and 'debug' for the template data directory name
- templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName());
+ templateDirPath = Path.Combine(Internal.FullExportTemplatesDir, TemplateDirName());
validTemplatePathFound = true;
if (!Directory.Exists(templateDirPath))
@@ -380,7 +380,7 @@ namespace GodotTools.Export
private static bool PlatformHasTemplateDir(string platform)
{
- // OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
+ // macOS export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform);
}
@@ -398,13 +398,13 @@ namespace GodotTools.Export
private static string GetBclProfileDir(string profile)
{
- string templatesDir = Internal.FullTemplatesDir;
+ string templatesDir = Internal.FullExportTemplatesDir;
return Path.Combine(templatesDir, "bcl", profile);
}
private static string DeterminePlatformBclDir(string platform)
{
- string templatesDir = Internal.FullTemplatesDir;
+ string templatesDir = Internal.FullExportTemplatesDir;
string platformBclDir = Path.Combine(templatesDir, "bcl", platform);
if (!File.Exists(Path.Combine(platformBclDir, "mscorlib.dll")))
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 69960bdbeb..b39c3d1c0d 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -263,16 +263,16 @@ namespace GodotTools
var args = new List<string>();
- bool osxAppBundleInstalled = false;
+ bool macOSAppBundleInstalled = false;
if (OS.IsMacOS)
{
// The package path is '/Applications/Visual Studio Code.app'
const string vscodeBundleId = "com.microsoft.VSCode";
- osxAppBundleInstalled = Internal.IsOsxAppBundleInstalled(vscodeBundleId);
+ macOSAppBundleInstalled = Internal.IsMacOSAppBundleInstalled(vscodeBundleId);
- if (osxAppBundleInstalled)
+ if (macOSAppBundleInstalled)
{
args.Add("-b");
args.Add(vscodeBundleId);
@@ -307,13 +307,13 @@ namespace GodotTools
if (OS.IsMacOS)
{
- if (!osxAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath))
+ if (!macOSAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath))
{
GD.PushError("Cannot find code editor: VSCode");
return Error.FileNotFound;
}
- command = osxAppBundleInstalled ? "/usr/bin/open" : _vsCodePath;
+ command = macOSAppBundleInstalled ? "/usr/bin/open" : _vsCodePath;
}
else
{
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs
index 3f1d5ac3ca..7a0983a8cb 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs
@@ -30,7 +30,7 @@ namespace GodotTools.Ides.MonoDevelop
{
string bundleId = BundleIds[_editorId];
- if (Internal.IsOsxAppBundleInstalled(bundleId))
+ if (Internal.IsMacOSAppBundleInstalled(bundleId))
{
command = "open";
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
index ac29efb716..3440eb701c 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
@@ -66,6 +66,9 @@ namespace GodotTools.Ides.Rider
if (string.IsNullOrEmpty(path))
return false;
+ if (path.IndexOfAny(Path.GetInvalidPathChars()) != -1)
+ return false;
+
var fileInfo = new FileInfo(path);
string filename = fileInfo.Name.ToLowerInvariant();
return filename.StartsWith("rider", StringComparison.Ordinal);
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
index 77370090ec..12c90178c9 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
@@ -12,12 +12,12 @@ namespace GodotTools.Internals
public static string UpdateApiAssembliesFromPrebuilt(string config) =>
internal_UpdateApiAssembliesFromPrebuilt(config);
- public static string FullTemplatesDir =>
- internal_FullTemplatesDir();
+ public static string FullExportTemplatesDir =>
+ internal_FullExportTemplatesDir();
public static string SimplifyGodotPath(this string path) => internal_SimplifyGodotPath(path);
- public static bool IsOsxAppBundleInstalled(string bundleId) => internal_IsOsxAppBundleInstalled(bundleId);
+ public static bool IsMacOSAppBundleInstalled(string bundleId) => internal_IsMacOSAppBundleInstalled(bundleId);
public static bool GodotIs32Bits() => internal_GodotIs32Bits();
@@ -57,13 +57,13 @@ namespace GodotTools.Internals
private static extern string internal_UpdateApiAssembliesFromPrebuilt(string config);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern string internal_FullTemplatesDir();
+ private static extern string internal_FullExportTemplatesDir();
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_SimplifyGodotPath(this string path);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern bool internal_IsOsxAppBundleInstalled(string bundleId);
+ private static extern bool internal_IsMacOSAppBundleInstalled(string bundleId);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool internal_GodotIs32Bits();
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
index 2db549c623..5cef6e5c3c 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
@@ -37,13 +37,13 @@ namespace GodotTools.Utils
public static class Platforms
{
public const string Windows = "windows";
- public const string MacOS = "osx";
+ public const string MacOS = "macos";
public const string LinuxBSD = "linuxbsd";
public const string Server = "server";
public const string UWP = "uwp";
public const string Haiku = "haiku";
public const string Android = "android";
- public const string iOS = "iphone";
+ public const string iOS = "ios";
public const string HTML5 = "javascript";
}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 9d3d481068..2e628cb576 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -917,6 +917,8 @@ void BindingsGenerator::_generate_array_extensions(StringBuilder &p_output) {
ARRAY_ALL(Vector2i);
ARRAY_ALL(Vector3);
ARRAY_ALL(Vector3i);
+ ARRAY_ALL(Vector4);
+ ARRAY_ALL(Vector4i);
#undef ARRAY_ALL
#undef ARRAY_IS_EMPTY
@@ -990,6 +992,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 +1440,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 +2875,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 +2913,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 +3021,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 +3085,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 +3097,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);
@@ -3213,6 +3224,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
r_iarg.default_argument = "new %s" + r_iarg.default_argument;
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
break;
+ case Variant::VECTOR4:
+ case Variant::VECTOR4I:
+ r_iarg.default_argument = "new %s" + r_iarg.default_argument;
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ break;
case Variant::OBJECT:
ERR_FAIL_COND_V_MSG(!p_val.is_zero(), false,
"Parameter of type '" + String(r_iarg.type.cname) + "' can only have null/zero as the default value.");
@@ -3267,6 +3283,15 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
}
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
} break;
+ case Variant::PROJECTION: {
+ Projection transform = p_val.operator Projection();
+ if (transform == Projection()) {
+ r_iarg.default_argument = "Projection.Identity";
+ } else {
+ r_iarg.default_argument = "new Projection(new Vector4" + transform.matrix[0].operator String() + ", new Vector4" + transform.matrix[1].operator String() + ", new Vector4" + transform.matrix[2].operator String() + ", new Vector4" + transform.matrix[3].operator String() + ")";
+ }
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ } break;
case Variant::BASIS: {
Basis basis = p_val.operator Basis();
if (basis == Basis()) {
@@ -3676,6 +3701,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..ee170e4558 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;
@@ -589,6 +590,9 @@ class BindingsGenerator {
StringName type_Vector2 = StaticCString::create("Vector2");
StringName type_Rect2 = StaticCString::create("Rect2");
StringName type_Vector3 = StaticCString::create("Vector3");
+ StringName type_Vector3i = StaticCString::create("Vector3i");
+ StringName type_Vector4 = StaticCString::create("Vector4");
+ StringName type_Vector4i = StaticCString::create("Vector4i");
// Object not included as it must be checked for all derived classes
static constexpr int nullable_types_count = 17;
diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp
index a1789412f4..7bce6f2c21 100644
--- a/modules/mono/editor/code_completion.cpp
+++ b/modules/mono/editor/code_completion.cpp
@@ -172,7 +172,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
}
} break;
case CompletionKind::SHADER_PARAMS: {
- print_verbose("Shared params completion for C# not implemented.");
+ print_verbose("Shader uniforms completion for C# is not implemented yet.");
} break;
case CompletionKind::SIGNALS: {
Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path());
diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp
index f7f710f3f1..f830c7ffe1 100644
--- a/modules/mono/editor/editor_internal_calls.cpp
+++ b/modules/mono/editor/editor_internal_calls.cpp
@@ -39,7 +39,9 @@
#include "core/version.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/plugins/script_editor_plugin.h"
#include "main/main.h"
@@ -47,7 +49,7 @@
#include "../glue/cs_glue_version.gen.h"
#include "../godotsharp_dirs.h"
#include "../mono_gd/gd_mono_marshal.h"
-#include "../utils/osx_utils.h"
+#include "../utils/macos_utils.h"
#include "code_completion.h"
#include "godotsharp_export.h"
@@ -188,8 +190,8 @@ MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_c
return GDMonoMarshal::mono_string_from_godot(error_str);
}
-MonoString *godot_icall_Internal_FullTemplatesDir() {
- String full_templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
+MonoString *godot_icall_Internal_FullExportTemplatesDir() {
+ String full_templates_dir = EditorPaths::get_singleton()->get_export_templates_dir().plus_file(VERSION_FULL_CONFIG);
return GDMonoMarshal::mono_string_from_godot(full_templates_dir);
}
@@ -198,10 +200,10 @@ MonoString *godot_icall_Internal_SimplifyGodotPath(MonoString *p_path) {
return GDMonoMarshal::mono_string_from_godot(path.simplify_path());
}
-MonoBoolean godot_icall_Internal_IsOsxAppBundleInstalled(MonoString *p_bundle_id) {
-#ifdef OSX_ENABLED
+MonoBoolean godot_icall_Internal_IsMacOSAppBundleInstalled(MonoString *p_bundle_id) {
+#ifdef MACOS_ENABLED
String bundle_id = GDMonoMarshal::mono_string_to_godot(p_bundle_id);
- return (MonoBoolean)osx_is_app_bundle_installed(bundle_id);
+ return (MonoBoolean)macos_is_app_bundle_installed(bundle_id);
#else
(void)p_bundle_id; // UNUSED
return (MonoBoolean) false;
@@ -364,9 +366,9 @@ void register_editor_internal_calls() {
// Internals
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_UpdateApiAssembliesFromPrebuilt", godot_icall_Internal_UpdateApiAssembliesFromPrebuilt);
- GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullTemplatesDir", godot_icall_Internal_FullTemplatesDir);
+ GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullExportTemplatesDir", godot_icall_Internal_FullExportTemplatesDir);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_SimplifyGodotPath", godot_icall_Internal_SimplifyGodotPath);
- GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsOsxAppBundleInstalled", godot_icall_Internal_IsOsxAppBundleInstalled);
+ GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsMacOSAppBundleInstalled", godot_icall_Internal_IsMacOSAppBundleInstalled);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIs32Bits", godot_icall_Internal_GodotIs32Bits);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIsRealTDouble", godot_icall_Internal_GodotIsRealTDouble);
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotMainIteration", godot_icall_Internal_GodotMainIteration);
diff --git a/modules/mono/editor/editor_internal_calls.h b/modules/mono/editor/editor_internal_calls.h
index a899634d57..8262ac211a 100644
--- a/modules/mono/editor/editor_internal_calls.h
+++ b/modules/mono/editor/editor_internal_calls.h
@@ -28,9 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EDITOR_INTERNAL_CALL_H
-#define EDITOR_INTERNAL_CALL_H
+#ifndef EDITOR_INTERNAL_CALLS_H
+#define EDITOR_INTERNAL_CALLS_H
void register_editor_internal_calls();
-#endif // EDITOR_INTERNAL_CALL_H
+#endif // EDITOR_INTERNAL_CALLS_H
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..fb37838ffa
--- /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="MultiplayerAPI.RPCMode"/> and <see cref="MultiplayerPeer.TransferModeEnum"/>.
+ /// 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 MultiplayerAPI.RPCMode Mode { get; } = MultiplayerAPI.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 MultiplayerPeer.TransferModeEnum TransferMode { get; set; } = MultiplayerPeer.TransferModeEnum.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(MultiplayerAPI.RPCMode mode = MultiplayerAPI.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/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index 37bdc42c2d..437878818c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -531,9 +531,9 @@ namespace Godot
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated basis matrix.</returns>
- public Basis Rotated(Vector3 axis, real_t phi)
+ public Basis Rotated(Vector3 axis, real_t angle)
{
- return new Basis(axis, phi) * this;
+ return new Basis(axis, angle) * this;
}
/// <summary>
@@ -774,15 +774,15 @@ namespace Godot
/// </summary>
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate, in radians.</param>
- public Basis(Vector3 axis, real_t phi)
+ public Basis(Vector3 axis, real_t angle)
{
Vector3 axisSq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
- real_t cosine = Mathf.Cos(phi);
+ real_t cosine = Mathf.Cos(angle);
Row0.x = axisSq.x + cosine * (1.0f - axisSq.x);
Row1.y = axisSq.y + cosine * (1.0f - axisSq.y);
Row2.z = axisSq.z + cosine * (1.0f - axisSq.z);
- real_t sine = Mathf.Sin(phi);
+ real_t sine = Mathf.Sin(angle);
real_t t = 1.0f - cosine;
real_t xyzt = axis.x * axis.y * t;
@@ -828,6 +828,22 @@ namespace Godot
}
/// <summary>
+ /// Constructs a pure scale basis matrix with no rotation or shearing.
+ /// The scale values are set as the main diagonal of the matrix,
+ /// and all of the other parts of the matrix are zero.
+ /// </summary>
+ /// <param name="scale">The scale Vector3.</param>
+ /// <returns>A pure scale Basis matrix.</returns>
+ public static Basis FromScale(Vector3 scale)
+ {
+ return new Basis(
+ scale.x, 0, 0,
+ 0, scale.y, 0,
+ 0, 0, scale.z
+ );
+ }
+
+ /// <summary>
/// Composes these two basis matrices by multiplying them
/// together. This has the effect of transforming the second basis
/// (the child) by the first basis (the parent).
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index fc9d40ca48..a6324504fc 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -916,7 +916,7 @@ namespace Godot
/// <c>new Color(1 - c.r, 1 - c.g, 1 - c.b, 1 - c.a)</c>.
/// </summary>
/// <param name="color">The color to invert.</param>
- /// <returns>The inverted color</returns>
+ /// <returns>The inverted color.</returns>
public static Color operator -(Color color)
{
return Colors.White - color;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
index bb076a9633..236d0666bc 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
@@ -239,11 +239,20 @@ namespace Godot
}
/// <summary>
- /// Converts one or more arguments of any type to string in the best way possible and prints them to the console. The following BBCode tags are supported: b, i, u, s, indent, code, url, center, right, color, bgcolor, fgcolor. Color tags only support named colors such as [code]red[/code], [i]not[/i] hexadecimal color codes. Unsupported tags will be left as-is in standard output.
- /// When printing to standard output, the supported subset of BBCode is converted to ANSI escape codes for the terminal emulator to display. Displaying ANSI escape codes is currently only supported on Linux and macOS. Support for ANSI escape codes may vary across terminal emulators, especially for italic and strikethrough.
+ /// Converts one or more arguments of any type to string in the best way possible
+ /// and prints them to the console.
+ /// The following BBCode tags are supported: b, i, u, s, indent, code, url, center,
+ /// right, color, bgcolor, fgcolor.
+ /// Color tags only support named colors such as <c>red</c>, not hexadecimal color codes.
+ /// Unsupported tags will be left as-is in standard output.
+ /// When printing to standard output, the supported subset of BBCode is converted to
+ /// ANSI escape codes for the terminal emulator to display. Displaying ANSI escape codes
+ /// is currently only supported on Linux and macOS. Support for ANSI escape codes may vary
+ /// across terminal emulators, especially for italic and strikethrough.
///
/// Note: Consider using <see cref="PushError(string)"/> and <see cref="PushWarning(string)"/>
- /// to print error and warning messages instead of <see cref="Print(object[])"/> or <see cref="PrintRich(object[])"/>.
+ /// to print error and warning messages instead of <see cref="Print(object[])"/> or
+ /// <see cref="PrintRich(object[])"/>.
/// This distinguishes them from print messages used for debugging purposes,
/// while also displaying a stack trace when an error or warning is printed.
/// </summary>
@@ -253,7 +262,6 @@ namespace Godot
/// </code>
/// </example>
/// <param name="what">Arguments that will be printed.</param>
- /// </summary>
public static void PrintRich(params object[] what)
{
godot_icall_GD_print_rich(GetPrintParams(what));
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/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
index 63af1c5892..fd97a71e47 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
@@ -118,15 +118,15 @@ namespace Godot
/// <summary>
/// Returns <see langword="true"/> if point is inside the plane.
- /// Comparison uses a custom minimum epsilon threshold.
+ /// Comparison uses a custom minimum tolerance threshold.
/// </summary>
/// <param name="point">The point to check.</param>
- /// <param name="epsilon">The tolerance threshold.</param>
+ /// <param name="tolerance">The tolerance threshold.</param>
/// <returns>A <see langword="bool"/> for whether or not the plane has the point.</returns>
- public bool HasPoint(Vector3 point, real_t epsilon = Mathf.Epsilon)
+ public bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon)
{
real_t dist = _normal.Dot(point) - D;
- return Mathf.Abs(dist) <= epsilon;
+ return Mathf.Abs(dist) <= tolerance;
}
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
new file mode 100644
index 0000000000..d774021131
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
@@ -0,0 +1,820 @@
+#if REAL_T_IS_DOUBLE
+using real_t = System.Double;
+#else
+using real_t = System.Single;
+#endif
+using System;
+using System.Runtime.InteropServices;
+
+namespace Godot
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Projection : IEquatable<Projection>
+ {
+ /// <summary>
+ /// Enumerated index values for the planes.
+ /// </summary>
+ public enum Planes
+ {
+ /// <summary>
+ /// The projection's near plane.
+ /// </summary>
+ Near,
+ /// <summary>
+ /// The projection's far plane.
+ /// </summary>
+ Far,
+ /// <summary>
+ /// The projection's left plane.
+ /// </summary>
+ Left,
+ /// <summary>
+ /// The projection's top plane.
+ /// </summary>
+ Top,
+ /// <summary>
+ /// The projection's right plane.
+ /// </summary>
+ Right,
+ /// <summary>
+ /// The projection's bottom plane.
+ /// </summary>
+ Bottom,
+ }
+
+ /// <summary>
+ /// The projections's X column. Also accessible by using the index position <c>[0]</c>.
+ /// </summary>
+ public Vector4 x;
+
+ /// <summary>
+ /// The projections's Y column. Also accessible by using the index position <c>[1]</c>.
+ /// </summary>
+ public Vector4 y;
+
+ /// <summary>
+ /// The projections's Z column. Also accessible by using the index position <c>[2]</c>.
+ /// </summary>
+ public Vector4 z;
+
+ /// <summary>
+ /// The projections's W column. Also accessible by using the index position <c>[3]</c>.
+ /// </summary>
+ public Vector4 w;
+
+ /// <summary>
+ /// Constructs a projection from 4 vectors (matrix columns).
+ /// </summary>
+ /// <param name="x">The X column, or column index 0.</param>
+ /// <param name="y">The Y column, or column index 1.</param>
+ /// <param name="z">The Z column, or column index 2.</param>
+ /// <param name="w">The W column, or column index 3.</param>
+ public Projection(Vector4 x, Vector4 y, Vector4 z, Vector4 w)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="Projection"/> from an existing <see cref="Projection"/>.
+ /// </summary>
+ /// <param name="proj">The existing <see cref="Projection"/>.</param>
+ public Projection(Projection proj)
+ {
+ x = proj.x;
+ y = proj.y;
+ z = proj.z;
+ w = proj.w;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="Projection"/> from a <see cref="Transform3D"/>.
+ /// </summary>
+ /// <param name="transform">The <see cref="Transform3D"/>.</param>
+ public Projection(Transform3D transform)
+ {
+ x = new Vector4(transform.basis.Row0.x, transform.basis.Row1.x, transform.basis.Row2.x, 0);
+ y = new Vector4(transform.basis.Row0.y, transform.basis.Row1.y, transform.basis.Row2.y, 0);
+ z = new Vector4(transform.basis.Row0.z, transform.basis.Row1.z, transform.basis.Row2.z, 0);
+ w = new Vector4(transform.origin.x, transform.origin.y, transform.origin.z, 1);
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="Transform3D"/> from the <see cref="Projection"/>.
+ /// </summary>
+ /// <param name="proj">The <see cref="Projection"/>.</param>
+ public static explicit operator Transform3D(Projection proj)
+ {
+ return new Transform3D(
+ new Basis(
+ new Vector3(proj.x.x, proj.x.y, proj.x.z),
+ new Vector3(proj.y.x, proj.y.y, proj.y.z),
+ new Vector3(proj.z.x, proj.z.y, proj.z.z)
+ ),
+ new Vector3(proj.w.x, proj.w.y, proj.w.z)
+ );
+ }
+
+ public static Projection CreateDepthCorrection(bool flipY)
+ {
+ return new Projection(
+ new Vector4(1, 0, 0, 0),
+ new Vector4(0, flipY ? -1 : 1, 0, 0),
+ new Vector4(0, 0, (real_t)0.5, 0),
+ new Vector4(0, 0, (real_t)0.5, 1)
+ );
+ }
+
+ public static Projection CreateFitAabb(AABB aabb)
+ {
+ Vector3 min = aabb.Position;
+ Vector3 max = aabb.Position + aabb.Size;
+
+ return new Projection(
+ new Vector4(2 / (max.x - min.x), 0, 0, 0),
+ new Vector4(0, 2 / (max.y - min.y), 0, 0),
+ new Vector4(0, 0, 2 / (max.z - min.z), 0),
+ new Vector4(-(max.x + min.x) / (max.x - min.x), -(max.y + min.y) / (max.y - min.y), -(max.z + min.z) / (max.z - min.z), 1)
+ );
+ }
+
+ public static Projection CreateForHmd(int eye, real_t aspect, real_t intraocularDist, real_t displayWidth, real_t displayToLens, real_t oversample, real_t zNear, real_t zFar)
+ {
+ real_t f1 = (intraocularDist * (real_t)0.5) / displayToLens;
+ real_t f2 = ((displayWidth - intraocularDist) * (real_t)0.5) / displayToLens;
+ real_t f3 = (displayWidth / (real_t)4.0) / displayToLens;
+
+ real_t add = ((f1 + f2) * (oversample - (real_t)1.0)) / (real_t)2.0;
+ f1 += add;
+ f2 += add;
+ f3 *= oversample;
+
+ f3 /= aspect;
+
+ switch (eye)
+ {
+ case 1:
+ return CreateFrustum(-f2 * zNear, f1 * zNear, -f3 * zNear, f3 * zNear, zNear, zFar);
+ case 2:
+ return CreateFrustum(-f1 * zNear, f2 * zNear, -f3 * zNear, f3 * zNear, zNear, zFar);
+ default:
+ return Zero;
+ }
+ }
+
+ public static Projection CreateFrustum(real_t left, real_t right, real_t bottom, real_t top, real_t near, real_t far)
+ {
+ if (right <= left)
+ {
+ throw new ArgumentException("right is less or equal to left.");
+ }
+ if (top <= bottom)
+ {
+ throw new ArgumentException("top is less or equal to bottom.");
+ }
+ if (far <= near)
+ {
+ throw new ArgumentException("far is less or equal to near.");
+ }
+
+ real_t x = 2 * near / (right - left);
+ real_t y = 2 * near / (top - bottom);
+
+ real_t a = (right + left) / (right - left);
+ real_t b = (top + bottom) / (top - bottom);
+ real_t c = -(far + near) / (far - near);
+ real_t d = -2 * far * near / (far - near);
+
+ return new Projection(
+ new Vector4(x, 0, 0, 0),
+ new Vector4(0, y, 0, 0),
+ new Vector4(a, b, c, -1),
+ new Vector4(0, 0, d, 0)
+ );
+ }
+
+ public static Projection CreateFrustumAspect(real_t size, real_t aspect, Vector2 offset, real_t near, real_t far, bool flipFov)
+ {
+ if (!flipFov)
+ {
+ size *= aspect;
+ }
+ return CreateFrustum(-size / 2 + offset.x, +size / 2 + offset.x, -size / aspect / 2 + offset.y, +size / aspect / 2 + offset.y, near, far);
+ }
+
+ public static Projection CreateLightAtlasRect(Rect2 rect)
+ {
+ return new Projection(
+ new Vector4(rect.Size.x, 0, 0, 0),
+ new Vector4(0, rect.Size.y, 0, 0),
+ new Vector4(0, 0, 1, 0),
+ new Vector4(rect.Position.x, rect.Position.y, 0, 1)
+ );
+ }
+
+ public static Projection CreateOrthogonal(real_t left, real_t right, real_t bottom, real_t top, real_t zNear, real_t zFar)
+ {
+ Projection proj = Projection.Identity;
+ proj.x.x = (real_t)2.0 / (right - left);
+ proj.w.x = -((right + left) / (right - left));
+ proj.y.y = (real_t)2.0 / (top - bottom);
+ proj.w.y = -((top + bottom) / (top - bottom));
+ proj.z.z = (real_t)(-2.0) / (zFar - zNear);
+ proj.w.z = -((zFar + zNear) / (zFar - zNear));
+ proj.w.w = (real_t)1.0;
+ return proj;
+ }
+
+ public static Projection CreateOrthogonalAspect(real_t size, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
+ {
+ if (!flipFov)
+ {
+ size *= aspect;
+ }
+ return CreateOrthogonal(-size / 2, +size / 2, -size / aspect / 2, +size / aspect / 2, zNear, zFar);
+ }
+
+ public static Projection CreatePerspective(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
+ {
+ if (flipFov)
+ {
+ fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect);
+ }
+ real_t radians = Mathf.Deg2Rad(fovyDegrees / (real_t)2.0);
+ real_t deltaZ = zFar - zNear;
+ real_t sine = Mathf.Sin(radians);
+
+ if ((deltaZ == 0) || (sine == 0) || (aspect == 0))
+ {
+ return Zero;
+ }
+
+ real_t cotangent = Mathf.Cos(radians) / sine;
+
+ Projection proj = Projection.Identity;
+
+ proj.x.x = cotangent / aspect;
+ proj.y.y = cotangent;
+ proj.z.z = -(zFar + zNear) / deltaZ;
+ proj.z.w = -1;
+ proj.w.z = -2 * zNear * zFar / deltaZ;
+ proj.w.w = 0;
+
+ return proj;
+ }
+
+ public static Projection CreatePerspectiveHmd(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov, int eye, real_t intraocularDist, real_t convergenceDist)
+ {
+ if (flipFov)
+ {
+ fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect);
+ }
+
+ real_t ymax = zNear * Mathf.Tan(Mathf.Deg2Rad(fovyDegrees / (real_t)2.0));
+ real_t xmax = ymax * aspect;
+ real_t frustumshift = (intraocularDist / (real_t)2.0) * zNear / convergenceDist;
+ real_t left;
+ real_t right;
+ real_t modeltranslation;
+ switch (eye)
+ {
+ case 1:
+ left = -xmax + frustumshift;
+ right = xmax + frustumshift;
+ modeltranslation = intraocularDist / (real_t)2.0;
+ break;
+ case 2:
+ left = -xmax - frustumshift;
+ right = xmax - frustumshift;
+ modeltranslation = -intraocularDist / (real_t)2.0;
+ break;
+ default:
+ left = -xmax;
+ right = xmax;
+ modeltranslation = (real_t)0.0;
+ break;
+ }
+ Projection proj = CreateFrustum(left, right, -ymax, ymax, zNear, zFar);
+ Projection cm = Projection.Identity;
+ cm.w.x = modeltranslation;
+ return proj * cm;
+ }
+
+ public real_t Determinant()
+ {
+ return x.w * y.z * z.y * w.x - x.z * y.w * z.y * w.x -
+ x.w * y.y * z.z * w.x + x.y * y.w * z.z * w.x +
+ x.z * y.y * z.w * w.x - x.y * y.z * z.w * w.x -
+ x.w * y.z * z.x * w.y + x.z * y.w * z.x * w.y +
+ x.w * y.x * z.z * w.y - x.x * y.w * z.z * w.y -
+ x.z * y.x * z.w * w.y + x.x * y.z * z.w * w.y +
+ x.w * y.y * z.x * w.z - x.y * y.w * z.x * w.z -
+ x.w * y.x * z.y * w.z + x.x * y.w * z.y * w.z +
+ x.y * y.x * z.w * w.z - x.x * y.y * z.w * w.z -
+ x.z * y.y * z.x * w.w + x.y * y.z * z.x * w.w +
+ x.z * y.x * z.y * w.w - x.x * y.z * z.y * w.w -
+ x.y * y.x * z.z * w.w + x.x * y.y * z.z * w.w;
+ }
+
+ public real_t GetAspect()
+ {
+ Vector2 vpHe = GetViewportHalfExtents();
+ return vpHe.x / vpHe.y;
+ }
+
+ public real_t GetFov()
+ {
+ Plane rightPlane = new Plane(x.w - x.x, y.w - y.x, z.w - z.x, -w.w + w.x).Normalized();
+ if (z.x == 0 && z.y == 0)
+ {
+ return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))) * (real_t)2.0;
+ }
+ else
+ {
+ Plane leftPlane = new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x).Normalized();
+ return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(leftPlane.Normal.x))) + Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x)));
+ }
+ }
+
+ public static real_t GetFovy(real_t fovx, real_t aspect)
+ {
+ return Mathf.Rad2Deg(Mathf.Atan(aspect * Mathf.Tan(Mathf.Deg2Rad(fovx) * (real_t)0.5)) * (real_t)2.0);
+ }
+
+ public real_t GetLodMultiplier()
+ {
+ if (IsOrthogonal())
+ {
+ return GetViewportHalfExtents().x;
+ }
+ else
+ {
+ real_t zn = GetZNear();
+ real_t width = GetViewportHalfExtents().x * (real_t)2.0;
+ return (real_t)1.0 / (zn / width);
+ }
+ }
+
+ public int GetPixelsPerMeter(int forPixelWidth)
+ {
+ Vector3 result = Xform(new Vector3(1, 0, -1));
+
+ return (int)((result.x * (real_t)0.5 + (real_t)0.5) * forPixelWidth);
+ }
+
+ public Plane GetProjectionPlane(Planes plane)
+ {
+ Plane newPlane = plane switch
+ {
+ Planes.Near => new Plane(x.w + x.z, y.w + y.z, z.w + z.z, w.w + w.z),
+ Planes.Far => new Plane(x.w - x.z, y.w - y.z, z.w - z.z, w.w - w.z),
+ Planes.Left => new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x),
+ Planes.Top => new Plane(x.w - x.y, y.w - y.y, z.w - z.y, w.w - w.y),
+ Planes.Right => new Plane(x.w - x.x, y.w - y.x, z.w - z.x, w.w - w.x),
+ Planes.Bottom => new Plane(x.w + x.y, y.w + y.y, z.w + z.y, w.w + w.y),
+ _ => new Plane(),
+ };
+ newPlane.Normal = -newPlane.Normal;
+ return newPlane.Normalized();
+ }
+
+ public Vector2 GetFarPlaneHalfExtents()
+ {
+ var res = GetProjectionPlane(Planes.Far).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top));
+ return new Vector2(res.Value.x, res.Value.y);
+ }
+
+ public Vector2 GetViewportHalfExtents()
+ {
+ var res = GetProjectionPlane(Planes.Near).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top));
+ return new Vector2(res.Value.x, res.Value.y);
+ }
+
+ public real_t GetZFar()
+ {
+ return GetProjectionPlane(Planes.Far).D;
+ }
+
+ public real_t GetZNear()
+ {
+ return -GetProjectionPlane(Planes.Near).D;
+ }
+
+ public Projection FlippedY()
+ {
+ Projection proj = this;
+ proj.y = -proj.y;
+ return proj;
+ }
+
+ public Projection PerspectiveZNearAdjusted(real_t newZNear)
+ {
+ Projection proj = this;
+ real_t zFar = GetZFar();
+ real_t zNear = newZNear;
+ real_t deltaZ = zFar - zNear;
+ proj.z.z = -(zFar + zNear) / deltaZ;
+ proj.w.z = -2 * zNear * zFar / deltaZ;
+ return proj;
+ }
+
+ public Projection JitterOffseted(Vector2 offset)
+ {
+ Projection proj = this;
+ proj.w.x += offset.x;
+ proj.w.y += offset.y;
+ return proj;
+ }
+
+ public Projection Inverse()
+ {
+ Projection proj = this;
+ int i, j, k;
+ int[] pvt_i = new int[4];
+ int[] pvt_j = new int[4]; /* Locations of pivot matrix */
+ real_t pvt_val; /* Value of current pivot element */
+ real_t hold; /* Temporary storage */
+ real_t determinant = 1.0f;
+ for (k = 0; k < 4; k++)
+ {
+ /* Locate k'th pivot element */
+ pvt_val = proj[k][k]; /* Initialize for search */
+ pvt_i[k] = k;
+ pvt_j[k] = k;
+ for (i = k; i < 4; i++)
+ {
+ for (j = k; j < 4; j++)
+ {
+ if (Mathf.Abs(proj[i][j]) > Mathf.Abs(pvt_val))
+ {
+ pvt_i[k] = i;
+ pvt_j[k] = j;
+ pvt_val = proj[i][j];
+ }
+ }
+ }
+
+ /* Product of pivots, gives determinant when finished */
+ determinant *= pvt_val;
+ if (Mathf.IsZeroApprox(determinant))
+ {
+ return Zero;
+ }
+
+ /* "Interchange" rows (with sign change stuff) */
+ i = pvt_i[k];
+ if (i != k)
+ { /* If rows are different */
+ for (j = 0; j < 4; j++)
+ {
+ hold = -proj[k][j];
+ proj[k, j] = proj[i][j];
+ proj[i, j] = hold;
+ }
+ }
+
+ /* "Interchange" columns */
+ j = pvt_j[k];
+ if (j != k)
+ { /* If columns are different */
+ for (i = 0; i < 4; i++)
+ {
+ hold = -proj[i][k];
+ proj[i, k] = proj[i][j];
+ proj[i, j] = hold;
+ }
+ }
+
+ /* Divide column by minus pivot value */
+ for (i = 0; i < 4; i++)
+ {
+ if (i != k)
+ {
+ proj[i, k] /= (-pvt_val);
+ }
+ }
+
+ /* Reduce the matrix */
+ for (i = 0; i < 4; i++)
+ {
+ hold = proj[i][k];
+ for (j = 0; j < 4; j++)
+ {
+ if (i != k && j != k)
+ {
+ proj[i, j] += hold * proj[k][j];
+ }
+ }
+ }
+
+ /* Divide row by pivot */
+ for (j = 0; j < 4; j++)
+ {
+ if (j != k)
+ {
+ proj[k, j] /= pvt_val;
+ }
+ }
+
+ /* Replace pivot by reciprocal (at last we can touch it). */
+ proj[k, k] = (real_t)1.0 / pvt_val;
+ }
+
+ /* That was most of the work, one final pass of row/column interchange */
+ /* to finish */
+ for (k = 4 - 2; k >= 0; k--)
+ { /* Don't need to work with 1 by 1 corner*/
+ i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */
+ if (i != k)
+ { /* If rows are different */
+ for (j = 0; j < 4; j++)
+ {
+ hold = proj[k][j];
+ proj[k, j] = -proj[i][j];
+ proj[i, j] = hold;
+ }
+ }
+
+ j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */
+ if (j != k)
+ { /* If columns are different */
+ for (i = 0; i < 4; i++)
+ {
+ hold = proj[i][k];
+ proj[i, k] = -proj[i][j];
+ proj[i, j] = hold;
+ }
+ }
+ }
+ return proj;
+ }
+
+ public bool IsOrthogonal()
+ {
+ return w.w == (real_t)1.0;
+ }
+
+ /// <summary>
+ /// Composes these two projections by multiplying them
+ /// together. This has the effect of applying the right
+ /// and then the left projection.
+ /// </summary>
+ /// <param name="left">The parent transform.</param>
+ /// <param name="right">The child transform.</param>
+ /// <returns>The composed projection.</returns>
+ public static Projection operator *(Projection left, Projection right)
+ {
+ return new Projection(
+ new Vector4(
+ left.x.x * right.x.x + left.y.x * right.x.y + left.z.x * right.x.z + left.w.x * right.x.w,
+ left.x.y * right.x.x + left.y.y * right.x.y + left.z.y * right.x.z + left.w.y * right.x.w,
+ left.x.z * right.x.x + left.y.z * right.x.y + left.z.z * right.x.z + left.w.z * right.x.w,
+ left.x.w * right.x.x + left.y.w * right.x.y + left.z.w * right.x.z + left.w.w * right.x.w
+ ), new Vector4(
+ left.x.x * right.y.x + left.y.x * right.y.y + left.z.x * right.y.z + left.w.x * right.y.w,
+ left.x.y * right.y.x + left.y.y * right.y.y + left.z.y * right.y.z + left.w.y * right.y.w,
+ left.x.z * right.y.x + left.y.z * right.y.y + left.z.z * right.y.z + left.w.z * right.y.w,
+ left.x.w * right.y.x + left.y.w * right.y.y + left.z.w * right.y.z + left.w.w * right.y.w
+ ), new Vector4(
+ left.x.x * right.z.x + left.y.x * right.z.y + left.z.x * right.z.z + left.w.x * right.z.w,
+ left.x.y * right.z.x + left.y.y * right.z.y + left.z.y * right.z.z + left.w.y * right.z.w,
+ left.x.z * right.z.x + left.y.z * right.z.y + left.z.z * right.z.z + left.w.z * right.z.w,
+ left.x.w * right.z.x + left.y.w * right.z.y + left.z.w * right.z.z + left.w.w * right.z.w
+ ), new Vector4(
+ left.x.x * right.w.x + left.y.x * right.w.y + left.z.x * right.w.z + left.w.x * right.w.w,
+ left.x.y * right.w.x + left.y.y * right.w.y + left.z.y * right.w.z + left.w.y * right.w.w,
+ left.x.z * right.w.x + left.y.z * right.w.y + left.z.z * right.w.z + left.w.z * right.w.w,
+ left.x.w * right.w.x + left.y.w * right.w.y + left.z.w * right.w.z + left.w.w * right.w.w
+ )
+ );
+ }
+
+ /// <summary>
+ /// Returns a vector transformed (multiplied) by this projection.
+ /// </summary>
+ /// <param name="proj">The projection to apply.</param>
+ /// <param name="v">A vector to transform.</param>
+ /// <returns>The transformed vector.</returns>
+ public static Vector4 operator *(Projection proj, Vector4 v)
+ {
+ return new Vector4(
+ proj.x.x * v.x + proj.y.x * v.y + proj.z.x * v.z + proj.w.x * v.w,
+ proj.x.y * v.x + proj.y.y * v.y + proj.z.y * v.z + proj.w.y * v.w,
+ proj.x.z * v.x + proj.y.z * v.y + proj.z.z * v.z + proj.w.z * v.w,
+ proj.x.w * v.x + proj.y.w * v.y + proj.z.w * v.z + proj.w.w * v.w
+ );
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the projections are exactly equal.
+ /// </summary>
+ /// <param name="left">The left projection.</param>
+ /// <param name="right">The right projection.</param>
+ /// <returns>Whether or not the projections are exactly equal.</returns>
+ public static bool operator ==(Projection left, Projection right)
+ {
+ return left.Equals(right);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the projections are not exactly equal.
+ /// </summary>
+ /// <param name="left">The left projection.</param>
+ /// <param name="right">The right projection.</param>
+ /// <returns>Whether or not the projections are not exactly equal.</returns>
+ public static bool operator !=(Projection left, Projection right)
+ {
+ return !left.Equals(right);
+ }
+
+ /// <summary>
+ /// Access whole columns in the form of <see cref="Vector4"/>.
+ /// </summary>
+ /// <param name="column">Which column vector.</param>
+ public Vector4 this[int column]
+ {
+ get
+ {
+ switch (column)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ case 3:
+ return w;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (column)
+ {
+ case 0:
+ x = value;
+ return;
+ case 1:
+ y = value;
+ return;
+ case 2:
+ z = value;
+ return;
+ case 3:
+ w = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Access single values.
+ /// </summary>
+ /// <param name="column">Which column vector.</param>
+ /// <param name="row">Which row of the column.</param>
+ public real_t this[int column, int row]
+ {
+ get
+ {
+ switch (column)
+ {
+ case 0:
+ return x[row];
+ case 1:
+ return y[row];
+ case 2:
+ return z[row];
+ case 3:
+ return w[row];
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (column)
+ {
+ case 0:
+ x[row] = value;
+ return;
+ case 1:
+ y[row] = value;
+ return;
+ case 2:
+ z[row] = value;
+ return;
+ case 3:
+ w[row] = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns a vector transformed (multiplied) by this projection.
+ /// </summary>
+ /// <param name="v">A vector to transform.</param>
+ /// <returns>The transformed vector.</returns>
+ private Vector3 Xform(Vector3 v)
+ {
+ Vector3 ret = new Vector3(
+ x.x * v.x + y.x * v.y + z.x * v.z + w.x,
+ x.y * v.x + y.y * v.y + z.y * v.z + w.y,
+ x.z * v.x + y.z * v.y + z.z * v.z + w.z
+ );
+ return ret / (x.w * v.x + y.w * v.y + z.w * v.z + w.w);
+ }
+
+ // Constants
+ private static readonly Projection _zero = new Projection(
+ new Vector4(0, 0, 0, 0),
+ new Vector4(0, 0, 0, 0),
+ new Vector4(0, 0, 0, 0),
+ new Vector4(0, 0, 0, 0)
+ );
+ private static readonly Projection _identity = new Projection(
+ new Vector4(1, 0, 0, 0),
+ new Vector4(0, 1, 0, 0),
+ new Vector4(0, 0, 1, 0),
+ new Vector4(0, 0, 0, 1)
+ );
+
+ /// <summary>
+ /// Zero projection, a projection with all components set to <c>0</c>.
+ /// </summary>
+ /// <value>Equivalent to <c>new Projection(Vector4.Zero, Vector4.Zero, Vector4.Zero, Vector4.Zero)</c>.</value>
+ public static Projection Zero { get { return _zero; } }
+
+ /// <summary>
+ /// The identity projection, with no distortion applied.
+ /// This is used as a replacement for <c>Projection()</c> in GDScript.
+ /// Do not use <c>new Projection()</c> with no arguments in C#, because it sets all values to zero.
+ /// </summary>
+ /// <value>Equivalent to <c>new Projection(new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1))</c>.</value>
+ public static Projection Identity { get { return _identity; } }
+
+ /// <summary>
+ /// Serves as the hash function for <see cref="Projection"/>.
+ /// </summary>
+ /// <returns>A hash code for this projection.</returns>
+ public override int GetHashCode()
+ {
+ return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts this <see cref="Projection"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this projection.</returns>
+ public override string ToString()
+ {
+ return $"{x.x}, {x.y}, {x.z}, {x.w}\n{y.x}, {y.y}, {y.z}, {y.w}\n{z.x}, {z.y}, {z.z}, {z.w}\n{w.x}, {w.y}, {w.z}, {w.w}\n";
+ }
+
+ /// <summary>
+ /// Converts this <see cref="Projection"/> to a string with the given <paramref name="format"/>.
+ /// </summary>
+ /// <returns>A string representation of this projection.</returns>
+ public string ToString(string format)
+ {
+ return $"{x.x.ToString(format)}, {x.y.ToString(format)}, {x.z.ToString(format)}, {x.w.ToString(format)}\n" +
+ $"{y.x.ToString(format)}, {y.y.ToString(format)}, {y.z.ToString(format)}, {y.w.ToString(format)}\n" +
+ $"{z.x.ToString(format)}, {z.y.ToString(format)}, {z.z.ToString(format)}, {z.w.ToString(format)}\n" +
+ $"{w.x.ToString(format)}, {w.y.ToString(format)}, {w.z.ToString(format)}, {w.w.ToString(format)}\n";
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the projection is exactly equal
+ /// to the given object (<see paramref="obj"/>).
+ /// </summary>
+ /// <param name="obj">The object to compare with.</param>
+ /// <returns>Whether or not the vector and the object are equal.</returns>
+ public override bool Equals(object obj)
+ {
+ if (obj is Projection)
+ {
+ return Equals((Projection)obj);
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the projections are exactly equal.
+ /// </summary>
+ /// <param name="other">The other projection.</param>
+ /// <returns>Whether or not the projections are exactly equal.</returns>
+ public bool Equals(Projection other)
+ {
+ return x == other.x && y == other.y && z == other.z && w == other.w;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs
index 5680c9d55a..da01300586 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs
@@ -18,7 +18,7 @@ namespace Godot
public StringName Name => _signalName;
/// <summary>
- /// Creates a new <see cref="Signal"/> with the name <paramref name="name"/>
+ /// Creates a new <see cref="SignalInfo"/> with the name <paramref name="name"/>
/// in the specified <paramref name="owner"/>.
/// </summary>
/// <param name="owner">Object that contains the signal.</param>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index 89947899cb..68d097eb4e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -297,17 +297,33 @@ namespace Godot
}
/// <summary>
- /// Rotates the transform by <paramref name="angle"/> (in radians), using matrix multiplication.
+ /// Rotates the transform by <paramref name="angle"/> (in radians).
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform2D Rotated(real_t phi)
+ public Transform2D Rotated(real_t angle)
{
- return this * new Transform2D(phi, new Vector2());
+ return this * new Transform2D(angle, new Vector2());
}
/// <summary>
- /// Scales the transform by the given scaling factor, using matrix multiplication.
+ /// Rotates the transform by <paramref name="angle"/> (in radians).
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="angle">The angle to rotate, in radians.</param>
+ /// <returns>The rotated transformation matrix.</returns>
+ public Transform2D RotatedLocal(real_t angle)
+ {
+ return new Transform2D(angle, new Vector2()) * this;
+ }
+
+ /// <summary>
+ /// Scales the transform by the given scaling factor.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
@@ -320,12 +336,19 @@ namespace Godot
return copy;
}
- private void ScaleBasis(Vector2 scale)
+ /// <summary>
+ /// Scales the transform by the given scaling factor.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="scale">The scale to introduce.</param>
+ /// <returns>The scaled transformation matrix.</returns>
+ public Transform2D ScaledLocal(Vector2 scale)
{
- x.x *= scale.x;
- x.y *= scale.y;
- y.x *= scale.x;
- y.y *= scale.y;
+ Transform2D copy = this;
+ copy.x *= scale;
+ copy.y *= scale;
+ return copy;
}
private real_t Tdotx(Vector2 with)
@@ -339,17 +362,29 @@ namespace Godot
}
/// <summary>
- /// Translates the transform by the given <paramref name="offset"/>,
- /// relative to the transform's basis vectors.
- ///
- /// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>,
- /// this does not use matrix multiplication.
+ /// Translates the transform by the given <paramref name="offset"/>.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
public Transform2D Translated(Vector2 offset)
{
Transform2D copy = this;
+ copy.origin += offset;
+ return copy;
+ }
+
+ /// <summary>
+ /// Translates the transform by the given <paramref name="offset"/>.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="offset">The offset to translate by.</param>
+ /// <returns>The translated matrix.</returns>
+ public Transform2D TranslatedLocal(Vector2 offset)
+ {
+ Transform2D copy = this;
copy.origin += copy.BasisXform(offset);
return copy;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
index 7b211b6577..9eaf4f3252 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -186,19 +186,38 @@ namespace Godot
}
/// <summary>
- /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians),
- /// using matrix multiplication. The axis must be a normalized vector.
+ /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians).
+ /// The axis must be a normalized vector.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform3D Rotated(Vector3 axis, real_t phi)
+ public Transform3D Rotated(Vector3 axis, real_t angle)
{
- return new Transform3D(new Basis(axis, phi), new Vector3()) * this;
+ return new Transform3D(new Basis(axis, angle), new Vector3()) * this;
}
/// <summary>
- /// Scales the transform by the given 3D scaling factor, using matrix multiplication.
+ /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians).
+ /// The axis must be a normalized vector.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="axis">The axis to rotate around. Must be normalized.</param>
+ /// <param name="angle">The angle to rotate, in radians.</param>
+ /// <returns>The rotated transformation matrix.</returns>
+ public Transform3D RotatedLocal(Vector3 axis, real_t angle)
+ {
+ Basis tmpBasis = new Basis(axis, angle);
+ return new Transform3D(basis * tmpBasis, origin);
+ }
+
+ /// <summary>
+ /// Scales the transform by the given 3D <paramref name="scale"/> factor.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
@@ -207,6 +226,19 @@ namespace Godot
return new Transform3D(basis.Scaled(scale), origin * scale);
}
+ /// <summary>
+ /// Scales the transform by the given 3D <paramref name="scale"/> factor.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="scale">The scale to introduce.</param>
+ /// <returns>The scaled transformation matrix.</returns>
+ public Transform3D ScaledLocal(Vector3 scale)
+ {
+ Basis tmpBasis = Basis.FromScale(scale);
+ return new Transform3D(basis * tmpBasis, origin);
+ }
+
private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
{
// Make rotation matrix
@@ -231,21 +263,31 @@ namespace Godot
}
/// <summary>
- /// Translates the transform by the given <paramref name="offset"/>,
- /// relative to the transform's basis vectors.
- ///
- /// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>,
- /// this does not use matrix multiplication.
+ /// Translates the transform by the given <paramref name="offset"/>.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
public Transform3D Translated(Vector3 offset)
{
+ return new Transform3D(basis, origin + offset);
+ }
+
+ /// <summary>
+ /// Translates the transform by the given <paramref name="offset"/>.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="offset">The offset to translate by.</param>
+ /// <returns>The translated matrix.</returns>
+ public Transform3D TranslatedLocal(Vector3 offset)
+ {
return new Transform3D(basis, new Vector3
(
- origin[0] += basis.Row0.Dot(offset),
- origin[1] += basis.Row1.Dot(offset),
- origin[2] += basis.Row2.Dot(offset)
+ origin[0] + basis.Row0.Dot(offset),
+ origin[1] + basis.Row1.Dot(offset),
+ origin[2] + basis.Row2.Dot(offset)
));
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 9e990ce83e..67f70390dd 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>
@@ -474,10 +495,10 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate by, in radians.</param>
/// <returns>The rotated vector.</returns>
- public Vector2 Rotated(real_t phi)
+ public Vector2 Rotated(real_t angle)
{
- real_t sine = Mathf.Sin(phi);
- real_t cosi = Mathf.Cos(phi);
+ real_t sine = Mathf.Sin(angle);
+ real_t cosi = Mathf.Cos(angle);
return new Vector2(
x * cosi - y * sine,
x * sine + y * cosi);
@@ -513,7 +534,7 @@ namespace Godot
///
/// This method also handles interpolating the lengths if the input vectors
/// have different lengths. For the special case of one or both input vectors
- /// having zero length, this method behaves like <see cref="Lerp"/>.
+ /// having zero length, this method behaves like <see cref="Lerp(Vector2, real_t)"/>.
/// </summary>
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</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/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
index 412a885daa..b61954a84c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
@@ -461,7 +461,7 @@ namespace Godot
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector2i"/>
+ /// Divides each component of the <see cref="Vector2i"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="vec">The dividend vector.</param>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index 56859da7f2..67a98efc2d 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>
@@ -494,7 +515,7 @@ namespace Godot
/// <param name="axis">The vector to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate by, in radians.</param>
/// <returns>The rotated vector.</returns>
- public Vector3 Rotated(Vector3 axis, real_t phi)
+ public Vector3 Rotated(Vector3 axis, real_t angle)
{
#if DEBUG
if (!axis.IsNormalized())
@@ -502,7 +523,7 @@ namespace Godot
throw new ArgumentException("Argument is not normalized", nameof(axis));
}
#endif
- return new Basis(axis, phi).Xform(this);
+ return new Basis(axis, angle).Xform(this);
}
/// <summary>
@@ -553,7 +574,7 @@ namespace Godot
///
/// This method also handles interpolating the lengths if the input vectors
/// have different lengths. For the special case of one or both input vectors
- /// having zero length, this method behaves like <see cref="Lerp"/>.
+ /// having zero length, this method behaves like <see cref="Lerp(Vector3, real_t)"/>.
/// </summary>
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</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);
@@ -598,22 +620,6 @@ namespace Godot
);
}
- /// <summary>
- /// Returns a diagonal matrix with the vector as main diagonal.
- ///
- /// This is equivalent to a <see cref="Basis"/> with no rotation or shearing and
- /// this vector's components set as the scale.
- /// </summary>
- /// <returns>A <see cref="Basis"/> with the vector as its main diagonal.</returns>
- public Basis ToDiagonalMatrix()
- {
- return new Basis(
- x, 0, 0,
- 0, y, 0,
- 0, 0, z
- );
- }
-
// Constants
private static readonly Vector3 _zero = new Vector3(0, 0, 0);
private static readonly Vector3 _one = new Vector3(1, 1, 1);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
index abfd2ae720..0d4894f206 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
@@ -449,7 +449,7 @@ namespace Godot
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector3i"/>
+ /// Divides each component of the <see cref="Vector3i"/>
/// by the given <see langword="int"/>.
/// </summary>
/// <param name="vec">The dividend vector.</param>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
new file mode 100644
index 0000000000..72fe9cb16f
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
@@ -0,0 +1,730 @@
+#if REAL_T_IS_DOUBLE
+using real_t = System.Double;
+#else
+using real_t = System.Single;
+#endif
+using System;
+using System.Runtime.InteropServices;
+
+namespace Godot
+{
+ /// <summary>
+ /// 4-element structure that can be used to represent positions in 4D space or any other pair of numeric values.
+ /// </summary>
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Vector4 : IEquatable<Vector4>
+ {
+ /// <summary>
+ /// Enumerated index values for the axes.
+ /// Returned by <see cref="MaxAxisIndex"/> and <see cref="MinAxisIndex"/>.
+ /// </summary>
+ public enum Axis
+ {
+ /// <summary>
+ /// The vector's X axis.
+ /// </summary>
+ X = 0,
+ /// <summary>
+ /// The vector's Y axis.
+ /// </summary>
+ Y,
+ /// <summary>
+ /// The vector's Z axis.
+ /// </summary>
+ Z,
+ /// <summary>
+ /// The vector's W axis.
+ /// </summary>
+ W
+ }
+
+ /// <summary>
+ /// The vector's X component. Also accessible by using the index position <c>[0]</c>.
+ /// </summary>
+ public real_t x;
+
+ /// <summary>
+ /// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
+ /// </summary>
+ public real_t y;
+
+ /// <summary>
+ /// The vector's Z component. Also accessible by using the index position <c>[2]</c>.
+ /// </summary>
+ public real_t z;
+
+ /// <summary>
+ /// The vector's W component. Also accessible by using the index position <c>[3]</c>.
+ /// </summary>
+ public real_t w;
+
+ /// <summary>
+ /// Access vector components using their index.
+ /// </summary>
+ /// <exception cref="IndexOutOfRangeException">
+ /// Thrown when the given the <paramref name="index"/> is not 0, 1, 2 or 3.
+ /// </exception>
+ /// <value>
+ /// <c>[0]</c> is equivalent to <see cref="x"/>,
+ /// <c>[1]</c> is equivalent to <see cref="y"/>,
+ /// <c>[2]</c> is equivalent to <see cref="z"/>.
+ /// <c>[3]</c> is equivalent to <see cref="w"/>.
+ /// </value>
+ public real_t this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ case 3:
+ return w;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x = value;
+ return;
+ case 1:
+ y = value;
+ return;
+ case 2:
+ z = value;
+ return;
+ case 3:
+ w = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Helper method for deconstruction into a tuple.
+ /// </summary>
+ public void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w)
+ {
+ x = this.x;
+ y = this.y;
+ z = this.z;
+ w = this.w;
+ }
+
+ internal void Normalize()
+ {
+ real_t lengthsq = LengthSquared();
+
+ if (lengthsq == 0)
+ {
+ x = y = z = w = 0f;
+ }
+ else
+ {
+ real_t length = Mathf.Sqrt(lengthsq);
+ x /= length;
+ y /= length;
+ z /= length;
+ w /= length;
+ }
+ }
+
+
+ /// <summary>
+ /// Returns a new vector with all components in absolute values (i.e. positive).
+ /// </summary>
+ /// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns>
+ public Vector4 Abs()
+ {
+ return new Vector4(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w));
+ }
+
+ /// <summary>
+ /// Returns a new vector with all components rounded up (towards positive infinity).
+ /// </summary>
+ /// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns>
+ public Vector4 Ceil()
+ {
+ return new Vector4(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z), Mathf.Ceil(w));
+ }
+
+ /// <summary>
+ /// Returns a new vector with all components clamped between the
+ /// components of <paramref name="min"/> and <paramref name="max"/> using
+ /// <see cref="Mathf.Clamp(real_t, real_t, real_t)"/>.
+ /// </summary>
+ /// <param name="min">The vector with minimum allowed values.</param>
+ /// <param name="max">The vector with maximum allowed values.</param>
+ /// <returns>The vector with all components clamped.</returns>
+ public Vector4 Clamp(Vector4 min, Vector4 max)
+ {
+ return new Vector4
+ (
+ Mathf.Clamp(x, min.x, max.x),
+ Mathf.Clamp(y, min.y, max.y),
+ Mathf.Clamp(z, min.z, max.z),
+ Mathf.Clamp(w, min.w, max.w)
+ );
+ }
+
+
+ /// <summary>
+ /// Returns a new vector with all components rounded down (towards negative infinity).
+ /// </summary>
+ /// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns>
+ public Vector4 Floor()
+ {
+ return new Vector4(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z), Mathf.Floor(w));
+ }
+
+
+ /// <summary>
+ /// Returns the dot product of this vector and <paramref name="with"/>.
+ /// </summary>
+ /// <param name="with">The other vector to use.</param>
+ /// <returns>The dot product of the two vectors.</returns>
+ public real_t Dot(Vector4 with)
+ {
+ return (x * with.x) + (y * with.y) + (z * with.z) + (w + with.w);
+ }
+
+ /// <summary>
+ /// Returns the inverse of this vector. This is the same as <c>new Vector4(1 / v.x, 1 / v.y, 1 / v.z, 1 / v.w)</c>.
+ /// </summary>
+ /// <returns>The inverse of this vector.</returns>
+ public Vector4 Inverse()
+ {
+ return new Vector4(1 / x, 1 / y, 1 / z, 1 / w);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise.
+ /// </summary>
+ /// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns>
+ public bool IsNormalized()
+ {
+ return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
+ }
+
+ /// <summary>
+ /// Returns the length (magnitude) of this vector.
+ /// </summary>
+ /// <seealso cref="LengthSquared"/>
+ /// <returns>The length of this vector.</returns>
+ public real_t Length()
+ {
+ real_t x2 = x * x;
+ real_t y2 = y * y;
+ real_t z2 = z * z;
+ real_t w2 = w * w;
+
+ return Mathf.Sqrt(x2 + y2 + z2 + w2);
+ }
+
+ /// <summary>
+ /// Returns the squared length (squared magnitude) of this vector.
+ /// This method runs faster than <see cref="Length"/>, so prefer it if
+ /// you need to compare vectors or need the squared length for some formula.
+ /// </summary>
+ /// <returns>The squared length of this vector.</returns>
+ public real_t LengthSquared()
+ {
+ real_t x2 = x * x;
+ real_t y2 = y * y;
+ real_t z2 = z * z;
+ real_t w2 = w * w;
+
+ return x2 + y2 + z2 + w2;
+ }
+
+ /// <summary>
+ /// Returns the result of the linear interpolation between
+ /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>.
+ /// </summary>
+ /// <param name="to">The destination vector for interpolation.</param>
+ /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The resulting vector of the interpolation.</returns>
+ public Vector4 Lerp(Vector4 to, real_t weight)
+ {
+ return new Vector4
+ (
+ Mathf.Lerp(x, to.x, weight),
+ Mathf.Lerp(y, to.y, weight),
+ Mathf.Lerp(z, to.z, weight),
+ Mathf.Lerp(w, to.w, weight)
+ );
+ }
+
+ /// <summary>
+ /// Returns the axis of the vector's highest value. See <see cref="Axis"/>.
+ /// If all components are equal, this method returns <see cref="Axis.X"/>.
+ /// </summary>
+ /// <returns>The index of the highest axis.</returns>
+ public Axis MaxAxisIndex()
+ {
+ int max_index = 0;
+ real_t max_value = x;
+ for (int i = 1; i < 4; i++)
+ {
+ if (this[i] > max_value)
+ {
+ max_index = i;
+ max_value = this[i];
+ }
+ }
+ return (Axis)max_index;
+ }
+
+ /// <summary>
+ /// Returns the axis of the vector's lowest value. See <see cref="Axis"/>.
+ /// If all components are equal, this method returns <see cref="Axis.W"/>.
+ /// </summary>
+ /// <returns>The index of the lowest axis.</returns>
+ public Axis MinAxisIndex()
+ {
+ int min_index = 0;
+ real_t min_value = x;
+ for (int i = 1; i < 4; i++)
+ {
+ if (this[i] <= min_value)
+ {
+ min_index = i;
+ min_value = this[i];
+ }
+ }
+ return (Axis)min_index;
+ }
+
+ /// <summary>
+ /// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>.
+ /// </summary>
+ /// <returns>A normalized version of the vector.</returns>
+ public Vector4 Normalized()
+ {
+ Vector4 v = this;
+ v.Normalize();
+ return v;
+ }
+
+ /// <summary>
+ /// Returns this vector with all components rounded to the nearest integer,
+ /// with halfway cases rounded towards the nearest multiple of two.
+ /// </summary>
+ /// <returns>The rounded vector.</returns>
+ public Vector4 Round()
+ {
+ return new Vector4(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z), Mathf.Round(w));
+ }
+
+ /// <summary>
+ /// Returns a vector with each component set to one or negative one, depending
+ /// on the signs of this vector's components, or zero if the component is zero,
+ /// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
+ /// </summary>
+ /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
+ public Vector4 Sign()
+ {
+ Vector4 v;
+ v.x = Mathf.Sign(x);
+ v.y = Mathf.Sign(y);
+ v.z = Mathf.Sign(z);
+ v.w = Mathf.Sign(w);
+ return v;
+ }
+
+ // Constants
+ private static readonly Vector4 _zero = new Vector4(0, 0, 0, 0);
+ private static readonly Vector4 _one = new Vector4(1, 1, 1, 1);
+ private static readonly Vector4 _inf = new Vector4(Mathf.Inf, Mathf.Inf, Mathf.Inf, Mathf.Inf);
+
+ /// <summary>
+ /// Zero vector, a vector with all components set to <c>0</c>.
+ /// </summary>
+ /// <value>Equivalent to <c>new Vector4(0, 0, 0, 0)</c>.</value>
+ public static Vector4 Zero { get { return _zero; } }
+ /// <summary>
+ /// One vector, a vector with all components set to <c>1</c>.
+ /// </summary>
+ /// <value>Equivalent to <c>new Vector4(1, 1, 1, 1)</c>.</value>
+ public static Vector4 One { get { return _one; } }
+ /// <summary>
+ /// Infinity vector, a vector with all components set to <see cref="Mathf.Inf"/>.
+ /// </summary>
+ /// <value>Equivalent to <c>new Vector4(Mathf.Inf, Mathf.Inf, Mathf.Inf, Mathf.Inf)</c>.</value>
+ public static Vector4 Inf { get { return _inf; } }
+
+ /// <summary>
+ /// Constructs a new <see cref="Vector4"/> with the given components.
+ /// </summary>
+ /// <param name="x">The vector's X component.</param>
+ /// <param name="y">The vector's Y component.</param>
+ /// <param name="z">The vector's Z component.</param>
+ /// <param name="w">The vector's W component.</param>
+ public Vector4(real_t x, real_t y, real_t z, real_t w)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="Vector4"/> from an existing <see cref="Vector4"/>.
+ /// </summary>
+ /// <param name="v">The existing <see cref="Vector4"/>.</param>
+ public Vector4(Vector4 v)
+ {
+ x = v.x;
+ y = v.y;
+ z = v.z;
+ w = v.w;
+ }
+
+ /// <summary>
+ /// Adds each component of the <see cref="Vector4"/>
+ /// with the components of the given <see cref="Vector4"/>.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>The added vector.</returns>
+ public static Vector4 operator +(Vector4 left, Vector4 right)
+ {
+ left.x += right.x;
+ left.y += right.y;
+ left.z += right.z;
+ left.w += right.w;
+ return left;
+ }
+
+ /// <summary>
+ /// Subtracts each component of the <see cref="Vector4"/>
+ /// by the components of the given <see cref="Vector4"/>.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>The subtracted vector.</returns>
+ public static Vector4 operator -(Vector4 left, Vector4 right)
+ {
+ left.x -= right.x;
+ left.y -= right.y;
+ left.z -= right.z;
+ left.w -= right.w;
+ return left;
+ }
+
+ /// <summary>
+ /// Returns the negative value of the <see cref="Vector4"/>.
+ /// This is the same as writing <c>new Vector4(-v.x, -v.y, -v.z, -v.w)</c>.
+ /// This operation flips the direction of the vector while
+ /// keeping the same magnitude.
+ /// With floats, the number zero can be either positive or negative.
+ /// </summary>
+ /// <param name="vec">The vector to negate/flip.</param>
+ /// <returns>The negated/flipped vector.</returns>
+ public static Vector4 operator -(Vector4 vec)
+ {
+ vec.x = -vec.x;
+ vec.y = -vec.y;
+ vec.z = -vec.z;
+ vec.w = -vec.w;
+ return vec;
+ }
+
+ /// <summary>
+ /// Multiplies each component of the <see cref="Vector4"/>
+ /// by the given <see cref="real_t"/>.
+ /// </summary>
+ /// <param name="vec">The vector to multiply.</param>
+ /// <param name="scale">The scale to multiply by.</param>
+ /// <returns>The multiplied vector.</returns>
+ public static Vector4 operator *(Vector4 vec, real_t scale)
+ {
+ vec.x *= scale;
+ vec.y *= scale;
+ vec.z *= scale;
+ vec.w *= scale;
+ return vec;
+ }
+
+ /// <summary>
+ /// Multiplies each component of the <see cref="Vector4"/>
+ /// by the given <see cref="real_t"/>.
+ /// </summary>
+ /// <param name="scale">The scale to multiply by.</param>
+ /// <param name="vec">The vector to multiply.</param>
+ /// <returns>The multiplied vector.</returns>
+ public static Vector4 operator *(real_t scale, Vector4 vec)
+ {
+ vec.x *= scale;
+ vec.y *= scale;
+ vec.z *= scale;
+ vec.w *= scale;
+ return vec;
+ }
+
+ /// <summary>
+ /// Multiplies each component of the <see cref="Vector4"/>
+ /// by the components of the given <see cref="Vector4"/>.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>The multiplied vector.</returns>
+ public static Vector4 operator *(Vector4 left, Vector4 right)
+ {
+ left.x *= right.x;
+ left.y *= right.y;
+ left.z *= right.z;
+ left.w *= right.w;
+ return left;
+ }
+
+ /// <summary>
+ /// Divides each component of the <see cref="Vector4"/>
+ /// by the given <see cref="real_t"/>.
+ /// </summary>
+ /// <param name="vec">The dividend vector.</param>
+ /// <param name="divisor">The divisor value.</param>
+ /// <returns>The divided vector.</returns>
+ public static Vector4 operator /(Vector4 vec, real_t divisor)
+ {
+ vec.x /= divisor;
+ vec.y /= divisor;
+ vec.z /= divisor;
+ vec.w /= divisor;
+ return vec;
+ }
+
+ /// <summary>
+ /// Divides each component of the <see cref="Vector4"/>
+ /// by the components of the given <see cref="Vector4"/>.
+ /// </summary>
+ /// <param name="vec">The dividend vector.</param>
+ /// <param name="divisorv">The divisor vector.</param>
+ /// <returns>The divided vector.</returns>
+ public static Vector4 operator /(Vector4 vec, Vector4 divisorv)
+ {
+ vec.x /= divisorv.x;
+ vec.y /= divisorv.y;
+ vec.z /= divisorv.z;
+ vec.w /= divisorv.w;
+ return vec;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the vectors are exactly equal.
+ /// Note: Due to floating-point precision errors, consider using
+ /// <see cref="IsEqualApprox"/> instead, which is more reliable.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the vectors are exactly equal.</returns>
+ public static bool operator ==(Vector4 left, Vector4 right)
+ {
+ return left.Equals(right);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the vectors are not equal.
+ /// Note: Due to floating-point precision errors, consider using
+ /// <see cref="IsEqualApprox"/> instead, which is more reliable.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the vectors are not equal.</returns>
+ public static bool operator !=(Vector4 left, Vector4 right)
+ {
+ return !left.Equals(right);
+ }
+
+ /// <summary>
+ /// Compares two <see cref="Vector4"/> vectors by first checking if
+ /// the X value of the <paramref name="left"/> vector is less than
+ /// the X value of the <paramref name="right"/> vector.
+ /// If the X values are exactly equal, then it repeats this check
+ /// with the Y, Z and finally W values of the two vectors.
+ /// This operator is useful for sorting vectors.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the left is less than the right.</returns>
+ public static bool operator <(Vector4 left, Vector4 right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ {
+ if (left.z == right.z)
+ {
+ return left.w < right.w;
+ }
+ return left.z < right.z;
+ }
+ return left.y < right.y;
+ }
+ return left.x < right.x;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="Vector4"/> vectors by first checking if
+ /// the X value of the <paramref name="left"/> vector is greater than
+ /// the X value of the <paramref name="right"/> vector.
+ /// If the X values are exactly equal, then it repeats this check
+ /// with the Y, Z and finally W values of the two vectors.
+ /// This operator is useful for sorting vectors.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the left is greater than the right.</returns>
+ public static bool operator >(Vector4 left, Vector4 right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ {
+ if (left.z == right.z)
+ {
+ return left.w > right.w;
+ }
+ return left.z > right.z;
+ }
+ return left.y > right.y;
+ }
+ return left.x > right.x;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="Vector4"/> vectors by first checking if
+ /// the X value of the <paramref name="left"/> vector is less than
+ /// or equal to the X value of the <paramref name="right"/> vector.
+ /// If the X values are exactly equal, then it repeats this check
+ /// with the Y, Z and finally W values of the two vectors.
+ /// This operator is useful for sorting vectors.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the left is less than or equal to the right.</returns>
+ public static bool operator <=(Vector4 left, Vector4 right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ {
+ if (left.z == right.z)
+ {
+ return left.w <= right.w;
+ }
+ return left.z < right.z;
+ }
+ return left.y < right.y;
+ }
+ return left.x < right.x;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="Vector4"/> vectors by first checking if
+ /// the X value of the <paramref name="left"/> vector is greater than
+ /// or equal to the X value of the <paramref name="right"/> vector.
+ /// If the X values are exactly equal, then it repeats this check
+ /// with the Y, Z and finally W values of the two vectors.
+ /// This operator is useful for sorting vectors.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the left is greater than or equal to the right.</returns>
+ public static bool operator >=(Vector4 left, Vector4 right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ {
+ if (left.z == right.z)
+ {
+ return left.w >= right.w;
+ }
+ return left.z > right.z;
+ }
+ return left.y > right.y;
+ }
+ return left.x > right.x;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the vector is exactly equal
+ /// to the given object (<see paramref="obj"/>).
+ /// Note: Due to floating-point precision errors, consider using
+ /// <see cref="IsEqualApprox"/> instead, which is more reliable.
+ /// </summary>
+ /// <param name="obj">The object to compare with.</param>
+ /// <returns>Whether or not the vector and the object are equal.</returns>
+ public override bool Equals(object obj)
+ {
+ if (obj is Vector4)
+ {
+ return Equals((Vector4)obj);
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the vectors are exactly equal.
+ /// Note: Due to floating-point precision errors, consider using
+ /// <see cref="IsEqualApprox"/> instead, which is more reliable.
+ /// </summary>
+ /// <param name="other">The other vector.</param>
+ /// <returns>Whether or not the vectors are exactly equal.</returns>
+ public bool Equals(Vector4 other)
+ {
+ return x == other.x && y == other.y && z == other.z && w == other.w;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are approximately equal,
+ /// by running <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component.
+ /// </summary>
+ /// <param name="other">The other vector to compare.</param>
+ /// <returns>Whether or not the vectors are approximately equal.</returns>
+ public bool IsEqualApprox(Vector4 other)
+ {
+ return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
+ }
+
+ /// <summary>
+ /// Serves as the hash function for <see cref="Vector4"/>.
+ /// </summary>
+ /// <returns>A hash code for this vector.</returns>
+ public override int GetHashCode()
+ {
+ return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts this <see cref="Vector4"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this vector.</returns>
+ public override string ToString()
+ {
+ return $"({x}, {y}, {z}, {w})";
+ }
+
+ /// <summary>
+ /// Converts this <see cref="Vector4"/> to a string with the given <paramref name="format"/>.
+ /// </summary>
+ /// <returns>A string representation of this vector.</returns>
+ public string ToString(string format)
+ {
+ return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}, {w.ToString(format)})";
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
new file mode 100644
index 0000000000..365dcef486
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
@@ -0,0 +1,702 @@
+#if REAL_T_IS_DOUBLE
+using real_t = System.Double;
+#else
+using real_t = System.Single;
+#endif
+using System;
+using System.Runtime.InteropServices;
+
+namespace Godot
+{
+ /// <summary>
+ /// 4-element structure that can be used to represent 4D grid coordinates or sets of integers.
+ /// </summary>
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Vector4i : IEquatable<Vector4i>
+ {
+ /// <summary>
+ /// Enumerated index values for the axes.
+ /// Returned by <see cref="MaxAxisIndex"/> and <see cref="MinAxisIndex"/>.
+ /// </summary>
+ public enum Axis
+ {
+ /// <summary>
+ /// The vector's X axis.
+ /// </summary>
+ X = 0,
+ /// <summary>
+ /// The vector's Y axis.
+ /// </summary>
+ Y,
+ /// <summary>
+ /// The vector's Z axis.
+ /// </summary>
+ Z,
+ /// <summary>
+ /// The vector's W axis.
+ /// </summary>
+ W
+ }
+
+ /// <summary>
+ /// The vector's X component. Also accessible by using the index position <c>[0]</c>.
+ /// </summary>
+ public int x;
+
+ /// <summary>
+ /// The vector's Y component. Also accessible by using the index position <c>[1]</c>.
+ /// </summary>
+ public int y;
+
+ /// <summary>
+ /// The vector's Z component. Also accessible by using the index position <c>[2]</c>.
+ /// </summary>
+ public int z;
+
+ /// <summary>
+ /// The vector's W component. Also accessible by using the index position <c>[3]</c>.
+ /// </summary>
+ public int w;
+
+ /// <summary>
+ /// Access vector components using their <paramref name="index"/>.
+ /// </summary>
+ /// <exception cref="IndexOutOfRangeException">
+ /// Thrown when the given the <paramref name="index"/> is not 0, 1, 2 or 3.
+ /// </exception>
+ /// <value>
+ /// <c>[0]</c> is equivalent to <see cref="x"/>,
+ /// <c>[1]</c> is equivalent to <see cref="y"/>,
+ /// <c>[2]</c> is equivalent to <see cref="z"/>.
+ /// <c>[3]</c> is equivalent to <see cref="w"/>.
+ /// </value>
+ public int this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ case 3:
+ return w;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x = value;
+ return;
+ case 1:
+ y = value;
+ return;
+ case 2:
+ z = value;
+ return;
+ case 3:
+ w = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Helper method for deconstruction into a tuple.
+ /// </summary>
+ public void Deconstruct(out int x, out int y, out int z, out int w)
+ {
+ x = this.x;
+ y = this.y;
+ z = this.z;
+ w = this.w;
+ }
+
+ /// <summary>
+ /// Returns a new vector with all components in absolute values (i.e. positive).
+ /// </summary>
+ /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns>
+ public Vector4i Abs()
+ {
+ return new Vector4i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w));
+ }
+
+ /// <summary>
+ /// Returns a new vector with all components clamped between the
+ /// components of <paramref name="min"/> and <paramref name="max"/> using
+ /// <see cref="Mathf.Clamp(int, int, int)"/>.
+ /// </summary>
+ /// <param name="min">The vector with minimum allowed values.</param>
+ /// <param name="max">The vector with maximum allowed values.</param>
+ /// <returns>The vector with all components clamped.</returns>
+ public Vector4i Clamp(Vector4i min, Vector4i max)
+ {
+ return new Vector4i
+ (
+ Mathf.Clamp(x, min.x, max.x),
+ Mathf.Clamp(y, min.y, max.y),
+ Mathf.Clamp(z, min.z, max.z),
+ Mathf.Clamp(w, min.w, max.w)
+ );
+ }
+
+ /// <summary>
+ /// Returns the length (magnitude) of this vector.
+ /// </summary>
+ /// <seealso cref="LengthSquared"/>
+ /// <returns>The length of this vector.</returns>
+ public real_t Length()
+ {
+ int x2 = x * x;
+ int y2 = y * y;
+ int z2 = z * z;
+ int w2 = w * w;
+
+ return Mathf.Sqrt(x2 + y2 + z2 + w2);
+ }
+
+ /// <summary>
+ /// Returns the squared length (squared magnitude) of this vector.
+ /// This method runs faster than <see cref="Length"/>, so prefer it if
+ /// you need to compare vectors or need the squared length for some formula.
+ /// </summary>
+ /// <returns>The squared length of this vector.</returns>
+ public int LengthSquared()
+ {
+ int x2 = x * x;
+ int y2 = y * y;
+ int z2 = z * z;
+ int w2 = w * w;
+
+ return x2 + y2 + z2 + w2;
+ }
+
+ /// <summary>
+ /// Returns the axis of the vector's highest value. See <see cref="Axis"/>.
+ /// If all components are equal, this method returns <see cref="Axis.X"/>.
+ /// </summary>
+ /// <returns>The index of the highest axis.</returns>
+ public Axis MaxAxisIndex()
+ {
+ int max_index = 0;
+ int max_value = x;
+ for (int i = 1; i < 4; i++)
+ {
+ if (this[i] > max_value)
+ {
+ max_index = i;
+ max_value = this[i];
+ }
+ }
+ return (Axis)max_index;
+ }
+
+ /// <summary>
+ /// Returns the axis of the vector's lowest value. See <see cref="Axis"/>.
+ /// If all components are equal, this method returns <see cref="Axis.W"/>.
+ /// </summary>
+ /// <returns>The index of the lowest axis.</returns>
+ public Axis MinAxisIndex()
+ {
+ int min_index = 0;
+ int min_value = x;
+ for (int i = 1; i < 4; i++)
+ {
+ if (this[i] <= min_value)
+ {
+ min_index = i;
+ min_value = this[i];
+ }
+ }
+ return (Axis)min_index;
+ }
+
+ /// <summary>
+ /// Returns a vector with each component set to one or negative one, depending
+ /// on the signs of this vector's components, or zero if the component is zero,
+ /// by calling <see cref="Mathf.Sign(int)"/> on each component.
+ /// </summary>
+ /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
+ public Vector4i Sign()
+ {
+ return new Vector4i(Mathf.Sign(x), Mathf.Sign(y), Mathf.Sign(z), Mathf.Sign(w));
+ }
+
+ // Constants
+ private static readonly Vector4i _zero = new Vector4i(0, 0, 0, 0);
+ private static readonly Vector4i _one = new Vector4i(1, 1, 1, 1);
+
+ /// <summary>
+ /// Zero vector, a vector with all components set to <c>0</c>.
+ /// </summary>
+ /// <value>Equivalent to <c>new Vector4i(0, 0, 0, 0)</c>.</value>
+ public static Vector4i Zero { get { return _zero; } }
+ /// <summary>
+ /// One vector, a vector with all components set to <c>1</c>.
+ /// </summary>
+ /// <value>Equivalent to <c>new Vector4i(1, 1, 1, 1)</c>.</value>
+ public static Vector4i One { get { return _one; } }
+
+ /// <summary>
+ /// Constructs a new <see cref="Vector4i"/> with the given components.
+ /// </summary>
+ /// <param name="x">The vector's X component.</param>
+ /// <param name="y">The vector's Y component.</param>
+ /// <param name="z">The vector's Z component.</param>
+ /// <param name="w">The vector's W component.</param>
+ public Vector4i(int x, int y, int z, int w)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="Vector4i"/> from an existing <see cref="Vector4i"/>.
+ /// </summary>
+ /// <param name="vi">The existing <see cref="Vector4i"/>.</param>
+ public Vector4i(Vector4i vi)
+ {
+ this.x = vi.x;
+ this.y = vi.y;
+ this.z = vi.z;
+ this.w = vi.w;
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="Vector4i"/> from an existing <see cref="Vector4"/>
+ /// by rounding the components via <see cref="Mathf.RoundToInt(real_t)"/>.
+ /// </summary>
+ /// <param name="v">The <see cref="Vector4"/> to convert.</param>
+ public Vector4i(Vector4 v)
+ {
+ this.x = Mathf.RoundToInt(v.x);
+ this.y = Mathf.RoundToInt(v.y);
+ this.z = Mathf.RoundToInt(v.z);
+ this.w = Mathf.RoundToInt(v.w);
+ }
+
+ /// <summary>
+ /// Adds each component of the <see cref="Vector4i"/>
+ /// with the components of the given <see cref="Vector4i"/>.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>The added vector.</returns>
+ public static Vector4i operator +(Vector4i left, Vector4i right)
+ {
+ left.x += right.x;
+ left.y += right.y;
+ left.z += right.z;
+ left.w += right.w;
+ return left;
+ }
+
+ /// <summary>
+ /// Subtracts each component of the <see cref="Vector4i"/>
+ /// by the components of the given <see cref="Vector4i"/>.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>The subtracted vector.</returns>
+ public static Vector4i operator -(Vector4i left, Vector4i right)
+ {
+ left.x -= right.x;
+ left.y -= right.y;
+ left.z -= right.z;
+ left.w -= right.w;
+ return left;
+ }
+
+ /// <summary>
+ /// Returns the negative value of the <see cref="Vector4i"/>.
+ /// This is the same as writing <c>new Vector4i(-v.x, -v.y, -v.z, -v.w)</c>.
+ /// This operation flips the direction of the vector while
+ /// keeping the same magnitude.
+ /// </summary>
+ /// <param name="vec">The vector to negate/flip.</param>
+ /// <returns>The negated/flipped vector.</returns>
+ public static Vector4i operator -(Vector4i vec)
+ {
+ vec.x = -vec.x;
+ vec.y = -vec.y;
+ vec.z = -vec.z;
+ vec.w = -vec.w;
+ return vec;
+ }
+
+ /// <summary>
+ /// Multiplies each component of the <see cref="Vector4i"/>
+ /// by the given <see langword="int"/>.
+ /// </summary>
+ /// <param name="vec">The vector to multiply.</param>
+ /// <param name="scale">The scale to multiply by.</param>
+ /// <returns>The multiplied vector.</returns>
+ public static Vector4i operator *(Vector4i vec, int scale)
+ {
+ vec.x *= scale;
+ vec.y *= scale;
+ vec.z *= scale;
+ vec.w *= scale;
+ return vec;
+ }
+
+ /// <summary>
+ /// Multiplies each component of the <see cref="Vector4i"/>
+ /// by the given <see langword="int"/>.
+ /// </summary>
+ /// <param name="scale">The scale to multiply by.</param>
+ /// <param name="vec">The vector to multiply.</param>
+ /// <returns>The multiplied vector.</returns>
+ public static Vector4i operator *(int scale, Vector4i vec)
+ {
+ vec.x *= scale;
+ vec.y *= scale;
+ vec.z *= scale;
+ vec.w *= scale;
+ return vec;
+ }
+
+ /// <summary>
+ /// Multiplies each component of the <see cref="Vector4i"/>
+ /// by the components of the given <see cref="Vector4i"/>.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>The multiplied vector.</returns>
+ public static Vector4i operator *(Vector4i left, Vector4i right)
+ {
+ left.x *= right.x;
+ left.y *= right.y;
+ left.z *= right.z;
+ left.w *= right.w;
+ return left;
+ }
+
+ /// <summary>
+ /// Divides each component of the <see cref="Vector4i"/>
+ /// by the given <see langword="int"/>.
+ /// </summary>
+ /// <param name="vec">The dividend vector.</param>
+ /// <param name="divisor">The divisor value.</param>
+ /// <returns>The divided vector.</returns>
+ public static Vector4i operator /(Vector4i vec, int divisor)
+ {
+ vec.x /= divisor;
+ vec.y /= divisor;
+ vec.z /= divisor;
+ vec.w /= divisor;
+ return vec;
+ }
+
+ /// <summary>
+ /// Divides each component of the <see cref="Vector4i"/>
+ /// by the components of the given <see cref="Vector4i"/>.
+ /// </summary>
+ /// <param name="vec">The dividend vector.</param>
+ /// <param name="divisorv">The divisor vector.</param>
+ /// <returns>The divided vector.</returns>
+ public static Vector4i operator /(Vector4i vec, Vector4i divisorv)
+ {
+ vec.x /= divisorv.x;
+ vec.y /= divisorv.y;
+ vec.z /= divisorv.z;
+ vec.w /= divisorv.w;
+ return vec;
+ }
+
+ /// <summary>
+ /// Gets the remainder of each component of the <see cref="Vector4i"/>
+ /// with the components of the given <see langword="int"/>.
+ /// This operation uses truncated division, which is often not desired
+ /// as it does not work well with negative numbers.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print(new Vecto43i(10, -20, 30, -40) % 7); // Prints "(3, -6, 2, -5)"
+ /// </code>
+ /// </example>
+ /// <param name="vec">The dividend vector.</param>
+ /// <param name="divisor">The divisor value.</param>
+ /// <returns>The remainder vector.</returns>
+ public static Vector4i operator %(Vector4i vec, int divisor)
+ {
+ vec.x %= divisor;
+ vec.y %= divisor;
+ vec.z %= divisor;
+ vec.w %= divisor;
+ return vec;
+ }
+
+ /// <summary>
+ /// Gets the remainder of each component of the <see cref="Vector4i"/>
+ /// with the components of the given <see cref="Vector4i"/>.
+ /// This operation uses truncated division, which is often not desired
+ /// as it does not work well with negative numbers.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// GD.Print(new Vector4i(10, -20, 30, -40) % new Vector4i(6, 7, 8, 9)); // Prints "(4, -6, 6, -4)"
+ /// </code>
+ /// </example>
+ /// <param name="vec">The dividend vector.</param>
+ /// <param name="divisorv">The divisor vector.</param>
+ /// <returns>The remainder vector.</returns>
+ public static Vector4i operator %(Vector4i vec, Vector4i divisorv)
+ {
+ vec.x %= divisorv.x;
+ vec.y %= divisorv.y;
+ vec.z %= divisorv.z;
+ vec.w %= divisorv.w;
+ return vec;
+ }
+
+ /// <summary>
+ /// Performs a bitwise AND operation with this <see cref="Vector4i"/>
+ /// and the given <see langword="int"/>.
+ /// </summary>
+ /// <param name="vec">The vector to AND with.</param>
+ /// <param name="and">The integer to AND with.</param>
+ /// <returns>The result of the bitwise AND.</returns>
+ public static Vector4i operator &(Vector4i vec, int and)
+ {
+ vec.x &= and;
+ vec.y &= and;
+ vec.z &= and;
+ vec.w &= and;
+ return vec;
+ }
+
+ /// <summary>
+ /// Performs a bitwise AND operation with this <see cref="Vector4i"/>
+ /// and the given <see cref="Vector4i"/>.
+ /// </summary>
+ /// <param name="vec">The left vector to AND with.</param>
+ /// <param name="andv">The right vector to AND with.</param>
+ /// <returns>The result of the bitwise AND.</returns>
+ public static Vector4i operator &(Vector4i vec, Vector4i andv)
+ {
+ vec.x &= andv.x;
+ vec.y &= andv.y;
+ vec.z &= andv.z;
+ vec.w &= andv.w;
+ return vec;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the vectors are equal.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the vectors are equal.</returns>
+ public static bool operator ==(Vector4i left, Vector4i right)
+ {
+ return left.Equals(right);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the vectors are not equal.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the vectors are not equal.</returns>
+ public static bool operator !=(Vector4i left, Vector4i right)
+ {
+ return !left.Equals(right);
+ }
+
+ /// <summary>
+ /// Compares two <see cref="Vector4i"/> vectors by first checking if
+ /// the X value of the <paramref name="left"/> vector is less than
+ /// the X value of the <paramref name="right"/> vector.
+ /// If the X values are exactly equal, then it repeats this check
+ /// with the Y, Z and finally W values of the two vectors.
+ /// This operator is useful for sorting vectors.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the left is less than the right.</returns>
+ public static bool operator <(Vector4i left, Vector4i right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ {
+ if (left.z == right.z)
+ {
+ return left.w < right.w;
+ }
+ return left.z < right.z;
+ }
+ return left.y < right.y;
+ }
+ return left.x < right.x;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="Vector4i"/> vectors by first checking if
+ /// the X value of the <paramref name="left"/> vector is greater than
+ /// the X value of the <paramref name="right"/> vector.
+ /// If the X values are exactly equal, then it repeats this check
+ /// with the Y, Z and finally W values of the two vectors.
+ /// This operator is useful for sorting vectors.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the left is greater than the right.</returns>
+ public static bool operator >(Vector4i left, Vector4i right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ {
+ if (left.z == right.z)
+ {
+ return left.w > right.w;
+ }
+ return left.z > right.z;
+ }
+ return left.y > right.y;
+ }
+ return left.x > right.x;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="Vector4i"/> vectors by first checking if
+ /// the X value of the <paramref name="left"/> vector is less than
+ /// or equal to the X value of the <paramref name="right"/> vector.
+ /// If the X values are exactly equal, then it repeats this check
+ /// with the Y, Z and finally W values of the two vectors.
+ /// This operator is useful for sorting vectors.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the left is less than or equal to the right.</returns>
+ public static bool operator <=(Vector4i left, Vector4i right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ {
+ if (left.z == right.z)
+ {
+ return left.w <= right.w;
+ }
+ return left.z < right.z;
+ }
+ return left.y < right.y;
+ }
+ return left.x < right.x;
+ }
+
+ /// <summary>
+ /// Compares two <see cref="Vector4i"/> vectors by first checking if
+ /// the X value of the <paramref name="left"/> vector is greater than
+ /// or equal to the X value of the <paramref name="right"/> vector.
+ /// If the X values are exactly equal, then it repeats this check
+ /// with the Y, Z and finally W values of the two vectors.
+ /// This operator is useful for sorting vectors.
+ /// </summary>
+ /// <param name="left">The left vector.</param>
+ /// <param name="right">The right vector.</param>
+ /// <returns>Whether or not the left is greater than or equal to the right.</returns>
+ public static bool operator >=(Vector4i left, Vector4i right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ {
+ if (left.z == right.z)
+ {
+ return left.w >= right.w;
+ }
+ return left.z > right.z;
+ }
+ return left.y > right.y;
+ }
+ return left.x > right.x;
+ }
+
+ /// <summary>
+ /// Converts this <see cref="Vector4i"/> to a <see cref="Vector4"/>.
+ /// </summary>
+ /// <param name="value">The vector to convert.</param>
+ public static implicit operator Vector4(Vector4i value)
+ {
+ return new Vector4(value.x, value.y, value.z, value.w);
+ }
+
+ /// <summary>
+ /// Converts a <see cref="Vector4"/> to a <see cref="Vector4i"/>.
+ /// </summary>
+ /// <param name="value">The vector to convert.</param>
+ public static explicit operator Vector4i(Vector4 value)
+ {
+ return new Vector4i(value);
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the vector is equal
+ /// to the given object (<see paramref="obj"/>).
+ /// </summary>
+ /// <param name="obj">The object to compare with.</param>
+ /// <returns>Whether or not the vector and the object are equal.</returns>
+ public override bool Equals(object obj)
+ {
+ if (obj is Vector4i)
+ {
+ return Equals((Vector4i)obj);
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Returns <see langword="true"/> if the vectors are equal.
+ /// </summary>
+ /// <param name="other">The other vector.</param>
+ /// <returns>Whether or not the vectors are equal.</returns>
+ public bool Equals(Vector4i other)
+ {
+ return x == other.x && y == other.y && z == other.z && w == other.w;
+ }
+
+ /// <summary>
+ /// Serves as the hash function for <see cref="Vector4i"/>.
+ /// </summary>
+ /// <returns>A hash code for this vector.</returns>
+ public override int GetHashCode()
+ {
+ return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts this <see cref="Vector4i"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this vector.</returns>
+ public override string ToString()
+ {
+ return $"({x}, {y}, {z}, {w})";
+ }
+
+ /// <summary>
+ /// Converts this <see cref="Vector4i"/> to a string with the given <paramref name="format"/>.
+ /// </summary>
+ /// <returns>A string representation of this vector.</returns>
+ public string ToString(string format)
+ {
+ return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}), {w.ToString(format)})";
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index 1fcfe74c86..4f55ce47e8 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" />
@@ -50,6 +50,7 @@
<Compile Include="Core\NodePath.cs" />
<Compile Include="Core\Object.base.cs" />
<Compile Include="Core\Plane.cs" />
+ <Compile Include="Core\Projection.cs" />
<Compile Include="Core\Quaternion.cs" />
<Compile Include="Core\Rect2.cs" />
<Compile Include="Core\Rect2i.cs" />
@@ -65,6 +66,8 @@
<Compile Include="Core\Vector2i.cs" />
<Compile Include="Core\Vector3.cs" />
<Compile Include="Core\Vector3i.cs" />
+ <Compile Include="Core\Vector4.cs" />
+ <Compile Include="Core\Vector4i.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<!--
diff --git a/modules/mono/glue/callable_glue.cpp b/modules/mono/glue/callable_glue.cpp
index e59b34313c..521dc3dff7 100644
--- a/modules/mono/glue/callable_glue.cpp
+++ b/modules/mono/glue/callable_glue.cpp
@@ -49,7 +49,7 @@ MonoObject *godot_icall_Callable_Call(GDMonoMarshal::M_Callable *p_callable, Mon
Variant result;
Callable::CallError error;
- callable.call(args.ptr(), argc, result, error);
+ callable.callp(args.ptr(), argc, result, error);
return GDMonoMarshal::variant_to_mono_object(result);
}
@@ -68,7 +68,7 @@ void godot_icall_Callable_CallDeferred(GDMonoMarshal::M_Callable *p_callable, Mo
args.set(i, &arg_store.get(i));
}
- callable.call_deferred(args.ptr(), argc);
+ callable.call_deferredp(args.ptr(), argc);
}
void godot_register_callable_icalls() {
diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h
index 9638b23410..f9ad1a9893 100644
--- a/modules/mono/glue/glue_header.h
+++ b/modules/mono/glue/glue_header.h
@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef GLUE_HEADER_H
+#define GLUE_HEADER_H
+
#ifdef MONO_GLUE_ENABLED
#include "../mono_gd/gd_mono_marshal.h"
@@ -84,3 +87,5 @@ void godot_register_glue_header_icalls() {
#include "arguments_vector.h"
#endif // MONO_GLUE_ENABLED
+
+#endif // GLUE_HEADER_H
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/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index cb2b60fcce..f17b24e399 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -184,7 +184,7 @@ private:
data_mono_bin_dir = data_mono_root_dir.plus_file("bin");
#endif
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
if (!DirAccess::exists(data_editor_tools_dir)) {
data_editor_tools_dir = exe_dir.plus_file("../Resources/GodotSharp/Tools");
}
@@ -222,7 +222,7 @@ private:
data_mono_bin_dir = data_mono_root_dir.plus_file("bin");
#endif
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
if (!DirAccess::exists(data_mono_root_dir)) {
data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc");
data_mono_lib_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/lib");
diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h
index ab9e508c99..e2aff1d19d 100644
--- a/modules/mono/mono_gc_handle.h
+++ b/modules/mono/mono_gc_handle.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CSHARP_GC_HANDLE_H
-#define CSHARP_GC_HANDLE_H
+#ifndef MONO_GC_HANDLE_H
+#define MONO_GC_HANDLE_H
#include <mono/jit/jit.h>
@@ -104,4 +104,4 @@ public:
~MonoGCHandleRef() { release(); }
};
-#endif // CSHARP_GC_HANDLE_H
+#endif // MONO_GC_HANDLE_H
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 39a8ef22b7..d3d3bb2bef 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -55,7 +55,7 @@
#ifdef ANDROID_ENABLED
#include "android_mono_config.h"
#include "support/android_support.h"
-#elif defined(IPHONE_ENABLED)
+#elif defined(IOS_ENABLED)
#include "support/ios_support.h"
#endif
@@ -188,7 +188,7 @@ MonoDomain *gd_initialize_mono_runtime() {
MonoDomain *gd_initialize_mono_runtime() {
gd_mono_debug_init();
-#if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED)
+#if defined(IOS_ENABLED) || defined(ANDROID_ENABLED)
// I don't know whether this actually matters or not
const char *runtime_version = "mobile";
#else
@@ -263,7 +263,7 @@ void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_di
if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) {
r_config_dir = mono_reg_info.config_dir;
}
-#elif defined(OSX_ENABLED)
+#elif defined(MACOS_ENABLED)
const char *c_assembly_rootdir = mono_assembly_getrootdir();
const char *c_config_dir = mono_get_config_dir();
@@ -343,7 +343,7 @@ void GDMono::initialize() {
#if defined(ANDROID_ENABLED)
gdmono::android::support::initialize();
-#elif defined(IPHONE_ENABLED)
+#elif defined(IOS_ENABLED)
gdmono::ios::support::initialize();
#endif
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index 44a8e26b8f..69d8c7edc9 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -108,9 +108,12 @@ void CachedData::clear_godot_api_cache() {
class_Transform2D = nullptr;
class_Vector3 = nullptr;
class_Vector3i = nullptr;
+ class_Vector4 = nullptr;
+ class_Vector4i = nullptr;
class_Basis = nullptr;
class_Quaternion = nullptr;
class_Transform3D = nullptr;
+ class_Projection = nullptr;
class_AABB = nullptr;
class_Color = nullptr;
class_Plane = nullptr;
@@ -140,8 +143,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;
@@ -236,9 +242,12 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D));
CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3));
CACHE_CLASS_AND_CHECK(Vector3i, GODOT_API_CLASS(Vector3i));
+ CACHE_CLASS_AND_CHECK(Vector4, GODOT_API_CLASS(Vector4));
+ CACHE_CLASS_AND_CHECK(Vector4i, GODOT_API_CLASS(Vector4i));
CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis));
CACHE_CLASS_AND_CHECK(Quaternion, GODOT_API_CLASS(Quaternion));
CACHE_CLASS_AND_CHECK(Transform3D, GODOT_API_CLASS(Transform3D));
+ CACHE_CLASS_AND_CHECK(Projection, GODOT_API_CLASS(Projection));
CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB));
CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color));
CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane));
@@ -268,8 +277,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..e9cc26899e 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -79,9 +79,12 @@ struct CachedData {
GDMonoClass *class_Transform2D = nullptr;
GDMonoClass *class_Vector3 = nullptr;
GDMonoClass *class_Vector3i = nullptr;
+ GDMonoClass *class_Vector4 = nullptr;
+ GDMonoClass *class_Vector4i = nullptr;
GDMonoClass *class_Basis = nullptr;
GDMonoClass *class_Quaternion = nullptr;
GDMonoClass *class_Transform3D = nullptr;
+ GDMonoClass *class_Projection = nullptr;
GDMonoClass *class_AABB = nullptr;
GDMonoClass *class_Color = nullptr;
GDMonoClass *class_Plane = nullptr;
@@ -111,8 +114,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/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index 333a06c94a..cb025fc67a 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -140,6 +140,18 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
break;
}
+ if (tclass == CACHED_CLASS(Vector4)) {
+ GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_value.operator ::Vector4());
+ mono_field_set_value(p_object, mono_field, &from);
+ break;
+ }
+
+ if (tclass == CACHED_CLASS(Vector4i)) {
+ GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_value.operator ::Vector4i());
+ mono_field_set_value(p_object, mono_field, &from);
+ break;
+ }
+
if (tclass == CACHED_CLASS(Basis)) {
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis());
mono_field_set_value(p_object, mono_field, &from);
@@ -158,6 +170,12 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
break;
}
+ if (tclass == CACHED_CLASS(Projection)) {
+ GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_value.operator ::Projection());
+ mono_field_set_value(p_object, mono_field, &from);
+ break;
+ }
+
if (tclass == CACHED_CLASS(AABB)) {
GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB());
mono_field_set_value(p_object, mono_field, &from);
@@ -328,6 +346,14 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_value.operator ::Vector3i());
mono_field_set_value(p_object, mono_field, &from);
} break;
+ case Variant::VECTOR4: {
+ GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_value.operator ::Vector4());
+ mono_field_set_value(p_object, mono_field, &from);
+ } break;
+ case Variant::VECTOR4I: {
+ GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_value.operator ::Vector4i());
+ mono_field_set_value(p_object, mono_field, &from);
+ } break;
case Variant::TRANSFORM2D: {
GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D());
mono_field_set_value(p_object, mono_field, &from);
@@ -352,6 +378,10 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D());
mono_field_set_value(p_object, mono_field, &from);
} break;
+ case Variant::PROJECTION: {
+ GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_value.operator ::Projection());
+ mono_field_set_value(p_object, mono_field, &from);
+ } break;
case Variant::COLOR: {
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color());
mono_field_set_value(p_object, mono_field, &from);
diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h
index 87ef245f3f..1d30f7a369 100644
--- a/modules/mono/mono_gd/gd_mono_field.h
+++ b/modules/mono/mono_gd/gd_mono_field.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GDMONOFIELD_H
-#define GDMONOFIELD_H
+#ifndef GD_MONO_FIELD_H
+#define GD_MONO_FIELD_H
#include "gd_mono.h"
#include "gd_mono_header.h"
@@ -75,4 +75,4 @@ public:
~GDMonoField();
};
-#endif // GDMONOFIELD_H
+#endif // GD_MONO_FIELD_H
diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h
index 9fc35f8e31..93ba6a410e 100644
--- a/modules/mono/mono_gd/gd_mono_log.h
+++ b/modules/mono/mono_gd/gd_mono_log.h
@@ -35,7 +35,7 @@
#include "core/typedefs.h"
-#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED)
+#if !defined(JAVASCRIPT_ENABLED) && !defined(IOS_ENABLED)
// We have custom mono log callbacks for WASM and iOS
#define GD_MONO_LOG_ENABLED
#endif
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index 957abca37b..a860442764 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -99,6 +99,13 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_
if (vtclass == CACHED_CLASS(Vector3i)) {
return Variant::VECTOR3I;
}
+ if (vtclass == CACHED_CLASS(Vector4)) {
+ return Variant::VECTOR4;
+ }
+
+ if (vtclass == CACHED_CLASS(Vector4i)) {
+ return Variant::VECTOR4I;
+ }
if (vtclass == CACHED_CLASS(Basis)) {
return Variant::BASIS;
@@ -111,7 +118,9 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_
if (vtclass == CACHED_CLASS(Transform3D)) {
return Variant::TRANSFORM3D;
}
-
+ if (vtclass == CACHED_CLASS(Projection)) {
+ return Variant::PROJECTION;
+ }
if (vtclass == CACHED_CLASS(AABB)) {
return Variant::AABB;
}
@@ -539,6 +548,14 @@ MonoObject *variant_to_mono_object(const Variant &p_var) {
GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_var.operator ::Transform2D());
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform2D), &from);
}
+ case Variant::VECTOR4: {
+ GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_var.operator ::Vector4());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector4), &from);
+ }
+ case Variant::VECTOR4I: {
+ GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_var.operator ::Vector4i());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector4i), &from);
+ }
case Variant::PLANE: {
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_var.operator ::Plane());
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from);
@@ -559,6 +576,10 @@ MonoObject *variant_to_mono_object(const Variant &p_var) {
GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_var.operator ::Transform3D());
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform3D), &from);
}
+ case Variant::PROJECTION: {
+ GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_var.operator ::Projection());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Projection), &from);
+ }
case Variant::COLOR: {
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var.operator ::Color());
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Color), &from);
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 778e52b6cb..51f11ab18a 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GDMONOMARSHAL_H
-#define GDMONOMARSHAL_H
+#ifndef GD_MONO_MARSHAL_H
+#define GD_MONO_MARSHAL_H
#include "core/variant/variant.h"
@@ -256,6 +256,18 @@ enum {
offsetof(Vector3, y) == (sizeof(real_t) * 1) &&
offsetof(Vector3, z) == (sizeof(real_t) * 2)),
+ MATCHES_Vector4 = (MATCHES_real_t && (sizeof(Vector4) == (sizeof(real_t) * 4)) &&
+ offsetof(Vector4, x) == (sizeof(real_t) * 0) &&
+ offsetof(Vector4, y) == (sizeof(real_t) * 1) &&
+ offsetof(Vector4, z) == (sizeof(real_t) * 2) &&
+ offsetof(Vector4, w) == (sizeof(real_t) * 3)),
+
+ MATCHES_Vector4i = (MATCHES_int && (sizeof(Vector4i) == (sizeof(int32_t) * 4)) &&
+ offsetof(Vector4i, x) == (sizeof(int32_t) * 0) &&
+ offsetof(Vector4i, y) == (sizeof(int32_t) * 1) &&
+ offsetof(Vector4i, z) == (sizeof(int32_t) * 2) &&
+ offsetof(Vector4i, w) == (sizeof(int32_t) * 3)),
+
MATCHES_Vector3i = (MATCHES_int && (sizeof(Vector3i) == (sizeof(int32_t) * 3)) &&
offsetof(Vector3i, x) == (sizeof(int32_t) * 0) &&
offsetof(Vector3i, y) == (sizeof(int32_t) * 1) &&
@@ -273,6 +285,8 @@ enum {
offsetof(Transform3D, basis) == 0 &&
offsetof(Transform3D, origin) == sizeof(Basis)),
+ MATCHES_Projection = (MATCHES_Vector4 && (sizeof(Projection) == (sizeof(Vector4) * 4))),
+
MATCHES_AABB = (MATCHES_Vector3 && (sizeof(AABB) == (sizeof(Vector3) * 2)) &&
offsetof(AABB, position) == (sizeof(Vector3) * 0) &&
offsetof(AABB, size) == (sizeof(Vector3) * 1)),
@@ -291,9 +305,9 @@ enum {
// In the future we may force this if we want to ref return these structs
#ifdef GD_MONO_FORCE_INTEROP_STRUCT_COPY
/* clang-format off */
-static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 &&
- MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_AABB && MATCHES_Color &&
- MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i);
+static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 && MATCHES_Vector4 &&
+ MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_Projection && MATCHES_AABB && MATCHES_Color &&
+ MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i && MATCHES_Vector4i);
/* clang-format on */
#endif
} // namespace InteropLayout
@@ -401,6 +415,32 @@ struct M_Vector3i {
}
};
+struct M_Vector4 {
+ real_t x, y, z, w;
+
+ static _FORCE_INLINE_ Vector4 convert_to(const M_Vector4 &p_from) {
+ return Vector4(p_from.x, p_from.y, p_from.z, p_from.w);
+ }
+
+ static _FORCE_INLINE_ M_Vector4 convert_from(const Vector4 &p_from) {
+ M_Vector4 ret = { p_from.x, p_from.y, p_from.z, p_from.w };
+ return ret;
+ }
+};
+
+struct M_Vector4i {
+ int32_t x, y, z, w;
+
+ static _FORCE_INLINE_ Vector4i convert_to(const M_Vector4i &p_from) {
+ return Vector4i(p_from.x, p_from.y, p_from.z, p_from.w);
+ }
+
+ static _FORCE_INLINE_ M_Vector4i convert_from(const Vector4i &p_from) {
+ M_Vector4i ret = { p_from.x, p_from.y, p_from.z, p_from.w };
+ return ret;
+ }
+};
+
struct M_Basis {
M_Vector3 elements[3];
@@ -447,6 +487,22 @@ struct M_Transform3D {
}
};
+struct M_Projection {
+ M_Vector4 vec1;
+ M_Vector4 vec2;
+ M_Vector4 vec3;
+ M_Vector4 vec4;
+
+ static _FORCE_INLINE_ Projection convert_to(const M_Projection &p_from) {
+ return Projection(M_Vector4::convert_to(p_from.vec1), M_Vector4::convert_to(p_from.vec2), M_Vector4::convert_to(p_from.vec3), M_Vector4::convert_to(p_from.vec4));
+ }
+
+ static _FORCE_INLINE_ M_Projection convert_from(const Projection &p_from) {
+ M_Projection ret = { M_Vector4::convert_from(p_from.matrix[0]), M_Vector4::convert_from(p_from.matrix[1]), M_Vector4::convert_from(p_from.matrix[2]), M_Vector4::convert_from(p_from.matrix[3]) };
+ return ret;
+ }
+};
+
struct M_AABB {
M_Vector3 position;
M_Vector3 size;
@@ -533,8 +589,11 @@ DECL_TYPE_MARSHAL_TEMPLATES(Transform2D)
DECL_TYPE_MARSHAL_TEMPLATES(Vector3)
DECL_TYPE_MARSHAL_TEMPLATES(Vector3i)
DECL_TYPE_MARSHAL_TEMPLATES(Basis)
+DECL_TYPE_MARSHAL_TEMPLATES(Vector4)
+DECL_TYPE_MARSHAL_TEMPLATES(Vector4i)
DECL_TYPE_MARSHAL_TEMPLATES(Quaternion)
DECL_TYPE_MARSHAL_TEMPLATES(Transform3D)
+DECL_TYPE_MARSHAL_TEMPLATES(Projection)
DECL_TYPE_MARSHAL_TEMPLATES(AABB)
DECL_TYPE_MARSHAL_TEMPLATES(Color)
DECL_TYPE_MARSHAL_TEMPLATES(Plane)
@@ -543,4 +602,4 @@ DECL_TYPE_MARSHAL_TEMPLATES(Plane)
#define MARSHALLED_OUT(m_type, m_from) (GDMonoMarshal::marshalled_out_##m_type(m_from))
} // namespace GDMonoMarshal
-#endif // GDMONOMARSHAL_H
+#endif // GD_MONO_MARSHAL_H
diff --git a/modules/mono/mono_gd/gd_mono_method_thunk.h b/modules/mono/mono_gd/gd_mono_method_thunk.h
index bb163b89bc..0180dee3ea 100644
--- a/modules/mono/mono_gd/gd_mono_method_thunk.h
+++ b/modules/mono/mono_gd/gd_mono_method_thunk.h
@@ -39,7 +39,7 @@
#include "gd_mono_method.h"
#include "gd_mono_utils.h"
-#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED)
+#if !defined(JAVASCRIPT_ENABLED) && !defined(IOS_ENABLED)
#define HAVE_METHOD_THUNKS
#endif
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 246a1cd31e..300cacfa4b 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GD_MONOUTILS_H
-#define GD_MONOUTILS_H
+#ifndef GD_MONO_UTILS_H
+#define GD_MONO_UTILS_H
#include <mono/metadata/threads.h>
@@ -202,4 +202,4 @@ void add_internal_call(const char *p_name, R (*p_func)(P...)) {
#define GD_MONO_ASSERT_THREAD_ATTACHED ((void)0)
#endif
-#endif // GD_MONOUTILS_H
+#endif // GD_MONO_UTILS_H
diff --git a/modules/mono/mono_gd/support/ios_support.h b/modules/mono/mono_gd/support/ios_support.h
index 2f444d5089..03e86df698 100644
--- a/modules/mono/mono_gd/support/ios_support.h
+++ b/modules/mono/mono_gd/support/ios_support.h
@@ -31,7 +31,7 @@
#ifndef IOS_SUPPORT_H
#define IOS_SUPPORT_H
-#if defined(IPHONE_ENABLED)
+#if defined(IOS_ENABLED)
#include "core/string/ustring.h"
@@ -45,6 +45,6 @@ void cleanup();
} // namespace ios
} // namespace gdmono
-#endif // IPHONE_ENABLED
+#endif // IOS_ENABLED
#endif // IOS_SUPPORT_H
diff --git a/modules/mono/mono_gd/support/ios_support.mm b/modules/mono/mono_gd/support/ios_support.mm
index df97dfba49..7c941b9d1e 100644
--- a/modules/mono/mono_gd/support/ios_support.mm
+++ b/modules/mono/mono_gd/support/ios_support.mm
@@ -30,7 +30,7 @@
#include "ios_support.h"
-#if defined(IPHONE_ENABLED)
+#if defined(IOS_ENABLED)
#import <Foundation/Foundation.h>
#include <os/log.h>
@@ -147,4 +147,4 @@ GD_PINVOKE_EXPORT void xamarin_start_wwan(const char *p_uri) {
os_log_error(OS_LOG_DEFAULT, "Not implemented: 'xamarin_start_wwan'");
}
-#endif // IPHONE_ENABLED
+#endif // IOS_ENABLED
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
index 618e1b58e0..437c4ca54a 100644
--- a/modules/mono/signal_awaiter_utils.cpp
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -44,7 +44,7 @@ Error gd_mono_connect_signal_awaiter(Object *p_source, const StringName &p_signa
SignalAwaiterCallable *awaiter_callable = memnew(SignalAwaiterCallable(p_target, p_awaiter, p_signal));
Callable callable = Callable(awaiter_callable);
- return p_source->connect(p_signal, callable, Vector<Variant>(), Object::CONNECT_ONESHOT);
+ return p_source->connect(p_signal, callable, Object::CONNECT_ONESHOT);
}
bool SignalAwaiterCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) {
diff --git a/modules/mono/utils/osx_utils.cpp b/modules/mono/utils/macos_utils.cpp
index abb59420eb..cd4f7a827e 100644
--- a/modules/mono/utils/osx_utils.cpp
+++ b/modules/mono/utils/macos_utils.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* osx_utils.cpp */
+/* macos_utils.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,16 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "osx_utils.h"
+#include "macos_utils.h"
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
#include "core/string/print_string.h"
#import <CoreFoundation/CoreFoundation.h>
#import <CoreServices/CoreServices.h>
-bool osx_is_app_bundle_installed(const String &p_bundle_id) {
+bool macos_is_app_bundle_installed(const String &p_bundle_id) {
CFStringRef bundle_id = CFStringCreateWithCString(nullptr, p_bundle_id.utf8(), kCFStringEncodingUTF8);
CFArrayRef result = LSCopyApplicationURLsForBundleIdentifier(bundle_id, nullptr);
CFRelease(bundle_id);
diff --git a/modules/mono/utils/osx_utils.h b/modules/mono/utils/macos_utils.h
index 2f6c6dad51..ca4957f5a7 100644
--- a/modules/mono/utils/osx_utils.h
+++ b/modules/mono/utils/macos_utils.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* osx_utils.h */
+/* macos_utils.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -30,13 +30,13 @@
#include "core/string/ustring.h"
-#ifndef OSX_UTILS_H
-#define OSX_UTILS_H
+#ifndef MONO_MACOS_UTILS_H
+#define MONO_MACOS_UTILS_H
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
-bool osx_is_app_bundle_installed(const String &p_bundle_id);
+bool macos_is_app_bundle_installed(const String &p_bundle_id);
#endif
-#endif // OSX_UTILS_H
+#endif // MONO_MACOS_UTILS_H
diff --git a/modules/mono/utils/macros.h b/modules/mono/utils/macros.h
index 2ca1a4cbf1..b7bd9a2495 100644
--- a/modules/mono/utils/macros.h
+++ b/modules/mono/utils/macros.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef UTIL_MACROS_H
-#define UTIL_MACROS_H
+#ifndef MONO_MACROS_H
+#define MONO_MACROS_H
#define _GD_VARNAME_CONCAT_B_(m_ignore, m_name) m_name
#define _GD_VARNAME_CONCAT_A_(m_a, m_b, m_c) _GD_VARNAME_CONCAT_B_(hello there, m_a##m_b##m_c)
@@ -69,4 +69,4 @@ public:
#define SCOPE_EXIT \
auto GD_UNIQUE_NAME(gd_scope_exit) = gdmono::ScopeExitAux() + [=]() -> void
-#endif // UTIL_MACROS_H
+#endif // MONO_MACROS_H
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/path_utils.h b/modules/mono/utils/path_utils.h
index a8cd8daf04..9a2c757361 100644
--- a/modules/mono/utils/path_utils.h
+++ b/modules/mono/utils/path_utils.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PATH_UTILS_H
-#define PATH_UTILS_H
+#ifndef MONO_PATH_UTILS_H
+#define MONO_PATH_UTILS_H
#include "core/string/string_builder.h"
#include "core/string/ustring.h"
@@ -58,4 +58,4 @@ String realpath(const String &p_path);
String relative_to(const String &p_path, const String &p_relative_to);
} // namespace path
-#endif // PATH_UTILS_H
+#endif // MONO_PATH_UTILS_H
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/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h
index d79888716a..fa4c5e89f4 100644
--- a/modules/mono/utils/string_utils.h
+++ b/modules/mono/utils/string_utils.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef STRING_FORMAT_H
-#define STRING_FORMAT_H
+#ifndef MONO_STRING_UTILS_H
+#define MONO_STRING_UTILS_H
#include "core/string/ustring.h"
#include "core/variant/variant.h"
@@ -59,4 +59,4 @@ String str_format(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE
char *str_format_new(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_1_2;
char *str_format_new(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE_1_0;
-#endif // STRING_FORMAT_H
+#endif // MONO_STRING_UTILS_H
diff --git a/modules/msdfgen/SCsub b/modules/msdfgen/SCsub
index 227369f4bd..0c269bc7f4 100644
--- a/modules/msdfgen/SCsub
+++ b/modules/msdfgen/SCsub
@@ -36,7 +36,7 @@ if env["builtin_msdfgen"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env_msdfgen.Append(CPPPATH=["#thirdparty/freetype/include", "#thirdparty/msdfgen", "#thirdparty/nanosvg"])
+ env_msdfgen.Prepend(CPPPATH=["#thirdparty/freetype/include", "#thirdparty/msdfgen", "#thirdparty/nanosvg"])
lib = env_msdfgen.add_library("msdfgen_builtin", thirdparty_sources)
thirdparty_obj += lib
diff --git a/modules/msdfgen/config.py b/modules/msdfgen/config.py
index 653e466a74..631894400d 100644
--- a/modules/msdfgen/config.py
+++ b/modules/msdfgen/config.py
@@ -1,5 +1,6 @@
def can_build(env, platform):
- return env.module_check_dependencies("msdfgen", ["freetype"])
+ env.module_add_dependencies("msdfgen", ["freetype"])
+ return True
def configure(env):
diff --git a/modules/multiplayer/SCsub b/modules/multiplayer/SCsub
new file mode 100644
index 0000000000..ff33655537
--- /dev/null
+++ b/modules/multiplayer/SCsub
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+Import("env")
+Import("env_modules")
+
+env_mp = env_modules.Clone()
+
+module_obj = []
+env_mp.add_source_files(module_obj, "*.cpp")
+
+if env["tools"]:
+ env_mp.add_source_files(module_obj, "editor/*.cpp")
+
+env.modules_sources += module_obj
diff --git a/modules/multiplayer/config.py b/modules/multiplayer/config.py
new file mode 100644
index 0000000000..414bf0afcf
--- /dev/null
+++ b/modules/multiplayer/config.py
@@ -0,0 +1,19 @@
+def can_build(env, platform):
+ return True
+
+
+def configure(env):
+ pass
+
+
+def get_doc_classes():
+ return [
+ "SceneReplicationConfig",
+ "SceneMultiplayer",
+ "MultiplayerSpawner",
+ "MultiplayerSynchronizer",
+ ]
+
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/modules/multiplayer/doc_classes/MultiplayerSpawner.xml b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml
new file mode 100644
index 0000000000..881796ed26
--- /dev/null
+++ b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="MultiplayerSpawner" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+ <brief_description>
+ Automatically replicates spawnable nodes from the authority to other multiplayer peers.
+ </brief_description>
+ <description>
+ Spawnable scenes can be configured in the editor or through code (see [method add_spawnable_scene]).
+ Also supports custom node spawns through [method spawn], calling [method _spawn_custom] on all peers.
+
+ Internally, [MultiplayerSpawner] uses [method MultiplayerAPI.object_configuration_add] to notify spawns passing the spawned node as the [code]object[/code] and itself as the [code]configuration[/code], and [method MultiplayerAPI.object_configuration_remove] to notify despawns in a similar way.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="_spawn_custom" qualifiers="virtual">
+ <return type="Node" />
+ <argument index="0" name="data" type="Variant" />
+ <description>
+ Method called on all peers when a custom spawn was requested by the authority using [method spawn]. Should return a [Node] that is not in the scene tree.
+
+ [b]Note:[/b] Spawned nodes should [b]not[/b] be added to the scene with `add_child`. This is done automatically.
+ </description>
+ </method>
+ <method name="add_spawnable_scene">
+ <return type="void" />
+ <argument index="0" name="path" type="String" />
+ <description>
+ Adds a scene path to spawnable scenes, making it automatically replicated from the multiplayer authority to other peers when added as children of the node pointed by [member spawn_path].
+ </description>
+ </method>
+ <method name="clear_spawnable_scenes">
+ <return type="void" />
+ <description>
+ Clears all spawnable scenes. Does not despawn existing instances on remote peers.
+ </description>
+ </method>
+ <method name="get_spawnable_scene" qualifiers="const">
+ <return type="String" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ Returns the spawnable scene path by index.
+ </description>
+ </method>
+ <method name="get_spawnable_scene_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the count of spawnable scene paths.
+ </description>
+ </method>
+ <method name="spawn">
+ <return type="Node" />
+ <argument index="0" name="data" type="Variant" default="null" />
+ <description>
+ Requests a custom spawn, with [code]data[/code] passed to [method _spawn_custom] on all peers. Returns the locally spawned node instance already inside the scene tree, and added as a child of the node pointed by [member spawn_path].
+
+ [b]Note:[/b] Spawnable scenes are spawned automatically. [method spawn] is only needed for custom spawns.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="spawn_limit" type="int" setter="set_spawn_limit" getter="get_spawn_limit" default="0">
+ Maximum nodes that is allowed to be spawned by this spawner. Includes both spawnable scenes and custom spawns.
+
+ When set to [code]0[/code] (the default), there is no limit.
+ </member>
+ <member name="spawn_path" type="NodePath" setter="set_spawn_path" getter="get_spawn_path" default="NodePath(&quot;&quot;)">
+ Path to the spawn root. Spawnable scenes that are added as direct children are replicated to other peers.
+ </member>
+ </members>
+ <signals>
+ <signal name="despawned">
+ <argument index="0" name="node" type="Node" />
+ <description>
+ Emitted when a spawnable scene or custom spawn was despawned by the multiplayer authority. Only called on puppets.
+ </description>
+ </signal>
+ <signal name="spawned">
+ <argument index="0" name="node" type="Node" />
+ <description>
+ Emitted when a spawnable scene or custom spawn was spawned by the multiplayer authority. Only called on puppets.
+ </description>
+ </signal>
+ </signals>
+</class>
diff --git a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
new file mode 100644
index 0000000000..a2ea64061c
--- /dev/null
+++ b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="MultiplayerSynchronizer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+ <brief_description>
+ Synchronizes properties from the multiplayer authority to the remote peers.
+ </brief_description>
+ <description>
+ By default, [MultiplayerSynchronizer] synchronizes configured properties to all peers.
+ Visiblity can be handled directly with [method set_visibility_for] or as-needed with [method add_visibility_filter] and [method update_visibility].
+
+ [MultiplayerSpawner]s will handle nodes according to visibility of synchronizers as long as the node at [member root_path] was spawned by one.
+
+ Internally, [MultiplayerSynchronizer] uses [method MultiplayerAPI.object_configuration_add] to notify synchronization start passing the [Node] at [member root_path] as the [code]object[/code] and itself as the [code]configuration[/code], and uses [method MultiplayerAPI.object_configuration_remove] to notify synchronization end in a similar way.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_visibility_filter">
+ <return type="void" />
+ <argument index="0" name="filter" type="Callable" />
+ <description>
+ Adds a peer visibility filter for this synchronizer.
+
+ [code]filter[/code] should take a peer id [int] and return a [bool].
+ </description>
+ </method>
+ <method name="get_visibility_for" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="peer" type="int" />
+ <description>
+ Queries the current visibility for peer [code]peer[/code].
+ </description>
+ </method>
+ <method name="remove_visibility_filter">
+ <return type="void" />
+ <argument index="0" name="filter" type="Callable" />
+ <description>
+ Removes a peer visiblity filter from this synchronizer.
+ </description>
+ </method>
+ <method name="set_visibility_for">
+ <return type="void" />
+ <argument index="0" name="peer" type="int" />
+ <argument index="1" name="visible" type="bool" />
+ <description>
+ Sets the visibility of [code]peer[/code] to [code]visible[/code]. If [code]peer[/code] is [code]0[/code], the value of [member public_visibility] will be updated instead.
+ </description>
+ </method>
+ <method name="update_visibility">
+ <return type="void" />
+ <argument index="0" name="for_peer" type="int" default="0" />
+ <description>
+ Updates the visibility of [code]peer[/code] according to visibility filters. If [code]peer[/code] is [code]0[/code] (the default), all peers' visibilties are updated.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="public_visibility" type="bool" setter="set_visibility_public" getter="is_visibility_public" default="true">
+ Whether synchronization should be visible to all peers by default. See [method set_visibility_for] and [method add_visibility_filter] for ways of configuring fine-grained visibility options.
+ </member>
+ <member name="replication_config" type="SceneReplicationConfig" setter="set_replication_config" getter="get_replication_config">
+ Resource containing which properties to synchronize.
+ </member>
+ <member name="replication_interval" type="float" setter="set_replication_interval" getter="get_replication_interval" default="0.0">
+ Time interval between synchronizes. When set to [code]0.0[/code] (the default), synchronizes happen every network process frame.
+ </member>
+ <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath(&quot;..&quot;)">
+ Node path that replicated properties are relative to.
+ If [member root_path] was spawned by a [MultiplayerSpawner], the node will be also be spawned and despawned based on this synchronizer visibility options.
+ </member>
+ <member name="visibility_update_mode" type="int" setter="set_visibility_update_mode" getter="get_visibility_update_mode" enum="MultiplayerSynchronizer.VisibilityUpdateMode" default="0">
+ Specifies when visibility filters are updated (see [enum VisibilityUpdateMode] for options).
+ </member>
+ </members>
+ <signals>
+ <signal name="visibility_changed">
+ <argument index="0" name="for_peer" type="int" />
+ <description>
+ Emitted when visibility of [code]for_peer[/code] is updated. See [method update_visibility].
+ </description>
+ </signal>
+ </signals>
+ <constants>
+ <constant name="VISIBILITY_PROCESS_IDLE" value="0" enum="VisibilityUpdateMode">
+ Visibility filters are updated every idle process frame.
+ </constant>
+ <constant name="VISIBILITY_PROCESS_PHYSICS" value="1" enum="VisibilityUpdateMode">
+ Visibility filters are updated every physics process frame.
+ </constant>
+ <constant name="VISIBILITY_PROCESS_NONE" value="2" enum="VisibilityUpdateMode">
+ Visibility filters are not updated automatically, and must be updated manually by calling [method update_visibility].
+ </constant>
+ </constants>
+</class>
diff --git a/modules/multiplayer/doc_classes/SceneMultiplayer.xml b/modules/multiplayer/doc_classes/SceneMultiplayer.xml
new file mode 100644
index 0000000000..0c3ed2d784
--- /dev/null
+++ b/modules/multiplayer/doc_classes/SceneMultiplayer.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SceneMultiplayer" inherits="MultiplayerAPI" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+ <brief_description>
+ High-level multiplayer API implementation.
+ </brief_description>
+ <description>
+ This class is the default implementation of [MultiplayerAPI], used to provide multiplayer functionalities in Godot Engine.
+ This implementation supports RPCs via [method Node.rpc] and [method Node.rpc_id] and requires [method MultiplayerAPI.rpc] to be passed a [Node] (it will fail for other object types).
+ This implementation additionally provide [SceneTree] replication via the [MultiplayerSpawner] and [MultiplayerSynchronizer] nodes, and the [SceneReplicationConfig] resource.
+ [b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice.
+ [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="clear">
+ <return type="void" />
+ <description>
+ Clears the current SceneMultiplayer network state (you shouldn't call this unless you know what you are doing).
+ </description>
+ </method>
+ <method name="send_bytes">
+ <return type="int" enum="Error" />
+ <argument index="0" name="bytes" type="PackedByteArray" />
+ <argument index="1" name="id" type="int" default="0" />
+ <argument index="2" name="mode" type="int" enum="MultiplayerPeer.TransferMode" default="2" />
+ <argument index="3" name="channel" type="int" default="0" />
+ <description>
+ Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method MultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="allow_object_decoding" type="bool" setter="set_allow_object_decoding" getter="is_object_decoding_allowed" default="false">
+ If [code]true[/code], the MultiplayerAPI will allow encoding and decoding of object during RPCs.
+ [b]Warning:[/b] Deserialized objects can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threat such as remote code execution.
+ </member>
+ <member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" default="false">
+ If [code]true[/code], the MultiplayerAPI's [member MultiplayerAPI.multiplayer_peer] refuses new incoming connections.
+ </member>
+ <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath(&quot;&quot;)">
+ The root path to use for RPCs and replication. Instead of an absolute path, a relative path will be used to find the node upon which the RPC should be executed.
+ This effectively allows to have different branches of the scene tree to be managed by different MultiplayerAPI, allowing for example to run both client and server in the same scene.
+ </member>
+ </members>
+ <signals>
+ <signal name="peer_packet">
+ <argument index="0" name="id" type="int" />
+ <argument index="1" name="packet" type="PackedByteArray" />
+ <description>
+ Emitted when this MultiplayerAPI's [member MultiplayerAPI.multiplayer_peer] receives a [code]packet[/code] with custom data (see [method send_bytes]). ID is the peer ID of the peer that sent the packet.
+ </description>
+ </signal>
+ </signals>
+</class>
diff --git a/doc/classes/SceneReplicationConfig.xml b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml
index 62c108a477..fc91592c7a 100644
--- a/doc/classes/SceneReplicationConfig.xml
+++ b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="SceneReplicationConfig" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="SceneReplicationConfig" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
+ Configuration for properties to synchronize with a [MultiplayerSynchronizer].
</brief_description>
<description>
</description>
@@ -12,35 +13,41 @@
<argument index="0" name="path" type="NodePath" />
<argument index="1" name="index" type="int" default="-1" />
<description>
+ Adds the property identified by the given [code]path[/code] to the list of the properties being synchronized, optionally passing an [code]index[/code].
</description>
</method>
<method name="get_properties" qualifiers="const">
<return type="NodePath[]" />
<description>
+ Returns a list of synchronized property [NodePath]s.
</description>
</method>
<method name="has_property" qualifiers="const">
<return type="bool" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Returns whether the given [code]path[/code] is configured for synchronization.
</description>
</method>
<method name="property_get_index" qualifiers="const">
<return type="int" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Finds the index of the given [code]path[/code].
</description>
</method>
<method name="property_get_spawn">
<return type="bool" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Returns whether the property identified by the given [code]path[/code] is configured to be synchronized on spawn.
</description>
</method>
<method name="property_get_sync">
<return type="bool" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Returns whether the property identified by the given [code]path[/code] is configured to be synchronized on process.
</description>
</method>
<method name="property_set_spawn">
@@ -48,6 +55,7 @@
<argument index="0" name="path" type="NodePath" />
<argument index="1" name="enabled" type="bool" />
<description>
+ Sets whether the property identified by the given [code]path[/code] is configured to be synchronized on spawn.
</description>
</method>
<method name="property_set_sync">
@@ -55,12 +63,14 @@
<argument index="0" name="path" type="NodePath" />
<argument index="1" name="enabled" type="bool" />
<description>
+ Sets whether the property identified by the given [code]path[/code] is configured to be synchronized on process.
</description>
</method>
<method name="remove_property">
<return type="void" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Removes the property identified by the given [code]path[/code] from the configuration.
</description>
</method>
</methods>
diff --git a/editor/plugins/replication_editor_plugin.cpp b/modules/multiplayer/editor/replication_editor_plugin.cpp
index 72fe3c5f20..50f1434ad8 100644
--- a/editor/plugins/replication_editor_plugin.cpp
+++ b/modules/multiplayer/editor/replication_editor_plugin.cpp
@@ -32,10 +32,13 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/inspector_dock.h"
+#include "editor/scene_tree_editor.h"
+#include "modules/multiplayer/multiplayer_synchronizer.h"
#include "scene/gui/dialogs.h"
+#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
-#include "scene/multiplayer/multiplayer_synchronizer.h"
void ReplicationEditor::_pick_node_filter_text_changed(const String &p_newtext) {
TreeItem *root_item = pick_node->get_scene_tree()->get_scene_tree()->get_root();
@@ -166,12 +169,12 @@ ReplicationEditor::ReplicationEditor() {
set_custom_minimum_size(Size2(0, 200) * EDSCALE);
delete_dialog = memnew(ConfirmationDialog);
- delete_dialog->connect("cancelled", callable_mp(this, &ReplicationEditor::_dialog_closed), varray(false));
- delete_dialog->connect("confirmed", callable_mp(this, &ReplicationEditor::_dialog_closed), varray(true));
+ delete_dialog->connect("cancelled", callable_mp(this, &ReplicationEditor::_dialog_closed).bind(false));
+ delete_dialog->connect("confirmed", callable_mp(this, &ReplicationEditor::_dialog_closed).bind(true));
add_child(delete_dialog);
error_dialog = memnew(AcceptDialog);
- error_dialog->get_ok_button()->set_text(TTR("Close"));
+ error_dialog->set_ok_button_text(TTR("Close"));
error_dialog->set_title(TTR("Error!"));
add_child(error_dialog);
@@ -242,7 +245,7 @@ ReplicationEditor::ReplicationEditor() {
drop_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
drop_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
tree->add_child(drop_label);
- drop_label->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ drop_label->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
tree->set_drag_forwarding(this);
}
@@ -252,8 +255,6 @@ void ReplicationEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_checked", "property", "column", "checked"), &ReplicationEditor::_update_checked);
ClassDB::bind_method("_can_drop_data_fw", &ReplicationEditor::_can_drop_data_fw);
ClassDB::bind_method("_drop_data_fw", &ReplicationEditor::_drop_data_fw);
-
- ADD_SIGNAL(MethodInfo("keying_changed"));
}
bool ReplicationEditor::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
@@ -319,10 +320,6 @@ void ReplicationEditor::_notification(int p_what) {
add_pick_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
pin->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")));
} break;
-
- case NOTIFICATION_VISIBILITY_CHANGED: {
- update_keying();
- } break;
}
}
@@ -338,28 +335,15 @@ void ReplicationEditor::_add_pressed() {
return;
}
String np_text = np_line_edit->get_text();
- if (np_text.find(":") == -1) {
- np_text = ":" + np_text;
- }
- NodePath prop = NodePath(np_text);
- if (prop.is_empty()) {
- return;
- }
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
- undo_redo->create_action(TTR("Add property"));
- config = current->get_replication_config();
- if (config.is_null()) {
- config.instantiate();
- current->set_replication_config(config);
- undo_redo->add_do_method(current, "set_replication_config", config);
- undo_redo->add_undo_method(current, "set_replication_config", Ref<SceneReplicationConfig>());
- _update_config();
+ int idx = np_text.find(":");
+ if (idx == -1) {
+ np_text = ".:" + np_text;
+ } else if (idx == 0) {
+ np_text = "." + np_text;
}
- undo_redo->add_do_method(config.ptr(), "add_property", prop);
- undo_redo->add_undo_method(config.ptr(), "remove_property", prop);
- undo_redo->add_do_method(this, "_update_config");
- undo_redo->add_undo_method(this, "_update_config");
- undo_redo->commit_action();
+ NodePath path = NodePath(np_text);
+
+ _add_sync_property(path);
}
void ReplicationEditor::_tree_item_edited() {
@@ -437,32 +421,12 @@ void ReplicationEditor::_update_checked(const NodePath &p_prop, int p_column, bo
}
}
-void ReplicationEditor::update_keying() {
- /// TODO make keying usable.
-#if 0
- bool keying_enabled = false;
- EditorSelectionHistory *editor_history = EditorNode::get_singleton()->get_editor_selection_history();
- if (is_visible_in_tree() && config.is_valid() && editor_history->get_path_size() > 0) {
- Object *obj = ObjectDB::get_instance(editor_history->get_path_object(0));
- keying_enabled = Object::cast_to<Node>(obj) != nullptr;
- }
-
- if (keying_enabled == keying) {
- return;
- }
-
- keying = keying_enabled;
- emit_signal(SNAME("keying_changed"));
-#endif
-}
-
void ReplicationEditor::_update_config() {
deleting = NodePath();
tree->clear();
tree->create_item();
drop_label->set_visible(true);
if (!config.is_valid()) {
- update_keying();
return;
}
TypedArray<NodePath> props = config->get_properties();
@@ -473,7 +437,6 @@ void ReplicationEditor::_update_config() {
const NodePath path = props[i];
_add_property(path, config->property_get_spawn(path), config->property_get_sync(path));
}
- update_keying();
}
void ReplicationEditor::edit(MultiplayerSynchronizer *p_sync) {
@@ -529,43 +492,6 @@ void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn,
item->set_editable(2, true);
}
-void ReplicationEditor::property_keyed(const String &p_property) {
- ERR_FAIL_COND(!current || config.is_null());
- Node *root = current->get_node(current->get_root_path());
- ERR_FAIL_COND(!root);
- EditorSelectionHistory *history = EditorNode::get_singleton()->get_editor_selection_history();
- ERR_FAIL_COND(history->get_path_size() == 0);
- Node *node = Object::cast_to<Node>(ObjectDB::get_instance(history->get_path_object(0)));
- ERR_FAIL_COND(!node);
- if (node->is_class("MultiplayerSynchronizer")) {
- error_dialog->set_text(TTR("Properties of 'MultiplayerSynchronizer' cannot be configured for replication."));
- error_dialog->popup_centered();
- return;
- }
- if (history->get_path_size() > 1 || p_property.get_slice_count(":") > 1) {
- error_dialog->set_text(TTR("Subresources cannot yet be configured for replication."));
- error_dialog->popup_centered();
- return;
- }
-
- String path = root->get_path_to(node);
- for (int i = 1; i < history->get_path_size(); i++) {
- String prop = history->get_path_property(i);
- ERR_FAIL_COND(prop == "");
- path += ":" + prop;
- }
- path += ":" + p_property;
-
- NodePath prop = path;
- UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
- undo_redo->create_action(TTR("Add property"));
- undo_redo->add_do_method(config.ptr(), "add_property", prop);
- undo_redo->add_undo_method(config.ptr(), "remove_property", prop);
- undo_redo->add_do_method(this, "_update_config");
- undo_redo->add_undo_method(this, "_update_config");
- undo_redo->commit_action();
-}
-
/// ReplicationEditorPlugin
ReplicationEditorPlugin::ReplicationEditorPlugin() {
repl_editor = memnew(ReplicationEditor);
@@ -577,26 +503,9 @@ ReplicationEditorPlugin::ReplicationEditorPlugin() {
ReplicationEditorPlugin::~ReplicationEditorPlugin() {
}
-void ReplicationEditorPlugin::_keying_changed() {
- // TODO make lock usable.
- //InspectorDock::get_inspector_singleton()->set_keying(repl_editor->has_keying(), this);
-}
-
-void ReplicationEditorPlugin::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) {
- if (!repl_editor->has_keying()) {
- return;
- }
- repl_editor->property_keyed(p_keyed);
-}
-
void ReplicationEditorPlugin::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- //Node3DEditor::get_singleton()->connect("transform_key_request", callable_mp(this, &AnimationPlayerEditorPlugin::_transform_key_request));
- InspectorDock::get_inspector_singleton()->connect("property_keyed", callable_mp(this, &ReplicationEditorPlugin::_property_keyed));
- repl_editor->connect("keying_changed", callable_mp(this, &ReplicationEditorPlugin::_keying_changed));
- // TODO make lock usable.
- //InspectorDock::get_inspector_singleton()->connect("object_inspected", callable_mp(repl_editor, &ReplicationEditor::update_keying));
get_tree()->connect("node_removed", callable_mp(this, &ReplicationEditorPlugin::_node_removed));
} break;
}
@@ -632,8 +541,6 @@ bool ReplicationEditorPlugin::handles(Object *p_object) const {
void ReplicationEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
- //editor->hide_animation_player_editors();
- //editor->animation_panel_make_visible(true);
button->show();
EditorNode::get_singleton()->make_bottom_panel_item_visible(repl_editor);
} else if (!repl_editor->get_pin()->is_pressed()) {
diff --git a/editor/plugins/replication_editor_plugin.h b/modules/multiplayer/editor/replication_editor_plugin.h
index df3d97f884..e60e49cc25 100644
--- a/editor/plugins/replication_editor_plugin.h
+++ b/modules/multiplayer/editor/replication_editor_plugin.h
@@ -32,15 +32,17 @@
#define REPLICATION_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "scene/resources/scene_replication_config.h"
#include "editor/editor_spin_slider.h"
-#include "editor/property_editor.h"
#include "editor/property_selector.h"
+#include "../scene_replication_config.h"
+
class ConfirmationDialog;
class MultiplayerSynchronizer;
+class SceneTreeDialog;
class Tree;
+class TreeItem;
class ReplicationEditor : public VBoxContainer {
GDCLASS(ReplicationEditor, VBoxContainer);
@@ -59,7 +61,6 @@ private:
Ref<SceneReplicationConfig> config;
NodePath deleting;
Tree *tree = nullptr;
- bool keying = false;
PropertySelector *prop_selector = nullptr;
SceneTreeDialog *pick_node = nullptr;
@@ -96,11 +97,8 @@ protected:
void _notification(int p_what);
public:
- void update_keying();
void edit(MultiplayerSynchronizer *p_object);
- bool has_keying() const { return keying; }
MultiplayerSynchronizer *get_current() const { return current; }
- void property_keyed(const String &p_property);
Button *get_pin() { return pin; }
ReplicationEditor();
@@ -115,8 +113,6 @@ private:
ReplicationEditor *repl_editor = nullptr;
void _node_removed(Node *p_node);
- void _keying_changed();
- void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance);
void _pinned();
diff --git a/scene/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp
index ddd01d0a43..e8f3aecc69 100644
--- a/scene/multiplayer/multiplayer_spawner.cpp
+++ b/modules/multiplayer/multiplayer_spawner.cpp
@@ -31,7 +31,7 @@
#include "multiplayer_spawner.h"
#include "core/io/marshalls.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
@@ -71,7 +71,7 @@ bool MultiplayerSpawner::_get(const StringName &p_name, Variant &r_ret) const {
}
void MultiplayerSpawner::_get_property_list(List<PropertyInfo> *p_list) const {
- p_list->push_back(PropertyInfo(Variant::INT, "_spawnable_scene_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Scenes,scenes/"));
+ p_list->push_back(PropertyInfo(Variant::INT, "_spawnable_scene_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Auto Spawn List,scenes/"));
List<String> exts;
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &exts);
String ext_hint;
@@ -126,7 +126,7 @@ void MultiplayerSpawner::_set_spawnable_scenes(const Vector<String> &p_scenes) {
void MultiplayerSpawner::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_spawnable_scene", "path"), &MultiplayerSpawner::add_spawnable_scene);
ClassDB::bind_method(D_METHOD("get_spawnable_scene_count"), &MultiplayerSpawner::get_spawnable_scene_count);
- ClassDB::bind_method(D_METHOD("get_spawnable_scene", "path"), &MultiplayerSpawner::get_spawnable_scene);
+ ClassDB::bind_method(D_METHOD("get_spawnable_scene", "index"), &MultiplayerSpawner::get_spawnable_scene);
ClassDB::bind_method(D_METHOD("clear_spawnable_scenes"), &MultiplayerSpawner::clear_spawnable_scenes);
ClassDB::bind_method(D_METHOD("_get_spawnable_scenes"), &MultiplayerSpawner::_get_spawnable_scenes);
@@ -144,14 +144,10 @@ void MultiplayerSpawner::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_spawn_limit", "limit"), &MultiplayerSpawner::set_spawn_limit);
ADD_PROPERTY(PropertyInfo(Variant::INT, "spawn_limit", PROPERTY_HINT_RANGE, "0,1024,1,or_greater"), "set_spawn_limit", "get_spawn_limit");
- ClassDB::bind_method(D_METHOD("set_auto_spawning", "enabled"), &MultiplayerSpawner::set_auto_spawning);
- ClassDB::bind_method(D_METHOD("is_auto_spawning"), &MultiplayerSpawner::is_auto_spawning);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_spawn"), "set_auto_spawning", "is_auto_spawning");
-
GDVIRTUAL_BIND(_spawn_custom, "data");
- ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
}
void MultiplayerSpawner::_update_spawn_node() {
@@ -169,7 +165,7 @@ void MultiplayerSpawner::_update_spawn_node() {
Node *node = spawn_path.is_empty() && is_inside_tree() ? nullptr : get_node_or_null(spawn_path);
if (node) {
spawn_node = node->get_instance_id();
- if (auto_spawn) {
+ if (get_spawnable_scene_count() && !GDVIRTUAL_IS_OVERRIDDEN(_spawn_custom)) {
node->connect("child_entered_tree", callable_mp(this, &MultiplayerSpawner::_node_added));
}
} else {
@@ -194,7 +190,7 @@ void MultiplayerSpawner::_notification(int p_what) {
if (node->is_connected(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready))) {
node->disconnect(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready));
}
- get_multiplayer()->despawn(node, this);
+ get_multiplayer()->object_configuration_remove(node, this);
}
tracked_nodes.clear();
} break;
@@ -221,15 +217,6 @@ void MultiplayerSpawner::_node_added(Node *p_node) {
_track(p_node, Variant(), id);
}
-void MultiplayerSpawner::set_auto_spawning(bool p_enabled) {
- auto_spawn = p_enabled;
- _update_spawn_node();
-}
-
-bool MultiplayerSpawner::is_auto_spawning() const {
- return auto_spawn;
-}
-
NodePath MultiplayerSpawner::get_spawn_path() const {
return spawn_path;
}
@@ -243,13 +230,13 @@ void MultiplayerSpawner::_track(Node *p_node, const Variant &p_argument, int p_s
ObjectID oid = p_node->get_instance_id();
if (!tracked_nodes.has(oid)) {
tracked_nodes[oid] = SpawnInfo(p_argument.duplicate(true), p_scene_id);
- p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit), varray(p_node->get_instance_id()), CONNECT_ONESHOT);
- p_node->connect(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready), varray(p_node->get_instance_id()), CONNECT_ONESHOT);
+ p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit).bind(p_node->get_instance_id()), CONNECT_ONESHOT);
+ p_node->connect(SceneStringNames::get_singleton()->ready, callable_mp(this, &MultiplayerSpawner::_node_ready).bind(p_node->get_instance_id()), CONNECT_ONESHOT);
}
}
void MultiplayerSpawner::_node_ready(ObjectID p_id) {
- get_multiplayer()->spawn(ObjectDB::get_instance(p_id), this);
+ get_multiplayer()->object_configuration_add(ObjectDB::get_instance(p_id), this);
}
void MultiplayerSpawner::_node_exit(ObjectID p_id) {
@@ -257,7 +244,7 @@ void MultiplayerSpawner::_node_exit(ObjectID p_id) {
ERR_FAIL_COND(!node);
if (tracked_nodes.has(p_id)) {
tracked_nodes.erase(p_id);
- get_multiplayer()->despawn(node, this);
+ get_multiplayer()->object_configuration_remove(node, this);
}
}
@@ -290,12 +277,11 @@ Node *MultiplayerSpawner::instantiate_scene(int p_id) {
Node *MultiplayerSpawner::instantiate_custom(const Variant &p_data) {
ERR_FAIL_COND_V_MSG(spawn_limit && spawn_limit <= tracked_nodes.size(), nullptr, "Spawn limit reached!");
- Object *obj = nullptr;
Node *node = nullptr;
- if (GDVIRTUAL_CALL(_spawn_custom, p_data, obj)) {
- node = Object::cast_to<Node>(obj);
+ if (GDVIRTUAL_CALL(_spawn_custom, p_data, node)) {
+ return node;
}
- return node;
+ ERR_FAIL_V_MSG(nullptr, "Method '_spawn_custom' is not implemented on this peer.");
}
Node *MultiplayerSpawner::spawn(const Variant &p_data) {
diff --git a/scene/multiplayer/multiplayer_spawner.h b/modules/multiplayer/multiplayer_spawner.h
index e8abe702a0..fc3befc2d4 100644
--- a/scene/multiplayer/multiplayer_spawner.h
+++ b/modules/multiplayer/multiplayer_spawner.h
@@ -36,7 +36,8 @@
#include "core/templates/local_vector.h"
#include "core/variant/typed_array.h"
#include "scene/resources/packed_scene.h"
-#include "scene/resources/scene_replication_config.h"
+
+#include "scene_replication_config.h"
class MultiplayerSpawner : public Node {
GDCLASS(MultiplayerSpawner, Node);
@@ -69,7 +70,6 @@ private:
ObjectID spawn_node;
HashMap<ObjectID, SpawnInfo> tracked_nodes;
- bool auto_spawn = false;
uint32_t spawn_limit = 0;
void _update_spawn_node();
@@ -91,7 +91,9 @@ protected:
void _get_property_list(List<PropertyInfo> *p_list) const;
#endif
public:
- Node *get_spawn_node() const { return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr; }
+ Node *get_spawn_node() const {
+ return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr;
+ }
void add_spawnable_scene(const String &p_path);
int get_spawnable_scene_count() const;
@@ -102,8 +104,6 @@ public:
void set_spawn_path(const NodePath &p_path);
uint32_t get_spawn_limit() const { return spawn_limit; }
void set_spawn_limit(uint32_t p_limit) { spawn_limit = p_limit; }
- bool is_auto_spawning() const;
- void set_auto_spawning(bool p_enabled);
const Variant get_spawn_argument(const ObjectID &p_id) const;
int find_spawnable_scene_index_from_object(const ObjectID &p_id) const;
@@ -112,7 +112,7 @@ public:
Node *instantiate_custom(const Variant &p_data);
Node *instantiate_scene(int p_idx);
- GDVIRTUAL1R(Object *, _spawn_custom, const Variant &);
+ GDVIRTUAL1R(Node *, _spawn_custom, const Variant &);
MultiplayerSpawner() {}
};
diff --git a/scene/multiplayer/multiplayer_synchronizer.cpp b/modules/multiplayer/multiplayer_synchronizer.cpp
index 68f6e54fa8..eee1495c14 100644
--- a/scene/multiplayer/multiplayer_synchronizer.cpp
+++ b/modules/multiplayer/multiplayer_synchronizer.cpp
@@ -31,7 +31,7 @@
#include "multiplayer_synchronizer.h"
#include "core/config/engine.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
Object *MultiplayerSynchronizer::_get_prop_target(Object *p_obj, const NodePath &p_path) {
if (p_path.get_name_count() == 0) {
@@ -43,16 +43,54 @@ Object *MultiplayerSynchronizer::_get_prop_target(Object *p_obj, const NodePath
}
void MultiplayerSynchronizer::_stop() {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr;
if (node) {
- get_multiplayer()->replication_stop(node, this);
+ get_multiplayer()->object_configuration_remove(node, this);
}
}
void MultiplayerSynchronizer::_start() {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr;
if (node) {
- get_multiplayer()->replication_start(node, this);
+ get_multiplayer()->object_configuration_add(node, this);
+ _update_process();
+ }
+}
+
+void MultiplayerSynchronizer::_update_process() {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+ Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr;
+ if (!node) {
+ return;
+ }
+ set_process_internal(false);
+ set_physics_process_internal(false);
+ if (!visibility_filters.size()) {
+ return;
+ }
+ switch (visibility_update_mode) {
+ case VISIBILITY_PROCESS_IDLE:
+ set_process_internal(true);
+ break;
+ case VISIBILITY_PROCESS_PHYSICS:
+ set_physics_process_internal(true);
+ break;
+ case VISIBILITY_PROCESS_NONE:
+ break;
}
}
@@ -85,6 +123,66 @@ Error MultiplayerSynchronizer::set_state(const List<NodePath> &p_properties, Obj
return OK;
}
+bool MultiplayerSynchronizer::is_visibility_public() const {
+ return peer_visibility.has(0);
+}
+
+void MultiplayerSynchronizer::set_visibility_public(bool p_visible) {
+ set_visibility_for(0, p_visible);
+}
+
+bool MultiplayerSynchronizer::is_visible_to(int p_peer) {
+ if (visibility_filters.size()) {
+ Variant arg = p_peer;
+ const Variant *argv[1] = { &arg };
+ for (Callable filter : visibility_filters) {
+ Variant ret;
+ Callable::CallError err;
+ filter.callp(argv, 1, ret, err);
+ ERR_FAIL_COND_V(err.error != Callable::CallError::CALL_OK || ret.get_type() != Variant::BOOL, false);
+ if (!ret.operator bool()) {
+ return false;
+ }
+ }
+ }
+ return peer_visibility.has(0) || peer_visibility.has(p_peer);
+}
+
+void MultiplayerSynchronizer::add_visibility_filter(Callable p_callback) {
+ visibility_filters.insert(p_callback);
+ _update_process();
+}
+
+void MultiplayerSynchronizer::remove_visibility_filter(Callable p_callback) {
+ visibility_filters.erase(p_callback);
+ _update_process();
+}
+
+void MultiplayerSynchronizer::set_visibility_for(int p_peer, bool p_visible) {
+ if (peer_visibility.has(p_peer) == p_visible) {
+ return;
+ }
+ if (p_visible) {
+ peer_visibility.insert(p_peer);
+ } else {
+ peer_visibility.erase(p_peer);
+ }
+ update_visibility(p_peer);
+}
+
+bool MultiplayerSynchronizer::get_visibility_for(int p_peer) const {
+ return peer_visibility.has(p_peer);
+}
+
+void MultiplayerSynchronizer::set_visibility_update_mode(VisibilityUpdateMode p_mode) {
+ visibility_update_mode = p_mode;
+ _update_process();
+}
+
+MultiplayerSynchronizer::VisibilityUpdateMode MultiplayerSynchronizer::get_visibility_update_mode() const {
+ return visibility_update_mode;
+}
+
void MultiplayerSynchronizer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_path", "path"), &MultiplayerSynchronizer::set_root_path);
ClassDB::bind_method(D_METHOD("get_root_path"), &MultiplayerSynchronizer::get_root_path);
@@ -95,9 +193,29 @@ void MultiplayerSynchronizer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_replication_config", "config"), &MultiplayerSynchronizer::set_replication_config);
ClassDB::bind_method(D_METHOD("get_replication_config"), &MultiplayerSynchronizer::get_replication_config);
+ ClassDB::bind_method(D_METHOD("set_visibility_update_mode", "mode"), &MultiplayerSynchronizer::set_visibility_update_mode);
+ ClassDB::bind_method(D_METHOD("get_visibility_update_mode"), &MultiplayerSynchronizer::get_visibility_update_mode);
+ ClassDB::bind_method(D_METHOD("update_visibility", "for_peer"), &MultiplayerSynchronizer::update_visibility, DEFVAL(0));
+
+ ClassDB::bind_method(D_METHOD("set_visibility_public", "visible"), &MultiplayerSynchronizer::set_visibility_public);
+ ClassDB::bind_method(D_METHOD("is_visibility_public"), &MultiplayerSynchronizer::is_visibility_public);
+
+ ClassDB::bind_method(D_METHOD("add_visibility_filter", "filter"), &MultiplayerSynchronizer::add_visibility_filter);
+ ClassDB::bind_method(D_METHOD("remove_visibility_filter", "filter"), &MultiplayerSynchronizer::remove_visibility_filter);
+ ClassDB::bind_method(D_METHOD("set_visibility_for", "peer", "visible"), &MultiplayerSynchronizer::set_visibility_for);
+ ClassDB::bind_method(D_METHOD("get_visibility_for", "peer"), &MultiplayerSynchronizer::get_visibility_for);
+
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "replication_interval", PROPERTY_HINT_RANGE, "0,5,0.001,suffix:s"), "set_replication_interval", "get_replication_interval");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "replication_config", PROPERTY_HINT_RESOURCE_TYPE, "SceneReplicationConfig"), "set_replication_config", "get_replication_config");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "replication_config", PROPERTY_HINT_RESOURCE_TYPE, "SceneReplicationConfig", PROPERTY_USAGE_NO_EDITOR), "set_replication_config", "get_replication_config");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,None"), "set_visibility_update_mode", "get_visibility_update_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "public_visibility"), "set_visibility_public", "is_visibility_public");
+
+ BIND_ENUM_CONSTANT(VISIBILITY_PROCESS_IDLE);
+ BIND_ENUM_CONSTANT(VISIBILITY_PROCESS_PHYSICS);
+ BIND_ENUM_CONSTANT(VISIBILITY_PROCESS_NONE);
+
+ ADD_SIGNAL(MethodInfo("visibility_changed", PropertyInfo(Variant::INT, "for_peer")));
}
void MultiplayerSynchronizer::_notification(int p_what) {
@@ -118,6 +236,11 @@ void MultiplayerSynchronizer::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
_stop();
} break;
+
+ case NOTIFICATION_INTERNAL_PROCESS:
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ update_visibility(0);
+ } break;
}
}
@@ -142,6 +265,18 @@ Ref<SceneReplicationConfig> MultiplayerSynchronizer::get_replication_config() {
return replication_config;
}
+void MultiplayerSynchronizer::update_visibility(int p_for_peer) {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+ Node *node = is_inside_tree() ? get_node_or_null(root_path) : nullptr;
+ if (node && get_multiplayer()->has_multiplayer_peer() && is_multiplayer_authority()) {
+ emit_signal(SNAME("visibility_changed"), p_for_peer);
+ }
+}
+
void MultiplayerSynchronizer::set_root_path(const NodePath &p_path) {
_stop();
root_path = p_path;
@@ -158,7 +293,12 @@ void MultiplayerSynchronizer::set_multiplayer_authority(int p_peer_id, bool p_re
Node::set_multiplayer_authority(p_peer_id, p_recursive);
return;
}
- get_multiplayer()->replication_stop(node, this);
+ get_multiplayer()->object_configuration_remove(node, this);
Node::set_multiplayer_authority(p_peer_id, p_recursive);
- get_multiplayer()->replication_start(node, this);
+ get_multiplayer()->object_configuration_add(node, this);
+}
+
+MultiplayerSynchronizer::MultiplayerSynchronizer() {
+ // Publicly visible by default.
+ peer_visibility.insert(0);
}
diff --git a/scene/multiplayer/multiplayer_synchronizer.h b/modules/multiplayer/multiplayer_synchronizer.h
index f61ef459da..e84d41db86 100644
--- a/scene/multiplayer/multiplayer_synchronizer.h
+++ b/modules/multiplayer/multiplayer_synchronizer.h
@@ -33,19 +33,30 @@
#include "scene/main/node.h"
-#include "scene/resources/scene_replication_config.h"
+#include "scene_replication_config.h"
class MultiplayerSynchronizer : public Node {
GDCLASS(MultiplayerSynchronizer, Node);
+public:
+ enum VisibilityUpdateMode {
+ VISIBILITY_PROCESS_IDLE,
+ VISIBILITY_PROCESS_PHYSICS,
+ VISIBILITY_PROCESS_NONE,
+ };
+
private:
Ref<SceneReplicationConfig> replication_config;
NodePath root_path = NodePath(".."); // Start with parent, like with AnimationPlayer.
uint64_t interval_msec = 0;
+ VisibilityUpdateMode visibility_update_mode = VISIBILITY_PROCESS_IDLE;
+ HashSet<Callable> visibility_filters;
+ HashSet<int> peer_visibility;
static Object *_get_prop_target(Object *p_obj, const NodePath &p_prop);
void _start();
void _stop();
+ void _update_process();
protected:
static void _bind_methods();
@@ -66,7 +77,20 @@ public:
NodePath get_root_path() const;
virtual void set_multiplayer_authority(int p_peer_id, bool p_recursive = true) override;
- MultiplayerSynchronizer() {}
+ bool is_visibility_public() const;
+ void set_visibility_public(bool p_public);
+ bool is_visible_to(int p_peer);
+ void set_visibility_for(int p_peer, bool p_visible);
+ bool get_visibility_for(int p_peer) const;
+ void update_visibility(int p_for_peer);
+ void set_visibility_update_mode(VisibilityUpdateMode p_mode);
+ void add_visibility_filter(Callable p_callback);
+ void remove_visibility_filter(Callable p_callback);
+ VisibilityUpdateMode get_visibility_update_mode() const;
+
+ MultiplayerSynchronizer();
};
+VARIANT_ENUM_CAST(MultiplayerSynchronizer::VisibilityUpdateMode);
+
#endif // MULTIPLAYER_SYNCHRONIZER_H
diff --git a/modules/multiplayer/register_types.cpp b/modules/multiplayer/register_types.cpp
new file mode 100644
index 0000000000..a2c524da80
--- /dev/null
+++ b/modules/multiplayer/register_types.cpp
@@ -0,0 +1,60 @@
+/*************************************************************************/
+/* register_types.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 "register_types.h"
+
+#include "multiplayer_spawner.h"
+#include "multiplayer_synchronizer.h"
+#include "scene_multiplayer.h"
+#include "scene_replication_interface.h"
+#include "scene_rpc_interface.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_plugin.h"
+#include "editor/replication_editor_plugin.h"
+#endif
+
+void initialize_multiplayer_module(ModuleInitializationLevel p_level) {
+ if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
+ GDREGISTER_CLASS(SceneReplicationConfig);
+ GDREGISTER_CLASS(MultiplayerSpawner);
+ GDREGISTER_CLASS(MultiplayerSynchronizer);
+ GDREGISTER_CLASS(SceneMultiplayer);
+ MultiplayerAPI::set_default_interface("SceneMultiplayer");
+ }
+#ifdef TOOLS_ENABLED
+ if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
+ EditorPlugins::add_by_type<ReplicationEditorPlugin>();
+ }
+#endif
+}
+
+void uninitialize_multiplayer_module(ModuleInitializationLevel p_level) {
+}
diff --git a/modules/multiplayer/register_types.h b/modules/multiplayer/register_types.h
new file mode 100644
index 0000000000..aca6cf46ed
--- /dev/null
+++ b/modules/multiplayer/register_types.h
@@ -0,0 +1,39 @@
+/*************************************************************************/
+/* register_types.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 MULTIPLAYER_REGISTER_TYPES_H
+#define MULTIPLAYER_REGISTER_TYPES_H
+
+#include "modules/register_module_types.h"
+
+void initialize_multiplayer_module(ModuleInitializationLevel p_level);
+void uninitialize_multiplayer_module(ModuleInitializationLevel p_level);
+
+#endif // MULTIPLAYER_REGISTER_TYPES_H
diff --git a/scene/multiplayer/scene_cache_interface.cpp b/modules/multiplayer/scene_cache_interface.cpp
index 7c271341db..b3b642f815 100644
--- a/scene/multiplayer/scene_cache_interface.cpp
+++ b/modules/multiplayer/scene_cache_interface.cpp
@@ -34,13 +34,7 @@
#include "scene/main/node.h"
#include "scene/main/window.h"
-MultiplayerCacheInterface *SceneCacheInterface::_create(MultiplayerAPI *p_multiplayer) {
- return memnew(SceneCacheInterface(p_multiplayer));
-}
-
-void SceneCacheInterface::make_default() {
- MultiplayerAPI::create_default_cache_interface = _create;
-}
+#include "scene_multiplayer.h"
void SceneCacheInterface::on_peer_change(int p_id, bool p_connected) {
if (p_connected) {
@@ -98,7 +92,7 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac
Vector<uint8_t> packet;
packet.resize(1 + 1 + len);
- packet.write[0] = MultiplayerAPI::NETWORK_COMMAND_CONFIRM_PATH;
+ packet.write[0] = SceneMultiplayer::NETWORK_COMMAND_CONFIRM_PATH;
packet.write[1] = valid_rpc_checksum;
encode_cstring(pname.get_data(), &packet.write[2]);
@@ -110,7 +104,7 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac
#endif
multiplayer_peer->set_transfer_channel(0);
- multiplayer_peer->set_transfer_mode(Multiplayer::TRANSFER_MODE_RELIABLE);
+ multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
multiplayer_peer->set_target_peer(p_from);
multiplayer_peer->put_packet(packet.ptr(), packet.size());
}
@@ -150,7 +144,7 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat
packet.resize(1 + 4 + path_len + methods_md5_len);
int ofs = 0;
- packet.write[ofs] = MultiplayerAPI::NETWORK_COMMAND_SIMPLIFY_PATH;
+ packet.write[ofs] = SceneMultiplayer::NETWORK_COMMAND_SIMPLIFY_PATH;
ofs += 1;
ofs += encode_cstring(methods_md5.utf8().get_data(), &packet.write[ofs]);
@@ -170,7 +164,7 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat
for (int peer_id : p_peers) {
multiplayer_peer->set_target_peer(peer_id);
multiplayer_peer->set_transfer_channel(0);
- multiplayer_peer->set_transfer_mode(Multiplayer::TRANSFER_MODE_RELIABLE);
+ multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
err = multiplayer_peer->put_packet(packet.ptr(), packet.size());
ERR_FAIL_COND_V(err != OK, err);
// Insert into confirmed, but as false since it was not confirmed.
@@ -187,18 +181,29 @@ bool SceneCacheInterface::is_cache_confirmed(NodePath p_path, int p_peer) {
return F->value;
}
-bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int p_peer_id, int &r_id) {
+int SceneCacheInterface::make_object_cache(Object *p_obj) {
Node *node = Object::cast_to<Node>(p_obj);
- ERR_FAIL_COND_V(!node, false);
+ ERR_FAIL_COND_V(!node, -1);
+ NodePath for_path = multiplayer->get_root_path().rel_path_to(node->get_path());
// See if the path is cached.
- PathSentCache *psc = path_send_cache.getptr(p_path);
+ PathSentCache *psc = path_send_cache.getptr(for_path);
if (!psc) {
// Path is not cached, create.
- path_send_cache[p_path] = PathSentCache();
- psc = path_send_cache.getptr(p_path);
+ path_send_cache[for_path] = PathSentCache();
+ psc = path_send_cache.getptr(for_path);
psc->id = last_send_cache_id++;
}
- r_id = psc->id;
+ return psc->id;
+}
+
+bool SceneCacheInterface::send_object_cache(Object *p_obj, int p_peer_id, int &r_id) {
+ Node *node = Object::cast_to<Node>(p_obj);
+ ERR_FAIL_COND_V(!node, false);
+
+ r_id = make_object_cache(p_obj);
+ ERR_FAIL_COND_V(r_id < 0, false);
+ NodePath for_path = multiplayer->get_root_path().rel_path_to(node->get_path());
+ PathSentCache *psc = path_send_cache.getptr(for_path);
bool has_all_peers = true;
List<int> peers_to_add; // If one is missing, take note to add it.
@@ -218,9 +223,6 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int
if (p_peer_id < 0 && E == -p_peer_id) {
continue; // Continue, excluded.
}
- if (p_peer_id > 0 && E != p_peer_id) {
- continue; // Continue, not for this peer.
- }
HashMap<int, bool>::Iterator F = psc->confirmed_peers.find(E);
if (!F) {
@@ -233,7 +235,7 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int
}
if (peers_to_add.size()) {
- _send_confirm_path(node, p_path, psc, peers_to_add);
+ _send_confirm_path(node, for_path, psc, peers_to_add);
}
return has_all_peers;
diff --git a/scene/multiplayer/scene_cache_interface.h b/modules/multiplayer/scene_cache_interface.h
index 3116233b5b..1e80792fe7 100644
--- a/scene/multiplayer/scene_cache_interface.h
+++ b/modules/multiplayer/scene_cache_interface.h
@@ -31,13 +31,15 @@
#ifndef SCENE_CACHE_INTERFACE_H
#define SCENE_CACHE_INTERFACE_H
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
-class SceneCacheInterface : public MultiplayerCacheInterface {
- GDCLASS(SceneCacheInterface, MultiplayerCacheInterface);
+class SceneMultiplayer;
+
+class SceneCacheInterface : public RefCounted {
+ GDCLASS(SceneCacheInterface, RefCounted);
private:
- MultiplayerAPI *multiplayer = nullptr;
+ SceneMultiplayer *multiplayer = nullptr;
//path sent caches
struct PathSentCache {
@@ -61,22 +63,20 @@ private:
protected:
Error _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, const List<int> &p_peers);
- static MultiplayerCacheInterface *_create(MultiplayerAPI *p_multiplayer);
public:
- static void make_default();
-
- virtual void clear() override;
- virtual void on_peer_change(int p_id, bool p_connected) override;
- virtual void process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) override;
- virtual void process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) override;
+ void clear();
+ void on_peer_change(int p_id, bool p_connected);
+ void process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len);
+ void process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len);
// Returns true if all peers have cached path.
- virtual bool send_object_cache(Object *p_obj, NodePath p_path, int p_target, int &p_id) override;
- virtual Object *get_cached_object(int p_from, uint32_t p_cache_id) override;
- virtual bool is_cache_confirmed(NodePath p_path, int p_peer) override;
+ bool send_object_cache(Object *p_obj, int p_target, int &p_id);
+ int make_object_cache(Object *p_obj);
+ Object *get_cached_object(int p_from, uint32_t p_cache_id);
+ bool is_cache_confirmed(NodePath p_path, int p_peer);
- SceneCacheInterface(MultiplayerAPI *p_multiplayer) { multiplayer = p_multiplayer; }
+ SceneCacheInterface(SceneMultiplayer *p_multiplayer) { multiplayer = p_multiplayer; }
};
#endif // SCENE_CACHE_INTERFACE_H
diff --git a/modules/multiplayer/scene_multiplayer.cpp b/modules/multiplayer/scene_multiplayer.cpp
new file mode 100644
index 0000000000..3fc1eef366
--- /dev/null
+++ b/modules/multiplayer/scene_multiplayer.cpp
@@ -0,0 +1,332 @@
+/*************************************************************************/
+/* scene_multiplayer.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 "scene_multiplayer.h"
+
+#include "core/debugger/engine_debugger.h"
+#include "core/io/marshalls.h"
+
+#include <stdint.h>
+
+#ifdef DEBUG_ENABLED
+#include "core/os/os.h"
+#endif
+
+#ifdef DEBUG_ENABLED
+void SceneMultiplayer::profile_bandwidth(const String &p_inout, int p_size) {
+ if (EngineDebugger::is_profiling("multiplayer")) {
+ Array values;
+ values.push_back(p_inout);
+ values.push_back(OS::get_singleton()->get_ticks_msec());
+ values.push_back(p_size);
+ EngineDebugger::profiler_add_frame_data("multiplayer", values);
+ }
+}
+#endif
+
+Error SceneMultiplayer::poll() {
+ if (!multiplayer_peer.is_valid() || multiplayer_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED) {
+ return ERR_UNCONFIGURED;
+ }
+
+ multiplayer_peer->poll();
+
+ if (!multiplayer_peer.is_valid()) { // It's possible that polling might have resulted in a disconnection, so check here.
+ return OK;
+ }
+
+ while (multiplayer_peer->get_available_packet_count()) {
+ int sender = multiplayer_peer->get_packet_peer();
+ const uint8_t *packet;
+ int len;
+
+ Error err = multiplayer_peer->get_packet(&packet, len);
+ ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error getting packet! %d", err));
+
+ remote_sender_id = sender;
+ _process_packet(sender, packet, len);
+ remote_sender_id = 0;
+
+ if (!multiplayer_peer.is_valid()) {
+ return OK; // It's also possible that a packet or RPC caused a disconnection, so also check here.
+ }
+ }
+ replicator->on_network_process();
+ return OK;
+}
+
+void SceneMultiplayer::clear() {
+ connected_peers.clear();
+ packet_cache.clear();
+ cache->clear();
+}
+
+void SceneMultiplayer::set_root_path(const NodePath &p_path) {
+ ERR_FAIL_COND_MSG(!p_path.is_absolute() && !p_path.is_empty(), "SceneMultiplayer root path must be absolute.");
+ root_path = p_path;
+}
+
+NodePath SceneMultiplayer::get_root_path() const {
+ return root_path;
+}
+
+void SceneMultiplayer::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) {
+ if (p_peer == multiplayer_peer) {
+ return; // Nothing to do
+ }
+
+ ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == MultiplayerPeer::CONNECTION_DISCONNECTED,
+ "Supplied MultiplayerPeer must be connecting or connected.");
+
+ if (multiplayer_peer.is_valid()) {
+ multiplayer_peer->disconnect("peer_connected", callable_mp(this, &SceneMultiplayer::_add_peer));
+ multiplayer_peer->disconnect("peer_disconnected", callable_mp(this, &SceneMultiplayer::_del_peer));
+ multiplayer_peer->disconnect("connection_succeeded", callable_mp(this, &SceneMultiplayer::_connected_to_server));
+ multiplayer_peer->disconnect("connection_failed", callable_mp(this, &SceneMultiplayer::_connection_failed));
+ multiplayer_peer->disconnect("server_disconnected", callable_mp(this, &SceneMultiplayer::_server_disconnected));
+ clear();
+ }
+
+ multiplayer_peer = p_peer;
+
+ if (multiplayer_peer.is_valid()) {
+ multiplayer_peer->connect("peer_connected", callable_mp(this, &SceneMultiplayer::_add_peer));
+ multiplayer_peer->connect("peer_disconnected", callable_mp(this, &SceneMultiplayer::_del_peer));
+ multiplayer_peer->connect("connection_succeeded", callable_mp(this, &SceneMultiplayer::_connected_to_server));
+ multiplayer_peer->connect("connection_failed", callable_mp(this, &SceneMultiplayer::_connection_failed));
+ multiplayer_peer->connect("server_disconnected", callable_mp(this, &SceneMultiplayer::_server_disconnected));
+ }
+ replicator->on_reset();
+}
+
+Ref<MultiplayerPeer> SceneMultiplayer::get_multiplayer_peer() {
+ return multiplayer_peer;
+}
+
+void SceneMultiplayer::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) {
+ ERR_FAIL_COND_MSG(root_path.is_empty(), "Multiplayer root was not initialized. If you are using custom multiplayer, remember to set the root path via SceneMultiplayer.set_root_path before using it.");
+ ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small.");
+
+#ifdef DEBUG_ENABLED
+ profile_bandwidth("in", p_packet_len);
+#endif
+
+ // Extract the `packet_type` from the LSB three bits:
+ uint8_t packet_type = p_packet[0] & CMD_MASK;
+
+ switch (packet_type) {
+ case NETWORK_COMMAND_SIMPLIFY_PATH: {
+ cache->process_simplify_path(p_from, p_packet, p_packet_len);
+ } break;
+
+ case NETWORK_COMMAND_CONFIRM_PATH: {
+ cache->process_confirm_path(p_from, p_packet, p_packet_len);
+ } break;
+
+ case NETWORK_COMMAND_REMOTE_CALL: {
+ rpc->process_rpc(p_from, p_packet, p_packet_len);
+ } break;
+
+ case NETWORK_COMMAND_RAW: {
+ _process_raw(p_from, p_packet, p_packet_len);
+ } break;
+ case NETWORK_COMMAND_SPAWN: {
+ replicator->on_spawn_receive(p_from, p_packet, p_packet_len);
+ } break;
+ case NETWORK_COMMAND_DESPAWN: {
+ replicator->on_despawn_receive(p_from, p_packet, p_packet_len);
+ } break;
+ case NETWORK_COMMAND_SYNC: {
+ replicator->on_sync_receive(p_from, p_packet, p_packet_len);
+ } break;
+ }
+}
+
+void SceneMultiplayer::_add_peer(int p_id) {
+ connected_peers.insert(p_id);
+ cache->on_peer_change(p_id, true);
+ replicator->on_peer_change(p_id, true);
+ emit_signal(SNAME("peer_connected"), p_id);
+}
+
+void SceneMultiplayer::_del_peer(int p_id) {
+ replicator->on_peer_change(p_id, false);
+ cache->on_peer_change(p_id, false);
+ connected_peers.erase(p_id);
+ emit_signal(SNAME("peer_disconnected"), p_id);
+}
+
+void SceneMultiplayer::_connected_to_server() {
+ emit_signal(SNAME("connected_to_server"));
+}
+
+void SceneMultiplayer::_connection_failed() {
+ emit_signal(SNAME("connection_failed"));
+}
+
+void SceneMultiplayer::_server_disconnected() {
+ replicator->on_reset();
+ emit_signal(SNAME("server_disconnected"));
+}
+
+Error SceneMultiplayer::send_bytes(Vector<uint8_t> p_data, int p_to, MultiplayerPeer::TransferMode p_mode, int p_channel) {
+ ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet.");
+ ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no multiplayer peer is active.");
+ ERR_FAIL_COND_V_MSG(multiplayer_peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a multiplayer peer which is not connected.");
+
+ if (packet_cache.size() < p_data.size() + 1) {
+ packet_cache.resize(p_data.size() + 1);
+ }
+
+ const uint8_t *r = p_data.ptr();
+ packet_cache.write[0] = NETWORK_COMMAND_RAW;
+ memcpy(&packet_cache.write[1], &r[0], p_data.size());
+
+ multiplayer_peer->set_target_peer(p_to);
+ multiplayer_peer->set_transfer_channel(p_channel);
+ multiplayer_peer->set_transfer_mode(p_mode);
+
+ return multiplayer_peer->put_packet(packet_cache.ptr(), p_data.size() + 1);
+}
+
+void SceneMultiplayer::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) {
+ ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small.");
+
+ Vector<uint8_t> out;
+ int len = p_packet_len - 1;
+ out.resize(len);
+ {
+ uint8_t *w = out.ptrw();
+ memcpy(&w[0], &p_packet[1], len);
+ }
+ emit_signal(SNAME("peer_packet"), p_from, out);
+}
+
+int SceneMultiplayer::get_unique_id() {
+ ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), 0, "No multiplayer peer is assigned. Unable to get unique ID.");
+ return multiplayer_peer->get_unique_id();
+}
+
+void SceneMultiplayer::set_refuse_new_connections(bool p_refuse) {
+ ERR_FAIL_COND_MSG(!multiplayer_peer.is_valid(), "No multiplayer peer is assigned. Unable to set 'refuse_new_connections'.");
+ multiplayer_peer->set_refuse_new_connections(p_refuse);
+}
+
+bool SceneMultiplayer::is_refusing_new_connections() const {
+ ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), false, "No multiplayer peer is assigned. Unable to get 'refuse_new_connections'.");
+ return multiplayer_peer->is_refusing_new_connections();
+}
+
+Vector<int> SceneMultiplayer::get_peer_ids() {
+ ERR_FAIL_COND_V_MSG(!multiplayer_peer.is_valid(), Vector<int>(), "No multiplayer peer is assigned. Assume no peers are connected.");
+
+ Vector<int> ret;
+ for (const int &E : connected_peers) {
+ ret.push_back(E);
+ }
+
+ return ret;
+}
+
+void SceneMultiplayer::set_allow_object_decoding(bool p_enable) {
+ allow_object_decoding = p_enable;
+}
+
+bool SceneMultiplayer::is_object_decoding_allowed() const {
+ return allow_object_decoding;
+}
+
+String SceneMultiplayer::get_rpc_md5(const Object *p_obj) {
+ return rpc->get_rpc_md5(p_obj);
+}
+
+Error SceneMultiplayer::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+ return rpc->rpcp(p_obj, p_peer_id, p_method, p_arg, p_argcount);
+}
+
+Error SceneMultiplayer::object_configuration_add(Object *p_obj, Variant p_config) {
+ if (p_obj == nullptr && p_config.get_type() == Variant::NODE_PATH) {
+ set_root_path(p_config);
+ return OK;
+ }
+ MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object());
+ MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object());
+ if (spawner) {
+ return replicator->on_spawn(p_obj, p_config);
+ } else if (sync) {
+ return replicator->on_replication_start(p_obj, p_config);
+ }
+ return ERR_INVALID_PARAMETER;
+}
+
+Error SceneMultiplayer::object_configuration_remove(Object *p_obj, Variant p_config) {
+ if (p_obj == nullptr && p_config.get_type() == Variant::NODE_PATH) {
+ ERR_FAIL_COND_V(root_path != p_config.operator NodePath(), ERR_INVALID_PARAMETER);
+ set_root_path(NodePath());
+ return OK;
+ }
+ MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object());
+ MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object());
+ if (spawner) {
+ return replicator->on_despawn(p_obj, p_config);
+ }
+ if (sync) {
+ return replicator->on_replication_stop(p_obj, p_config);
+ }
+ return ERR_INVALID_PARAMETER;
+}
+
+void SceneMultiplayer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_root_path", "path"), &SceneMultiplayer::set_root_path);
+ ClassDB::bind_method(D_METHOD("get_root_path"), &SceneMultiplayer::get_root_path);
+ ClassDB::bind_method(D_METHOD("clear"), &SceneMultiplayer::clear);
+ ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "refuse"), &SceneMultiplayer::set_refuse_new_connections);
+ ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &SceneMultiplayer::is_refusing_new_connections);
+ ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &SceneMultiplayer::set_allow_object_decoding);
+ ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &SceneMultiplayer::is_object_decoding_allowed);
+ ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode", "channel"), &SceneMultiplayer::send_bytes, DEFVAL(MultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(MultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_path"), "set_root_path", "get_root_path");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections");
+ ADD_PROPERTY_DEFAULT("refuse_new_connections", false);
+
+ ADD_SIGNAL(MethodInfo("peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "packet")));
+}
+
+SceneMultiplayer::SceneMultiplayer() {
+ replicator = Ref<SceneReplicationInterface>(memnew(SceneReplicationInterface(this)));
+ rpc = Ref<SceneRPCInterface>(memnew(SceneRPCInterface(this)));
+ cache = Ref<SceneCacheInterface>(memnew(SceneCacheInterface(this)));
+}
+
+SceneMultiplayer::~SceneMultiplayer() {
+ clear();
+}
diff --git a/modules/multiplayer/scene_multiplayer.h b/modules/multiplayer/scene_multiplayer.h
new file mode 100644
index 0000000000..a99cca7b21
--- /dev/null
+++ b/modules/multiplayer/scene_multiplayer.h
@@ -0,0 +1,136 @@
+/*************************************************************************/
+/* scene_multiplayer.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 SCENE_MULTIPLAYER_H
+#define SCENE_MULTIPLAYER_H
+
+#include "scene/main/multiplayer_api.h"
+
+#include "scene_cache_interface.h"
+#include "scene_replication_interface.h"
+#include "scene_rpc_interface.h"
+
+class SceneMultiplayer : public MultiplayerAPI {
+ GDCLASS(SceneMultiplayer, MultiplayerAPI);
+
+public:
+ enum NetworkCommands {
+ NETWORK_COMMAND_REMOTE_CALL = 0,
+ NETWORK_COMMAND_SIMPLIFY_PATH,
+ NETWORK_COMMAND_CONFIRM_PATH,
+ NETWORK_COMMAND_RAW,
+ NETWORK_COMMAND_SPAWN,
+ NETWORK_COMMAND_DESPAWN,
+ NETWORK_COMMAND_SYNC,
+ };
+
+ // For each command, the 4 MSB can contain custom flags, as defined by subsystems.
+ enum {
+ CMD_FLAG_0_SHIFT = 4,
+ CMD_FLAG_1_SHIFT = 5,
+ CMD_FLAG_2_SHIFT = 6,
+ CMD_FLAG_3_SHIFT = 7,
+ };
+
+ // This is the mask that will be used to extract the command.
+ enum {
+ CMD_MASK = 7, // 0x7 -> 0b00001111
+ };
+
+private:
+ Ref<MultiplayerPeer> multiplayer_peer;
+ HashSet<int> connected_peers;
+ int remote_sender_id = 0;
+ int remote_sender_override = 0;
+
+ Vector<uint8_t> packet_cache;
+
+ NodePath root_path;
+ bool allow_object_decoding = false;
+
+ Ref<SceneCacheInterface> cache;
+ Ref<SceneReplicationInterface> replicator;
+ Ref<SceneRPCInterface> rpc;
+
+protected:
+ static void _bind_methods();
+
+ void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len);
+ void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
+
+ void _add_peer(int p_id);
+ void _del_peer(int p_id);
+ void _connected_to_server();
+ void _connection_failed();
+ void _server_disconnected();
+
+public:
+ virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) override;
+ virtual Ref<MultiplayerPeer> get_multiplayer_peer() override;
+
+ virtual Error poll() override;
+ virtual int get_unique_id() override;
+ virtual Vector<int> get_peer_ids() override;
+ virtual int get_remote_sender_id() override { return remote_sender_override ? remote_sender_override : remote_sender_id; }
+
+ virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override;
+
+ virtual Error object_configuration_add(Object *p_obj, Variant p_config) override;
+ virtual Error object_configuration_remove(Object *p_obj, Variant p_config) override;
+
+ void clear();
+
+ // Usually from object_configuration_add/remove
+ void set_root_path(const NodePath &p_path);
+ NodePath get_root_path() const;
+
+ Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, MultiplayerPeer::TransferMode p_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE, int p_channel = 0);
+ String get_rpc_md5(const Object *p_obj);
+
+ const HashSet<int> get_connected_peers() const { return connected_peers; }
+
+ void set_remote_sender_override(int p_id) { remote_sender_override = p_id; }
+ void set_refuse_new_connections(bool p_refuse);
+ bool is_refusing_new_connections() const;
+
+ void set_allow_object_decoding(bool p_enable);
+ bool is_object_decoding_allowed() const;
+
+ Ref<SceneCacheInterface> get_path_cache() { return cache; }
+
+#ifdef DEBUG_ENABLED
+ void profile_bandwidth(const String &p_inout, int p_size);
+#endif
+
+ SceneMultiplayer();
+ ~SceneMultiplayer();
+};
+
+#endif // SCENE_MULTIPLAYER_H
diff --git a/scene/resources/scene_replication_config.cpp b/modules/multiplayer/scene_replication_config.cpp
index 6789f9f7d5..ae06516b7b 100644
--- a/scene/resources/scene_replication_config.cpp
+++ b/modules/multiplayer/scene_replication_config.cpp
@@ -30,7 +30,7 @@
#include "scene_replication_config.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/node.h"
bool SceneReplicationConfig::_set(const StringName &p_name, const Variant &p_value) {
diff --git a/scene/resources/scene_replication_config.h b/modules/multiplayer/scene_replication_config.h
index ab3658d2a7..ab3658d2a7 100644
--- a/scene/resources/scene_replication_config.h
+++ b/modules/multiplayer/scene_replication_config.h
diff --git a/scene/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp
index e4715ceb88..6e3dbfab47 100644
--- a/scene/multiplayer/scene_replication_interface.cpp
+++ b/modules/multiplayer/scene_replication_interface.cpp
@@ -32,21 +32,15 @@
#include "core/io/marshalls.h"
#include "scene/main/node.h"
-#include "scene/multiplayer/multiplayer_spawner.h"
-#include "scene/multiplayer/multiplayer_synchronizer.h"
+
+#include "multiplayer_spawner.h"
+#include "multiplayer_synchronizer.h"
+#include "scene_multiplayer.h"
#define MAKE_ROOM(m_amount) \
if (packet_cache.size() < m_amount) \
packet_cache.resize(m_amount);
-MultiplayerReplicationInterface *SceneReplicationInterface::_create(MultiplayerAPI *p_multiplayer) {
- return memnew(SceneReplicationInterface(p_multiplayer));
-}
-
-void SceneReplicationInterface::make_default() {
- MultiplayerAPI::create_default_replication_interface = _create;
-}
-
void SceneReplicationInterface::_free_remotes(int p_id) {
const HashMap<uint32_t, ObjectID> remotes = rep_state->peer_get_remotes(p_id);
for (const KeyValue<uint32_t, ObjectID> &E : remotes) {
@@ -60,14 +54,13 @@ void SceneReplicationInterface::on_peer_change(int p_id, bool p_connected) {
if (p_connected) {
rep_state->on_peer_change(p_id, p_connected);
for (const ObjectID &oid : rep_state->get_spawned_nodes()) {
- _send_spawn(rep_state->get_node(oid), rep_state->get_spawner(oid), p_id);
+ _update_spawn_visibility(p_id, oid);
}
- for (const ObjectID &oid : rep_state->get_path_only_nodes()) {
- Node *node = rep_state->get_node(oid);
+ for (const ObjectID &oid : rep_state->get_synced_nodes()) {
MultiplayerSynchronizer *sync = rep_state->get_synchronizer(oid);
- ERR_CONTINUE(!node || !sync);
+ ERR_CONTINUE(!sync); // ERR_BUG
if (sync->is_multiplayer_authority()) {
- rep_state->peer_add_node(p_id, oid);
+ _update_sync_visibility(p_id, oid);
}
}
} else {
@@ -97,7 +90,13 @@ Error SceneReplicationInterface::on_spawn(Object *p_obj, Variant p_config) {
ERR_FAIL_COND_V(!spawner, ERR_INVALID_PARAMETER);
Error err = rep_state->config_add_spawn(node, spawner);
ERR_FAIL_COND_V(err != OK, err);
- return _send_spawn(node, spawner, 0);
+ const ObjectID oid = node->get_instance_id();
+ if (multiplayer->has_multiplayer_peer() && spawner->is_multiplayer_authority()) {
+ rep_state->ensure_net_id(oid);
+ _update_spawn_visibility(0, oid);
+ }
+ ERR_FAIL_COND_V(err != OK, err);
+ return OK;
}
Error SceneReplicationInterface::on_despawn(Object *p_obj, Variant p_config) {
@@ -105,9 +104,19 @@ Error SceneReplicationInterface::on_despawn(Object *p_obj, Variant p_config) {
ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER);
MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object());
ERR_FAIL_COND_V(!p_obj || !spawner, ERR_INVALID_PARAMETER);
- Error err = rep_state->config_del_spawn(node, spawner);
- ERR_FAIL_COND_V(err != OK, err);
- return _send_despawn(node, 0);
+ // Forcibly despawn to all peers that knowns me.
+ int len = 0;
+ Error err = _make_despawn_packet(node, len);
+ ERR_FAIL_COND_V(err != OK, ERR_BUG);
+ const ObjectID oid = p_obj->get_instance_id();
+ for (int pid : rep_state->get_peers()) {
+ if (!rep_state->is_peer_spawn(pid, oid)) {
+ continue;
+ }
+ _send_raw(packet_cache.ptr(), len, pid, true);
+ }
+ // Also remove spawner tracking from the replication state.
+ return rep_state->config_del_spawn(node, spawner);
}
Error SceneReplicationInterface::on_replication_start(Object *p_obj, Variant p_config) {
@@ -115,7 +124,15 @@ Error SceneReplicationInterface::on_replication_start(Object *p_obj, Variant p_c
ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER);
MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object());
ERR_FAIL_COND_V(!sync, ERR_INVALID_PARAMETER);
+
+ // Add to synchronizer list and setup visibility.
rep_state->config_add_sync(node, sync);
+ const ObjectID oid = node->get_instance_id();
+ sync->connect("visibility_changed", callable_mp(this, &SceneReplicationInterface::_visibility_changed).bind(oid));
+ if (multiplayer->has_multiplayer_peer() && sync->is_multiplayer_authority()) {
+ _update_sync_visibility(0, oid);
+ }
+
// Try to apply initial state if spawning (hack to apply if before ready).
if (pending_spawn == p_obj->get_instance_id()) {
pending_spawn = ObjectID(); // Make sure this only happens once.
@@ -127,9 +144,6 @@ Error SceneReplicationInterface::on_replication_start(Object *p_obj, Variant p_c
ERR_FAIL_COND_V(err, err);
err = MultiplayerSynchronizer::set_state(props, node, vars);
ERR_FAIL_COND_V(err, err);
- } else if (multiplayer->has_multiplayer_peer() && sync->is_multiplayer_authority()) {
- // Either it's a spawn or a static sync, in any case add it to the list of known nodes.
- rep_state->peer_add_node(0, p_obj->get_instance_id());
}
return OK;
}
@@ -138,10 +152,103 @@ Error SceneReplicationInterface::on_replication_stop(Object *p_obj, Variant p_co
Node *node = Object::cast_to<Node>(p_obj);
ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER);
MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object());
- ERR_FAIL_COND_V(!p_obj || !sync, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(!sync, ERR_INVALID_PARAMETER);
+ sync->disconnect("visibility_changed", callable_mp(this, &SceneReplicationInterface::_visibility_changed));
return rep_state->config_del_sync(node, sync);
}
+void SceneReplicationInterface::_visibility_changed(int p_peer, ObjectID p_oid) {
+ if (rep_state->is_spawned_node(p_oid)) {
+ _update_spawn_visibility(p_peer, p_oid);
+ }
+ if (rep_state->is_synced_node(p_oid)) {
+ _update_sync_visibility(p_peer, p_oid);
+ }
+}
+
+Error SceneReplicationInterface::_update_sync_visibility(int p_peer, const ObjectID &p_oid) {
+ MultiplayerSynchronizer *sync = rep_state->get_synchronizer(p_oid);
+ ERR_FAIL_COND_V(!sync || !sync->is_multiplayer_authority(), ERR_BUG);
+ bool is_visible = sync->is_visible_to(p_peer);
+ if (p_peer == 0) {
+ for (int pid : rep_state->get_peers()) {
+ // Might be visible to this specific peer.
+ is_visible = is_visible || sync->is_visible_to(pid);
+ if (rep_state->is_peer_sync(pid, p_oid) == is_visible) {
+ continue;
+ }
+ if (is_visible) {
+ rep_state->peer_add_sync(pid, p_oid);
+ } else {
+ rep_state->peer_del_sync(pid, p_oid);
+ }
+ }
+ return OK;
+ } else {
+ if (is_visible == rep_state->is_peer_sync(p_peer, p_oid)) {
+ return OK;
+ }
+ if (is_visible) {
+ return rep_state->peer_add_sync(p_peer, p_oid);
+ } else {
+ return rep_state->peer_del_sync(p_peer, p_oid);
+ }
+ }
+}
+
+Error SceneReplicationInterface::_update_spawn_visibility(int p_peer, const ObjectID &p_oid) {
+ MultiplayerSpawner *spawner = rep_state->get_spawner(p_oid);
+ MultiplayerSynchronizer *sync = rep_state->get_synchronizer(p_oid);
+ Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_oid));
+ ERR_FAIL_COND_V(!node || !spawner || !spawner->is_multiplayer_authority(), ERR_BUG);
+ bool is_visible = !sync || sync->is_visible_to(p_peer);
+ // Spawn (and despawn) when needed.
+ HashSet<int> to_spawn;
+ HashSet<int> to_despawn;
+ if (p_peer) {
+ if (is_visible == rep_state->is_peer_spawn(p_peer, p_oid)) {
+ return OK;
+ }
+ if (is_visible) {
+ to_spawn.insert(p_peer);
+ } else {
+ to_despawn.insert(p_peer);
+ }
+ } else {
+ // Check visibility for each peers.
+ for (int pid : rep_state->get_peers()) {
+ bool peer_visible = is_visible || sync->is_visible_to(pid);
+ if (peer_visible == rep_state->is_peer_spawn(pid, p_oid)) {
+ continue;
+ }
+ if (peer_visible) {
+ to_spawn.insert(pid);
+ } else {
+ to_despawn.insert(pid);
+ }
+ }
+ }
+ if (to_spawn.size()) {
+ int len = 0;
+ _make_spawn_packet(node, len);
+ for (int pid : to_spawn) {
+ int path_id;
+ multiplayer->get_path_cache()->send_object_cache(spawner, pid, path_id);
+ _send_raw(packet_cache.ptr(), len, pid, true);
+ rep_state->peer_add_spawn(pid, p_oid);
+ }
+ }
+ if (to_despawn.size()) {
+ int len = 0;
+ _make_despawn_packet(node, len);
+ for (int pid : to_despawn) {
+ rep_state->peer_del_spawn(pid, p_oid);
+ _send_raw(packet_cache.ptr(), len, pid, true);
+ }
+ }
+ return OK;
+}
+
Error SceneReplicationInterface::_send_raw(const uint8_t *p_buffer, int p_size, int p_peer, bool p_reliable) {
ERR_FAIL_COND_V(!p_buffer || p_size < 1, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!multiplayer, ERR_UNCONFIGURED);
@@ -154,22 +261,24 @@ Error SceneReplicationInterface::_send_raw(const uint8_t *p_buffer, int p_size,
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
peer->set_target_peer(p_peer);
peer->set_transfer_channel(0);
- peer->set_transfer_mode(p_reliable ? Multiplayer::TRANSFER_MODE_RELIABLE : Multiplayer::TRANSFER_MODE_UNRELIABLE);
+ peer->set_transfer_mode(p_reliable ? MultiplayerPeer::TRANSFER_MODE_RELIABLE : MultiplayerPeer::TRANSFER_MODE_UNRELIABLE);
return peer->put_packet(p_buffer, p_size);
}
-Error SceneReplicationInterface::_send_spawn(Node *p_node, MultiplayerSpawner *p_spawner, int p_peer) {
- ERR_FAIL_COND_V(p_peer < 0, ERR_BUG);
+Error SceneReplicationInterface::_make_spawn_packet(Node *p_node, int &r_len) {
ERR_FAIL_COND_V(!multiplayer, ERR_BUG);
- ERR_FAIL_COND_V(!p_spawner || !p_node, ERR_BUG);
const ObjectID oid = p_node->get_instance_id();
- uint32_t nid = rep_state->ensure_net_id(oid);
+ MultiplayerSpawner *spawner = rep_state->get_spawner(oid);
+ ERR_FAIL_COND_V(!spawner || !p_node, ERR_BUG);
+
+ uint32_t nid = rep_state->get_net_id(oid);
+ ERR_FAIL_COND_V(!nid, ERR_UNCONFIGURED);
// Prepare custom arg and scene_id
- uint8_t scene_id = p_spawner->find_spawnable_scene_index_from_object(oid);
+ uint8_t scene_id = spawner->find_spawnable_scene_index_from_object(oid);
bool is_custom = scene_id == MultiplayerSpawner::INVALID_ID;
- Variant spawn_arg = p_spawner->get_spawn_argument(oid);
+ Variant spawn_arg = spawner->get_spawn_argument(oid);
int spawn_arg_size = 0;
if (is_custom) {
Error err = MultiplayerAPI::encode_and_compress_variant(spawn_arg, nullptr, spawn_arg_size, false);
@@ -181,7 +290,8 @@ Error SceneReplicationInterface::_send_spawn(Node *p_node, MultiplayerSpawner *p
Vector<Variant> state_vars;
Vector<const Variant *> state_varp;
MultiplayerSynchronizer *synchronizer = rep_state->get_synchronizer(oid);
- if (synchronizer && synchronizer->get_replication_config().is_valid()) {
+ if (synchronizer) {
+ ERR_FAIL_COND_V(synchronizer->get_replication_config().is_null(), ERR_BUG);
const List<NodePath> props = synchronizer->get_replication_config()->get_spawn_properties();
Error err = MultiplayerSynchronizer::get_state(props, p_node, state_vars, state_varp);
ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to retrieve spawn state.");
@@ -189,18 +299,13 @@ Error SceneReplicationInterface::_send_spawn(Node *p_node, MultiplayerSpawner *p
ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to encode spawn state.");
}
- // Prepare simplified path.
- NodePath rel_path = multiplayer->get_root_path().rel_path_to(p_spawner->get_path());
-
- int path_id = 0;
- multiplayer->send_object_cache(p_spawner, rel_path, p_peer, path_id);
-
- // Encode name and parent ID.
+ // Encode scene ID, path ID, net ID, node name.
+ int path_id = multiplayer->get_path_cache()->make_object_cache(spawner);
CharString cname = p_node->get_name().operator String().utf8();
int nlen = encode_cstring(cname.get_data(), nullptr);
MAKE_ROOM(1 + 1 + 4 + 4 + 4 + nlen + (is_custom ? 4 + spawn_arg_size : 0) + state_size);
uint8_t *ptr = packet_cache.ptrw();
- ptr[0] = (uint8_t)MultiplayerAPI::NETWORK_COMMAND_SPAWN;
+ ptr[0] = (uint8_t)SceneMultiplayer::NETWORK_COMMAND_SPAWN;
ptr[1] = scene_id;
int ofs = 2;
ofs += encode_uint32(path_id, &ptr[ofs]);
@@ -220,22 +325,20 @@ Error SceneReplicationInterface::_send_spawn(Node *p_node, MultiplayerSpawner *p
ERR_FAIL_COND_V(err, err);
ofs += state_size;
}
- Error err = _send_raw(ptr, ofs, p_peer, true);
- ERR_FAIL_COND_V(err, err);
- return rep_state->peer_add_node(p_peer, oid);
+ r_len = ofs;
+ return OK;
}
-Error SceneReplicationInterface::_send_despawn(Node *p_node, int p_peer) {
+Error SceneReplicationInterface::_make_despawn_packet(Node *p_node, int &r_len) {
const ObjectID oid = p_node->get_instance_id();
MAKE_ROOM(5);
uint8_t *ptr = packet_cache.ptrw();
- ptr[0] = (uint8_t)MultiplayerAPI::NETWORK_COMMAND_DESPAWN;
+ ptr[0] = (uint8_t)SceneMultiplayer::NETWORK_COMMAND_DESPAWN;
int ofs = 1;
uint32_t nid = rep_state->get_net_id(oid);
ofs += encode_uint32(nid, &ptr[ofs]);
- Error err = _send_raw(ptr, ofs, p_peer, true);
- ERR_FAIL_COND_V(err, err);
- return rep_state->peer_del_node(p_peer, oid);
+ r_len = ofs;
+ return OK;
}
Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) {
@@ -245,7 +348,7 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b
ofs += 1;
uint32_t node_target = decode_uint32(&p_buffer[ofs]);
ofs += 4;
- MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(multiplayer->get_cached_object(p_from, node_target));
+ MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(multiplayer->get_path_cache()->get_cached_object(p_from, node_target));
ERR_FAIL_COND_V(!spawner, ERR_DOES_NOT_EXIST);
ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED);
@@ -293,6 +396,8 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b
pending_buffer_size = state_len;
}
parent->add_child(node);
+ spawner->emit_signal(SNAME("spawned"), node);
+
pending_spawn = ObjectID();
pending_buffer = nullptr;
pending_buffer_size = 0;
@@ -308,33 +413,55 @@ Error SceneReplicationInterface::on_despawn_receive(int p_from, const uint8_t *p
Error err = rep_state->peer_del_remote(p_from, net_id, &node);
ERR_FAIL_COND_V(err != OK, err);
ERR_FAIL_COND_V(!node, ERR_BUG);
+
+ MultiplayerSpawner *spawner = rep_state->get_spawner(node->get_instance_id());
+ ERR_FAIL_COND_V(!spawner, ERR_DOES_NOT_EXIST);
+ ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED);
+
if (node->get_parent() != nullptr) {
node->get_parent()->remove_child(node);
}
node->queue_delete();
+ spawner->emit_signal(SNAME("despawned"), node);
+
return OK;
}
void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) {
- const HashSet<ObjectID> &known = rep_state->get_known_nodes(p_peer);
- if (known.is_empty()) {
+ const HashSet<ObjectID> &to_sync = rep_state->get_peer_sync_nodes(p_peer);
+ if (to_sync.is_empty()) {
return;
}
MAKE_ROOM(sync_mtu);
uint8_t *ptr = packet_cache.ptrw();
- ptr[0] = MultiplayerAPI::NETWORK_COMMAND_SYNC;
+ ptr[0] = SceneMultiplayer::NETWORK_COMMAND_SYNC;
int ofs = 1;
ofs += encode_uint16(rep_state->peer_sync_next(p_peer), &ptr[1]);
// Can only send updates for already notified nodes.
// This is a lazy implementation, we could optimize much more here with by grouping by replication config.
- for (const ObjectID &oid : known) {
+ for (const ObjectID &oid : to_sync) {
if (!rep_state->update_sync_time(oid, p_msec)) {
continue; // nothing to sync.
}
MultiplayerSynchronizer *sync = rep_state->get_synchronizer(oid);
- ERR_CONTINUE(!sync);
+ ERR_CONTINUE(!sync || !sync->get_replication_config().is_valid());
Node *node = rep_state->get_node(oid);
ERR_CONTINUE(!node);
+ uint32_t net_id = rep_state->get_net_id(oid);
+ if (net_id == 0 || (net_id & 0x80000000)) {
+ int path_id = 0;
+ bool verified = multiplayer->get_path_cache()->send_object_cache(sync, p_peer, path_id);
+ ERR_CONTINUE_MSG(path_id < 0, "This should never happen!");
+ if (net_id == 0) {
+ // First time path based ID.
+ net_id = path_id | 0x80000000;
+ rep_state->set_net_id(oid, net_id | 0x80000000);
+ }
+ if (!verified) {
+ // The path based sync is not yet confirmed, skipping.
+ continue;
+ }
+ }
int size;
Vector<Variant> vars;
Vector<const Variant *> varp;
@@ -351,16 +478,6 @@ void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) {
ofs = 3;
}
if (size) {
- uint32_t net_id = rep_state->get_net_id(oid);
- if (net_id == 0 || (net_id & 0x80000000)) {
- // First time path based ID.
- NodePath rel_path = multiplayer->get_root_path().rel_path_to(sync->get_path());
- int path_id = 0;
- multiplayer->send_object_cache(sync, rel_path, p_peer, path_id);
- ERR_CONTINUE_MSG(net_id && net_id != (uint32_t(path_id) | 0x80000000), "This should never happen!");
- net_id = path_id;
- rep_state->set_net_id(oid, net_id | 0x80000000);
- }
ofs += encode_uint32(rep_state->get_net_id(oid), &ptr[ofs]);
ofs += encode_uint32(size, &ptr[ofs]);
MultiplayerAPI::encode_and_compress_variants(varp.ptrw(), varp.size(), &ptr[ofs], size);
@@ -385,7 +502,7 @@ Error SceneReplicationInterface::on_sync_receive(int p_from, const uint8_t *p_bu
ofs += 4;
Node *node = nullptr;
if (net_id & 0x80000000) {
- MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(multiplayer->get_cached_object(p_from, net_id & 0x7FFFFFFF));
+ MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(multiplayer->get_path_cache()->get_cached_object(p_from, net_id & 0x7FFFFFFF));
ERR_FAIL_COND_V(!sync || sync->get_multiplayer_authority() != p_from, ERR_UNAUTHORIZED);
node = sync->get_node(sync->get_root_path());
} else {
diff --git a/scene/multiplayer/scene_replication_interface.h b/modules/multiplayer/scene_replication_interface.h
index 60ac95c93c..8981647429 100644
--- a/scene/multiplayer/scene_replication_interface.h
+++ b/modules/multiplayer/scene_replication_interface.h
@@ -28,26 +28,31 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SCENE_TREE_REPLICATOR_INTERFACE_H
-#define SCENE_TREE_REPLICATOR_INTERFACE_H
+#ifndef SCENE_REPLICATION_INTERFACE_H
+#define SCENE_REPLICATION_INTERFACE_H
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
-#include "scene/multiplayer/scene_replication_state.h"
+#include "scene_replication_state.h"
-class SceneReplicationInterface : public MultiplayerReplicationInterface {
- GDCLASS(SceneReplicationInterface, MultiplayerReplicationInterface);
+class SceneMultiplayer;
+
+class SceneReplicationInterface : public RefCounted {
+ GDCLASS(SceneReplicationInterface, RefCounted);
private:
void _send_sync(int p_peer, uint64_t p_msec);
- Error _send_spawn(Node *p_node, MultiplayerSpawner *p_spawner, int p_peer);
- Error _send_despawn(Node *p_node, int p_peer);
+ Error _make_spawn_packet(Node *p_node, int &r_len);
+ Error _make_despawn_packet(Node *p_node, int &r_len);
Error _send_raw(const uint8_t *p_buffer, int p_size, int p_peer, bool p_reliable);
+ void _visibility_changed(int p_peer, ObjectID p_oid);
+ Error _update_sync_visibility(int p_peer, const ObjectID &p_oid);
+ Error _update_spawn_visibility(int p_peer, const ObjectID &p_oid);
void _free_remotes(int p_peer);
Ref<SceneReplicationState> rep_state;
- MultiplayerAPI *multiplayer = nullptr;
+ SceneMultiplayer *multiplayer = nullptr;
PackedByteArray packet_cache;
int sync_mtu = 1350; // Highly dependent on underlying protocol.
@@ -56,29 +61,26 @@ private:
const uint8_t *pending_buffer = nullptr;
int pending_buffer_size = 0;
-protected:
- static MultiplayerReplicationInterface *_create(MultiplayerAPI *p_multiplayer);
-
public:
static void make_default();
- virtual void on_reset() override;
- virtual void on_peer_change(int p_id, bool p_connected) override;
+ void on_reset();
+ void on_peer_change(int p_id, bool p_connected);
- virtual Error on_spawn(Object *p_obj, Variant p_config) override;
- virtual Error on_despawn(Object *p_obj, Variant p_config) override;
- virtual Error on_replication_start(Object *p_obj, Variant p_config) override;
- virtual Error on_replication_stop(Object *p_obj, Variant p_config) override;
- virtual void on_network_process() override;
+ Error on_spawn(Object *p_obj, Variant p_config);
+ Error on_despawn(Object *p_obj, Variant p_config);
+ Error on_replication_start(Object *p_obj, Variant p_config);
+ Error on_replication_stop(Object *p_obj, Variant p_config);
+ void on_network_process();
- virtual Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) override;
- virtual Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) override;
- virtual Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) override;
+ Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
+ Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
+ Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
- SceneReplicationInterface(MultiplayerAPI *p_multiplayer) {
+ SceneReplicationInterface(SceneMultiplayer *p_multiplayer) {
rep_state.instantiate();
multiplayer = p_multiplayer;
}
};
-#endif // SCENE_TREE_REPLICATOR_INTERFACE_H
+#endif // SCENE_REPLICATION_INTERFACE_H
diff --git a/scene/multiplayer/scene_replication_state.cpp b/modules/multiplayer/scene_replication_state.cpp
index 937b30cb36..25442bb7fa 100644
--- a/scene/multiplayer/scene_replication_state.cpp
+++ b/modules/multiplayer/scene_replication_state.cpp
@@ -28,18 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "scene/multiplayer/scene_replication_state.h"
+#include "scene_replication_state.h"
-#include "core/multiplayer/multiplayer_api.h"
-#include "scene/multiplayer/multiplayer_spawner.h"
-#include "scene/multiplayer/multiplayer_synchronizer.h"
#include "scene/scene_string_names.h"
+#include "multiplayer_spawner.h"
+#include "multiplayer_synchronizer.h"
+
SceneReplicationState::TrackedNode &SceneReplicationState::_track(const ObjectID &p_id) {
if (!tracked_nodes.has(p_id)) {
tracked_nodes[p_id] = TrackedNode(p_id);
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_id));
- node->connect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationState::_untrack), varray(p_id), Node::CONNECT_ONESHOT);
+ node->connect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationState::_untrack).bind(p_id), Node::CONNECT_ONESHOT);
}
return tracked_nodes[p_id];
}
@@ -56,7 +56,8 @@ void SceneReplicationState::_untrack(const ObjectID &p_id) {
// If we spawned or synced it, we need to remove it from any peer it was sent to.
if (net_id || peer == 0) {
for (KeyValue<int, PeerInfo> &E : peers_info) {
- E.value.known_nodes.erase(p_id);
+ E.value.sync_nodes.erase(p_id);
+ E.value.spawn_nodes.erase(p_id);
}
}
}
@@ -93,11 +94,6 @@ bool SceneReplicationState::update_sync_time(const ObjectID &p_id, uint64_t p_ms
return false;
}
-const HashSet<ObjectID> SceneReplicationState::get_known_nodes(int p_peer) {
- ERR_FAIL_COND_V(!peers_info.has(p_peer), HashSet<ObjectID>());
- return peers_info[p_peer].known_nodes;
-}
-
uint32_t SceneReplicationState::get_net_id(const ObjectID &p_id) const {
const TrackedNode *tnode = tracked_nodes.getptr(p_id);
ERR_FAIL_COND_V(!tnode, 0);
@@ -147,8 +143,6 @@ Error SceneReplicationState::config_add_spawn(Node *p_node, MultiplayerSpawner *
ERR_FAIL_COND_V(tobj.spawner != ObjectID(), ERR_ALREADY_IN_USE);
tobj.spawner = p_spawner->get_instance_id();
spawned_nodes.insert(oid);
- // The spawner may be notified after the synchronizer.
- path_only_nodes.erase(oid);
return OK;
}
@@ -159,6 +153,9 @@ Error SceneReplicationState::config_del_spawn(Node *p_node, MultiplayerSpawner *
ERR_FAIL_COND_V(tobj.spawner != p_spawner->get_instance_id(), ERR_INVALID_PARAMETER);
tobj.spawner = ObjectID();
spawned_nodes.erase(oid);
+ for (KeyValue<int, PeerInfo> &E : peers_info) {
+ E.value.spawn_nodes.erase(oid);
+ }
return OK;
}
@@ -167,10 +164,7 @@ Error SceneReplicationState::config_add_sync(Node *p_node, MultiplayerSynchroniz
TrackedNode &tobj = _track(oid);
ERR_FAIL_COND_V(tobj.synchronizer != ObjectID(), ERR_ALREADY_IN_USE);
tobj.synchronizer = p_sync->get_instance_id();
- // If it doesn't have a spawner, we might need to assign ID for this node using it's path.
- if (tobj.spawner.is_null()) {
- path_only_nodes.insert(oid);
- }
+ synced_nodes.insert(oid);
return OK;
}
@@ -180,38 +174,57 @@ Error SceneReplicationState::config_del_sync(Node *p_node, MultiplayerSynchroniz
TrackedNode &tobj = _track(oid);
ERR_FAIL_COND_V(tobj.synchronizer != p_sync->get_instance_id(), ERR_INVALID_PARAMETER);
tobj.synchronizer = ObjectID();
- if (path_only_nodes.has(oid)) {
- p_node->disconnect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationState::_untrack));
- _untrack(oid);
- path_only_nodes.erase(oid);
+ synced_nodes.erase(oid);
+ for (KeyValue<int, PeerInfo> &E : peers_info) {
+ E.value.sync_nodes.erase(oid);
}
return OK;
}
-Error SceneReplicationState::peer_add_node(int p_peer, const ObjectID &p_id) {
- if (p_peer) {
- ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
- peers_info[p_peer].known_nodes.insert(p_id);
- } else {
- for (KeyValue<int, PeerInfo> &E : peers_info) {
- E.value.known_nodes.insert(p_id);
- }
- }
+Error SceneReplicationState::peer_add_sync(int p_peer, const ObjectID &p_id) {
+ ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
+ peers_info[p_peer].sync_nodes.insert(p_id);
return OK;
}
-Error SceneReplicationState::peer_del_node(int p_peer, const ObjectID &p_id) {
- if (p_peer) {
- ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
- peers_info[p_peer].known_nodes.erase(p_id);
- } else {
- for (KeyValue<int, PeerInfo> &E : peers_info) {
- E.value.known_nodes.erase(p_id);
- }
- }
+Error SceneReplicationState::peer_del_sync(int p_peer, const ObjectID &p_id) {
+ ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
+ peers_info[p_peer].sync_nodes.erase(p_id);
+ return OK;
+}
+
+const HashSet<ObjectID> SceneReplicationState::get_peer_sync_nodes(int p_peer) {
+ ERR_FAIL_COND_V(!peers_info.has(p_peer), HashSet<ObjectID>());
+ return peers_info[p_peer].sync_nodes;
+}
+
+bool SceneReplicationState::is_peer_sync(int p_peer, const ObjectID &p_id) const {
+ ERR_FAIL_COND_V(!peers_info.has(p_peer), false);
+ return peers_info[p_peer].sync_nodes.has(p_id);
+}
+
+Error SceneReplicationState::peer_add_spawn(int p_peer, const ObjectID &p_id) {
+ ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
+ peers_info[p_peer].spawn_nodes.insert(p_id);
+ return OK;
+}
+
+Error SceneReplicationState::peer_del_spawn(int p_peer, const ObjectID &p_id) {
+ ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
+ peers_info[p_peer].spawn_nodes.erase(p_id);
return OK;
}
+const HashSet<ObjectID> SceneReplicationState::get_peer_spawn_nodes(int p_peer) {
+ ERR_FAIL_COND_V(!peers_info.has(p_peer), HashSet<ObjectID>());
+ return peers_info[p_peer].spawn_nodes;
+}
+
+bool SceneReplicationState::is_peer_spawn(int p_peer, const ObjectID &p_id) const {
+ ERR_FAIL_COND_V(!peers_info.has(p_peer), false);
+ return peers_info[p_peer].spawn_nodes.has(p_id);
+}
+
Node *SceneReplicationState::peer_get_remote(int p_peer, uint32_t p_net_id) {
PeerInfo *info = peers_info.getptr(p_peer);
return info && info->recv_nodes.has(p_net_id) ? Object::cast_to<Node>(ObjectDB::get_instance(info->recv_nodes[p_net_id])) : nullptr;
diff --git a/scene/multiplayer/scene_replication_state.h b/modules/multiplayer/scene_replication_state.h
index 60a6c5d70c..bdff6ae3b7 100644
--- a/scene/multiplayer/scene_replication_state.h
+++ b/modules/multiplayer/scene_replication_state.h
@@ -28,11 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SCENE_REPLICATON_STATE_H
-#define SCENE_REPLICATON_STATE_H
+#ifndef SCENE_REPLICATION_STATE_H
+#define SCENE_REPLICATION_STATE_H
#include "core/object/ref_counted.h"
+#include "multiplayer_spawner.h"
+#include "multiplayer_synchronizer.h"
+
class MultiplayerSpawner;
class MultiplayerSynchronizer;
class Node;
@@ -62,7 +65,8 @@ private:
};
struct PeerInfo {
- HashSet<ObjectID> known_nodes;
+ HashSet<ObjectID> sync_nodes;
+ HashSet<ObjectID> spawn_nodes;
HashMap<uint32_t, ObjectID> recv_nodes;
uint16_t last_sent_sync = 0;
uint16_t last_recv_sync = 0;
@@ -73,7 +77,7 @@ private:
HashMap<ObjectID, TrackedNode> tracked_nodes;
HashMap<int, PeerInfo> peers_info;
HashSet<ObjectID> spawned_nodes;
- HashSet<ObjectID> path_only_nodes;
+ HashSet<ObjectID> synced_nodes;
TrackedNode &_track(const ObjectID &p_id);
void _untrack(const ObjectID &p_id);
@@ -82,7 +86,9 @@ private:
public:
const HashSet<int> get_peers() const { return known_peers; }
const HashSet<ObjectID> &get_spawned_nodes() const { return spawned_nodes; }
- const HashSet<ObjectID> &get_path_only_nodes() const { return path_only_nodes; }
+ bool is_spawned_node(const ObjectID &p_id) const { return spawned_nodes.has(p_id); }
+ const HashSet<ObjectID> &get_synced_nodes() const { return synced_nodes; }
+ bool is_synced_node(const ObjectID &p_id) const { return synced_nodes.has(p_id); }
MultiplayerSynchronizer *get_synchronizer(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_synchronizer() : nullptr; }
MultiplayerSpawner *get_spawner(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_spawner() : nullptr; }
@@ -90,7 +96,6 @@ public:
bool update_last_node_sync(const ObjectID &p_id, uint16_t p_time);
bool update_sync_time(const ObjectID &p_id, uint64_t p_msec);
- const HashSet<ObjectID> get_known_nodes(int p_peer);
uint32_t get_net_id(const ObjectID &p_id) const;
void set_net_id(const ObjectID &p_id, uint32_t p_net_id);
uint32_t ensure_net_id(const ObjectID &p_id);
@@ -104,8 +109,17 @@ public:
Error config_add_sync(Node *p_node, MultiplayerSynchronizer *p_sync);
Error config_del_sync(Node *p_node, MultiplayerSynchronizer *p_sync);
- Error peer_add_node(int p_peer, const ObjectID &p_id);
- Error peer_del_node(int p_peer, const ObjectID &p_id);
+ Error peer_add_sync(int p_peer, const ObjectID &p_id);
+ Error peer_del_sync(int p_peer, const ObjectID &p_id);
+
+ const HashSet<ObjectID> get_peer_sync_nodes(int p_peer);
+ bool is_peer_sync(int p_peer, const ObjectID &p_id) const;
+
+ Error peer_add_spawn(int p_peer, const ObjectID &p_id);
+ Error peer_del_spawn(int p_peer, const ObjectID &p_id);
+
+ const HashSet<ObjectID> get_peer_spawn_nodes(int p_peer);
+ bool is_peer_spawn(int p_peer, const ObjectID &p_id) const;
const HashMap<uint32_t, ObjectID> peer_get_remotes(int p_peer) const;
Node *peer_get_remote(int p_peer, uint32_t p_net_id);
@@ -118,4 +132,4 @@ public:
SceneReplicationState() {}
};
-#endif // SCENE_REPLICATON_STATE_H
+#endif // SCENE_REPLICATION_STATE_H
diff --git a/scene/multiplayer/scene_rpc_interface.cpp b/modules/multiplayer/scene_rpc_interface.cpp
index 84700a82f3..65090b9316 100644
--- a/scene/multiplayer/scene_rpc_interface.cpp
+++ b/modules/multiplayer/scene_rpc_interface.cpp
@@ -28,21 +28,28 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "scene/multiplayer/scene_rpc_interface.h"
+#include "scene_rpc_interface.h"
#include "core/debugger/engine_debugger.h"
#include "core/io/marshalls.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/node.h"
#include "scene/main/window.h"
-MultiplayerRPCInterface *SceneRPCInterface::_create(MultiplayerAPI *p_multiplayer) {
- return memnew(SceneRPCInterface(p_multiplayer));
-}
+#include "scene_multiplayer.h"
-void SceneRPCInterface::make_default() {
- MultiplayerAPI::create_default_rpc_interface = _create;
-}
+// The RPC meta is composed by a single byte that contains (starting from the least significant bit):
+// - `NetworkCommands` in the first four bits.
+// - `NetworkNodeIdCompression` in the next 2 bits.
+// - `NetworkNameIdCompression` in the next 1 bit.
+// - `byte_only_or_no_args` in the next 1 bit.
+#define NODE_ID_COMPRESSION_SHIFT SceneMultiplayer::CMD_FLAG_0_SHIFT
+#define NAME_ID_COMPRESSION_SHIFT SceneMultiplayer::CMD_FLAG_2_SHIFT
+#define BYTE_ONLY_OR_NO_ARGS_SHIFT SceneMultiplayer::CMD_FLAG_3_SHIFT
+
+#define NODE_ID_COMPRESSION_FLAG ((1 << NODE_ID_COMPRESSION_SHIFT) | (1 << (NODE_ID_COMPRESSION_SHIFT + 1)))
+#define NAME_ID_COMPRESSION_FLAG (1 << NAME_ID_COMPRESSION_SHIFT)
+#define BYTE_ONLY_OR_NO_ARGS_FLAG (1 << BYTE_ONLY_OR_NO_ARGS_SHIFT)
#ifdef DEBUG_ENABLED
_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id) {
@@ -67,50 +74,58 @@ int get_packet_len(uint32_t p_node_target, int p_packet_len) {
}
}
-const Multiplayer::RPCConfig _get_rpc_config(const Node *p_node, const StringName &p_method, uint16_t &r_id) {
- const Vector<Multiplayer::RPCConfig> node_config = p_node->get_node_rpc_methods();
- for (int i = 0; i < node_config.size(); i++) {
- if (node_config[i].name == p_method) {
- r_id = ((uint16_t)i) | (1 << 15);
- return node_config[i];
- }
+void SceneRPCInterface::_parse_rpc_config(const Variant &p_config, bool p_for_node, RPCConfigCache &r_cache) {
+ if (p_config.get_type() == Variant::NIL) {
+ return;
}
- if (p_node->get_script_instance()) {
- const Vector<Multiplayer::RPCConfig> script_config = p_node->get_script_instance()->get_rpc_methods();
- for (int i = 0; i < script_config.size(); i++) {
- if (script_config[i].name == p_method) {
- r_id = (uint16_t)i;
- return script_config[i];
- }
+ ERR_FAIL_COND(p_config.get_type() != Variant::DICTIONARY);
+ const Dictionary config = p_config;
+ Array names = config.keys();
+ names.sort(); // Ensure ID order
+ for (int i = 0; i < names.size(); i++) {
+ ERR_CONTINUE(names[i].get_type() != Variant::STRING);
+ String name = names[i].operator String();
+ ERR_CONTINUE(config[name].get_type() != Variant::DICTIONARY);
+ ERR_CONTINUE(!config[name].operator Dictionary().has("rpc_mode"));
+ Dictionary dict = config[name];
+ RPCConfig cfg;
+ cfg.name = name;
+ cfg.rpc_mode = ((MultiplayerAPI::RPCMode)dict.get("rpc_mode", MultiplayerAPI::RPC_MODE_AUTHORITY).operator int());
+ cfg.transfer_mode = ((MultiplayerPeer::TransferMode)dict.get("transfer_mode", MultiplayerPeer::TRANSFER_MODE_RELIABLE).operator int());
+ cfg.call_local = dict.get("call_local", false).operator bool();
+ cfg.channel = dict.get("channel", 0).operator int();
+ uint16_t id = ((uint16_t)i);
+ if (p_for_node) {
+ id |= (1 << 15);
}
+ r_cache.configs[id] = cfg;
+ r_cache.ids[name] = id;
}
- return Multiplayer::RPCConfig();
}
-const Multiplayer::RPCConfig _get_rpc_config_by_id(Node *p_node, uint16_t p_id) {
- Vector<Multiplayer::RPCConfig> config;
- uint16_t id = p_id;
- if (id & (1 << 15)) {
- id = id & ~(1 << 15);
- config = p_node->get_node_rpc_methods();
- } else if (p_node->get_script_instance()) {
- config = p_node->get_script_instance()->get_rpc_methods();
+const SceneRPCInterface::RPCConfigCache &SceneRPCInterface::_get_node_config(const Node *p_node) {
+ const ObjectID oid = p_node->get_instance_id();
+ if (rpc_cache.has(oid)) {
+ return rpc_cache[oid];
}
- if (id < config.size()) {
- return config[id];
+ RPCConfigCache cache;
+ _parse_rpc_config(p_node->get_node_rpc_config(), true, cache);
+ if (p_node->get_script_instance()) {
+ _parse_rpc_config(p_node->get_script_instance()->get_rpc_config(), false, cache);
}
- return Multiplayer::RPCConfig();
+ rpc_cache[oid] = cache;
+ return rpc_cache[oid];
}
-_FORCE_INLINE_ bool _can_call_mode(Node *p_node, Multiplayer::RPCMode mode, int p_remote_id) {
+_FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, int p_remote_id) {
switch (mode) {
- case Multiplayer::RPC_MODE_DISABLED: {
+ case MultiplayerAPI::RPC_MODE_DISABLED: {
return false;
} break;
- case Multiplayer::RPC_MODE_ANY_PEER: {
+ case MultiplayerAPI::RPC_MODE_ANY_PEER: {
return true;
} break;
- case Multiplayer::RPC_MODE_AUTHORITY: {
+ case MultiplayerAPI::RPC_MODE_AUTHORITY: {
return !p_node->is_multiplayer_authority() && p_remote_id == p_node->get_multiplayer_authority();
} break;
}
@@ -118,19 +133,13 @@ _FORCE_INLINE_ bool _can_call_mode(Node *p_node, Multiplayer::RPCMode mode, int
return false;
}
-String SceneRPCInterface::get_rpc_md5(const Object *p_obj) const {
+String SceneRPCInterface::get_rpc_md5(const Object *p_obj) {
const Node *node = Object::cast_to<Node>(p_obj);
ERR_FAIL_COND_V(!node, "");
+ const RPCConfigCache cache = _get_node_config(node);
String rpc_list;
- const Vector<Multiplayer::RPCConfig> node_config = node->get_node_rpc_methods();
- for (int i = 0; i < node_config.size(); i++) {
- rpc_list += String(node_config[i].name);
- }
- if (node->get_script_instance()) {
- const Vector<Multiplayer::RPCConfig> script_config = node->get_script_instance()->get_rpc_methods();
- for (int i = 0; i < script_config.size(); i++) {
- rpc_list += String(script_config[i].name);
- }
+ for (const KeyValue<uint16_t, RPCConfig> &config : cache.configs) {
+ rpc_list += String(config.value.name);
}
return rpc_list.md5_text();
}
@@ -159,7 +168,7 @@ Node *SceneRPCInterface::_process_get_node(int p_from, const uint8_t *p_packet,
return node;
} else {
// Use cached path.
- return Object::cast_to<Node>(multiplayer->get_cached_object(p_from, p_node_target));
+ return Object::cast_to<Node>(multiplayer->get_path_cache()->get_cached_object(p_from, p_node_target));
}
}
@@ -240,8 +249,9 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
ERR_FAIL_COND_MSG(p_offset > p_packet_len, "Invalid packet received. Size too small.");
// Check that remote can call the RPC on this node.
- const Multiplayer::RPCConfig config = _get_rpc_config_by_id(p_node, p_rpc_method_id);
- ERR_FAIL_COND(config.name == StringName());
+ const RPCConfigCache &cache_config = _get_node_config(p_node);
+ ERR_FAIL_COND(!cache_config.configs.has(p_rpc_method_id));
+ const RPCConfig &config = cache_config.configs[p_rpc_method_id];
bool can_call = _can_call_mode(p_node, config.rpc_mode, p_from);
ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(config.name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)config.rpc_mode) + ", authority is " + itos(p_node->get_multiplayer_authority()) + ".");
@@ -286,7 +296,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
}
}
-void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const Multiplayer::RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
+void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
ERR_FAIL_COND_MSG(peer.is_null(), "Attempt to call RPC without active multiplayer peer.");
@@ -297,17 +307,14 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
ERR_FAIL_COND_MSG(p_argcount > 255, "Too many arguments (>255).");
if (p_to != 0 && !multiplayer->get_connected_peers().has(ABS(p_to))) {
- ERR_FAIL_COND_MSG(p_to == peer->get_unique_id(), "Attempt to call RPC on yourself! Peer unique ID: " + itos(peer->get_unique_id()) + ".");
+ ERR_FAIL_COND_MSG(p_to == multiplayer->get_unique_id(), "Attempt to call RPC on yourself! Peer unique ID: " + itos(multiplayer->get_unique_id()) + ".");
ERR_FAIL_MSG("Attempt to call RPC with unknown peer ID: " + itos(p_to) + ".");
}
- NodePath from_path = multiplayer->get_root_path().rel_path_to(p_from->get_path());
- ERR_FAIL_COND_MSG(from_path.is_empty(), "Unable to send RPC. Relative path is empty. THIS IS LIKELY A BUG IN THE ENGINE!");
-
// See if all peers have cached path (if so, call can be fast).
int psc_id;
- const bool has_all_peers = multiplayer->send_object_cache(p_from, from_path, p_to, psc_id);
+ const bool has_all_peers = multiplayer->get_path_cache()->send_object_cache(p_from, p_to, psc_id);
// Create base packet, lots of hardcode because it must be tight.
@@ -318,7 +325,7 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
packet_cache.resize(m_amount);
// Encode meta.
- uint8_t command_type = MultiplayerAPI::NETWORK_COMMAND_REMOTE_CALL;
+ uint8_t command_type = SceneMultiplayer::NETWORK_COMMAND_REMOTE_CALL;
uint8_t node_id_compression = UINT8_MAX;
uint8_t name_id_compression = UINT8_MAX;
bool byte_only_or_no_args = false;
@@ -414,6 +421,7 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
// Not all verified path, so send one by one.
// Append path at the end, since we will need it for some packets.
+ NodePath from_path = multiplayer->get_root_path().rel_path_to(p_from->get_path());
CharString pname = String(from_path).utf8();
int path_len = encode_cstring(pname.get_data(), nullptr);
MAKE_ROOM(ofs + path_len);
@@ -428,7 +436,7 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
continue; // Continue, not for this peer.
}
- bool confirmed = multiplayer->is_cache_confirmed(from_path, P);
+ bool confirmed = multiplayer->get_path_cache()->is_cache_confirmed(from_path, P);
peer->set_target_peer(P); // To this one specifically.
@@ -445,22 +453,25 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
}
}
-void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+Error SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
- ERR_FAIL_COND_MSG(!peer.is_valid(), "Trying to call an RPC while no multiplayer peer is active.");
+ ERR_FAIL_COND_V_MSG(!peer.is_valid(), ERR_UNCONFIGURED, "Trying to call an RPC while no multiplayer peer is active.");
Node *node = Object::cast_to<Node>(p_obj);
- ERR_FAIL_COND(!node);
- ERR_FAIL_COND_MSG(!node->is_inside_tree(), "Trying to call an RPC on a node which is not inside SceneTree.");
- ERR_FAIL_COND_MSG(peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, "Trying to call an RPC via a multiplayer peer which is not connected.");
+ ERR_FAIL_COND_V_MSG(!node || !node->is_inside_tree(), ERR_INVALID_PARAMETER, "The object must be a valid Node inside the SceneTree");
+ ERR_FAIL_COND_V_MSG(peer->get_connection_status() != MultiplayerPeer::CONNECTION_CONNECTED, ERR_CONNECTION_ERROR, "Trying to call an RPC via a multiplayer peer which is not connected.");
- int node_id = peer->get_unique_id();
+ int caller_id = multiplayer->get_unique_id();
bool call_local_native = false;
bool call_local_script = false;
- uint16_t rpc_id = UINT16_MAX;
- const Multiplayer::RPCConfig config = _get_rpc_config(node, p_method, rpc_id);
- ERR_FAIL_COND_MSG(config.name == StringName(),
+ const RPCConfigCache &config_cache = _get_node_config(node);
+ uint16_t rpc_id = config_cache.ids.has(p_method) ? config_cache.ids[p_method] : UINT16_MAX;
+ ERR_FAIL_COND_V_MSG(rpc_id == UINT16_MAX, ERR_INVALID_PARAMETER,
vformat("Unable to get the RPC configuration for the function \"%s\" at path: \"%s\". This happens when the method is missing or not marked for RPCs in the local script.", p_method, node->get_path()));
- if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
+ const RPCConfig &config = config_cache.configs[rpc_id];
+
+ ERR_FAIL_COND_V_MSG(p_peer_id == caller_id && !config.call_local, ERR_INVALID_PARAMETER, "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
+
+ if (p_peer_id == 0 || p_peer_id == caller_id || (p_peer_id < 0 && p_peer_id != -caller_id)) {
if (rpc_id & (1 << 15)) {
call_local_native = config.call_local;
} else {
@@ -468,7 +479,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
}
}
- if (p_peer_id != node_id) {
+ if (p_peer_id != caller_id) {
#ifdef DEBUG_ENABLED
_profile_node_data("rpc_out", node->get_instance_id());
#endif
@@ -479,7 +490,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
if (call_local_native) {
Callable::CallError ce;
- multiplayer->set_remote_sender_override(peer->get_unique_id());
+ multiplayer->set_remote_sender_override(multiplayer->get_unique_id());
node->callp(p_method, p_arg, p_argcount, ce);
multiplayer->set_remote_sender_override(0);
@@ -487,7 +498,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
String error = Variant::get_call_error_text(node, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in local call: - " + error + ".";
ERR_PRINT(error);
- return;
+ return FAILED;
}
}
@@ -495,7 +506,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
Callable::CallError ce;
ce.error = Callable::CallError::CALL_OK;
- multiplayer->set_remote_sender_override(peer->get_unique_id());
+ multiplayer->set_remote_sender_override(multiplayer->get_unique_id());
node->get_script_instance()->callp(p_method, p_arg, p_argcount, ce);
multiplayer->set_remote_sender_override(0);
@@ -503,9 +514,8 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
String error = Variant::get_call_error_text(node, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in script local call: - " + error + ".";
ERR_PRINT(error);
- return;
+ return FAILED;
}
}
-
- ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.call_local, "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
+ return OK;
}
diff --git a/scene/multiplayer/scene_rpc_interface.h b/modules/multiplayer/scene_rpc_interface.h
index 86e1d0d280..aa9be525a2 100644
--- a/scene/multiplayer/scene_rpc_interface.h
+++ b/modules/multiplayer/scene_rpc_interface.h
@@ -31,13 +31,40 @@
#ifndef SCENE_RPC_INTERFACE_H
#define SCENE_RPC_INTERFACE_H
-#include "core/multiplayer/multiplayer.h"
-#include "core/multiplayer/multiplayer_api.h"
+#include "core/object/ref_counted.h"
+#include "scene/main/multiplayer_api.h"
-class SceneRPCInterface : public MultiplayerRPCInterface {
- GDCLASS(SceneRPCInterface, MultiplayerRPCInterface);
+class SceneMultiplayer;
+class Node;
+
+class SceneRPCInterface : public RefCounted {
+ GDCLASS(SceneRPCInterface, RefCounted);
private:
+ struct RPCConfig {
+ StringName name;
+ MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
+ bool call_local = false;
+ MultiplayerPeer::TransferMode transfer_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ int channel = 0;
+
+ bool operator==(RPCConfig const &p_other) const {
+ return name == p_other.name;
+ }
+ };
+
+ struct RPCConfigCache {
+ HashMap<uint16_t, RPCConfig> configs;
+ HashMap<StringName, uint16_t> ids;
+ };
+
+ struct SortRPCConfig {
+ StringName::AlphCompare compare;
+ bool operator()(const RPCConfig &p_a, const RPCConfig &p_b) const {
+ return compare(p_a.name, p_b.name);
+ }
+ };
+
enum NetworkNodeIdCompression {
NETWORK_NODE_ID_COMPRESSION_8 = 0,
NETWORK_NODE_ID_COMPRESSION_16,
@@ -49,43 +76,27 @@ private:
NETWORK_NAME_ID_COMPRESSION_16,
};
- // The RPC meta is composed by a single byte that contains (starting from the least significant bit):
- // - `NetworkCommands` in the first four bits.
- // - `NetworkNodeIdCompression` in the next 2 bits.
- // - `NetworkNameIdCompression` in the next 1 bit.
- // - `byte_only_or_no_args` in the next 1 bit.
- enum {
- NODE_ID_COMPRESSION_SHIFT = MultiplayerAPI::CMD_FLAG_0_SHIFT, // 2 bits for this.
- NAME_ID_COMPRESSION_SHIFT = MultiplayerAPI::CMD_FLAG_2_SHIFT,
- BYTE_ONLY_OR_NO_ARGS_SHIFT = MultiplayerAPI::CMD_FLAG_3_SHIFT,
- };
-
- enum {
- NODE_ID_COMPRESSION_FLAG = (1 << NODE_ID_COMPRESSION_SHIFT) | (1 << (NODE_ID_COMPRESSION_SHIFT + 1)), // 2 bits for this.
- NAME_ID_COMPRESSION_FLAG = (1 << NAME_ID_COMPRESSION_SHIFT),
- BYTE_ONLY_OR_NO_ARGS_FLAG = (1 << BYTE_ONLY_OR_NO_ARGS_SHIFT),
- };
-
- MultiplayerAPI *multiplayer = nullptr;
+ SceneMultiplayer *multiplayer = nullptr;
Vector<uint8_t> packet_cache;
-protected:
- static MultiplayerRPCInterface *_create(MultiplayerAPI *p_multiplayer);
+ HashMap<ObjectID, RPCConfigCache> rpc_cache;
+protected:
_FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id);
void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
- void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const Multiplayer::RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
+ void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
Node *_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len);
-public:
- static void make_default();
+ void _parse_rpc_config(const Variant &p_config, bool p_for_node, RPCConfigCache &r_cache);
+ const RPCConfigCache &_get_node_config(const Node *p_node);
- virtual void rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override;
- virtual void process_rpc(int p_from, const uint8_t *p_packet, int p_packet_len) override;
- virtual String get_rpc_md5(const Object *p_obj) const override;
+public:
+ Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
+ void process_rpc(int p_from, const uint8_t *p_packet, int p_packet_len);
+ String get_rpc_md5(const Object *p_obj);
- SceneRPCInterface(MultiplayerAPI *p_multiplayer) { multiplayer = p_multiplayer; }
+ SceneRPCInterface(SceneMultiplayer *p_multiplayer) { multiplayer = p_multiplayer; }
};
#endif // SCENE_RPC_INTERFACE_H
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index bcbc721dbb..2cdb5b7cb4 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -249,8 +249,10 @@ Array GodotNavigationServer::map_get_regions(RID p_map) const {
Array regions_rids;
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, regions_rids);
- for (NavRegion *region : map->get_regions()) {
- regions_rids.push_back(region->get_self());
+ const LocalVector<NavRegion *> regions = map->get_regions();
+ regions_rids.resize(regions.size());
+ for (uint32_t i = 0; i < regions.size(); i++) {
+ regions_rids[i] = regions[i]->get_self();
}
return regions_rids;
}
@@ -259,8 +261,10 @@ Array GodotNavigationServer::map_get_agents(RID p_map) const {
Array agents_rids;
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, agents_rids);
- for (RvoAgent *agent : map->get_agents()) {
- agents_rids.push_back(agent->get_self());
+ const LocalVector<RvoAgent *> agents = map->get_agents();
+ agents_rids.resize(agents.size());
+ for (uint32_t i = 0; i < agents.size(); i++) {
+ agents_rids[i] = agents[i]->get_self();
}
return agents_rids;
}
@@ -539,15 +543,15 @@ COMMAND_1(free, RID, p_object) {
NavMap *map = map_owner.get_or_null(p_object);
// Removes any assigned region
- std::vector<NavRegion *> regions = map->get_regions();
- for (size_t i(0); i < regions.size(); i++) {
+ LocalVector<NavRegion *> regions = map->get_regions();
+ for (uint32_t i = 0; i < regions.size(); i++) {
map->remove_region(regions[i]);
regions[i]->set_map(nullptr);
}
// Remove any assigned agent
- std::vector<RvoAgent *> agents = map->get_agents();
- for (size_t i(0); i < agents.size(); i++) {
+ LocalVector<RvoAgent *> agents = map->get_agents();
+ for (uint32_t i = 0; i < agents.size(); i++) {
map->remove_agent(agents[i]);
agents[i]->set_map(nullptr);
}
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 8e7e99888c..da1f8cba0b 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -69,7 +69,7 @@ class GodotNavigationServer : public NavigationServer3D {
/// Mutex used to make any operation threadsafe.
Mutex operations_mutex;
- std::vector<SetCommand *> commands;
+ LocalVector<SetCommand *> commands;
mutable RID_Owner<NavMap> map_owner;
mutable RID_Owner<NavRegion> region_owner;
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 17d6e0a0a1..49029b5513 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -30,9 +30,9 @@
#include "nav_map.h"
+#include "core/object/worker_thread_pool.h"
#include "nav_region.h"
#include "rvo_agent.h"
-
#include <algorithm>
#define THREE_POINTS_CROSS_PRODUCT(m_a, m_b, m_c) (((m_c) - (m_a)).cross((m_b) - (m_a)))
@@ -117,7 +117,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
}
// List of all reachable navigation polys.
- std::vector<gd::NavigationPoly> navigation_polys;
+ LocalVector<gd::NavigationPoly> navigation_polys;
navigation_polys.reserve(polygons.size() * 0.75);
// Add the start polygon to the reachable navigation polygons.
@@ -170,20 +170,18 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, pathway);
const float new_distance = (least_cost_poly->entry.distance_to(new_entry) * region_travel_cost) + region_enter_cost + least_cost_poly->traveled_distance;
- const std::vector<gd::NavigationPoly>::iterator it = std::find(
- navigation_polys.begin(),
- navigation_polys.end(),
- gd::NavigationPoly(connection.polygon));
+ int64_t already_visited_polygon_index = navigation_polys.find(gd::NavigationPoly(connection.polygon));
- if (it != navigation_polys.end()) {
+ if (already_visited_polygon_index != -1) {
// Polygon already visited, check if we can reduce the travel cost.
- if (new_distance < it->traveled_distance) {
- it->back_navigation_poly_id = least_cost_id;
- it->back_navigation_edge = connection.edge;
- it->back_navigation_edge_pathway_start = connection.pathway_start;
- it->back_navigation_edge_pathway_end = connection.pathway_end;
- it->traveled_distance = new_distance;
- it->entry = new_entry;
+ gd::NavigationPoly &avp = navigation_polys[already_visited_polygon_index];
+ if (new_distance < avp.traveled_distance) {
+ avp.back_navigation_poly_id = least_cost_id;
+ avp.back_navigation_edge = connection.edge;
+ avp.back_navigation_edge_pathway_start = connection.pathway_start;
+ avp.back_navigation_edge_pathway_end = connection.pathway_end;
+ avp.traveled_distance = new_distance;
+ avp.entry = new_entry;
}
} else {
// Add the neighbour polygon to the reachable ones.
@@ -470,15 +468,15 @@ void NavMap::add_region(NavRegion *p_region) {
}
void NavMap::remove_region(NavRegion *p_region) {
- const std::vector<NavRegion *>::iterator it = std::find(regions.begin(), regions.end(), p_region);
- if (it != regions.end()) {
- regions.erase(it);
+ int64_t region_index = regions.find(p_region);
+ if (region_index != -1) {
+ regions.remove_at_unordered(region_index);
regenerate_links = true;
}
}
bool NavMap::has_agent(RvoAgent *agent) const {
- return std::find(agents.begin(), agents.end(), agent) != agents.end();
+ return (agents.find(agent) != -1);
}
void NavMap::add_agent(RvoAgent *agent) {
@@ -490,15 +488,15 @@ void NavMap::add_agent(RvoAgent *agent) {
void NavMap::remove_agent(RvoAgent *agent) {
remove_agent_as_controlled(agent);
- const std::vector<RvoAgent *>::iterator it = std::find(agents.begin(), agents.end(), agent);
- if (it != agents.end()) {
- agents.erase(it);
+ int64_t agent_index = agents.find(agent);
+ if (agent_index != -1) {
+ agents.remove_at_unordered(agent_index);
agents_dirty = true;
}
}
void NavMap::set_agent_as_controlled(RvoAgent *agent) {
- const bool exist = std::find(controlled_agents.begin(), controlled_agents.end(), agent) != controlled_agents.end();
+ const bool exist = (controlled_agents.find(agent) != -1);
if (!exist) {
ERR_FAIL_COND(!has_agent(agent));
controlled_agents.push_back(agent);
@@ -506,22 +504,23 @@ void NavMap::set_agent_as_controlled(RvoAgent *agent) {
}
void NavMap::remove_agent_as_controlled(RvoAgent *agent) {
- const std::vector<RvoAgent *>::iterator it = std::find(controlled_agents.begin(), controlled_agents.end(), agent);
- if (it != controlled_agents.end()) {
- controlled_agents.erase(it);
+ int64_t active_avoidance_agent_index = controlled_agents.find(agent);
+ if (active_avoidance_agent_index != -1) {
+ controlled_agents.remove_at_unordered(active_avoidance_agent_index);
+ agents_dirty = true;
}
}
void NavMap::sync() {
// Check if we need to update the links.
if (regenerate_polygons) {
- for (size_t r(0); r < regions.size(); r++) {
+ for (uint32_t r = 0; r < regions.size(); r++) {
regions[r]->scratch_polygons();
}
regenerate_links = true;
}
- for (size_t r(0); r < regions.size(); r++) {
+ for (uint32_t r = 0; r < regions.size(); r++) {
if (regions[r]->sync()) {
regenerate_links = true;
}
@@ -529,33 +528,33 @@ void NavMap::sync() {
if (regenerate_links) {
// Remove regions connections.
- for (size_t r(0); r < regions.size(); r++) {
+ for (uint32_t r = 0; r < regions.size(); r++) {
regions[r]->get_connections().clear();
}
// Resize the polygon count.
int count = 0;
- for (size_t r(0); r < regions.size(); r++) {
+ for (uint32_t r = 0; r < regions.size(); r++) {
count += regions[r]->get_polygons().size();
}
polygons.resize(count);
// Copy all region polygons in the map.
count = 0;
- for (size_t r(0); r < regions.size(); r++) {
- std::copy(
- regions[r]->get_polygons().data(),
- regions[r]->get_polygons().data() + regions[r]->get_polygons().size(),
- polygons.begin() + count);
+ for (uint32_t r = 0; r < regions.size(); r++) {
+ const LocalVector<gd::Polygon> &polygons_source = regions[r]->get_polygons();
+ for (uint32_t n = 0; n < polygons_source.size(); n++) {
+ polygons[count + n] = polygons_source[n];
+ }
count += regions[r]->get_polygons().size();
}
// Group all edges per key.
HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey> connections;
- for (size_t poly_id(0); poly_id < polygons.size(); poly_id++) {
+ for (uint32_t poly_id = 0; poly_id < polygons.size(); poly_id++) {
gd::Polygon &poly(polygons[poly_id]);
- for (size_t p(0); p < poly.points.size(); p++) {
+ for (uint32_t p = 0; p < poly.points.size(); p++) {
int next_point = (p + 1) % poly.points.size();
gd::EdgeKey ek(poly.points[p].key, poly.points[next_point].key);
@@ -662,6 +661,7 @@ void NavMap::sync() {
// Update agents tree.
if (agents_dirty) {
+ // cannot use LocalVector here as RVO library expects std::vector to build KdTree
std::vector<RVO::Agent *> raw_agents;
raw_agents.reserve(agents.size());
for (size_t i(0); i < agents.size(); i++) {
@@ -683,14 +683,8 @@ void NavMap::compute_single_step(uint32_t index, RvoAgent **agent) {
void NavMap::step(real_t p_deltatime) {
deltatime = p_deltatime;
if (controlled_agents.size() > 0) {
- if (step_work_pool.get_thread_count() == 0) {
- step_work_pool.init();
- }
- step_work_pool.do_work(
- controlled_agents.size(),
- this,
- &NavMap::compute_single_step,
- controlled_agents.data());
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &NavMap::compute_single_step, controlled_agents.ptr(), controlled_agents.size(), -1, true, SNAME("NavigationMapAgents"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
}
}
@@ -700,7 +694,7 @@ void NavMap::dispatch_callbacks() {
}
}
-void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const {
+void NavMap::clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const {
Vector3 from = path[path.size() - 1];
if (from.is_equal_approx(p_to_point)) {
@@ -736,5 +730,4 @@ NavMap::NavMap() {
}
NavMap::~NavMap() {
- step_work_pool.finish();
}
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index 2036dbecd7..e50a1afbe9 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -34,8 +34,8 @@
#include "nav_rid.h"
#include "core/math/math_defs.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/rb_map.h"
-#include "core/templates/thread_work_pool.h"
#include "nav_utils.h"
#include <KdTree.h>
@@ -58,10 +58,10 @@ class NavMap : public NavRid {
bool regenerate_polygons = true;
bool regenerate_links = true;
- std::vector<NavRegion *> regions;
+ LocalVector<NavRegion *> regions;
/// Map polygons
- std::vector<gd::Polygon> polygons;
+ LocalVector<gd::Polygon> polygons;
/// Rvo world
RVO::KdTree rvo;
@@ -70,10 +70,10 @@ class NavMap : public NavRid {
bool agents_dirty = false;
/// All the Agents (even the controlled one)
- std::vector<RvoAgent *> agents;
+ LocalVector<RvoAgent *> agents;
/// Controlled agents
- std::vector<RvoAgent *> controlled_agents;
+ LocalVector<RvoAgent *> controlled_agents;
/// Physics delta time
real_t deltatime = 0.0;
@@ -81,9 +81,6 @@ class NavMap : public NavRid {
/// Change the id each time the map is updated.
uint32_t map_update_id = 0;
- /// Pooled threads for computing steps
- ThreadWorkPool step_work_pool;
-
public:
NavMap();
~NavMap();
@@ -114,14 +111,14 @@ public:
void add_region(NavRegion *p_region);
void remove_region(NavRegion *p_region);
- const std::vector<NavRegion *> &get_regions() const {
+ const LocalVector<NavRegion *> &get_regions() const {
return regions;
}
bool has_agent(RvoAgent *agent) const;
void add_agent(RvoAgent *agent);
void remove_agent(RvoAgent *agent);
- const std::vector<RvoAgent *> &get_agents() const {
+ const LocalVector<RvoAgent *> &get_agents() const {
return agents;
}
@@ -138,7 +135,7 @@ public:
private:
void compute_single_step(uint32_t index, RvoAgent **agent);
- void clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const;
+ void clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const;
};
#endif // NAV_MAP_H
diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h
index 484856ae36..c9d2d80f6c 100644
--- a/modules/navigation/nav_region.h
+++ b/modules/navigation/nav_region.h
@@ -53,7 +53,7 @@ class NavRegion : public NavRid {
bool polygons_dirty = true;
/// Cache
- std::vector<gd::Polygon> polygons;
+ LocalVector<gd::Polygon> polygons;
public:
NavRegion() {}
@@ -93,7 +93,7 @@ public:
Vector3 get_connection_pathway_start(int p_connection_id) const;
Vector3 get_connection_pathway_end(int p_connection_id) const;
- std::vector<gd::Polygon> const &get_polygons() const {
+ LocalVector<gd::Polygon> const &get_polygons() const {
return polygons;
}
diff --git a/modules/navigation/nav_utils.h b/modules/navigation/nav_utils.h
index a9f4e0e2fc..47f04b6a75 100644
--- a/modules/navigation/nav_utils.h
+++ b/modules/navigation/nav_utils.h
@@ -34,7 +34,7 @@
#include "core/math/vector3.h"
#include "core/templates/hash_map.h"
#include "core/templates/hashfuncs.h"
-#include "core/templates/vector.h"
+#include "core/templates/local_vector.h"
#include <vector>
class NavRegion;
@@ -96,13 +96,13 @@ struct Polygon {
NavRegion *owner = nullptr;
/// The points of this `Polygon`
- std::vector<Point> points;
+ LocalVector<Point> points;
/// Are the points clockwise ?
bool clockwise;
/// The edges of this `Polygon`
- std::vector<Edge> edges;
+ LocalVector<Edge> edges;
/// The center of this `Polygon`
Vector3 center;
@@ -124,6 +124,8 @@ struct NavigationPoly {
/// The distance to the destination.
float traveled_distance = 0.0;
+ NavigationPoly() { poly = nullptr; }
+
NavigationPoly(const Polygon *p_poly) :
poly(p_poly) {}
diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp
index 32c3f0aad4..27a86f45b5 100644
--- a/modules/noise/editor/noise_editor_plugin.cpp
+++ b/modules/noise/editor/noise_editor_plugin.cpp
@@ -54,7 +54,7 @@ public:
set_custom_minimum_size(Size2(0, EDSCALE * PREVIEW_HEIGHT));
_texture_rect = memnew(TextureRect);
- _texture_rect->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ _texture_rect->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
_texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_COVERED);
add_child(_texture_rect);
diff --git a/modules/ogg/config.py b/modules/ogg/config.py
index 5a417ba8dd..f7ec4de6be 100644
--- a/modules/ogg/config.py
+++ b/modules/ogg/config.py
@@ -8,8 +8,8 @@ def configure(env):
def get_doc_classes():
return [
- "OGGPacketSequence",
- "OGGPacketSequencePlayback",
+ "OggPacketSequence",
+ "OggPacketSequencePlayback",
]
diff --git a/modules/ogg/doc_classes/OGGPacketSequence.xml b/modules/ogg/doc_classes/OggPacketSequence.xml
index bff3691ce0..d3bd4455d8 100644
--- a/modules/ogg/doc_classes/OGGPacketSequence.xml
+++ b/modules/ogg/doc_classes/OggPacketSequence.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OGGPacketSequence" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+<class name="OggPacketSequence" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
- A sequence of OGG packets.
+ A sequence of Ogg packets.
</brief_description>
<description>
- A sequence of OGG packets.
+ A sequence of Ogg packets.
</description>
<tutorials>
</tutorials>
@@ -21,7 +21,7 @@
Contains the granule positions for each page in this packet sequence.
</member>
<member name="packet_data" type="Array" setter="set_packet_data" getter="get_packet_data" default="[]">
- Contains the raw packets that make up this OGGPacketSequence.
+ Contains the raw packets that make up this OggPacketSequence.
</member>
<member name="sampling_rate" type="float" setter="set_sampling_rate" getter="get_sampling_rate" default="0.0">
Holds sample rate information about this sequence. Must be set by another class that actually understands the codec.
diff --git a/modules/ogg/doc_classes/OGGPacketSequencePlayback.xml b/modules/ogg/doc_classes/OggPacketSequencePlayback.xml
index 11fc1f4cb6..5c0d75278b 100644
--- a/modules/ogg/doc_classes/OGGPacketSequencePlayback.xml
+++ b/modules/ogg/doc_classes/OggPacketSequencePlayback.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OGGPacketSequencePlayback" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+<class name="OggPacketSequencePlayback" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>
diff --git a/modules/ogg/ogg_packet_sequence.cpp b/modules/ogg/ogg_packet_sequence.cpp
index da52ecfdd5..de8bf4a087 100644
--- a/modules/ogg/ogg_packet_sequence.cpp
+++ b/modules/ogg/ogg_packet_sequence.cpp
@@ -31,7 +31,7 @@
#include "ogg_packet_sequence.h"
#include "core/variant/typed_array.h"
-void OGGPacketSequence::push_page(int64_t p_granule_pos, const Vector<PackedByteArray> &p_data) {
+void OggPacketSequence::push_page(int64_t p_granule_pos, const Vector<PackedByteArray> &p_data) {
Vector<PackedByteArray> data_stored;
for (int i = 0; i < p_data.size(); i++) {
data_stored.push_back(p_data[i]);
@@ -41,7 +41,7 @@ void OGGPacketSequence::push_page(int64_t p_granule_pos, const Vector<PackedByte
data_version++;
}
-void OGGPacketSequence::set_packet_data(const Array &p_data) {
+void OggPacketSequence::set_packet_data(const Array &p_data) {
data_version++; // Update the data version so old playbacks know that they can't rely on us anymore.
page_data.clear();
for (int page_idx = 0; page_idx < p_data.size(); page_idx++) {
@@ -54,7 +54,7 @@ void OGGPacketSequence::set_packet_data(const Array &p_data) {
}
}
-Array OGGPacketSequence::get_packet_data() const {
+Array OggPacketSequence::get_packet_data() const {
Array ret;
for (const Vector<PackedByteArray> &page : page_data) {
Array page_variant;
@@ -66,7 +66,7 @@ Array OGGPacketSequence::get_packet_data() const {
return ret;
}
-void OGGPacketSequence::set_packet_granule_positions(const Array &p_granule_positions) {
+void OggPacketSequence::set_packet_granule_positions(const Array &p_granule_positions) {
data_version++; // Update the data version so old playbacks know that they can't rely on us anymore.
page_granule_positions.clear();
for (int page_idx = 0; page_idx < p_granule_positions.size(); page_idx++) {
@@ -75,7 +75,7 @@ void OGGPacketSequence::set_packet_granule_positions(const Array &p_granule_posi
}
}
-Array OGGPacketSequence::get_packet_granule_positions() const {
+Array OggPacketSequence::get_packet_granule_positions() const {
Array ret;
for (int64_t granule_pos : page_granule_positions) {
ret.push_back(granule_pos);
@@ -83,22 +83,22 @@ Array OGGPacketSequence::get_packet_granule_positions() const {
return ret;
}
-void OGGPacketSequence::set_sampling_rate(float p_sampling_rate) {
+void OggPacketSequence::set_sampling_rate(float p_sampling_rate) {
sampling_rate = p_sampling_rate;
}
-float OGGPacketSequence::get_sampling_rate() const {
+float OggPacketSequence::get_sampling_rate() const {
return sampling_rate;
}
-int64_t OGGPacketSequence::get_final_granule_pos() const {
+int64_t OggPacketSequence::get_final_granule_pos() const {
if (!page_granule_positions.is_empty()) {
return page_granule_positions[page_granule_positions.size() - 1];
}
return -1;
}
-float OGGPacketSequence::get_length() const {
+float OggPacketSequence::get_length() const {
int64_t granule_pos = get_final_granule_pos();
if (granule_pos < 0) {
return 0;
@@ -106,33 +106,33 @@ float OGGPacketSequence::get_length() const {
return granule_pos / sampling_rate;
}
-Ref<OGGPacketSequencePlayback> OGGPacketSequence::instance_playback() {
- Ref<OGGPacketSequencePlayback> playback;
+Ref<OggPacketSequencePlayback> OggPacketSequence::instantiate_playback() {
+ Ref<OggPacketSequencePlayback> playback;
playback.instantiate();
- playback->ogg_packet_sequence = Ref<OGGPacketSequence>(this);
+ playback->ogg_packet_sequence = Ref<OggPacketSequence>(this);
playback->data_version = data_version;
return playback;
}
-void OGGPacketSequence::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_packet_data", "packet_data"), &OGGPacketSequence::set_packet_data);
- ClassDB::bind_method(D_METHOD("get_packet_data"), &OGGPacketSequence::get_packet_data);
+void OggPacketSequence::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_packet_data", "packet_data"), &OggPacketSequence::set_packet_data);
+ ClassDB::bind_method(D_METHOD("get_packet_data"), &OggPacketSequence::get_packet_data);
- ClassDB::bind_method(D_METHOD("set_packet_granule_positions", "granule_positions"), &OGGPacketSequence::set_packet_granule_positions);
- ClassDB::bind_method(D_METHOD("get_packet_granule_positions"), &OGGPacketSequence::get_packet_granule_positions);
+ ClassDB::bind_method(D_METHOD("set_packet_granule_positions", "granule_positions"), &OggPacketSequence::set_packet_granule_positions);
+ ClassDB::bind_method(D_METHOD("get_packet_granule_positions"), &OggPacketSequence::get_packet_granule_positions);
- ClassDB::bind_method(D_METHOD("set_sampling_rate", "sampling_rate"), &OGGPacketSequence::set_sampling_rate);
- ClassDB::bind_method(D_METHOD("get_sampling_rate"), &OGGPacketSequence::get_sampling_rate);
+ ClassDB::bind_method(D_METHOD("set_sampling_rate", "sampling_rate"), &OggPacketSequence::set_sampling_rate);
+ ClassDB::bind_method(D_METHOD("get_sampling_rate"), &OggPacketSequence::get_sampling_rate);
- ClassDB::bind_method(D_METHOD("get_length"), &OGGPacketSequence::get_length);
+ ClassDB::bind_method(D_METHOD("get_length"), &OggPacketSequence::get_length);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "packet_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_data", "get_packet_data");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "granule_positions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_granule_positions", "get_packet_granule_positions");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sampling_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_sampling_rate", "get_sampling_rate");
}
-bool OGGPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const {
+bool OggPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const {
ERR_FAIL_COND_V(data_version != ogg_packet_sequence->data_version, false);
ERR_FAIL_COND_V(ogg_packet_sequence->page_data.is_empty(), false);
ERR_FAIL_COND_V(ogg_packet_sequence->page_granule_positions.is_empty(), false);
@@ -161,7 +161,7 @@ bool OGGPacketSequencePlayback::next_ogg_packet(ogg_packet **p_packet) const {
return true;
}
-uint32_t OGGPacketSequencePlayback::seek_page_internal(int64_t granule, uint32_t after_page_inclusive, uint32_t before_page_inclusive) {
+uint32_t OggPacketSequencePlayback::seek_page_internal(int64_t granule, uint32_t after_page_inclusive, uint32_t before_page_inclusive) {
// FIXME: This function needs better corner case handling.
if (before_page_inclusive == after_page_inclusive) {
return before_page_inclusive;
@@ -198,7 +198,7 @@ uint32_t OGGPacketSequencePlayback::seek_page_internal(int64_t granule, uint32_t
}
}
-bool OGGPacketSequencePlayback::seek_page(int64_t p_granule_pos) {
+bool OggPacketSequencePlayback::seek_page(int64_t p_granule_pos) {
int correct_page = seek_page_internal(p_granule_pos, 0, ogg_packet_sequence->page_data.size() - 1);
if (correct_page == -1) {
return false;
@@ -213,10 +213,10 @@ bool OGGPacketSequencePlayback::seek_page(int64_t p_granule_pos) {
return true;
}
-OGGPacketSequencePlayback::OGGPacketSequencePlayback() {
+OggPacketSequencePlayback::OggPacketSequencePlayback() {
packet = new ogg_packet();
}
-OGGPacketSequencePlayback::~OGGPacketSequencePlayback() {
+OggPacketSequencePlayback::~OggPacketSequencePlayback() {
delete packet;
}
diff --git a/modules/ogg/ogg_packet_sequence.h b/modules/ogg/ogg_packet_sequence.h
index 73e3cb4fff..efd3b64a39 100644
--- a/modules/ogg/ogg_packet_sequence.h
+++ b/modules/ogg/ogg_packet_sequence.h
@@ -38,12 +38,12 @@
#include "core/variant/variant.h"
#include "thirdparty/libogg/ogg/ogg.h"
-class OGGPacketSequencePlayback;
+class OggPacketSequencePlayback;
-class OGGPacketSequence : public Resource {
- GDCLASS(OGGPacketSequence, Resource);
+class OggPacketSequence : public Resource {
+ GDCLASS(OggPacketSequence, Resource);
- friend class OGGPacketSequencePlayback;
+ friend class OggPacketSequencePlayback;
// List of pages, each of which is a list of packets on that page. The innermost PackedByteArrays contain complete ogg packets.
Vector<Vector<PackedByteArray>> page_data;
@@ -73,7 +73,7 @@ public:
void set_packet_granule_positions(const Array &p_granule_positions);
Array get_packet_granule_positions() const;
- // Sets a sampling rate associated with this object. OGGPacketSequence doesn't understand codecs,
+ // Sets a sampling rate associated with this object. OggPacketSequence doesn't understand codecs,
// so this value is naively stored as a convenience.
void set_sampling_rate(float p_sampling_rate);
@@ -86,18 +86,18 @@ public:
// Returns the granule position of the last page in this sequence.
int64_t get_final_granule_pos() const;
- Ref<OGGPacketSequencePlayback> instance_playback();
+ Ref<OggPacketSequencePlayback> instantiate_playback();
- OGGPacketSequence() {}
- virtual ~OGGPacketSequence() {}
+ OggPacketSequence() {}
+ virtual ~OggPacketSequence() {}
};
-class OGGPacketSequencePlayback : public RefCounted {
- GDCLASS(OGGPacketSequencePlayback, RefCounted);
+class OggPacketSequencePlayback : public RefCounted {
+ GDCLASS(OggPacketSequencePlayback, RefCounted);
- friend class OGGPacketSequence;
+ friend class OggPacketSequence;
- Ref<OGGPacketSequence> ogg_packet_sequence;
+ Ref<OggPacketSequence> ogg_packet_sequence;
mutable int64_t page_cursor = 0;
mutable int32_t packet_cursor = 0;
@@ -121,8 +121,8 @@ public:
// Returns true on success, false on failure.
bool seek_page(int64_t p_granule_pos);
- OGGPacketSequencePlayback();
- virtual ~OGGPacketSequencePlayback();
+ OggPacketSequencePlayback();
+ virtual ~OggPacketSequencePlayback();
};
#endif // OGG_PACKET_SEQUENCE_H
diff --git a/modules/ogg/register_types.cpp b/modules/ogg/register_types.cpp
index 01f04aa3d5..aca6d1e1f8 100644
--- a/modules/ogg/register_types.cpp
+++ b/modules/ogg/register_types.cpp
@@ -37,8 +37,8 @@ void initialize_ogg_module(ModuleInitializationLevel p_level) {
return;
}
- GDREGISTER_CLASS(OGGPacketSequence);
- GDREGISTER_CLASS(OGGPacketSequencePlayback);
+ GDREGISTER_CLASS(OggPacketSequence);
+ GDREGISTER_CLASS(OggPacketSequencePlayback);
}
void uninitialize_ogg_module(ModuleInitializationLevel p_level) {
diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub
index 8783e061d2..593d1ff3c1 100644
--- a/modules/openxr/SCsub
+++ b/modules/openxr/SCsub
@@ -35,7 +35,11 @@ if env["platform"] == "android":
# may need to include java parts of the openxr loader
elif env["platform"] == "linuxbsd":
- env_thirdparty.AppendUnique(CPPDEFINES=["XR_OS_LINUX", "XR_USE_PLATFORM_XLIB"])
+ env_thirdparty.AppendUnique(CPPDEFINES=["XR_OS_LINUX"])
+
+ if env["x11"]:
+ env_thirdparty.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_XLIB"])
+
# FIXME: Review what needs to be set for Android and macOS.
env_thirdparty.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"])
elif env["platform"] == "windows":
diff --git a/modules/openxr/action_map/openxr_action.h b/modules/openxr/action_map/openxr_action.h
index 5e57f89133..a7c1c9988c 100644
--- a/modules/openxr/action_map/openxr_action.h
+++ b/modules/openxr/action_map/openxr_action.h
@@ -84,4 +84,4 @@ public:
VARIANT_ENUM_CAST(OpenXRAction::ActionType);
-#endif // !OPENXR_ACTION_H
+#endif // OPENXR_ACTION_H
diff --git a/modules/openxr/action_map/openxr_action_map.h b/modules/openxr/action_map/openxr_action_map.h
index dcd8fc71aa..8659cd3942 100644
--- a/modules/openxr/action_map/openxr_action_map.h
+++ b/modules/openxr/action_map/openxr_action_map.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef OPENXR_ACTION_SETS_H
-#define OPENXR_ACTION_SETS_H
+#ifndef OPENXR_ACTION_MAP_H
+#define OPENXR_ACTION_MAP_H
#include "core/io/resource.h"
@@ -79,4 +79,4 @@ public:
~OpenXRActionMap();
};
-#endif // !OPENXR_ACTION_SETS_H
+#endif // OPENXR_ACTION_MAP_H
diff --git a/modules/openxr/action_map/openxr_action_set.h b/modules/openxr/action_map/openxr_action_set.h
index b1d7168894..2ef7ba4c32 100644
--- a/modules/openxr/action_map/openxr_action_set.h
+++ b/modules/openxr/action_map/openxr_action_set.h
@@ -72,4 +72,4 @@ public:
~OpenXRActionSet();
};
-#endif // !OPENXR_ACTION_SET_H
+#endif // OPENXR_ACTION_SET_H
diff --git a/modules/openxr/action_map/openxr_defs.h b/modules/openxr/action_map/openxr_defs.h
index 9bdd9a6ded..446e6eb9c6 100644
--- a/modules/openxr/action_map/openxr_defs.h
+++ b/modules/openxr/action_map/openxr_defs.h
@@ -121,4 +121,4 @@ public:
static PackedStringArray get_interaction_profile_paths();
};
-#endif // !OPENXR_DEFS_H
+#endif // OPENXR_DEFS_H
diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp
index 342c36cdff..99d7a17acf 100644
--- a/modules/openxr/action_map/openxr_interaction_profile.cpp
+++ b/modules/openxr/action_map/openxr_interaction_profile.cpp
@@ -40,7 +40,7 @@ void OpenXRIPBinding::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_paths"), &OpenXRIPBinding::get_paths);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "paths", PROPERTY_HINT_ARRAY_TYPE, "STRING"), "set_paths", "get_paths");
- ClassDB::bind_method(D_METHOD("has_path"), &OpenXRIPBinding::has_path);
+ ClassDB::bind_method(D_METHOD("has_path", "path"), &OpenXRIPBinding::has_path);
ClassDB::bind_method(D_METHOD("add_path", "path"), &OpenXRIPBinding::add_path);
ClassDB::bind_method(D_METHOD("remove_path", "path"), &OpenXRIPBinding::remove_path);
}
diff --git a/modules/openxr/action_map/openxr_interaction_profile.h b/modules/openxr/action_map/openxr_interaction_profile.h
index 46b1bda50f..c77fd490bb 100644
--- a/modules/openxr/action_map/openxr_interaction_profile.h
+++ b/modules/openxr/action_map/openxr_interaction_profile.h
@@ -98,4 +98,4 @@ public:
~OpenXRInteractionProfile();
};
-#endif // !OPENXR_INTERACTION_PROFILE_H
+#endif // OPENXR_INTERACTION_PROFILE_H
diff --git a/modules/openxr/doc_classes/OpenXRIPBinding.xml b/modules/openxr/doc_classes/OpenXRIPBinding.xml
index 9e1176874a..f96637f2f5 100644
--- a/modules/openxr/doc_classes/OpenXRIPBinding.xml
+++ b/modules/openxr/doc_classes/OpenXRIPBinding.xml
@@ -24,7 +24,7 @@
</method>
<method name="has_path" qualifiers="const">
<return type="bool" />
- <argument index="0" name="arg0" type="String" />
+ <argument index="0" name="path" type="String" />
<description>
Returns [code]true[/code] if this input/output path is part of this binding.
</description>
diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml
index 74f708bc95..25bf496de9 100644
--- a/modules/openxr/doc_classes/OpenXRInterface.xml
+++ b/modules/openxr/doc_classes/OpenXRInterface.xml
@@ -5,10 +5,10 @@
</brief_description>
<description>
The OpenXR interface allows Godot to interact with OpenXR runtimes and make it possible to create XR experiences and games.
- Due to the needs of OpenXR this interface works slightly different then other plugin based XR interfaces. It needs to be initialised when Godot starts. You need to enable OpenXR, settings for this can be found in your games project settings under the XR heading. You do need to mark a viewport for use with XR in order for Godot to know which render result should be output to the headset.
+ Due to the needs of OpenXR this interface works slightly different than other plugin based XR interfaces. It needs to be initialised when Godot starts. You need to enable OpenXR, settings for this can be found in your games project settings under the XR heading. You do need to mark a viewport for use with XR in order for Godot to know which render result should be output to the headset.
</description>
<tutorials>
- <link title="OpenXR documentation">$DOCS_URL/tutorials/vr/openxr/index.html</link>
+ <link title="Setting up XR">$DOCS_URL/tutorials/xr/setting_up_xr.html</link>
</tutorials>
<signals>
<signal name="pose_recentered">
diff --git a/modules/openxr/editor/openxr_action_editor.h b/modules/openxr/editor/openxr_action_editor.h
index 6e1b7ab779..6cf098cf08 100644
--- a/modules/openxr/editor/openxr_action_editor.h
+++ b/modules/openxr/editor/openxr_action_editor.h
@@ -64,4 +64,4 @@ public:
OpenXRActionEditor(Ref<OpenXRAction> p_action);
};
-#endif // !OPENXR_ACTION_EDITOR_H
+#endif // OPENXR_ACTION_EDITOR_H
diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
index 87b7f50224..0a2d0a3110 100644
--- a/modules/openxr/editor/openxr_action_map_editor.cpp
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -258,7 +258,7 @@ void OpenXRActionMapEditor::_load_action_map(const String p_path, bool p_create_
}
void OpenXRActionMapEditor::_on_save_action_map() {
- Error err = ResourceSaver::save(edited_path, action_map);
+ Error err = ResourceSaver::save(action_map, edited_path);
if (err != OK) {
EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), edited_path));
return;
diff --git a/modules/openxr/editor/openxr_action_map_editor.h b/modules/openxr/editor/openxr_action_map_editor.h
index dfc941b500..a19bc90f56 100644
--- a/modules/openxr/editor/openxr_action_map_editor.h
+++ b/modules/openxr/editor/openxr_action_map_editor.h
@@ -97,4 +97,4 @@ public:
~OpenXRActionMapEditor();
};
-#endif // !OPENXR_ACTION_MAP_EDITOR_H
+#endif // OPENXR_ACTION_MAP_EDITOR_H
diff --git a/modules/openxr/editor/openxr_action_set_editor.h b/modules/openxr/editor/openxr_action_set_editor.h
index f3960dcbf9..d8c85d03dd 100644
--- a/modules/openxr/editor/openxr_action_set_editor.h
+++ b/modules/openxr/editor/openxr_action_set_editor.h
@@ -85,4 +85,4 @@ public:
OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set);
};
-#endif // !OPENXR_ACTION_SET_EDITOR_H
+#endif // OPENXR_ACTION_SET_EDITOR_H
diff --git a/modules/openxr/editor/openxr_editor_plugin.h b/modules/openxr/editor/openxr_editor_plugin.h
index af8ee7d54c..ce230ee95b 100644
--- a/modules/openxr/editor/openxr_editor_plugin.h
+++ b/modules/openxr/editor/openxr_editor_plugin.h
@@ -50,4 +50,4 @@ public:
~OpenXREditorPlugin();
};
-#endif // !OPENXR_EDITOR_PLUGIN_H
+#endif // OPENXR_EDITOR_PLUGIN_H
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
index 24ac5494dd..e2dc2d1b74 100644
--- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
@@ -169,9 +169,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co
Button *path_add = memnew(Button);
path_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
path_add->set_flat(true);
- Vector<Variant> add_binds;
- add_binds.push_back(String(p_io_path->openxr_path));
- path_add->connect("pressed", callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for), add_binds);
+ path_add->connect("pressed", callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for).bind(String(p_io_path->openxr_path)));
path_hb->add_child(path_add);
if (interaction_profile.is_valid()) {
@@ -198,10 +196,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co
Button *action_rem = memnew(Button);
action_rem->set_flat(true);
action_rem->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
- Vector<Variant> remove_binds;
- remove_binds.push_back(action->get_name_with_set());
- remove_binds.push_back(String(p_io_path->openxr_path));
- action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditorBase *)this, &OpenXRInteractionProfileEditorBase::_remove_binding), remove_binds);
+ action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditorBase *)this, &OpenXRInteractionProfileEditorBase::_remove_binding).bind(action->get_name_with_set(), String(p_io_path->openxr_path)));
action_hb->add_child(action_rem);
}
}
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.h b/modules/openxr/editor/openxr_interaction_profile_editor.h
index f50da1a003..20a37a80eb 100644
--- a/modules/openxr/editor/openxr_interaction_profile_editor.h
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.h
@@ -80,4 +80,4 @@ public:
OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile);
};
-#endif // !OPENXR_INTERACTION_PROFILE_EDITOR_H
+#endif // OPENXR_INTERACTION_PROFILE_EDITOR_H
diff --git a/modules/openxr/editor/openxr_select_action_dialog.cpp b/modules/openxr/editor/openxr_select_action_dialog.cpp
index c2a2965200..80e58044d5 100644
--- a/modules/openxr/editor/openxr_select_action_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_action_dialog.cpp
@@ -96,11 +96,9 @@ void OpenXRSelectActionDialog::open() {
Button *action_button = memnew(Button);
String action_name = action->get_name_with_set();
- Vector<Variant> binds;
- binds.push_back(action_name);
action_button->set_flat(true);
action_button->set_text(action->get_name() + ": " + action->get_localized_name());
- action_button->connect("pressed", callable_mp(this, &OpenXRSelectActionDialog::_on_select_action), binds);
+ action_button->connect("pressed", callable_mp(this, &OpenXRSelectActionDialog::_on_select_action).bind(action_name));
action_hb->add_child(action_button);
action_buttons[action_name] = action_button->get_path();
diff --git a/modules/openxr/editor/openxr_select_action_dialog.h b/modules/openxr/editor/openxr_select_action_dialog.h
index ea2c30373b..cbe1380e18 100644
--- a/modules/openxr/editor/openxr_select_action_dialog.h
+++ b/modules/openxr/editor/openxr_select_action_dialog.h
@@ -64,4 +64,4 @@ public:
OpenXRSelectActionDialog(Ref<OpenXRActionMap> p_action_map);
};
-#endif // !OPENXR_SELECT_ACTION_DIALOG_H
+#endif // OPENXR_SELECT_ACTION_DIALOG_H
diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
index 12b110f146..23b025db08 100644
--- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
@@ -80,11 +80,9 @@ void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_inclu
String path = interaction_profiles[i];
if (!p_do_not_include.has(path)) {
Button *ip_button = memnew(Button);
- Vector<Variant> binds;
- binds.push_back(path);
ip_button->set_flat(true);
ip_button->set_text(OpenXRDefs::get_profile(path)->display_name);
- ip_button->connect("pressed", callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile), binds);
+ ip_button->connect("pressed", callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile).bind(path));
main_vb->add_child(ip_button);
ip_buttons[path] = ip_button->get_path();
diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h
index d177861ff3..54bfe3120a 100644
--- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h
+++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h
@@ -63,4 +63,4 @@ public:
OpenXRSelectInteractionProfileDialog();
};
-#endif // !OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
+#endif // OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
diff --git a/modules/openxr/extensions/openxr_android_extension.h b/modules/openxr/extensions/openxr_android_extension.h
index e102197a55..88b0e310e7 100644
--- a/modules/openxr/extensions/openxr_android_extension.h
+++ b/modules/openxr/extensions/openxr_android_extension.h
@@ -44,4 +44,4 @@ private:
static OpenXRAndroidExtension *singleton;
};
-#endif // !OPENXR_ANDROID_EXTENSION_H
+#endif // OPENXR_ANDROID_EXTENSION_H
diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h
index 0f7c0ba0bc..ecc6e0dd4e 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper.h
@@ -32,7 +32,7 @@
#define OPENXR_EXTENSION_WRAPPER_H
#include "core/error/error_macros.h"
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/templates/hash_map.h"
#include "core/templates/rid.h"
@@ -97,11 +97,11 @@ public:
virtual String get_swapchain_format_name(int64_t p_swapchain_format) const = 0;
virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) = 0;
virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) = 0;
- virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, CameraMatrix &r_camera_matrix) = 0;
+ virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) = 0;
virtual bool copy_render_target_to_image(RID p_from_render_target, void *p_swapchain_graphics_data, int p_image_index) = 0;
OpenXRGraphicsExtensionWrapper(OpenXRAPI *p_openxr_api) :
OpenXRExtensionWrapper(p_openxr_api){};
};
-#endif // ~OPENXR_EXTENSION_WRAPPER_H
+#endif // OPENXR_EXTENSION_WRAPPER_H
diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h
index 7670bc074b..7f37351f27 100644
--- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h
+++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h
@@ -49,4 +49,4 @@ private:
bool available = false;
};
-#endif // !OPENXR_HTC_VIVE_TRACKER_EXTENSION_H
+#endif // OPENXR_HTC_VIVE_TRACKER_EXTENSION_H
diff --git a/modules/openxr/extensions/openxr_vulkan_extension.cpp b/modules/openxr/extensions/openxr_vulkan_extension.cpp
index 2ddf3b8a7d..2608c4ac17 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"
@@ -421,7 +420,7 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
return true;
}
-bool OpenXRVulkanExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, CameraMatrix &r_camera_matrix) {
+bool OpenXRVulkanExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) {
// Even though this is a Vulkan renderer we're using OpenGL coordinate systems
XrMatrix4x4f matrix;
XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);
@@ -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/openxr/extensions/openxr_vulkan_extension.h b/modules/openxr/extensions/openxr_vulkan_extension.h
index 1e34fe1f80..5dddc4b9c9 100644
--- a/modules/openxr/extensions/openxr_vulkan_extension.h
+++ b/modules/openxr/extensions/openxr_vulkan_extension.h
@@ -63,7 +63,7 @@ public:
virtual String get_swapchain_format_name(int64_t p_swapchain_format) const override;
virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) override;
virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) override;
- virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, CameraMatrix &r_camera_matrix) override;
+ virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) override;
virtual bool copy_render_target_to_image(RID p_from_render_target, void *p_swapchain_graphics_data, int p_image_index) override;
private:
@@ -90,4 +90,4 @@ private:
XrResult xrCreateVulkanDeviceKHR(XrInstance p_instance, const XrVulkanDeviceCreateInfoKHR *p_create_info, VkDevice *r_device, VkResult *r_result);
};
-#endif // !OPENXR_VULKAN_EXTENSION_H
+#endif // OPENXR_VULKAN_EXTENSION_H
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 5e35942012..92d074cb75 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -58,19 +58,14 @@ bool OpenXRAPI::openxr_is_enabled(bool p_check_run_in_editor) {
// @TODO we need an overrule switch so we can force enable openxr, i.e run "godot --openxr_enabled"
if (Engine::get_singleton()->is_editor_hint() && p_check_run_in_editor) {
-#ifdef TOOLS_ENABLED
// Disabled for now, using XR inside of the editor we'll be working on during the coming months.
return false;
-
- // bool enabled = GLOBAL_GET("xr/openxr/in_editor"); // EDITOR_GET("xr/openxr/in_editor");
- // return enabled;
-#else
- // we should never get here, editor hint won't be true if the editor isn't compiled in.
- return false;
-#endif
} else {
- bool enabled = GLOBAL_GET("xr/openxr/enabled");
- return enabled;
+ if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) {
+ return GLOBAL_GET("xr/openxr/enabled");
+ } else {
+ return XRServer::get_xr_mode() == XRServer::XRMODE_ON;
+ }
}
}
@@ -1180,7 +1175,7 @@ bool OpenXRAPI::get_view_transform(uint32_t p_view, Transform3D &r_transform) {
return true;
}
-bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, CameraMatrix &p_camera_matrix) {
+bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, Projection &p_camera_matrix) {
ERR_FAIL_COND_V(!running, false);
ERR_FAIL_NULL_V(graphics_extension, false);
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index fe9e2937b2..dc224c4237 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef OPENXR_DRIVER_H
-#define OPENXR_DRIVER_H
+#ifndef OPENXR_API_H
+#define OPENXR_API_H
#include "core/error/error_macros.h"
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/math/transform_3d.h"
#include "core/math/vector2.h"
#include "core/os/memory.h"
@@ -249,7 +249,7 @@ public:
Size2 get_recommended_target_size();
XRPose::TrackingConfidence get_head_center(Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity);
bool get_view_transform(uint32_t p_view, Transform3D &r_transform);
- bool get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, CameraMatrix &p_camera_matrix);
+ bool get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, Projection &p_camera_matrix);
bool process();
void pre_render();
@@ -292,4 +292,4 @@ public:
~OpenXRAPI();
};
-#endif // !OPENXR_DRIVER_H
+#endif // OPENXR_API_H
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index 9dfa005600..6c2f08e21d 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -123,7 +123,7 @@ void OpenXRInterface::_load_action_map() {
#ifdef TOOLS_ENABLED
// Save our action sets so our user can
action_map->set_path(default_tres_name, true);
- ResourceSaver::save(default_tres_name, action_map);
+ ResourceSaver::save(action_map, default_tres_name);
#endif
}
}
@@ -631,8 +631,8 @@ Transform3D OpenXRInterface::get_transform_for_view(uint32_t p_view, const Trans
return p_cam_transform * xr_server->get_reference_frame() * t;
}
-CameraMatrix OpenXRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
- CameraMatrix cm;
+Projection OpenXRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
+ Projection cm;
if (openxr_api) {
if (openxr_api->get_view_projection(p_view, p_z_near, p_z_far, cm)) {
diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h
index a223acfed0..a99012fd1d 100644
--- a/modules/openxr/openxr_interface.h
+++ b/modules/openxr/openxr_interface.h
@@ -121,7 +121,7 @@ public:
virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
- virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
+ virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
virtual void process() override;
virtual void pre_render() override;
@@ -140,4 +140,4 @@ public:
~OpenXRInterface();
};
-#endif // !OPENXR_INTERFACE_H
+#endif // OPENXR_INTERFACE_H
diff --git a/modules/openxr/openxr_util.h b/modules/openxr/openxr_util.h
index 4371b74d2f..a5cc7cd512 100644
--- a/modules/openxr/openxr_util.h
+++ b/modules/openxr/openxr_util.h
@@ -44,4 +44,4 @@ public:
static String make_xr_version_string(XrVersion p_version);
};
-#endif // !OPENXR_UTIL_H
+#endif // OPENXR_UTIL_H
diff --git a/modules/raycast/lightmap_raycaster.h b/modules/raycast/lightmap_raycaster.h
index 4266b46ea8..2e9f59dda4 100644
--- a/modules/raycast/lightmap_raycaster.h
+++ b/modules/raycast/lightmap_raycaster.h
@@ -74,4 +74,4 @@ public:
~LightmapRaycasterEmbree();
};
-#endif
+#endif // LIGHTMAP_RAYCASTER_H
diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp
index 89e75f774e..13824c3830 100644
--- a/modules/raycast/raycast_occlusion_cull.cpp
+++ b/modules/raycast/raycast_occlusion_cull.cpp
@@ -30,6 +30,7 @@
#include "raycast_occlusion_cull.h"
#include "core/config/project_settings.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/local_vector.h"
#ifdef __SSE2__
@@ -78,9 +79,9 @@ void RaycastOcclusionCull::RaycastHZBuffer::resize(const Size2i &p_size) {
memset(camera_ray_masks.ptr(), ~0, camera_rays_tile_count * TILE_RAYS * sizeof(uint32_t));
}
-void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool) {
+void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) {
CameraRayThreadData td;
- td.thread_count = p_thread_work_pool.get_thread_count();
+ td.thread_count = WorkerThreadPool::get_singleton()->get_thread_count();
td.z_near = p_cam_projection.get_z_near();
td.z_far = p_cam_projection.get_z_far() * 1.05f;
@@ -88,7 +89,7 @@ void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D
td.camera_dir = -p_cam_transform.basis.get_column(2);
td.camera_orthogonal = p_cam_orthogonal;
- CameraMatrix inv_camera_matrix = p_cam_projection.inverse();
+ Projection inv_camera_matrix = p_cam_projection.inverse();
Vector3 camera_corner_proj = Vector3(-1.0f, -1.0f, -1.0f);
Vector3 camera_corner_view = inv_camera_matrix.xform(camera_corner_proj);
td.pixel_corner = p_cam_transform.xform(camera_corner_view);
@@ -106,7 +107,8 @@ void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D
debug_tex_range = td.z_far;
- p_thread_work_pool.do_work(td.thread_count, this, &RaycastHZBuffer::_camera_rays_threaded, &td);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RaycastHZBuffer::_camera_rays_threaded, &td, td.thread_count, -1, true, SNAME("RaycastOcclusionCullUpdateCamera"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
}
void RaycastOcclusionCull::RaycastHZBuffer::_camera_rays_threaded(uint32_t p_thread, const CameraRayThreadData *p_data) {
@@ -331,10 +333,10 @@ void RaycastOcclusionCull::scenario_remove_instance(RID p_scenario, RID p_instan
}
void RaycastOcclusionCull::Scenario::_update_dirty_instance_thread(int p_idx, RID *p_instances) {
- _update_dirty_instance(p_idx, p_instances, nullptr);
+ _update_dirty_instance(p_idx, p_instances);
}
-void RaycastOcclusionCull::Scenario::_update_dirty_instance(int p_idx, RID *p_instances, ThreadWorkPool *p_thread_pool) {
+void RaycastOcclusionCull::Scenario::_update_dirty_instance(int p_idx, RID *p_instances) {
OccluderInstance *occ_inst = instances.getptr(p_instances[p_idx]);
if (!occ_inst) {
@@ -355,14 +357,16 @@ void RaycastOcclusionCull::Scenario::_update_dirty_instance(int p_idx, RID *p_in
const Vector3 *read_ptr = occ->vertices.ptr();
Vector3 *write_ptr = occ_inst->xformed_vertices.ptr();
- if (p_thread_pool && vertices_size > 1024) {
+ if (vertices_size > 1024) {
TransformThreadData td;
td.xform = occ_inst->xform;
td.read = read_ptr;
td.write = write_ptr;
td.vertex_count = vertices_size;
- td.thread_count = p_thread_pool->get_thread_count();
- p_thread_pool->do_work(td.thread_count, this, &Scenario::_transform_vertices_thread, &td);
+ td.thread_count = WorkerThreadPool::get_singleton()->get_thread_count();
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &Scenario::_transform_vertices_thread, &td, td.thread_count, -1, true, SNAME("RaycastOcclusionCull"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
} else {
_transform_vertices_range(read_ptr, write_ptr, occ_inst->xform, 0, vertices_size);
}
@@ -392,7 +396,7 @@ void RaycastOcclusionCull::Scenario::_commit_scene(void *p_ud) {
scenario->commit_done = true;
}
-bool RaycastOcclusionCull::Scenario::update(ThreadWorkPool &p_thread_pool) {
+bool RaycastOcclusionCull::Scenario::update() {
ERR_FAIL_COND_V(singleton == nullptr, false);
if (commit_thread == nullptr) {
@@ -426,13 +430,15 @@ bool RaycastOcclusionCull::Scenario::update(ThreadWorkPool &p_thread_pool) {
instances.erase(removed_instances[i]);
}
- if (dirty_instances_array.size() / p_thread_pool.get_thread_count() > 128) {
+ if (dirty_instances_array.size() / WorkerThreadPool::get_singleton()->get_thread_count() > 128) {
// Lots of instances, use per-instance threading
- p_thread_pool.do_work(dirty_instances_array.size(), this, &Scenario::_update_dirty_instance_thread, dirty_instances_array.ptr());
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &Scenario::_update_dirty_instance_thread, dirty_instances_array.ptr(), dirty_instances_array.size(), -1, true, SNAME("RaycastOcclusionCullUpdate"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
} else {
// Few instances, use threading on the vertex transforms
for (unsigned int i = 0; i < dirty_instances_array.size(); i++) {
- _update_dirty_instance(i, dirty_instances_array.ptr(), &p_thread_pool);
+ _update_dirty_instance(i, dirty_instances_array.ptr());
}
}
@@ -484,7 +490,7 @@ void RaycastOcclusionCull::Scenario::_raycast(uint32_t p_idx, const RaycastThrea
rtcIntersect16((const int *)&p_raycast_data->masks[p_idx * TILE_RAYS], ebr_scene[current_scene_idx], &ctx, &p_raycast_data->rays[p_idx]);
}
-void RaycastOcclusionCull::Scenario::raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count, ThreadWorkPool &p_thread_pool) const {
+void RaycastOcclusionCull::Scenario::raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count) const {
ERR_FAIL_COND(singleton == nullptr);
if (raycast_singleton->ebr_device == nullptr) {
return; // Embree is initialized on demand when there is some scenario with occluders in it.
@@ -498,7 +504,8 @@ void RaycastOcclusionCull::Scenario::raycast(CameraRayTile *r_rays, const uint32
td.rays = r_rays;
td.masks = p_valid_masks;
- p_thread_pool.do_work(p_tile_count, this, &Scenario::_raycast, &td);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &Scenario::_raycast, &td, p_tile_count, -1, true, SNAME("RaycastOcclusionCullRaycast"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
}
////////////////////////////////////////////////////////
@@ -524,7 +531,7 @@ void RaycastOcclusionCull::buffer_set_size(RID p_buffer, const Vector2i &p_size)
buffers[p_buffer].resize(p_size);
}
-void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {
+void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) {
if (!buffers.has(p_buffer)) {
return;
}
@@ -537,16 +544,16 @@ void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_
Scenario &scenario = scenarios[buffer.scenario_rid];
- bool removed = scenario.update(p_thread_pool);
+ bool removed = scenario.update();
if (removed) {
scenarios.erase(buffer.scenario_rid);
return;
}
- buffer.update_camera_rays(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_thread_pool);
+ buffer.update_camera_rays(p_cam_transform, p_cam_projection, p_cam_orthogonal);
- scenario.raycast(buffer.camera_rays, buffer.camera_ray_masks.ptr(), buffer.camera_rays_tile_count, p_thread_pool);
+ scenario.raycast(buffer.camera_rays, buffer.camera_ray_masks.ptr(), buffer.camera_rays_tile_count);
buffer.sort_rays(-p_cam_transform.basis.get_column(2), p_cam_orthogonal);
buffer.update_mips();
}
diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h
index 6562c4e9c4..056b808640 100644
--- a/modules/raycast/raycast_occlusion_cull.h
+++ b/modules/raycast/raycast_occlusion_cull.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef OCCLUSION_CULL_RAYCASTER_H
-#define OCCLUSION_CULL_RAYCASTER_H
+#ifndef RAYCAST_OCCLUSION_CULL_H
+#define RAYCAST_OCCLUSION_CULL_H
#include "core/io/image.h"
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/object/object.h"
#include "core/object/ref_counted.h"
#include "core/templates/local_vector.h"
@@ -76,7 +76,7 @@ public:
virtual void clear() override;
virtual void resize(const Size2i &p_size) override;
void sort_rays(const Vector3 &p_camera_dir, bool p_orthogonal);
- void update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool);
+ void update_camera_rays(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal);
~RaycastHZBuffer();
};
@@ -143,14 +143,14 @@ private:
LocalVector<RID> removed_instances;
void _update_dirty_instance_thread(int p_idx, RID *p_instances);
- void _update_dirty_instance(int p_idx, RID *p_instances, ThreadWorkPool *p_thread_pool);
+ void _update_dirty_instance(int p_idx, RID *p_instances);
void _transform_vertices_thread(uint32_t p_thread, TransformThreadData *p_data);
void _transform_vertices_range(const Vector3 *p_read, Vector3 *p_write, const Transform3D &p_xform, int p_from, int p_to);
static void _commit_scene(void *p_ud);
- bool update(ThreadWorkPool &p_thread_pool);
+ bool update();
void _raycast(uint32_t p_thread, const RaycastThreadData *p_raycast_data) const;
- void raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count, ThreadWorkPool &p_thread_pool) const;
+ void raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count) const;
};
static RaycastOcclusionCull *raycast_singleton;
@@ -183,7 +183,8 @@ public:
virtual HZBuffer *buffer_get_ptr(RID p_buffer) override;
virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) override;
virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) override;
- virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) override;
+ virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) override;
+
virtual RID buffer_get_debug_texture(RID p_buffer) override;
virtual void set_build_quality(RS::ViewportOcclusionCullingBuildQuality p_quality) override;
@@ -192,4 +193,4 @@ public:
~RaycastOcclusionCull();
};
-#endif // OCCLUSION_CULL_RAYCASTER_H
+#endif // RAYCAST_OCCLUSION_CULL_H
diff --git a/modules/raycast/static_raycaster.h b/modules/raycast/static_raycaster.h
index e2909f9b56..607a392683 100644
--- a/modules/raycast/static_raycaster.h
+++ b/modules/raycast/static_raycaster.h
@@ -61,4 +61,4 @@ public:
~StaticRaycasterEmbree();
};
-#endif
+#endif // STATIC_RAYCASTER_H
diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml
index deabc5ccd3..52a7fe492f 100644
--- a/modules/regex/doc_classes/RegEx.xml
+++ b/modules/regex/doc_classes/RegEx.xml
@@ -62,6 +62,13 @@
Compiles and assign the search pattern to use. Returns [constant OK] if the compilation is successful. If an error is encountered, details are printed to standard output and an error is returned.
</description>
</method>
+ <method name="create_from_string" qualifiers="static">
+ <return type="RegEx" />
+ <argument index="0" name="pattern" type="String" />
+ <description>
+ Creates and compiles a new [RegEx] object.
+ </description>
+ </method>
<method name="get_group_count" qualifiers="const">
<return type="int" />
<description>
@@ -96,7 +103,7 @@
</description>
</method>
<method name="search_all" qualifiers="const">
- <return type="Array" />
+ <return type="RegExMatch[]" />
<argument index="0" name="subject" type="String" />
<argument index="1" name="offset" type="int" default="0" />
<argument index="2" name="end" type="int" default="-1" />
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index bbe92139e0..569066867a 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -159,6 +159,13 @@ void RegEx::_pattern_info(uint32_t what, void *where) const {
pcre2_pattern_info_32((pcre2_code_32 *)code, what, where);
}
+Ref<RegEx> RegEx::create_from_string(const String &p_pattern) {
+ Ref<RegEx> ret;
+ ret.instantiate();
+ ret->compile(p_pattern);
+ return ret;
+}
+
void RegEx::clear() {
if (code) {
pcre2_code_free_32((pcre2_code_32 *)code);
@@ -194,6 +201,7 @@ Error RegEx::compile(const String &p_pattern) {
Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) const {
ERR_FAIL_COND_V(!is_valid(), nullptr);
+ ERR_FAIL_COND_V_MSG(p_offset < 0, nullptr, "RegEx search offset must be >= 0");
Ref<RegExMatch> result = memnew(RegExMatch);
@@ -257,9 +265,11 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end)
return result;
}
-Array RegEx::search_all(const String &p_subject, int p_offset, int p_end) const {
+TypedArray<RegExMatch> RegEx::search_all(const String &p_subject, int p_offset, int p_end) const {
+ ERR_FAIL_COND_V_MSG(p_offset < 0, Array(), "RegEx search offset must be >= 0");
+
int last_end = -1;
- Array result;
+ TypedArray<RegExMatch> result;
Ref<RegExMatch> match = search(p_subject, p_offset, p_end);
while (match.is_valid()) {
if (last_end == match->get_end(0)) {
@@ -274,6 +284,7 @@ Array RegEx::search_all(const String &p_subject, int p_offset, int p_end) const
String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_all, int p_offset, int p_end) const {
ERR_FAIL_COND_V(!is_valid(), String());
+ ERR_FAIL_COND_V_MSG(p_offset < 0, String(), "RegEx sub offset must be >= 0");
// safety_zone is the number of chars we allocate in addition to the number of chars expected in order to
// guard against the PCRE API writing one additional \0 at the end. PCRE's API docs are unclear on whether
@@ -380,6 +391,8 @@ RegEx::~RegEx() {
}
void RegEx::_bind_methods() {
+ ClassDB::bind_static_method("RegEx", D_METHOD("create_from_string", "pattern"), &RegEx::create_from_string);
+
ClassDB::bind_method(D_METHOD("clear"), &RegEx::clear);
ClassDB::bind_method(D_METHOD("compile", "pattern"), &RegEx::compile);
ClassDB::bind_method(D_METHOD("search", "subject", "offset", "end"), &RegEx::search, DEFVAL(0), DEFVAL(-1));
diff --git a/modules/regex/regex.h b/modules/regex/regex.h
index 1455188670..9296de929f 100644
--- a/modules/regex/regex.h
+++ b/modules/regex/regex.h
@@ -37,6 +37,7 @@
#include "core/templates/vector.h"
#include "core/variant/array.h"
#include "core/variant/dictionary.h"
+#include "core/variant/typed_array.h"
class RegExMatch : public RefCounted {
GDCLASS(RegExMatch, RefCounted);
@@ -81,11 +82,13 @@ protected:
static void _bind_methods();
public:
+ static Ref<RegEx> create_from_string(const String &p_pattern);
+
void clear();
Error compile(const String &p_pattern);
Ref<RegExMatch> search(const String &p_subject, int p_offset = 0, int p_end = -1) const;
- Array search_all(const String &p_subject, int p_offset = 0, int p_end = -1) const;
+ TypedArray<RegExMatch> search_all(const String &p_subject, int p_offset = 0, int p_end = -1) const;
String sub(const String &p_subject, const String &p_replacement, bool p_all = false, int p_offset = 0, int p_end = -1) const;
bool is_valid() const;
diff --git a/modules/regex/tests/test_regex.h b/modules/regex/tests/test_regex.h
index 3f500e7b2f..91af393db1 100644
--- a/modules/regex/tests/test_regex.h
+++ b/modules/regex/tests/test_regex.h
@@ -130,16 +130,6 @@ TEST_CASE("[RegEx] Empty Pattern") {
CHECK(re.is_valid());
}
-TEST_CASE("[RegEx] Invalid offset") {
- const String s = "Godot";
-
- RegEx re("o");
- REQUIRE(re.is_valid());
- CHECK(re.search(s, -1) == nullptr);
- CHECK(re.search_all(s, -1).size() == 0);
- CHECK(re.sub(s, "", true, -1) == "");
-}
-
TEST_CASE("[RegEx] Invalid end position") {
const String s = "Godot";
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index dcb1f1d744..87e2fae2d0 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -80,8 +80,8 @@ void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_strin
float fw, fh;
picture->size(&fw, &fh);
- uint32_t width = MIN(fw * p_scale, 16 * 1024);
- uint32_t height = MIN(fh * p_scale, 16 * 1024);
+ uint32_t width = MIN(round(fw * p_scale), 16 * 1024);
+ uint32_t height = MIN(round(fh * p_scale), 16 * 1024);
picture->size(width, height);
std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen();
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index a46f17311a..c6678307af 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -36,8 +36,8 @@ def make_icu_data(target, source, env):
# Thirdparty source files
thirdparty_obj = []
-freetype_enabled = env.module_check_dependencies("text_server_adv", ["freetype"], True)
-msdfgen_enabled = env.module_check_dependencies("text_server_adv", ["msdfgen"], True)
+freetype_enabled = "freetype" in env.module_list
+msdfgen_enabled = "msdfgen" in env.module_list
if env["builtin_harfbuzz"]:
env_harfbuzz = env_modules.Clone()
@@ -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",
@@ -113,15 +113,18 @@ if env["builtin_harfbuzz"]:
if freetype_enabled:
thirdparty_sources += [
"src/hb-ft.cc",
- "src/hb-graphite2.cc",
]
+ if env["graphite"]:
+ thirdparty_sources += [
+ "src/hb-graphite2.cc",
+ ]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env_harfbuzz.Append(CPPPATH=["#thirdparty/harfbuzz/src"])
+ env_harfbuzz.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"])
env_harfbuzz.Append(CCFLAGS=["-DHAVE_ICU"])
if env["builtin_icu"]:
- env_harfbuzz.Append(CPPPATH=["#thirdparty/icu4c/common/"])
+ env_harfbuzz.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
env_harfbuzz.Append(CCFLAGS=["-DU_HAVE_LIB_SUFFIX=1", "-DU_LIB_SUFFIX_C_NAME=_godot", "-DHAVE_ICU_BUILTIN"])
if freetype_enabled:
@@ -132,9 +135,9 @@ if env["builtin_harfbuzz"]:
]
)
if env["builtin_freetype"]:
- env_harfbuzz.Append(CPPPATH=["#thirdparty/freetype/include"])
- if env["builtin_graphite"]:
- env_harfbuzz.Append(CPPPATH=["#thirdparty/graphite/include"])
+ env_harfbuzz.Prepend(CPPPATH=["#thirdparty/freetype/include"])
+ if env["builtin_graphite"] and env["graphite"]:
+ env_harfbuzz.Prepend(CPPPATH=["#thirdparty/graphite/include"])
env_harfbuzz.Append(CCFLAGS=["-DGRAPHITE2_STATIC"])
if env["platform"] == "android" or env["platform"] == "linuxbsd":
@@ -146,7 +149,7 @@ if env["builtin_harfbuzz"]:
else:
env_harfbuzz.Append(CCFLAGS=["-DHB_NO_MT"])
- env_text_server_adv.Append(CPPPATH=["#thirdparty/harfbuzz/src"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"])
lib = env_harfbuzz.add_library("harfbuzz_builtin", thirdparty_sources)
thirdparty_obj += lib
@@ -165,7 +168,7 @@ if env["builtin_harfbuzz"]:
env.Append(LIBS=[lib])
-if env["builtin_graphite"] and freetype_enabled:
+if env["builtin_graphite"] and freetype_enabled and env["graphite"]:
env_graphite = env_modules.Clone()
env_graphite.disable_warnings()
@@ -209,7 +212,7 @@ if env["builtin_graphite"] and freetype_enabled:
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env_graphite.Append(CPPPATH=["#thirdparty/graphite/src", "#thirdparty/graphite/include"])
+ env_graphite.Prepend(CPPPATH=["#thirdparty/graphite/src", "#thirdparty/graphite/include"])
env_graphite.Append(
CCFLAGS=[
"-DGRAPHITE2_STATIC",
@@ -439,6 +442,10 @@ if env["builtin_icu"]:
"common/uvectr32.cpp",
"common/uvectr64.cpp",
"common/wintz.cpp",
+ "i18n/scriptset.cpp",
+ "i18n/ucln_in.cpp",
+ "i18n/uspoof.cpp",
+ "i18n/uspoof_impl.cpp",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
@@ -447,11 +454,11 @@ if env["builtin_icu"]:
if env_icu["tools"]:
env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name)
env_icu.Command("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name, make_icu_data)
- env_text_server_adv.Append(CPPPATH=["#thirdparty/icu4c/"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/"])
else:
thirdparty_sources += ["icu_data/icudata_stub.cpp"]
- env_icu.Append(CPPPATH=["#thirdparty/icu4c/common/"])
+ env_icu.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
env_icu.Append(
CXXFLAGS=[
"-DU_STATIC_IMPLEMENTATION",
@@ -463,6 +470,7 @@ if env["builtin_icu"]:
"-DUCONFIG_NO_IDNA",
"-DUCONFIG_NO_FILE_IO",
"-DUCONFIG_NO_TRANSLITERATION",
+ "-DUCONFIG_NO_REGULAR_EXPRESSIONS",
"-DPKGDATA_MODE=static",
"-DU_ENABLE_DYLOAD=0",
"-DU_HAVE_LIB_SUFFIX=1",
@@ -480,7 +488,7 @@ if env["builtin_icu"]:
if env_text_server_adv["tools"]:
env_text_server_adv.Append(CXXFLAGS=["-DICU_STATIC_DATA"])
- env_text_server_adv.Append(CPPPATH=["#thirdparty/icu4c/common/"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
lib = env_icu.add_library("icu_builtin", thirdparty_sources)
thirdparty_obj += lib
@@ -504,13 +512,14 @@ if env["builtin_icu"]:
module_obj = []
if env["builtin_msdfgen"] and msdfgen_enabled:
- env_text_server_adv.Append(CPPPATH=["#thirdparty/msdfgen"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/msdfgen"])
if env["builtin_freetype"] and freetype_enabled:
- env_text_server_adv.Append(CPPPATH=["#thirdparty/freetype/include"])
+ env_text_server_adv.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/freetype/include"])
-if env["builtin_graphite"] and freetype_enabled:
- env_text_server_adv.Append(CPPPATH=["#thirdparty/graphite/include"])
+if env["builtin_graphite"] and freetype_enabled and env["graphite"]:
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/graphite/include"])
env_text_server_adv.add_source_files(module_obj, "*.cpp")
env.modules_sources += module_obj
diff --git a/modules/text_server_adv/config.py b/modules/text_server_adv/config.py
index 8c8df9b05e..179a2ff378 100644
--- a/modules/text_server_adv/config.py
+++ b/modules/text_server_adv/config.py
@@ -2,6 +2,14 @@ def can_build(env, platform):
return True
+def get_opts(platform):
+ from SCons.Variables import BoolVariable
+
+ return [
+ BoolVariable("graphite", "Enable SIL Graphite smart fonts support", True),
+ ]
+
+
def configure(env):
pass
diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct
index 0e36ef6805..0170c007ae 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",
@@ -624,15 +624,15 @@ env.Append(CPPDEFINES=["GDEXTENSION"])
env.Append(CPPPATH=["../"])
sources = Glob("../*.cpp")
-if env["platform"] == "osx":
- methods.write_osx_plist(
- f'./bin/libtextserver_advanced.osx.{env["target"]}.framework',
- f'libtextserver_advanced.osx.{env["target"]}',
+if env["platform"] == "macos":
+ methods.write_macos_plist(
+ f'./bin/libtextserver_advanced.macos.{env["target"]}.framework',
+ f'libtextserver_advanced.macos.{env["target"]}',
"org.godotengine.textserver_advanced",
"ICU / HarfBuzz / Graphite Text Server",
)
library = env.SharedLibrary(
- f'./bin/libtextserver_advanced.osx.{env["target"]}.framework/libtextserver_advanced.osx.{env["target"]}',
+ f'./bin/libtextserver_advanced.macos.{env["target"]}.framework/libtextserver_advanced.macos.{env["target"]}',
source=sources,
)
else:
diff --git a/modules/text_server_adv/gdextension_build/methods.py b/modules/text_server_adv/gdextension_build/methods.py
index d404f2851e..3c5229462c 100644
--- a/modules/text_server_adv/gdextension_build/methods.py
+++ b/modules/text_server_adv/gdextension_build/methods.py
@@ -98,7 +98,7 @@ def make_icu_data(target, source, env):
g.write("#endif")
-def write_osx_plist(target, binary_name, identifier, name):
+def write_macos_plist(target, binary_name, identifier, name):
os.makedirs(f"{target}/Resourece/", exist_ok=True)
f = open(f"{target}/Resourece/Info.plist", "w")
diff --git a/modules/text_server_adv/gdextension_build/text_server_adv.gdextension b/modules/text_server_adv/gdextension_build/text_server_adv.gdextension
index 5956476a5e..11ed271ae9 100644
--- a/modules/text_server_adv/gdextension_build/text_server_adv.gdextension
+++ b/modules/text_server_adv/gdextension_build/text_server_adv.gdextension
@@ -8,5 +8,5 @@ linux.64.debug = "bin/libtextserver_advanced.linux.debug.64.so"
linux.64.release = "bin/libtextserver_advanced.linux.release.64.so"
windows.64.debug = "bin/libtextserver_advanced.windows.debug.64.dll"
windows.64.release = "bin/libtextserver_advanced.windows.release.64.dll"
-macos.debug = "bin/libtextserver_advanced.osx.debug.framework"
-macos.release = "bin/libtextserver_advanced.osx.release.framework"
+macos.debug = "bin/libtextserver_advanced.macos.debug.framework"
+macos.release = "bin/libtextserver_advanced.macos.release.framework"
diff --git a/modules/text_server_adv/script_iterator.h b/modules/text_server_adv/script_iterator.h
index 2bd045b91a..025b62c6fb 100644
--- a/modules/text_server_adv/script_iterator.h
+++ b/modules/text_server_adv/script_iterator.h
@@ -75,4 +75,4 @@ public:
ScriptIterator(const String &p_string, int p_start, int p_length);
};
-#endif //SCRIPT_ITERATOR_H
+#endif // SCRIPT_ITERATOR_H
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index c4269a53f4..73dbf2f443 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "text_server_adv.h"
+#include "core/object/worker_thread_pool.h"
#ifdef GDEXTENSION
// Headers for building as GDExtension plug-in.
@@ -75,7 +76,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 +229,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);
@@ -345,6 +346,8 @@ bool TextServerAdvanced::has_feature(Feature p_feature) const {
case FEATURE_FONT_VARIABLE:
case FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION:
case FEATURE_USE_SUPPORT_DATA:
+ case FEATURE_UNICODE_IDENTIFIERS:
+ case FEATURE_UNICODE_SECURITY:
return true;
default: {
}
@@ -375,7 +378,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 +479,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 +751,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 +781,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 +978,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();
@@ -1017,10 +1042,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
td.projection = &projection;
td.distancePixelConversion = &distancePixelConversion;
- if (p_font_data->work_pool.get_thread_count() == 0) {
- p_font_data->work_pool.init();
- }
- p_font_data->work_pool.do_work(h, this, &TextServerAdvanced::_generateMTSDF_threaded, &td);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &TextServerAdvanced::_generateMTSDF_threaded, &td, h, -1, true, SNAME("FontServerRasterizeMSDF"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
msdfgen::msdfErrorCorrection(image, shape, projection, p_pixel_range, config);
@@ -1059,7 +1082,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 +1159,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 +1283,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.
@@ -1338,7 +1361,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
fd->underline_position = (-FT_MulFix(fd->face->underline_position, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale;
fd->underline_thickness = (FT_MulFix(fd->face->underline_thickness, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale;
+#if HB_VERSION_ATLEAST(3, 3, 0)
hb_font_set_synthetic_slant(fd->hb_handle, p_font_data->transform[0][1]);
+#else
+#ifndef _MSC_VER
+#warning Building with HarfBuzz < 3.3.0, synthetic slant offset correction disabled.
+#endif
+#endif
if (!p_font_data->face_init) {
// Get style flags and name.
@@ -1350,29 +1379,31 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
}
p_font_data->style_flags = 0;
if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) {
- p_font_data->style_flags |= FONT_BOLD;
+ p_font_data->style_flags.set_flag(FONT_BOLD);
}
if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) {
- p_font_data->style_flags |= FONT_ITALIC;
+ p_font_data->style_flags.set_flag(FONT_ITALIC);
}
if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) {
- p_font_data->style_flags |= FONT_FIXED_WIDTH;
+ p_font_data->style_flags.set_flag(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 +1627,61 @@ _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;
+
+#if HB_VERSION_ATLEAST(2, 1, 0)
+ 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)) {
+ PackedInt32Array 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);
+ memset((uint32_t *)lbl.ptrw(), 0, sizeof(uint32_t) * 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"] = String((const char32_t *)lbl.ptr());
+ }
+#else
+#ifndef _MSC_VER
+#warning Building with HarfBuzz < 2.1.0, readable OpenType feature names disabled.
+#endif
+#endif
+ 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;
+
+#if HB_VERSION_ATLEAST(2, 1, 0)
+ 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)) {
+ PackedInt32Array 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);
+ memset((uint32_t *)lbl.ptrw(), 0, sizeof(uint32_t) * 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"] = String((const char32_t *)lbl.ptr());
+ }
+#else
+#ifndef _MSC_VER
+#warning Building with HarfBuzz < 2.1.0, readable OpenType feature names disabled.
+#endif
+#endif
+ 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 +1747,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 +1759,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 +1773,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 +1790,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 +1804,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 +1815,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 +1823,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);
@@ -1792,8 +1863,8 @@ int64_t TextServerAdvanced::font_get_face_count(const RID &p_font_rid) const {
return face_count;
}
-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);
+void TextServerAdvanced::font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) {
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1802,8 +1873,8 @@ void TextServerAdvanced::font_set_style(const RID &p_font_rid, int64_t /*FontSty
fd->style_flags = p_style;
}
-int64_t /*FontStyle*/ TextServerAdvanced::font_get_style(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+BitField<TextServer::FontStyle> TextServerAdvanced::font_get_style(const RID &p_font_rid) const {
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -1813,7 +1884,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 +1894,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 +1904,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 +1914,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 +1924,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 +1935,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 +1943,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 +1958,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 +1966,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 +1977,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 +1985,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 +1996,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 +2004,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 +2015,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 +2023,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 +2031,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 +2039,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 +2050,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 +2058,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 +2069,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 +2077,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 +2085,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 +2093,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 +2104,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 +2112,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 +2123,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 +2131,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 +2142,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 +2150,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 +2161,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 +2169,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 +2203,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 +2214,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 +2230,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 +2240,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 +2256,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 +2267,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 +2283,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 +2294,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 +2310,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 +2326,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 +2341,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 +2354,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 +2364,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 +2376,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 +2402,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 +2424,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 +2440,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 +2453,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 +2469,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 +2480,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 +2491,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 +2505,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 +2533,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 +2548,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 +2569,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 +2584,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 +2605,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 +2620,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 +2636,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 +2651,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 +2667,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 +2682,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 +2707,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 +2721,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 +2746,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 +2760,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 +2810,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 +2819,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 +2837,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 +2848,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 +2859,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 +2892,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 +2917,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 +2925,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 +2936,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 +2969,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 +3002,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 +3031,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 +3077,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 +3109,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 +3155,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 +3187,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 +3199,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 +3207,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 +3215,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 +3223,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 +3235,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 +3249,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 +3257,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 +3265,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 +3273,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 +3285,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 +3295,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 +3303,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 +3313,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 +3593,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 +3885,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);
@@ -3972,7 +4013,7 @@ RID TextServerAdvanced::shaped_text_get_parent(const RID &p_shaped) const {
return sd->parent;
}
-double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags) {
+double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags) {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.0);
@@ -3988,7 +4029,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double
int start_pos = 0;
int end_pos = sd->glyphs.size() - 1;
- if ((p_jst_flags & JUSTIFICATION_AFTER_LAST_TAB) == JUSTIFICATION_AFTER_LAST_TAB) {
+ if (p_jst_flags.has_flag(JUSTIFICATION_AFTER_LAST_TAB)) {
int start, end, delta;
if (sd->para_direction == DIRECTION_LTR) {
start = sd->glyphs.size() - 1;
@@ -4014,7 +4055,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double
}
double justification_width;
- if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) == JUSTIFICATION_CONSTRAIN_ELLIPSIS) {
+ if (p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) {
if (sd->overrun_trim_data.trim_pos >= 0) {
if (sd->para_direction == DIRECTION_RTL) {
start_pos = sd->overrun_trim_data.trim_pos;
@@ -4029,7 +4070,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double
justification_width = sd->width;
}
- if ((p_jst_flags & JUSTIFICATION_TRIM_EDGE_SPACES) == JUSTIFICATION_TRIM_EDGE_SPACES) {
+ if (p_jst_flags.has_flag(JUSTIFICATION_TRIM_EDGE_SPACES)) {
// Trim spaces.
while ((start_pos < end_pos) && ((sd->glyphs[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
justification_width -= sd->glyphs[start_pos].advance * sd->glyphs[start_pos].repeat;
@@ -4068,7 +4109,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double
}
}
- if ((elongation_count > 0) && ((p_jst_flags & JUSTIFICATION_KASHIDA) == JUSTIFICATION_KASHIDA)) {
+ if ((elongation_count > 0) && p_jst_flags.has_flag(JUSTIFICATION_KASHIDA)) {
double delta_width_per_kashida = (p_width - justification_width) / elongation_count;
for (int i = start_pos; i <= end_pos; i++) {
Glyph &gl = sd->glyphs.write[i];
@@ -4089,7 +4130,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double
}
}
}
- if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) {
+ if ((space_count > 0) && p_jst_flags.has_flag(JUSTIFICATION_WORD_BOUND)) {
double delta_width_per_space = (p_width - justification_width) / space_count;
double adv_remain = 0;
for (int i = start_pos; i <= end_pos; i++) {
@@ -4122,7 +4163,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double
sd->fit_width_minimum_reached = true;
}
- if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) != JUSTIFICATION_CONSTRAIN_ELLIPSIS) {
+ if (!p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) {
sd->width = justification_width;
}
@@ -4185,7 +4226,7 @@ double TextServerAdvanced::shaped_text_tab_align(const RID &p_shaped, const Pack
return 0.0;
}
-void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) {
+void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped_line);
ERR_FAIL_COND_MSG(!sd, "ShapedTextDataAdvanced invalid.");
@@ -4197,10 +4238,10 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_l
sd->text_trimmed = false;
sd->overrun_trim_data.ellipsis_glyph_buf.clear();
- bool add_ellipsis = (p_trim_flags & OVERRUN_ADD_ELLIPSIS) == OVERRUN_ADD_ELLIPSIS;
- bool cut_per_word = (p_trim_flags & OVERRUN_TRIM_WORD_ONLY) == OVERRUN_TRIM_WORD_ONLY;
- bool enforce_ellipsis = (p_trim_flags & OVERRUN_ENFORCE_ELLIPSIS) == OVERRUN_ENFORCE_ELLIPSIS;
- bool justification_aware = (p_trim_flags & OVERRUN_JUSTIFICATION_AWARE) == OVERRUN_JUSTIFICATION_AWARE;
+ bool add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS);
+ bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY);
+ bool enforce_ellipsis = p_trim_flags.has_flag(OVERRUN_ENFORCE_ELLIPSIS);
+ bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE);
Glyph *sd_glyphs = sd->glyphs.ptrw();
@@ -4257,7 +4298,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 +4446,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++) {
@@ -4665,7 +4706,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(const RID &p_shape
for (int i = 0; i < sd_size; i++) {
if (sd_glyphs[i].count > 0) {
char32_t c = sd->text[sd_glyphs[i].start - sd->start];
- if (c == 0x0640) {
+ if (c == 0x0640 && sd_glyphs[i].start == sd_glyphs[i].end - 1) {
sd_glyphs[i].flags |= GRAPHEME_IS_ELONGATION;
}
if (sd->jstops.has(sd_glyphs[i].start)) {
@@ -4677,6 +4718,11 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(const RID &p_shape
if (sd_glyphs[i].font_rid != RID()) {
Glyph gl = _shape_single_glyph(sd, 0x0640, HB_SCRIPT_ARABIC, HB_DIRECTION_RTL, sd->glyphs[i].font_rid, sd->glyphs[i].font_size);
if ((sd_glyphs[i].flags & GRAPHEME_IS_VALID) == GRAPHEME_IS_VALID) {
+#if HB_VERSION_ATLEAST(5, 1, 0)
+ if ((i > 0) && ((sd_glyphs[i - 1].flags & GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL) != GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL)) {
+ continue;
+ }
+#endif
gl.start = sd_glyphs[i].start;
gl.end = sd_glyphs[i].end;
gl.repeat = 0;
@@ -4851,29 +4897,38 @@ 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);
hb_buffer_clear_contents(p_sd->hb_buffer);
hb_buffer_set_direction(p_sd->hb_buffer, p_direction);
+ int flags = (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0);
if (p_sd->preserve_control) {
- hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)(HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES | (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0)));
+ flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES;
} else {
- hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)(HB_BUFFER_FLAG_DEFAULT | (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0)));
+ flags |= HB_BUFFER_FLAG_DEFAULT;
}
+#if HB_VERSION_ATLEAST(5, 1, 0)
+ flags |= HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL;
+#endif
+ hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)flags);
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);
}
@@ -4931,10 +4986,16 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
gl.font_rid = p_fonts[p_fb_index];
gl.font_size = fs;
- if (glyph_info[i].mask & HB_GLYPH_FLAG_DEFINED) {
+ if (glyph_info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) {
gl.flags |= GRAPHEME_IS_CONNECTED;
}
+#if HB_VERSION_ATLEAST(5, 1, 0)
+ if (glyph_info[i].mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL) {
+ gl.flags |= GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL;
+ }
+#endif
+
gl.index = glyph_info[i].codepoint;
if (gl.index != 0) {
_ensure_glyph(fd, fss, gl.index);
@@ -4954,10 +5015,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 +5352,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 +5366,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 +5377,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 {
@@ -5593,6 +5657,68 @@ String TextServerAdvanced::percent_sign(const String &p_language) const {
return "%";
}
+int TextServerAdvanced::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
+ UErrorCode status = U_ZERO_ERROR;
+ int match_index = -1;
+
+ Char16String utf16 = p_string.utf16();
+ Vector<UChar *> skeletons;
+ skeletons.resize(p_dict.size());
+
+ USpoofChecker *sc = uspoof_open(&status);
+ uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status);
+ for (int i = 0; i < p_dict.size(); i++) {
+ Char16String word = p_dict[i].utf16();
+ int32_t len = uspoof_getSkeleton(sc, 0, word.get_data(), -1, NULL, 0, &status);
+ skeletons.write[i] = (UChar *)memalloc(++len * sizeof(UChar));
+ status = U_ZERO_ERROR;
+ uspoof_getSkeleton(sc, 0, word.get_data(), -1, skeletons.write[i], len, &status);
+ }
+
+ int32_t len = uspoof_getSkeleton(sc, 0, utf16.get_data(), -1, NULL, 0, &status);
+ UChar *skel = (UChar *)memalloc(++len * sizeof(UChar));
+ status = U_ZERO_ERROR;
+ uspoof_getSkeleton(sc, 0, utf16.get_data(), -1, skel, len, &status);
+ for (int i = 0; i < skeletons.size(); i++) {
+ if (u_strcmp(skel, skeletons[i]) == 0) {
+ match_index = i;
+ break;
+ }
+ }
+ memfree(skel);
+
+ for (int i = 0; i < skeletons.size(); i++) {
+ memfree(skeletons.write[i]);
+ }
+ uspoof_close(sc);
+
+ ERR_FAIL_COND_V_MSG(U_FAILURE(status), -1, u_errorName(status));
+
+ return match_index;
+}
+
+bool TextServerAdvanced::spoof_check(const String &p_string) const {
+ UErrorCode status = U_ZERO_ERROR;
+ Char16String utf16 = p_string.utf16();
+
+ USet *allowed = uset_openEmpty();
+ uset_addAll(allowed, uspoof_getRecommendedSet(&status));
+ uset_addAll(allowed, uspoof_getInclusionSet(&status));
+
+ USpoofChecker *sc = uspoof_open(&status);
+ uspoof_setAllowedChars(sc, allowed, &status);
+ uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE);
+
+ int32_t bitmask = uspoof_check(sc, utf16.get_data(), -1, NULL, &status);
+
+ uspoof_close(sc);
+ uset_close(allowed);
+
+ ERR_FAIL_COND_V_MSG(U_FAILURE(status), false, u_errorName(status));
+
+ return (bitmask != 0);
+}
+
String TextServerAdvanced::strip_diacritics(const String &p_string) const {
UErrorCode err = U_ZERO_ERROR;
@@ -5627,16 +5753,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 +5772,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 +5790,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++) {
@@ -5707,6 +5837,191 @@ PackedInt32Array TextServerAdvanced::string_get_word_breaks(const String &p_stri
return ret;
}
+bool TextServerAdvanced::is_valid_identifier(const String &p_string) const {
+ enum UAX31SequenceStatus {
+ SEQ_NOT_STARTED,
+ SEQ_STARTED,
+ SEQ_STARTED_VIR,
+ SEQ_NEAR_END,
+ };
+
+ const char32_t *str = p_string.ptr();
+ int len = p_string.length();
+
+ if (len == 0) {
+ return false; // Empty string.
+ }
+
+ UErrorCode err = U_ZERO_ERROR;
+ Char16String utf16 = p_string.utf16();
+ const UNormalizer2 *norm_c = unorm2_getNFCInstance(&err);
+ if (U_FAILURE(err)) {
+ return false; // Failed to load normalizer.
+ }
+ bool isnurom = unorm2_isNormalized(norm_c, utf16.ptr(), utf16.length(), &err);
+ if (U_FAILURE(err) || !isnurom) {
+ return false; // Do not conform to Normalization Form C.
+ }
+
+ UAX31SequenceStatus A1_sequence_status = SEQ_NOT_STARTED;
+ UScriptCode A1_scr = USCRIPT_INHERITED;
+ UAX31SequenceStatus A2_sequence_status = SEQ_NOT_STARTED;
+ UScriptCode A2_scr = USCRIPT_INHERITED;
+ UAX31SequenceStatus B_sequence_status = SEQ_NOT_STARTED;
+ UScriptCode B_scr = USCRIPT_INHERITED;
+
+ for (int i = 0; i < len; i++) {
+ err = U_ZERO_ERROR;
+ UScriptCode scr = uscript_getScript(str[i], &err);
+ if (U_FAILURE(err)) {
+ return false; // Invalid script.
+ }
+ if (uscript_getUsage(scr) != USCRIPT_USAGE_RECOMMENDED) {
+ return false; // Not a recommended script.
+ }
+ uint8_t cat = u_charType(str[i]);
+ int32_t jt = u_getIntPropertyValue(str[i], UCHAR_JOINING_TYPE);
+
+ // UAX #31 section 2.3 subsections A1, A2 and B, check ZWNJ and ZWJ usage.
+ switch (A1_sequence_status) {
+ case SEQ_NEAR_END: {
+ if ((A1_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A1_scr)) {
+ return false; // Mixed script.
+ }
+ if (jt == U_JT_RIGHT_JOINING || jt == U_JT_DUAL_JOINING) {
+ A1_sequence_status = SEQ_NOT_STARTED; // Valid end of sequence, reset.
+ } else if (jt != U_JT_TRANSPARENT) {
+ return false; // Invalid end of sequence.
+ }
+ } break;
+ case SEQ_STARTED: {
+ if ((A1_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A1_scr)) {
+ A1_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (jt != U_JT_TRANSPARENT) {
+ if (str[i] == 0x200C /*ZWNJ*/) {
+ A1_sequence_status = SEQ_NEAR_END;
+ continue;
+ } else {
+ A1_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ if (A1_sequence_status == SEQ_NOT_STARTED) {
+ if (jt == U_JT_LEFT_JOINING || jt == U_JT_DUAL_JOINING) {
+ A1_sequence_status = SEQ_STARTED;
+ A1_scr = scr;
+ }
+ };
+
+ switch (A2_sequence_status) {
+ case SEQ_NEAR_END: {
+ if ((A2_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A2_scr)) {
+ return false; // Mixed script.
+ }
+ if (cat == U_UPPERCASE_LETTER || cat == U_LOWERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_MODIFIER_LETTER || cat == U_OTHER_LETTER) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Valid end of sequence, reset.
+ } else if (cat != U_MODIFIER_LETTER || u_getCombiningClass(str[i]) == 0) {
+ return false; // Invalid end of sequence.
+ }
+ } break;
+ case SEQ_STARTED_VIR: {
+ if ((A2_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A2_scr)) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (str[i] == 0x200C /*ZWNJ*/) {
+ A2_sequence_status = SEQ_NEAR_END;
+ continue;
+ } else if (cat != U_MODIFIER_LETTER || u_getCombiningClass(str[i]) == 0) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ } break;
+ case SEQ_STARTED: {
+ if ((A2_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A2_scr)) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (u_getCombiningClass(str[i]) == 9 /*Virama Combining Class*/) {
+ A2_sequence_status = SEQ_STARTED_VIR;
+ } else if (cat != U_MODIFIER_LETTER) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ if (A2_sequence_status == SEQ_NOT_STARTED) {
+ if (cat == U_UPPERCASE_LETTER || cat == U_LOWERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_MODIFIER_LETTER || cat == U_OTHER_LETTER) {
+ A2_sequence_status = SEQ_STARTED;
+ A2_scr = scr;
+ }
+ }
+
+ switch (B_sequence_status) {
+ case SEQ_NEAR_END: {
+ if ((B_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != B_scr)) {
+ return false; // Mixed script.
+ }
+ if (u_getIntPropertyValue(str[i], UCHAR_INDIC_SYLLABIC_CATEGORY) != U_INSC_VOWEL_DEPENDENT) {
+ B_sequence_status = SEQ_NOT_STARTED; // Valid end of sequence, reset.
+ } else {
+ return false; // Invalid end of sequence.
+ }
+ } break;
+ case SEQ_STARTED_VIR: {
+ if ((B_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != B_scr)) {
+ B_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (str[i] == 0x200D /*ZWJ*/) {
+ B_sequence_status = SEQ_NEAR_END;
+ continue;
+ } else if (cat != U_MODIFIER_LETTER || u_getCombiningClass(str[i]) == 0) {
+ B_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ } break;
+ case SEQ_STARTED: {
+ if ((B_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != B_scr)) {
+ B_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (u_getCombiningClass(str[i]) == 9 /*Virama Combining Class*/) {
+ B_sequence_status = SEQ_STARTED_VIR;
+ } else if (cat != U_MODIFIER_LETTER) {
+ B_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ if (B_sequence_status == SEQ_NOT_STARTED) {
+ if (cat == U_UPPERCASE_LETTER || cat == U_LOWERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_MODIFIER_LETTER || cat == U_OTHER_LETTER) {
+ B_sequence_status = SEQ_STARTED;
+ B_scr = scr;
+ }
+ }
+
+ if (u_hasBinaryProperty(str[i], UCHAR_PATTERN_SYNTAX) || u_hasBinaryProperty(str[i], UCHAR_PATTERN_WHITE_SPACE) || u_hasBinaryProperty(str[i], UCHAR_NONCHARACTER_CODE_POINT)) {
+ return false; // Not a XID_Start or XID_Continue character.
+ }
+ if (i == 0) {
+ if (!(cat == U_LOWERCASE_LETTER || cat == U_UPPERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_OTHER_LETTER || cat == U_MODIFIER_LETTER || cat == U_LETTER_NUMBER || str[0] == 0x2118 || str[0] == 0x212E || str[0] == 0x309B || str[0] == 0x309C || str[0] == 0x005F)) {
+ return false; // Not a XID_Start character.
+ }
+ } else {
+ if (!(cat == U_LOWERCASE_LETTER || cat == U_UPPERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_OTHER_LETTER || cat == U_MODIFIER_LETTER || cat == U_LETTER_NUMBER || cat == U_NON_SPACING_MARK || cat == U_COMBINING_SPACING_MARK || cat == U_DECIMAL_DIGIT_NUMBER || cat == U_CONNECTOR_PUNCTUATION || str[i] == 0x2118 || str[i] == 0x212E || str[i] == 0x309B || str[i] == 0x309C || str[i] == 0x1369 || str[i] == 0x1371 || str[i] == 0x00B7 || str[i] == 0x0387 || str[i] == 0x19DA || str[i] == 0x0E33 || str[i] == 0x0EB3 || str[i] == 0xFF9E || str[i] == 0xFF9F)) {
+ return false; // Not a XID_Continue character.
+ }
+ }
+ }
+ return true;
+}
+
TextServerAdvanced::TextServerAdvanced() {
_insert_num_systems_lang();
_insert_feature_sets();
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index e7690cb70d..7ae329d616 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -65,11 +65,12 @@
#include <godot_cpp/classes/image.hpp>
#include <godot_cpp/classes/image_texture.hpp>
#include <godot_cpp/classes/ref.hpp>
+#include <godot_cpp/classes/worker_thread_pool.hpp>
#include <godot_cpp/templates/hash_map.hpp>
#include <godot_cpp/templates/hash_set.hpp>
#include <godot_cpp/templates/rid_owner.hpp>
-#include <godot_cpp/templates/thread_work_pool.hpp>
+
#include <godot_cpp/templates/vector.hpp>
using namespace godot;
@@ -77,9 +78,9 @@ using namespace godot;
#else
// Headers for building as built-in module.
+#include "core/object/worker_thread_pool.h"
#include "core/templates/hash_map.h"
#include "core/templates/rid_owner.h"
-#include "core/templates/thread_work_pool.h"
#include "scene/resources/texture.h"
#include "servers/text/text_server_extension.h"
@@ -100,6 +101,7 @@ using namespace godot;
#include <unicode/uloc.h>
#include <unicode/unorm2.h>
#include <unicode/uscript.h>
+#include <unicode/uspoof.h>
#include <unicode/ustring.h>
#include <unicode/utypes.h>
@@ -111,7 +113,10 @@ using namespace godot;
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
#include FT_BBOX_H
-
+#include FT_CONFIG_OPTIONS_H
+#if !defined(FT_CONFIG_OPTION_USE_BROTLI) && !defined(_MSC_VER)
+#warning FreeType is configured without Brotli support, built-in fonts will not be available.
+#endif
#include <hb-ft.h>
#include <hb-ot.h>
#endif
@@ -133,12 +138,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 +188,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 +196,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 +208,7 @@ class TextServerAdvanced : public TextServerExtension {
FT_StreamRec stream;
#endif
- ~FontDataForSizeAdvanced() {
+ ~FontForSizeAdvanced() {
if (hb_handle != nullptr) {
hb_font_destroy(hb_handle);
}
@@ -211,7 +220,7 @@ class TextServerAdvanced : public TextServerExtension {
}
};
- struct FontDataAdvanced {
+ struct FontAdvanced {
Mutex mutex;
bool antialiased = true;
@@ -228,11 +237,11 @@ class TextServerAdvanced : public TextServerExtension {
double embolden = 0.0;
Transform2D transform;
- uint32_t style_flags = 0;
+ BitField<TextServer::FontStyle> style_flags = 0;
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;
@@ -248,30 +257,28 @@ class TextServerAdvanced : public TextServerExtension {
const uint8_t *data_ptr;
size_t data_size;
int face_index = 0;
- mutable ThreadWorkPool work_pool;
- ~FontDataAdvanced() {
- work_pool.finish();
- for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : cache) {
+ ~FontAdvanced() {
+ 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 +288,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 +299,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 +360,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 +399,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 +417,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 +432,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;
@@ -479,8 +489,8 @@ public:
virtual int64_t font_get_face_count(const RID &p_font_rid) const override;
- virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override;
- virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override;
+ virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) override;
+ virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const override;
virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) override;
virtual String font_get_style_name(const RID &p_font_rid) const override;
@@ -546,9 +556,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 +653,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;
@@ -657,7 +667,7 @@ public:
virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override;
virtual RID shaped_text_get_parent(const RID &p_shaped) const override;
- virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
+ virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override;
virtual bool shaped_text_shape(const RID &p_shaped) override;
@@ -669,7 +679,7 @@ public:
virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override;
virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override;
- virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override;
+ virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) override;
virtual bool shaped_text_is_ready(const RID &p_shaped) const override;
@@ -695,7 +705,11 @@ public:
virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const override;
+ virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
+ virtual bool spoof_check(const String &p_string) const override;
+
virtual String strip_diacritics(const String &p_string) const override;
+ virtual bool is_valid_identifier(const String &p_string) const override;
virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
diff --git a/modules/text_server_fb/SCsub b/modules/text_server_fb/SCsub
index 121f38fcd5..429d2e1fdc 100644
--- a/modules/text_server_fb/SCsub
+++ b/modules/text_server_fb/SCsub
@@ -3,15 +3,16 @@
Import("env")
Import("env_modules")
-freetype_enabled = env.module_check_dependencies("text_server_fb", ["freetype"], True)
-msdfgen_enabled = env.module_check_dependencies("text_server_fb", ["msdfgen"], True)
+freetype_enabled = "freetype" in env.module_list
+msdfgen_enabled = "msdfgen" in env.module_list
env_text_server_fb = env_modules.Clone()
if env["builtin_msdfgen"] and msdfgen_enabled:
- env_text_server_fb.Append(CPPPATH=["#thirdparty/msdfgen"])
+ env_text_server_fb.Prepend(CPPPATH=["#thirdparty/msdfgen"])
if env["builtin_freetype"] and freetype_enabled:
- env_text_server_fb.Append(CPPPATH=["#thirdparty/freetype/include"])
+ env_text_server_fb.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
+ env_text_server_fb.Prepend(CPPPATH=["#thirdparty/freetype/include"])
env_text_server_fb.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct
index 6c9e10db18..de0a549900 100644
--- a/modules/text_server_fb/gdextension_build/SConstruct
+++ b/modules/text_server_fb/gdextension_build/SConstruct
@@ -184,15 +184,15 @@ env.Append(CPPDEFINES=["GDEXTENSION"])
env.Append(CPPPATH=["../"])
sources = Glob("../*.cpp")
-if env["platform"] == "osx":
- methods.write_osx_plist(
- f'./bin/libtextserver_fallback.osx.{env["target"]}.framework',
- f'libtextserver_fallback.osx.{env["target"]}',
+if env["platform"] == "macos":
+ methods.write_macos_plist(
+ f'./bin/libtextserver_fallback.macos.{env["target"]}.framework',
+ f'libtextserver_fallback.macos.{env["target"]}',
"org.godotengine.textserver_fallback",
"Fallback Text Server",
)
library = env.SharedLibrary(
- f'./bin/libtextserver_fallback.osx.{env["target"]}.framework/libtextserver_fallback.osx.{env["target"]}',
+ f'./bin/libtextserver_fallback.macos.{env["target"]}.framework/libtextserver_fallback.macos.{env["target"]}',
source=sources,
)
else:
diff --git a/modules/text_server_fb/gdextension_build/methods.py b/modules/text_server_fb/gdextension_build/methods.py
index d404f2851e..3c5229462c 100644
--- a/modules/text_server_fb/gdextension_build/methods.py
+++ b/modules/text_server_fb/gdextension_build/methods.py
@@ -98,7 +98,7 @@ def make_icu_data(target, source, env):
g.write("#endif")
-def write_osx_plist(target, binary_name, identifier, name):
+def write_macos_plist(target, binary_name, identifier, name):
os.makedirs(f"{target}/Resourece/", exist_ok=True)
f = open(f"{target}/Resourece/Info.plist", "w")
diff --git a/modules/text_server_fb/gdextension_build/text_server_fb.gdextension b/modules/text_server_fb/gdextension_build/text_server_fb.gdextension
index 1026c6cb85..9236555d63 100644
--- a/modules/text_server_fb/gdextension_build/text_server_fb.gdextension
+++ b/modules/text_server_fb/gdextension_build/text_server_fb.gdextension
@@ -8,5 +8,5 @@ linux.64.debug = "bin/libtextserver_fallback.linux.debug.64.so"
linux.64.release = "bin/libtextserver_fallback.linux.release.64.so"
windows.64.debug = "bin/libtextserver_fallback.windows.debug.64.dll"
windows.64.release = "bin/libtextserver_fallback.windows.release.64.dll"
-macos.debug = "bin/libtextserver_fallback.osx.debug.framework"
-macos.release = "bin/libtextserver_fallback.osx.release.framework"
+macos.debug = "bin/libtextserver_fallback.macos.debug.framework"
+macos.release = "bin/libtextserver_fallback.macos.release.framework"
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index f93c5909c9..55d912a10a 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();
@@ -461,10 +461,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
td.projection = &projection;
td.distancePixelConversion = &distancePixelConversion;
- if (p_font_data->work_pool.get_thread_count() == 0) {
- p_font_data->work_pool.init();
- }
- p_font_data->work_pool.do_work(h, this, &TextServerFallback::_generateMTSDF_threaded, &td);
+ WorkerThreadPool::GroupID group_id = WorkerThreadPool::get_singleton()->add_template_group_task(this, &TextServerFallback::_generateMTSDF_threaded, &td, h, -1, true, SNAME("TextServerFBRenderMSDF"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_id);
msdfgen::msdfErrorCorrection(image, shape, projection, p_pixel_range, config);
@@ -502,7 +500,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 +577,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 +703,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.
@@ -791,13 +789,13 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback
}
p_font_data->style_flags = 0;
if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) {
- p_font_data->style_flags |= FONT_BOLD;
+ p_font_data->style_flags.set_flag(FONT_BOLD);
}
if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) {
- p_font_data->style_flags |= FONT_ITALIC;
+ p_font_data->style_flags.set_flag(FONT_ITALIC);
}
if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) {
- p_font_data->style_flags |= FONT_FIXED_WIDTH;
+ p_font_data->style_flags.set_flag(FONT_FIXED_WIDTH);
}
// Read OpenType variations.
p_font_data->supported_varaitions.clear();
@@ -851,8 +849,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 +862,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 +879,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);
@@ -891,8 +889,8 @@ void TextServerFallback::font_set_data_ptr(const RID &p_font_rid, const uint8_t
fd->data_size = p_data_size;
}
-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);
+void TextServerFallback::font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) {
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -905,7 +903,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 +914,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 +922,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);
@@ -964,8 +962,8 @@ int64_t TextServerFallback::font_get_face_count(const RID &p_font_rid) const {
return face_count;
}
-int64_t /*FontStyle*/ TextServerFallback::font_get_style(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+BitField<TextServer::FontStyle> TextServerFallback::font_get_style(const RID &p_font_rid) const {
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -975,7 +973,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 +983,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 +993,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 +1003,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 +1013,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 +1024,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 +1032,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 +1047,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 +1055,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 +1066,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 +1074,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 +1085,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 +1093,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 +1104,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 +1112,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 +1120,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 +1128,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 +1139,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 +1147,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 +1158,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 +1166,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 +1174,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 +1182,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 +1193,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 +1201,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 +1212,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 +1220,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 +1231,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 +1239,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 +1250,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 +1258,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 +1292,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 +1303,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 +1319,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 +1329,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 +1345,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 +1356,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 +1372,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 +1383,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 +1399,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 +1415,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 +1430,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 +1443,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 +1453,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 +1465,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 +1491,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 +1513,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 +1529,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 +1542,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 +1558,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 +1569,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 +1580,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 +1608,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 +1623,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 +1644,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 +1659,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 +1680,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 +1695,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 +1711,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 +1726,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 +1742,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 +1757,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 +1782,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 +1796,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 +1821,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 +1835,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 +1885,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 +1901,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 +1912,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 +1923,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 +1934,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 +1974,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 +1982,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 +1993,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 +2026,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 +2059,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 +2088,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 +2134,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 +2166,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 +2212,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 +2244,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 +2256,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 +2264,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 +2272,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 +2280,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 +2292,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 +2304,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 +2312,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 +2320,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 +2330,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 +2342,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 +2352,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 +2364,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 +2570,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 +2877,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);
@@ -2980,7 +2948,7 @@ RID TextServerFallback::shaped_text_get_parent(const RID &p_shaped) const {
return sd->parent;
}
-double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags) {
+double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<JustificationFlag> p_jst_flags) {
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.0);
@@ -2995,7 +2963,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double
int start_pos = 0;
int end_pos = sd->glyphs.size() - 1;
- if ((p_jst_flags & JUSTIFICATION_AFTER_LAST_TAB) == JUSTIFICATION_AFTER_LAST_TAB) {
+ if (p_jst_flags.has_flag(JUSTIFICATION_AFTER_LAST_TAB)) {
int start, end, delta;
if (sd->para_direction == DIRECTION_LTR) {
start = sd->glyphs.size() - 1;
@@ -3021,7 +2989,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double
}
double justification_width;
- if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) == JUSTIFICATION_CONSTRAIN_ELLIPSIS) {
+ if (p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) {
if (sd->overrun_trim_data.trim_pos >= 0) {
end_pos = sd->overrun_trim_data.trim_pos;
justification_width = sd->width_trimmed;
@@ -3032,7 +3000,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double
justification_width = sd->width;
}
- if ((p_jst_flags & JUSTIFICATION_TRIM_EDGE_SPACES) == JUSTIFICATION_TRIM_EDGE_SPACES) {
+ if (p_jst_flags.has_flag(JUSTIFICATION_TRIM_EDGE_SPACES)) {
// Trim spaces.
while ((start_pos < end_pos) && ((sd->glyphs[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
justification_width -= sd->glyphs[start_pos].advance * sd->glyphs[start_pos].repeat;
@@ -3064,7 +3032,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double
}
}
- if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) {
+ if ((space_count > 0) && p_jst_flags.has_flag(JUSTIFICATION_WORD_BOUND)) {
double delta_width_per_space = (p_width - justification_width) / space_count;
for (int i = start_pos; i <= end_pos; i++) {
Glyph &gl = sd->glyphs.write[i];
@@ -3082,7 +3050,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double
sd->fit_width_minimum_reached = true;
}
- if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) != JUSTIFICATION_CONSTRAIN_ELLIPSIS) {
+ if (!p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) {
sd->width = justification_width;
}
@@ -3217,7 +3185,7 @@ bool TextServerFallback::shaped_text_update_justification_ops(const RID &p_shape
return true;
}
-void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) {
+void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) {
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped_line);
ERR_FAIL_COND_MSG(!sd, "ShapedTextDataFallback invalid.");
@@ -3229,10 +3197,10 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_l
sd->text_trimmed = false;
sd->overrun_trim_data.ellipsis_glyph_buf.clear();
- bool add_ellipsis = (p_trim_flags & OVERRUN_ADD_ELLIPSIS) == OVERRUN_ADD_ELLIPSIS;
- bool cut_per_word = (p_trim_flags & OVERRUN_TRIM_WORD_ONLY) == OVERRUN_TRIM_WORD_ONLY;
- bool enforce_ellipsis = (p_trim_flags & OVERRUN_ENFORCE_ELLIPSIS) == OVERRUN_ENFORCE_ELLIPSIS;
- bool justification_aware = (p_trim_flags & OVERRUN_JUSTIFICATION_AWARE) == OVERRUN_JUSTIFICATION_AWARE;
+ bool add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS);
+ bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY);
+ bool enforce_ellipsis = p_trim_flags.has_flag(OVERRUN_ENFORCE_ELLIPSIS);
+ bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE);
Glyph *sd_glyphs = sd->glyphs.ptrw();
@@ -3289,7 +3257,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 +3459,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 +3592,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 +3606,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 +3617,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..fef19d442b 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef TEXT_SERVER_FALLBACK_H
-#define TEXT_SERVER_FALLBACK_H
+#ifndef TEXT_SERVER_FB_H
+#define TEXT_SERVER_FB_H
/*************************************************************************/
/* Fallback Text Server provides simplified TS functionality, without */
@@ -79,9 +79,9 @@ using namespace godot;
#include "servers/text/text_server_extension.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/hash_map.h"
#include "core/templates/rid_owner.h"
-#include "core/templates/thread_work_pool.h"
#include "scene/resources/texture.h"
#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
@@ -98,6 +98,10 @@ using namespace godot;
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
#include FT_BBOX_H
+#include FT_CONFIG_OPTIONS_H
+#if !defined(FT_CONFIG_OPTION_USE_BROTLI) && !defined(_MSC_VER)
+#warning FreeType is configured without Brotli support, built-in fonts will not be available.
+#endif
#endif
/*************************************************************************/
@@ -144,7 +148,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 +156,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 +167,7 @@ class TextServerFallback : public TextServerExtension {
FT_StreamRec stream;
#endif
- ~FontDataForSizeFallback() {
+ ~FontForSizeFallback() {
#ifdef MODULE_FREETYPE_ENABLED
if (face != nullptr) {
FT_Done_Face(face);
@@ -175,7 +176,7 @@ class TextServerFallback : public TextServerExtension {
}
};
- struct FontDataFallback {
+ struct FontFallback {
Mutex mutex;
bool antialiased = true;
@@ -192,11 +193,11 @@ class TextServerFallback : public TextServerExtension {
double embolden = 0.0;
Transform2D transform;
- uint32_t style_flags = 0;
+ BitField<TextServer::FontStyle> style_flags = 0;
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;
@@ -211,30 +212,27 @@ class TextServerFallback : public TextServerExtension {
size_t data_size;
int face_index = 0;
- mutable ThreadWorkPool work_pool;
-
- ~FontDataFallback() {
- work_pool.finish();
- for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : cache) {
+ ~FontFallback() {
+ 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 +242,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 +310,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 +325,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;
@@ -370,8 +369,8 @@ public:
virtual int64_t font_get_face_count(const RID &p_font_rid) const override;
- virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override;
- virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override;
+ virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) override;
+ virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const override;
virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) override;
virtual String font_get_style_name(const RID &p_font_rid) const override;
@@ -437,9 +436,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 +532,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;
@@ -547,7 +546,7 @@ public:
virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override;
virtual RID shaped_text_get_parent(const RID &p_shaped) const override;
- virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
+ virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override;
virtual bool shaped_text_shape(const RID &p_shaped) override;
@@ -559,7 +558,7 @@ public:
virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override;
virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override;
- virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override;
+ virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) override;
virtual bool shaped_text_is_ready(const RID &p_shaped) const override;
@@ -588,4 +587,4 @@ public:
~TextServerFallback();
};
-#endif // TEXT_SERVER_FALLBACK_H
+#endif // TEXT_SERVER_FB_H
diff --git a/modules/tga/SCsub b/modules/tga/SCsub
index 067caa6ea0..ccd7d2ee37 100644
--- a/modules/tga/SCsub
+++ b/modules/tga/SCsub
@@ -5,5 +5,5 @@ Import("env_modules")
env_tga = env_modules.Clone()
-# Godot's own source files
+# Godot source files
env_tga.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/theora/config.py b/modules/theora/config.py
index 7f354a8fda..9a27e8e132 100644
--- a/modules/theora/config.py
+++ b/modules/theora/config.py
@@ -1,7 +1,8 @@
def can_build(env, platform):
if env["arch"].startswith("rv"):
return False
- return env.module_check_dependencies("theora", ["ogg", "vorbis"])
+ env.module_add_dependencies("theora", ["ogg", "vorbis"])
+ return True
def configure(env):
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/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h
index 8940ed6aff..00d799dc24 100644
--- a/modules/theora/video_stream_theora.h
+++ b/modules/theora/video_stream_theora.h
@@ -170,7 +170,7 @@ protected:
static void _bind_methods();
public:
- Ref<VideoStreamPlayback> instance_playback() override {
+ Ref<VideoStreamPlayback> instantiate_playback() override {
Ref<VideoStreamPlaybackTheora> pb = memnew(VideoStreamPlaybackTheora);
pb->set_audio_track(audio_track);
pb->set_file(file);
@@ -192,4 +192,4 @@ public:
virtual String get_resource_type(const String &p_path) const;
};
-#endif
+#endif // VIDEO_STREAM_THEORA_H
diff --git a/modules/tinyexr/image_loader_tinyexr.h b/modules/tinyexr/image_loader_tinyexr.h
index c147861c26..0d3de93956 100644
--- a/modules/tinyexr/image_loader_tinyexr.h
+++ b/modules/tinyexr/image_loader_tinyexr.h
@@ -40,4 +40,4 @@ public:
ImageLoaderTinyEXR();
};
-#endif
+#endif // IMAGE_LOADER_TINYEXR_H
diff --git a/modules/upnp/upnp.h b/modules/upnp/upnp.h
index 6d87b42c56..be7ede3ee0 100644
--- a/modules/upnp/upnp.h
+++ b/modules/upnp/upnp.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_UPNP_H
-#define GODOT_UPNP_H
+#ifndef UPNP_H
+#define UPNP_H
#include "core/object/ref_counted.h"
@@ -121,4 +121,4 @@ public:
VARIANT_ENUM_CAST(UPNP::UPNPResult)
-#endif // GODOT_UPNP_H
+#endif // UPNP_H
diff --git a/modules/upnp/upnp_device.h b/modules/upnp/upnp_device.h
index 18491dce27..1c9dc82df5 100644
--- a/modules/upnp/upnp_device.h
+++ b/modules/upnp/upnp_device.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_UPNP_DEVICE_H
-#define GODOT_UPNP_DEVICE_H
+#ifndef UPNP_DEVICE_H
+#define UPNP_DEVICE_H
#include "core/object/ref_counted.h"
@@ -90,4 +90,4 @@ private:
VARIANT_ENUM_CAST(UPNPDevice::IGDStatus)
-#endif // GODOT_UPNP_DEVICE_H
+#endif // UPNP_DEVICE_H
diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp
index ceea0eaf1d..7f8e9d8254 100644
--- a/modules/visual_script/editor/visual_script_editor.cpp
+++ b/modules/visual_script/editor/visual_script_editor.cpp
@@ -42,10 +42,32 @@
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/graph_edit.h"
+#include "scene/gui/separator.h"
#include "scene/gui/view_panner.h"
#include "scene/main/window.h"
#ifdef TOOLS_ENABLED
+
+void VisualScriptEditedProperty::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_edited_property", "value"), &VisualScriptEditedProperty::set_edited_property);
+ ClassDB::bind_method(D_METHOD("get_edited_property"), &VisualScriptEditedProperty::get_edited_property);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NIL, "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_edited_property", "get_edited_property");
+}
+
+void VisualScriptEditedProperty::set_edited_property(Variant p_variant) {
+ edited_property = p_variant;
+}
+
+Variant VisualScriptEditedProperty::get_edited_property() const {
+ return edited_property;
+}
+
+/////////////////
+
class VisualScriptEditorSignalEdit : public Object {
GDCLASS(VisualScriptEditorSignalEdit, Object);
@@ -376,6 +398,12 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
case Variant::VECTOR3I:
color = Color(0.84, 0.49, 0.93);
break;
+ case Variant::VECTOR4:
+ color = Color(0.84, 0.49, 0.94);
+ break;
+ case Variant::VECTOR4I:
+ color = Color(0.84, 0.49, 0.94);
+ break;
case Variant::TRANSFORM2D:
color = Color(0.77, 0.93, 0.41);
break;
@@ -681,8 +709,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
gnode->set_meta("__vnode", node);
gnode->set_name(itos(E));
- gnode->connect("dragged", callable_mp(this, &VisualScriptEditor::_node_moved), varray(E));
- gnode->connect("close_request", callable_mp(this, &VisualScriptEditor::_remove_node), varray(E), CONNECT_DEFERRED);
+ gnode->connect("dragged", callable_mp(this, &VisualScriptEditor::_node_moved).bind(E));
+ gnode->connect("close_request", callable_mp(this, &VisualScriptEditor::_remove_node).bind(E), CONNECT_DEFERRED);
{
Ref<VisualScriptFunction> v = node;
@@ -702,7 +730,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Input Port"));
hbnc->add_child(btn);
- btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_input_port), varray(E), CONNECT_DEFERRED);
+ btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_input_port).bind(E), CONNECT_DEFERRED);
}
if (nd_list->is_output_port_editable()) {
if (nd_list->is_input_port_editable()) {
@@ -712,7 +740,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Output Port"));
hbnc->add_child(btn);
- btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_output_port), varray(E), CONNECT_DEFERRED);
+ btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_output_port).bind(E), CONNECT_DEFERRED);
}
gnode->add_child(hbnc);
} else if (Object::cast_to<VisualScriptExpression>(node.ptr())) {
@@ -722,7 +750,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
line_edit->set_expand_to_text_length_enabled(true);
line_edit->add_theme_font_override("font", get_theme_font(SNAME("source"), SNAME("EditorFonts")));
gnode->add_child(line_edit);
- line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E));
+ line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed).bind(E));
} else {
String text = node->get_text();
if (!text.is_empty()) {
@@ -738,7 +766,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
gnode->set_comment(true);
gnode->set_resizable(true);
gnode->set_custom_minimum_size(vsc->get_size() * EDSCALE);
- gnode->connect("resize_request", callable_mp(this, &VisualScriptEditor::_comment_node_resized), varray(E));
+ gnode->connect("resize_request", callable_mp(this, &VisualScriptEditor::_comment_node_resized).bind(E));
}
if (node_styles.has(node->get_category())) {
@@ -841,8 +869,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0));
name_box->set_text(left_name);
name_box->set_expand_to_text_length_enabled(true);
- name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E));
- name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E, i, true));
+ name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size).bind(E));
+ name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out).bind(name_box, E, i, true));
} else {
hbc->add_child(memnew(Label(left_name)));
}
@@ -855,13 +883,13 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
opbtn->select(left_type);
opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
hbc->add_child(opbtn);
- opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E, i, true), CONNECT_DEFERRED);
+ opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type).bind(E, i, true), CONNECT_DEFERRED);
}
Button *rmbtn = memnew(Button);
rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
hbc->add_child(rmbtn);
- rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port), varray(E, i), CONNECT_DEFERRED);
+ rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port).bind(E, i), CONNECT_DEFERRED);
} else {
hbc->add_child(memnew(Label(left_name)));
}
@@ -880,7 +908,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
if (left_type == Variant::COLOR) {
button->set_custom_minimum_size(Size2(30, 0) * EDSCALE);
- button->connect("draw", callable_mp(this, &VisualScriptEditor::_draw_color_over_button), varray(button, value));
+ button->connect("draw", callable_mp(this, &VisualScriptEditor::_draw_color_over_button).bind(button, value));
} else if (left_type == Variant::OBJECT && Ref<Resource>(value).is_valid()) {
Ref<Resource> res = value;
Array arr;
@@ -935,7 +963,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
} else {
button->set_text(value);
}
- button->connect("pressed", callable_mp(this, &VisualScriptEditor::_default_value_edited), varray(button, E, i));
+ button->connect("pressed", callable_mp(this, &VisualScriptEditor::_default_value_edited).bind(button, E, i));
hbc2->add_child(button);
}
} else {
@@ -959,7 +987,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *rmbtn = memnew(Button);
rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
hbc->add_child(rmbtn);
- rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port), varray(E, i), CONNECT_DEFERRED);
+ rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port).bind(E, i), CONNECT_DEFERRED);
if (nd_list->is_output_port_type_editable()) {
OptionButton *opbtn = memnew(OptionButton);
@@ -969,7 +997,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
opbtn->select(right_type);
opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
hbc->add_child(opbtn);
- opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E, i, false), CONNECT_DEFERRED);
+ opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type).bind(E, i, false), CONNECT_DEFERRED);
}
if (nd_list->is_output_port_name_editable()) {
@@ -978,8 +1006,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0));
name_box->set_text(right_name);
name_box->set_expand_to_text_length_enabled(true);
- name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E));
- name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E, i, false));
+ name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size).bind(E));
+ name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out).bind(name_box, E, i, false));
} else {
hbc->add_child(memnew(Label(right_name)));
}
@@ -1227,7 +1255,7 @@ void VisualScriptEditor::_member_selected() {
selected = ti->get_metadata(0);
if (ti->get_parent() == members->get_root()->get_first_child()) {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::META);
#else
bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL);
@@ -1464,7 +1492,7 @@ void VisualScriptEditor::_add_func_input() {
func_input_vbox->add_child(hbox);
hbox->set_meta("id", hbox->get_index());
- delete_button->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_func_input), varray(hbox));
+ delete_button->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_func_input).bind(hbox));
name_box->select_all();
name_box->grab_focus();
@@ -2208,7 +2236,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant &
String(d["type"]) == "files" ||
String(d["type"]) == "nodes")) {
if (String(d["type"]) == "obj_property") {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Getter. Hold Shift to drop a generic signature."), find_keycode_name(Key::META)));
#else
const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature."));
@@ -2216,7 +2244,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant &
}
if (String(d["type"]) == "nodes") {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a simple reference to the node."), find_keycode_name(Key::META)));
#else
const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a simple reference to the node."));
@@ -2224,7 +2252,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant &
}
if (String(d["type"]) == "visual_script_variable_drag") {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Variable Setter."), find_keycode_name(Key::META)));
#else
const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a Variable Setter."));
@@ -2287,7 +2315,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
if (String(d["type"]) == "visual_script_variable_drag") {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
bool use_set = Input::get_singleton()->is_key_pressed(Key::META);
#else
bool use_set = Input::get_singleton()->is_key_pressed(Key::CTRL);
@@ -2396,7 +2424,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
if (String(d["type"]) == "files") {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
bool use_preload = Input::get_singleton()->is_key_pressed(Key::META);
#else
bool use_preload = Input::get_singleton()->is_key_pressed(Key::CTRL);
@@ -2459,7 +2487,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
return;
}
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
bool use_node = Input::get_singleton()->is_key_pressed(Key::META);
#else
bool use_node = Input::get_singleton()->is_key_pressed(Key::CTRL);
@@ -2524,7 +2552,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
Node *node = Object::cast_to<Node>(obj);
Vector2 pos = _get_pos_in_graph(p_point);
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
bool use_get = Input::get_singleton()->is_key_pressed(Key::META);
#else
bool use_get = Input::get_singleton()->is_key_pressed(Key::CTRL);
@@ -3378,7 +3406,7 @@ void VisualScriptEditor::connect_data(Ref<VisualScriptNode> vnode_old, Ref<Visua
}
void VisualScriptEditor::_selected_connect_node(const String &p_text, const String &p_category, const bool p_connecting) {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::META);
#else
bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL);
@@ -3892,14 +3920,14 @@ int VisualScriptEditor::_create_new_node_from_name(const String &p_text, const V
return new_id;
}
-void VisualScriptEditor::_default_value_changed() {
+void VisualScriptEditor::_default_value_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
Ref<VisualScriptNode> vsn = script->get_node(editing_id);
if (vsn.is_null()) {
return;
}
undo_redo->create_action(TTR("Change Input Value"));
- undo_redo->add_do_method(vsn.ptr(), "set_default_input_value", editing_input, default_value_edit->get_variant());
+ undo_redo->add_do_method(vsn.ptr(), "set_default_input_value", editing_input, p_value);
undo_redo->add_undo_method(vsn.ptr(), "set_default_input_value", editing_input, vsn->get_default_input_value(editing_input));
undo_redo->add_do_method(this, "_update_graph", editing_id);
@@ -3922,9 +3950,6 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i
Variant::construct(pinfo.type, existing, &existingp, 1, ce);
}
- default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_screen_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y) * graph->get_zoom());
- default_value_edit->reset_size();
-
if (pinfo.type == Variant::NODE_PATH) {
Node *edited_scene = get_tree()->get_edited_scene_root();
if (edited_scene) { // Fixing an old crash bug ( Visual Script Crashes on editing NodePath with an empty scene open).
@@ -3942,11 +3967,33 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i
}
}
- if (default_value_edit->edit(nullptr, pinfo.name, pinfo.type, existing, pinfo.hint, pinfo.hint_string)) {
- if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT) {
- default_value_edit->popup_centered_ratio();
+ edited_default_property_holder->set_edited_property(existing);
+
+ if (default_property_editor) {
+ default_property_editor->disconnect("property_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed));
+ default_property_editor_popup->remove_child(default_property_editor);
+ }
+
+ default_property_editor = EditorInspector::instantiate_property_editor(edited_default_property_holder.ptr(), pinfo.type, "edited_property", pinfo.hint, pinfo.hint_string, PROPERTY_USAGE_NONE);
+ if (default_property_editor) {
+ default_property_editor->set_object_and_property(edited_default_property_holder.ptr(), "edited_property");
+ default_property_editor->update_property();
+ default_property_editor->set_name_split_ratio(0);
+ default_property_editor_popup->add_child(default_property_editor);
+
+ default_property_editor->connect("property_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed));
+
+ Button *button = Object::cast_to<Button>(p_button);
+ if (button) {
+ default_property_editor_popup->set_position(button->get_screen_position() + Vector2(0, button->get_size().height) * graph->get_zoom());
+ }
+
+ default_property_editor_popup->reset_size();
+
+ if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT || !button) {
+ default_property_editor_popup->popup_centered_ratio();
} else {
- default_value_edit->popup();
+ default_property_editor_popup->popup();
}
}
@@ -3982,9 +4029,9 @@ void VisualScriptEditor::_notification(int p_what) {
case NOTIFICATION_READY: {
variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_members));
- variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph), varray(-1), CONNECT_DEFERRED);
+ variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph).bind(-1), CONNECT_DEFERRED);
signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_members));
- signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph), varray(-1), CONNECT_DEFERRED);
+ signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph).bind(-1), CONNECT_DEFERRED);
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
@@ -4602,7 +4649,7 @@ VisualScriptEditor::VisualScriptEditor() {
members->set_hide_root(true);
members->connect("button_clicked", callable_mp(this, &VisualScriptEditor::_member_button));
members->connect("item_edited", callable_mp(this, &VisualScriptEditor::_member_edited));
- members->connect("cell_selected", callable_mp(this, &VisualScriptEditor::_member_selected), varray(), CONNECT_DEFERRED);
+ members->connect("cell_selected", callable_mp(this, &VisualScriptEditor::_member_selected), CONNECT_DEFERRED);
members->connect("gui_input", callable_mp(this, &VisualScriptEditor::_members_gui_input));
members->connect("item_mouse_selected", callable_mp(this, &VisualScriptEditor::_member_rmb_selected));
members->set_allow_rmb_select(true);
@@ -4628,7 +4675,7 @@ VisualScriptEditor::VisualScriptEditor() {
graph = memnew(GraphEdit);
add_child(graph);
graph->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- graph->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ graph->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
graph->set_show_zoom_label(true);
graph->connect("node_selected", callable_mp(this, &VisualScriptEditor::_node_selected));
graph->connect("begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move));
@@ -4717,7 +4764,7 @@ VisualScriptEditor::VisualScriptEditor() {
function_create_dialog = memnew(ConfirmationDialog);
function_create_dialog->set_title(TTR("Create Function"));
function_create_dialog->add_child(function_vb);
- function_create_dialog->get_ok_button()->set_text(TTR("Create"));
+ function_create_dialog->set_ok_button_text(TTR("Create"));
function_create_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualScriptEditor::_create_function));
add_child(function_create_dialog);
@@ -4761,7 +4808,7 @@ VisualScriptEditor::VisualScriptEditor() {
graph->connect("connection_to_empty", callable_mp(this, &VisualScriptEditor::_graph_connect_to_empty));
edit_signal_dialog = memnew(AcceptDialog);
- edit_signal_dialog->get_ok_button()->set_text(TTR("Close"));
+ edit_signal_dialog->set_ok_button_text(TTR("Close"));
add_child(edit_signal_dialog);
signal_editor = memnew(VisualScriptEditorSignalEdit);
@@ -4771,7 +4818,7 @@ VisualScriptEditor::VisualScriptEditor() {
edit_signal_edit->edit(signal_editor);
edit_variable_dialog = memnew(AcceptDialog);
- edit_variable_dialog->get_ok_button()->set_text(TTR("Close"));
+ edit_variable_dialog->set_ok_button_text(TTR("Close"));
add_child(edit_variable_dialog);
variable_editor = memnew(VisualScriptEditorVariableEdit);
@@ -4789,9 +4836,11 @@ VisualScriptEditor::VisualScriptEditor() {
set_process_input(true);
- default_value_edit = memnew(CustomPropertyEditor);
- add_child(default_value_edit);
- default_value_edit->connect("variant_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed));
+ default_property_editor_popup = memnew(PopupPanel);
+ default_property_editor_popup->set_min_size(Size2i(180, 0) * EDSCALE);
+ add_child(default_property_editor_popup);
+
+ edited_default_property_holder.instantiate();
new_connect_node_select = memnew(VisualScriptPropertySelector);
add_child(new_connect_node_select);
@@ -4821,12 +4870,15 @@ VisualScriptEditor::VisualScriptEditor() {
base_type_map.insert("Rect2i", Variant::RECT2I);
base_type_map.insert("Vector3", Variant::VECTOR3);
base_type_map.insert("Vector3i", Variant::VECTOR3I);
+ base_type_map.insert("Vector4", Variant::VECTOR4);
+ base_type_map.insert("Vector4i", Variant::VECTOR4I);
base_type_map.insert("Transform2D", Variant::TRANSFORM2D);
base_type_map.insert("Plane", Variant::PLANE);
base_type_map.insert("Quaternion", Variant::QUATERNION);
base_type_map.insert("AABB", Variant::AABB);
base_type_map.insert("Basis", Variant::BASIS);
base_type_map.insert("Transform3D", Variant::TRANSFORM3D);
+ base_type_map.insert("Projection", Variant::PROJECTION);
base_type_map.insert("Color", Variant::COLOR);
base_type_map.insert("NodePath", Variant::NODE_PATH);
base_type_map.insert("RID", Variant::RID);
diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h
index fd59d22cbe..6b337e52f6 100644
--- a/modules/visual_script/editor/visual_script_editor.h
+++ b/modules/visual_script/editor/visual_script_editor.h
@@ -28,21 +28,37 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VISUALSCRIPT_EDITOR_H
-#define VISUALSCRIPT_EDITOR_H
+#ifndef VISUAL_SCRIPT_EDITOR_H
+#define VISUAL_SCRIPT_EDITOR_H
#include "../visual_script.h"
#include "editor/create_dialog.h"
#include "editor/plugins/script_editor_plugin.h"
-#include "editor/property_editor.h"
-#include "scene/gui/graph_edit.h"
#include "visual_script_property_selector.h"
+class GraphEdit;
+
class VisualScriptEditorSignalEdit;
class VisualScriptEditorVariableEdit;
#ifdef TOOLS_ENABLED
+class VisualScriptEditedProperty : public RefCounted {
+ GDCLASS(VisualScriptEditedProperty, RefCounted);
+
+private:
+ Variant edited_property;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_edited_property(Variant p_variant);
+ Variant get_edited_property() const;
+
+ VisualScriptEditedProperty() {}
+};
+
// TODO: Maybe this class should be refactored.
// See https://github.com/godotengine/godot/issues/51913
class VisualScriptEditor : public ScriptEditorBase {
@@ -115,7 +131,9 @@ class VisualScriptEditor : public ScriptEditorBase {
AcceptDialog *edit_variable_dialog = nullptr;
EditorInspector *edit_variable_edit = nullptr;
- CustomPropertyEditor *default_value_edit = nullptr;
+ PopupPanel *default_property_editor_popup = nullptr;
+ EditorProperty *default_property_editor = nullptr;
+ Ref<VisualScriptEditedProperty> edited_default_property_holder;
UndoRedo *undo_redo = nullptr;
@@ -276,7 +294,7 @@ class VisualScriptEditor : public ScriptEditorBase {
int data_disconnect_node = 0;
int data_disconnect_port = 0;
- void _default_value_changed();
+ void _default_value_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing);
void _default_value_edited(Node *p_button, int p_id, int p_input_port);
void _menu_option(int p_what);
@@ -374,4 +392,4 @@ public:
#endif
-#endif // VISUALSCRIPT_EDITOR_H
+#endif // VISUAL_SCRIPT_EDITOR_H
diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp
index ae30655301..712c89368b 100644
--- a/modules/visual_script/editor/visual_script_property_selector.cpp
+++ b/modules/visual_script/editor/visual_script_property_selector.cpp
@@ -39,6 +39,7 @@
#include "editor/doc_tools.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "scene/main/node.h"
#include "scene/main/window.h"
@@ -533,7 +534,7 @@ VisualScriptPropertySelector::VisualScriptPropertySelector() {
scroller->add_child(help_bit);
help_bit->connect("request_hide", callable_mp(this, &VisualScriptPropertySelector::_hide_requested));
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
get_ok_button()->set_disabled(true);
set_hide_on_ok(false);
}
diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h
index 91d81bba47..4de626467e 100644
--- a/modules/visual_script/editor/visual_script_property_selector.h
+++ b/modules/visual_script/editor/visual_script_property_selector.h
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VISUALSCRIPT_PROPERTYSELECTOR_H
-#define VISUALSCRIPT_PROPERTYSELECTOR_H
+#ifndef VISUAL_SCRIPT_PROPERTY_SELECTOR_H
+#define VISUAL_SCRIPT_PROPERTY_SELECTOR_H
#include "../visual_script.h"
#include "editor/editor_help.h"
-#include "editor/property_editor.h"
#include "scene/gui/rich_text_label.h"
+#include "scene/gui/tree.h"
class VisualScriptPropertySelector : public ConfirmationDialog {
GDCLASS(VisualScriptPropertySelector, ConfirmationDialog);
@@ -226,4 +226,4 @@ public:
SearchRunner(VisualScriptPropertySelector *p_selector_ui, Tree *p_results_tree);
};
-#endif // VISUALSCRIPT_PROPERTYSELECTOR_H
+#endif // VISUAL_SCRIPT_PROPERTY_SELECTOR_H
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index c5bcf23c8e..73249371cd 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -279,7 +279,7 @@ void VisualScript::add_node(int p_id, const Ref<VisualScriptNode> &p_node, const
nd.pos = p_pos;
Ref<VisualScriptNode> vsn = p_node;
- vsn->connect("ports_changed", callable_mp(this, &VisualScript::_node_ports_changed), varray(p_id));
+ vsn->connect("ports_changed", callable_mp(this, &VisualScript::_node_ports_changed).bind(p_id));
vsn->script_used = Ref<VisualScript>(this);
vsn->validate_input_default_values(); // Validate when fully loaded.
@@ -948,7 +948,7 @@ bool VisualScript::are_subnodes_edited() const {
}
#endif
-const Vector<Multiplayer::RPCConfig> VisualScript::get_rpc_methods() const {
+const Variant VisualScript::get_rpc_config() const {
return rpc_functions;
}
@@ -1012,22 +1012,16 @@ void VisualScript::_set_data(const Dictionary &p_data) {
for (const KeyValue<StringName, Function> &E : functions) {
if (E.value.func_id >= 0 && nodes.has(E.value.func_id)) {
Ref<VisualScriptFunction> vsf = nodes[E.value.func_id].node;
- if (vsf.is_valid()) {
- if (vsf->get_rpc_mode() != Multiplayer::RPC_MODE_DISABLED) {
- Multiplayer::RPCConfig nd;
- nd.name = E.key;
- nd.rpc_mode = vsf->get_rpc_mode();
- nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; // TODO
- if (rpc_functions.find(nd) == -1) {
- rpc_functions.push_back(nd);
- }
- }
+ if (!vsf.is_valid() || vsf->get_rpc_mode() == MultiplayerAPI::RPC_MODE_DISABLED) {
+ continue;
}
+ Dictionary nd;
+ nd["rpc_mode"] = vsf->get_rpc_mode();
+ nd["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE; // TODO
+ nd["call_local"] = false; // TODO
+ rpc_functions[E.key] = nd;
}
}
-
- // Sort so we are 100% that they are always the same.
- rpc_functions.sort_custom<Multiplayer::SortRPCConfig>();
}
Dictionary VisualScript::_get_data() const {
@@ -1212,6 +1206,10 @@ bool VisualScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
}
void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
+#ifdef TOOLS_ENABLED
+ p_properties->push_back(script->get_class_category());
+#endif // TOOLS_ENABLED
+
for (const KeyValue<StringName, VisualScript::Variable> &E : script->variables) {
if (!E.value._export) {
continue;
@@ -1811,8 +1809,8 @@ Ref<Script> VisualScriptInstance::get_script() const {
return script;
}
-const Vector<Multiplayer::RPCConfig> VisualScriptInstance::get_rpc_methods() const {
- return script->get_rpc_methods();
+const Variant VisualScriptInstance::get_rpc_config() const {
+ return script->get_rpc_config();
}
void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) {
@@ -2128,7 +2126,14 @@ void VisualScriptFunctionState::connect_to_signal(Object *p_obj, const String &p
binds.push_back(p_binds[i]);
}
binds.push_back(Ref<VisualScriptFunctionState>(this)); //add myself on the back to avoid dying from unreferencing
- p_obj->connect(p_signal, Callable(this, "_signal_callback"), binds, CONNECT_ONESHOT);
+
+ Vector<const Variant *> bind_ptrs;
+ bind_ptrs.resize(p_binds.size());
+ for (int i = 0; i < bind_ptrs.size(); i++) {
+ bind_ptrs.write[i] = &binds.write[i];
+ }
+
+ p_obj->connect(p_signal, Callable(this, "_signal_callback").bindp((const Variant **)bind_ptrs.ptr(), bind_ptrs.size()), CONNECT_ONESHOT);
}
bool VisualScriptFunctionState::is_valid() const {
@@ -2435,6 +2440,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..14cb14e8d9 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -235,7 +235,7 @@ private:
HashMap<StringName, Function> functions;
HashMap<StringName, Variable> variables;
HashMap<StringName, Vector<Argument>> custom_signals;
- Vector<Multiplayer::RPCConfig> rpc_functions;
+ Dictionary rpc_functions;
HashMap<Object *, VisualScriptInstance *> instances;
@@ -363,7 +363,7 @@ public:
virtual int get_member_line(const StringName &p_member) const override;
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
+ virtual const Variant get_rpc_config() const override;
#ifdef TOOLS_ENABLED
virtual bool are_subnodes_edited() const;
@@ -444,7 +444,7 @@ public:
virtual ScriptLanguage *get_language();
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const;
+ virtual const Variant get_rpc_config() const;
VisualScriptInstance();
~VisualScriptInstance();
@@ -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/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h
index c93eb0686b..7e10f98f36 100644
--- a/modules/visual_script/visual_script_expression.h
+++ b/modules/visual_script/visual_script_expression.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VISUALSCRIPTEXPRESSION_H
-#define VISUALSCRIPTEXPRESSION_H
+#ifndef VISUAL_SCRIPT_EXPRESSION_H
+#define VISUAL_SCRIPT_EXPRESSION_H
#include "visual_script.h"
#include "visual_script_builtin_funcs.h"
@@ -281,4 +281,4 @@ public:
void register_visual_script_expression_node();
-#endif // VISUALSCRIPTEXPRESSION_H
+#endif // VISUAL_SCRIPT_EXPRESSION_H
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 2dfc6da181..5907e6a489 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -90,7 +90,7 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value
}
if (p_name == "rpc/mode") {
- rpc_mode = Multiplayer::RPCMode(int(p_value));
+ rpc_mode = MultiplayerAPI::RPCMode(int(p_value));
return true;
}
@@ -261,11 +261,11 @@ int VisualScriptFunction::get_argument_count() const {
return arguments.size();
}
-void VisualScriptFunction::set_rpc_mode(Multiplayer::RPCMode p_mode) {
+void VisualScriptFunction::set_rpc_mode(MultiplayerAPI::RPCMode p_mode) {
rpc_mode = p_mode;
}
-Multiplayer::RPCMode VisualScriptFunction::get_rpc_mode() const {
+MultiplayerAPI::RPCMode VisualScriptFunction::get_rpc_mode() const {
return rpc_mode;
}
@@ -311,14 +311,14 @@ void VisualScriptFunction::reset_state() {
stack_size = 256;
stack_less = false;
sequenced = true;
- rpc_mode = Multiplayer::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
}
VisualScriptFunction::VisualScriptFunction() {
stack_size = 256;
stack_less = false;
sequenced = true;
- rpc_mode = Multiplayer::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
}
void VisualScriptFunction::set_stack_less(bool p_enable) {
@@ -4025,6 +4025,8 @@ void register_visual_script_nodes() {
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2I), create_node_deconst_typed<Variant::Type::VECTOR2I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3), create_node_deconst_typed<Variant::Type::VECTOR3>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3I), create_node_deconst_typed<Variant::Type::VECTOR3I>);
+ VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR4), create_node_deconst_typed<Variant::Type::VECTOR4>);
+ VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR4I), create_node_deconst_typed<Variant::Type::VECTOR4I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::COLOR), create_node_deconst_typed<Variant::Type::COLOR>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2), create_node_deconst_typed<Variant::Type::RECT2>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2I), create_node_deconst_typed<Variant::Type::RECT2I>);
@@ -4034,6 +4036,7 @@ void register_visual_script_nodes() {
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::AABB), create_node_deconst_typed<Variant::Type::AABB>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::BASIS), create_node_deconst_typed<Variant::Type::BASIS>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM3D), create_node_deconst_typed<Variant::Type::TRANSFORM3D>);
+ VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::PROJECTION), create_node_deconst_typed<Variant::Type::PROJECTION>);
VisualScriptLanguage::singleton->add_register_func("functions/compose_array", create_node_generic<VisualScriptComposeArray>);
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index 18573f8682..35e3c490cd 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -33,6 +33,7 @@
#include "core/object/gdvirtual.gen.inc"
#include "core/object/script_language.h"
+#include "scene/main/multiplayer_api.h"
#include "visual_script.h"
class VisualScriptFunction : public VisualScriptNode {
@@ -49,7 +50,7 @@ class VisualScriptFunction : public VisualScriptNode {
bool stack_less;
int stack_size;
- Multiplayer::RPCMode rpc_mode;
+ MultiplayerAPI::RPCMode rpc_mode;
bool sequenced;
protected:
@@ -90,8 +91,8 @@ public:
void set_stack_size(int p_size);
int get_stack_size() const;
- void set_rpc_mode(Multiplayer::RPCMode p_mode);
- Multiplayer::RPCMode get_rpc_mode() const;
+ void set_rpc_mode(MultiplayerAPI::RPCMode p_mode);
+ MultiplayerAPI::RPCMode get_rpc_mode() const;
virtual VisualScriptNodeInstance *instantiate(VisualScriptInstance *p_instance) override;
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 89a6b03ff8..8315eea614 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -34,7 +34,7 @@
#include "core/variant/typed_array.h"
#include "thirdparty/libogg/ogg/ogg.h"
-int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
+int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
ERR_FAIL_COND_V(!ready, 0);
if (!active) {
@@ -43,28 +43,93 @@ int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram
int todo = p_frames;
- int start_buffer = 0;
+ int beat_length_frames = -1;
+ bool beat_loop = vorbis_stream->has_loop();
+ if (beat_loop && vorbis_stream->get_bpm() > 0 && vorbis_stream->get_beat_count() > 0) {
+ beat_length_frames = vorbis_stream->get_beat_count() * vorbis_data->get_sampling_rate() * 60 / vorbis_stream->get_bpm();
+ }
while (todo > 0 && active) {
AudioFrame *buffer = p_buffer;
- if (start_buffer > 0) {
- buffer = buffer + start_buffer;
+ buffer += p_frames - todo;
+
+ int to_mix = todo;
+ if (beat_length_frames >= 0 && (beat_length_frames - (int)frames_mixed) < to_mix) {
+ to_mix = MAX(0, beat_length_frames - (int)frames_mixed);
}
- int mixed = _mix_frames_vorbis(buffer, todo);
+
+ int mixed = _mix_frames_vorbis(buffer, to_mix);
ERR_FAIL_COND_V(mixed < 0, 0);
todo -= mixed;
frames_mixed += mixed;
- start_buffer += mixed;
+
+ if (loop_fade_remaining < FADE_SIZE) {
+ int to_fade = loop_fade_remaining + MIN(FADE_SIZE - loop_fade_remaining, mixed);
+ for (int i = loop_fade_remaining; i < to_fade; i++) {
+ buffer[i - loop_fade_remaining] += loop_fade[i] * (float(FADE_SIZE - i) / float(FADE_SIZE));
+ }
+ loop_fade_remaining = to_fade;
+ }
+
+ if (beat_length_frames >= 0) {
+ /**
+ * Length determined by beat length
+ * This code is commented out because, in practice, it is prefered that the fade
+ * is done by the transitioner and this stream just goes on until it ends while fading out.
+ *
+ * End fade implementation is left here for reference in case at some point this feature
+ * is desired.
+
+ if (!beat_loop && (int)frames_mixed > beat_length_frames - FADE_SIZE) {
+ print_line("beat length fade/after mix?");
+ //No loop, just fade and finish
+ for (int i = 0; i < mixed; i++) {
+ int idx = frames_mixed + i - mixed;
+ buffer[i] *= 1.0 - float(MAX(0, (idx - (beat_length_frames - FADE_SIZE)))) / float(FADE_SIZE);
+ }
+ if ((int)frames_mixed == beat_length_frames) {
+ for (int i = p_frames - todo; i < p_frames; i++) {
+ p_buffer[i] = AudioFrame(0, 0);
+ }
+ active = false;
+ break;
+ }
+ } else
+ **/
+
+ if (beat_loop && beat_length_frames <= (int)frames_mixed) {
+ // End of file when doing beat-based looping. <= used instead of == because importer editing
+ if (!have_packets_left && !have_samples_left) {
+ //Nothing remaining, so do nothing.
+ loop_fade_remaining = FADE_SIZE;
+ } else {
+ // Add some loop fade;
+ int faded_mix = _mix_frames_vorbis(loop_fade, FADE_SIZE);
+
+ for (int i = faded_mix; i < FADE_SIZE; i++) {
+ // In case lesss was mixed, pad with zeros
+ loop_fade[i] = AudioFrame(0, 0);
+ }
+ loop_fade_remaining = 0;
+ }
+
+ seek(vorbis_stream->loop_offset);
+ loops++;
+ // We still have buffer to fill, start from this element in the next iteration.
+ continue;
+ }
+ }
+
if (!have_packets_left && !have_samples_left) {
- //end of file!
+ // Actual end of file!
bool is_not_empty = mixed > 0 || vorbis_stream->get_length() > 0;
if (vorbis_stream->loop && is_not_empty) {
//loop
seek(vorbis_stream->loop_offset);
loops++;
- // we still have buffer to fill, start from this element in the next iteration.
- start_buffer = p_frames - todo;
+ // We still have buffer to fill, start from this element in the next iteration.
+
} else {
for (int i = p_frames - todo; i < p_frames; i++) {
p_buffer[i] = AudioFrame(0, 0);
@@ -76,7 +141,7 @@ int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram
return p_frames - todo;
}
-int AudioStreamPlaybackOGGVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p_frames) {
+int AudioStreamPlaybackOggVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p_frames) {
ERR_FAIL_COND_V(!ready, 0);
if (!have_samples_left) {
ogg_packet *packet = nullptr;
@@ -119,18 +184,18 @@ int AudioStreamPlaybackOGGVorbis::_mix_frames_vorbis(AudioFrame *p_buffer, int p
return frames;
}
-float AudioStreamPlaybackOGGVorbis::get_stream_sampling_rate() {
+float AudioStreamPlaybackOggVorbis::get_stream_sampling_rate() {
return vorbis_data->get_sampling_rate();
}
-bool AudioStreamPlaybackOGGVorbis::_alloc_vorbis() {
+bool AudioStreamPlaybackOggVorbis::_alloc_vorbis() {
vorbis_info_init(&info);
info_is_allocated = true;
vorbis_comment_init(&comment);
comment_is_allocated = true;
ERR_FAIL_COND_V(vorbis_data.is_null(), false);
- vorbis_data_playback = vorbis_data->instance_playback();
+ vorbis_data_playback = vorbis_data->instantiate_playback();
ogg_packet *packet;
int err;
@@ -158,31 +223,36 @@ bool AudioStreamPlaybackOGGVorbis::_alloc_vorbis() {
return true;
}
-void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) {
+void AudioStreamPlaybackOggVorbis::start(float p_from_pos) {
ERR_FAIL_COND(!ready);
+ loop_fade_remaining = FADE_SIZE;
active = true;
seek(p_from_pos);
loops = 0;
begin_resample();
}
-void AudioStreamPlaybackOGGVorbis::stop() {
+void AudioStreamPlaybackOggVorbis::stop() {
active = false;
}
-bool AudioStreamPlaybackOGGVorbis::is_playing() const {
+bool AudioStreamPlaybackOggVorbis::is_playing() const {
return active;
}
-int AudioStreamPlaybackOGGVorbis::get_loop_count() const {
+int AudioStreamPlaybackOggVorbis::get_loop_count() const {
return loops;
}
-float AudioStreamPlaybackOGGVorbis::get_playback_position() const {
+float AudioStreamPlaybackOggVorbis::get_playback_position() const {
return float(frames_mixed) / vorbis_data->get_sampling_rate();
}
-void AudioStreamPlaybackOGGVorbis::seek(float p_time) {
+void AudioStreamPlaybackOggVorbis::tag_used_streams() {
+ vorbis_stream->tag_used(get_playback_position());
+}
+
+void AudioStreamPlaybackOggVorbis::seek(float p_time) {
ERR_FAIL_COND(!ready);
ERR_FAIL_COND(vorbis_stream.is_null());
if (!active) {
@@ -300,7 +370,7 @@ void AudioStreamPlaybackOGGVorbis::seek(float p_time) {
}
}
-AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() {
+AudioStreamPlaybackOggVorbis::~AudioStreamPlaybackOggVorbis() {
if (block_is_allocated) {
vorbis_block_clear(&block);
}
@@ -315,13 +385,13 @@ AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() {
}
}
-Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() {
- Ref<AudioStreamPlaybackOGGVorbis> ovs;
+Ref<AudioStreamPlayback> AudioStreamOggVorbis::instantiate_playback() {
+ Ref<AudioStreamPlaybackOggVorbis> ovs;
ERR_FAIL_COND_V(packet_sequence.is_null(), nullptr);
ovs.instantiate();
- ovs->vorbis_stream = Ref<AudioStreamOGGVorbis>(this);
+ ovs->vorbis_stream = Ref<AudioStreamOggVorbis>(this);
ovs->vorbis_data = packet_sequence;
ovs->frames_mixed = 0;
ovs->active = false;
@@ -333,11 +403,11 @@ Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() {
return nullptr;
}
-String AudioStreamOGGVorbis::get_stream_name() const {
+String AudioStreamOggVorbis::get_stream_name() const {
return ""; //return stream_name;
}
-void AudioStreamOGGVorbis::maybe_update_info() {
+void AudioStreamOggVorbis::maybe_update_info() {
ERR_FAIL_COND(packet_sequence.is_null());
vorbis_info info;
@@ -347,7 +417,7 @@ void AudioStreamOGGVorbis::maybe_update_info() {
vorbis_info_init(&info);
vorbis_comment_init(&comment);
- Ref<OGGPacketSequencePlayback> packet_sequence_playback = packet_sequence->instance_playback();
+ Ref<OggPacketSequencePlayback> packet_sequence_playback = packet_sequence->instantiate_playback();
for (int i = 0; i < 3; i++) {
ogg_packet *packet;
@@ -373,57 +443,99 @@ void AudioStreamOGGVorbis::maybe_update_info() {
vorbis_info_clear(&info);
}
-void AudioStreamOGGVorbis::set_packet_sequence(Ref<OGGPacketSequence> p_packet_sequence) {
+void AudioStreamOggVorbis::set_packet_sequence(Ref<OggPacketSequence> p_packet_sequence) {
packet_sequence = p_packet_sequence;
if (packet_sequence.is_valid()) {
maybe_update_info();
}
}
-Ref<OGGPacketSequence> AudioStreamOGGVorbis::get_packet_sequence() const {
+Ref<OggPacketSequence> AudioStreamOggVorbis::get_packet_sequence() const {
return packet_sequence;
}
-void AudioStreamOGGVorbis::set_loop(bool p_enable) {
+void AudioStreamOggVorbis::set_loop(bool p_enable) {
loop = p_enable;
}
-bool AudioStreamOGGVorbis::has_loop() const {
+bool AudioStreamOggVorbis::has_loop() const {
return loop;
}
-void AudioStreamOGGVorbis::set_loop_offset(float p_seconds) {
+void AudioStreamOggVorbis::set_loop_offset(float p_seconds) {
loop_offset = p_seconds;
}
-float AudioStreamOGGVorbis::get_loop_offset() const {
+float AudioStreamOggVorbis::get_loop_offset() const {
return loop_offset;
}
-float AudioStreamOGGVorbis::get_length() const {
+float AudioStreamOggVorbis::get_length() const {
ERR_FAIL_COND_V(packet_sequence.is_null(), 0);
return packet_sequence->get_length();
}
-bool AudioStreamOGGVorbis::is_monophonic() const {
+void AudioStreamOggVorbis::set_bpm(double p_bpm) {
+ ERR_FAIL_COND(p_bpm < 0);
+ bpm = p_bpm;
+ emit_changed();
+}
+
+double AudioStreamOggVorbis::get_bpm() const {
+ return bpm;
+}
+
+void AudioStreamOggVorbis::set_beat_count(int p_beat_count) {
+ ERR_FAIL_COND(p_beat_count < 0);
+ beat_count = p_beat_count;
+ emit_changed();
+}
+
+int AudioStreamOggVorbis::get_beat_count() const {
+ return beat_count;
+}
+
+void AudioStreamOggVorbis::set_bar_beats(int p_bar_beats) {
+ ERR_FAIL_COND(p_bar_beats < 2);
+ bar_beats = p_bar_beats;
+ emit_changed();
+}
+
+int AudioStreamOggVorbis::get_bar_beats() const {
+ return bar_beats;
+}
+
+bool AudioStreamOggVorbis::is_monophonic() const {
return false;
}
-void AudioStreamOGGVorbis::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_packet_sequence", "packet_sequence"), &AudioStreamOGGVorbis::set_packet_sequence);
- ClassDB::bind_method(D_METHOD("get_packet_sequence"), &AudioStreamOGGVorbis::get_packet_sequence);
+void AudioStreamOggVorbis::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_packet_sequence", "packet_sequence"), &AudioStreamOggVorbis::set_packet_sequence);
+ ClassDB::bind_method(D_METHOD("get_packet_sequence"), &AudioStreamOggVorbis::get_packet_sequence);
+
+ ClassDB::bind_method(D_METHOD("set_loop", "enable"), &AudioStreamOggVorbis::set_loop);
+ ClassDB::bind_method(D_METHOD("has_loop"), &AudioStreamOggVorbis::has_loop);
+
+ ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOggVorbis::set_loop_offset);
+ ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOggVorbis::get_loop_offset);
+
+ ClassDB::bind_method(D_METHOD("set_bpm", "bpm"), &AudioStreamOggVorbis::set_bpm);
+ ClassDB::bind_method(D_METHOD("get_bpm"), &AudioStreamOggVorbis::get_bpm);
- ClassDB::bind_method(D_METHOD("set_loop", "enable"), &AudioStreamOGGVorbis::set_loop);
- ClassDB::bind_method(D_METHOD("has_loop"), &AudioStreamOGGVorbis::has_loop);
+ ClassDB::bind_method(D_METHOD("set_beat_count", "count"), &AudioStreamOggVorbis::set_beat_count);
+ ClassDB::bind_method(D_METHOD("get_beat_count"), &AudioStreamOggVorbis::get_beat_count);
- ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOGGVorbis::set_loop_offset);
- ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOGGVorbis::get_loop_offset);
+ ClassDB::bind_method(D_METHOD("set_bar_beats", "count"), &AudioStreamOggVorbis::set_bar_beats);
+ ClassDB::bind_method(D_METHOD("get_bar_beats"), &AudioStreamOggVorbis::get_bar_beats);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packet_sequence", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_sequence", "get_packet_sequence");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), "set_bpm", "get_bpm");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,1,or_greater"), "set_beat_count", "get_beat_count");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,1,or_greater"), "set_bar_beats", "get_bar_beats");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset"), "set_loop_offset", "get_loop_offset");
}
-AudioStreamOGGVorbis::AudioStreamOGGVorbis() {}
+AudioStreamOggVorbis::AudioStreamOggVorbis() {}
-AudioStreamOGGVorbis::~AudioStreamOGGVorbis() {}
+AudioStreamOggVorbis::~AudioStreamOggVorbis() {}
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h
index b09ef9ff5d..0350e1f761 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.h
+++ b/modules/vorbis/audio_stream_ogg_vorbis.h
@@ -28,23 +28,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIO_STREAM_LIBVORBIS_H
-#define AUDIO_STREAM_LIBVORBIS_H
+#ifndef AUDIO_STREAM_OGG_VORBIS_H
+#define AUDIO_STREAM_OGG_VORBIS_H
#include "core/variant/variant.h"
#include "modules/ogg/ogg_packet_sequence.h"
#include "servers/audio/audio_stream.h"
#include "thirdparty/libvorbis/vorbis/codec.h"
-class AudioStreamOGGVorbis;
+class AudioStreamOggVorbis;
-class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled {
- GDCLASS(AudioStreamPlaybackOGGVorbis, AudioStreamPlaybackResampled);
+class AudioStreamPlaybackOggVorbis : public AudioStreamPlaybackResampled {
+ GDCLASS(AudioStreamPlaybackOggVorbis, AudioStreamPlaybackResampled);
uint32_t frames_mixed = 0;
bool active = false;
int loops = 0;
+ enum {
+ FADE_SIZE = 256
+ };
+ AudioFrame loop_fade[FADE_SIZE];
+ int loop_fade_remaining = FADE_SIZE;
+
vorbis_info info;
vorbis_comment comment;
vorbis_dsp_state dsp_state;
@@ -60,12 +66,13 @@ class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled {
bool have_samples_left = false;
bool have_packets_left = false;
- friend class AudioStreamOGGVorbis;
+ friend class AudioStreamOggVorbis;
- Ref<OGGPacketSequence> vorbis_data;
- Ref<OGGPacketSequencePlayback> vorbis_data_playback;
- Ref<AudioStreamOGGVorbis> vorbis_stream;
+ Ref<OggPacketSequence> vorbis_data;
+ Ref<OggPacketSequencePlayback> vorbis_data_playback;
+ Ref<AudioStreamOggVorbis> vorbis_stream;
+ int _mix_frames(AudioFrame *p_buffer, int p_frames);
int _mix_frames_vorbis(AudioFrame *p_buffer, int p_frames);
// Allocates vorbis data structures. Returns true upon success, false on failure.
@@ -85,16 +92,18 @@ public:
virtual float get_playback_position() const override;
virtual void seek(float p_time) override;
- AudioStreamPlaybackOGGVorbis() {}
- ~AudioStreamPlaybackOGGVorbis();
+ virtual void tag_used_streams() override;
+
+ AudioStreamPlaybackOggVorbis() {}
+ ~AudioStreamPlaybackOggVorbis();
};
-class AudioStreamOGGVorbis : public AudioStream {
- GDCLASS(AudioStreamOGGVorbis, AudioStream);
+class AudioStreamOggVorbis : public AudioStream {
+ GDCLASS(AudioStreamOggVorbis, AudioStream);
OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged.
RES_BASE_EXTENSION("oggvorbisstr");
- friend class AudioStreamPlaybackOGGVorbis;
+ friend class AudioStreamPlaybackOggVorbis;
int channels = 1;
float length = 0.0;
@@ -105,30 +114,43 @@ class AudioStreamOGGVorbis : public AudioStream {
// Also causes allocation and deallocation.
void maybe_update_info();
- Ref<OGGPacketSequence> packet_sequence;
+ Ref<OggPacketSequence> packet_sequence;
+
+ double bpm = 0;
+ int beat_count = 0;
+ int bar_beats = 4;
protected:
static void _bind_methods();
public:
void set_loop(bool p_enable);
- bool has_loop() const;
+ virtual bool has_loop() const override;
void set_loop_offset(float p_seconds);
float get_loop_offset() const;
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ void set_bpm(double p_bpm);
+ virtual double get_bpm() const override;
+
+ void set_beat_count(int p_beat_count);
+ virtual int get_beat_count() const override;
+
+ void set_bar_beats(int p_bar_beats);
+ virtual int get_bar_beats() const override;
+
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
- void set_packet_sequence(Ref<OGGPacketSequence> p_packet_sequence);
- Ref<OGGPacketSequence> get_packet_sequence() const;
+ void set_packet_sequence(Ref<OggPacketSequence> p_packet_sequence);
+ Ref<OggPacketSequence> get_packet_sequence() const;
virtual float get_length() const override; //if supported, otherwise return 0
virtual bool is_monophonic() const override;
- AudioStreamOGGVorbis();
- virtual ~AudioStreamOGGVorbis();
+ AudioStreamOggVorbis();
+ virtual ~AudioStreamOggVorbis();
};
-#endif // AUDIO_STREAM_LIBVORBIS_H
+#endif // AUDIO_STREAM_OGG_VORBIS_H
diff --git a/modules/vorbis/config.py b/modules/vorbis/config.py
index 978eccb29f..a231ef179d 100644
--- a/modules/vorbis/config.py
+++ b/modules/vorbis/config.py
@@ -1,5 +1,6 @@
def can_build(env, platform):
- return env.module_check_dependencies("vorbis", ["ogg"])
+ env.module_add_dependencies("vorbis", ["ogg"])
+ return True
def configure(env):
@@ -8,8 +9,8 @@ def configure(env):
def get_doc_classes():
return [
- "AudioStreamOGGVorbis",
- "AudioStreamPlaybackOGGVorbis",
+ "AudioStreamOggVorbis",
+ "AudioStreamPlaybackOggVorbis",
]
diff --git a/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml
index 2f210a6cb4..225ea4e6ae 100644
--- a/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml
+++ b/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamOGGVorbis" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+<class name="AudioStreamOggVorbis" inherits="AudioStream" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>
@@ -7,14 +7,20 @@
<tutorials>
</tutorials>
<members>
+ <member name="bar_beats" type="int" setter="set_bar_beats" getter="get_bar_beats" default="4">
+ </member>
+ <member name="beat_count" type="int" setter="set_beat_count" getter="get_beat_count" default="0">
+ </member>
+ <member name="bpm" type="float" setter="set_bpm" getter="get_bpm" default="0.0">
+ </member>
<member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false">
If [code]true[/code], the stream will automatically loop when it reaches the end.
</member>
<member name="loop_offset" type="float" setter="set_loop_offset" getter="get_loop_offset" default="0.0">
Time in seconds at which the stream starts after being looped.
</member>
- <member name="packet_sequence" type="OGGPacketSequence" setter="set_packet_sequence" getter="get_packet_sequence">
- Contains the raw OGG data for this stream.
+ <member name="packet_sequence" type="OggPacketSequence" setter="set_packet_sequence" getter="get_packet_sequence">
+ Contains the raw Ogg data for this stream.
</member>
</members>
</class>
diff --git a/modules/vorbis/doc_classes/AudioStreamPlaybackOGGVorbis.xml b/modules/vorbis/doc_classes/AudioStreamPlaybackOggVorbis.xml
index 68aa46147f..0879c773ac 100644
--- a/modules/vorbis/doc_classes/AudioStreamPlaybackOGGVorbis.xml
+++ b/modules/vorbis/doc_classes/AudioStreamPlaybackOggVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamPlaybackOGGVorbis" inherits="AudioStreamPlaybackResampled" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+<class name="AudioStreamPlaybackOggVorbis" inherits="AudioStreamPlaybackResampled" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>
diff --git a/modules/vorbis/register_types.cpp b/modules/vorbis/register_types.cpp
index 7f81f88cdb..84a71fe82d 100644
--- a/modules/vorbis/register_types.cpp
+++ b/modules/vorbis/register_types.cpp
@@ -40,13 +40,13 @@ void initialize_vorbis_module(ModuleInitializationLevel p_level) {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- Ref<ResourceImporterOGGVorbis> ogg_vorbis_importer;
+ Ref<ResourceImporterOggVorbis> ogg_vorbis_importer;
ogg_vorbis_importer.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(ogg_vorbis_importer);
}
#endif
- GDREGISTER_CLASS(AudioStreamOGGVorbis);
- GDREGISTER_CLASS(AudioStreamPlaybackOGGVorbis);
+ GDREGISTER_CLASS(AudioStreamOggVorbis);
+ GDREGISTER_CLASS(AudioStreamPlaybackOggVorbis);
}
void uninitialize_vorbis_module(ModuleInitializationLevel p_level) {
diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp
index 7ee6446313..bf5f7206b8 100644
--- a/modules/vorbis/resource_importer_ogg_vorbis.cpp
+++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp
@@ -30,56 +30,59 @@
#include "resource_importer_ogg_vorbis.h"
-#include "audio_stream_ogg_vorbis.h"
#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
#include "scene/resources/texture.h"
#include "thirdparty/libogg/ogg/ogg.h"
#include "thirdparty/libvorbis/vorbis/codec.h"
-String ResourceImporterOGGVorbis::get_importer_name() const {
+#ifdef TOOLS_ENABLED
+#include "editor/import/audio_stream_import_settings.h"
+#endif
+
+String ResourceImporterOggVorbis::get_importer_name() const {
return "oggvorbisstr";
}
-String ResourceImporterOGGVorbis::get_visible_name() const {
+String ResourceImporterOggVorbis::get_visible_name() const {
return "oggvorbisstr";
}
-void ResourceImporterOGGVorbis::get_recognized_extensions(List<String> *p_extensions) const {
+void ResourceImporterOggVorbis::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("ogg");
}
-String ResourceImporterOGGVorbis::get_save_extension() const {
+String ResourceImporterOggVorbis::get_save_extension() const {
return "oggvorbisstr";
}
-String ResourceImporterOGGVorbis::get_resource_type() const {
- return "AudioStreamOGGVorbis";
+String ResourceImporterOggVorbis::get_resource_type() const {
+ return "AudioStreamOggVorbis";
}
-bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
+bool ResourceImporterOggVorbis::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
return true;
}
-int ResourceImporterOGGVorbis::get_preset_count() const {
+int ResourceImporterOggVorbis::get_preset_count() const {
return 0;
}
-String ResourceImporterOGGVorbis::get_preset_name(int p_idx) const {
+String ResourceImporterOggVorbis::get_preset_name(int p_idx) const {
return String();
}
-void ResourceImporterOGGVorbis::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
+void ResourceImporterOggVorbis::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,or_greater"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,or_greater"), 4));
}
-Error ResourceImporterOGGVorbis::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) {
- bool loop = p_options["loop"];
- float loop_offset = p_options["loop_offset"];
-
- Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_source_file + "'.");
+Ref<AudioStreamOggVorbis> ResourceImporterOggVorbis::import_ogg_vorbis(const String &p_path) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), Ref<AudioStreamOggVorbis>(), "Cannot open file '" + p_path + "'.");
uint64_t len = f->get_length();
@@ -89,10 +92,10 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
f->get_buffer(w, len);
- Ref<AudioStreamOGGVorbis> ogg_vorbis_stream;
+ Ref<AudioStreamOggVorbis> ogg_vorbis_stream;
ogg_vorbis_stream.instantiate();
- Ref<OGGPacketSequence> ogg_packet_sequence;
+ Ref<OggPacketSequence> ogg_packet_sequence;
ogg_packet_sequence.instantiate();
ogg_stream_state stream_state;
@@ -107,16 +110,16 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
size_t packet_count = 0;
bool done = false;
while (!done) {
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
while (ogg_sync_pageout(&sync_state, &page) != 1) {
if (cursor >= len) {
done = true;
break;
}
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
char *sync_buf = ogg_sync_buffer(&sync_state, OGG_SYNC_BUFFER_SIZE);
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err));
- ERR_FAIL_COND_V(cursor > len, Error::ERR_INVALID_DATA);
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V(cursor > len, Ref<AudioStreamOggVorbis>());
size_t copy_size = len - cursor;
if (copy_size > OGG_SYNC_BUFFER_SIZE) {
copy_size = OGG_SYNC_BUFFER_SIZE;
@@ -124,22 +127,22 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
memcpy(sync_buf, &file_data[cursor], copy_size);
ogg_sync_wrote(&sync_state, copy_size);
cursor += copy_size;
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
}
if (done) {
break;
}
- ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
// Have a page now.
if (!initialized_stream) {
if (ogg_stream_init(&stream_state, ogg_page_serialno(&page))) {
- ERR_FAIL_V_MSG(Error::ERR_OUT_OF_MEMORY, "Failed allocating memory for OGG Vorbis stream.");
+ ERR_FAIL_V_MSG(Ref<AudioStreamOggVorbis>(), "Failed allocating memory for Ogg Vorbis stream.");
}
initialized_stream = true;
}
ogg_stream_pagein(&stream_state, &page);
- ERR_FAIL_COND_V_MSG((err = ogg_stream_check(&stream_state)), Error::ERR_INVALID_DATA, "Ogg stream error " + itos(err));
+ ERR_FAIL_COND_V_MSG((err = ogg_stream_check(&stream_state)), Ref<AudioStreamOggVorbis>(), "Ogg stream error " + itos(err));
int desync_iters = 0;
Vector<Vector<uint8_t>> packet_data;
@@ -150,7 +153,7 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
if (err == -1) {
// According to the docs this is usually recoverable, but don't sit here spinning forever.
desync_iters++;
- ERR_FAIL_COND_V_MSG(desync_iters > 100, Error::ERR_INVALID_DATA, "Packet sync issue during ogg import");
+ ERR_FAIL_COND_V_MSG(desync_iters > 100, Ref<AudioStreamOggVorbis>(), "Packet sync issue during Ogg import");
continue;
} else if (err == 0) {
// Not enough data to fully reconstruct a packet. Go on to the next page.
@@ -183,15 +186,48 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
ogg_sync_clear(&sync_state);
if (ogg_packet_sequence->get_packet_granule_positions().is_empty()) {
- ERR_FAIL_V_MSG(Error::ERR_FILE_CORRUPT, "OGG Vorbis decoding failed. Check that your data is a valid OGG Vorbis audio stream.");
+ ERR_FAIL_V_MSG(Ref<AudioStreamOggVorbis>(), "Ogg Vorbis decoding failed. Check that your data is a valid Ogg Vorbis audio stream.");
}
ogg_vorbis_stream->set_packet_sequence(ogg_packet_sequence);
+
+ return ogg_vorbis_stream;
+}
+
+#ifdef TOOLS_ENABLED
+
+bool ResourceImporterOggVorbis::has_advanced_options() const {
+ return true;
+}
+
+void ResourceImporterOggVorbis::show_advanced_options(const String &p_path) {
+ Ref<AudioStreamOggVorbis> ogg_stream = import_ogg_vorbis(p_path);
+ if (ogg_stream.is_valid()) {
+ AudioStreamImportSettings::get_singleton()->edit(p_path, "oggvorbisstr", ogg_stream);
+ }
+}
+#endif
+
+Error ResourceImporterOggVorbis::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) {
+ bool loop = p_options["loop"];
+ float loop_offset = p_options["loop_offset"];
+ double bpm = p_options["bpm"];
+ int beat_count = p_options["beat_count"];
+ int bar_beats = p_options["bar_beats"];
+
+ Ref<AudioStreamOggVorbis> ogg_vorbis_stream = import_ogg_vorbis(p_source_file);
+ if (ogg_vorbis_stream.is_null()) {
+ return ERR_CANT_OPEN;
+ }
+
ogg_vorbis_stream->set_loop(loop);
ogg_vorbis_stream->set_loop_offset(loop_offset);
+ ogg_vorbis_stream->set_bpm(bpm);
+ ogg_vorbis_stream->set_beat_count(beat_count);
+ ogg_vorbis_stream->set_bar_beats(bar_beats);
- return ResourceSaver::save(p_save_path + ".oggvorbisstr", ogg_vorbis_stream);
+ return ResourceSaver::save(ogg_vorbis_stream, p_save_path + ".oggvorbisstr");
}
-ResourceImporterOGGVorbis::ResourceImporterOGGVorbis() {
+ResourceImporterOggVorbis::ResourceImporterOggVorbis() {
}
diff --git a/modules/vorbis/resource_importer_ogg_vorbis.h b/modules/vorbis/resource_importer_ogg_vorbis.h
index 3b4a68a1fd..a1a970e2cc 100644
--- a/modules/vorbis/resource_importer_ogg_vorbis.h
+++ b/modules/vorbis/resource_importer_ogg_vorbis.h
@@ -31,10 +31,11 @@
#ifndef RESOURCE_IMPORTER_OGG_VORBIS_H
#define RESOURCE_IMPORTER_OGG_VORBIS_H
+#include "audio_stream_ogg_vorbis.h"
#include "core/io/resource_importer.h"
-class ResourceImporterOGGVorbis : public ResourceImporter {
- GDCLASS(ResourceImporterOGGVorbis, ResourceImporter);
+class ResourceImporterOggVorbis : public ResourceImporter {
+ GDCLASS(ResourceImporterOggVorbis, ResourceImporter);
enum {
OGG_SYNC_BUFFER_SIZE = 8192,
@@ -43,7 +44,13 @@ class ResourceImporterOGGVorbis : public ResourceImporter {
private:
// virtual int get_samples_in_packet(Vector<uint8_t> p_packet) = 0;
+ static Ref<AudioStreamOggVorbis> import_ogg_vorbis(const String &p_path);
+
public:
+#ifdef TOOLS_ENABLED
+ virtual bool has_advanced_options() const override;
+ virtual void show_advanced_options(const String &p_path) override;
+#endif
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual String get_save_extension() const override;
virtual String get_resource_type() const override;
@@ -56,7 +63,7 @@ public:
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;
- ResourceImporterOGGVorbis();
+ ResourceImporterOggVorbis();
};
#endif // RESOURCE_IMPORTER_OGG_VORBIS_H
diff --git a/modules/webp/image_loader_webp.h b/modules/webp/image_loader_webp.h
index 448f683eb3..9a5dc6cd7c 100644
--- a/modules/webp/image_loader_webp.h
+++ b/modules/webp/image_loader_webp.h
@@ -40,4 +40,4 @@ public:
ImageLoaderWebP();
};
-#endif
+#endif // IMAGE_LOADER_WEBP_H
diff --git a/modules/webp/resource_saver_webp.cpp b/modules/webp/resource_saver_webp.cpp
index d270d39163..bd71c2869a 100644
--- a/modules/webp/resource_saver_webp.cpp
+++ b/modules/webp/resource_saver_webp.cpp
@@ -35,7 +35,7 @@
#include "scene/resources/texture.h"
#include "webp_common.h"
-Error ResourceSaverWebP::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceSaverWebP::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Ref<ImageTexture> texture = p_resource;
ERR_FAIL_COND_V_MSG(!texture.is_valid(), ERR_INVALID_PARAMETER, "Can't save invalid texture as WEBP.");
diff --git a/modules/webp/resource_saver_webp.h b/modules/webp/resource_saver_webp.h
index 59e944efa0..cbd5864463 100644
--- a/modules/webp/resource_saver_webp.h
+++ b/modules/webp/resource_saver_webp.h
@@ -39,7 +39,7 @@ public:
static Error save_image(const String &p_path, const Ref<Image> &p_img, const bool p_lossy = false, const float p_quality = 0.75f);
static Vector<uint8_t> save_image_to_buffer(const Ref<Image> &p_img, const bool p_lossy = false, const float p_quality = 0.75f);
- virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
virtual bool recognize(const Ref<Resource> &p_resource) const;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
diff --git a/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
index 3996a002ed..df92097135 100644
--- a/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
+++ b/modules/webrtc/doc_classes/WebRTCMultiplayerPeer.xml
@@ -57,7 +57,7 @@
Initialize the multiplayer peer with the given [code]peer_id[/code] (must be between 1 and 2147483647).
If [code]server_compatibilty[/code] is [code]false[/code] (default), the multiplayer peer will be immediately in state [constant MultiplayerPeer.CONNECTION_CONNECTED] and [signal MultiplayerPeer.connection_succeeded] will not be emitted.
If [code]server_compatibilty[/code] is [code]true[/code] the peer will suppress all [signal MultiplayerPeer.peer_connected] signals until a peer with id [constant MultiplayerPeer.TARGET_PEER_SERVER] connects and then emit [signal MultiplayerPeer.connection_succeeded]. After that the signal [signal MultiplayerPeer.peer_connected] will be emitted for every already connected peer, and any new peer that might connect. If the server peer disconnects after that, signal [signal MultiplayerPeer.server_disconnected] will be emitted and state will become [constant MultiplayerPeer.CONNECTION_CONNECTED].
- You can optionally specify a [code]channels_config[/code] array of [enum TransferMode] which will be used to create extra channels (WebRTC only supports one transfer mode per channel).
+ You can optionally specify a [code]channels_config[/code] array of [enum MultiplayerPeer.TransferMode] which will be used to create extra channels (WebRTC only supports one transfer mode per channel).
</description>
</method>
<method name="remove_peer">
diff --git a/modules/webrtc/webrtc_data_channel.h b/modules/webrtc/webrtc_data_channel.h
index 75e29283ec..9d20ad3266 100644
--- a/modules/webrtc/webrtc_data_channel.h
+++ b/modules/webrtc/webrtc_data_channel.h
@@ -81,4 +81,5 @@ public:
VARIANT_ENUM_CAST(WebRTCDataChannel::WriteMode);
VARIANT_ENUM_CAST(WebRTCDataChannel::ChannelState);
+
#endif // WEBRTC_DATA_CHANNEL_H
diff --git a/modules/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp
index 6f68b84ad3..e03b6b2473 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.cpp
+++ b/modules/webrtc/webrtc_multiplayer_peer.cpp
@@ -197,14 +197,14 @@ Error WebRTCMultiplayerPeer::initialize(int p_self_id, bool p_server_compat, Arr
cfg["ordered"] = true;
switch (mode) {
- case Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED:
+ case TRANSFER_MODE_UNRELIABLE_ORDERED:
cfg["maxPacketLifetime"] = 1;
break;
- case Multiplayer::TRANSFER_MODE_UNRELIABLE:
+ case TRANSFER_MODE_UNRELIABLE:
cfg["maxPacketLifetime"] = 1;
cfg["ordered"] = false;
break;
- case Multiplayer::TRANSFER_MODE_RELIABLE:
+ case TRANSFER_MODE_RELIABLE:
break;
default:
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("The 'channels_config' array must contain only enum values from 'MultiplayerPeer.Multiplayer::TransferMode'. Got: %d", mode));
@@ -339,13 +339,13 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si
int ch = get_transfer_channel();
if (ch == 0) {
switch (get_transfer_mode()) {
- case Multiplayer::TRANSFER_MODE_RELIABLE:
+ case TRANSFER_MODE_RELIABLE:
ch = CH_RELIABLE;
break;
- case Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED:
+ case TRANSFER_MODE_UNRELIABLE_ORDERED:
ch = CH_ORDERED;
break;
- case Multiplayer::TRANSFER_MODE_UNRELIABLE:
+ case TRANSFER_MODE_UNRELIABLE:
ch = CH_UNRELIABLE;
break;
}
diff --git a/modules/webrtc/webrtc_multiplayer_peer.h b/modules/webrtc/webrtc_multiplayer_peer.h
index 97550a3e9d..ea7c60036b 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.h
+++ b/modules/webrtc/webrtc_multiplayer_peer.h
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef WEBRTC_MULTIPLAYER_H
-#define WEBRTC_MULTIPLAYER_H
+#ifndef WEBRTC_MULTIPLAYER_PEER_H
+#define WEBRTC_MULTIPLAYER_PEER_H
-#include "core/multiplayer/multiplayer_peer.h"
+#include "scene/main/multiplayer_peer.h"
#include "webrtc_peer_connection.h"
class WebRTCMultiplayerPeer : public MultiplayerPeer {
@@ -106,4 +106,4 @@ public:
ConnectionStatus get_connection_status() const override;
};
-#endif // WEBRTC_MULTIPLAYER_H
+#endif // WEBRTC_MULTIPLAYER_PEER_H
diff --git a/modules/webrtc/webrtc_peer_connection.h b/modules/webrtc/webrtc_peer_connection.h
index 8c324d0942..122ea3d00f 100644
--- a/modules/webrtc/webrtc_peer_connection.h
+++ b/modules/webrtc/webrtc_peer_connection.h
@@ -74,4 +74,5 @@ public:
};
VARIANT_ENUM_CAST(WebRTCPeerConnection::ConnectionState);
+
#endif // WEBRTC_PEER_CONNECTION_H
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/modules/websocket/emws_client.h b/modules/websocket/emws_client.h
index ca327a56fa..b71fd78124 100644
--- a/modules/websocket/emws_client.h
+++ b/modules/websocket/emws_client.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EMWSCLIENT_H
-#define EMWSCLIENT_H
+#ifndef EMWS_CLIENT_H
+#define EMWS_CLIENT_H
#ifdef JAVASCRIPT_ENABLED
@@ -68,4 +68,4 @@ public:
#endif // JAVASCRIPT_ENABLED
-#endif // EMWSCLIENT_H
+#endif // EMWS_CLIENT_H
diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h
index 6bb4552c37..f52f615c35 100644
--- a/modules/websocket/emws_peer.h
+++ b/modules/websocket/emws_peer.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef EMWSPEER_H
-#define EMWSPEER_H
+#ifndef EMWS_PEER_H
+#define EMWS_PEER_H
#ifdef JAVASCRIPT_ENABLED
@@ -90,4 +90,4 @@ public:
#endif // JAVASCRIPT_ENABLED
-#endif // LSWPEER_H
+#endif // EMWS_PEER_H
diff --git a/modules/websocket/emws_server.h b/modules/websocket/emws_server.h
deleted file mode 100644
index ae31d9dbb0..0000000000
--- a/modules/websocket/emws_server.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*************************************************************************/
-/* emws_server.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 EMWSSERVER_H
-#define EMWSSERVER_H
-
-#ifdef JAVASCRIPT_ENABLED
-
-#include "core/object/ref_counted.h"
-#include "emws_peer.h"
-#include "websocket_server.h"
-
-class EMWSServer : public WebSocketServer {
- GDCIIMPL(EMWSServer, WebSocketServer);
-
-public:
- Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) override;
- void set_extra_headers(const Vector<String> &p_headers) override;
- Error listen(int p_port, Vector<String> p_protocols = Vector<String>(), bool gd_mp_api = false) override;
- void stop() override;
- bool is_listening() const override;
- bool has_peer(int p_id) const override;
- Ref<WebSocketPeer> get_peer(int p_id) const override;
- IPAddress get_peer_address(int p_peer_id) const override;
- int get_peer_port(int p_peer_id) const override;
- void disconnect_peer(int p_peer_id, int p_code = 1000, String p_reason = "") override;
- int get_max_packet_size() const override;
- virtual void poll() override;
- virtual Vector<String> get_protocols() const;
-
- EMWSServer();
- ~EMWSServer();
-};
-
-#endif
-
-#endif // LWSSERVER_H
diff --git a/modules/websocket/register_types.cpp b/modules/websocket/register_types.cpp
index f562de111f..056111ec92 100644
--- a/modules/websocket/register_types.cpp
+++ b/modules/websocket/register_types.cpp
@@ -33,11 +33,13 @@
#include "core/config/project_settings.h"
#include "core/error/error_macros.h"
+#include "websocket_client.h"
+#include "websocket_server.h"
+
#ifdef JAVASCRIPT_ENABLED
#include "emscripten.h"
#include "emws_client.h"
#include "emws_peer.h"
-#include "emws_server.h"
#else
#include "wsl_client.h"
#include "wsl_server.h"
@@ -60,7 +62,6 @@ void initialize_websocket_module(ModuleInitializationLevel p_level) {
#ifdef JAVASCRIPT_ENABLED
EMWSPeer::make_default();
EMWSClient::make_default();
- EMWSServer::make_default();
#else
WSLPeer::make_default();
WSLClient::make_default();
diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h
index db529a669d..3259e78b3b 100644
--- a/modules/websocket/websocket_multiplayer_peer.h
+++ b/modules/websocket/websocket_multiplayer_peer.h
@@ -32,8 +32,8 @@
#define WEBSOCKET_MULTIPLAYER_PEER_H
#include "core/error/error_list.h"
-#include "core/multiplayer/multiplayer_peer.h"
#include "core/templates/list.h"
+#include "scene/main/multiplayer_peer.h"
#include "websocket_peer.h"
class WebSocketMultiplayerPeer : public MultiplayerPeer {
diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h
index 13fef2424f..22099f7258 100644
--- a/modules/websocket/websocket_peer.h
+++ b/modules/websocket/websocket_peer.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef WEBSOCKETPEER_H
-#define WEBSOCKETPEER_H
+#ifndef WEBSOCKET_PEER_H
+#define WEBSOCKET_PEER_H
#include "core/error/error_list.h"
#include "core/io/packet_peer.h"
@@ -66,4 +66,5 @@ public:
};
VARIANT_ENUM_CAST(WebSocketPeer::WriteMode);
-#endif // WEBSOCKETPEER_H
+
+#endif // WEBSOCKET_PEER_H
diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h
index 7bd80851f5..ac04c4e57e 100644
--- a/modules/websocket/websocket_server.h
+++ b/modules/websocket/websocket_server.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef WEBSOCKET_H
-#define WEBSOCKET_H
+#ifndef WEBSOCKET_SERVER_H
+#define WEBSOCKET_SERVER_H
#include "core/crypto/crypto.h"
#include "core/object/ref_counted.h"
@@ -87,4 +87,4 @@ public:
~WebSocketServer();
};
-#endif // WEBSOCKET_H
+#endif // WEBSOCKET_SERVER_H
diff --git a/modules/websocket/wsl_client.h b/modules/websocket/wsl_client.h
index 22d7ffa839..58b867fbe4 100644
--- a/modules/websocket/wsl_client.h
+++ b/modules/websocket/wsl_client.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef WSLCLIENT_H
-#define WSLCLIENT_H
+#ifndef WSL_CLIENT_H
+#define WSL_CLIENT_H
#ifndef JAVASCRIPT_ENABLED
@@ -88,4 +88,4 @@ public:
#endif // JAVASCRIPT_ENABLED
-#endif // WSLCLIENT_H
+#endif // WSL_CLIENT_H
diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h
index abeecdd537..aabd3fd43e 100644
--- a/modules/websocket/wsl_peer.h
+++ b/modules/websocket/wsl_peer.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef WSLPEER_H
-#define WSLPEER_H
+#ifndef WSL_PEER_H
+#define WSL_PEER_H
#ifndef JAVASCRIPT_ENABLED
@@ -112,4 +112,4 @@ public:
#endif // JAVASCRIPT_ENABLED
-#endif // LSWPEER_H
+#endif // WSL_PEER_H
diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h
index a920e9c665..ec7567c732 100644
--- a/modules/websocket/wsl_server.h
+++ b/modules/websocket/wsl_server.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef WSLSERVER_H
-#define WSLSERVER_H
+#ifndef WSL_SERVER_H
+#define WSL_SERVER_H
#ifndef JAVASCRIPT_ENABLED
@@ -95,4 +95,4 @@ public:
#endif // JAVASCRIPT_ENABLED
-#endif // WSLSERVER_H
+#endif // WSL_SERVER_H
diff --git a/modules/webxr/godot_webxr.h b/modules/webxr/godot_webxr.h
index 34225df001..52104895d4 100644
--- a/modules/webxr/godot_webxr.h
+++ b/modules/webxr/godot_webxr.h
@@ -82,4 +82,4 @@ extern int *godot_webxr_get_bounds_geometry();
}
#endif
-#endif /* GODOT_WEBXR_H */
+#endif // GODOT_WEBXR_H
diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp
index 74e744402b..07e6760555 100644
--- a/modules/webxr/webxr_interface_js.cpp
+++ b/modules/webxr/webxr_interface_js.cpp
@@ -363,8 +363,8 @@ Transform3D WebXRInterfaceJS::get_transform_for_view(uint32_t p_view, const Tran
return p_cam_transform * xr_server->get_reference_frame() * transform_for_eye;
};
-CameraMatrix WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
- CameraMatrix eye;
+Projection WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
+ Projection eye;
float *js_matrix = godot_webxr_get_projection_for_eye(p_view + 1);
if (!initialized || js_matrix == nullptr) {
diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h
index 31858194f6..f1ffedba46 100644
--- a/modules/webxr/webxr_interface_js.h
+++ b/modules/webxr/webxr_interface_js.h
@@ -87,7 +87,7 @@ public:
virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
- virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
+ virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void process() override;
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/display_server_android.cpp b/platform/android/display_server_android.cpp
index 3be220d110..b51dd18af6 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -221,12 +221,12 @@ bool DisplayServerAndroid::screen_is_touchscreen(int p_screen) const {
return true;
}
-void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) {
+void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {
GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
ERR_FAIL_NULL(godot_io_java);
if (godot_io_java->has_vk()) {
- godot_io_java->show_vk(p_existing_text, p_multiline, p_max_length, p_cursor_start, p_cursor_end);
+ godot_io_java->show_vk(p_existing_text, (int)p_type, p_max_length, p_cursor_start, p_cursor_end);
} else {
ERR_PRINT("Virtual keyboard not available");
}
@@ -276,9 +276,9 @@ void DisplayServerAndroid::_window_callback(const Callable &p_callable, const Va
Variant ret;
Callable::CallError ce;
if (p_deferred) {
- p_callable.call((const Variant **)&argp, 1, ret, ce);
+ p_callable.callp((const Variant **)&argp, 1, ret, ce);
} else {
- p_callable.call_deferred((const Variant **)&argp, 1);
+ p_callable.call_deferredp((const Variant **)&argp, 1);
}
}
}
@@ -482,7 +482,7 @@ void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) {
Variant ret;
Callable::CallError ce;
- rect_changed_callback.call(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce);
+ rect_changed_callback.callp(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce);
}
DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index 65bf2ec1a8..2f30642319 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -122,7 +122,7 @@ public:
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
virtual void virtual_keyboard_hide() override;
virtual int virtual_keyboard_get_height() const override;
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 560f188b82..5bbe0ffab6 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -30,10 +30,10 @@
#include "export.h"
-#include "export_plugin.h"
-
#include "core/os/os.h"
#include "editor/editor_settings.h"
+#include "editor/export/editor_export.h"
+#include "export_plugin.h"
void register_android_exporter() {
EDITOR_DEF("export/android/android_sdk_path", "");
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index b40c1f5090..6f1b4bde40 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") {
@@ -1663,7 +1671,7 @@ Vector<String> EditorExportPlatformAndroid::get_enabled_abis(const Ref<EditorExp
return enabled_abis;
}
-void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
+void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
if (driver == "opengl3") {
r_features->push_back("etc");
@@ -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++) {
@@ -1692,6 +1705,8 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
}
plugins_changed.clear();
+ // Android supports multiple architectures in an app bundle, so
+ // we expose each option as a checkbox in the export dialog.
const Vector<String> abis = get_abis();
for (int i = 0; i < abis.size(); ++i) {
const String abi = abis[i];
@@ -1710,8 +1725,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 +2052,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 +2214,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 +2369,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 +2525,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 +2538,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 +2666,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";
@@ -3062,7 +3111,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
CLEANUP_AND_RETURN(OK);
}
-void EditorExportPlatformAndroid::get_platform_features(List<String> *r_features) {
+void EditorExportPlatformAndroid::get_platform_features(List<String> *r_features) const {
r_features->push_back("mobile");
r_features->push_back("android");
}
@@ -3071,13 +3120,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..1da3f68f9a 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -35,7 +35,7 @@
#include "core/io/zip_io.h"
#include "core/os/os.h"
-#include "editor/editor_export.h"
+#include "editor/export/editor_export_platform.h"
const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
@@ -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);
@@ -154,7 +156,7 @@ public:
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
public:
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
virtual void get_export_options(List<ExportOption> *r_options) override;
@@ -229,7 +231,7 @@ public:
Error export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags);
- virtual void get_platform_features(List<String> *r_features) override;
+ virtual void get_platform_features(List<String> *r_features) const override;
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override;
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..232b4458c6 100644
--- a/platform/android/export/gradle_export_util.h
+++ b/platform/android/export/gradle_export_util.h
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_GRADLE_EXPORT_UTIL_H
-#define GODOT_GRADLE_EXPORT_UTIL_H
+#ifndef ANDROID_GRADLE_EXPORT_UTIL_H
+#define ANDROID_GRADLE_EXPORT_UTIL_H
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/zip_io.h"
#include "core/os/os.h"
-#include "editor/editor_export.h"
+#include "editor/export/editor_export.h"
const String godot_project_name_xml_string = R"(<?xml version="1.0" encoding="utf-8"?>
<!--WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
@@ -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
+#endif // ANDROID_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..8d7ade8ead 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -37,40 +37,46 @@
#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();
public:
static AAssetManager *asset_manager;
- virtual Error _open(const String &p_path, int p_mode_flags); // open a file
- virtual bool is_open() const; // true when file is open
+ 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
- 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
- virtual uint64_t get_length() const; // get size of the file
+ /// 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 bool eof_reached() const; // reading passed EOF
+ 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 uint8_t get_8() const; // get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ virtual bool eof_reached() const override; // reading passed EOF
- virtual Error get_error() const; // get last error
+ 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 void flush();
- virtual void store_8(uint8_t p_dest); // store a byte
+ virtual Error get_error() const override; // get last error
- virtual bool file_exists(const String &p_path); // return true if a file exists
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override; // store a byte
- virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
- virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
+ virtual bool file_exists(const String &p_path) override; // return true if a file exists
+
+ virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
+ 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; }
~FileAccessAndroid();
};
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
new file mode 100644
index 0000000000..6b21c18d59
--- /dev/null
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -0,0 +1,331 @@
+/*************************************************************************/
+/* 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 "core/templates/local_vector.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;
+}
+
+String FileAccessFilesystemJAndroid::get_line() const {
+ ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use.");
+
+ const size_t buffer_size_limit = 2048;
+ const uint64_t file_size = get_length();
+ const uint64_t start_position = get_position();
+
+ String result;
+ LocalVector<uint8_t> line_buffer;
+ size_t current_buffer_size = 0;
+ uint64_t line_buffer_position = 0;
+
+ while (true) {
+ size_t line_buffer_size = MIN(buffer_size_limit, file_size - get_position());
+ if (line_buffer_size <= 0) {
+ break;
+ }
+
+ current_buffer_size += line_buffer_size;
+ line_buffer.resize(current_buffer_size);
+
+ uint64_t bytes_read = get_buffer(&line_buffer[line_buffer_position], current_buffer_size - line_buffer_position);
+ if (bytes_read <= 0) {
+ break;
+ }
+
+ for (; bytes_read > 0; line_buffer_position++, bytes_read--) {
+ uint8_t elem = line_buffer[line_buffer_position];
+ if (elem == '\n' || elem == '\0') {
+ // Found the end of the line
+ const_cast<FileAccessFilesystemJAndroid *>(this)->seek(start_position + line_buffer_position + 1);
+ if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) {
+ return String();
+ }
+ return result;
+ }
+ }
+ }
+
+ if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) {
+ return String();
+ }
+ return result;
+}
+
+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..7deb8de37b
--- /dev/null
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -0,0 +1,98 @@
+/*************************************************************************/
+/* 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 String get_line() const override; ///< get a line
+ 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..d283de8ce8 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) {
@@ -299,9 +203,10 @@ public class GodotIO {
return result;
}
- public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
- if (edit != null)
- edit.showKeyboard(p_existing_text, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end);
+ public void showKeyboard(String p_existing_text, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+ if (edit != null) {
+ edit.showKeyboard(p_existing_text, GodotEditText.VirtualKeyboardType.values()[p_type], p_max_input_length, p_cursor_start, p_cursor_end);
+ }
//InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
//inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
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/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
index ecb2af0a7b..7925b54fc4 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
@@ -52,6 +52,18 @@ public class GodotEditText extends EditText {
private final static int HANDLER_OPEN_IME_KEYBOARD = 2;
private final static int HANDLER_CLOSE_IME_KEYBOARD = 3;
+ // Enum must be kept up-to-date with DisplayServer::VirtualKeyboardType
+ public enum VirtualKeyboardType {
+ KEYBOARD_TYPE_DEFAULT,
+ KEYBOARD_TYPE_MULTILINE,
+ KEYBOARD_TYPE_NUMBER,
+ KEYBOARD_TYPE_NUMBER_DECIMAL,
+ KEYBOARD_TYPE_PHONE,
+ KEYBOARD_TYPE_EMAIL_ADDRESS,
+ KEYBOARD_TYPE_PASSWORD,
+ KEYBOARD_TYPE_URL
+ }
+
// ===========================================================
// Fields
// ===========================================================
@@ -60,7 +72,7 @@ public class GodotEditText extends EditText {
private EditHandler sHandler = new EditHandler(this);
private String mOriginText;
private int mMaxInputLength = Integer.MAX_VALUE;
- private boolean mMultiline = false;
+ private VirtualKeyboardType mKeyboardType = VirtualKeyboardType.KEYBOARD_TYPE_DEFAULT;
private static class EditHandler extends Handler {
private final WeakReference<GodotEditText> mEdit;
@@ -100,8 +112,8 @@ public class GodotEditText extends EditText {
setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_DONE);
}
- public boolean isMultiline() {
- return mMultiline;
+ public VirtualKeyboardType getKeyboardType() {
+ return mKeyboardType;
}
private void handleMessage(final Message msg) {
@@ -122,8 +134,31 @@ public class GodotEditText extends EditText {
}
int inputType = InputType.TYPE_CLASS_TEXT;
- if (edit.isMultiline()) {
- inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE;
+ switch (edit.getKeyboardType()) {
+ case KEYBOARD_TYPE_DEFAULT:
+ inputType = InputType.TYPE_CLASS_TEXT;
+ break;
+ case KEYBOARD_TYPE_MULTILINE:
+ inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
+ break;
+ case KEYBOARD_TYPE_NUMBER:
+ inputType = InputType.TYPE_CLASS_NUMBER;
+ break;
+ case KEYBOARD_TYPE_NUMBER_DECIMAL:
+ inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED;
+ break;
+ case KEYBOARD_TYPE_PHONE:
+ inputType = InputType.TYPE_CLASS_PHONE;
+ break;
+ case KEYBOARD_TYPE_EMAIL_ADDRESS:
+ inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
+ break;
+ case KEYBOARD_TYPE_PASSWORD:
+ inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
+ break;
+ case KEYBOARD_TYPE_URL:
+ inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI;
+ break;
}
edit.setInputType(inputType);
@@ -201,7 +236,7 @@ public class GodotEditText extends EditText {
// ===========================================================
// Methods
// ===========================================================
- public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+ public void showKeyboard(String p_existing_text, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
int maxInputLength = (p_max_input_length <= 0) ? Integer.MAX_VALUE : p_max_input_length;
if (p_cursor_start == -1) { // cursor position not given
this.mOriginText = p_existing_text;
@@ -214,7 +249,7 @@ public class GodotEditText extends EditText {
this.mMaxInputLength = maxInputLength - (p_existing_text.length() - p_cursor_end);
}
- this.mMultiline = p_multiline;
+ this.mKeyboardType = p_type;
final Message msg = new Message();
msg.what = HANDLER_OPEN_IME_KEYBOARD;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index e940aafa9e..7714703a21 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -115,7 +115,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
}
for (int i = 0; i < count; ++i) {
int key = newChars[i];
- if ((key == '\n') && !mEdit.isMultiline()) {
+ if ((key == '\n') && !(mEdit.getKeyboardType() == GodotEditText.VirtualKeyboardType.KEYBOARD_TYPE_MULTILINE)) {
// Return keys are handled through action events
continue;
}
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..c9282dd247
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt
@@ -0,0 +1,113 @@
+/*************************************************************************/
+/* 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;
+
+ class Identifier(context: Context) {
+
+ private val internalAppDir: String? = context.filesDir.canonicalPath
+ private val internalCacheDir: String? = context.cacheDir.canonicalPath
+ private val externalAppDir: String? = context.getExternalFilesDir(null)?.canonicalPath
+ private val sharedDir : String? = Environment.getExternalStorageDirectory().canonicalPath
+ private val downloadsSharedDir: String? = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).canonicalPath
+ private val documentsSharedDir: String? = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).canonicalPath
+
+ /**
+ * Determines which [StorageScope] the given path falls under.
+ */
+ fun identifyStorageScope(path: String?): StorageScope {
+ if (path == null) {
+ return UNKNOWN
+ }
+
+ val pathFile = File(path)
+ if (!pathFile.isAbsolute) {
+ return UNKNOWN
+ }
+
+ val canonicalPathFile = pathFile.canonicalPath
+
+ if (internalAppDir != null && canonicalPathFile.startsWith(internalAppDir)) {
+ return APP
+ }
+
+ if (internalCacheDir != null && canonicalPathFile.startsWith(internalCacheDir)) {
+ return APP
+ }
+
+ if (externalAppDir != null && canonicalPathFile.startsWith(externalAppDir)) {
+ return APP
+ }
+
+ if (sharedDir != null && 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
+ if ((downloadsSharedDir != null && canonicalPathFile.startsWith(downloadsSharedDir))
+ || (documentsSharedDir != null && 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..54fc56fa3e
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt
@@ -0,0 +1,231 @@
+/*************************************************************************/
+/* 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 storageScopeIdentifier = StorageScope.Identifier(context)
+ 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 storageScopeIdentifier.identifyStorageScope(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, storageScopeIdentifier, 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, storageScopeIdentifier, 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, storageScopeIdentifier, 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..463dabfb23
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt
@@ -0,0 +1,187 @@
+/*************************************************************************/
+/* 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)
+ endOfFile = readBytes == -1
+ || (fileChannel.position() >= fileChannel.size() && fileChannel.size() > 0)
+ if (readBytes == -1) {
+ 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/modules/websocket/emws_server.cpp b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessFlags.kt
index 2033098cad..c6b242a4b6 100644
--- a/modules/websocket/emws_server.cpp
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessFlags.kt
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* emws_server.cpp */
+/* FileAccessFlags.kt */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,65 +28,60 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef JAVASCRIPT_ENABLED
-
-#include "emws_server.h"
-#include "core/os/os.h"
-
-void EMWSServer::set_extra_headers(const Vector<String> &p_headers) {
-}
-
-Error EMWSServer::listen(int p_port, Vector<String> p_protocols, bool gd_mp_api) {
- return FAILED;
-}
-
-bool EMWSServer::is_listening() const {
- return false;
-}
-
-void EMWSServer::stop() {
-}
-
-bool EMWSServer::has_peer(int p_id) const {
- return false;
-}
-
-Ref<WebSocketPeer> EMWSServer::get_peer(int p_id) const {
- return nullptr;
-}
-
-Vector<String> EMWSServer::get_protocols() const {
- Vector<String> out;
-
- return out;
-}
-
-IPAddress EMWSServer::get_peer_address(int p_peer_id) const {
- return IPAddress();
-}
-
-int EMWSServer::get_peer_port(int p_peer_id) const {
- return 0;
-}
-
-void EMWSServer::disconnect_peer(int p_peer_id, int p_code, String p_reason) {
-}
-
-void EMWSServer::poll() {
-}
-
-int EMWSServer::get_max_packet_size() const {
- return 0;
-}
-
-Error EMWSServer::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) {
- return OK;
-}
-
-EMWSServer::EMWSServer() {
-}
-
-EMWSServer::~EMWSServer() {
+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
+ }
+ }
}
-
-#endif // JAVASCRIPT_ENABLED
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..04b6772c45
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt
@@ -0,0 +1,203 @@
+/*************************************************************************/
+/* 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
+
+ internal fun fileExists(context: Context, storageScopeIdentifier: StorageScope.Identifier, path: String?): Boolean {
+ val storageScope = storageScopeIdentifier.identifyStorageScope(path)
+ if (storageScope == StorageScope.UNKNOWN) {
+ return false
+ }
+
+ return try {
+ DataAccess.fileExists(storageScope, context, path!!)
+ } catch (e: SecurityException) {
+ false
+ }
+ }
+
+ internal fun removeFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, path: String?): Boolean {
+ val storageScope = storageScopeIdentifier.identifyStorageScope(path)
+ if (storageScope == StorageScope.UNKNOWN) {
+ return false
+ }
+
+ return try {
+ DataAccess.removeFile(storageScope, context, path!!)
+ } catch (e: Exception) {
+ false
+ }
+ }
+
+ internal fun renameFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, from: String?, to: String?): Boolean {
+ val storageScope = storageScopeIdentifier.identifyStorageScope(from)
+ if (storageScope == StorageScope.UNKNOWN) {
+ return false
+ }
+
+ return try {
+ DataAccess.renameFile(storageScope, context, from!!, to!!)
+ } catch (e: Exception) {
+ false
+ }
+ }
+ }
+
+ private val storageScopeIdentifier = StorageScope.Identifier(context)
+ 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 = storageScopeIdentifier.identifyStorageScope(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, storageScopeIdentifier, path)
+
+ fun fileLastModified(filepath: String?): Long {
+ val storageScope = storageScopeIdentifier.identifyStorageScope(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_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp
index b71c6ef1e6..5877c15114 100644
--- a/platform/android/java_godot_io_wrapper.cpp
+++ b/platform/android/java_godot_io_wrapper.cpp
@@ -61,7 +61,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
_get_scaled_density = p_env->GetMethodID(cls, "getScaledDensity", "()F");
_get_screen_refresh_rate = p_env->GetMethodID(cls, "getScreenRefreshRate", "(D)D");
_get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;");
- _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;ZIII)V");
+ _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;IIII)V");
_hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V");
_set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V");
_get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I");
@@ -214,12 +214,12 @@ bool GodotIOJavaWrapper::has_vk() {
return (_show_keyboard != nullptr) && (_hide_keyboard != nullptr);
}
-void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+void GodotIOJavaWrapper::show_vk(const String &p_existing, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
if (_show_keyboard) {
JNIEnv *env = get_jni_env();
ERR_FAIL_NULL(env);
jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
- env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end);
+ env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_type, p_max_input_length, p_cursor_start, p_cursor_end);
}
}
diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h
index aec7d1db97..dc68f4d90d 100644
--- a/platform/android/java_godot_io_wrapper.h
+++ b/platform/android/java_godot_io_wrapper.h
@@ -82,7 +82,7 @@ public:
Rect2i get_display_safe_area();
String get_unique_id();
bool has_vk();
- void show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end);
+ void show_vk(const String &p_existing, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end);
void hide_vk();
int get_vk_height();
void set_vk_height(int p_height);
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/java_godot_view_wrapper.h b/platform/android/java_godot_view_wrapper.h
index b1f258bbb5..c52f459d64 100644
--- a/platform/android/java_godot_view_wrapper.h
+++ b/platform/android/java_godot_view_wrapper.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_JAVA_GODOT_VIEW_WRAPPER_H
-#define GODOT_JAVA_GODOT_VIEW_WRAPPER_H
+#ifndef JAVA_GODOT_VIEW_WRAPPER_H
+#define JAVA_GODOT_VIEW_WRAPPER_H
#include <android/log.h>
#include <jni.h>
@@ -57,4 +57,4 @@ public:
~GodotJavaViewWrapper();
};
-#endif // GODOT_JAVA_GODOT_VIEW_WRAPPER_H
+#endif // JAVA_GODOT_VIEW_WRAPPER_H
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/SCsub b/platform/ios/SCsub
index 5e10bf5646..bf12ab6dd7 100644
--- a/platform/iphone/SCsub
+++ b/platform/ios/SCsub
@@ -2,16 +2,16 @@
Import("env")
-iphone_lib = [
- "godot_iphone.mm",
- "os_iphone.mm",
+ios_lib = [
+ "godot_ios.mm",
+ "os_ios.mm",
"main.m",
"app_delegate.mm",
"view_controller.mm",
"ios.mm",
- "vulkan_context_iphone.mm",
- "display_server_iphone.mm",
- "joypad_iphone.mm",
+ "vulkan_context_ios.mm",
+ "display_server_ios.mm",
+ "joypad_ios.mm",
"godot_view.mm",
"tts_ios.mm",
"display_layer.mm",
@@ -23,7 +23,7 @@ iphone_lib = [
]
env_ios = env.Clone()
-ios_lib = env_ios.add_library("iphone", iphone_lib)
+ios_lib = env_ios.add_library("ios", ios_lib)
# (iOS) Enable module support
env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
@@ -32,9 +32,9 @@ env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
def combine_libs(target=None, source=None, env=None):
lib_path = target[0].srcnode().abspath
if "osxcross" in env:
- libtool = "$IPHONEPATH/usr/bin/${ios_triple}libtool"
+ libtool = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}libtool"
else:
- libtool = "$IPHONEPATH/usr/bin/libtool"
+ libtool = "$IOS_TOOLCHAIN_PATH/usr/bin/libtool"
env.Execute(
libtool + ' -static -o "' + lib_path + '" ' + " ".join([('"' + lib.srcnode().abspath + '"') for lib in source])
)
diff --git a/platform/iphone/api/api.cpp b/platform/ios/api/api.cpp
index f2e6fd7a7a..00c76a9256 100644
--- a/platform/iphone/api/api.cpp
+++ b/platform/ios/api/api.cpp
@@ -30,19 +30,19 @@
#include "api.h"
-#if defined(IPHONE_ENABLED)
+#if defined(IOS_ENABLED)
-void register_iphone_api() {
+void register_ios_api() {
godot_ios_plugins_initialize();
}
-void unregister_iphone_api() {
+void unregister_ios_api() {
godot_ios_plugins_deinitialize();
}
#else
-void register_iphone_api() {}
-void unregister_iphone_api() {}
+void register_ios_api() {}
+void unregister_ios_api() {}
#endif
diff --git a/platform/iphone/api/api.h b/platform/ios/api/api.h
index ece91a9f1a..c7fd4ce77b 100644
--- a/platform/iphone/api/api.h
+++ b/platform/ios/api/api.h
@@ -28,15 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef IPHONE_API_H
-#define IPHONE_API_H
+#ifndef IOS_API_H
+#define IOS_API_H
-#if defined(IPHONE_ENABLED)
+#if defined(IOS_ENABLED)
extern void godot_ios_plugins_initialize();
extern void godot_ios_plugins_deinitialize();
#endif
-void register_iphone_api();
-void unregister_iphone_api();
+void register_ios_api();
+void unregister_ios_api();
-#endif // IPHONE_API_H
+#endif // IOS_API_H
diff --git a/platform/iphone/app_delegate.h b/platform/ios/app_delegate.h
index 0ec1dc071b..0ec1dc071b 100644
--- a/platform/iphone/app_delegate.h
+++ b/platform/ios/app_delegate.h
diff --git a/platform/iphone/app_delegate.mm b/platform/ios/app_delegate.mm
index c5c9b5a5f9..fb183d52d4 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/ios/app_delegate.mm
@@ -34,7 +34,7 @@
#include "drivers/coreaudio/audio_driver_coreaudio.h"
#import "godot_view.h"
#include "main/main.h"
-#include "os_iphone.h"
+#include "os_ios.h"
#import "view_controller.h"
#import <AVFoundation/AVFoundation.h>
@@ -45,8 +45,8 @@
extern int gargc;
extern char **gargv;
-extern int iphone_main(int, char **, String, String);
-extern void iphone_finish();
+extern int ios_main(int, char **, String, String);
+extern void ios_finish();
@implementation AppDelegate
@@ -71,7 +71,7 @@ static ViewController *mainViewController = nil;
paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths objectAtIndex:0];
- int err = iphone_main(gargc, gargv, String::utf8([documentsDirectory UTF8String]), String::utf8([cacheDirectory UTF8String]));
+ int err = ios_main(gargc, gargv, String::utf8([documentsDirectory UTF8String]), String::utf8([cacheDirectory UTF8String]));
if (err != 0) {
// bail, things did not go very well for us, should probably output a message on screen with our error code...
@@ -106,10 +106,10 @@ static ViewController *mainViewController = nil;
if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
NSLog(@"Audio interruption began");
- OSIPhone::get_singleton()->on_focus_out();
+ OS_IOS::get_singleton()->on_focus_out();
} else if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeEnded]]) {
NSLog(@"Audio interruption ended");
- OSIPhone::get_singleton()->on_focus_in();
+ OS_IOS::get_singleton()->on_focus_in();
}
}
}
@@ -121,7 +121,7 @@ static ViewController *mainViewController = nil;
}
- (void)applicationWillTerminate:(UIApplication *)application {
- iphone_finish();
+ ios_finish();
}
// When application goes to background (e.g. user switches to another app or presses Home),
@@ -135,11 +135,11 @@ static ViewController *mainViewController = nil;
// notification panel by swiping from the upper part of the screen.
- (void)applicationWillResignActive:(UIApplication *)application {
- OSIPhone::get_singleton()->on_focus_out();
+ OS_IOS::get_singleton()->on_focus_out();
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
- OSIPhone::get_singleton()->on_focus_in();
+ OS_IOS::get_singleton()->on_focus_in();
}
- (void)dealloc {
diff --git a/platform/iphone/detect.py b/platform/ios/detect.py
index 392a0151be..67c90b10a0 100644
--- a/platform/iphone/detect.py
+++ b/platform/ios/detect.py
@@ -23,11 +23,11 @@ def get_opts():
return [
(
- "IPHONEPATH",
- "Path to iPhone toolchain",
+ "IOS_TOOLCHAIN_PATH",
+ "Path to iOS toolchain",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
),
- ("IPHONESDK", "Path to the iPhone SDK", ""),
+ ("IOS_SDK_PATH", "Path to the iOS SDK", ""),
BoolVariable("ios_simulator", "Build for iOS Simulator", False),
BoolVariable("ios_exceptions", "Enable exceptions", False),
("ios_triple", "Triple for ios toolchain", ""),
@@ -75,10 +75,10 @@ def configure(env):
if "OSXCROSS_IOS" in os.environ:
env["osxcross"] = True
- env["ENV"]["PATH"] = env["IPHONEPATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
+ env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
- compiler_path = "$IPHONEPATH/usr/bin/${ios_triple}"
- s_compiler_path = "$IPHONEPATH/Developer/usr/bin/"
+ compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}"
+ s_compiler_path = "$IOS_TOOLCHAIN_PATH/Developer/usr/bin/"
ccache_path = os.environ.get("CCACHE")
if ccache_path is None:
@@ -97,11 +97,13 @@ def configure(env):
## Compile flags
if env["ios_simulator"]:
- detect_darwin_sdk_path("iphonesimulator", env)
+ detect_darwin_sdk_path("iossimulator", 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)
+ detect_darwin_sdk_path("ios", env)
+ env.Append(ASFLAGS=["-miphoneos-version-min=11.0"])
env.Append(CCFLAGS=["-miphoneos-version-min=11.0"])
if env["arch"] == "x86_64":
@@ -110,18 +112,20 @@ def configure(env):
CCFLAGS=(
"-fobjc-arc -arch x86_64"
" -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks"
- " -fasm-blocks -isysroot $IPHONESDK"
+ " -fasm-blocks -isysroot $IOS_SDK_PATH"
).split()
)
+ env.Append(ASFLAGS=["-arch", "x86_64"])
elif env["arch"] == "arm64":
env.Append(
CCFLAGS=(
"-fobjc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing"
" -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits"
" -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies"
- " -isysroot $IPHONESDK".split()
+ " -isysroot $IOS_SDK_PATH".split()
)
)
+ env.Append(ASFLAGS=["-arch", "arm64"])
env.Append(CPPDEFINES=["NEED_LONG_INT"])
# Disable exceptions on non-tools (template) builds
@@ -131,18 +135,18 @@ def configure(env):
else:
env.Append(CCFLAGS=["-fno-exceptions"])
- # Temp fix for ABS/MAX/MIN macros in iPhone SDK blocking compilation
+ # Temp fix for ABS/MAX/MIN macros in iOS SDK blocking compilation
env.Append(CCFLAGS=["-Wno-ambiguous-macro"])
env.Prepend(
CPPPATH=[
- "$IPHONESDK/usr/include",
- "$IPHONESDK/System/Library/Frameworks/AudioUnit.framework/Headers",
+ "$IOS_SDK_PATH/usr/include",
+ "$IOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers",
]
)
- env.Prepend(CPPPATH=["#platform/iphone"])
- env.Append(CPPDEFINES=["IPHONE_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED"])
+ env.Prepend(CPPPATH=["#platform/ios"])
+ env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED"])
if env["vulkan"]:
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
diff --git a/platform/iphone/device_metrics.h b/platform/ios/device_metrics.h
index b9fb9b2fd9..b9fb9b2fd9 100644
--- a/platform/iphone/device_metrics.h
+++ b/platform/ios/device_metrics.h
diff --git a/platform/iphone/device_metrics.m b/platform/ios/device_metrics.m
index ec4dd8130d..ec4dd8130d 100644
--- a/platform/iphone/device_metrics.m
+++ b/platform/ios/device_metrics.m
diff --git a/platform/iphone/display_layer.h b/platform/ios/display_layer.h
index a17c75dba1..a17c75dba1 100644
--- a/platform/iphone/display_layer.h
+++ b/platform/ios/display_layer.h
diff --git a/platform/iphone/display_layer.mm b/platform/ios/display_layer.mm
index 92e81448ac..7c83494768 100644
--- a/platform/iphone/display_layer.mm
+++ b/platform/ios/display_layer.mm
@@ -32,9 +32,9 @@
#include "core/config/project_settings.h"
#include "core/os/keyboard.h"
-#include "display_server_iphone.h"
+#include "display_server_ios.h"
#include "main/main.h"
-#include "os_iphone.h"
+#include "os_ios.h"
#include "servers/audio_server.h"
#import <AudioToolbox/AudioServices.h>
diff --git a/platform/iphone/display_server_iphone.h b/platform/ios/display_server_ios.h
index 7af222e3f8..bbb2dd3ab3 100644
--- a/platform/iphone/display_server_iphone.h
+++ b/platform/ios/display_server_ios.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* display_server_iphone.h */
+/* display_server_ios.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef display_server_iphone_h
-#define display_server_iphone_h
+#ifndef DISPLAY_SERVER_IOS_H
+#define DISPLAY_SERVER_IOS_H
#include "core/input/input.h"
#include "servers/display_server.h"
@@ -38,7 +38,7 @@
#include "drivers/vulkan/rendering_device_vulkan.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
-#include "vulkan_context_iphone.h"
+#include "vulkan_context_ios.h"
#import <QuartzCore/CAMetalLayer.h>
#ifdef USE_VOLK
@@ -48,13 +48,13 @@
#endif
#endif
-class DisplayServerIPhone : public DisplayServer {
- GDCLASS(DisplayServerIPhone, DisplayServer)
+class DisplayServerIOS : public DisplayServer {
+ GDCLASS(DisplayServerIOS, DisplayServer)
_THREAD_SAFE_CLASS_
#if defined(VULKAN_ENABLED)
- VulkanContextIPhone *context_vulkan = nullptr;
+ VulkanContextIOS *context_vulkan = nullptr;
RenderingDeviceVulkan *rendering_device_vulkan = nullptr;
#endif
@@ -73,15 +73,15 @@ class DisplayServerIPhone : public DisplayServer {
void perform_event(const Ref<InputEvent> &p_event);
- DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
- ~DisplayServerIPhone();
+ DisplayServerIOS(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ ~DisplayServerIOS();
public:
String rendering_driver;
- static DisplayServerIPhone *get_singleton();
+ static DisplayServerIOS *get_singleton();
- static void register_iphone_driver();
+ static void register_ios_driver();
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
@@ -199,7 +199,7 @@ public:
virtual bool screen_is_touchscreen(int p_screen) const override;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) override;
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) override;
virtual void virtual_keyboard_hide() override;
void virtual_keyboard_set_height(int height);
@@ -214,4 +214,4 @@ public:
void resize_window(CGSize size);
};
-#endif /* display_server_iphone_h */
+#endif // DISPLAY_SERVER_IOS_H
diff --git a/platform/iphone/display_server_iphone.mm b/platform/ios/display_server_ios.mm
index 573ee9b7a8..080ee5f3ab 100644
--- a/platform/iphone/display_server_iphone.mm
+++ b/platform/ios/display_server_ios.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* display_server_iphone.mm */
+/* display_server_ios.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "display_server_iphone.h"
+#include "display_server_ios.h"
#import "app_delegate.h"
#include "core/config/project_settings.h"
@@ -37,20 +37,20 @@
#import "godot_view.h"
#include "ios.h"
#import "keyboard_input_view.h"
-#include "os_iphone.h"
+#include "os_ios.h"
#include "tts_ios.h"
#import "view_controller.h"
#import <Foundation/Foundation.h>
#import <sys/utsname.h>
-static const float kDisplayServerIPhoneAcceleration = 1;
+static const float kDisplayServerIOSAcceleration = 1.f;
-DisplayServerIPhone *DisplayServerIPhone::get_singleton() {
- return (DisplayServerIPhone *)DisplayServer::get_singleton();
+DisplayServerIOS *DisplayServerIOS::get_singleton() {
+ return (DisplayServerIOS *)DisplayServer::get_singleton();
}
-DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
rendering_driver = p_rendering_driver;
// Init TTS
@@ -101,7 +101,7 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Windo
rendering_device_vulkan = nullptr;
if (rendering_driver == "vulkan") {
- context_vulkan = memnew(VulkanContextIPhone);
+ context_vulkan = memnew(VulkanContextIOS);
if (context_vulkan->initialize() != OK) {
memdelete(context_vulkan);
context_vulkan = nullptr;
@@ -136,7 +136,7 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Windo
r_error = OK;
}
-DisplayServerIPhone::~DisplayServerIPhone() {
+DisplayServerIOS::~DisplayServerIOS() {
#if defined(VULKAN_ENABLED)
if (rendering_device_vulkan) {
rendering_device_vulkan->finalize();
@@ -152,11 +152,11 @@ DisplayServerIPhone::~DisplayServerIPhone() {
#endif
}
-DisplayServer *DisplayServerIPhone::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- return memnew(DisplayServerIPhone(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerIOS::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ return memnew(DisplayServerIOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
}
-Vector<String> DisplayServerIPhone::get_rendering_drivers_func() {
+Vector<String> DisplayServerIOS::get_rendering_drivers_func() {
Vector<String> drivers;
#if defined(VULKAN_ENABLED)
@@ -169,56 +169,57 @@ Vector<String> DisplayServerIPhone::get_rendering_drivers_func() {
return drivers;
}
-void DisplayServerIPhone::register_iphone_driver() {
- register_create_function("iphone", create_func, get_rendering_drivers_func);
+void DisplayServerIOS::register_ios_driver() {
+ register_create_function("iOS", create_func, get_rendering_drivers_func);
}
// MARK: Events
-void DisplayServerIPhone::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerIOS::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
window_resize_callback = p_callable;
}
-void DisplayServerIPhone::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerIOS::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) {
window_event_callback = p_callable;
}
-void DisplayServerIPhone::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerIOS::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) {
input_event_callback = p_callable;
}
-void DisplayServerIPhone::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerIOS::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) {
input_text_callback = p_callable;
}
-void DisplayServerIPhone::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerIOS::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) {
// Probably not supported for iOS
}
-void DisplayServerIPhone::process_events() {
+void DisplayServerIOS::process_events() {
+ Input::get_singleton()->flush_buffered_events();
}
-void DisplayServerIPhone::_dispatch_input_events(const Ref<InputEvent> &p_event) {
- DisplayServerIPhone::get_singleton()->send_input_event(p_event);
+void DisplayServerIOS::_dispatch_input_events(const Ref<InputEvent> &p_event) {
+ DisplayServerIOS::get_singleton()->send_input_event(p_event);
}
-void DisplayServerIPhone::send_input_event(const Ref<InputEvent> &p_event) const {
+void DisplayServerIOS::send_input_event(const Ref<InputEvent> &p_event) const {
_window_callback(input_event_callback, p_event);
}
-void DisplayServerIPhone::send_input_text(const String &p_text) const {
+void DisplayServerIOS::send_input_text(const String &p_text) const {
_window_callback(input_text_callback, p_text);
}
-void DisplayServerIPhone::send_window_event(DisplayServer::WindowEvent p_event) const {
+void DisplayServerIOS::send_window_event(DisplayServer::WindowEvent p_event) const {
_window_callback(window_event_callback, int(p_event));
}
-void DisplayServerIPhone::_window_callback(const Callable &p_callable, const Variant &p_arg) const {
+void DisplayServerIOS::_window_callback(const Callable &p_callable, const Variant &p_arg) const {
if (!p_callable.is_null()) {
const Variant *argp = &p_arg;
Variant ret;
Callable::CallError ce;
- p_callable.call((const Variant **)&argp, 1, ret, ce);
+ p_callable.callp((const Variant **)&argp, 1, ret, ce);
}
}
@@ -226,7 +227,7 @@ void DisplayServerIPhone::_window_callback(const Callable &p_callable, const Var
// MARK: Touches
-void DisplayServerIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) {
+void DisplayServerIOS::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) {
if (!GLOBAL_DEF("debug/disable_touch", false)) {
Ref<InputEventScreenTouch> ev;
ev.instantiate();
@@ -238,7 +239,7 @@ void DisplayServerIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_presse
}
}
-void DisplayServerIPhone::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) {
+void DisplayServerIOS::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) {
if (!GLOBAL_DEF("debug/disable_touch", false)) {
Ref<InputEventScreenDrag> ev;
ev.instantiate();
@@ -249,17 +250,17 @@ void DisplayServerIPhone::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int
}
}
-void DisplayServerIPhone::perform_event(const Ref<InputEvent> &p_event) {
+void DisplayServerIOS::perform_event(const Ref<InputEvent> &p_event) {
Input::get_singleton()->parse_input_event(p_event);
}
-void DisplayServerIPhone::touches_cancelled(int p_idx) {
+void DisplayServerIOS::touches_cancelled(int p_idx) {
touch_press(p_idx, -1, -1, false, false);
}
// MARK: Keyboard
-void DisplayServerIPhone::key(Key p_key, bool p_pressed) {
+void DisplayServerIOS::key(Key p_key, bool p_pressed) {
Ref<InputEventKey> ev;
ev.instantiate();
ev->set_echo(false);
@@ -272,31 +273,31 @@ void DisplayServerIPhone::key(Key p_key, bool p_pressed) {
// MARK: Motion
-void DisplayServerIPhone::update_gravity(float p_x, float p_y, float p_z) {
+void DisplayServerIOS::update_gravity(float p_x, float p_y, float p_z) {
Input::get_singleton()->set_gravity(Vector3(p_x, p_y, p_z));
}
-void DisplayServerIPhone::update_accelerometer(float p_x, float p_y, float p_z) {
+void DisplayServerIOS::update_accelerometer(float p_x, float p_y, float p_z) {
// Found out the Z should not be negated! Pass as is!
Vector3 v_accelerometer = Vector3(
- p_x / kDisplayServerIPhoneAcceleration,
- p_y / kDisplayServerIPhoneAcceleration,
- p_z / kDisplayServerIPhoneAcceleration);
+ p_x / kDisplayServerIOSAcceleration,
+ p_y / kDisplayServerIOSAcceleration,
+ p_z / kDisplayServerIOSAcceleration);
Input::get_singleton()->set_accelerometer(v_accelerometer);
}
-void DisplayServerIPhone::update_magnetometer(float p_x, float p_y, float p_z) {
+void DisplayServerIOS::update_magnetometer(float p_x, float p_y, float p_z) {
Input::get_singleton()->set_magnetometer(Vector3(p_x, p_y, p_z));
}
-void DisplayServerIPhone::update_gyroscope(float p_x, float p_y, float p_z) {
+void DisplayServerIOS::update_gyroscope(float p_x, float p_y, float p_z) {
Input::get_singleton()->set_gyroscope(Vector3(p_x, p_y, p_z));
}
// MARK: -
-bool DisplayServerIPhone::has_feature(Feature p_feature) const {
+bool DisplayServerIOS::has_feature(Feature p_feature) const {
switch (p_feature) {
// case FEATURE_CURSOR_SHAPE:
// case FEATURE_CUSTOM_CURSOR_SHAPE:
@@ -321,46 +322,46 @@ bool DisplayServerIPhone::has_feature(Feature p_feature) const {
}
}
-String DisplayServerIPhone::get_name() const {
- return "iPhone";
+String DisplayServerIOS::get_name() const {
+ return "iOS";
}
-bool DisplayServerIPhone::tts_is_speaking() const {
+bool DisplayServerIOS::tts_is_speaking() const {
ERR_FAIL_COND_V(!tts, false);
return [tts isSpeaking];
}
-bool DisplayServerIPhone::tts_is_paused() const {
+bool DisplayServerIOS::tts_is_paused() const {
ERR_FAIL_COND_V(!tts, false);
return [tts isPaused];
}
-Array DisplayServerIPhone::tts_get_voices() const {
+Array DisplayServerIOS::tts_get_voices() const {
ERR_FAIL_COND_V(!tts, Array());
return [tts getVoices];
}
-void DisplayServerIPhone::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
+void DisplayServerIOS::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
ERR_FAIL_COND(!tts);
[tts speak:p_text voice:p_voice volume:p_volume pitch:p_pitch rate:p_rate utterance_id:p_utterance_id interrupt:p_interrupt];
}
-void DisplayServerIPhone::tts_pause() {
+void DisplayServerIOS::tts_pause() {
ERR_FAIL_COND(!tts);
[tts pauseSpeaking];
}
-void DisplayServerIPhone::tts_resume() {
+void DisplayServerIOS::tts_resume() {
ERR_FAIL_COND(!tts);
[tts resumeSpeaking];
}
-void DisplayServerIPhone::tts_stop() {
+void DisplayServerIOS::tts_stop() {
ERR_FAIL_COND(!tts);
[tts stopSpeaking];
}
-Rect2i DisplayServerIPhone::get_display_safe_area() const {
+Rect2i DisplayServerIOS::get_display_safe_area() const {
if (@available(iOS 11, *)) {
UIEdgeInsets insets = UIEdgeInsetsZero;
UIView *view = AppDelegate.viewController.godotView;
@@ -376,15 +377,15 @@ Rect2i DisplayServerIPhone::get_display_safe_area() const {
}
}
-int DisplayServerIPhone::get_screen_count() const {
+int DisplayServerIOS::get_screen_count() const {
return 1;
}
-Point2i DisplayServerIPhone::screen_get_position(int p_screen) const {
+Point2i DisplayServerIOS::screen_get_position(int p_screen) const {
return Size2i();
}
-Size2i DisplayServerIPhone::screen_get_size(int p_screen) const {
+Size2i DisplayServerIOS::screen_get_size(int p_screen) const {
CALayer *layer = AppDelegate.viewController.godotView.renderingLayer;
if (!layer) {
@@ -394,11 +395,11 @@ Size2i DisplayServerIPhone::screen_get_size(int p_screen) const {
return Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_scale(p_screen);
}
-Rect2i DisplayServerIPhone::screen_get_usable_rect(int p_screen) const {
+Rect2i DisplayServerIOS::screen_get_usable_rect(int p_screen) const {
return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen));
}
-int DisplayServerIPhone::screen_get_dpi(int p_screen) const {
+int DisplayServerIOS::screen_get_dpi(int p_screen) const {
struct utsname systemInfo;
uname(&systemInfo);
@@ -435,25 +436,25 @@ int DisplayServerIPhone::screen_get_dpi(int p_screen) const {
}
}
-float DisplayServerIPhone::screen_get_refresh_rate(int p_screen) const {
+float DisplayServerIOS::screen_get_refresh_rate(int p_screen) const {
return [UIScreen mainScreen].maximumFramesPerSecond;
}
-float DisplayServerIPhone::screen_get_scale(int p_screen) const {
+float DisplayServerIOS::screen_get_scale(int p_screen) const {
return [UIScreen mainScreen].nativeScale;
}
-Vector<DisplayServer::WindowID> DisplayServerIPhone::get_window_list() const {
+Vector<DisplayServer::WindowID> DisplayServerIOS::get_window_list() const {
Vector<DisplayServer::WindowID> list;
list.push_back(MAIN_WINDOW_ID);
return list;
}
-DisplayServer::WindowID DisplayServerIPhone::get_window_at_screen_position(const Point2i &p_position) const {
+DisplayServer::WindowID DisplayServerIOS::get_window_at_screen_position(const Point2i &p_position) const {
return MAIN_WINDOW_ID;
}
-int64_t DisplayServerIPhone::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const {
+int64_t DisplayServerIOS::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const {
ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0);
switch (p_handle_type) {
case DISPLAY_HANDLE: {
@@ -471,160 +472,192 @@ int64_t DisplayServerIPhone::window_get_native_handle(HandleType p_handle_type,
}
}
-void DisplayServerIPhone::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
+void DisplayServerIOS::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
window_attached_instance_id = p_instance;
}
-ObjectID DisplayServerIPhone::window_get_attached_instance_id(WindowID p_window) const {
+ObjectID DisplayServerIOS::window_get_attached_instance_id(WindowID p_window) const {
return window_attached_instance_id;
}
-void DisplayServerIPhone::window_set_title(const String &p_title, WindowID p_window) {
+void DisplayServerIOS::window_set_title(const String &p_title, WindowID p_window) {
// Probably not supported for iOS
}
-int DisplayServerIPhone::window_get_current_screen(WindowID p_window) const {
+int DisplayServerIOS::window_get_current_screen(WindowID p_window) const {
return SCREEN_OF_MAIN_WINDOW;
}
-void DisplayServerIPhone::window_set_current_screen(int p_screen, WindowID p_window) {
+void DisplayServerIOS::window_set_current_screen(int p_screen, WindowID p_window) {
// Probably not supported for iOS
}
-Point2i DisplayServerIPhone::window_get_position(WindowID p_window) const {
+Point2i DisplayServerIOS::window_get_position(WindowID p_window) const {
return Point2i();
}
-void DisplayServerIPhone::window_set_position(const Point2i &p_position, WindowID p_window) {
+void DisplayServerIOS::window_set_position(const Point2i &p_position, WindowID p_window) {
// Probably not supported for single window iOS app
}
-void DisplayServerIPhone::window_set_transient(WindowID p_window, WindowID p_parent) {
+void DisplayServerIOS::window_set_transient(WindowID p_window, WindowID p_parent) {
// Probably not supported for iOS
}
-void DisplayServerIPhone::window_set_max_size(const Size2i p_size, WindowID p_window) {
+void DisplayServerIOS::window_set_max_size(const Size2i p_size, WindowID p_window) {
// Probably not supported for iOS
}
-Size2i DisplayServerIPhone::window_get_max_size(WindowID p_window) const {
+Size2i DisplayServerIOS::window_get_max_size(WindowID p_window) const {
return Size2i();
}
-void DisplayServerIPhone::window_set_min_size(const Size2i p_size, WindowID p_window) {
+void DisplayServerIOS::window_set_min_size(const Size2i p_size, WindowID p_window) {
// Probably not supported for iOS
}
-Size2i DisplayServerIPhone::window_get_min_size(WindowID p_window) const {
+Size2i DisplayServerIOS::window_get_min_size(WindowID p_window) const {
return Size2i();
}
-void DisplayServerIPhone::window_set_size(const Size2i p_size, WindowID p_window) {
+void DisplayServerIOS::window_set_size(const Size2i p_size, WindowID p_window) {
// Probably not supported for iOS
}
-Size2i DisplayServerIPhone::window_get_size(WindowID p_window) const {
+Size2i DisplayServerIOS::window_get_size(WindowID p_window) const {
CGRect screenBounds = [UIScreen mainScreen].bounds;
return Size2i(screenBounds.size.width, screenBounds.size.height) * screen_get_max_scale();
}
-Size2i DisplayServerIPhone::window_get_real_size(WindowID p_window) const {
+Size2i DisplayServerIOS::window_get_real_size(WindowID p_window) const {
return window_get_size(p_window);
}
-void DisplayServerIPhone::window_set_mode(WindowMode p_mode, WindowID p_window) {
+void DisplayServerIOS::window_set_mode(WindowMode p_mode, WindowID p_window) {
// Probably not supported for iOS
}
-DisplayServer::WindowMode DisplayServerIPhone::window_get_mode(WindowID p_window) const {
+DisplayServer::WindowMode DisplayServerIOS::window_get_mode(WindowID p_window) const {
return WindowMode::WINDOW_MODE_FULLSCREEN;
}
-bool DisplayServerIPhone::window_is_maximize_allowed(WindowID p_window) const {
+bool DisplayServerIOS::window_is_maximize_allowed(WindowID p_window) const {
return false;
}
-void DisplayServerIPhone::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) {
+void DisplayServerIOS::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) {
// Probably not supported for iOS
}
-bool DisplayServerIPhone::window_get_flag(WindowFlags p_flag, WindowID p_window) const {
+bool DisplayServerIOS::window_get_flag(WindowFlags p_flag, WindowID p_window) const {
return false;
}
-void DisplayServerIPhone::window_request_attention(WindowID p_window) {
+void DisplayServerIOS::window_request_attention(WindowID p_window) {
// Probably not supported for iOS
}
-void DisplayServerIPhone::window_move_to_foreground(WindowID p_window) {
+void DisplayServerIOS::window_move_to_foreground(WindowID p_window) {
// Probably not supported for iOS
}
-float DisplayServerIPhone::screen_get_max_scale() const {
+float DisplayServerIOS::screen_get_max_scale() const {
return screen_get_scale(SCREEN_OF_MAIN_WINDOW);
}
-void DisplayServerIPhone::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) {
+void DisplayServerIOS::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) {
screen_orientation = p_orientation;
}
-DisplayServer::ScreenOrientation DisplayServerIPhone::screen_get_orientation(int p_screen) const {
+DisplayServer::ScreenOrientation DisplayServerIOS::screen_get_orientation(int p_screen) const {
return screen_orientation;
}
-bool DisplayServerIPhone::window_can_draw(WindowID p_window) const {
+bool DisplayServerIOS::window_can_draw(WindowID p_window) const {
return true;
}
-bool DisplayServerIPhone::can_any_window_draw() const {
+bool DisplayServerIOS::can_any_window_draw() const {
return true;
}
-bool DisplayServerIPhone::screen_is_touchscreen(int p_screen) const {
+bool DisplayServerIOS::screen_is_touchscreen(int p_screen) const {
return true;
}
-void DisplayServerIPhone::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) {
+void DisplayServerIOS::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {
NSString *existingString = [[NSString alloc] initWithUTF8String:p_existing_text.utf8().get_data()];
+ AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
+ AppDelegate.viewController.keyboardView.textContentType = nil;
+ switch (p_type) {
+ case KEYBOARD_TYPE_DEFAULT: {
+ AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
+ } break;
+ case KEYBOARD_TYPE_MULTILINE: {
+ AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
+ } break;
+ case KEYBOARD_TYPE_NUMBER: {
+ AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeNumberPad;
+ } break;
+ case KEYBOARD_TYPE_NUMBER_DECIMAL: {
+ AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDecimalPad;
+ } break;
+ case KEYBOARD_TYPE_PHONE: {
+ AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypePhonePad;
+ AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeTelephoneNumber;
+ } break;
+ case KEYBOARD_TYPE_EMAIL_ADDRESS: {
+ AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeEmailAddress;
+ AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeEmailAddress;
+ } break;
+ case KEYBOARD_TYPE_PASSWORD: {
+ AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
+ AppDelegate.viewController.keyboardView.textContentType = UITextContentTypePassword;
+ } break;
+ case KEYBOARD_TYPE_URL: {
+ AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeWebSearch;
+ AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeURL;
+ } break;
+ }
+
[AppDelegate.viewController.keyboardView
becomeFirstResponderWithString:existingString
- multiline:p_multiline
cursorStart:p_cursor_start
cursorEnd:p_cursor_end];
}
-void DisplayServerIPhone::virtual_keyboard_hide() {
+void DisplayServerIOS::virtual_keyboard_hide() {
[AppDelegate.viewController.keyboardView resignFirstResponder];
}
-void DisplayServerIPhone::virtual_keyboard_set_height(int height) {
+void DisplayServerIOS::virtual_keyboard_set_height(int height) {
virtual_keyboard_height = height * screen_get_max_scale();
}
-int DisplayServerIPhone::virtual_keyboard_get_height() const {
+int DisplayServerIOS::virtual_keyboard_get_height() const {
return virtual_keyboard_height;
}
-void DisplayServerIPhone::clipboard_set(const String &p_text) {
+void DisplayServerIOS::clipboard_set(const String &p_text) {
[UIPasteboard generalPasteboard].string = [NSString stringWithUTF8String:p_text.utf8()];
}
-String DisplayServerIPhone::clipboard_get() const {
+String DisplayServerIOS::clipboard_get() const {
NSString *text = [UIPasteboard generalPasteboard].string;
return String::utf8([text UTF8String]);
}
-void DisplayServerIPhone::screen_set_keep_on(bool p_enable) {
+void DisplayServerIOS::screen_set_keep_on(bool p_enable) {
[UIApplication sharedApplication].idleTimerDisabled = p_enable;
}
-bool DisplayServerIPhone::screen_is_kept_on() const {
+bool DisplayServerIOS::screen_is_kept_on() const {
return [UIApplication sharedApplication].idleTimerDisabled;
}
-void DisplayServerIPhone::resize_window(CGSize viewSize) {
+void DisplayServerIOS::resize_window(CGSize viewSize) {
Size2i size = Size2i(viewSize.width, viewSize.height) * screen_get_max_scale();
#if defined(VULKAN_ENABLED)
@@ -637,14 +670,14 @@ void DisplayServerIPhone::resize_window(CGSize viewSize) {
_window_callback(window_resize_callback, resize_rect);
}
-void DisplayServerIPhone::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+void DisplayServerIOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
#endif
}
-DisplayServer::VSyncMode DisplayServerIPhone::window_get_vsync_mode(WindowID p_window) const {
+DisplayServer::VSyncMode DisplayServerIOS::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
return context_vulkan->get_vsync_mode(p_window);
diff --git a/platform/iphone/export/export.cpp b/platform/ios/export/export.cpp
index 3b02e661c1..6024db2f2c 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/ios/export/export.cpp
@@ -30,9 +30,10 @@
#include "export.h"
+#include "editor/export/editor_export.h"
#include "export_plugin.h"
-void register_iphone_exporter() {
+void register_ios_exporter() {
Ref<EditorExportPlatformIOS> platform;
platform.instantiate();
diff --git a/platform/osx/export/export.h b/platform/ios/export/export.h
index b386337a09..756a1356ea 100644
--- a/platform/osx/export/export.h
+++ b/platform/ios/export/export.h
@@ -28,9 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef OSX_EXPORT_H
-#define OSX_EXPORT_H
+#ifndef IOS_EXPORT_H
+#define IOS_EXPORT_H
-void register_osx_exporter();
+void register_ios_exporter();
-#endif // OSX_EXPORT_H
+#endif // IOS_EXPORT_H
diff --git a/platform/iphone/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 4cf1c279eb..9ca2948542 100644
--- a/platform/iphone/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -30,9 +30,10 @@
#include "export_plugin.h"
+#include "core/string/translation.h"
#include "editor/editor_node.h"
-void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
+void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
// Vulkan and OpenGL ES 3.0 both mandate ETC2 support.
r_features->push_back("etc2");
@@ -43,7 +44,7 @@ void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset>
}
}
-Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() {
+Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() const {
Vector<ExportArchitecture> archs;
archs.push_back(ExportArchitecture("arm64", true));
return archs;
@@ -418,7 +419,7 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
}
// !BAS! I'm assuming the 9 in the original code was a typo. I've added -1 or else it seems to also be adding our terminating zero...
- // should apply the same fix in our OSX export.
+ // should apply the same fix in our macOS export.
CharString cs = strnew.utf8();
pfile.resize(cs.size() - 1);
for (int i = 0; i < cs.size() - 1; i++) {
@@ -1155,7 +1156,7 @@ Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir
return OK;
}
-Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<EditorExportPreset> &p_preset) {
+Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<EditorExportPreset> &p_preset) const {
Vector<ExportArchitecture> all_archs = _get_supported_architectures();
Vector<String> enabled_archs;
for (int i = 0; i < all_archs.size(); ++i) {
@@ -1394,7 +1395,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (src_pkg_name.is_empty()) {
String err;
- src_pkg_name = find_export_template("iphone.zip", &err);
+ src_pkg_name = find_export_template("ios.zip", &err);
if (src_pkg_name.is_empty()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("Export template not found."));
return ERR_FILE_NOT_FOUND;
@@ -1444,7 +1445,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
return ERR_SKIP;
}
- String library_to_use = "libgodot.iphone." + String(p_debug ? "debug" : "release") + ".xcframework";
+ String library_to_use = "libgodot.ios." + String(p_debug ? "debug" : "release") + ".xcframework";
print_line("Static framework: " + library_to_use);
String pkg_name;
@@ -1502,7 +1503,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
int ret = unzGoToFirstFile(src_pkg_zip);
Vector<uint8_t> project_file_data;
while (ret == UNZ_OK) {
-#if defined(OSX_ENABLED) || defined(X11_ENABLED)
+#if defined(MACOS_ENABLED) || defined(X11_ENABLED)
bool is_execute = false;
#endif
@@ -1527,17 +1528,17 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
//write
- file = file.replace_first("iphone/", "");
+ file = file.replace_first("ios/", "");
if (files_to_parse.has(file)) {
_fix_config_file(p_preset, data, config_data, p_debug);
- } else if (file.begins_with("libgodot.iphone")) {
+ } else if (file.begins_with("libgodot.ios")) {
if (!file.begins_with(library_to_use) || file.ends_with(String("/empty"))) {
ret = unzGoToNextFile(src_pkg_zip);
continue; //ignore!
}
found_library = true;
-#if defined(OSX_ENABLED) || defined(X11_ENABLED)
+#if defined(MACOS_ENABLED) || defined(X11_ENABLED)
is_execute = true;
#endif
file = file.replace(library_to_use, binary_name + ".xcframework");
@@ -1580,7 +1581,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
f->store_buffer(data.ptr(), data.size());
}
-#if defined(OSX_ENABLED) || defined(X11_ENABLED)
+#if defined(MACOS_ENABLED) || defined(X11_ENABLED)
if (is_execute) {
// we need execute rights on this file
chmod(file.utf8().get_data(), 0755);
@@ -1725,7 +1726,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
f->store_buffer(project_file_data.ptr(), project_file_data.size());
}
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
{
if (ep.step("Code-signing dylibs", 2)) {
return ERR_SKIP;
@@ -1790,7 +1791,7 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset
// Look for export templates (first official, and if defined custom templates).
- bool dvalid = exists_export_template("iphone.zip", &err);
+ bool dvalid = exists_export_template("ios.zip", &err);
bool rvalid = dvalid; // Both in the same ZIP.
if (p_preset->get("custom_template/debug") != "") {
@@ -1838,12 +1839,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(_ios_logo)));
plugins_changed.set();
-
check_for_changes_thread.start(_check_for_changes_poll_thread, this);
}
diff --git a/platform/iphone/export/export_plugin.h b/platform/ios/export/export_plugin.h
index 1db7418e3f..07e30c1d00 100644
--- a/platform/iphone/export/export_plugin.h
+++ b/platform/ios/export/export_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef IPHONE_EXPORT_PLUGIN_H
-#define IPHONE_EXPORT_PLUGIN_H
+#ifndef IOS_EXPORT_PLUGIN_H
+#define IOS_EXPORT_PLUGIN_H
#include "core/config/project_settings.h"
#include "core/io/file_access.h"
@@ -40,10 +40,10 @@
#include "core/os/os.h"
#include "core/templates/safe_refcount.h"
#include "core/version.h"
-#include "editor/editor_export.h"
#include "editor/editor_settings.h"
+#include "editor/export/editor_export_platform.h"
#include "main/splash.gen.h"
-#include "platform/iphone/logo.gen.h"
+#include "platform/ios/logo.gen.h"
#include "string.h"
#include "godot_plugin_config.h"
@@ -106,8 +106,8 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
Error _export_loading_screen_file(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir);
Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir);
- Vector<ExportArchitecture> _get_supported_architectures();
- Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset);
+ Vector<ExportArchitecture> _get_supported_architectures() const;
+ Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset) const;
void _add_assets_to_project(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets);
Error _export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets);
@@ -173,7 +173,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
}
protected:
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
virtual void get_export_options(List<ExportOption> *r_options) override;
public:
@@ -199,7 +199,7 @@ public:
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override;
- virtual void get_platform_features(List<String> *r_features) override {
+ virtual void get_platform_features(List<String> *r_features) const override {
r_features->push_back("mobile");
r_features->push_back("ios");
}
@@ -290,4 +290,4 @@ public:
}
};
-#endif
+#endif // IOS_EXPORT_PLUGIN_H
diff --git a/platform/iphone/export/godot_plugin_config.cpp b/platform/ios/export/godot_plugin_config.cpp
index 9118b95337..9118b95337 100644
--- a/platform/iphone/export/godot_plugin_config.cpp
+++ b/platform/ios/export/godot_plugin_config.cpp
diff --git a/platform/iphone/export/godot_plugin_config.h b/platform/ios/export/godot_plugin_config.h
index 9ef8aa8c6d..5ca8b05b42 100644
--- a/platform/iphone/export/godot_plugin_config.h
+++ b/platform/ios/export/godot_plugin_config.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef IPHONE_GODOT_PLUGIN_CONFIG_H
-#define IPHONE_GODOT_PLUGIN_CONFIG_H
+#ifndef IOS_GODOT_PLUGIN_CONFIG_H
+#define IOS_GODOT_PLUGIN_CONFIG_H
#include "core/error/error_list.h"
#include "core/io/config_file.h"
@@ -129,4 +129,4 @@ struct PluginConfigIOS {
static PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, const String &path);
};
-#endif // GODOT_PLUGIN_CONFIG_H
+#endif // IOS_GODOT_PLUGIN_CONFIG_H
diff --git a/platform/iphone/godot_app_delegate.h b/platform/ios/godot_app_delegate.h
index 703a906bda..703a906bda 100644
--- a/platform/iphone/godot_app_delegate.h
+++ b/platform/ios/godot_app_delegate.h
diff --git a/platform/iphone/godot_app_delegate.m b/platform/ios/godot_app_delegate.m
index 84347f9a30..84347f9a30 100644
--- a/platform/iphone/godot_app_delegate.m
+++ b/platform/ios/godot_app_delegate.m
diff --git a/platform/iphone/godot_iphone.mm b/platform/ios/godot_ios.mm
index 49474ef554..5f3e786b8a 100644
--- a/platform/iphone/godot_iphone.mm
+++ b/platform/ios/godot_ios.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* godot_iphone.mm */
+/* godot_ios.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -30,17 +30,17 @@
#include "core/string/ustring.h"
#include "main/main.h"
-#include "os_iphone.h"
+#include "os_ios.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-static OSIPhone *os = nullptr;
+static OS_IOS *os = nullptr;
int add_path(int, char **);
int add_cmdline(int, char **);
-int iphone_main(int, char **, String);
+int ios_main(int, char **, String);
int add_path(int p_argc, char **p_args) {
NSString *str = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"godot_path"];
@@ -74,7 +74,7 @@ int add_cmdline(int p_argc, char **p_args) {
return p_argc;
}
-int iphone_main(int argc, char **argv, String data_dir, String cache_dir) {
+int ios_main(int argc, char **argv, String data_dir, String cache_dir) {
size_t len = strlen(argv[0]);
while (len--) {
@@ -91,11 +91,11 @@ int iphone_main(int argc, char **argv, String data_dir, String cache_dir) {
chdir(path);
}
- printf("godot_iphone %s\n", argv[0]);
+ printf("godot_ios %s\n", argv[0]);
char cwd[512];
getcwd(cwd, sizeof(cwd));
printf("cwd %s\n", cwd);
- os = new OSIPhone(data_dir, cache_dir);
+ os = new OS_IOS(data_dir, cache_dir);
// We must override main when testing is enabled
TEST_MAIN_OVERRIDE
@@ -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;
}
@@ -121,8 +124,8 @@ int iphone_main(int argc, char **argv, String data_dir, String cache_dir) {
return 0;
}
-void iphone_finish() {
- printf("iphone_finish\n");
+void ios_finish() {
+ printf("ios_finish\n");
Main::cleanup();
delete os;
}
diff --git a/platform/iphone/godot_view.h b/platform/ios/godot_view.h
index fcb97fa63a..fcb97fa63a 100644
--- a/platform/iphone/godot_view.h
+++ b/platform/ios/godot_view.h
diff --git a/platform/iphone/godot_view.mm b/platform/ios/godot_view.mm
index e48dd2e507..9ed219508c 100644
--- a/platform/iphone/godot_view.mm
+++ b/platform/ios/godot_view.mm
@@ -33,7 +33,7 @@
#include "core/os/keyboard.h"
#include "core/string/ustring.h"
#import "display_layer.h"
-#include "display_server_iphone.h"
+#include "display_server_ios.h"
#import "godot_view_gesture_recognizer.h"
#import "godot_view_renderer.h"
@@ -281,8 +281,8 @@ static const float earth_gravity = 9.80665;
self.renderingLayer.frame = self.bounds;
[self.renderingLayer layoutDisplayLayer];
- if (DisplayServerIPhone::get_singleton()) {
- DisplayServerIPhone::get_singleton()->resize_window(self.bounds.size);
+ if (DisplayServerIOS::get_singleton()) {
+ DisplayServerIOS::get_singleton()->resize_window(self.bounds.size);
}
}
@@ -348,7 +348,7 @@ static const float earth_gravity = 9.80665;
int tid = [self getTouchIDForTouch:touch];
ERR_FAIL_COND(tid == -1);
CGPoint touchPoint = [touch locationInView:self];
- DisplayServerIPhone::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
+ DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
}
}
}
@@ -362,7 +362,7 @@ static const float earth_gravity = 9.80665;
ERR_FAIL_COND(tid == -1);
CGPoint touchPoint = [touch locationInView:self];
CGPoint prev_point = [touch previousLocationInView:self];
- DisplayServerIPhone::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor);
+ DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor);
}
}
}
@@ -376,7 +376,7 @@ static const float earth_gravity = 9.80665;
ERR_FAIL_COND(tid == -1);
[self removeTouch:touch];
CGPoint touchPoint = [touch locationInView:self];
- DisplayServerIPhone::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
+ DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
}
}
}
@@ -388,7 +388,7 @@ static const float earth_gravity = 9.80665;
UITouch *touch = [tlist objectAtIndex:i];
int tid = [self getTouchIDForTouch:touch];
ERR_FAIL_COND(tid == -1);
- DisplayServerIPhone::get_singleton()->touches_cancelled(tid);
+ DisplayServerIOS::get_singleton()->touches_cancelled(tid);
}
}
[self clearTouches];
@@ -452,28 +452,28 @@ static const float earth_gravity = 9.80665;
switch (interfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft: {
- DisplayServerIPhone::get_singleton()->update_gravity(-gravity.y, gravity.x, gravity.z);
- DisplayServerIPhone::get_singleton()->update_accelerometer(-(acceleration.y + gravity.y), (acceleration.x + gravity.x), acceleration.z + gravity.z);
- DisplayServerIPhone::get_singleton()->update_magnetometer(-magnetic.y, magnetic.x, magnetic.z);
- DisplayServerIPhone::get_singleton()->update_gyroscope(-rotation.y, rotation.x, rotation.z);
+ DisplayServerIOS::get_singleton()->update_gravity(-gravity.y, gravity.x, gravity.z);
+ DisplayServerIOS::get_singleton()->update_accelerometer(-(acceleration.y + gravity.y), (acceleration.x + gravity.x), acceleration.z + gravity.z);
+ DisplayServerIOS::get_singleton()->update_magnetometer(-magnetic.y, magnetic.x, magnetic.z);
+ DisplayServerIOS::get_singleton()->update_gyroscope(-rotation.y, rotation.x, rotation.z);
} break;
case UIInterfaceOrientationLandscapeRight: {
- DisplayServerIPhone::get_singleton()->update_gravity(gravity.y, -gravity.x, gravity.z);
- DisplayServerIPhone::get_singleton()->update_accelerometer((acceleration.y + gravity.y), -(acceleration.x + gravity.x), acceleration.z + gravity.z);
- DisplayServerIPhone::get_singleton()->update_magnetometer(magnetic.y, -magnetic.x, magnetic.z);
- DisplayServerIPhone::get_singleton()->update_gyroscope(rotation.y, -rotation.x, rotation.z);
+ DisplayServerIOS::get_singleton()->update_gravity(gravity.y, -gravity.x, gravity.z);
+ DisplayServerIOS::get_singleton()->update_accelerometer((acceleration.y + gravity.y), -(acceleration.x + gravity.x), acceleration.z + gravity.z);
+ DisplayServerIOS::get_singleton()->update_magnetometer(magnetic.y, -magnetic.x, magnetic.z);
+ DisplayServerIOS::get_singleton()->update_gyroscope(rotation.y, -rotation.x, rotation.z);
} break;
case UIInterfaceOrientationPortraitUpsideDown: {
- DisplayServerIPhone::get_singleton()->update_gravity(-gravity.x, gravity.y, gravity.z);
- DisplayServerIPhone::get_singleton()->update_accelerometer(-(acceleration.x + gravity.x), (acceleration.y + gravity.y), acceleration.z + gravity.z);
- DisplayServerIPhone::get_singleton()->update_magnetometer(-magnetic.x, magnetic.y, magnetic.z);
- DisplayServerIPhone::get_singleton()->update_gyroscope(-rotation.x, rotation.y, rotation.z);
+ DisplayServerIOS::get_singleton()->update_gravity(-gravity.x, gravity.y, gravity.z);
+ DisplayServerIOS::get_singleton()->update_accelerometer(-(acceleration.x + gravity.x), (acceleration.y + gravity.y), acceleration.z + gravity.z);
+ DisplayServerIOS::get_singleton()->update_magnetometer(-magnetic.x, magnetic.y, magnetic.z);
+ DisplayServerIOS::get_singleton()->update_gyroscope(-rotation.x, rotation.y, rotation.z);
} break;
default: { // assume portrait
- DisplayServerIPhone::get_singleton()->update_gravity(gravity.x, gravity.y, gravity.z);
- DisplayServerIPhone::get_singleton()->update_accelerometer(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z);
- DisplayServerIPhone::get_singleton()->update_magnetometer(magnetic.x, magnetic.y, magnetic.z);
- DisplayServerIPhone::get_singleton()->update_gyroscope(rotation.x, rotation.y, rotation.z);
+ DisplayServerIOS::get_singleton()->update_gravity(gravity.x, gravity.y, gravity.z);
+ DisplayServerIOS::get_singleton()->update_accelerometer(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z);
+ DisplayServerIOS::get_singleton()->update_magnetometer(magnetic.x, magnetic.y, magnetic.z);
+ DisplayServerIOS::get_singleton()->update_gyroscope(rotation.x, rotation.y, rotation.z);
} break;
}
}
diff --git a/platform/iphone/godot_view_gesture_recognizer.h b/platform/ios/godot_view_gesture_recognizer.h
index 9fd8a6b222..9fd8a6b222 100644
--- a/platform/iphone/godot_view_gesture_recognizer.h
+++ b/platform/ios/godot_view_gesture_recognizer.h
diff --git a/platform/iphone/godot_view_gesture_recognizer.mm b/platform/ios/godot_view_gesture_recognizer.mm
index 49a92add5e..49a92add5e 100644
--- a/platform/iphone/godot_view_gesture_recognizer.mm
+++ b/platform/ios/godot_view_gesture_recognizer.mm
diff --git a/platform/iphone/godot_view_renderer.h b/platform/ios/godot_view_renderer.h
index b3ee23ae4f..b3ee23ae4f 100644
--- a/platform/iphone/godot_view_renderer.h
+++ b/platform/ios/godot_view_renderer.h
diff --git a/platform/iphone/godot_view_renderer.mm b/platform/ios/godot_view_renderer.mm
index 32477ae41c..140410fbef 100644
--- a/platform/iphone/godot_view_renderer.mm
+++ b/platform/ios/godot_view_renderer.mm
@@ -32,9 +32,9 @@
#include "core/config/project_settings.h"
#include "core/os/keyboard.h"
-#import "display_server_iphone.h"
+#import "display_server_ios.h"
#include "main/main.h"
-#include "os_iphone.h"
+#include "os_ios.h"
#include "servers/audio_server.h"
#import <AudioToolbox/AudioServices.h>
@@ -69,7 +69,7 @@
if (!self.hasStartedMain) {
self.hasStartedMain = YES;
- OSIPhone::get_singleton()->start();
+ OS_IOS::get_singleton()->start();
return YES;
}
@@ -108,11 +108,11 @@
}
- (void)renderOnView:(UIView *)view {
- if (!OSIPhone::get_singleton()) {
+ if (!OS_IOS::get_singleton()) {
return;
}
- OSIPhone::get_singleton()->iterate();
+ OS_IOS::get_singleton()->iterate();
}
@end
diff --git a/platform/iphone/ios.h b/platform/ios/ios.h
index 0607d7b395..0b3842b233 100644
--- a/platform/iphone/ios.h
+++ b/platform/ios/ios.h
@@ -58,4 +58,4 @@ public:
iOS();
};
-#endif
+#endif // IOS_H
diff --git a/platform/iphone/ios.mm b/platform/ios/ios.mm
index 79baae028a..79baae028a 100644
--- a/platform/iphone/ios.mm
+++ b/platform/ios/ios.mm
diff --git a/platform/iphone/joypad_iphone.h b/platform/ios/joypad_ios.h
index 37e272a2c9..66c4b090bc 100644
--- a/platform/iphone/joypad_iphone.h
+++ b/platform/ios/joypad_ios.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* joypad_iphone.h */
+/* joypad_ios.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -30,7 +30,7 @@
#import <GameController/GameController.h>
-@interface JoypadIPhoneObserver : NSObject
+@interface JoypadIOSObserver : NSObject
- (void)startObserving;
- (void)startProcessing;
@@ -38,13 +38,13 @@
@end
-class JoypadIPhone {
+class JoypadIOS {
private:
- JoypadIPhoneObserver *observer;
+ JoypadIOSObserver *observer;
public:
- JoypadIPhone();
- ~JoypadIPhone();
+ JoypadIOS();
+ ~JoypadIOS();
void start_processing();
};
diff --git a/platform/iphone/joypad_iphone.mm b/platform/ios/joypad_ios.mm
index 9c2feeaaca..e147cb2527 100644
--- a/platform/iphone/joypad_iphone.mm
+++ b/platform/ios/joypad_ios.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* joypad_iphone.mm */
+/* joypad_ios.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#import "joypad_iphone.h"
+#import "joypad_ios.h"
#include "core/config/project_settings.h"
#include "drivers/coreaudio/audio_driver_coreaudio.h"
@@ -36,27 +36,27 @@
#import "godot_view.h"
-#include "os_iphone.h"
+#include "os_ios.h"
-JoypadIPhone::JoypadIPhone() {
- observer = [[JoypadIPhoneObserver alloc] init];
+JoypadIOS::JoypadIOS() {
+ observer = [[JoypadIOSObserver alloc] init];
[observer startObserving];
}
-JoypadIPhone::~JoypadIPhone() {
+JoypadIOS::~JoypadIOS() {
if (observer) {
[observer finishObserving];
observer = nil;
}
}
-void JoypadIPhone::start_processing() {
+void JoypadIOS::start_processing() {
if (observer) {
[observer startProcessing];
}
}
-@interface JoypadIPhoneObserver ()
+@interface JoypadIOSObserver ()
@property(assign, nonatomic) BOOL isObserving;
@property(assign, nonatomic) BOOL isProcessing;
@@ -65,7 +65,7 @@ void JoypadIPhone::start_processing() {
@end
-@implementation JoypadIPhoneObserver
+@implementation JoypadIOSObserver
- (instancetype)init {
self = [super init];
diff --git a/platform/iphone/keyboard_input_view.h b/platform/ios/keyboard_input_view.h
index 33fa5d571a..fc34e6a11b 100644
--- a/platform/iphone/keyboard_input_view.h
+++ b/platform/ios/keyboard_input_view.h
@@ -32,6 +32,6 @@
@interface GodotKeyboardInputView : UITextView
-- (BOOL)becomeFirstResponderWithString:(NSString *)existingString multiline:(BOOL)flag cursorStart:(NSInteger)start cursorEnd:(NSInteger)end;
+- (BOOL)becomeFirstResponderWithString:(NSString *)existingString cursorStart:(NSInteger)start cursorEnd:(NSInteger)end;
@end
diff --git a/platform/iphone/keyboard_input_view.mm b/platform/ios/keyboard_input_view.mm
index f2a7b22483..f031a1de22 100644
--- a/platform/iphone/keyboard_input_view.mm
+++ b/platform/ios/keyboard_input_view.mm
@@ -31,8 +31,8 @@
#import "keyboard_input_view.h"
#include "core/os/keyboard.h"
-#include "display_server_iphone.h"
-#include "os_iphone.h"
+#include "display_server_ios.h"
+#include "os_ios.h"
@interface GodotKeyboardInputView () <UITextViewDelegate>
@@ -84,7 +84,7 @@
return YES;
}
-- (BOOL)becomeFirstResponderWithString:(NSString *)existingString multiline:(BOOL)flag cursorStart:(NSInteger)start cursorEnd:(NSInteger)end {
+- (BOOL)becomeFirstResponderWithString:(NSString *)existingString cursorStart:(NSInteger)start cursorEnd:(NSInteger)end {
self.text = existingString;
self.previousText = existingString;
@@ -115,8 +115,8 @@
- (void)deleteText:(NSInteger)charactersToDelete {
for (int i = 0; i < charactersToDelete; i++) {
- DisplayServerIPhone::get_singleton()->key(Key::BACKSPACE, true);
- DisplayServerIPhone::get_singleton()->key(Key::BACKSPACE, false);
+ DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, true);
+ DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, false);
}
}
@@ -138,8 +138,8 @@
break;
}
- DisplayServerIPhone::get_singleton()->key((Key)character, true);
- DisplayServerIPhone::get_singleton()->key((Key)character, false);
+ DisplayServerIOS::get_singleton()->key((Key)character, true);
+ DisplayServerIOS::get_singleton()->key((Key)character, false);
}
}
diff --git a/platform/iphone/logo.png b/platform/ios/logo.png
index 966d8aa70a..966d8aa70a 100644
--- a/platform/iphone/logo.png
+++ b/platform/ios/logo.png
Binary files differ
diff --git a/platform/iphone/main.m b/platform/ios/main.m
index acfa7ab731..acfa7ab731 100644
--- a/platform/iphone/main.m
+++ b/platform/ios/main.m
diff --git a/platform/iphone/os_iphone.h b/platform/ios/os_ios.h
index d03403bbb4..3b88f53b6a 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/ios/os_ios.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* os_iphone.h */
+/* os_ios.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,24 +28,24 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef IPHONE_ENABLED
+#ifdef IOS_ENABLED
-#ifndef OS_IPHONE_H
-#define OS_IPHONE_H
+#ifndef OS_IOS_H
+#define OS_IOS_H
#include "drivers/coreaudio/audio_driver_coreaudio.h"
#include "drivers/unix/os_unix.h"
#include "ios.h"
-#include "joypad_iphone.h"
+#include "joypad_ios.h"
#include "servers/audio_server.h"
#include "servers/rendering/renderer_compositor.h"
#if defined(VULKAN_ENABLED)
#include "drivers/vulkan/rendering_device_vulkan.h"
-#include "platform/iphone/vulkan_context_iphone.h"
+#include "platform/ios/vulkan_context_ios.h"
#endif
-class OSIPhone : public OS_Unix {
+class OS_IOS : public OS_Unix {
private:
static HashMap<String, void *> dynamic_symbol_lookup_table;
friend void register_dynamic_symbol(char *name, void *address);
@@ -54,7 +54,7 @@ private:
iOS *ios = nullptr;
- JoypadIPhone *joypad_iphone = nullptr;
+ JoypadIOS *joypad_ios = nullptr;
MainLoop *main_loop = nullptr;
@@ -79,10 +79,10 @@ private:
void deinitialize_modules();
public:
- static OSIPhone *get_singleton();
+ static OS_IOS *get_singleton();
- OSIPhone(String p_data_dir, String p_cache_dir);
- ~OSIPhone();
+ OS_IOS(String p_data_dir, String p_cache_dir);
+ ~OS_IOS();
void initialize_modules();
@@ -92,6 +92,9 @@ public:
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
+ virtual Vector<String> get_system_fonts() const override;
+ virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override;
+
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
virtual Error close_dynamic_library(void *p_library_handle) override;
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
@@ -119,6 +122,6 @@ public:
void on_focus_in();
};
-#endif // OS_IPHONE_H
+#endif // OS_IOS_H
-#endif // IPHONE_ENABLED
+#endif // OS_IOS_H
diff --git a/platform/iphone/os_iphone.mm b/platform/ios/os_ios.mm
index 95b06b728e..b9d186f355 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/ios/os_ios.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* os_iphone.mm */
+/* os_ios.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,22 +28,23 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef IPHONE_ENABLED
+#ifdef IOS_ENABLED
-#include "os_iphone.h"
+#include "os_ios.h"
#import "app_delegate.h"
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/file_access_pack.h"
-#include "display_server_iphone.h"
+#include "display_server_ios.h"
#include "drivers/unix/syslog_logger.h"
#import "godot_view.h"
#include "main/main.h"
#import "view_controller.h"
#import <AudioToolbox/AudioServices.h>
+#import <CoreText/CoreText.h>
#import <UIKit/UIKit.h>
#import <dlfcn.h>
#include <sys/sysctl.h>
@@ -65,7 +66,7 @@ typedef void (*init_callback)();
static init_callback *ios_init_callbacks = nullptr;
static int ios_init_callbacks_count = 0;
static int ios_init_callbacks_capacity = 0;
-HashMap<String, void *> OSIPhone::dynamic_symbol_lookup_table;
+HashMap<String, void *> OS_IOS::dynamic_symbol_lookup_table;
void add_ios_init_callback(init_callback cb) {
if (ios_init_callbacks_count == ios_init_callbacks_capacity) {
@@ -82,14 +83,14 @@ void add_ios_init_callback(init_callback cb) {
}
void register_dynamic_symbol(char *name, void *address) {
- OSIPhone::dynamic_symbol_lookup_table[String(name)] = address;
+ OS_IOS::dynamic_symbol_lookup_table[String(name)] = address;
}
-OSIPhone *OSIPhone::get_singleton() {
- return (OSIPhone *)OS::get_singleton();
+OS_IOS *OS_IOS::get_singleton() {
+ return (OS_IOS *)OS::get_singleton();
}
-OSIPhone::OSIPhone(String p_data_dir, String p_cache_dir) {
+OS_IOS::OS_IOS(String p_data_dir, String p_cache_dir) {
for (int i = 0; i < ios_init_callbacks_count; ++i) {
ios_init_callbacks[i]();
}
@@ -116,37 +117,37 @@ OSIPhone::OSIPhone(String p_data_dir, String p_cache_dir) {
AudioDriverManager::add_driver(&audio_driver);
- DisplayServerIPhone::register_iphone_driver();
+ DisplayServerIOS::register_ios_driver();
}
-OSIPhone::~OSIPhone() {}
+OS_IOS::~OS_IOS() {}
-void OSIPhone::alert(const String &p_alert, const String &p_title) {
+void OS_IOS::alert(const String &p_alert, const String &p_title) {
const CharString utf8_alert = p_alert.utf8();
const CharString utf8_title = p_title.utf8();
iOS::alert(utf8_alert.get_data(), utf8_title.get_data());
}
-void OSIPhone::initialize_core() {
+void OS_IOS::initialize_core() {
OS_Unix::initialize_core();
set_user_data_dir(user_data_dir);
}
-void OSIPhone::initialize() {
+void OS_IOS::initialize() {
initialize_core();
}
-void OSIPhone::initialize_modules() {
+void OS_IOS::initialize_modules() {
ios = memnew(iOS);
Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", ios));
- joypad_iphone = memnew(JoypadIPhone);
+ joypad_ios = memnew(JoypadIOS);
}
-void OSIPhone::deinitialize_modules() {
- if (joypad_iphone) {
- memdelete(joypad_iphone);
+void OS_IOS::deinitialize_modules() {
+ if (joypad_ios) {
+ memdelete(joypad_ios);
}
if (ios) {
@@ -154,7 +155,7 @@ void OSIPhone::deinitialize_modules() {
}
}
-void OSIPhone::set_main_loop(MainLoop *p_main_loop) {
+void OS_IOS::set_main_loop(MainLoop *p_main_loop) {
main_loop = p_main_loop;
if (main_loop) {
@@ -162,11 +163,11 @@ void OSIPhone::set_main_loop(MainLoop *p_main_loop) {
}
}
-MainLoop *OSIPhone::get_main_loop() const {
+MainLoop *OS_IOS::get_main_loop() const {
return main_loop;
}
-void OSIPhone::delete_main_loop() {
+void OS_IOS::delete_main_loop() {
if (main_loop) {
main_loop->finalize();
memdelete(main_loop);
@@ -175,7 +176,7 @@ void OSIPhone::delete_main_loop() {
main_loop = nullptr;
}
-bool OSIPhone::iterate() {
+bool OS_IOS::iterate() {
if (!main_loop) {
return true;
}
@@ -187,15 +188,15 @@ bool OSIPhone::iterate() {
return Main::iteration();
}
-void OSIPhone::start() {
+void OS_IOS::start() {
Main::start();
- if (joypad_iphone) {
- joypad_iphone->start_processing();
+ if (joypad_ios) {
+ joypad_ios->start_processing();
}
}
-void OSIPhone::finalize() {
+void OS_IOS::finalize() {
deinitialize_modules();
// Already gets called
@@ -204,7 +205,7 @@ void OSIPhone::finalize() {
// MARK: Dynamic Libraries
-Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
+Error OS_IOS::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
if (p_path.length() == 0) {
p_library_handle = RTLD_SELF;
@@ -217,16 +218,16 @@ Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handl
return OS_Unix::open_dynamic_library(p_path, p_library_handle, p_also_set_library_path, r_resolved_path);
}
-Error OSIPhone::close_dynamic_library(void *p_library_handle) {
+Error OS_IOS::close_dynamic_library(void *p_library_handle) {
if (p_library_handle == RTLD_SELF) {
return OK;
}
return OS_Unix::close_dynamic_library(p_library_handle);
}
-Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) {
+Error OS_IOS::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) {
if (p_library_handle == RTLD_SELF) {
- void **ptr = OSIPhone::dynamic_symbol_lookup_table.getptr(p_name);
+ void **ptr = OS_IOS::dynamic_symbol_lookup_table.getptr(p_name);
if (ptr) {
p_symbol_handle = *ptr;
return OK;
@@ -235,11 +236,11 @@ Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const
return OS_Unix::get_dynamic_library_symbol_handle(p_library_handle, p_name, p_symbol_handle, p_optional);
}
-String OSIPhone::get_name() const {
+String OS_IOS::get_name() const {
return "iOS";
}
-String OSIPhone::get_model_name() const {
+String OS_IOS::get_model_name() const {
String model = ios->get_model();
if (model != "") {
return model;
@@ -248,7 +249,7 @@ String OSIPhone::get_model_name() const {
return OS_Unix::get_model_name();
}
-Error OSIPhone::shell_open(String p_uri) {
+Error OS_IOS::shell_open(String p_uri) {
NSString *urlPath = [[NSString alloc] initWithUTF8String:p_uri.utf8().get_data()];
NSURL *url = [NSURL URLWithString:urlPath];
@@ -263,21 +264,21 @@ Error OSIPhone::shell_open(String p_uri) {
return OK;
}
-void OSIPhone::set_user_data_dir(String p_dir) {
+void OS_IOS::set_user_data_dir(String p_dir) {
Ref<DirAccess> da = DirAccess::open(p_dir);
user_data_dir = da->get_current_dir();
printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data());
}
-String OSIPhone::get_user_data_dir() const {
+String OS_IOS::get_user_data_dir() const {
return user_data_dir;
}
-String OSIPhone::get_cache_path() const {
+String OS_IOS::get_cache_path() const {
return cache_dir;
}
-String OSIPhone::get_locale() const {
+String OS_IOS::get_locale() const {
NSString *preferedLanguage = [NSLocale preferredLanguages].firstObject;
if (preferedLanguage) {
@@ -288,12 +289,12 @@ String OSIPhone::get_locale() const {
return String::utf8([localeIdentifier UTF8String]).replace("-", "_");
}
-String OSIPhone::get_unique_id() const {
+String OS_IOS::get_unique_id() const {
NSString *uuid = [UIDevice currentDevice].identifierForVendor.UUIDString;
return String::utf8([uuid UTF8String]);
}
-String OSIPhone::get_processor_name() const {
+String OS_IOS::get_processor_name() const {
char buffer[256];
size_t buffer_len = 256;
if (sysctlbyname("machdep.cpu.brand_string", &buffer, &buffer_len, NULL, 0) == 0) {
@@ -302,7 +303,81 @@ String OSIPhone::get_processor_name() const {
ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string."));
}
-void OSIPhone::vibrate_handheld(int p_duration_ms) {
+Vector<String> OS_IOS::get_system_fonts() const {
+ HashSet<String> font_names;
+ CFArrayRef fonts = CTFontManagerCopyAvailableFontFamilyNames();
+ if (fonts) {
+ for (CFIndex i = 0; i < CFArrayGetCount(fonts); i++) {
+ CFStringRef cf_name = (CFStringRef)CFArrayGetValueAtIndex(fonts, i);
+ if (cf_name && (CFStringGetLength(cf_name) > 0) && (CFStringCompare(cf_name, CFSTR("LastResort"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && (CFStringGetCharacterAtIndex(cf_name, 0) != '.')) {
+ NSString *ns_name = (__bridge NSString *)cf_name;
+ font_names.insert(String::utf8([ns_name UTF8String]));
+ }
+ }
+ CFRelease(fonts);
+ }
+
+ Vector<String> ret;
+ for (const String &E : font_names) {
+ ret.push_back(E);
+ }
+ return ret;
+}
+
+String OS_IOS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
+ String ret;
+
+ String font_name = p_font_name;
+ if (font_name.to_lower() == "sans-serif") {
+ font_name = "Helvetica";
+ } else if (font_name.to_lower() == "serif") {
+ font_name = "Times";
+ } else if (font_name.to_lower() == "monospace") {
+ font_name = "Courier";
+ } else if (font_name.to_lower() == "fantasy") {
+ font_name = "Papyrus";
+ } else if (font_name.to_lower() == "cursive") {
+ font_name = "Apple Chancery";
+ };
+
+ CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
+
+ CTFontSymbolicTraits traits = 0;
+ if (p_bold) {
+ traits |= kCTFontBoldTrait;
+ }
+ if (p_italic) {
+ traits |= kCTFontItalicTrait;
+ }
+
+ CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
+ CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
+ CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
+
+ CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
+ CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
+ CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
+
+ CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes);
+ if (font) {
+ CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(font, kCTFontURLAttribute);
+ if (url) {
+ NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]];
+ ret = String::utf8([font_path UTF8String]);
+ CFRelease(url);
+ }
+ CFRelease(font);
+ }
+
+ CFRelease(attributes);
+ CFRelease(traits_dict);
+ CFRelease(sym_traits);
+ CFRelease(name);
+
+ return ret;
+}
+
+void OS_IOS::vibrate_handheld(int p_duration_ms) {
if (ios->supports_haptic_engine()) {
ios->vibrate_haptic_engine((float)p_duration_ms / 1000.f);
} else {
@@ -311,16 +386,16 @@ void OSIPhone::vibrate_handheld(int p_duration_ms) {
}
}
-bool OSIPhone::_check_internal_feature_support(const String &p_feature) {
+bool OS_IOS::_check_internal_feature_support(const String &p_feature) {
return p_feature == "mobile";
}
-void OSIPhone::on_focus_out() {
+void OS_IOS::on_focus_out() {
if (is_focused) {
is_focused = false;
- if (DisplayServerIPhone::get_singleton()) {
- DisplayServerIPhone::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT);
+ if (DisplayServerIOS::get_singleton()) {
+ DisplayServerIOS::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT);
}
[AppDelegate.viewController.godotView stopRendering];
@@ -329,12 +404,12 @@ void OSIPhone::on_focus_out() {
}
}
-void OSIPhone::on_focus_in() {
+void OS_IOS::on_focus_in() {
if (!is_focused) {
is_focused = true;
- if (DisplayServerIPhone::get_singleton()) {
- DisplayServerIPhone::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN);
+ if (DisplayServerIOS::get_singleton()) {
+ DisplayServerIOS::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN);
}
[AppDelegate.viewController.godotView startRendering];
@@ -343,4 +418,4 @@ void OSIPhone::on_focus_in() {
}
}
-#endif // IPHONE_ENABLED
+#endif // IOS_ENABLED
diff --git a/platform/iphone/platform_config.h b/platform/ios/platform_config.h
index fed77d8932..fed77d8932 100644
--- a/platform/iphone/platform_config.h
+++ b/platform/ios/platform_config.h
diff --git a/platform/iphone/tts_ios.h b/platform/ios/tts_ios.h
index 064316b0b2..064316b0b2 100644
--- a/platform/iphone/tts_ios.h
+++ b/platform/ios/tts_ios.h
diff --git a/platform/iphone/tts_ios.mm b/platform/ios/tts_ios.mm
index a079d02add..a079d02add 100644
--- a/platform/iphone/tts_ios.mm
+++ b/platform/ios/tts_ios.mm
diff --git a/platform/iphone/view_controller.h b/platform/ios/view_controller.h
index c8b37a4d11..c8b37a4d11 100644
--- a/platform/iphone/view_controller.h
+++ b/platform/ios/view_controller.h
diff --git a/platform/iphone/view_controller.mm b/platform/ios/view_controller.mm
index 4f4ef4f046..43669d3f94 100644
--- a/platform/iphone/view_controller.mm
+++ b/platform/ios/view_controller.mm
@@ -30,11 +30,11 @@
#import "view_controller.h"
#include "core/config/project_settings.h"
-#include "display_server_iphone.h"
+#include "display_server_ios.h"
#import "godot_view.h"
#import "godot_view_renderer.h"
#import "keyboard_input_view.h"
-#include "os_iphone.h"
+#include "os_ios.h"
#import <AVFoundation/AVFoundation.h>
#import <GameController/GameController.h>
@@ -168,11 +168,11 @@
}
- (BOOL)shouldAutorotate {
- if (!DisplayServerIPhone::get_singleton()) {
+ if (!DisplayServerIOS::get_singleton()) {
return NO;
}
- switch (DisplayServerIPhone::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) {
+ switch (DisplayServerIOS::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) {
case DisplayServer::SCREEN_SENSOR:
case DisplayServer::SCREEN_SENSOR_LANDSCAPE:
case DisplayServer::SCREEN_SENSOR_PORTRAIT:
@@ -183,11 +183,11 @@
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
- if (!DisplayServerIPhone::get_singleton()) {
+ if (!DisplayServerIOS::get_singleton()) {
return UIInterfaceOrientationMaskAll;
}
- switch (DisplayServerIPhone::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) {
+ switch (DisplayServerIOS::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) {
case DisplayServer::SCREEN_PORTRAIT:
return UIInterfaceOrientationMaskPortrait;
case DisplayServer::SCREEN_REVERSE_LANDSCAPE:
@@ -226,14 +226,14 @@
CGRect rawFrame = [value CGRectValue];
CGRect keyboardFrame = [self.view convertRect:rawFrame fromView:nil];
- if (DisplayServerIPhone::get_singleton()) {
- DisplayServerIPhone::get_singleton()->virtual_keyboard_set_height(keyboardFrame.size.height);
+ if (DisplayServerIOS::get_singleton()) {
+ DisplayServerIOS::get_singleton()->virtual_keyboard_set_height(keyboardFrame.size.height);
}
}
- (void)keyboardHidden:(NSNotification *)notification {
- if (DisplayServerIPhone::get_singleton()) {
- DisplayServerIPhone::get_singleton()->virtual_keyboard_set_height(0);
+ if (DisplayServerIOS::get_singleton()) {
+ DisplayServerIOS::get_singleton()->virtual_keyboard_set_height(0);
}
}
diff --git a/platform/iphone/vulkan_context_iphone.h b/platform/ios/vulkan_context_ios.h
index 7576525755..e9c09e087a 100644
--- a/platform/iphone/vulkan_context_iphone.h
+++ b/platform/ios/vulkan_context_ios.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* vulkan_context_iphone.h */
+/* vulkan_context_ios.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,21 +28,21 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VULKAN_CONTEXT_IPHONE_H
-#define VULKAN_CONTEXT_IPHONE_H
+#ifndef VULKAN_CONTEXT_IOS_H
+#define VULKAN_CONTEXT_IOS_H
#include "drivers/vulkan/vulkan_context.h"
#import <UIKit/UIKit.h>
-class VulkanContextIPhone : public VulkanContext {
+class VulkanContextIOS : public VulkanContext {
virtual const char *_get_platform_surface_extension() const;
public:
Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height);
- VulkanContextIPhone();
- ~VulkanContextIPhone();
+ VulkanContextIOS();
+ ~VulkanContextIOS();
};
-#endif // VULKAN_CONTEXT_IPHONE_H
+#endif // VULKAN_CONTEXT_IOS_H
diff --git a/platform/iphone/vulkan_context_iphone.mm b/platform/ios/vulkan_context_ios.mm
index 17cb0f6009..09cd369aa5 100644
--- a/platform/iphone/vulkan_context_iphone.mm
+++ b/platform/ios/vulkan_context_ios.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* vulkan_context_iphone.mm */
+/* vulkan_context_ios.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,18 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "vulkan_context_iphone.h"
+#include "vulkan_context_ios.h"
#ifdef USE_VOLK
#include <volk.h>
#else
#include <vulkan/vulkan.h>
#endif
-const char *VulkanContextIPhone::_get_platform_surface_extension() const {
+const char *VulkanContextIOS::_get_platform_surface_extension() const {
return VK_MVK_IOS_SURFACE_EXTENSION_NAME;
}
-Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height) {
+Error VulkanContextIOS::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height) {
VkIOSSurfaceCreateInfoMVK createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = nullptr;
@@ -54,6 +54,6 @@ Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, Di
return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
-VulkanContextIPhone::VulkanContextIPhone() {}
+VulkanContextIOS::VulkanContextIOS() {}
-VulkanContextIPhone::~VulkanContextIPhone() {}
+VulkanContextIOS::~VulkanContextIOS() {}
diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h
index b7b0b3ac96..807e2f936b 100644
--- a/platform/javascript/audio_driver_javascript.h
+++ b/platform/javascript/audio_driver_javascript.h
@@ -158,4 +158,4 @@ public:
};
#endif
-#endif
+#endif // AUDIO_DRIVER_JAVASCRIPT_H
diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp
index a96c539a1f..48f637fcfe 100644
--- a/platform/javascript/display_server_javascript.cpp
+++ b/platform/javascript/display_server_javascript.cpp
@@ -83,7 +83,7 @@ void DisplayServerJavaScript::drop_files_js_callback(char **p_filev, int p_filec
Variant *vp = &v;
Variant ret;
Callable::CallError ce;
- ds->drop_files_callback.call((const Variant **)&vp, 1, ret, ce);
+ ds->drop_files_callback.callp((const Variant **)&vp, 1, ret, ce);
}
// JavaScript quit request callback.
@@ -94,7 +94,7 @@ void DisplayServerJavaScript::request_quit_callback() {
Variant *eventp = &event;
Variant ret;
Callable::CallError ce;
- ds->window_event_callback.call((const Variant **)&eventp, 1, ret, ce);
+ ds->window_event_callback.callp((const Variant **)&eventp, 1, ret, ce);
}
}
@@ -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";
}
}
@@ -586,7 +586,7 @@ void DisplayServerJavaScript::vk_input_text_callback(const char *p_text, int p_c
Variant *eventp = &event;
Variant ret;
Callable::CallError ce;
- ds->input_text_callback.call((const Variant **)&eventp, 1, ret, ce);
+ ds->input_text_callback.callp((const Variant **)&eventp, 1, ret, ce);
// Insert key right to reach position.
Input *input = Input::get_singleton();
Ref<InputEventKey> k;
@@ -604,8 +604,8 @@ void DisplayServerJavaScript::vk_input_text_callback(const char *p_text, int p_c
}
}
-void DisplayServerJavaScript::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
- godot_js_display_vk_show(p_existing_text.utf8().get_data(), p_multiline, p_cursor_start, p_cursor_end);
+void DisplayServerJavaScript::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+ godot_js_display_vk_show(p_existing_text.utf8().get_data(), p_type, p_cursor_start, p_cursor_end);
}
void DisplayServerJavaScript::virtual_keyboard_hide() {
@@ -691,7 +691,7 @@ void DisplayServerJavaScript::send_window_event_callback(int p_notification) {
Variant *eventp = &event;
Variant ret;
Callable::CallError ce;
- ds->window_event_callback.call((const Variant **)&eventp, 1, ret, ce);
+ ds->window_event_callback.callp((const Variant **)&eventp, 1, ret, ce);
}
}
@@ -734,7 +734,7 @@ void DisplayServerJavaScript::_dispatch_input_event(const Ref<InputEvent> &p_eve
Variant *evp = &ev;
Variant ret;
Callable::CallError ce;
- cb.call((const Variant **)&evp, 1, ret, ce);
+ cb.callp((const Variant **)&evp, 1, ret, ce);
}
}
diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h
index 79b0fbb652..fb7f5d02a8 100644
--- a/platform/javascript/display_server_javascript.h
+++ b/platform/javascript/display_server_javascript.h
@@ -157,7 +157,7 @@ public:
virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
virtual void virtual_keyboard_hide() override;
// windows
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index 825c1b6638..ea236f62f7 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -30,6 +30,7 @@
#include "export.h"
+#include "editor/editor_settings.h"
#include "export_plugin.h"
void register_javascript_exporter() {
diff --git a/platform/javascript/export/export.h b/platform/javascript/export/export.h
index 41cc66cfb8..29c335ed0e 100644
--- a/platform/javascript/export/export.h
+++ b/platform/javascript/export/export.h
@@ -33,4 +33,4 @@
void register_javascript_exporter();
-#endif
+#endif // JAVASCRIPT_EXPORT_H
diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp
index 901580c140..b99f88d067 100644
--- a/platform/javascript/export/export_plugin.cpp
+++ b/platform/javascript/export/export_plugin.cpp
@@ -31,6 +31,7 @@
#include "export_plugin.h"
#include "core/config/project_settings.h"
+#include "editor/editor_settings.h"
Error EditorExportPlatformJavaScript::_extract_template(const String &p_template, const String &p_dir, const String &p_name, bool pwa) {
Ref<FileAccess> io_fa;
@@ -302,7 +303,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> &
return OK;
}
-void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
+void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
if (p_preset->get("vram_texture_compression/for_desktop")) {
r_features->push_back("s3tc");
}
@@ -661,13 +662,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/javascript/export/export_plugin.h b/platform/javascript/export/export_plugin.h
index 1aaec5454d..fbaa3615cb 100644
--- a/platform/javascript/export/export_plugin.h
+++ b/platform/javascript/export/export_plugin.h
@@ -36,8 +36,8 @@
#include "core/io/stream_peer_ssl.h"
#include "core/io/tcp_server.h"
#include "core/io/zip_io.h"
-#include "editor/editor_export.h"
#include "editor/editor_node.h"
+#include "editor/export/editor_export_platform.h"
#include "main/splash.gen.h"
#include "platform/javascript/logo.gen.h"
#include "platform/javascript/run_icon.gen.h"
@@ -110,7 +110,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
static void _server_thread_poll(void *data);
public:
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
virtual void get_export_options(List<ExportOption> *r_options) override;
@@ -130,7 +130,7 @@ public:
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_option, int p_debug_flags) override;
virtual Ref<Texture2D> get_run_icon() const override;
- virtual void get_platform_features(List<String> *r_features) override {
+ virtual void get_platform_features(List<String> *r_features) const override {
r_features->push_back("web");
r_features->push_back(get_os_name().to_lower());
}
@@ -144,4 +144,4 @@ public:
~EditorExportPlatformJavaScript();
};
-#endif
+#endif // JAVASCRIPT_EXPORT_PLUGIN_H
diff --git a/platform/javascript/export/export_server.h b/platform/javascript/export/export_server.h
index a831b76076..ddbe3cca30 100644
--- a/platform/javascript/export/export_server.h
+++ b/platform/javascript/export/export_server.h
@@ -35,7 +35,6 @@
#include "core/io/stream_peer_ssl.h"
#include "core/io/tcp_server.h"
#include "core/io/zip_io.h"
-#include "editor/editor_export.h"
#include "editor/editor_paths.h"
class EditorHTTPServer : public RefCounted {
@@ -248,4 +247,4 @@ public:
}
};
-#endif
+#endif // JAVASCRIPT_EXPORT_SERVER_H
diff --git a/platform/javascript/godot_audio.h b/platform/javascript/godot_audio.h
index 012f8daeb7..3855b7301e 100644
--- a/platform/javascript/godot_audio.h
+++ b/platform/javascript/godot_audio.h
@@ -63,4 +63,4 @@ extern void godot_audio_script_start(float *p_in_buf, int p_in_size, float *p_ou
}
#endif
-#endif /* GODOT_AUDIO_H */
+#endif // GODOT_AUDIO_H
diff --git a/platform/javascript/godot_js.h b/platform/javascript/godot_js.h
index 1a383c9799..a323f2d157 100644
--- a/platform/javascript/godot_js.h
+++ b/platform/javascript/godot_js.h
@@ -58,6 +58,7 @@ extern void godot_js_input_mouse_move_cb(void (*p_callback)(double p_x, double p
extern void godot_js_input_mouse_wheel_cb(int (*p_callback)(double p_delta_x, double p_delta_y));
extern void godot_js_input_touch_cb(void (*p_callback)(int p_type, int p_count), uint32_t *r_identifiers, double *r_coords);
extern void godot_js_input_key_cb(void (*p_callback)(int p_type, int p_repeat, int p_modifiers), char r_code[32], char r_key[32]);
+extern void godot_js_input_vibrate_handheld(int p_duration_ms);
// Input gamepad
extern void godot_js_input_gamepad_cb(void (*p_on_change)(int p_index, int p_connected, const char *p_id, const char *p_guid));
@@ -120,11 +121,11 @@ extern void godot_js_display_notification_cb(void (*p_callback)(int p_notificati
extern int godot_js_display_vk_available();
extern int godot_js_display_tts_available();
extern void godot_js_display_vk_cb(void (*p_input)(const char *p_text, int p_cursor));
-extern void godot_js_display_vk_show(const char *p_text, int p_multiline, int p_start, int p_end);
+extern void godot_js_display_vk_show(const char *p_text, int p_type, int p_start, int p_end);
extern void godot_js_display_vk_hide();
#ifdef __cplusplus
}
#endif
-#endif /* GODOT_JS_H */
+#endif // GODOT_JS_H
diff --git a/platform/javascript/godot_webgl2.h b/platform/javascript/godot_webgl2.h
index 7c357ff66d..968b70f84b 100644
--- a/platform/javascript/godot_webgl2.h
+++ b/platform/javascript/godot_webgl2.h
@@ -34,4 +34,4 @@
#include "GLES3/gl3.h"
#include "webgl/webgl2.h"
-#endif
+#endif // GODOT_WEBGL2_H
diff --git a/platform/javascript/http_client_javascript.h b/platform/javascript/http_client_javascript.h
index 096aa6a153..fcd225ffc9 100644
--- a/platform/javascript/http_client_javascript.h
+++ b/platform/javascript/http_client_javascript.h
@@ -105,4 +105,5 @@ public:
HTTPClientJavaScript();
~HTTPClientJavaScript();
};
+
#endif // HTTP_CLIENT_JAVASCRIPT_H
diff --git a/platform/javascript/javascript_singleton.cpp b/platform/javascript/javascript_singleton.cpp
index 8dc7aba5f8..204e92b82b 100644
--- a/platform/javascript/javascript_singleton.cpp
+++ b/platform/javascript/javascript_singleton.cpp
@@ -259,7 +259,7 @@ void JavaScriptObjectImpl::_callback(void *p_ref, int p_args_id, int p_argc) {
const Variant *argv[1] = { &arg };
Callable::CallError err;
Variant ret;
- obj->_callable.call(argv, 1, ret, err);
+ obj->_callable.callp(argv, 1, ret, err);
// Set return value
godot_js_wrapper_ex exchange;
diff --git a/platform/javascript/js/engine/config.js b/platform/javascript/js/engine/config.js
index 2e5e1ed0d1..9c4b6c2012 100644
--- a/platform/javascript/js/engine/config.js
+++ b/platform/javascript/js/engine/config.js
@@ -334,6 +334,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
locale = navigator.languages ? navigator.languages[0] : navigator.language;
locale = locale.split('.')[0];
}
+ locale = locale.replace('-', '_');
const onExit = this.onExit;
// Godot configuration.
diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js
index 5997631bf8..c7729a8c5b 100644
--- a/platform/javascript/js/libs/library_godot_display.js
+++ b/platform/javascript/js/libs/library_godot_display.js
@@ -73,7 +73,7 @@ const GodotDisplayVK = {
GodotDisplayVK.textarea = create('textarea');
GodotDisplayVK.updateSize();
},
- show: function (text, multiline, start, end) {
+ show: function (text, type, start, end) {
if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) {
return;
}
@@ -81,7 +81,46 @@ const GodotDisplayVK = {
GodotDisplayVK.hide();
}
GodotDisplayVK.updateSize();
- const elem = multiline ? GodotDisplayVK.textarea : GodotDisplayVK.textinput;
+
+ let elem = GodotDisplayVK.textinput;
+ switch (type) {
+ case 0: // KEYBOARD_TYPE_DEFAULT
+ elem.type = 'text';
+ elem.inputmode = '';
+ break;
+ case 1: // KEYBOARD_TYPE_MULTILINE
+ elem = GodotDisplayVK.textarea;
+ break;
+ case 2: // KEYBOARD_TYPE_NUMBER
+ elem.type = 'text';
+ elem.inputmode = 'numeric';
+ break;
+ case 3: // KEYBOARD_TYPE_NUMBER_DECIMAL
+ elem.type = 'text';
+ elem.inputmode = 'decimal';
+ break;
+ case 4: // KEYBOARD_TYPE_PHONE
+ elem.type = 'tel';
+ elem.inputmode = '';
+ break;
+ case 5: // KEYBOARD_TYPE_EMAIL_ADDRESS
+ elem.type = 'email';
+ elem.inputmode = '';
+ break;
+ case 6: // KEYBOARD_TYPE_PASSWORD
+ elem.type = 'password';
+ elem.inputmode = '';
+ break;
+ case 7: // KEYBOARD_TYPE_URL
+ elem.type = 'url';
+ elem.inputmode = '';
+ break;
+ default:
+ elem.type = 'text';
+ elem.inputmode = '';
+ break;
+ }
+
elem.readonly = false;
elem.disabled = false;
elem.value = text;
@@ -694,11 +733,11 @@ const GodotDisplay = {
* Virtual Keyboard
*/
godot_js_display_vk_show__sig: 'viiii',
- godot_js_display_vk_show: function (p_text, p_multiline, p_start, p_end) {
+ godot_js_display_vk_show: function (p_text, p_type, p_start, p_end) {
const text = GodotRuntime.parseString(p_text);
const start = p_start > 0 ? p_start : 0;
const end = p_end > 0 ? p_end : start;
- GodotDisplayVK.show(text, p_multiline, start, end);
+ GodotDisplayVK.show(text, p_type, start, end);
},
godot_js_display_vk_hide__sig: 'v',
diff --git a/platform/javascript/js/libs/library_godot_input.js b/platform/javascript/js/libs/library_godot_input.js
index 1e64c260f8..51571d64a2 100644
--- a/platform/javascript/js/libs/library_godot_input.js
+++ b/platform/javascript/js/libs/library_godot_input.js
@@ -534,6 +534,15 @@ const GodotInput = {
GodotRuntime.free(ptr);
}, false);
},
+
+ godot_js_input_vibrate_handheld__sig: 'vi',
+ godot_js_input_vibrate_handheld: function (p_duration_ms) {
+ if (typeof navigator.vibrate !== 'function') {
+ GodotRuntime.print('This browser does not support vibration.');
+ } else {
+ navigator.vibrate(p_duration_ms);
+ }
+ },
};
autoAddDeps(GodotInput, '$GodotInput');
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index 1686353229..dc81b8b4b6 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -177,6 +177,10 @@ String OS_JavaScript::get_name() const {
return "HTML5";
}
+void OS_JavaScript::vibrate_handheld(int p_duration_ms) {
+ godot_js_input_vibrate_handheld(p_duration_ms);
+}
+
String OS_JavaScript::get_user_data_dir() const {
return "/userfs";
}
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 0c672111cc..35e13c94fc 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -90,6 +90,8 @@ public:
// Implemented in javascript_main.cpp loop callback instead.
void add_frame_delay(bool p_can_draw) override {}
+ void vibrate_handheld(int p_duration_ms) override;
+
String get_cache_path() const override;
String get_config_path() const override;
String get_data_path() const override;
@@ -107,4 +109,4 @@ public:
OS_JavaScript();
};
-#endif
+#endif // OS_JAVASCRIPT_H
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub
index 09a432eae2..35c41556ee 100644
--- a/platform/linuxbsd/SCsub
+++ b/platform/linuxbsd/SCsub
@@ -12,7 +12,7 @@ common_linuxbsd = [
"freedesktop_screensaver.cpp",
]
-if "x11" in env and env["x11"]:
+if env["x11"]:
common_linuxbsd += [
"gl_manager_x11.cpp",
"detect_prime_x11.cpp",
@@ -20,15 +20,21 @@ if "x11" in env and env["x11"]:
"key_mapping_x11.cpp",
]
-if "speechd" in env and env["speechd"]:
+ if env["vulkan"]:
+ common_linuxbsd.append("vulkan_context_x11.cpp")
+
+if env["speechd"]:
common_linuxbsd.append(["speechd-so_wrap.c", "tts_linux.cpp"])
-if "vulkan" in env and env["vulkan"]:
- common_linuxbsd.append("vulkan_context_x11.cpp")
+if env["fontconfig"]:
+ common_linuxbsd.append("fontconfig-so_wrap.c")
-if "udev" in env and env["udev"]:
+if env["udev"]:
common_linuxbsd.append("libudev-so_wrap.c")
+if env["dbus"]:
+ common_linuxbsd.append("dbus-so_wrap.c")
+
prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_linuxbsd)
if env["debug_symbols"] and env["separate_debug_symbols"]:
diff --git a/platform/linuxbsd/crash_handler_linuxbsd.h b/platform/linuxbsd/crash_handler_linuxbsd.h
index 2e44476c3f..1b77352cca 100644
--- a/platform/linuxbsd/crash_handler_linuxbsd.h
+++ b/platform/linuxbsd/crash_handler_linuxbsd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CRASH_HANDLER_X11_H
-#define CRASH_HANDLER_X11_H
+#ifndef CRASH_HANDLER_LINUXBSD_H
+#define CRASH_HANDLER_LINUXBSD_H
class CrashHandler {
bool disabled;
@@ -44,4 +44,4 @@ public:
~CrashHandler();
};
-#endif // CRASH_HANDLER_X11_H
+#endif // CRASH_HANDLER_LINUXBSD_H
diff --git a/platform/linuxbsd/dbus-so_wrap.c b/platform/linuxbsd/dbus-so_wrap.c
new file mode 100644
index 0000000000..0876bc88b0
--- /dev/null
+++ b/platform/linuxbsd/dbus-so_wrap.c
@@ -0,0 +1,2641 @@
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by ./generate-wrapper.py 0.3 on 2022-07-29 07:23:21
+// flags: ./generate-wrapper.py --include /usr/include/dbus-1.0/dbus/dbus.h --sys-include <dbus/dbus.h> --soname libdbus-1.so --init-name dbus --output-header dbus-so_wrap.h --output-implementation dbus-so_wrap.c
+//
+#include <stdint.h>
+
+#define dbus_error_init dbus_error_init_dylibloader_orig_dbus
+#define dbus_error_free dbus_error_free_dylibloader_orig_dbus
+#define dbus_set_error dbus_set_error_dylibloader_orig_dbus
+#define dbus_set_error_const dbus_set_error_const_dylibloader_orig_dbus
+#define dbus_move_error dbus_move_error_dylibloader_orig_dbus
+#define dbus_error_has_name dbus_error_has_name_dylibloader_orig_dbus
+#define dbus_error_is_set dbus_error_is_set_dylibloader_orig_dbus
+#define dbus_parse_address dbus_parse_address_dylibloader_orig_dbus
+#define dbus_address_entry_get_value dbus_address_entry_get_value_dylibloader_orig_dbus
+#define dbus_address_entry_get_method dbus_address_entry_get_method_dylibloader_orig_dbus
+#define dbus_address_entries_free dbus_address_entries_free_dylibloader_orig_dbus
+#define dbus_address_escape_value dbus_address_escape_value_dylibloader_orig_dbus
+#define dbus_address_unescape_value dbus_address_unescape_value_dylibloader_orig_dbus
+#define dbus_malloc dbus_malloc_dylibloader_orig_dbus
+#define dbus_malloc0 dbus_malloc0_dylibloader_orig_dbus
+#define dbus_realloc dbus_realloc_dylibloader_orig_dbus
+#define dbus_free dbus_free_dylibloader_orig_dbus
+#define dbus_free_string_array dbus_free_string_array_dylibloader_orig_dbus
+#define dbus_shutdown dbus_shutdown_dylibloader_orig_dbus
+#define dbus_message_new dbus_message_new_dylibloader_orig_dbus
+#define dbus_message_new_method_call dbus_message_new_method_call_dylibloader_orig_dbus
+#define dbus_message_new_method_return dbus_message_new_method_return_dylibloader_orig_dbus
+#define dbus_message_new_signal dbus_message_new_signal_dylibloader_orig_dbus
+#define dbus_message_new_error dbus_message_new_error_dylibloader_orig_dbus
+#define dbus_message_new_error_printf dbus_message_new_error_printf_dylibloader_orig_dbus
+#define dbus_message_copy dbus_message_copy_dylibloader_orig_dbus
+#define dbus_message_ref dbus_message_ref_dylibloader_orig_dbus
+#define dbus_message_unref dbus_message_unref_dylibloader_orig_dbus
+#define dbus_message_get_type dbus_message_get_type_dylibloader_orig_dbus
+#define dbus_message_set_path dbus_message_set_path_dylibloader_orig_dbus
+#define dbus_message_get_path dbus_message_get_path_dylibloader_orig_dbus
+#define dbus_message_has_path dbus_message_has_path_dylibloader_orig_dbus
+#define dbus_message_set_interface dbus_message_set_interface_dylibloader_orig_dbus
+#define dbus_message_get_interface dbus_message_get_interface_dylibloader_orig_dbus
+#define dbus_message_has_interface dbus_message_has_interface_dylibloader_orig_dbus
+#define dbus_message_set_member dbus_message_set_member_dylibloader_orig_dbus
+#define dbus_message_get_member dbus_message_get_member_dylibloader_orig_dbus
+#define dbus_message_has_member dbus_message_has_member_dylibloader_orig_dbus
+#define dbus_message_set_error_name dbus_message_set_error_name_dylibloader_orig_dbus
+#define dbus_message_get_error_name dbus_message_get_error_name_dylibloader_orig_dbus
+#define dbus_message_set_destination dbus_message_set_destination_dylibloader_orig_dbus
+#define dbus_message_get_destination dbus_message_get_destination_dylibloader_orig_dbus
+#define dbus_message_set_sender dbus_message_set_sender_dylibloader_orig_dbus
+#define dbus_message_get_sender dbus_message_get_sender_dylibloader_orig_dbus
+#define dbus_message_get_signature dbus_message_get_signature_dylibloader_orig_dbus
+#define dbus_message_set_no_reply dbus_message_set_no_reply_dylibloader_orig_dbus
+#define dbus_message_get_no_reply dbus_message_get_no_reply_dylibloader_orig_dbus
+#define dbus_message_is_method_call dbus_message_is_method_call_dylibloader_orig_dbus
+#define dbus_message_is_signal dbus_message_is_signal_dylibloader_orig_dbus
+#define dbus_message_is_error dbus_message_is_error_dylibloader_orig_dbus
+#define dbus_message_has_destination dbus_message_has_destination_dylibloader_orig_dbus
+#define dbus_message_has_sender dbus_message_has_sender_dylibloader_orig_dbus
+#define dbus_message_has_signature dbus_message_has_signature_dylibloader_orig_dbus
+#define dbus_message_get_serial dbus_message_get_serial_dylibloader_orig_dbus
+#define dbus_message_set_serial dbus_message_set_serial_dylibloader_orig_dbus
+#define dbus_message_set_reply_serial dbus_message_set_reply_serial_dylibloader_orig_dbus
+#define dbus_message_get_reply_serial dbus_message_get_reply_serial_dylibloader_orig_dbus
+#define dbus_message_set_auto_start dbus_message_set_auto_start_dylibloader_orig_dbus
+#define dbus_message_get_auto_start dbus_message_get_auto_start_dylibloader_orig_dbus
+#define dbus_message_get_path_decomposed dbus_message_get_path_decomposed_dylibloader_orig_dbus
+#define dbus_message_append_args dbus_message_append_args_dylibloader_orig_dbus
+#define dbus_message_append_args_valist dbus_message_append_args_valist_dylibloader_orig_dbus
+#define dbus_message_get_args dbus_message_get_args_dylibloader_orig_dbus
+#define dbus_message_get_args_valist dbus_message_get_args_valist_dylibloader_orig_dbus
+#define dbus_message_contains_unix_fds dbus_message_contains_unix_fds_dylibloader_orig_dbus
+#define dbus_message_iter_init_closed dbus_message_iter_init_closed_dylibloader_orig_dbus
+#define dbus_message_iter_init dbus_message_iter_init_dylibloader_orig_dbus
+#define dbus_message_iter_has_next dbus_message_iter_has_next_dylibloader_orig_dbus
+#define dbus_message_iter_next dbus_message_iter_next_dylibloader_orig_dbus
+#define dbus_message_iter_get_signature dbus_message_iter_get_signature_dylibloader_orig_dbus
+#define dbus_message_iter_get_arg_type dbus_message_iter_get_arg_type_dylibloader_orig_dbus
+#define dbus_message_iter_get_element_type dbus_message_iter_get_element_type_dylibloader_orig_dbus
+#define dbus_message_iter_recurse dbus_message_iter_recurse_dylibloader_orig_dbus
+#define dbus_message_iter_get_basic dbus_message_iter_get_basic_dylibloader_orig_dbus
+#define dbus_message_iter_get_element_count dbus_message_iter_get_element_count_dylibloader_orig_dbus
+#define dbus_message_iter_get_array_len dbus_message_iter_get_array_len_dylibloader_orig_dbus
+#define dbus_message_iter_get_fixed_array dbus_message_iter_get_fixed_array_dylibloader_orig_dbus
+#define dbus_message_iter_init_append dbus_message_iter_init_append_dylibloader_orig_dbus
+#define dbus_message_iter_append_basic dbus_message_iter_append_basic_dylibloader_orig_dbus
+#define dbus_message_iter_append_fixed_array dbus_message_iter_append_fixed_array_dylibloader_orig_dbus
+#define dbus_message_iter_open_container dbus_message_iter_open_container_dylibloader_orig_dbus
+#define dbus_message_iter_close_container dbus_message_iter_close_container_dylibloader_orig_dbus
+#define dbus_message_iter_abandon_container dbus_message_iter_abandon_container_dylibloader_orig_dbus
+#define dbus_message_iter_abandon_container_if_open dbus_message_iter_abandon_container_if_open_dylibloader_orig_dbus
+#define dbus_message_lock dbus_message_lock_dylibloader_orig_dbus
+#define dbus_set_error_from_message dbus_set_error_from_message_dylibloader_orig_dbus
+#define dbus_message_allocate_data_slot dbus_message_allocate_data_slot_dylibloader_orig_dbus
+#define dbus_message_free_data_slot dbus_message_free_data_slot_dylibloader_orig_dbus
+#define dbus_message_set_data dbus_message_set_data_dylibloader_orig_dbus
+#define dbus_message_get_data dbus_message_get_data_dylibloader_orig_dbus
+#define dbus_message_type_from_string dbus_message_type_from_string_dylibloader_orig_dbus
+#define dbus_message_type_to_string dbus_message_type_to_string_dylibloader_orig_dbus
+#define dbus_message_marshal dbus_message_marshal_dylibloader_orig_dbus
+#define dbus_message_demarshal dbus_message_demarshal_dylibloader_orig_dbus
+#define dbus_message_demarshal_bytes_needed dbus_message_demarshal_bytes_needed_dylibloader_orig_dbus
+#define dbus_message_set_allow_interactive_authorization dbus_message_set_allow_interactive_authorization_dylibloader_orig_dbus
+#define dbus_message_get_allow_interactive_authorization dbus_message_get_allow_interactive_authorization_dylibloader_orig_dbus
+#define dbus_connection_open dbus_connection_open_dylibloader_orig_dbus
+#define dbus_connection_open_private dbus_connection_open_private_dylibloader_orig_dbus
+#define dbus_connection_ref dbus_connection_ref_dylibloader_orig_dbus
+#define dbus_connection_unref dbus_connection_unref_dylibloader_orig_dbus
+#define dbus_connection_close dbus_connection_close_dylibloader_orig_dbus
+#define dbus_connection_get_is_connected dbus_connection_get_is_connected_dylibloader_orig_dbus
+#define dbus_connection_get_is_authenticated dbus_connection_get_is_authenticated_dylibloader_orig_dbus
+#define dbus_connection_get_is_anonymous dbus_connection_get_is_anonymous_dylibloader_orig_dbus
+#define dbus_connection_get_server_id dbus_connection_get_server_id_dylibloader_orig_dbus
+#define dbus_connection_can_send_type dbus_connection_can_send_type_dylibloader_orig_dbus
+#define dbus_connection_set_exit_on_disconnect dbus_connection_set_exit_on_disconnect_dylibloader_orig_dbus
+#define dbus_connection_flush dbus_connection_flush_dylibloader_orig_dbus
+#define dbus_connection_read_write_dispatch dbus_connection_read_write_dispatch_dylibloader_orig_dbus
+#define dbus_connection_read_write dbus_connection_read_write_dylibloader_orig_dbus
+#define dbus_connection_borrow_message dbus_connection_borrow_message_dylibloader_orig_dbus
+#define dbus_connection_return_message dbus_connection_return_message_dylibloader_orig_dbus
+#define dbus_connection_steal_borrowed_message dbus_connection_steal_borrowed_message_dylibloader_orig_dbus
+#define dbus_connection_pop_message dbus_connection_pop_message_dylibloader_orig_dbus
+#define dbus_connection_get_dispatch_status dbus_connection_get_dispatch_status_dylibloader_orig_dbus
+#define dbus_connection_dispatch dbus_connection_dispatch_dylibloader_orig_dbus
+#define dbus_connection_has_messages_to_send dbus_connection_has_messages_to_send_dylibloader_orig_dbus
+#define dbus_connection_send dbus_connection_send_dylibloader_orig_dbus
+#define dbus_connection_send_with_reply dbus_connection_send_with_reply_dylibloader_orig_dbus
+#define dbus_connection_send_with_reply_and_block dbus_connection_send_with_reply_and_block_dylibloader_orig_dbus
+#define dbus_connection_set_watch_functions dbus_connection_set_watch_functions_dylibloader_orig_dbus
+#define dbus_connection_set_timeout_functions dbus_connection_set_timeout_functions_dylibloader_orig_dbus
+#define dbus_connection_set_wakeup_main_function dbus_connection_set_wakeup_main_function_dylibloader_orig_dbus
+#define dbus_connection_set_dispatch_status_function dbus_connection_set_dispatch_status_function_dylibloader_orig_dbus
+#define dbus_connection_get_unix_user dbus_connection_get_unix_user_dylibloader_orig_dbus
+#define dbus_connection_get_unix_process_id dbus_connection_get_unix_process_id_dylibloader_orig_dbus
+#define dbus_connection_get_adt_audit_session_data dbus_connection_get_adt_audit_session_data_dylibloader_orig_dbus
+#define dbus_connection_set_unix_user_function dbus_connection_set_unix_user_function_dylibloader_orig_dbus
+#define dbus_connection_get_windows_user dbus_connection_get_windows_user_dylibloader_orig_dbus
+#define dbus_connection_set_windows_user_function dbus_connection_set_windows_user_function_dylibloader_orig_dbus
+#define dbus_connection_set_allow_anonymous dbus_connection_set_allow_anonymous_dylibloader_orig_dbus
+#define dbus_connection_set_route_peer_messages dbus_connection_set_route_peer_messages_dylibloader_orig_dbus
+#define dbus_connection_add_filter dbus_connection_add_filter_dylibloader_orig_dbus
+#define dbus_connection_remove_filter dbus_connection_remove_filter_dylibloader_orig_dbus
+#define dbus_connection_allocate_data_slot dbus_connection_allocate_data_slot_dylibloader_orig_dbus
+#define dbus_connection_free_data_slot dbus_connection_free_data_slot_dylibloader_orig_dbus
+#define dbus_connection_set_data dbus_connection_set_data_dylibloader_orig_dbus
+#define dbus_connection_get_data dbus_connection_get_data_dylibloader_orig_dbus
+#define dbus_connection_set_change_sigpipe dbus_connection_set_change_sigpipe_dylibloader_orig_dbus
+#define dbus_connection_set_max_message_size dbus_connection_set_max_message_size_dylibloader_orig_dbus
+#define dbus_connection_get_max_message_size dbus_connection_get_max_message_size_dylibloader_orig_dbus
+#define dbus_connection_set_max_received_size dbus_connection_set_max_received_size_dylibloader_orig_dbus
+#define dbus_connection_get_max_received_size dbus_connection_get_max_received_size_dylibloader_orig_dbus
+#define dbus_connection_set_max_message_unix_fds dbus_connection_set_max_message_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_get_max_message_unix_fds dbus_connection_get_max_message_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_set_max_received_unix_fds dbus_connection_set_max_received_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_get_max_received_unix_fds dbus_connection_get_max_received_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_get_outgoing_size dbus_connection_get_outgoing_size_dylibloader_orig_dbus
+#define dbus_connection_get_outgoing_unix_fds dbus_connection_get_outgoing_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_preallocate_send dbus_connection_preallocate_send_dylibloader_orig_dbus
+#define dbus_connection_free_preallocated_send dbus_connection_free_preallocated_send_dylibloader_orig_dbus
+#define dbus_connection_send_preallocated dbus_connection_send_preallocated_dylibloader_orig_dbus
+#define dbus_connection_try_register_object_path dbus_connection_try_register_object_path_dylibloader_orig_dbus
+#define dbus_connection_register_object_path dbus_connection_register_object_path_dylibloader_orig_dbus
+#define dbus_connection_try_register_fallback dbus_connection_try_register_fallback_dylibloader_orig_dbus
+#define dbus_connection_register_fallback dbus_connection_register_fallback_dylibloader_orig_dbus
+#define dbus_connection_unregister_object_path dbus_connection_unregister_object_path_dylibloader_orig_dbus
+#define dbus_connection_get_object_path_data dbus_connection_get_object_path_data_dylibloader_orig_dbus
+#define dbus_connection_list_registered dbus_connection_list_registered_dylibloader_orig_dbus
+#define dbus_connection_get_unix_fd dbus_connection_get_unix_fd_dylibloader_orig_dbus
+#define dbus_connection_get_socket dbus_connection_get_socket_dylibloader_orig_dbus
+#define dbus_watch_get_fd dbus_watch_get_fd_dylibloader_orig_dbus
+#define dbus_watch_get_unix_fd dbus_watch_get_unix_fd_dylibloader_orig_dbus
+#define dbus_watch_get_socket dbus_watch_get_socket_dylibloader_orig_dbus
+#define dbus_watch_get_flags dbus_watch_get_flags_dylibloader_orig_dbus
+#define dbus_watch_get_data dbus_watch_get_data_dylibloader_orig_dbus
+#define dbus_watch_set_data dbus_watch_set_data_dylibloader_orig_dbus
+#define dbus_watch_handle dbus_watch_handle_dylibloader_orig_dbus
+#define dbus_watch_get_enabled dbus_watch_get_enabled_dylibloader_orig_dbus
+#define dbus_timeout_get_interval dbus_timeout_get_interval_dylibloader_orig_dbus
+#define dbus_timeout_get_data dbus_timeout_get_data_dylibloader_orig_dbus
+#define dbus_timeout_set_data dbus_timeout_set_data_dylibloader_orig_dbus
+#define dbus_timeout_handle dbus_timeout_handle_dylibloader_orig_dbus
+#define dbus_timeout_get_enabled dbus_timeout_get_enabled_dylibloader_orig_dbus
+#define dbus_bus_get dbus_bus_get_dylibloader_orig_dbus
+#define dbus_bus_get_private dbus_bus_get_private_dylibloader_orig_dbus
+#define dbus_bus_register dbus_bus_register_dylibloader_orig_dbus
+#define dbus_bus_set_unique_name dbus_bus_set_unique_name_dylibloader_orig_dbus
+#define dbus_bus_get_unique_name dbus_bus_get_unique_name_dylibloader_orig_dbus
+#define dbus_bus_get_unix_user dbus_bus_get_unix_user_dylibloader_orig_dbus
+#define dbus_bus_get_id dbus_bus_get_id_dylibloader_orig_dbus
+#define dbus_bus_request_name dbus_bus_request_name_dylibloader_orig_dbus
+#define dbus_bus_release_name dbus_bus_release_name_dylibloader_orig_dbus
+#define dbus_bus_name_has_owner dbus_bus_name_has_owner_dylibloader_orig_dbus
+#define dbus_bus_start_service_by_name dbus_bus_start_service_by_name_dylibloader_orig_dbus
+#define dbus_bus_add_match dbus_bus_add_match_dylibloader_orig_dbus
+#define dbus_bus_remove_match dbus_bus_remove_match_dylibloader_orig_dbus
+#define dbus_get_local_machine_id dbus_get_local_machine_id_dylibloader_orig_dbus
+#define dbus_get_version dbus_get_version_dylibloader_orig_dbus
+#define dbus_setenv dbus_setenv_dylibloader_orig_dbus
+#define dbus_try_get_local_machine_id dbus_try_get_local_machine_id_dylibloader_orig_dbus
+#define dbus_pending_call_ref dbus_pending_call_ref_dylibloader_orig_dbus
+#define dbus_pending_call_unref dbus_pending_call_unref_dylibloader_orig_dbus
+#define dbus_pending_call_set_notify dbus_pending_call_set_notify_dylibloader_orig_dbus
+#define dbus_pending_call_cancel dbus_pending_call_cancel_dylibloader_orig_dbus
+#define dbus_pending_call_get_completed dbus_pending_call_get_completed_dylibloader_orig_dbus
+#define dbus_pending_call_steal_reply dbus_pending_call_steal_reply_dylibloader_orig_dbus
+#define dbus_pending_call_block dbus_pending_call_block_dylibloader_orig_dbus
+#define dbus_pending_call_allocate_data_slot dbus_pending_call_allocate_data_slot_dylibloader_orig_dbus
+#define dbus_pending_call_free_data_slot dbus_pending_call_free_data_slot_dylibloader_orig_dbus
+#define dbus_pending_call_set_data dbus_pending_call_set_data_dylibloader_orig_dbus
+#define dbus_pending_call_get_data dbus_pending_call_get_data_dylibloader_orig_dbus
+#define dbus_server_listen dbus_server_listen_dylibloader_orig_dbus
+#define dbus_server_ref dbus_server_ref_dylibloader_orig_dbus
+#define dbus_server_unref dbus_server_unref_dylibloader_orig_dbus
+#define dbus_server_disconnect dbus_server_disconnect_dylibloader_orig_dbus
+#define dbus_server_get_is_connected dbus_server_get_is_connected_dylibloader_orig_dbus
+#define dbus_server_get_address dbus_server_get_address_dylibloader_orig_dbus
+#define dbus_server_get_id dbus_server_get_id_dylibloader_orig_dbus
+#define dbus_server_set_new_connection_function dbus_server_set_new_connection_function_dylibloader_orig_dbus
+#define dbus_server_set_watch_functions dbus_server_set_watch_functions_dylibloader_orig_dbus
+#define dbus_server_set_timeout_functions dbus_server_set_timeout_functions_dylibloader_orig_dbus
+#define dbus_server_set_auth_mechanisms dbus_server_set_auth_mechanisms_dylibloader_orig_dbus
+#define dbus_server_allocate_data_slot dbus_server_allocate_data_slot_dylibloader_orig_dbus
+#define dbus_server_free_data_slot dbus_server_free_data_slot_dylibloader_orig_dbus
+#define dbus_server_set_data dbus_server_set_data_dylibloader_orig_dbus
+#define dbus_server_get_data dbus_server_get_data_dylibloader_orig_dbus
+#define dbus_signature_iter_init dbus_signature_iter_init_dylibloader_orig_dbus
+#define dbus_signature_iter_get_current_type dbus_signature_iter_get_current_type_dylibloader_orig_dbus
+#define dbus_signature_iter_get_signature dbus_signature_iter_get_signature_dylibloader_orig_dbus
+#define dbus_signature_iter_get_element_type dbus_signature_iter_get_element_type_dylibloader_orig_dbus
+#define dbus_signature_iter_next dbus_signature_iter_next_dylibloader_orig_dbus
+#define dbus_signature_iter_recurse dbus_signature_iter_recurse_dylibloader_orig_dbus
+#define dbus_signature_validate dbus_signature_validate_dylibloader_orig_dbus
+#define dbus_signature_validate_single dbus_signature_validate_single_dylibloader_orig_dbus
+#define dbus_type_is_valid dbus_type_is_valid_dylibloader_orig_dbus
+#define dbus_type_is_basic dbus_type_is_basic_dylibloader_orig_dbus
+#define dbus_type_is_container dbus_type_is_container_dylibloader_orig_dbus
+#define dbus_type_is_fixed dbus_type_is_fixed_dylibloader_orig_dbus
+#define dbus_validate_path dbus_validate_path_dylibloader_orig_dbus
+#define dbus_validate_interface dbus_validate_interface_dylibloader_orig_dbus
+#define dbus_validate_member dbus_validate_member_dylibloader_orig_dbus
+#define dbus_validate_error_name dbus_validate_error_name_dylibloader_orig_dbus
+#define dbus_validate_bus_name dbus_validate_bus_name_dylibloader_orig_dbus
+#define dbus_validate_utf8 dbus_validate_utf8_dylibloader_orig_dbus
+#define dbus_threads_init dbus_threads_init_dylibloader_orig_dbus
+#define dbus_threads_init_default dbus_threads_init_default_dylibloader_orig_dbus
+#include <dbus/dbus.h>
+#undef dbus_error_init
+#undef dbus_error_free
+#undef dbus_set_error
+#undef dbus_set_error_const
+#undef dbus_move_error
+#undef dbus_error_has_name
+#undef dbus_error_is_set
+#undef dbus_parse_address
+#undef dbus_address_entry_get_value
+#undef dbus_address_entry_get_method
+#undef dbus_address_entries_free
+#undef dbus_address_escape_value
+#undef dbus_address_unescape_value
+#undef dbus_malloc
+#undef dbus_malloc0
+#undef dbus_realloc
+#undef dbus_free
+#undef dbus_free_string_array
+#undef dbus_shutdown
+#undef dbus_message_new
+#undef dbus_message_new_method_call
+#undef dbus_message_new_method_return
+#undef dbus_message_new_signal
+#undef dbus_message_new_error
+#undef dbus_message_new_error_printf
+#undef dbus_message_copy
+#undef dbus_message_ref
+#undef dbus_message_unref
+#undef dbus_message_get_type
+#undef dbus_message_set_path
+#undef dbus_message_get_path
+#undef dbus_message_has_path
+#undef dbus_message_set_interface
+#undef dbus_message_get_interface
+#undef dbus_message_has_interface
+#undef dbus_message_set_member
+#undef dbus_message_get_member
+#undef dbus_message_has_member
+#undef dbus_message_set_error_name
+#undef dbus_message_get_error_name
+#undef dbus_message_set_destination
+#undef dbus_message_get_destination
+#undef dbus_message_set_sender
+#undef dbus_message_get_sender
+#undef dbus_message_get_signature
+#undef dbus_message_set_no_reply
+#undef dbus_message_get_no_reply
+#undef dbus_message_is_method_call
+#undef dbus_message_is_signal
+#undef dbus_message_is_error
+#undef dbus_message_has_destination
+#undef dbus_message_has_sender
+#undef dbus_message_has_signature
+#undef dbus_message_get_serial
+#undef dbus_message_set_serial
+#undef dbus_message_set_reply_serial
+#undef dbus_message_get_reply_serial
+#undef dbus_message_set_auto_start
+#undef dbus_message_get_auto_start
+#undef dbus_message_get_path_decomposed
+#undef dbus_message_append_args
+#undef dbus_message_append_args_valist
+#undef dbus_message_get_args
+#undef dbus_message_get_args_valist
+#undef dbus_message_contains_unix_fds
+#undef dbus_message_iter_init_closed
+#undef dbus_message_iter_init
+#undef dbus_message_iter_has_next
+#undef dbus_message_iter_next
+#undef dbus_message_iter_get_signature
+#undef dbus_message_iter_get_arg_type
+#undef dbus_message_iter_get_element_type
+#undef dbus_message_iter_recurse
+#undef dbus_message_iter_get_basic
+#undef dbus_message_iter_get_element_count
+#undef dbus_message_iter_get_array_len
+#undef dbus_message_iter_get_fixed_array
+#undef dbus_message_iter_init_append
+#undef dbus_message_iter_append_basic
+#undef dbus_message_iter_append_fixed_array
+#undef dbus_message_iter_open_container
+#undef dbus_message_iter_close_container
+#undef dbus_message_iter_abandon_container
+#undef dbus_message_iter_abandon_container_if_open
+#undef dbus_message_lock
+#undef dbus_set_error_from_message
+#undef dbus_message_allocate_data_slot
+#undef dbus_message_free_data_slot
+#undef dbus_message_set_data
+#undef dbus_message_get_data
+#undef dbus_message_type_from_string
+#undef dbus_message_type_to_string
+#undef dbus_message_marshal
+#undef dbus_message_demarshal
+#undef dbus_message_demarshal_bytes_needed
+#undef dbus_message_set_allow_interactive_authorization
+#undef dbus_message_get_allow_interactive_authorization
+#undef dbus_connection_open
+#undef dbus_connection_open_private
+#undef dbus_connection_ref
+#undef dbus_connection_unref
+#undef dbus_connection_close
+#undef dbus_connection_get_is_connected
+#undef dbus_connection_get_is_authenticated
+#undef dbus_connection_get_is_anonymous
+#undef dbus_connection_get_server_id
+#undef dbus_connection_can_send_type
+#undef dbus_connection_set_exit_on_disconnect
+#undef dbus_connection_flush
+#undef dbus_connection_read_write_dispatch
+#undef dbus_connection_read_write
+#undef dbus_connection_borrow_message
+#undef dbus_connection_return_message
+#undef dbus_connection_steal_borrowed_message
+#undef dbus_connection_pop_message
+#undef dbus_connection_get_dispatch_status
+#undef dbus_connection_dispatch
+#undef dbus_connection_has_messages_to_send
+#undef dbus_connection_send
+#undef dbus_connection_send_with_reply
+#undef dbus_connection_send_with_reply_and_block
+#undef dbus_connection_set_watch_functions
+#undef dbus_connection_set_timeout_functions
+#undef dbus_connection_set_wakeup_main_function
+#undef dbus_connection_set_dispatch_status_function
+#undef dbus_connection_get_unix_user
+#undef dbus_connection_get_unix_process_id
+#undef dbus_connection_get_adt_audit_session_data
+#undef dbus_connection_set_unix_user_function
+#undef dbus_connection_get_windows_user
+#undef dbus_connection_set_windows_user_function
+#undef dbus_connection_set_allow_anonymous
+#undef dbus_connection_set_route_peer_messages
+#undef dbus_connection_add_filter
+#undef dbus_connection_remove_filter
+#undef dbus_connection_allocate_data_slot
+#undef dbus_connection_free_data_slot
+#undef dbus_connection_set_data
+#undef dbus_connection_get_data
+#undef dbus_connection_set_change_sigpipe
+#undef dbus_connection_set_max_message_size
+#undef dbus_connection_get_max_message_size
+#undef dbus_connection_set_max_received_size
+#undef dbus_connection_get_max_received_size
+#undef dbus_connection_set_max_message_unix_fds
+#undef dbus_connection_get_max_message_unix_fds
+#undef dbus_connection_set_max_received_unix_fds
+#undef dbus_connection_get_max_received_unix_fds
+#undef dbus_connection_get_outgoing_size
+#undef dbus_connection_get_outgoing_unix_fds
+#undef dbus_connection_preallocate_send
+#undef dbus_connection_free_preallocated_send
+#undef dbus_connection_send_preallocated
+#undef dbus_connection_try_register_object_path
+#undef dbus_connection_register_object_path
+#undef dbus_connection_try_register_fallback
+#undef dbus_connection_register_fallback
+#undef dbus_connection_unregister_object_path
+#undef dbus_connection_get_object_path_data
+#undef dbus_connection_list_registered
+#undef dbus_connection_get_unix_fd
+#undef dbus_connection_get_socket
+#undef dbus_watch_get_fd
+#undef dbus_watch_get_unix_fd
+#undef dbus_watch_get_socket
+#undef dbus_watch_get_flags
+#undef dbus_watch_get_data
+#undef dbus_watch_set_data
+#undef dbus_watch_handle
+#undef dbus_watch_get_enabled
+#undef dbus_timeout_get_interval
+#undef dbus_timeout_get_data
+#undef dbus_timeout_set_data
+#undef dbus_timeout_handle
+#undef dbus_timeout_get_enabled
+#undef dbus_bus_get
+#undef dbus_bus_get_private
+#undef dbus_bus_register
+#undef dbus_bus_set_unique_name
+#undef dbus_bus_get_unique_name
+#undef dbus_bus_get_unix_user
+#undef dbus_bus_get_id
+#undef dbus_bus_request_name
+#undef dbus_bus_release_name
+#undef dbus_bus_name_has_owner
+#undef dbus_bus_start_service_by_name
+#undef dbus_bus_add_match
+#undef dbus_bus_remove_match
+#undef dbus_get_local_machine_id
+#undef dbus_get_version
+#undef dbus_setenv
+#undef dbus_try_get_local_machine_id
+#undef dbus_pending_call_ref
+#undef dbus_pending_call_unref
+#undef dbus_pending_call_set_notify
+#undef dbus_pending_call_cancel
+#undef dbus_pending_call_get_completed
+#undef dbus_pending_call_steal_reply
+#undef dbus_pending_call_block
+#undef dbus_pending_call_allocate_data_slot
+#undef dbus_pending_call_free_data_slot
+#undef dbus_pending_call_set_data
+#undef dbus_pending_call_get_data
+#undef dbus_server_listen
+#undef dbus_server_ref
+#undef dbus_server_unref
+#undef dbus_server_disconnect
+#undef dbus_server_get_is_connected
+#undef dbus_server_get_address
+#undef dbus_server_get_id
+#undef dbus_server_set_new_connection_function
+#undef dbus_server_set_watch_functions
+#undef dbus_server_set_timeout_functions
+#undef dbus_server_set_auth_mechanisms
+#undef dbus_server_allocate_data_slot
+#undef dbus_server_free_data_slot
+#undef dbus_server_set_data
+#undef dbus_server_get_data
+#undef dbus_signature_iter_init
+#undef dbus_signature_iter_get_current_type
+#undef dbus_signature_iter_get_signature
+#undef dbus_signature_iter_get_element_type
+#undef dbus_signature_iter_next
+#undef dbus_signature_iter_recurse
+#undef dbus_signature_validate
+#undef dbus_signature_validate_single
+#undef dbus_type_is_valid
+#undef dbus_type_is_basic
+#undef dbus_type_is_container
+#undef dbus_type_is_fixed
+#undef dbus_validate_path
+#undef dbus_validate_interface
+#undef dbus_validate_member
+#undef dbus_validate_error_name
+#undef dbus_validate_bus_name
+#undef dbus_validate_utf8
+#undef dbus_threads_init
+#undef dbus_threads_init_default
+#include <dlfcn.h>
+#include <stdio.h>
+void (*dbus_error_init_dylibloader_wrapper_dbus)( DBusError*);
+void (*dbus_error_free_dylibloader_wrapper_dbus)( DBusError*);
+void (*dbus_set_error_dylibloader_wrapper_dbus)( DBusError*,const char*,const char*,...);
+void (*dbus_set_error_const_dylibloader_wrapper_dbus)( DBusError*,const char*,const char*);
+void (*dbus_move_error_dylibloader_wrapper_dbus)( DBusError*, DBusError*);
+dbus_bool_t (*dbus_error_has_name_dylibloader_wrapper_dbus)(const DBusError*,const char*);
+dbus_bool_t (*dbus_error_is_set_dylibloader_wrapper_dbus)(const DBusError*);
+dbus_bool_t (*dbus_parse_address_dylibloader_wrapper_dbus)(const char*, DBusAddressEntry***, int*, DBusError*);
+const char* (*dbus_address_entry_get_value_dylibloader_wrapper_dbus)( DBusAddressEntry*,const char*);
+const char* (*dbus_address_entry_get_method_dylibloader_wrapper_dbus)( DBusAddressEntry*);
+void (*dbus_address_entries_free_dylibloader_wrapper_dbus)( DBusAddressEntry**);
+char* (*dbus_address_escape_value_dylibloader_wrapper_dbus)(const char*);
+char* (*dbus_address_unescape_value_dylibloader_wrapper_dbus)(const char*, DBusError*);
+void* (*dbus_malloc_dylibloader_wrapper_dbus)( size_t);
+void* (*dbus_malloc0_dylibloader_wrapper_dbus)( size_t);
+void* (*dbus_realloc_dylibloader_wrapper_dbus)( void*, size_t);
+void (*dbus_free_dylibloader_wrapper_dbus)( void*);
+void (*dbus_free_string_array_dylibloader_wrapper_dbus)( char**);
+void (*dbus_shutdown_dylibloader_wrapper_dbus)( void);
+DBusMessage* (*dbus_message_new_dylibloader_wrapper_dbus)( int);
+DBusMessage* (*dbus_message_new_method_call_dylibloader_wrapper_dbus)(const char*,const char*,const char*,const char*);
+DBusMessage* (*dbus_message_new_method_return_dylibloader_wrapper_dbus)( DBusMessage*);
+DBusMessage* (*dbus_message_new_signal_dylibloader_wrapper_dbus)(const char*,const char*,const char*);
+DBusMessage* (*dbus_message_new_error_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*);
+DBusMessage* (*dbus_message_new_error_printf_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*,...);
+DBusMessage* (*dbus_message_copy_dylibloader_wrapper_dbus)(const DBusMessage*);
+DBusMessage* (*dbus_message_ref_dylibloader_wrapper_dbus)( DBusMessage*);
+void (*dbus_message_unref_dylibloader_wrapper_dbus)( DBusMessage*);
+int (*dbus_message_get_type_dylibloader_wrapper_dbus)( DBusMessage*);
+dbus_bool_t (*dbus_message_set_path_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+const char* (*dbus_message_get_path_dylibloader_wrapper_dbus)( DBusMessage*);
+dbus_bool_t (*dbus_message_has_path_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+dbus_bool_t (*dbus_message_set_interface_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+const char* (*dbus_message_get_interface_dylibloader_wrapper_dbus)( DBusMessage*);
+dbus_bool_t (*dbus_message_has_interface_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+dbus_bool_t (*dbus_message_set_member_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+const char* (*dbus_message_get_member_dylibloader_wrapper_dbus)( DBusMessage*);
+dbus_bool_t (*dbus_message_has_member_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+dbus_bool_t (*dbus_message_set_error_name_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+const char* (*dbus_message_get_error_name_dylibloader_wrapper_dbus)( DBusMessage*);
+dbus_bool_t (*dbus_message_set_destination_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+const char* (*dbus_message_get_destination_dylibloader_wrapper_dbus)( DBusMessage*);
+dbus_bool_t (*dbus_message_set_sender_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+const char* (*dbus_message_get_sender_dylibloader_wrapper_dbus)( DBusMessage*);
+const char* (*dbus_message_get_signature_dylibloader_wrapper_dbus)( DBusMessage*);
+void (*dbus_message_set_no_reply_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t);
+dbus_bool_t (*dbus_message_get_no_reply_dylibloader_wrapper_dbus)( DBusMessage*);
+dbus_bool_t (*dbus_message_is_method_call_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*);
+dbus_bool_t (*dbus_message_is_signal_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*);
+dbus_bool_t (*dbus_message_is_error_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+dbus_bool_t (*dbus_message_has_destination_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+dbus_bool_t (*dbus_message_has_sender_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+dbus_bool_t (*dbus_message_has_signature_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+dbus_uint32_t (*dbus_message_get_serial_dylibloader_wrapper_dbus)( DBusMessage*);
+void (*dbus_message_set_serial_dylibloader_wrapper_dbus)( DBusMessage*, dbus_uint32_t);
+dbus_bool_t (*dbus_message_set_reply_serial_dylibloader_wrapper_dbus)( DBusMessage*, dbus_uint32_t);
+dbus_uint32_t (*dbus_message_get_reply_serial_dylibloader_wrapper_dbus)( DBusMessage*);
+void (*dbus_message_set_auto_start_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t);
+dbus_bool_t (*dbus_message_get_auto_start_dylibloader_wrapper_dbus)( DBusMessage*);
+dbus_bool_t (*dbus_message_get_path_decomposed_dylibloader_wrapper_dbus)( DBusMessage*, char***);
+dbus_bool_t (*dbus_message_append_args_dylibloader_wrapper_dbus)( DBusMessage*, int,...);
+dbus_bool_t (*dbus_message_append_args_valist_dylibloader_wrapper_dbus)( DBusMessage*, int, va_list);
+dbus_bool_t (*dbus_message_get_args_dylibloader_wrapper_dbus)( DBusMessage*, DBusError*, int,...);
+dbus_bool_t (*dbus_message_get_args_valist_dylibloader_wrapper_dbus)( DBusMessage*, DBusError*, int, va_list);
+dbus_bool_t (*dbus_message_contains_unix_fds_dylibloader_wrapper_dbus)( DBusMessage*);
+void (*dbus_message_iter_init_closed_dylibloader_wrapper_dbus)( DBusMessageIter*);
+dbus_bool_t (*dbus_message_iter_init_dylibloader_wrapper_dbus)( DBusMessage*, DBusMessageIter*);
+dbus_bool_t (*dbus_message_iter_has_next_dylibloader_wrapper_dbus)( DBusMessageIter*);
+dbus_bool_t (*dbus_message_iter_next_dylibloader_wrapper_dbus)( DBusMessageIter*);
+char* (*dbus_message_iter_get_signature_dylibloader_wrapper_dbus)( DBusMessageIter*);
+int (*dbus_message_iter_get_arg_type_dylibloader_wrapper_dbus)( DBusMessageIter*);
+int (*dbus_message_iter_get_element_type_dylibloader_wrapper_dbus)( DBusMessageIter*);
+void (*dbus_message_iter_recurse_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*);
+void (*dbus_message_iter_get_basic_dylibloader_wrapper_dbus)( DBusMessageIter*, void*);
+int (*dbus_message_iter_get_element_count_dylibloader_wrapper_dbus)( DBusMessageIter*);
+int (*dbus_message_iter_get_array_len_dylibloader_wrapper_dbus)( DBusMessageIter*);
+void (*dbus_message_iter_get_fixed_array_dylibloader_wrapper_dbus)( DBusMessageIter*, void*, int*);
+void (*dbus_message_iter_init_append_dylibloader_wrapper_dbus)( DBusMessage*, DBusMessageIter*);
+dbus_bool_t (*dbus_message_iter_append_basic_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const void*);
+dbus_bool_t (*dbus_message_iter_append_fixed_array_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const void*, int);
+dbus_bool_t (*dbus_message_iter_open_container_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const char*, DBusMessageIter*);
+dbus_bool_t (*dbus_message_iter_close_container_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*);
+void (*dbus_message_iter_abandon_container_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*);
+void (*dbus_message_iter_abandon_container_if_open_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*);
+void (*dbus_message_lock_dylibloader_wrapper_dbus)( DBusMessage*);
+dbus_bool_t (*dbus_set_error_from_message_dylibloader_wrapper_dbus)( DBusError*, DBusMessage*);
+dbus_bool_t (*dbus_message_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+void (*dbus_message_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+dbus_bool_t (*dbus_message_set_data_dylibloader_wrapper_dbus)( DBusMessage*, dbus_int32_t, void*, DBusFreeFunction);
+void* (*dbus_message_get_data_dylibloader_wrapper_dbus)( DBusMessage*, dbus_int32_t);
+int (*dbus_message_type_from_string_dylibloader_wrapper_dbus)(const char*);
+const char* (*dbus_message_type_to_string_dylibloader_wrapper_dbus)( int);
+dbus_bool_t (*dbus_message_marshal_dylibloader_wrapper_dbus)( DBusMessage*, char**, int*);
+DBusMessage* (*dbus_message_demarshal_dylibloader_wrapper_dbus)(const char*, int, DBusError*);
+int (*dbus_message_demarshal_bytes_needed_dylibloader_wrapper_dbus)(const char*, int);
+void (*dbus_message_set_allow_interactive_authorization_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t);
+dbus_bool_t (*dbus_message_get_allow_interactive_authorization_dylibloader_wrapper_dbus)( DBusMessage*);
+DBusConnection* (*dbus_connection_open_dylibloader_wrapper_dbus)(const char*, DBusError*);
+DBusConnection* (*dbus_connection_open_private_dylibloader_wrapper_dbus)(const char*, DBusError*);
+DBusConnection* (*dbus_connection_ref_dylibloader_wrapper_dbus)( DBusConnection*);
+void (*dbus_connection_unref_dylibloader_wrapper_dbus)( DBusConnection*);
+void (*dbus_connection_close_dylibloader_wrapper_dbus)( DBusConnection*);
+dbus_bool_t (*dbus_connection_get_is_connected_dylibloader_wrapper_dbus)( DBusConnection*);
+dbus_bool_t (*dbus_connection_get_is_authenticated_dylibloader_wrapper_dbus)( DBusConnection*);
+dbus_bool_t (*dbus_connection_get_is_anonymous_dylibloader_wrapper_dbus)( DBusConnection*);
+char* (*dbus_connection_get_server_id_dylibloader_wrapper_dbus)( DBusConnection*);
+dbus_bool_t (*dbus_connection_can_send_type_dylibloader_wrapper_dbus)( DBusConnection*, int);
+void (*dbus_connection_set_exit_on_disconnect_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t);
+void (*dbus_connection_flush_dylibloader_wrapper_dbus)( DBusConnection*);
+dbus_bool_t (*dbus_connection_read_write_dispatch_dylibloader_wrapper_dbus)( DBusConnection*, int);
+dbus_bool_t (*dbus_connection_read_write_dylibloader_wrapper_dbus)( DBusConnection*, int);
+DBusMessage* (*dbus_connection_borrow_message_dylibloader_wrapper_dbus)( DBusConnection*);
+void (*dbus_connection_return_message_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*);
+void (*dbus_connection_steal_borrowed_message_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*);
+DBusMessage* (*dbus_connection_pop_message_dylibloader_wrapper_dbus)( DBusConnection*);
+DBusDispatchStatus (*dbus_connection_get_dispatch_status_dylibloader_wrapper_dbus)( DBusConnection*);
+DBusDispatchStatus (*dbus_connection_dispatch_dylibloader_wrapper_dbus)( DBusConnection*);
+dbus_bool_t (*dbus_connection_has_messages_to_send_dylibloader_wrapper_dbus)( DBusConnection*);
+dbus_bool_t (*dbus_connection_send_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, dbus_uint32_t*);
+dbus_bool_t (*dbus_connection_send_with_reply_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, DBusPendingCall**, int);
+DBusMessage* (*dbus_connection_send_with_reply_and_block_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, int, DBusError*);
+dbus_bool_t (*dbus_connection_set_watch_functions_dylibloader_wrapper_dbus)( DBusConnection*, DBusAddWatchFunction, DBusRemoveWatchFunction, DBusWatchToggledFunction, void*, DBusFreeFunction);
+dbus_bool_t (*dbus_connection_set_timeout_functions_dylibloader_wrapper_dbus)( DBusConnection*, DBusAddTimeoutFunction, DBusRemoveTimeoutFunction, DBusTimeoutToggledFunction, void*, DBusFreeFunction);
+void (*dbus_connection_set_wakeup_main_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusWakeupMainFunction, void*, DBusFreeFunction);
+void (*dbus_connection_set_dispatch_status_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusDispatchStatusFunction, void*, DBusFreeFunction);
+dbus_bool_t (*dbus_connection_get_unix_user_dylibloader_wrapper_dbus)( DBusConnection*, unsigned long*);
+dbus_bool_t (*dbus_connection_get_unix_process_id_dylibloader_wrapper_dbus)( DBusConnection*, unsigned long*);
+dbus_bool_t (*dbus_connection_get_adt_audit_session_data_dylibloader_wrapper_dbus)( DBusConnection*, void**, dbus_int32_t*);
+void (*dbus_connection_set_unix_user_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusAllowUnixUserFunction, void*, DBusFreeFunction);
+dbus_bool_t (*dbus_connection_get_windows_user_dylibloader_wrapper_dbus)( DBusConnection*, char**);
+void (*dbus_connection_set_windows_user_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusAllowWindowsUserFunction, void*, DBusFreeFunction);
+void (*dbus_connection_set_allow_anonymous_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t);
+void (*dbus_connection_set_route_peer_messages_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t);
+dbus_bool_t (*dbus_connection_add_filter_dylibloader_wrapper_dbus)( DBusConnection*, DBusHandleMessageFunction, void*, DBusFreeFunction);
+void (*dbus_connection_remove_filter_dylibloader_wrapper_dbus)( DBusConnection*, DBusHandleMessageFunction, void*);
+dbus_bool_t (*dbus_connection_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+void (*dbus_connection_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+dbus_bool_t (*dbus_connection_set_data_dylibloader_wrapper_dbus)( DBusConnection*, dbus_int32_t, void*, DBusFreeFunction);
+void* (*dbus_connection_get_data_dylibloader_wrapper_dbus)( DBusConnection*, dbus_int32_t);
+void (*dbus_connection_set_change_sigpipe_dylibloader_wrapper_dbus)( dbus_bool_t);
+void (*dbus_connection_set_max_message_size_dylibloader_wrapper_dbus)( DBusConnection*, long);
+long (*dbus_connection_get_max_message_size_dylibloader_wrapper_dbus)( DBusConnection*);
+void (*dbus_connection_set_max_received_size_dylibloader_wrapper_dbus)( DBusConnection*, long);
+long (*dbus_connection_get_max_received_size_dylibloader_wrapper_dbus)( DBusConnection*);
+void (*dbus_connection_set_max_message_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*, long);
+long (*dbus_connection_get_max_message_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*);
+void (*dbus_connection_set_max_received_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*, long);
+long (*dbus_connection_get_max_received_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*);
+long (*dbus_connection_get_outgoing_size_dylibloader_wrapper_dbus)( DBusConnection*);
+long (*dbus_connection_get_outgoing_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*);
+DBusPreallocatedSend* (*dbus_connection_preallocate_send_dylibloader_wrapper_dbus)( DBusConnection*);
+void (*dbus_connection_free_preallocated_send_dylibloader_wrapper_dbus)( DBusConnection*, DBusPreallocatedSend*);
+void (*dbus_connection_send_preallocated_dylibloader_wrapper_dbus)( DBusConnection*, DBusPreallocatedSend*, DBusMessage*, dbus_uint32_t*);
+dbus_bool_t (*dbus_connection_try_register_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*, DBusError*);
+dbus_bool_t (*dbus_connection_register_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*);
+dbus_bool_t (*dbus_connection_try_register_fallback_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*, DBusError*);
+dbus_bool_t (*dbus_connection_register_fallback_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*);
+dbus_bool_t (*dbus_connection_unregister_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*);
+dbus_bool_t (*dbus_connection_get_object_path_data_dylibloader_wrapper_dbus)( DBusConnection*,const char*, void**);
+dbus_bool_t (*dbus_connection_list_registered_dylibloader_wrapper_dbus)( DBusConnection*,const char*, char***);
+dbus_bool_t (*dbus_connection_get_unix_fd_dylibloader_wrapper_dbus)( DBusConnection*, int*);
+dbus_bool_t (*dbus_connection_get_socket_dylibloader_wrapper_dbus)( DBusConnection*, int*);
+int (*dbus_watch_get_fd_dylibloader_wrapper_dbus)( DBusWatch*);
+int (*dbus_watch_get_unix_fd_dylibloader_wrapper_dbus)( DBusWatch*);
+int (*dbus_watch_get_socket_dylibloader_wrapper_dbus)( DBusWatch*);
+unsigned int (*dbus_watch_get_flags_dylibloader_wrapper_dbus)( DBusWatch*);
+void* (*dbus_watch_get_data_dylibloader_wrapper_dbus)( DBusWatch*);
+void (*dbus_watch_set_data_dylibloader_wrapper_dbus)( DBusWatch*, void*, DBusFreeFunction);
+dbus_bool_t (*dbus_watch_handle_dylibloader_wrapper_dbus)( DBusWatch*, unsigned int);
+dbus_bool_t (*dbus_watch_get_enabled_dylibloader_wrapper_dbus)( DBusWatch*);
+int (*dbus_timeout_get_interval_dylibloader_wrapper_dbus)( DBusTimeout*);
+void* (*dbus_timeout_get_data_dylibloader_wrapper_dbus)( DBusTimeout*);
+void (*dbus_timeout_set_data_dylibloader_wrapper_dbus)( DBusTimeout*, void*, DBusFreeFunction);
+dbus_bool_t (*dbus_timeout_handle_dylibloader_wrapper_dbus)( DBusTimeout*);
+dbus_bool_t (*dbus_timeout_get_enabled_dylibloader_wrapper_dbus)( DBusTimeout*);
+DBusConnection* (*dbus_bus_get_dylibloader_wrapper_dbus)( DBusBusType, DBusError*);
+DBusConnection* (*dbus_bus_get_private_dylibloader_wrapper_dbus)( DBusBusType, DBusError*);
+dbus_bool_t (*dbus_bus_register_dylibloader_wrapper_dbus)( DBusConnection*, DBusError*);
+dbus_bool_t (*dbus_bus_set_unique_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*);
+const char* (*dbus_bus_get_unique_name_dylibloader_wrapper_dbus)( DBusConnection*);
+unsigned long (*dbus_bus_get_unix_user_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+char* (*dbus_bus_get_id_dylibloader_wrapper_dbus)( DBusConnection*, DBusError*);
+int (*dbus_bus_request_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, unsigned int, DBusError*);
+int (*dbus_bus_release_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+dbus_bool_t (*dbus_bus_name_has_owner_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+dbus_bool_t (*dbus_bus_start_service_by_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, dbus_uint32_t, dbus_uint32_t*, DBusError*);
+void (*dbus_bus_add_match_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+void (*dbus_bus_remove_match_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+char* (*dbus_get_local_machine_id_dylibloader_wrapper_dbus)( void);
+void (*dbus_get_version_dylibloader_wrapper_dbus)( int*, int*, int*);
+dbus_bool_t (*dbus_setenv_dylibloader_wrapper_dbus)(const char*,const char*);
+char* (*dbus_try_get_local_machine_id_dylibloader_wrapper_dbus)( DBusError*);
+DBusPendingCall* (*dbus_pending_call_ref_dylibloader_wrapper_dbus)( DBusPendingCall*);
+void (*dbus_pending_call_unref_dylibloader_wrapper_dbus)( DBusPendingCall*);
+dbus_bool_t (*dbus_pending_call_set_notify_dylibloader_wrapper_dbus)( DBusPendingCall*, DBusPendingCallNotifyFunction, void*, DBusFreeFunction);
+void (*dbus_pending_call_cancel_dylibloader_wrapper_dbus)( DBusPendingCall*);
+dbus_bool_t (*dbus_pending_call_get_completed_dylibloader_wrapper_dbus)( DBusPendingCall*);
+DBusMessage* (*dbus_pending_call_steal_reply_dylibloader_wrapper_dbus)( DBusPendingCall*);
+void (*dbus_pending_call_block_dylibloader_wrapper_dbus)( DBusPendingCall*);
+dbus_bool_t (*dbus_pending_call_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+void (*dbus_pending_call_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+dbus_bool_t (*dbus_pending_call_set_data_dylibloader_wrapper_dbus)( DBusPendingCall*, dbus_int32_t, void*, DBusFreeFunction);
+void* (*dbus_pending_call_get_data_dylibloader_wrapper_dbus)( DBusPendingCall*, dbus_int32_t);
+DBusServer* (*dbus_server_listen_dylibloader_wrapper_dbus)(const char*, DBusError*);
+DBusServer* (*dbus_server_ref_dylibloader_wrapper_dbus)( DBusServer*);
+void (*dbus_server_unref_dylibloader_wrapper_dbus)( DBusServer*);
+void (*dbus_server_disconnect_dylibloader_wrapper_dbus)( DBusServer*);
+dbus_bool_t (*dbus_server_get_is_connected_dylibloader_wrapper_dbus)( DBusServer*);
+char* (*dbus_server_get_address_dylibloader_wrapper_dbus)( DBusServer*);
+char* (*dbus_server_get_id_dylibloader_wrapper_dbus)( DBusServer*);
+void (*dbus_server_set_new_connection_function_dylibloader_wrapper_dbus)( DBusServer*, DBusNewConnectionFunction, void*, DBusFreeFunction);
+dbus_bool_t (*dbus_server_set_watch_functions_dylibloader_wrapper_dbus)( DBusServer*, DBusAddWatchFunction, DBusRemoveWatchFunction, DBusWatchToggledFunction, void*, DBusFreeFunction);
+dbus_bool_t (*dbus_server_set_timeout_functions_dylibloader_wrapper_dbus)( DBusServer*, DBusAddTimeoutFunction, DBusRemoveTimeoutFunction, DBusTimeoutToggledFunction, void*, DBusFreeFunction);
+dbus_bool_t (*dbus_server_set_auth_mechanisms_dylibloader_wrapper_dbus)( DBusServer*,const char**);
+dbus_bool_t (*dbus_server_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+void (*dbus_server_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+dbus_bool_t (*dbus_server_set_data_dylibloader_wrapper_dbus)( DBusServer*, int, void*, DBusFreeFunction);
+void* (*dbus_server_get_data_dylibloader_wrapper_dbus)( DBusServer*, int);
+void (*dbus_signature_iter_init_dylibloader_wrapper_dbus)( DBusSignatureIter*,const char*);
+int (*dbus_signature_iter_get_current_type_dylibloader_wrapper_dbus)(const DBusSignatureIter*);
+char* (*dbus_signature_iter_get_signature_dylibloader_wrapper_dbus)(const DBusSignatureIter*);
+int (*dbus_signature_iter_get_element_type_dylibloader_wrapper_dbus)(const DBusSignatureIter*);
+dbus_bool_t (*dbus_signature_iter_next_dylibloader_wrapper_dbus)( DBusSignatureIter*);
+void (*dbus_signature_iter_recurse_dylibloader_wrapper_dbus)(const DBusSignatureIter*, DBusSignatureIter*);
+dbus_bool_t (*dbus_signature_validate_dylibloader_wrapper_dbus)(const char*, DBusError*);
+dbus_bool_t (*dbus_signature_validate_single_dylibloader_wrapper_dbus)(const char*, DBusError*);
+dbus_bool_t (*dbus_type_is_valid_dylibloader_wrapper_dbus)( int);
+dbus_bool_t (*dbus_type_is_basic_dylibloader_wrapper_dbus)( int);
+dbus_bool_t (*dbus_type_is_container_dylibloader_wrapper_dbus)( int);
+dbus_bool_t (*dbus_type_is_fixed_dylibloader_wrapper_dbus)( int);
+dbus_bool_t (*dbus_validate_path_dylibloader_wrapper_dbus)(const char*, DBusError*);
+dbus_bool_t (*dbus_validate_interface_dylibloader_wrapper_dbus)(const char*, DBusError*);
+dbus_bool_t (*dbus_validate_member_dylibloader_wrapper_dbus)(const char*, DBusError*);
+dbus_bool_t (*dbus_validate_error_name_dylibloader_wrapper_dbus)(const char*, DBusError*);
+dbus_bool_t (*dbus_validate_bus_name_dylibloader_wrapper_dbus)(const char*, DBusError*);
+dbus_bool_t (*dbus_validate_utf8_dylibloader_wrapper_dbus)(const char*, DBusError*);
+dbus_bool_t (*dbus_threads_init_dylibloader_wrapper_dbus)(const DBusThreadFunctions*);
+dbus_bool_t (*dbus_threads_init_default_dylibloader_wrapper_dbus)( void);
+int initialize_dbus(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libdbus-1.so", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// dbus_error_init
+ *(void **) (&dbus_error_init_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_error_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_error_free
+ *(void **) (&dbus_error_free_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_error_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_set_error
+ *(void **) (&dbus_set_error_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_set_error");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_set_error_const
+ *(void **) (&dbus_set_error_const_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_set_error_const");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_move_error
+ *(void **) (&dbus_move_error_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_move_error");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_error_has_name
+ *(void **) (&dbus_error_has_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_error_has_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_error_is_set
+ *(void **) (&dbus_error_is_set_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_error_is_set");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_parse_address
+ *(void **) (&dbus_parse_address_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_parse_address");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_address_entry_get_value
+ *(void **) (&dbus_address_entry_get_value_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_entry_get_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_address_entry_get_method
+ *(void **) (&dbus_address_entry_get_method_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_entry_get_method");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_address_entries_free
+ *(void **) (&dbus_address_entries_free_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_entries_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_address_escape_value
+ *(void **) (&dbus_address_escape_value_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_escape_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_address_unescape_value
+ *(void **) (&dbus_address_unescape_value_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_address_unescape_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_malloc
+ *(void **) (&dbus_malloc_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_malloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_malloc0
+ *(void **) (&dbus_malloc0_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_malloc0");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_realloc
+ *(void **) (&dbus_realloc_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_realloc");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_free
+ *(void **) (&dbus_free_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_free");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_free_string_array
+ *(void **) (&dbus_free_string_array_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_free_string_array");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_shutdown
+ *(void **) (&dbus_shutdown_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_shutdown");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_new
+ *(void **) (&dbus_message_new_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_new_method_call
+ *(void **) (&dbus_message_new_method_call_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_method_call");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_new_method_return
+ *(void **) (&dbus_message_new_method_return_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_method_return");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_new_signal
+ *(void **) (&dbus_message_new_signal_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_signal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_new_error
+ *(void **) (&dbus_message_new_error_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_error");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_new_error_printf
+ *(void **) (&dbus_message_new_error_printf_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_new_error_printf");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_copy
+ *(void **) (&dbus_message_copy_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_copy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_ref
+ *(void **) (&dbus_message_ref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_unref
+ *(void **) (&dbus_message_unref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_type
+ *(void **) (&dbus_message_get_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_path
+ *(void **) (&dbus_message_set_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_path");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_path
+ *(void **) (&dbus_message_get_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_path");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_has_path
+ *(void **) (&dbus_message_has_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_path");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_interface
+ *(void **) (&dbus_message_set_interface_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_interface
+ *(void **) (&dbus_message_get_interface_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_has_interface
+ *(void **) (&dbus_message_has_interface_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_member
+ *(void **) (&dbus_message_set_member_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_member");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_member
+ *(void **) (&dbus_message_get_member_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_member");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_has_member
+ *(void **) (&dbus_message_has_member_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_member");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_error_name
+ *(void **) (&dbus_message_set_error_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_error_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_error_name
+ *(void **) (&dbus_message_get_error_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_error_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_destination
+ *(void **) (&dbus_message_set_destination_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_destination");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_destination
+ *(void **) (&dbus_message_get_destination_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_destination");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_sender
+ *(void **) (&dbus_message_set_sender_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_sender");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_sender
+ *(void **) (&dbus_message_get_sender_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_sender");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_signature
+ *(void **) (&dbus_message_get_signature_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_signature");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_no_reply
+ *(void **) (&dbus_message_set_no_reply_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_no_reply");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_no_reply
+ *(void **) (&dbus_message_get_no_reply_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_no_reply");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_is_method_call
+ *(void **) (&dbus_message_is_method_call_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_is_method_call");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_is_signal
+ *(void **) (&dbus_message_is_signal_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_is_signal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_is_error
+ *(void **) (&dbus_message_is_error_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_is_error");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_has_destination
+ *(void **) (&dbus_message_has_destination_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_destination");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_has_sender
+ *(void **) (&dbus_message_has_sender_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_sender");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_has_signature
+ *(void **) (&dbus_message_has_signature_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_has_signature");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_serial
+ *(void **) (&dbus_message_get_serial_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_serial");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_serial
+ *(void **) (&dbus_message_set_serial_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_serial");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_reply_serial
+ *(void **) (&dbus_message_set_reply_serial_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_reply_serial");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_reply_serial
+ *(void **) (&dbus_message_get_reply_serial_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_reply_serial");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_auto_start
+ *(void **) (&dbus_message_set_auto_start_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_auto_start");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_auto_start
+ *(void **) (&dbus_message_get_auto_start_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_auto_start");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_path_decomposed
+ *(void **) (&dbus_message_get_path_decomposed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_path_decomposed");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_append_args
+ *(void **) (&dbus_message_append_args_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_append_args");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_append_args_valist
+ *(void **) (&dbus_message_append_args_valist_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_append_args_valist");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_args
+ *(void **) (&dbus_message_get_args_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_args");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_args_valist
+ *(void **) (&dbus_message_get_args_valist_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_args_valist");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_contains_unix_fds
+ *(void **) (&dbus_message_contains_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_contains_unix_fds");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_init_closed
+ *(void **) (&dbus_message_iter_init_closed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_init_closed");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_init
+ *(void **) (&dbus_message_iter_init_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_has_next
+ *(void **) (&dbus_message_iter_has_next_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_has_next");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_next
+ *(void **) (&dbus_message_iter_next_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_next");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_get_signature
+ *(void **) (&dbus_message_iter_get_signature_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_signature");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_get_arg_type
+ *(void **) (&dbus_message_iter_get_arg_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_arg_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_get_element_type
+ *(void **) (&dbus_message_iter_get_element_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_element_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_recurse
+ *(void **) (&dbus_message_iter_recurse_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_recurse");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_get_basic
+ *(void **) (&dbus_message_iter_get_basic_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_basic");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_get_element_count
+ *(void **) (&dbus_message_iter_get_element_count_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_element_count");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_get_array_len
+ *(void **) (&dbus_message_iter_get_array_len_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_array_len");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_get_fixed_array
+ *(void **) (&dbus_message_iter_get_fixed_array_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_get_fixed_array");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_init_append
+ *(void **) (&dbus_message_iter_init_append_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_init_append");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_append_basic
+ *(void **) (&dbus_message_iter_append_basic_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_append_basic");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_append_fixed_array
+ *(void **) (&dbus_message_iter_append_fixed_array_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_append_fixed_array");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_open_container
+ *(void **) (&dbus_message_iter_open_container_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_open_container");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_close_container
+ *(void **) (&dbus_message_iter_close_container_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_close_container");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_abandon_container
+ *(void **) (&dbus_message_iter_abandon_container_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_abandon_container");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_iter_abandon_container_if_open
+ *(void **) (&dbus_message_iter_abandon_container_if_open_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_iter_abandon_container_if_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_lock
+ *(void **) (&dbus_message_lock_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_lock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_set_error_from_message
+ *(void **) (&dbus_set_error_from_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_set_error_from_message");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_allocate_data_slot
+ *(void **) (&dbus_message_allocate_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_allocate_data_slot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_free_data_slot
+ *(void **) (&dbus_message_free_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_free_data_slot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_data
+ *(void **) (&dbus_message_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_data
+ *(void **) (&dbus_message_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_type_from_string
+ *(void **) (&dbus_message_type_from_string_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_type_from_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_type_to_string
+ *(void **) (&dbus_message_type_to_string_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_type_to_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_marshal
+ *(void **) (&dbus_message_marshal_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_marshal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_demarshal
+ *(void **) (&dbus_message_demarshal_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_demarshal");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_demarshal_bytes_needed
+ *(void **) (&dbus_message_demarshal_bytes_needed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_demarshal_bytes_needed");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_set_allow_interactive_authorization
+ *(void **) (&dbus_message_set_allow_interactive_authorization_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_set_allow_interactive_authorization");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_message_get_allow_interactive_authorization
+ *(void **) (&dbus_message_get_allow_interactive_authorization_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_message_get_allow_interactive_authorization");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_open
+ *(void **) (&dbus_connection_open_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_open");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_open_private
+ *(void **) (&dbus_connection_open_private_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_open_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_ref
+ *(void **) (&dbus_connection_ref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_unref
+ *(void **) (&dbus_connection_unref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_close
+ *(void **) (&dbus_connection_close_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_close");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_is_connected
+ *(void **) (&dbus_connection_get_is_connected_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_is_connected");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_is_authenticated
+ *(void **) (&dbus_connection_get_is_authenticated_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_is_authenticated");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_is_anonymous
+ *(void **) (&dbus_connection_get_is_anonymous_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_is_anonymous");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_server_id
+ *(void **) (&dbus_connection_get_server_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_server_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_can_send_type
+ *(void **) (&dbus_connection_can_send_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_can_send_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_exit_on_disconnect
+ *(void **) (&dbus_connection_set_exit_on_disconnect_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_exit_on_disconnect");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_flush
+ *(void **) (&dbus_connection_flush_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_flush");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_read_write_dispatch
+ *(void **) (&dbus_connection_read_write_dispatch_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_read_write_dispatch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_read_write
+ *(void **) (&dbus_connection_read_write_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_read_write");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_borrow_message
+ *(void **) (&dbus_connection_borrow_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_borrow_message");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_return_message
+ *(void **) (&dbus_connection_return_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_return_message");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_steal_borrowed_message
+ *(void **) (&dbus_connection_steal_borrowed_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_steal_borrowed_message");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_pop_message
+ *(void **) (&dbus_connection_pop_message_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_pop_message");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_dispatch_status
+ *(void **) (&dbus_connection_get_dispatch_status_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_dispatch_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_dispatch
+ *(void **) (&dbus_connection_dispatch_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_dispatch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_has_messages_to_send
+ *(void **) (&dbus_connection_has_messages_to_send_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_has_messages_to_send");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_send
+ *(void **) (&dbus_connection_send_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_send");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_send_with_reply
+ *(void **) (&dbus_connection_send_with_reply_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_send_with_reply");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_send_with_reply_and_block
+ *(void **) (&dbus_connection_send_with_reply_and_block_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_send_with_reply_and_block");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_watch_functions
+ *(void **) (&dbus_connection_set_watch_functions_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_watch_functions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_timeout_functions
+ *(void **) (&dbus_connection_set_timeout_functions_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_timeout_functions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_wakeup_main_function
+ *(void **) (&dbus_connection_set_wakeup_main_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_wakeup_main_function");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_dispatch_status_function
+ *(void **) (&dbus_connection_set_dispatch_status_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_dispatch_status_function");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_unix_user
+ *(void **) (&dbus_connection_get_unix_user_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_unix_user");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_unix_process_id
+ *(void **) (&dbus_connection_get_unix_process_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_unix_process_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_adt_audit_session_data
+ *(void **) (&dbus_connection_get_adt_audit_session_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_adt_audit_session_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_unix_user_function
+ *(void **) (&dbus_connection_set_unix_user_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_unix_user_function");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_windows_user
+ *(void **) (&dbus_connection_get_windows_user_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_windows_user");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_windows_user_function
+ *(void **) (&dbus_connection_set_windows_user_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_windows_user_function");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_allow_anonymous
+ *(void **) (&dbus_connection_set_allow_anonymous_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_allow_anonymous");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_route_peer_messages
+ *(void **) (&dbus_connection_set_route_peer_messages_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_route_peer_messages");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_add_filter
+ *(void **) (&dbus_connection_add_filter_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_add_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_remove_filter
+ *(void **) (&dbus_connection_remove_filter_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_remove_filter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_allocate_data_slot
+ *(void **) (&dbus_connection_allocate_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_allocate_data_slot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_free_data_slot
+ *(void **) (&dbus_connection_free_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_free_data_slot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_data
+ *(void **) (&dbus_connection_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_data
+ *(void **) (&dbus_connection_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_change_sigpipe
+ *(void **) (&dbus_connection_set_change_sigpipe_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_change_sigpipe");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_max_message_size
+ *(void **) (&dbus_connection_set_max_message_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_max_message_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_max_message_size
+ *(void **) (&dbus_connection_get_max_message_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_max_message_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_max_received_size
+ *(void **) (&dbus_connection_set_max_received_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_max_received_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_max_received_size
+ *(void **) (&dbus_connection_get_max_received_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_max_received_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_max_message_unix_fds
+ *(void **) (&dbus_connection_set_max_message_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_max_message_unix_fds");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_max_message_unix_fds
+ *(void **) (&dbus_connection_get_max_message_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_max_message_unix_fds");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_set_max_received_unix_fds
+ *(void **) (&dbus_connection_set_max_received_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_set_max_received_unix_fds");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_max_received_unix_fds
+ *(void **) (&dbus_connection_get_max_received_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_max_received_unix_fds");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_outgoing_size
+ *(void **) (&dbus_connection_get_outgoing_size_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_outgoing_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_outgoing_unix_fds
+ *(void **) (&dbus_connection_get_outgoing_unix_fds_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_outgoing_unix_fds");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_preallocate_send
+ *(void **) (&dbus_connection_preallocate_send_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_preallocate_send");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_free_preallocated_send
+ *(void **) (&dbus_connection_free_preallocated_send_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_free_preallocated_send");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_send_preallocated
+ *(void **) (&dbus_connection_send_preallocated_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_send_preallocated");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_try_register_object_path
+ *(void **) (&dbus_connection_try_register_object_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_try_register_object_path");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_register_object_path
+ *(void **) (&dbus_connection_register_object_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_register_object_path");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_try_register_fallback
+ *(void **) (&dbus_connection_try_register_fallback_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_try_register_fallback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_register_fallback
+ *(void **) (&dbus_connection_register_fallback_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_register_fallback");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_unregister_object_path
+ *(void **) (&dbus_connection_unregister_object_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_unregister_object_path");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_object_path_data
+ *(void **) (&dbus_connection_get_object_path_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_object_path_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_list_registered
+ *(void **) (&dbus_connection_list_registered_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_list_registered");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_unix_fd
+ *(void **) (&dbus_connection_get_unix_fd_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_unix_fd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_connection_get_socket
+ *(void **) (&dbus_connection_get_socket_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_connection_get_socket");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_watch_get_fd
+ *(void **) (&dbus_watch_get_fd_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_fd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_watch_get_unix_fd
+ *(void **) (&dbus_watch_get_unix_fd_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_unix_fd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_watch_get_socket
+ *(void **) (&dbus_watch_get_socket_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_socket");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_watch_get_flags
+ *(void **) (&dbus_watch_get_flags_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_flags");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_watch_get_data
+ *(void **) (&dbus_watch_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_watch_set_data
+ *(void **) (&dbus_watch_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_set_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_watch_handle
+ *(void **) (&dbus_watch_handle_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_handle");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_watch_get_enabled
+ *(void **) (&dbus_watch_get_enabled_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_watch_get_enabled");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_timeout_get_interval
+ *(void **) (&dbus_timeout_get_interval_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_get_interval");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_timeout_get_data
+ *(void **) (&dbus_timeout_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_get_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_timeout_set_data
+ *(void **) (&dbus_timeout_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_set_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_timeout_handle
+ *(void **) (&dbus_timeout_handle_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_handle");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_timeout_get_enabled
+ *(void **) (&dbus_timeout_get_enabled_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_timeout_get_enabled");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_get
+ *(void **) (&dbus_bus_get_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_get_private
+ *(void **) (&dbus_bus_get_private_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get_private");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_register
+ *(void **) (&dbus_bus_register_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_register");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_set_unique_name
+ *(void **) (&dbus_bus_set_unique_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_set_unique_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_get_unique_name
+ *(void **) (&dbus_bus_get_unique_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get_unique_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_get_unix_user
+ *(void **) (&dbus_bus_get_unix_user_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get_unix_user");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_get_id
+ *(void **) (&dbus_bus_get_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_request_name
+ *(void **) (&dbus_bus_request_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_request_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_release_name
+ *(void **) (&dbus_bus_release_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_release_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_name_has_owner
+ *(void **) (&dbus_bus_name_has_owner_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_name_has_owner");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_start_service_by_name
+ *(void **) (&dbus_bus_start_service_by_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_start_service_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_add_match
+ *(void **) (&dbus_bus_add_match_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_add_match");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_bus_remove_match
+ *(void **) (&dbus_bus_remove_match_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_bus_remove_match");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_get_local_machine_id
+ *(void **) (&dbus_get_local_machine_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_get_local_machine_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_get_version
+ *(void **) (&dbus_get_version_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_get_version");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_setenv
+ *(void **) (&dbus_setenv_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_setenv");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_try_get_local_machine_id
+ *(void **) (&dbus_try_get_local_machine_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_try_get_local_machine_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_ref
+ *(void **) (&dbus_pending_call_ref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_unref
+ *(void **) (&dbus_pending_call_unref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_set_notify
+ *(void **) (&dbus_pending_call_set_notify_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_set_notify");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_cancel
+ *(void **) (&dbus_pending_call_cancel_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_cancel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_get_completed
+ *(void **) (&dbus_pending_call_get_completed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_get_completed");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_steal_reply
+ *(void **) (&dbus_pending_call_steal_reply_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_steal_reply");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_block
+ *(void **) (&dbus_pending_call_block_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_block");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_allocate_data_slot
+ *(void **) (&dbus_pending_call_allocate_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_allocate_data_slot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_free_data_slot
+ *(void **) (&dbus_pending_call_free_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_free_data_slot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_set_data
+ *(void **) (&dbus_pending_call_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_set_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_pending_call_get_data
+ *(void **) (&dbus_pending_call_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_pending_call_get_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_listen
+ *(void **) (&dbus_server_listen_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_listen");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_ref
+ *(void **) (&dbus_server_ref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_unref
+ *(void **) (&dbus_server_unref_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_disconnect
+ *(void **) (&dbus_server_disconnect_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_disconnect");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_get_is_connected
+ *(void **) (&dbus_server_get_is_connected_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_get_is_connected");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_get_address
+ *(void **) (&dbus_server_get_address_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_get_address");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_get_id
+ *(void **) (&dbus_server_get_id_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_get_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_set_new_connection_function
+ *(void **) (&dbus_server_set_new_connection_function_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_new_connection_function");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_set_watch_functions
+ *(void **) (&dbus_server_set_watch_functions_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_watch_functions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_set_timeout_functions
+ *(void **) (&dbus_server_set_timeout_functions_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_timeout_functions");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_set_auth_mechanisms
+ *(void **) (&dbus_server_set_auth_mechanisms_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_auth_mechanisms");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_allocate_data_slot
+ *(void **) (&dbus_server_allocate_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_allocate_data_slot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_free_data_slot
+ *(void **) (&dbus_server_free_data_slot_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_free_data_slot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_set_data
+ *(void **) (&dbus_server_set_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_set_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_server_get_data
+ *(void **) (&dbus_server_get_data_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_server_get_data");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_signature_iter_init
+ *(void **) (&dbus_signature_iter_init_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_signature_iter_get_current_type
+ *(void **) (&dbus_signature_iter_get_current_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_get_current_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_signature_iter_get_signature
+ *(void **) (&dbus_signature_iter_get_signature_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_get_signature");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_signature_iter_get_element_type
+ *(void **) (&dbus_signature_iter_get_element_type_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_get_element_type");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_signature_iter_next
+ *(void **) (&dbus_signature_iter_next_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_next");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_signature_iter_recurse
+ *(void **) (&dbus_signature_iter_recurse_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_iter_recurse");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_signature_validate
+ *(void **) (&dbus_signature_validate_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_validate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_signature_validate_single
+ *(void **) (&dbus_signature_validate_single_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_signature_validate_single");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_type_is_valid
+ *(void **) (&dbus_type_is_valid_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_type_is_valid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_type_is_basic
+ *(void **) (&dbus_type_is_basic_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_type_is_basic");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_type_is_container
+ *(void **) (&dbus_type_is_container_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_type_is_container");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_type_is_fixed
+ *(void **) (&dbus_type_is_fixed_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_type_is_fixed");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_validate_path
+ *(void **) (&dbus_validate_path_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_path");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_validate_interface
+ *(void **) (&dbus_validate_interface_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_interface");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_validate_member
+ *(void **) (&dbus_validate_member_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_member");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_validate_error_name
+ *(void **) (&dbus_validate_error_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_error_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_validate_bus_name
+ *(void **) (&dbus_validate_bus_name_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_bus_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_validate_utf8
+ *(void **) (&dbus_validate_utf8_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_validate_utf8");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_threads_init
+ *(void **) (&dbus_threads_init_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_threads_init");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// dbus_threads_init_default
+ *(void **) (&dbus_threads_init_default_dylibloader_wrapper_dbus) = dlsym(handle, "dbus_threads_init_default");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/dbus-so_wrap.h b/platform/linuxbsd/dbus-so_wrap.h
new file mode 100644
index 0000000000..52e1dd300c
--- /dev/null
+++ b/platform/linuxbsd/dbus-so_wrap.h
@@ -0,0 +1,970 @@
+#ifndef DYLIBLOAD_WRAPPER_DBUS
+#define DYLIBLOAD_WRAPPER_DBUS
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by ./generate-wrapper.py 0.3 on 2022-07-29 07:23:21
+// flags: ./generate-wrapper.py --include /usr/include/dbus-1.0/dbus/dbus.h --sys-include <dbus/dbus.h> --soname libdbus-1.so --init-name dbus --output-header dbus-so_wrap.h --output-implementation dbus-so_wrap.c
+//
+#include <stdint.h>
+
+#define dbus_error_init dbus_error_init_dylibloader_orig_dbus
+#define dbus_error_free dbus_error_free_dylibloader_orig_dbus
+#define dbus_set_error dbus_set_error_dylibloader_orig_dbus
+#define dbus_set_error_const dbus_set_error_const_dylibloader_orig_dbus
+#define dbus_move_error dbus_move_error_dylibloader_orig_dbus
+#define dbus_error_has_name dbus_error_has_name_dylibloader_orig_dbus
+#define dbus_error_is_set dbus_error_is_set_dylibloader_orig_dbus
+#define dbus_parse_address dbus_parse_address_dylibloader_orig_dbus
+#define dbus_address_entry_get_value dbus_address_entry_get_value_dylibloader_orig_dbus
+#define dbus_address_entry_get_method dbus_address_entry_get_method_dylibloader_orig_dbus
+#define dbus_address_entries_free dbus_address_entries_free_dylibloader_orig_dbus
+#define dbus_address_escape_value dbus_address_escape_value_dylibloader_orig_dbus
+#define dbus_address_unescape_value dbus_address_unescape_value_dylibloader_orig_dbus
+#define dbus_malloc dbus_malloc_dylibloader_orig_dbus
+#define dbus_malloc0 dbus_malloc0_dylibloader_orig_dbus
+#define dbus_realloc dbus_realloc_dylibloader_orig_dbus
+#define dbus_free dbus_free_dylibloader_orig_dbus
+#define dbus_free_string_array dbus_free_string_array_dylibloader_orig_dbus
+#define dbus_shutdown dbus_shutdown_dylibloader_orig_dbus
+#define dbus_message_new dbus_message_new_dylibloader_orig_dbus
+#define dbus_message_new_method_call dbus_message_new_method_call_dylibloader_orig_dbus
+#define dbus_message_new_method_return dbus_message_new_method_return_dylibloader_orig_dbus
+#define dbus_message_new_signal dbus_message_new_signal_dylibloader_orig_dbus
+#define dbus_message_new_error dbus_message_new_error_dylibloader_orig_dbus
+#define dbus_message_new_error_printf dbus_message_new_error_printf_dylibloader_orig_dbus
+#define dbus_message_copy dbus_message_copy_dylibloader_orig_dbus
+#define dbus_message_ref dbus_message_ref_dylibloader_orig_dbus
+#define dbus_message_unref dbus_message_unref_dylibloader_orig_dbus
+#define dbus_message_get_type dbus_message_get_type_dylibloader_orig_dbus
+#define dbus_message_set_path dbus_message_set_path_dylibloader_orig_dbus
+#define dbus_message_get_path dbus_message_get_path_dylibloader_orig_dbus
+#define dbus_message_has_path dbus_message_has_path_dylibloader_orig_dbus
+#define dbus_message_set_interface dbus_message_set_interface_dylibloader_orig_dbus
+#define dbus_message_get_interface dbus_message_get_interface_dylibloader_orig_dbus
+#define dbus_message_has_interface dbus_message_has_interface_dylibloader_orig_dbus
+#define dbus_message_set_member dbus_message_set_member_dylibloader_orig_dbus
+#define dbus_message_get_member dbus_message_get_member_dylibloader_orig_dbus
+#define dbus_message_has_member dbus_message_has_member_dylibloader_orig_dbus
+#define dbus_message_set_error_name dbus_message_set_error_name_dylibloader_orig_dbus
+#define dbus_message_get_error_name dbus_message_get_error_name_dylibloader_orig_dbus
+#define dbus_message_set_destination dbus_message_set_destination_dylibloader_orig_dbus
+#define dbus_message_get_destination dbus_message_get_destination_dylibloader_orig_dbus
+#define dbus_message_set_sender dbus_message_set_sender_dylibloader_orig_dbus
+#define dbus_message_get_sender dbus_message_get_sender_dylibloader_orig_dbus
+#define dbus_message_get_signature dbus_message_get_signature_dylibloader_orig_dbus
+#define dbus_message_set_no_reply dbus_message_set_no_reply_dylibloader_orig_dbus
+#define dbus_message_get_no_reply dbus_message_get_no_reply_dylibloader_orig_dbus
+#define dbus_message_is_method_call dbus_message_is_method_call_dylibloader_orig_dbus
+#define dbus_message_is_signal dbus_message_is_signal_dylibloader_orig_dbus
+#define dbus_message_is_error dbus_message_is_error_dylibloader_orig_dbus
+#define dbus_message_has_destination dbus_message_has_destination_dylibloader_orig_dbus
+#define dbus_message_has_sender dbus_message_has_sender_dylibloader_orig_dbus
+#define dbus_message_has_signature dbus_message_has_signature_dylibloader_orig_dbus
+#define dbus_message_get_serial dbus_message_get_serial_dylibloader_orig_dbus
+#define dbus_message_set_serial dbus_message_set_serial_dylibloader_orig_dbus
+#define dbus_message_set_reply_serial dbus_message_set_reply_serial_dylibloader_orig_dbus
+#define dbus_message_get_reply_serial dbus_message_get_reply_serial_dylibloader_orig_dbus
+#define dbus_message_set_auto_start dbus_message_set_auto_start_dylibloader_orig_dbus
+#define dbus_message_get_auto_start dbus_message_get_auto_start_dylibloader_orig_dbus
+#define dbus_message_get_path_decomposed dbus_message_get_path_decomposed_dylibloader_orig_dbus
+#define dbus_message_append_args dbus_message_append_args_dylibloader_orig_dbus
+#define dbus_message_append_args_valist dbus_message_append_args_valist_dylibloader_orig_dbus
+#define dbus_message_get_args dbus_message_get_args_dylibloader_orig_dbus
+#define dbus_message_get_args_valist dbus_message_get_args_valist_dylibloader_orig_dbus
+#define dbus_message_contains_unix_fds dbus_message_contains_unix_fds_dylibloader_orig_dbus
+#define dbus_message_iter_init_closed dbus_message_iter_init_closed_dylibloader_orig_dbus
+#define dbus_message_iter_init dbus_message_iter_init_dylibloader_orig_dbus
+#define dbus_message_iter_has_next dbus_message_iter_has_next_dylibloader_orig_dbus
+#define dbus_message_iter_next dbus_message_iter_next_dylibloader_orig_dbus
+#define dbus_message_iter_get_signature dbus_message_iter_get_signature_dylibloader_orig_dbus
+#define dbus_message_iter_get_arg_type dbus_message_iter_get_arg_type_dylibloader_orig_dbus
+#define dbus_message_iter_get_element_type dbus_message_iter_get_element_type_dylibloader_orig_dbus
+#define dbus_message_iter_recurse dbus_message_iter_recurse_dylibloader_orig_dbus
+#define dbus_message_iter_get_basic dbus_message_iter_get_basic_dylibloader_orig_dbus
+#define dbus_message_iter_get_element_count dbus_message_iter_get_element_count_dylibloader_orig_dbus
+#define dbus_message_iter_get_array_len dbus_message_iter_get_array_len_dylibloader_orig_dbus
+#define dbus_message_iter_get_fixed_array dbus_message_iter_get_fixed_array_dylibloader_orig_dbus
+#define dbus_message_iter_init_append dbus_message_iter_init_append_dylibloader_orig_dbus
+#define dbus_message_iter_append_basic dbus_message_iter_append_basic_dylibloader_orig_dbus
+#define dbus_message_iter_append_fixed_array dbus_message_iter_append_fixed_array_dylibloader_orig_dbus
+#define dbus_message_iter_open_container dbus_message_iter_open_container_dylibloader_orig_dbus
+#define dbus_message_iter_close_container dbus_message_iter_close_container_dylibloader_orig_dbus
+#define dbus_message_iter_abandon_container dbus_message_iter_abandon_container_dylibloader_orig_dbus
+#define dbus_message_iter_abandon_container_if_open dbus_message_iter_abandon_container_if_open_dylibloader_orig_dbus
+#define dbus_message_lock dbus_message_lock_dylibloader_orig_dbus
+#define dbus_set_error_from_message dbus_set_error_from_message_dylibloader_orig_dbus
+#define dbus_message_allocate_data_slot dbus_message_allocate_data_slot_dylibloader_orig_dbus
+#define dbus_message_free_data_slot dbus_message_free_data_slot_dylibloader_orig_dbus
+#define dbus_message_set_data dbus_message_set_data_dylibloader_orig_dbus
+#define dbus_message_get_data dbus_message_get_data_dylibloader_orig_dbus
+#define dbus_message_type_from_string dbus_message_type_from_string_dylibloader_orig_dbus
+#define dbus_message_type_to_string dbus_message_type_to_string_dylibloader_orig_dbus
+#define dbus_message_marshal dbus_message_marshal_dylibloader_orig_dbus
+#define dbus_message_demarshal dbus_message_demarshal_dylibloader_orig_dbus
+#define dbus_message_demarshal_bytes_needed dbus_message_demarshal_bytes_needed_dylibloader_orig_dbus
+#define dbus_message_set_allow_interactive_authorization dbus_message_set_allow_interactive_authorization_dylibloader_orig_dbus
+#define dbus_message_get_allow_interactive_authorization dbus_message_get_allow_interactive_authorization_dylibloader_orig_dbus
+#define dbus_connection_open dbus_connection_open_dylibloader_orig_dbus
+#define dbus_connection_open_private dbus_connection_open_private_dylibloader_orig_dbus
+#define dbus_connection_ref dbus_connection_ref_dylibloader_orig_dbus
+#define dbus_connection_unref dbus_connection_unref_dylibloader_orig_dbus
+#define dbus_connection_close dbus_connection_close_dylibloader_orig_dbus
+#define dbus_connection_get_is_connected dbus_connection_get_is_connected_dylibloader_orig_dbus
+#define dbus_connection_get_is_authenticated dbus_connection_get_is_authenticated_dylibloader_orig_dbus
+#define dbus_connection_get_is_anonymous dbus_connection_get_is_anonymous_dylibloader_orig_dbus
+#define dbus_connection_get_server_id dbus_connection_get_server_id_dylibloader_orig_dbus
+#define dbus_connection_can_send_type dbus_connection_can_send_type_dylibloader_orig_dbus
+#define dbus_connection_set_exit_on_disconnect dbus_connection_set_exit_on_disconnect_dylibloader_orig_dbus
+#define dbus_connection_flush dbus_connection_flush_dylibloader_orig_dbus
+#define dbus_connection_read_write_dispatch dbus_connection_read_write_dispatch_dylibloader_orig_dbus
+#define dbus_connection_read_write dbus_connection_read_write_dylibloader_orig_dbus
+#define dbus_connection_borrow_message dbus_connection_borrow_message_dylibloader_orig_dbus
+#define dbus_connection_return_message dbus_connection_return_message_dylibloader_orig_dbus
+#define dbus_connection_steal_borrowed_message dbus_connection_steal_borrowed_message_dylibloader_orig_dbus
+#define dbus_connection_pop_message dbus_connection_pop_message_dylibloader_orig_dbus
+#define dbus_connection_get_dispatch_status dbus_connection_get_dispatch_status_dylibloader_orig_dbus
+#define dbus_connection_dispatch dbus_connection_dispatch_dylibloader_orig_dbus
+#define dbus_connection_has_messages_to_send dbus_connection_has_messages_to_send_dylibloader_orig_dbus
+#define dbus_connection_send dbus_connection_send_dylibloader_orig_dbus
+#define dbus_connection_send_with_reply dbus_connection_send_with_reply_dylibloader_orig_dbus
+#define dbus_connection_send_with_reply_and_block dbus_connection_send_with_reply_and_block_dylibloader_orig_dbus
+#define dbus_connection_set_watch_functions dbus_connection_set_watch_functions_dylibloader_orig_dbus
+#define dbus_connection_set_timeout_functions dbus_connection_set_timeout_functions_dylibloader_orig_dbus
+#define dbus_connection_set_wakeup_main_function dbus_connection_set_wakeup_main_function_dylibloader_orig_dbus
+#define dbus_connection_set_dispatch_status_function dbus_connection_set_dispatch_status_function_dylibloader_orig_dbus
+#define dbus_connection_get_unix_user dbus_connection_get_unix_user_dylibloader_orig_dbus
+#define dbus_connection_get_unix_process_id dbus_connection_get_unix_process_id_dylibloader_orig_dbus
+#define dbus_connection_get_adt_audit_session_data dbus_connection_get_adt_audit_session_data_dylibloader_orig_dbus
+#define dbus_connection_set_unix_user_function dbus_connection_set_unix_user_function_dylibloader_orig_dbus
+#define dbus_connection_get_windows_user dbus_connection_get_windows_user_dylibloader_orig_dbus
+#define dbus_connection_set_windows_user_function dbus_connection_set_windows_user_function_dylibloader_orig_dbus
+#define dbus_connection_set_allow_anonymous dbus_connection_set_allow_anonymous_dylibloader_orig_dbus
+#define dbus_connection_set_route_peer_messages dbus_connection_set_route_peer_messages_dylibloader_orig_dbus
+#define dbus_connection_add_filter dbus_connection_add_filter_dylibloader_orig_dbus
+#define dbus_connection_remove_filter dbus_connection_remove_filter_dylibloader_orig_dbus
+#define dbus_connection_allocate_data_slot dbus_connection_allocate_data_slot_dylibloader_orig_dbus
+#define dbus_connection_free_data_slot dbus_connection_free_data_slot_dylibloader_orig_dbus
+#define dbus_connection_set_data dbus_connection_set_data_dylibloader_orig_dbus
+#define dbus_connection_get_data dbus_connection_get_data_dylibloader_orig_dbus
+#define dbus_connection_set_change_sigpipe dbus_connection_set_change_sigpipe_dylibloader_orig_dbus
+#define dbus_connection_set_max_message_size dbus_connection_set_max_message_size_dylibloader_orig_dbus
+#define dbus_connection_get_max_message_size dbus_connection_get_max_message_size_dylibloader_orig_dbus
+#define dbus_connection_set_max_received_size dbus_connection_set_max_received_size_dylibloader_orig_dbus
+#define dbus_connection_get_max_received_size dbus_connection_get_max_received_size_dylibloader_orig_dbus
+#define dbus_connection_set_max_message_unix_fds dbus_connection_set_max_message_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_get_max_message_unix_fds dbus_connection_get_max_message_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_set_max_received_unix_fds dbus_connection_set_max_received_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_get_max_received_unix_fds dbus_connection_get_max_received_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_get_outgoing_size dbus_connection_get_outgoing_size_dylibloader_orig_dbus
+#define dbus_connection_get_outgoing_unix_fds dbus_connection_get_outgoing_unix_fds_dylibloader_orig_dbus
+#define dbus_connection_preallocate_send dbus_connection_preallocate_send_dylibloader_orig_dbus
+#define dbus_connection_free_preallocated_send dbus_connection_free_preallocated_send_dylibloader_orig_dbus
+#define dbus_connection_send_preallocated dbus_connection_send_preallocated_dylibloader_orig_dbus
+#define dbus_connection_try_register_object_path dbus_connection_try_register_object_path_dylibloader_orig_dbus
+#define dbus_connection_register_object_path dbus_connection_register_object_path_dylibloader_orig_dbus
+#define dbus_connection_try_register_fallback dbus_connection_try_register_fallback_dylibloader_orig_dbus
+#define dbus_connection_register_fallback dbus_connection_register_fallback_dylibloader_orig_dbus
+#define dbus_connection_unregister_object_path dbus_connection_unregister_object_path_dylibloader_orig_dbus
+#define dbus_connection_get_object_path_data dbus_connection_get_object_path_data_dylibloader_orig_dbus
+#define dbus_connection_list_registered dbus_connection_list_registered_dylibloader_orig_dbus
+#define dbus_connection_get_unix_fd dbus_connection_get_unix_fd_dylibloader_orig_dbus
+#define dbus_connection_get_socket dbus_connection_get_socket_dylibloader_orig_dbus
+#define dbus_watch_get_fd dbus_watch_get_fd_dylibloader_orig_dbus
+#define dbus_watch_get_unix_fd dbus_watch_get_unix_fd_dylibloader_orig_dbus
+#define dbus_watch_get_socket dbus_watch_get_socket_dylibloader_orig_dbus
+#define dbus_watch_get_flags dbus_watch_get_flags_dylibloader_orig_dbus
+#define dbus_watch_get_data dbus_watch_get_data_dylibloader_orig_dbus
+#define dbus_watch_set_data dbus_watch_set_data_dylibloader_orig_dbus
+#define dbus_watch_handle dbus_watch_handle_dylibloader_orig_dbus
+#define dbus_watch_get_enabled dbus_watch_get_enabled_dylibloader_orig_dbus
+#define dbus_timeout_get_interval dbus_timeout_get_interval_dylibloader_orig_dbus
+#define dbus_timeout_get_data dbus_timeout_get_data_dylibloader_orig_dbus
+#define dbus_timeout_set_data dbus_timeout_set_data_dylibloader_orig_dbus
+#define dbus_timeout_handle dbus_timeout_handle_dylibloader_orig_dbus
+#define dbus_timeout_get_enabled dbus_timeout_get_enabled_dylibloader_orig_dbus
+#define dbus_bus_get dbus_bus_get_dylibloader_orig_dbus
+#define dbus_bus_get_private dbus_bus_get_private_dylibloader_orig_dbus
+#define dbus_bus_register dbus_bus_register_dylibloader_orig_dbus
+#define dbus_bus_set_unique_name dbus_bus_set_unique_name_dylibloader_orig_dbus
+#define dbus_bus_get_unique_name dbus_bus_get_unique_name_dylibloader_orig_dbus
+#define dbus_bus_get_unix_user dbus_bus_get_unix_user_dylibloader_orig_dbus
+#define dbus_bus_get_id dbus_bus_get_id_dylibloader_orig_dbus
+#define dbus_bus_request_name dbus_bus_request_name_dylibloader_orig_dbus
+#define dbus_bus_release_name dbus_bus_release_name_dylibloader_orig_dbus
+#define dbus_bus_name_has_owner dbus_bus_name_has_owner_dylibloader_orig_dbus
+#define dbus_bus_start_service_by_name dbus_bus_start_service_by_name_dylibloader_orig_dbus
+#define dbus_bus_add_match dbus_bus_add_match_dylibloader_orig_dbus
+#define dbus_bus_remove_match dbus_bus_remove_match_dylibloader_orig_dbus
+#define dbus_get_local_machine_id dbus_get_local_machine_id_dylibloader_orig_dbus
+#define dbus_get_version dbus_get_version_dylibloader_orig_dbus
+#define dbus_setenv dbus_setenv_dylibloader_orig_dbus
+#define dbus_try_get_local_machine_id dbus_try_get_local_machine_id_dylibloader_orig_dbus
+#define dbus_pending_call_ref dbus_pending_call_ref_dylibloader_orig_dbus
+#define dbus_pending_call_unref dbus_pending_call_unref_dylibloader_orig_dbus
+#define dbus_pending_call_set_notify dbus_pending_call_set_notify_dylibloader_orig_dbus
+#define dbus_pending_call_cancel dbus_pending_call_cancel_dylibloader_orig_dbus
+#define dbus_pending_call_get_completed dbus_pending_call_get_completed_dylibloader_orig_dbus
+#define dbus_pending_call_steal_reply dbus_pending_call_steal_reply_dylibloader_orig_dbus
+#define dbus_pending_call_block dbus_pending_call_block_dylibloader_orig_dbus
+#define dbus_pending_call_allocate_data_slot dbus_pending_call_allocate_data_slot_dylibloader_orig_dbus
+#define dbus_pending_call_free_data_slot dbus_pending_call_free_data_slot_dylibloader_orig_dbus
+#define dbus_pending_call_set_data dbus_pending_call_set_data_dylibloader_orig_dbus
+#define dbus_pending_call_get_data dbus_pending_call_get_data_dylibloader_orig_dbus
+#define dbus_server_listen dbus_server_listen_dylibloader_orig_dbus
+#define dbus_server_ref dbus_server_ref_dylibloader_orig_dbus
+#define dbus_server_unref dbus_server_unref_dylibloader_orig_dbus
+#define dbus_server_disconnect dbus_server_disconnect_dylibloader_orig_dbus
+#define dbus_server_get_is_connected dbus_server_get_is_connected_dylibloader_orig_dbus
+#define dbus_server_get_address dbus_server_get_address_dylibloader_orig_dbus
+#define dbus_server_get_id dbus_server_get_id_dylibloader_orig_dbus
+#define dbus_server_set_new_connection_function dbus_server_set_new_connection_function_dylibloader_orig_dbus
+#define dbus_server_set_watch_functions dbus_server_set_watch_functions_dylibloader_orig_dbus
+#define dbus_server_set_timeout_functions dbus_server_set_timeout_functions_dylibloader_orig_dbus
+#define dbus_server_set_auth_mechanisms dbus_server_set_auth_mechanisms_dylibloader_orig_dbus
+#define dbus_server_allocate_data_slot dbus_server_allocate_data_slot_dylibloader_orig_dbus
+#define dbus_server_free_data_slot dbus_server_free_data_slot_dylibloader_orig_dbus
+#define dbus_server_set_data dbus_server_set_data_dylibloader_orig_dbus
+#define dbus_server_get_data dbus_server_get_data_dylibloader_orig_dbus
+#define dbus_signature_iter_init dbus_signature_iter_init_dylibloader_orig_dbus
+#define dbus_signature_iter_get_current_type dbus_signature_iter_get_current_type_dylibloader_orig_dbus
+#define dbus_signature_iter_get_signature dbus_signature_iter_get_signature_dylibloader_orig_dbus
+#define dbus_signature_iter_get_element_type dbus_signature_iter_get_element_type_dylibloader_orig_dbus
+#define dbus_signature_iter_next dbus_signature_iter_next_dylibloader_orig_dbus
+#define dbus_signature_iter_recurse dbus_signature_iter_recurse_dylibloader_orig_dbus
+#define dbus_signature_validate dbus_signature_validate_dylibloader_orig_dbus
+#define dbus_signature_validate_single dbus_signature_validate_single_dylibloader_orig_dbus
+#define dbus_type_is_valid dbus_type_is_valid_dylibloader_orig_dbus
+#define dbus_type_is_basic dbus_type_is_basic_dylibloader_orig_dbus
+#define dbus_type_is_container dbus_type_is_container_dylibloader_orig_dbus
+#define dbus_type_is_fixed dbus_type_is_fixed_dylibloader_orig_dbus
+#define dbus_validate_path dbus_validate_path_dylibloader_orig_dbus
+#define dbus_validate_interface dbus_validate_interface_dylibloader_orig_dbus
+#define dbus_validate_member dbus_validate_member_dylibloader_orig_dbus
+#define dbus_validate_error_name dbus_validate_error_name_dylibloader_orig_dbus
+#define dbus_validate_bus_name dbus_validate_bus_name_dylibloader_orig_dbus
+#define dbus_validate_utf8 dbus_validate_utf8_dylibloader_orig_dbus
+#define dbus_threads_init dbus_threads_init_dylibloader_orig_dbus
+#define dbus_threads_init_default dbus_threads_init_default_dylibloader_orig_dbus
+#include <dbus/dbus.h>
+#undef dbus_error_init
+#undef dbus_error_free
+#undef dbus_set_error
+#undef dbus_set_error_const
+#undef dbus_move_error
+#undef dbus_error_has_name
+#undef dbus_error_is_set
+#undef dbus_parse_address
+#undef dbus_address_entry_get_value
+#undef dbus_address_entry_get_method
+#undef dbus_address_entries_free
+#undef dbus_address_escape_value
+#undef dbus_address_unescape_value
+#undef dbus_malloc
+#undef dbus_malloc0
+#undef dbus_realloc
+#undef dbus_free
+#undef dbus_free_string_array
+#undef dbus_shutdown
+#undef dbus_message_new
+#undef dbus_message_new_method_call
+#undef dbus_message_new_method_return
+#undef dbus_message_new_signal
+#undef dbus_message_new_error
+#undef dbus_message_new_error_printf
+#undef dbus_message_copy
+#undef dbus_message_ref
+#undef dbus_message_unref
+#undef dbus_message_get_type
+#undef dbus_message_set_path
+#undef dbus_message_get_path
+#undef dbus_message_has_path
+#undef dbus_message_set_interface
+#undef dbus_message_get_interface
+#undef dbus_message_has_interface
+#undef dbus_message_set_member
+#undef dbus_message_get_member
+#undef dbus_message_has_member
+#undef dbus_message_set_error_name
+#undef dbus_message_get_error_name
+#undef dbus_message_set_destination
+#undef dbus_message_get_destination
+#undef dbus_message_set_sender
+#undef dbus_message_get_sender
+#undef dbus_message_get_signature
+#undef dbus_message_set_no_reply
+#undef dbus_message_get_no_reply
+#undef dbus_message_is_method_call
+#undef dbus_message_is_signal
+#undef dbus_message_is_error
+#undef dbus_message_has_destination
+#undef dbus_message_has_sender
+#undef dbus_message_has_signature
+#undef dbus_message_get_serial
+#undef dbus_message_set_serial
+#undef dbus_message_set_reply_serial
+#undef dbus_message_get_reply_serial
+#undef dbus_message_set_auto_start
+#undef dbus_message_get_auto_start
+#undef dbus_message_get_path_decomposed
+#undef dbus_message_append_args
+#undef dbus_message_append_args_valist
+#undef dbus_message_get_args
+#undef dbus_message_get_args_valist
+#undef dbus_message_contains_unix_fds
+#undef dbus_message_iter_init_closed
+#undef dbus_message_iter_init
+#undef dbus_message_iter_has_next
+#undef dbus_message_iter_next
+#undef dbus_message_iter_get_signature
+#undef dbus_message_iter_get_arg_type
+#undef dbus_message_iter_get_element_type
+#undef dbus_message_iter_recurse
+#undef dbus_message_iter_get_basic
+#undef dbus_message_iter_get_element_count
+#undef dbus_message_iter_get_array_len
+#undef dbus_message_iter_get_fixed_array
+#undef dbus_message_iter_init_append
+#undef dbus_message_iter_append_basic
+#undef dbus_message_iter_append_fixed_array
+#undef dbus_message_iter_open_container
+#undef dbus_message_iter_close_container
+#undef dbus_message_iter_abandon_container
+#undef dbus_message_iter_abandon_container_if_open
+#undef dbus_message_lock
+#undef dbus_set_error_from_message
+#undef dbus_message_allocate_data_slot
+#undef dbus_message_free_data_slot
+#undef dbus_message_set_data
+#undef dbus_message_get_data
+#undef dbus_message_type_from_string
+#undef dbus_message_type_to_string
+#undef dbus_message_marshal
+#undef dbus_message_demarshal
+#undef dbus_message_demarshal_bytes_needed
+#undef dbus_message_set_allow_interactive_authorization
+#undef dbus_message_get_allow_interactive_authorization
+#undef dbus_connection_open
+#undef dbus_connection_open_private
+#undef dbus_connection_ref
+#undef dbus_connection_unref
+#undef dbus_connection_close
+#undef dbus_connection_get_is_connected
+#undef dbus_connection_get_is_authenticated
+#undef dbus_connection_get_is_anonymous
+#undef dbus_connection_get_server_id
+#undef dbus_connection_can_send_type
+#undef dbus_connection_set_exit_on_disconnect
+#undef dbus_connection_flush
+#undef dbus_connection_read_write_dispatch
+#undef dbus_connection_read_write
+#undef dbus_connection_borrow_message
+#undef dbus_connection_return_message
+#undef dbus_connection_steal_borrowed_message
+#undef dbus_connection_pop_message
+#undef dbus_connection_get_dispatch_status
+#undef dbus_connection_dispatch
+#undef dbus_connection_has_messages_to_send
+#undef dbus_connection_send
+#undef dbus_connection_send_with_reply
+#undef dbus_connection_send_with_reply_and_block
+#undef dbus_connection_set_watch_functions
+#undef dbus_connection_set_timeout_functions
+#undef dbus_connection_set_wakeup_main_function
+#undef dbus_connection_set_dispatch_status_function
+#undef dbus_connection_get_unix_user
+#undef dbus_connection_get_unix_process_id
+#undef dbus_connection_get_adt_audit_session_data
+#undef dbus_connection_set_unix_user_function
+#undef dbus_connection_get_windows_user
+#undef dbus_connection_set_windows_user_function
+#undef dbus_connection_set_allow_anonymous
+#undef dbus_connection_set_route_peer_messages
+#undef dbus_connection_add_filter
+#undef dbus_connection_remove_filter
+#undef dbus_connection_allocate_data_slot
+#undef dbus_connection_free_data_slot
+#undef dbus_connection_set_data
+#undef dbus_connection_get_data
+#undef dbus_connection_set_change_sigpipe
+#undef dbus_connection_set_max_message_size
+#undef dbus_connection_get_max_message_size
+#undef dbus_connection_set_max_received_size
+#undef dbus_connection_get_max_received_size
+#undef dbus_connection_set_max_message_unix_fds
+#undef dbus_connection_get_max_message_unix_fds
+#undef dbus_connection_set_max_received_unix_fds
+#undef dbus_connection_get_max_received_unix_fds
+#undef dbus_connection_get_outgoing_size
+#undef dbus_connection_get_outgoing_unix_fds
+#undef dbus_connection_preallocate_send
+#undef dbus_connection_free_preallocated_send
+#undef dbus_connection_send_preallocated
+#undef dbus_connection_try_register_object_path
+#undef dbus_connection_register_object_path
+#undef dbus_connection_try_register_fallback
+#undef dbus_connection_register_fallback
+#undef dbus_connection_unregister_object_path
+#undef dbus_connection_get_object_path_data
+#undef dbus_connection_list_registered
+#undef dbus_connection_get_unix_fd
+#undef dbus_connection_get_socket
+#undef dbus_watch_get_fd
+#undef dbus_watch_get_unix_fd
+#undef dbus_watch_get_socket
+#undef dbus_watch_get_flags
+#undef dbus_watch_get_data
+#undef dbus_watch_set_data
+#undef dbus_watch_handle
+#undef dbus_watch_get_enabled
+#undef dbus_timeout_get_interval
+#undef dbus_timeout_get_data
+#undef dbus_timeout_set_data
+#undef dbus_timeout_handle
+#undef dbus_timeout_get_enabled
+#undef dbus_bus_get
+#undef dbus_bus_get_private
+#undef dbus_bus_register
+#undef dbus_bus_set_unique_name
+#undef dbus_bus_get_unique_name
+#undef dbus_bus_get_unix_user
+#undef dbus_bus_get_id
+#undef dbus_bus_request_name
+#undef dbus_bus_release_name
+#undef dbus_bus_name_has_owner
+#undef dbus_bus_start_service_by_name
+#undef dbus_bus_add_match
+#undef dbus_bus_remove_match
+#undef dbus_get_local_machine_id
+#undef dbus_get_version
+#undef dbus_setenv
+#undef dbus_try_get_local_machine_id
+#undef dbus_pending_call_ref
+#undef dbus_pending_call_unref
+#undef dbus_pending_call_set_notify
+#undef dbus_pending_call_cancel
+#undef dbus_pending_call_get_completed
+#undef dbus_pending_call_steal_reply
+#undef dbus_pending_call_block
+#undef dbus_pending_call_allocate_data_slot
+#undef dbus_pending_call_free_data_slot
+#undef dbus_pending_call_set_data
+#undef dbus_pending_call_get_data
+#undef dbus_server_listen
+#undef dbus_server_ref
+#undef dbus_server_unref
+#undef dbus_server_disconnect
+#undef dbus_server_get_is_connected
+#undef dbus_server_get_address
+#undef dbus_server_get_id
+#undef dbus_server_set_new_connection_function
+#undef dbus_server_set_watch_functions
+#undef dbus_server_set_timeout_functions
+#undef dbus_server_set_auth_mechanisms
+#undef dbus_server_allocate_data_slot
+#undef dbus_server_free_data_slot
+#undef dbus_server_set_data
+#undef dbus_server_get_data
+#undef dbus_signature_iter_init
+#undef dbus_signature_iter_get_current_type
+#undef dbus_signature_iter_get_signature
+#undef dbus_signature_iter_get_element_type
+#undef dbus_signature_iter_next
+#undef dbus_signature_iter_recurse
+#undef dbus_signature_validate
+#undef dbus_signature_validate_single
+#undef dbus_type_is_valid
+#undef dbus_type_is_basic
+#undef dbus_type_is_container
+#undef dbus_type_is_fixed
+#undef dbus_validate_path
+#undef dbus_validate_interface
+#undef dbus_validate_member
+#undef dbus_validate_error_name
+#undef dbus_validate_bus_name
+#undef dbus_validate_utf8
+#undef dbus_threads_init
+#undef dbus_threads_init_default
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define dbus_error_init dbus_error_init_dylibloader_wrapper_dbus
+#define dbus_error_free dbus_error_free_dylibloader_wrapper_dbus
+#define dbus_set_error dbus_set_error_dylibloader_wrapper_dbus
+#define dbus_set_error_const dbus_set_error_const_dylibloader_wrapper_dbus
+#define dbus_move_error dbus_move_error_dylibloader_wrapper_dbus
+#define dbus_error_has_name dbus_error_has_name_dylibloader_wrapper_dbus
+#define dbus_error_is_set dbus_error_is_set_dylibloader_wrapper_dbus
+#define dbus_parse_address dbus_parse_address_dylibloader_wrapper_dbus
+#define dbus_address_entry_get_value dbus_address_entry_get_value_dylibloader_wrapper_dbus
+#define dbus_address_entry_get_method dbus_address_entry_get_method_dylibloader_wrapper_dbus
+#define dbus_address_entries_free dbus_address_entries_free_dylibloader_wrapper_dbus
+#define dbus_address_escape_value dbus_address_escape_value_dylibloader_wrapper_dbus
+#define dbus_address_unescape_value dbus_address_unescape_value_dylibloader_wrapper_dbus
+#define dbus_malloc dbus_malloc_dylibloader_wrapper_dbus
+#define dbus_malloc0 dbus_malloc0_dylibloader_wrapper_dbus
+#define dbus_realloc dbus_realloc_dylibloader_wrapper_dbus
+#define dbus_free dbus_free_dylibloader_wrapper_dbus
+#define dbus_free_string_array dbus_free_string_array_dylibloader_wrapper_dbus
+#define dbus_shutdown dbus_shutdown_dylibloader_wrapper_dbus
+#define dbus_message_new dbus_message_new_dylibloader_wrapper_dbus
+#define dbus_message_new_method_call dbus_message_new_method_call_dylibloader_wrapper_dbus
+#define dbus_message_new_method_return dbus_message_new_method_return_dylibloader_wrapper_dbus
+#define dbus_message_new_signal dbus_message_new_signal_dylibloader_wrapper_dbus
+#define dbus_message_new_error dbus_message_new_error_dylibloader_wrapper_dbus
+#define dbus_message_new_error_printf dbus_message_new_error_printf_dylibloader_wrapper_dbus
+#define dbus_message_copy dbus_message_copy_dylibloader_wrapper_dbus
+#define dbus_message_ref dbus_message_ref_dylibloader_wrapper_dbus
+#define dbus_message_unref dbus_message_unref_dylibloader_wrapper_dbus
+#define dbus_message_get_type dbus_message_get_type_dylibloader_wrapper_dbus
+#define dbus_message_set_path dbus_message_set_path_dylibloader_wrapper_dbus
+#define dbus_message_get_path dbus_message_get_path_dylibloader_wrapper_dbus
+#define dbus_message_has_path dbus_message_has_path_dylibloader_wrapper_dbus
+#define dbus_message_set_interface dbus_message_set_interface_dylibloader_wrapper_dbus
+#define dbus_message_get_interface dbus_message_get_interface_dylibloader_wrapper_dbus
+#define dbus_message_has_interface dbus_message_has_interface_dylibloader_wrapper_dbus
+#define dbus_message_set_member dbus_message_set_member_dylibloader_wrapper_dbus
+#define dbus_message_get_member dbus_message_get_member_dylibloader_wrapper_dbus
+#define dbus_message_has_member dbus_message_has_member_dylibloader_wrapper_dbus
+#define dbus_message_set_error_name dbus_message_set_error_name_dylibloader_wrapper_dbus
+#define dbus_message_get_error_name dbus_message_get_error_name_dylibloader_wrapper_dbus
+#define dbus_message_set_destination dbus_message_set_destination_dylibloader_wrapper_dbus
+#define dbus_message_get_destination dbus_message_get_destination_dylibloader_wrapper_dbus
+#define dbus_message_set_sender dbus_message_set_sender_dylibloader_wrapper_dbus
+#define dbus_message_get_sender dbus_message_get_sender_dylibloader_wrapper_dbus
+#define dbus_message_get_signature dbus_message_get_signature_dylibloader_wrapper_dbus
+#define dbus_message_set_no_reply dbus_message_set_no_reply_dylibloader_wrapper_dbus
+#define dbus_message_get_no_reply dbus_message_get_no_reply_dylibloader_wrapper_dbus
+#define dbus_message_is_method_call dbus_message_is_method_call_dylibloader_wrapper_dbus
+#define dbus_message_is_signal dbus_message_is_signal_dylibloader_wrapper_dbus
+#define dbus_message_is_error dbus_message_is_error_dylibloader_wrapper_dbus
+#define dbus_message_has_destination dbus_message_has_destination_dylibloader_wrapper_dbus
+#define dbus_message_has_sender dbus_message_has_sender_dylibloader_wrapper_dbus
+#define dbus_message_has_signature dbus_message_has_signature_dylibloader_wrapper_dbus
+#define dbus_message_get_serial dbus_message_get_serial_dylibloader_wrapper_dbus
+#define dbus_message_set_serial dbus_message_set_serial_dylibloader_wrapper_dbus
+#define dbus_message_set_reply_serial dbus_message_set_reply_serial_dylibloader_wrapper_dbus
+#define dbus_message_get_reply_serial dbus_message_get_reply_serial_dylibloader_wrapper_dbus
+#define dbus_message_set_auto_start dbus_message_set_auto_start_dylibloader_wrapper_dbus
+#define dbus_message_get_auto_start dbus_message_get_auto_start_dylibloader_wrapper_dbus
+#define dbus_message_get_path_decomposed dbus_message_get_path_decomposed_dylibloader_wrapper_dbus
+#define dbus_message_append_args dbus_message_append_args_dylibloader_wrapper_dbus
+#define dbus_message_append_args_valist dbus_message_append_args_valist_dylibloader_wrapper_dbus
+#define dbus_message_get_args dbus_message_get_args_dylibloader_wrapper_dbus
+#define dbus_message_get_args_valist dbus_message_get_args_valist_dylibloader_wrapper_dbus
+#define dbus_message_contains_unix_fds dbus_message_contains_unix_fds_dylibloader_wrapper_dbus
+#define dbus_message_iter_init_closed dbus_message_iter_init_closed_dylibloader_wrapper_dbus
+#define dbus_message_iter_init dbus_message_iter_init_dylibloader_wrapper_dbus
+#define dbus_message_iter_has_next dbus_message_iter_has_next_dylibloader_wrapper_dbus
+#define dbus_message_iter_next dbus_message_iter_next_dylibloader_wrapper_dbus
+#define dbus_message_iter_get_signature dbus_message_iter_get_signature_dylibloader_wrapper_dbus
+#define dbus_message_iter_get_arg_type dbus_message_iter_get_arg_type_dylibloader_wrapper_dbus
+#define dbus_message_iter_get_element_type dbus_message_iter_get_element_type_dylibloader_wrapper_dbus
+#define dbus_message_iter_recurse dbus_message_iter_recurse_dylibloader_wrapper_dbus
+#define dbus_message_iter_get_basic dbus_message_iter_get_basic_dylibloader_wrapper_dbus
+#define dbus_message_iter_get_element_count dbus_message_iter_get_element_count_dylibloader_wrapper_dbus
+#define dbus_message_iter_get_array_len dbus_message_iter_get_array_len_dylibloader_wrapper_dbus
+#define dbus_message_iter_get_fixed_array dbus_message_iter_get_fixed_array_dylibloader_wrapper_dbus
+#define dbus_message_iter_init_append dbus_message_iter_init_append_dylibloader_wrapper_dbus
+#define dbus_message_iter_append_basic dbus_message_iter_append_basic_dylibloader_wrapper_dbus
+#define dbus_message_iter_append_fixed_array dbus_message_iter_append_fixed_array_dylibloader_wrapper_dbus
+#define dbus_message_iter_open_container dbus_message_iter_open_container_dylibloader_wrapper_dbus
+#define dbus_message_iter_close_container dbus_message_iter_close_container_dylibloader_wrapper_dbus
+#define dbus_message_iter_abandon_container dbus_message_iter_abandon_container_dylibloader_wrapper_dbus
+#define dbus_message_iter_abandon_container_if_open dbus_message_iter_abandon_container_if_open_dylibloader_wrapper_dbus
+#define dbus_message_lock dbus_message_lock_dylibloader_wrapper_dbus
+#define dbus_set_error_from_message dbus_set_error_from_message_dylibloader_wrapper_dbus
+#define dbus_message_allocate_data_slot dbus_message_allocate_data_slot_dylibloader_wrapper_dbus
+#define dbus_message_free_data_slot dbus_message_free_data_slot_dylibloader_wrapper_dbus
+#define dbus_message_set_data dbus_message_set_data_dylibloader_wrapper_dbus
+#define dbus_message_get_data dbus_message_get_data_dylibloader_wrapper_dbus
+#define dbus_message_type_from_string dbus_message_type_from_string_dylibloader_wrapper_dbus
+#define dbus_message_type_to_string dbus_message_type_to_string_dylibloader_wrapper_dbus
+#define dbus_message_marshal dbus_message_marshal_dylibloader_wrapper_dbus
+#define dbus_message_demarshal dbus_message_demarshal_dylibloader_wrapper_dbus
+#define dbus_message_demarshal_bytes_needed dbus_message_demarshal_bytes_needed_dylibloader_wrapper_dbus
+#define dbus_message_set_allow_interactive_authorization dbus_message_set_allow_interactive_authorization_dylibloader_wrapper_dbus
+#define dbus_message_get_allow_interactive_authorization dbus_message_get_allow_interactive_authorization_dylibloader_wrapper_dbus
+#define dbus_connection_open dbus_connection_open_dylibloader_wrapper_dbus
+#define dbus_connection_open_private dbus_connection_open_private_dylibloader_wrapper_dbus
+#define dbus_connection_ref dbus_connection_ref_dylibloader_wrapper_dbus
+#define dbus_connection_unref dbus_connection_unref_dylibloader_wrapper_dbus
+#define dbus_connection_close dbus_connection_close_dylibloader_wrapper_dbus
+#define dbus_connection_get_is_connected dbus_connection_get_is_connected_dylibloader_wrapper_dbus
+#define dbus_connection_get_is_authenticated dbus_connection_get_is_authenticated_dylibloader_wrapper_dbus
+#define dbus_connection_get_is_anonymous dbus_connection_get_is_anonymous_dylibloader_wrapper_dbus
+#define dbus_connection_get_server_id dbus_connection_get_server_id_dylibloader_wrapper_dbus
+#define dbus_connection_can_send_type dbus_connection_can_send_type_dylibloader_wrapper_dbus
+#define dbus_connection_set_exit_on_disconnect dbus_connection_set_exit_on_disconnect_dylibloader_wrapper_dbus
+#define dbus_connection_flush dbus_connection_flush_dylibloader_wrapper_dbus
+#define dbus_connection_read_write_dispatch dbus_connection_read_write_dispatch_dylibloader_wrapper_dbus
+#define dbus_connection_read_write dbus_connection_read_write_dylibloader_wrapper_dbus
+#define dbus_connection_borrow_message dbus_connection_borrow_message_dylibloader_wrapper_dbus
+#define dbus_connection_return_message dbus_connection_return_message_dylibloader_wrapper_dbus
+#define dbus_connection_steal_borrowed_message dbus_connection_steal_borrowed_message_dylibloader_wrapper_dbus
+#define dbus_connection_pop_message dbus_connection_pop_message_dylibloader_wrapper_dbus
+#define dbus_connection_get_dispatch_status dbus_connection_get_dispatch_status_dylibloader_wrapper_dbus
+#define dbus_connection_dispatch dbus_connection_dispatch_dylibloader_wrapper_dbus
+#define dbus_connection_has_messages_to_send dbus_connection_has_messages_to_send_dylibloader_wrapper_dbus
+#define dbus_connection_send dbus_connection_send_dylibloader_wrapper_dbus
+#define dbus_connection_send_with_reply dbus_connection_send_with_reply_dylibloader_wrapper_dbus
+#define dbus_connection_send_with_reply_and_block dbus_connection_send_with_reply_and_block_dylibloader_wrapper_dbus
+#define dbus_connection_set_watch_functions dbus_connection_set_watch_functions_dylibloader_wrapper_dbus
+#define dbus_connection_set_timeout_functions dbus_connection_set_timeout_functions_dylibloader_wrapper_dbus
+#define dbus_connection_set_wakeup_main_function dbus_connection_set_wakeup_main_function_dylibloader_wrapper_dbus
+#define dbus_connection_set_dispatch_status_function dbus_connection_set_dispatch_status_function_dylibloader_wrapper_dbus
+#define dbus_connection_get_unix_user dbus_connection_get_unix_user_dylibloader_wrapper_dbus
+#define dbus_connection_get_unix_process_id dbus_connection_get_unix_process_id_dylibloader_wrapper_dbus
+#define dbus_connection_get_adt_audit_session_data dbus_connection_get_adt_audit_session_data_dylibloader_wrapper_dbus
+#define dbus_connection_set_unix_user_function dbus_connection_set_unix_user_function_dylibloader_wrapper_dbus
+#define dbus_connection_get_windows_user dbus_connection_get_windows_user_dylibloader_wrapper_dbus
+#define dbus_connection_set_windows_user_function dbus_connection_set_windows_user_function_dylibloader_wrapper_dbus
+#define dbus_connection_set_allow_anonymous dbus_connection_set_allow_anonymous_dylibloader_wrapper_dbus
+#define dbus_connection_set_route_peer_messages dbus_connection_set_route_peer_messages_dylibloader_wrapper_dbus
+#define dbus_connection_add_filter dbus_connection_add_filter_dylibloader_wrapper_dbus
+#define dbus_connection_remove_filter dbus_connection_remove_filter_dylibloader_wrapper_dbus
+#define dbus_connection_allocate_data_slot dbus_connection_allocate_data_slot_dylibloader_wrapper_dbus
+#define dbus_connection_free_data_slot dbus_connection_free_data_slot_dylibloader_wrapper_dbus
+#define dbus_connection_set_data dbus_connection_set_data_dylibloader_wrapper_dbus
+#define dbus_connection_get_data dbus_connection_get_data_dylibloader_wrapper_dbus
+#define dbus_connection_set_change_sigpipe dbus_connection_set_change_sigpipe_dylibloader_wrapper_dbus
+#define dbus_connection_set_max_message_size dbus_connection_set_max_message_size_dylibloader_wrapper_dbus
+#define dbus_connection_get_max_message_size dbus_connection_get_max_message_size_dylibloader_wrapper_dbus
+#define dbus_connection_set_max_received_size dbus_connection_set_max_received_size_dylibloader_wrapper_dbus
+#define dbus_connection_get_max_received_size dbus_connection_get_max_received_size_dylibloader_wrapper_dbus
+#define dbus_connection_set_max_message_unix_fds dbus_connection_set_max_message_unix_fds_dylibloader_wrapper_dbus
+#define dbus_connection_get_max_message_unix_fds dbus_connection_get_max_message_unix_fds_dylibloader_wrapper_dbus
+#define dbus_connection_set_max_received_unix_fds dbus_connection_set_max_received_unix_fds_dylibloader_wrapper_dbus
+#define dbus_connection_get_max_received_unix_fds dbus_connection_get_max_received_unix_fds_dylibloader_wrapper_dbus
+#define dbus_connection_get_outgoing_size dbus_connection_get_outgoing_size_dylibloader_wrapper_dbus
+#define dbus_connection_get_outgoing_unix_fds dbus_connection_get_outgoing_unix_fds_dylibloader_wrapper_dbus
+#define dbus_connection_preallocate_send dbus_connection_preallocate_send_dylibloader_wrapper_dbus
+#define dbus_connection_free_preallocated_send dbus_connection_free_preallocated_send_dylibloader_wrapper_dbus
+#define dbus_connection_send_preallocated dbus_connection_send_preallocated_dylibloader_wrapper_dbus
+#define dbus_connection_try_register_object_path dbus_connection_try_register_object_path_dylibloader_wrapper_dbus
+#define dbus_connection_register_object_path dbus_connection_register_object_path_dylibloader_wrapper_dbus
+#define dbus_connection_try_register_fallback dbus_connection_try_register_fallback_dylibloader_wrapper_dbus
+#define dbus_connection_register_fallback dbus_connection_register_fallback_dylibloader_wrapper_dbus
+#define dbus_connection_unregister_object_path dbus_connection_unregister_object_path_dylibloader_wrapper_dbus
+#define dbus_connection_get_object_path_data dbus_connection_get_object_path_data_dylibloader_wrapper_dbus
+#define dbus_connection_list_registered dbus_connection_list_registered_dylibloader_wrapper_dbus
+#define dbus_connection_get_unix_fd dbus_connection_get_unix_fd_dylibloader_wrapper_dbus
+#define dbus_connection_get_socket dbus_connection_get_socket_dylibloader_wrapper_dbus
+#define dbus_watch_get_fd dbus_watch_get_fd_dylibloader_wrapper_dbus
+#define dbus_watch_get_unix_fd dbus_watch_get_unix_fd_dylibloader_wrapper_dbus
+#define dbus_watch_get_socket dbus_watch_get_socket_dylibloader_wrapper_dbus
+#define dbus_watch_get_flags dbus_watch_get_flags_dylibloader_wrapper_dbus
+#define dbus_watch_get_data dbus_watch_get_data_dylibloader_wrapper_dbus
+#define dbus_watch_set_data dbus_watch_set_data_dylibloader_wrapper_dbus
+#define dbus_watch_handle dbus_watch_handle_dylibloader_wrapper_dbus
+#define dbus_watch_get_enabled dbus_watch_get_enabled_dylibloader_wrapper_dbus
+#define dbus_timeout_get_interval dbus_timeout_get_interval_dylibloader_wrapper_dbus
+#define dbus_timeout_get_data dbus_timeout_get_data_dylibloader_wrapper_dbus
+#define dbus_timeout_set_data dbus_timeout_set_data_dylibloader_wrapper_dbus
+#define dbus_timeout_handle dbus_timeout_handle_dylibloader_wrapper_dbus
+#define dbus_timeout_get_enabled dbus_timeout_get_enabled_dylibloader_wrapper_dbus
+#define dbus_bus_get dbus_bus_get_dylibloader_wrapper_dbus
+#define dbus_bus_get_private dbus_bus_get_private_dylibloader_wrapper_dbus
+#define dbus_bus_register dbus_bus_register_dylibloader_wrapper_dbus
+#define dbus_bus_set_unique_name dbus_bus_set_unique_name_dylibloader_wrapper_dbus
+#define dbus_bus_get_unique_name dbus_bus_get_unique_name_dylibloader_wrapper_dbus
+#define dbus_bus_get_unix_user dbus_bus_get_unix_user_dylibloader_wrapper_dbus
+#define dbus_bus_get_id dbus_bus_get_id_dylibloader_wrapper_dbus
+#define dbus_bus_request_name dbus_bus_request_name_dylibloader_wrapper_dbus
+#define dbus_bus_release_name dbus_bus_release_name_dylibloader_wrapper_dbus
+#define dbus_bus_name_has_owner dbus_bus_name_has_owner_dylibloader_wrapper_dbus
+#define dbus_bus_start_service_by_name dbus_bus_start_service_by_name_dylibloader_wrapper_dbus
+#define dbus_bus_add_match dbus_bus_add_match_dylibloader_wrapper_dbus
+#define dbus_bus_remove_match dbus_bus_remove_match_dylibloader_wrapper_dbus
+#define dbus_get_local_machine_id dbus_get_local_machine_id_dylibloader_wrapper_dbus
+#define dbus_get_version dbus_get_version_dylibloader_wrapper_dbus
+#define dbus_setenv dbus_setenv_dylibloader_wrapper_dbus
+#define dbus_try_get_local_machine_id dbus_try_get_local_machine_id_dylibloader_wrapper_dbus
+#define dbus_pending_call_ref dbus_pending_call_ref_dylibloader_wrapper_dbus
+#define dbus_pending_call_unref dbus_pending_call_unref_dylibloader_wrapper_dbus
+#define dbus_pending_call_set_notify dbus_pending_call_set_notify_dylibloader_wrapper_dbus
+#define dbus_pending_call_cancel dbus_pending_call_cancel_dylibloader_wrapper_dbus
+#define dbus_pending_call_get_completed dbus_pending_call_get_completed_dylibloader_wrapper_dbus
+#define dbus_pending_call_steal_reply dbus_pending_call_steal_reply_dylibloader_wrapper_dbus
+#define dbus_pending_call_block dbus_pending_call_block_dylibloader_wrapper_dbus
+#define dbus_pending_call_allocate_data_slot dbus_pending_call_allocate_data_slot_dylibloader_wrapper_dbus
+#define dbus_pending_call_free_data_slot dbus_pending_call_free_data_slot_dylibloader_wrapper_dbus
+#define dbus_pending_call_set_data dbus_pending_call_set_data_dylibloader_wrapper_dbus
+#define dbus_pending_call_get_data dbus_pending_call_get_data_dylibloader_wrapper_dbus
+#define dbus_server_listen dbus_server_listen_dylibloader_wrapper_dbus
+#define dbus_server_ref dbus_server_ref_dylibloader_wrapper_dbus
+#define dbus_server_unref dbus_server_unref_dylibloader_wrapper_dbus
+#define dbus_server_disconnect dbus_server_disconnect_dylibloader_wrapper_dbus
+#define dbus_server_get_is_connected dbus_server_get_is_connected_dylibloader_wrapper_dbus
+#define dbus_server_get_address dbus_server_get_address_dylibloader_wrapper_dbus
+#define dbus_server_get_id dbus_server_get_id_dylibloader_wrapper_dbus
+#define dbus_server_set_new_connection_function dbus_server_set_new_connection_function_dylibloader_wrapper_dbus
+#define dbus_server_set_watch_functions dbus_server_set_watch_functions_dylibloader_wrapper_dbus
+#define dbus_server_set_timeout_functions dbus_server_set_timeout_functions_dylibloader_wrapper_dbus
+#define dbus_server_set_auth_mechanisms dbus_server_set_auth_mechanisms_dylibloader_wrapper_dbus
+#define dbus_server_allocate_data_slot dbus_server_allocate_data_slot_dylibloader_wrapper_dbus
+#define dbus_server_free_data_slot dbus_server_free_data_slot_dylibloader_wrapper_dbus
+#define dbus_server_set_data dbus_server_set_data_dylibloader_wrapper_dbus
+#define dbus_server_get_data dbus_server_get_data_dylibloader_wrapper_dbus
+#define dbus_signature_iter_init dbus_signature_iter_init_dylibloader_wrapper_dbus
+#define dbus_signature_iter_get_current_type dbus_signature_iter_get_current_type_dylibloader_wrapper_dbus
+#define dbus_signature_iter_get_signature dbus_signature_iter_get_signature_dylibloader_wrapper_dbus
+#define dbus_signature_iter_get_element_type dbus_signature_iter_get_element_type_dylibloader_wrapper_dbus
+#define dbus_signature_iter_next dbus_signature_iter_next_dylibloader_wrapper_dbus
+#define dbus_signature_iter_recurse dbus_signature_iter_recurse_dylibloader_wrapper_dbus
+#define dbus_signature_validate dbus_signature_validate_dylibloader_wrapper_dbus
+#define dbus_signature_validate_single dbus_signature_validate_single_dylibloader_wrapper_dbus
+#define dbus_type_is_valid dbus_type_is_valid_dylibloader_wrapper_dbus
+#define dbus_type_is_basic dbus_type_is_basic_dylibloader_wrapper_dbus
+#define dbus_type_is_container dbus_type_is_container_dylibloader_wrapper_dbus
+#define dbus_type_is_fixed dbus_type_is_fixed_dylibloader_wrapper_dbus
+#define dbus_validate_path dbus_validate_path_dylibloader_wrapper_dbus
+#define dbus_validate_interface dbus_validate_interface_dylibloader_wrapper_dbus
+#define dbus_validate_member dbus_validate_member_dylibloader_wrapper_dbus
+#define dbus_validate_error_name dbus_validate_error_name_dylibloader_wrapper_dbus
+#define dbus_validate_bus_name dbus_validate_bus_name_dylibloader_wrapper_dbus
+#define dbus_validate_utf8 dbus_validate_utf8_dylibloader_wrapper_dbus
+#define dbus_threads_init dbus_threads_init_dylibloader_wrapper_dbus
+#define dbus_threads_init_default dbus_threads_init_default_dylibloader_wrapper_dbus
+extern void (*dbus_error_init_dylibloader_wrapper_dbus)( DBusError*);
+extern void (*dbus_error_free_dylibloader_wrapper_dbus)( DBusError*);
+extern void (*dbus_set_error_dylibloader_wrapper_dbus)( DBusError*,const char*,const char*,...);
+extern void (*dbus_set_error_const_dylibloader_wrapper_dbus)( DBusError*,const char*,const char*);
+extern void (*dbus_move_error_dylibloader_wrapper_dbus)( DBusError*, DBusError*);
+extern dbus_bool_t (*dbus_error_has_name_dylibloader_wrapper_dbus)(const DBusError*,const char*);
+extern dbus_bool_t (*dbus_error_is_set_dylibloader_wrapper_dbus)(const DBusError*);
+extern dbus_bool_t (*dbus_parse_address_dylibloader_wrapper_dbus)(const char*, DBusAddressEntry***, int*, DBusError*);
+extern const char* (*dbus_address_entry_get_value_dylibloader_wrapper_dbus)( DBusAddressEntry*,const char*);
+extern const char* (*dbus_address_entry_get_method_dylibloader_wrapper_dbus)( DBusAddressEntry*);
+extern void (*dbus_address_entries_free_dylibloader_wrapper_dbus)( DBusAddressEntry**);
+extern char* (*dbus_address_escape_value_dylibloader_wrapper_dbus)(const char*);
+extern char* (*dbus_address_unescape_value_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern void* (*dbus_malloc_dylibloader_wrapper_dbus)( size_t);
+extern void* (*dbus_malloc0_dylibloader_wrapper_dbus)( size_t);
+extern void* (*dbus_realloc_dylibloader_wrapper_dbus)( void*, size_t);
+extern void (*dbus_free_dylibloader_wrapper_dbus)( void*);
+extern void (*dbus_free_string_array_dylibloader_wrapper_dbus)( char**);
+extern void (*dbus_shutdown_dylibloader_wrapper_dbus)( void);
+extern DBusMessage* (*dbus_message_new_dylibloader_wrapper_dbus)( int);
+extern DBusMessage* (*dbus_message_new_method_call_dylibloader_wrapper_dbus)(const char*,const char*,const char*,const char*);
+extern DBusMessage* (*dbus_message_new_method_return_dylibloader_wrapper_dbus)( DBusMessage*);
+extern DBusMessage* (*dbus_message_new_signal_dylibloader_wrapper_dbus)(const char*,const char*,const char*);
+extern DBusMessage* (*dbus_message_new_error_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*);
+extern DBusMessage* (*dbus_message_new_error_printf_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*,...);
+extern DBusMessage* (*dbus_message_copy_dylibloader_wrapper_dbus)(const DBusMessage*);
+extern DBusMessage* (*dbus_message_ref_dylibloader_wrapper_dbus)( DBusMessage*);
+extern void (*dbus_message_unref_dylibloader_wrapper_dbus)( DBusMessage*);
+extern int (*dbus_message_get_type_dylibloader_wrapper_dbus)( DBusMessage*);
+extern dbus_bool_t (*dbus_message_set_path_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern const char* (*dbus_message_get_path_dylibloader_wrapper_dbus)( DBusMessage*);
+extern dbus_bool_t (*dbus_message_has_path_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern dbus_bool_t (*dbus_message_set_interface_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern const char* (*dbus_message_get_interface_dylibloader_wrapper_dbus)( DBusMessage*);
+extern dbus_bool_t (*dbus_message_has_interface_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern dbus_bool_t (*dbus_message_set_member_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern const char* (*dbus_message_get_member_dylibloader_wrapper_dbus)( DBusMessage*);
+extern dbus_bool_t (*dbus_message_has_member_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern dbus_bool_t (*dbus_message_set_error_name_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern const char* (*dbus_message_get_error_name_dylibloader_wrapper_dbus)( DBusMessage*);
+extern dbus_bool_t (*dbus_message_set_destination_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern const char* (*dbus_message_get_destination_dylibloader_wrapper_dbus)( DBusMessage*);
+extern dbus_bool_t (*dbus_message_set_sender_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern const char* (*dbus_message_get_sender_dylibloader_wrapper_dbus)( DBusMessage*);
+extern const char* (*dbus_message_get_signature_dylibloader_wrapper_dbus)( DBusMessage*);
+extern void (*dbus_message_set_no_reply_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t);
+extern dbus_bool_t (*dbus_message_get_no_reply_dylibloader_wrapper_dbus)( DBusMessage*);
+extern dbus_bool_t (*dbus_message_is_method_call_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*);
+extern dbus_bool_t (*dbus_message_is_signal_dylibloader_wrapper_dbus)( DBusMessage*,const char*,const char*);
+extern dbus_bool_t (*dbus_message_is_error_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern dbus_bool_t (*dbus_message_has_destination_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern dbus_bool_t (*dbus_message_has_sender_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern dbus_bool_t (*dbus_message_has_signature_dylibloader_wrapper_dbus)( DBusMessage*,const char*);
+extern dbus_uint32_t (*dbus_message_get_serial_dylibloader_wrapper_dbus)( DBusMessage*);
+extern void (*dbus_message_set_serial_dylibloader_wrapper_dbus)( DBusMessage*, dbus_uint32_t);
+extern dbus_bool_t (*dbus_message_set_reply_serial_dylibloader_wrapper_dbus)( DBusMessage*, dbus_uint32_t);
+extern dbus_uint32_t (*dbus_message_get_reply_serial_dylibloader_wrapper_dbus)( DBusMessage*);
+extern void (*dbus_message_set_auto_start_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t);
+extern dbus_bool_t (*dbus_message_get_auto_start_dylibloader_wrapper_dbus)( DBusMessage*);
+extern dbus_bool_t (*dbus_message_get_path_decomposed_dylibloader_wrapper_dbus)( DBusMessage*, char***);
+extern dbus_bool_t (*dbus_message_append_args_dylibloader_wrapper_dbus)( DBusMessage*, int,...);
+extern dbus_bool_t (*dbus_message_append_args_valist_dylibloader_wrapper_dbus)( DBusMessage*, int, va_list);
+extern dbus_bool_t (*dbus_message_get_args_dylibloader_wrapper_dbus)( DBusMessage*, DBusError*, int,...);
+extern dbus_bool_t (*dbus_message_get_args_valist_dylibloader_wrapper_dbus)( DBusMessage*, DBusError*, int, va_list);
+extern dbus_bool_t (*dbus_message_contains_unix_fds_dylibloader_wrapper_dbus)( DBusMessage*);
+extern void (*dbus_message_iter_init_closed_dylibloader_wrapper_dbus)( DBusMessageIter*);
+extern dbus_bool_t (*dbus_message_iter_init_dylibloader_wrapper_dbus)( DBusMessage*, DBusMessageIter*);
+extern dbus_bool_t (*dbus_message_iter_has_next_dylibloader_wrapper_dbus)( DBusMessageIter*);
+extern dbus_bool_t (*dbus_message_iter_next_dylibloader_wrapper_dbus)( DBusMessageIter*);
+extern char* (*dbus_message_iter_get_signature_dylibloader_wrapper_dbus)( DBusMessageIter*);
+extern int (*dbus_message_iter_get_arg_type_dylibloader_wrapper_dbus)( DBusMessageIter*);
+extern int (*dbus_message_iter_get_element_type_dylibloader_wrapper_dbus)( DBusMessageIter*);
+extern void (*dbus_message_iter_recurse_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*);
+extern void (*dbus_message_iter_get_basic_dylibloader_wrapper_dbus)( DBusMessageIter*, void*);
+extern int (*dbus_message_iter_get_element_count_dylibloader_wrapper_dbus)( DBusMessageIter*);
+extern int (*dbus_message_iter_get_array_len_dylibloader_wrapper_dbus)( DBusMessageIter*);
+extern void (*dbus_message_iter_get_fixed_array_dylibloader_wrapper_dbus)( DBusMessageIter*, void*, int*);
+extern void (*dbus_message_iter_init_append_dylibloader_wrapper_dbus)( DBusMessage*, DBusMessageIter*);
+extern dbus_bool_t (*dbus_message_iter_append_basic_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const void*);
+extern dbus_bool_t (*dbus_message_iter_append_fixed_array_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const void*, int);
+extern dbus_bool_t (*dbus_message_iter_open_container_dylibloader_wrapper_dbus)( DBusMessageIter*, int,const char*, DBusMessageIter*);
+extern dbus_bool_t (*dbus_message_iter_close_container_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*);
+extern void (*dbus_message_iter_abandon_container_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*);
+extern void (*dbus_message_iter_abandon_container_if_open_dylibloader_wrapper_dbus)( DBusMessageIter*, DBusMessageIter*);
+extern void (*dbus_message_lock_dylibloader_wrapper_dbus)( DBusMessage*);
+extern dbus_bool_t (*dbus_set_error_from_message_dylibloader_wrapper_dbus)( DBusError*, DBusMessage*);
+extern dbus_bool_t (*dbus_message_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+extern void (*dbus_message_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+extern dbus_bool_t (*dbus_message_set_data_dylibloader_wrapper_dbus)( DBusMessage*, dbus_int32_t, void*, DBusFreeFunction);
+extern void* (*dbus_message_get_data_dylibloader_wrapper_dbus)( DBusMessage*, dbus_int32_t);
+extern int (*dbus_message_type_from_string_dylibloader_wrapper_dbus)(const char*);
+extern const char* (*dbus_message_type_to_string_dylibloader_wrapper_dbus)( int);
+extern dbus_bool_t (*dbus_message_marshal_dylibloader_wrapper_dbus)( DBusMessage*, char**, int*);
+extern DBusMessage* (*dbus_message_demarshal_dylibloader_wrapper_dbus)(const char*, int, DBusError*);
+extern int (*dbus_message_demarshal_bytes_needed_dylibloader_wrapper_dbus)(const char*, int);
+extern void (*dbus_message_set_allow_interactive_authorization_dylibloader_wrapper_dbus)( DBusMessage*, dbus_bool_t);
+extern dbus_bool_t (*dbus_message_get_allow_interactive_authorization_dylibloader_wrapper_dbus)( DBusMessage*);
+extern DBusConnection* (*dbus_connection_open_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern DBusConnection* (*dbus_connection_open_private_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern DBusConnection* (*dbus_connection_ref_dylibloader_wrapper_dbus)( DBusConnection*);
+extern void (*dbus_connection_unref_dylibloader_wrapper_dbus)( DBusConnection*);
+extern void (*dbus_connection_close_dylibloader_wrapper_dbus)( DBusConnection*);
+extern dbus_bool_t (*dbus_connection_get_is_connected_dylibloader_wrapper_dbus)( DBusConnection*);
+extern dbus_bool_t (*dbus_connection_get_is_authenticated_dylibloader_wrapper_dbus)( DBusConnection*);
+extern dbus_bool_t (*dbus_connection_get_is_anonymous_dylibloader_wrapper_dbus)( DBusConnection*);
+extern char* (*dbus_connection_get_server_id_dylibloader_wrapper_dbus)( DBusConnection*);
+extern dbus_bool_t (*dbus_connection_can_send_type_dylibloader_wrapper_dbus)( DBusConnection*, int);
+extern void (*dbus_connection_set_exit_on_disconnect_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t);
+extern void (*dbus_connection_flush_dylibloader_wrapper_dbus)( DBusConnection*);
+extern dbus_bool_t (*dbus_connection_read_write_dispatch_dylibloader_wrapper_dbus)( DBusConnection*, int);
+extern dbus_bool_t (*dbus_connection_read_write_dylibloader_wrapper_dbus)( DBusConnection*, int);
+extern DBusMessage* (*dbus_connection_borrow_message_dylibloader_wrapper_dbus)( DBusConnection*);
+extern void (*dbus_connection_return_message_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*);
+extern void (*dbus_connection_steal_borrowed_message_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*);
+extern DBusMessage* (*dbus_connection_pop_message_dylibloader_wrapper_dbus)( DBusConnection*);
+extern DBusDispatchStatus (*dbus_connection_get_dispatch_status_dylibloader_wrapper_dbus)( DBusConnection*);
+extern DBusDispatchStatus (*dbus_connection_dispatch_dylibloader_wrapper_dbus)( DBusConnection*);
+extern dbus_bool_t (*dbus_connection_has_messages_to_send_dylibloader_wrapper_dbus)( DBusConnection*);
+extern dbus_bool_t (*dbus_connection_send_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, dbus_uint32_t*);
+extern dbus_bool_t (*dbus_connection_send_with_reply_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, DBusPendingCall**, int);
+extern DBusMessage* (*dbus_connection_send_with_reply_and_block_dylibloader_wrapper_dbus)( DBusConnection*, DBusMessage*, int, DBusError*);
+extern dbus_bool_t (*dbus_connection_set_watch_functions_dylibloader_wrapper_dbus)( DBusConnection*, DBusAddWatchFunction, DBusRemoveWatchFunction, DBusWatchToggledFunction, void*, DBusFreeFunction);
+extern dbus_bool_t (*dbus_connection_set_timeout_functions_dylibloader_wrapper_dbus)( DBusConnection*, DBusAddTimeoutFunction, DBusRemoveTimeoutFunction, DBusTimeoutToggledFunction, void*, DBusFreeFunction);
+extern void (*dbus_connection_set_wakeup_main_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusWakeupMainFunction, void*, DBusFreeFunction);
+extern void (*dbus_connection_set_dispatch_status_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusDispatchStatusFunction, void*, DBusFreeFunction);
+extern dbus_bool_t (*dbus_connection_get_unix_user_dylibloader_wrapper_dbus)( DBusConnection*, unsigned long*);
+extern dbus_bool_t (*dbus_connection_get_unix_process_id_dylibloader_wrapper_dbus)( DBusConnection*, unsigned long*);
+extern dbus_bool_t (*dbus_connection_get_adt_audit_session_data_dylibloader_wrapper_dbus)( DBusConnection*, void**, dbus_int32_t*);
+extern void (*dbus_connection_set_unix_user_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusAllowUnixUserFunction, void*, DBusFreeFunction);
+extern dbus_bool_t (*dbus_connection_get_windows_user_dylibloader_wrapper_dbus)( DBusConnection*, char**);
+extern void (*dbus_connection_set_windows_user_function_dylibloader_wrapper_dbus)( DBusConnection*, DBusAllowWindowsUserFunction, void*, DBusFreeFunction);
+extern void (*dbus_connection_set_allow_anonymous_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t);
+extern void (*dbus_connection_set_route_peer_messages_dylibloader_wrapper_dbus)( DBusConnection*, dbus_bool_t);
+extern dbus_bool_t (*dbus_connection_add_filter_dylibloader_wrapper_dbus)( DBusConnection*, DBusHandleMessageFunction, void*, DBusFreeFunction);
+extern void (*dbus_connection_remove_filter_dylibloader_wrapper_dbus)( DBusConnection*, DBusHandleMessageFunction, void*);
+extern dbus_bool_t (*dbus_connection_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+extern void (*dbus_connection_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+extern dbus_bool_t (*dbus_connection_set_data_dylibloader_wrapper_dbus)( DBusConnection*, dbus_int32_t, void*, DBusFreeFunction);
+extern void* (*dbus_connection_get_data_dylibloader_wrapper_dbus)( DBusConnection*, dbus_int32_t);
+extern void (*dbus_connection_set_change_sigpipe_dylibloader_wrapper_dbus)( dbus_bool_t);
+extern void (*dbus_connection_set_max_message_size_dylibloader_wrapper_dbus)( DBusConnection*, long);
+extern long (*dbus_connection_get_max_message_size_dylibloader_wrapper_dbus)( DBusConnection*);
+extern void (*dbus_connection_set_max_received_size_dylibloader_wrapper_dbus)( DBusConnection*, long);
+extern long (*dbus_connection_get_max_received_size_dylibloader_wrapper_dbus)( DBusConnection*);
+extern void (*dbus_connection_set_max_message_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*, long);
+extern long (*dbus_connection_get_max_message_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*);
+extern void (*dbus_connection_set_max_received_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*, long);
+extern long (*dbus_connection_get_max_received_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*);
+extern long (*dbus_connection_get_outgoing_size_dylibloader_wrapper_dbus)( DBusConnection*);
+extern long (*dbus_connection_get_outgoing_unix_fds_dylibloader_wrapper_dbus)( DBusConnection*);
+extern DBusPreallocatedSend* (*dbus_connection_preallocate_send_dylibloader_wrapper_dbus)( DBusConnection*);
+extern void (*dbus_connection_free_preallocated_send_dylibloader_wrapper_dbus)( DBusConnection*, DBusPreallocatedSend*);
+extern void (*dbus_connection_send_preallocated_dylibloader_wrapper_dbus)( DBusConnection*, DBusPreallocatedSend*, DBusMessage*, dbus_uint32_t*);
+extern dbus_bool_t (*dbus_connection_try_register_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*, DBusError*);
+extern dbus_bool_t (*dbus_connection_register_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*);
+extern dbus_bool_t (*dbus_connection_try_register_fallback_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*, DBusError*);
+extern dbus_bool_t (*dbus_connection_register_fallback_dylibloader_wrapper_dbus)( DBusConnection*,const char*,const DBusObjectPathVTable*, void*);
+extern dbus_bool_t (*dbus_connection_unregister_object_path_dylibloader_wrapper_dbus)( DBusConnection*,const char*);
+extern dbus_bool_t (*dbus_connection_get_object_path_data_dylibloader_wrapper_dbus)( DBusConnection*,const char*, void**);
+extern dbus_bool_t (*dbus_connection_list_registered_dylibloader_wrapper_dbus)( DBusConnection*,const char*, char***);
+extern dbus_bool_t (*dbus_connection_get_unix_fd_dylibloader_wrapper_dbus)( DBusConnection*, int*);
+extern dbus_bool_t (*dbus_connection_get_socket_dylibloader_wrapper_dbus)( DBusConnection*, int*);
+extern int (*dbus_watch_get_fd_dylibloader_wrapper_dbus)( DBusWatch*);
+extern int (*dbus_watch_get_unix_fd_dylibloader_wrapper_dbus)( DBusWatch*);
+extern int (*dbus_watch_get_socket_dylibloader_wrapper_dbus)( DBusWatch*);
+extern unsigned int (*dbus_watch_get_flags_dylibloader_wrapper_dbus)( DBusWatch*);
+extern void* (*dbus_watch_get_data_dylibloader_wrapper_dbus)( DBusWatch*);
+extern void (*dbus_watch_set_data_dylibloader_wrapper_dbus)( DBusWatch*, void*, DBusFreeFunction);
+extern dbus_bool_t (*dbus_watch_handle_dylibloader_wrapper_dbus)( DBusWatch*, unsigned int);
+extern dbus_bool_t (*dbus_watch_get_enabled_dylibloader_wrapper_dbus)( DBusWatch*);
+extern int (*dbus_timeout_get_interval_dylibloader_wrapper_dbus)( DBusTimeout*);
+extern void* (*dbus_timeout_get_data_dylibloader_wrapper_dbus)( DBusTimeout*);
+extern void (*dbus_timeout_set_data_dylibloader_wrapper_dbus)( DBusTimeout*, void*, DBusFreeFunction);
+extern dbus_bool_t (*dbus_timeout_handle_dylibloader_wrapper_dbus)( DBusTimeout*);
+extern dbus_bool_t (*dbus_timeout_get_enabled_dylibloader_wrapper_dbus)( DBusTimeout*);
+extern DBusConnection* (*dbus_bus_get_dylibloader_wrapper_dbus)( DBusBusType, DBusError*);
+extern DBusConnection* (*dbus_bus_get_private_dylibloader_wrapper_dbus)( DBusBusType, DBusError*);
+extern dbus_bool_t (*dbus_bus_register_dylibloader_wrapper_dbus)( DBusConnection*, DBusError*);
+extern dbus_bool_t (*dbus_bus_set_unique_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*);
+extern const char* (*dbus_bus_get_unique_name_dylibloader_wrapper_dbus)( DBusConnection*);
+extern unsigned long (*dbus_bus_get_unix_user_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+extern char* (*dbus_bus_get_id_dylibloader_wrapper_dbus)( DBusConnection*, DBusError*);
+extern int (*dbus_bus_request_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, unsigned int, DBusError*);
+extern int (*dbus_bus_release_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+extern dbus_bool_t (*dbus_bus_name_has_owner_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+extern dbus_bool_t (*dbus_bus_start_service_by_name_dylibloader_wrapper_dbus)( DBusConnection*,const char*, dbus_uint32_t, dbus_uint32_t*, DBusError*);
+extern void (*dbus_bus_add_match_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+extern void (*dbus_bus_remove_match_dylibloader_wrapper_dbus)( DBusConnection*,const char*, DBusError*);
+extern char* (*dbus_get_local_machine_id_dylibloader_wrapper_dbus)( void);
+extern void (*dbus_get_version_dylibloader_wrapper_dbus)( int*, int*, int*);
+extern dbus_bool_t (*dbus_setenv_dylibloader_wrapper_dbus)(const char*,const char*);
+extern char* (*dbus_try_get_local_machine_id_dylibloader_wrapper_dbus)( DBusError*);
+extern DBusPendingCall* (*dbus_pending_call_ref_dylibloader_wrapper_dbus)( DBusPendingCall*);
+extern void (*dbus_pending_call_unref_dylibloader_wrapper_dbus)( DBusPendingCall*);
+extern dbus_bool_t (*dbus_pending_call_set_notify_dylibloader_wrapper_dbus)( DBusPendingCall*, DBusPendingCallNotifyFunction, void*, DBusFreeFunction);
+extern void (*dbus_pending_call_cancel_dylibloader_wrapper_dbus)( DBusPendingCall*);
+extern dbus_bool_t (*dbus_pending_call_get_completed_dylibloader_wrapper_dbus)( DBusPendingCall*);
+extern DBusMessage* (*dbus_pending_call_steal_reply_dylibloader_wrapper_dbus)( DBusPendingCall*);
+extern void (*dbus_pending_call_block_dylibloader_wrapper_dbus)( DBusPendingCall*);
+extern dbus_bool_t (*dbus_pending_call_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+extern void (*dbus_pending_call_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+extern dbus_bool_t (*dbus_pending_call_set_data_dylibloader_wrapper_dbus)( DBusPendingCall*, dbus_int32_t, void*, DBusFreeFunction);
+extern void* (*dbus_pending_call_get_data_dylibloader_wrapper_dbus)( DBusPendingCall*, dbus_int32_t);
+extern DBusServer* (*dbus_server_listen_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern DBusServer* (*dbus_server_ref_dylibloader_wrapper_dbus)( DBusServer*);
+extern void (*dbus_server_unref_dylibloader_wrapper_dbus)( DBusServer*);
+extern void (*dbus_server_disconnect_dylibloader_wrapper_dbus)( DBusServer*);
+extern dbus_bool_t (*dbus_server_get_is_connected_dylibloader_wrapper_dbus)( DBusServer*);
+extern char* (*dbus_server_get_address_dylibloader_wrapper_dbus)( DBusServer*);
+extern char* (*dbus_server_get_id_dylibloader_wrapper_dbus)( DBusServer*);
+extern void (*dbus_server_set_new_connection_function_dylibloader_wrapper_dbus)( DBusServer*, DBusNewConnectionFunction, void*, DBusFreeFunction);
+extern dbus_bool_t (*dbus_server_set_watch_functions_dylibloader_wrapper_dbus)( DBusServer*, DBusAddWatchFunction, DBusRemoveWatchFunction, DBusWatchToggledFunction, void*, DBusFreeFunction);
+extern dbus_bool_t (*dbus_server_set_timeout_functions_dylibloader_wrapper_dbus)( DBusServer*, DBusAddTimeoutFunction, DBusRemoveTimeoutFunction, DBusTimeoutToggledFunction, void*, DBusFreeFunction);
+extern dbus_bool_t (*dbus_server_set_auth_mechanisms_dylibloader_wrapper_dbus)( DBusServer*,const char**);
+extern dbus_bool_t (*dbus_server_allocate_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+extern void (*dbus_server_free_data_slot_dylibloader_wrapper_dbus)( dbus_int32_t*);
+extern dbus_bool_t (*dbus_server_set_data_dylibloader_wrapper_dbus)( DBusServer*, int, void*, DBusFreeFunction);
+extern void* (*dbus_server_get_data_dylibloader_wrapper_dbus)( DBusServer*, int);
+extern void (*dbus_signature_iter_init_dylibloader_wrapper_dbus)( DBusSignatureIter*,const char*);
+extern int (*dbus_signature_iter_get_current_type_dylibloader_wrapper_dbus)(const DBusSignatureIter*);
+extern char* (*dbus_signature_iter_get_signature_dylibloader_wrapper_dbus)(const DBusSignatureIter*);
+extern int (*dbus_signature_iter_get_element_type_dylibloader_wrapper_dbus)(const DBusSignatureIter*);
+extern dbus_bool_t (*dbus_signature_iter_next_dylibloader_wrapper_dbus)( DBusSignatureIter*);
+extern void (*dbus_signature_iter_recurse_dylibloader_wrapper_dbus)(const DBusSignatureIter*, DBusSignatureIter*);
+extern dbus_bool_t (*dbus_signature_validate_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern dbus_bool_t (*dbus_signature_validate_single_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern dbus_bool_t (*dbus_type_is_valid_dylibloader_wrapper_dbus)( int);
+extern dbus_bool_t (*dbus_type_is_basic_dylibloader_wrapper_dbus)( int);
+extern dbus_bool_t (*dbus_type_is_container_dylibloader_wrapper_dbus)( int);
+extern dbus_bool_t (*dbus_type_is_fixed_dylibloader_wrapper_dbus)( int);
+extern dbus_bool_t (*dbus_validate_path_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern dbus_bool_t (*dbus_validate_interface_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern dbus_bool_t (*dbus_validate_member_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern dbus_bool_t (*dbus_validate_error_name_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern dbus_bool_t (*dbus_validate_bus_name_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern dbus_bool_t (*dbus_validate_utf8_dylibloader_wrapper_dbus)(const char*, DBusError*);
+extern dbus_bool_t (*dbus_threads_init_dylibloader_wrapper_dbus)(const DBusThreadFunctions*);
+extern dbus_bool_t (*dbus_threads_init_default_dylibloader_wrapper_dbus)( void);
+int initialize_dbus(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 19cf341c85..00e2b9e6eb 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -1,6 +1,7 @@
import os
import platform
import sys
+from methods import get_compiler_version, using_gcc
def is_active():
@@ -15,47 +16,11 @@ def can_build():
if os.name != "posix" or sys.platform == "darwin":
return False
- # Check the minimal dependencies
- x11_error = os.system("pkg-config --version > /dev/null")
- if x11_error:
+ pkgconf_error = os.system("pkg-config --version > /dev/null")
+ if pkgconf_error:
print("Error: pkg-config not found. Aborting.")
return False
- x11_error = os.system("pkg-config x11 --modversion > /dev/null")
- if x11_error:
- print("Error: X11 libraries not found. Aborting.")
- return False
-
- x11_error = os.system("pkg-config xcursor --modversion > /dev/null")
- if x11_error:
- print("Error: Xcursor library not found. Aborting.")
- return False
-
- x11_error = os.system("pkg-config xinerama --modversion > /dev/null")
- if x11_error:
- print("Error: Xinerama library not found. Aborting.")
- return False
-
- x11_error = os.system("pkg-config xext --modversion > /dev/null")
- if x11_error:
- print("Error: Xext library not found. Aborting.")
- return False
-
- x11_error = os.system("pkg-config xrandr --modversion > /dev/null")
- if x11_error:
- print("Error: XrandR library not found. Aborting.")
- return False
-
- x11_error = os.system("pkg-config xrender --modversion > /dev/null")
- if x11_error:
- print("Error: XRender library not found. Aborting.")
- return False
-
- x11_error = os.system("pkg-config xi --modversion > /dev/null")
- if x11_error:
- print("Error: Xi library not found. Aborting.")
- return False
-
return True
@@ -63,9 +28,9 @@ def get_opts():
from SCons.Variables import BoolVariable, EnumVariable
return [
+ EnumVariable("linker", "Linker program", "default", ("default", "bfd", "gold", "lld", "mold")),
BoolVariable("use_llvm", "Use the LLVM compiler", False),
- BoolVariable("use_lld", "Use the LLD linker", False),
- BoolVariable("use_thinlto", "Use ThinLTO", False),
+ BoolVariable("use_thinlto", "Use ThinLTO (LLVM only, requires linker=lld, implies use_lto=yes)", False),
BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True),
BoolVariable("use_coverage", "Test Godot coverage", False),
BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False),
@@ -76,6 +41,7 @@ def get_opts():
BoolVariable("pulseaudio", "Detect and use PulseAudio", True),
BoolVariable("dbus", "Detect and use D-Bus to handle screensaver", True),
BoolVariable("speechd", "Detect and use Speech Dispatcher for Text-to-Speech support", True),
+ BoolVariable("fontconfig", "Detect and use fontconfig for system fonts support", True),
BoolVariable("udev", "Use udev for gamepad connection callbacks", True),
BoolVariable("x11", "Enable X11 display", True),
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
@@ -147,15 +113,32 @@ def configure(env):
env["CXX"] = "clang++"
env.extra_suffix = ".llvm" + env.extra_suffix
- if env["use_lld"]:
- if env["use_llvm"]:
- env.Append(LINKFLAGS=["-fuse-ld=lld"])
- if env["use_thinlto"]:
- # A convenience so you don't need to write use_lto too when using SCons
- env["use_lto"] = True
+ if env["linker"] != "default":
+ print("Using linker program: " + env["linker"])
+ if env["linker"] == "mold" and using_gcc(env): # GCC < 12.1 doesn't support -fuse-ld=mold.
+ cc_version = get_compiler_version(env)
+ cc_semver = (int(cc_version["major"]), int(cc_version["minor"]))
+ if cc_semver < (12, 1):
+ found_wrapper = False
+ for path in ["/usr/libexec", "/usr/local/libexec", "/usr/lib", "/usr/local/lib"]:
+ if os.path.isfile(path + "/mold/ld"):
+ env.Append(LINKFLAGS=["-B" + path + "/mold"])
+ found_wrapper = True
+ break
+ if not found_wrapper:
+ print("Couldn't locate mold installation path. Make sure it's installed in /usr or /usr/local.")
+ sys.exit(255)
+ else:
+ env.Append(LINKFLAGS=["-fuse-ld=mold"])
else:
- print("Using LLD with GCC is not supported yet. Try compiling with 'use_llvm=yes'.")
+ env.Append(LINKFLAGS=["-fuse-ld=%s" % env["linker"]])
+
+ if env["use_thinlto"]:
+ if not env["use_llvm"] or env["linker"] != "lld":
+ print("ThinLTO is only compatible with LLVM and the LLD linker, use `use_llvm=yes linker=lld`.")
sys.exit(255)
+ else:
+ env["use_lto"] = True # ThinLTO implies LTO
if env["use_coverage"]:
env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
@@ -200,33 +183,32 @@ def configure(env):
env.Append(LINKFLAGS=["-fsanitize=memory"])
if env["use_lto"]:
- if not env["use_llvm"] and env.GetOption("num_jobs") > 1:
+ if env["use_thinlto"]:
+ env.Append(CCFLAGS=["-flto=thin"])
+ env.Append(LINKFLAGS=["-flto=thin"])
+ elif not env["use_llvm"] and env.GetOption("num_jobs") > 1:
env.Append(CCFLAGS=["-flto"])
env.Append(LINKFLAGS=["-flto=" + str(env.GetOption("num_jobs"))])
else:
- if env["use_lld"] and env["use_thinlto"]:
- env.Append(CCFLAGS=["-flto=thin"])
- env.Append(LINKFLAGS=["-flto=thin"])
- else:
- env.Append(CCFLAGS=["-flto"])
- env.Append(LINKFLAGS=["-flto"])
+ env.Append(CCFLAGS=["-flto"])
+ env.Append(LINKFLAGS=["-flto"])
if not env["use_llvm"]:
env["RANLIB"] = "gcc-ranlib"
env["AR"] = "gcc-ar"
env.Append(CCFLAGS=["-pipe"])
- env.Append(LINKFLAGS=["-pipe"])
## Dependencies
- env.ParseConfig("pkg-config x11 --cflags --libs")
- env.ParseConfig("pkg-config xcursor --cflags --libs")
- env.ParseConfig("pkg-config xinerama --cflags --libs")
- env.ParseConfig("pkg-config xext --cflags --libs")
- env.ParseConfig("pkg-config xrandr --cflags --libs")
- env.ParseConfig("pkg-config xrender --cflags --libs")
- env.ParseConfig("pkg-config xi --cflags --libs")
+ if env["x11"]:
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ env.ParseConfig("pkg-config xcursor --cflags --libs")
+ env.ParseConfig("pkg-config xinerama --cflags --libs")
+ env.ParseConfig("pkg-config xext --cflags --libs")
+ env.ParseConfig("pkg-config xrandr --cflags --libs")
+ env.ParseConfig("pkg-config xrender --cflags --libs")
+ env.ParseConfig("pkg-config xi --cflags --libs")
if env["touch"]:
env.Append(CPPDEFINES=["TOUCH_ENABLED"])
@@ -317,6 +299,14 @@ def configure(env):
## Flags
+ if env["fontconfig"]:
+ if os.system("pkg-config --exists fontconfig") == 0: # 0 means found
+ env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
+ env.ParseConfig("pkg-config fontconfig --cflags") # Only cflags, we dlopen the library.
+ else:
+ env["fontconfig"] = False
+ print("Warning: fontconfig libraries not found. Disabling the system fonts support.")
+
if os.system("pkg-config --exists alsa") == 0: # 0 means found
env["alsa"] = True
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
@@ -335,8 +325,9 @@ def configure(env):
if env["dbus"]:
if os.system("pkg-config --exists dbus-1") == 0: # 0 means found
env.Append(CPPDEFINES=["DBUS_ENABLED"])
- env.ParseConfig("pkg-config dbus-1 --cflags --libs")
+ env.ParseConfig("pkg-config dbus-1 --cflags") # Only cflags, we dlopen the library.
else:
+ env["dbus"] = False
print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.")
if env["speechd"]:
@@ -382,8 +373,9 @@ def configure(env):
# No pkgconfig file so far, hardcode expected lib name.
env.Append(LIBS=["glslang", "SPIRV"])
- env.Append(CPPDEFINES=["GLES3_ENABLED"])
- env.ParseConfig("pkg-config gl --cflags --libs")
+ if env["opengl3"]:
+ env.Append(CPPDEFINES=["GLES3_ENABLED"])
+ env.ParseConfig("pkg-config gl --cflags --libs")
env.Append(LIBS=["pthread"])
diff --git a/platform/linuxbsd/detect_prime_x11.cpp b/platform/linuxbsd/detect_prime_x11.cpp
index 42b7f68a5e..fb833ab5e6 100644
--- a/platform/linuxbsd/detect_prime_x11.cpp
+++ b/platform/linuxbsd/detect_prime_x11.cpp
@@ -177,6 +177,11 @@ int detect_prime() {
} else {
// In child, exit() here will not quit the engine.
+ // Prevent false leak reports as we will not be properly
+ // cleaning up these processes, and fork() makes a copy
+ // of all globals.
+ CoreGlobals::leak_reporting_enabled = false;
+
char string[201];
close(fdset[0]);
diff --git a/platform/linuxbsd/detect_prime_x11.h b/platform/linuxbsd/detect_prime_x11.h
index e60f9ebfdf..21ebaead32 100644
--- a/platform/linuxbsd/detect_prime_x11.h
+++ b/platform/linuxbsd/detect_prime_x11.h
@@ -34,4 +34,5 @@
int detect_prime();
#endif
-#endif
+
+#endif // DETECT_PRIME_X11_H
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 4aec111022..3409e43ba5 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] = String(dev->name).findn("eraser") > 0;
}
XIFreeDeviceInfo(info);
@@ -1487,8 +1489,8 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
XMoveResizeWindow(x11_display, wd.x11_window, position.x, position.y, size.x, size.y);
} else {
if (p_screen != window_get_current_screen(p_window)) {
- Point2i position = screen_get_position(p_screen);
- XMoveWindow(x11_display, wd.x11_window, position.x, position.y);
+ Vector2 ofs = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window));
+ window_set_position(ofs + screen_get_position(p_screen), p_window);
}
}
}
@@ -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");
@@ -3099,7 +3147,7 @@ void DisplayServerX11::_window_changed(XEvent *event) {
Variant *rectp = &rect;
Variant ret;
Callable::CallError ce;
- wd.rect_changed_callback.call((const Variant **)&rectp, 1, ret, ce);
+ wd.rect_changed_callback.callp((const Variant **)&rectp, 1, ret, ce);
}
}
@@ -3120,7 +3168,7 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) {
if (windows.has(E->get())) {
Callable callable = windows[E->get()].input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
return;
@@ -3133,7 +3181,7 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) {
if (windows.has(event_from_window->get_window_id())) {
Callable callable = windows[event_from_window->get_window_id()].input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
} else {
@@ -3141,7 +3189,7 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) {
for (KeyValue<WindowID, WindowData> &E : windows) {
Callable callable = E.value.input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
}
@@ -3153,7 +3201,7 @@ void DisplayServerX11::_send_window_event(const WindowData &wd, WindowEvent p_ev
Variant *eventp = &event;
Variant ret;
Callable::CallError ce;
- wd.event_callback.call((const Variant **)&eventp, 1, ret, ce);
+ wd.event_callback.callp((const Variant **)&eventp, 1, ret, ce);
}
}
@@ -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());
@@ -4012,7 +4068,7 @@ void DisplayServerX11::process_events() {
Variant *vp = &v;
Variant ret;
Callable::CallError ce;
- windows[window_id].drop_files_callback.call((const Variant **)&vp, 1, ret, ce);
+ windows[window_id].drop_files_callback.callp((const Variant **)&vp, 1, ret, ce);
}
//Reply that all is well.
@@ -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..990351d13f 100644
--- a/platform/linuxbsd/export/export.cpp
+++ b/platform/linuxbsd/export/export.cpp
@@ -30,20 +30,14 @@
#include "export.h"
+#include "editor/export/editor_export.h"
#include "export_plugin.h"
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");
platform->set_os_name("Linux");
platform->set_chmod_flags(0755);
diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp
index 4e14920e79..4d45d3ba12 100644
--- a/platform/linuxbsd/export/export_plugin.cpp
+++ b/platform/linuxbsd/export/export_plugin.cpp
@@ -79,31 +79,21 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset>
return err;
}
-void EditorExportPlatformLinuxBSD::set_extension(const String &p_extension, const String &p_feature_key) {
- extensions[p_feature_key] = p_extension;
-}
-
String EditorExportPlatformLinuxBSD::get_template_file_name(const String &p_target, const String &p_arch) const {
- return "linux_x11_" + p_arch + "_" + p_target;
+ return "linux_" + p_target + "." + p_arch;
}
List<String> EditorExportPlatformLinuxBSD::get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const {
List<String> list;
- for (const KeyValue<String, String> &E : extensions) {
- if (p_preset->get(E.key)) {
- list.push_back(extensions[E.key]);
- return list;
- }
- }
-
- if (extensions.has("default")) {
- list.push_back(extensions["default"]);
- return list;
- }
-
+ list.push_back(p_preset->get("binary_format/architecture"));
return list;
}
+void EditorExportPlatformLinuxBSD::get_export_options(List<ExportOption> *r_options) {
+ EditorExportPlatformPC::get_export_options(r_options);
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32,arm64,arm32,rv64,ppc64,ppc32"), "x86_64"));
+}
+
Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
// Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data
diff --git a/platform/linuxbsd/export/export_plugin.h b/platform/linuxbsd/export/export_plugin.h
index e04bcc20f9..4d6737498b 100644
--- a/platform/linuxbsd/export/export_plugin.h
+++ b/platform/linuxbsd/export/export_plugin.h
@@ -32,21 +32,21 @@
#define LINUXBSD_EXPORT_PLUGIN_H
#include "core/io/file_access.h"
-#include "editor/editor_export.h"
#include "editor/editor_settings.h"
+#include "editor/export/editor_export_platform_pc.h"
#include "platform/linuxbsd/logo.gen.h"
#include "scene/resources/texture.h"
class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC {
- HashMap<String, String> extensions;
Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path);
public:
void set_extension(const String &p_extension, const String &p_feature_key = "default");
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
+ virtual void get_export_options(List<ExportOption> *r_options) override;
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
virtual String get_template_file_name(const String &p_target, const String &p_arch) const override;
virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override;
};
-#endif
+#endif // LINUXBSD_EXPORT_PLUGIN_H
diff --git a/platform/linuxbsd/fontconfig-so_wrap.c b/platform/linuxbsd/fontconfig-so_wrap.c
new file mode 100644
index 0000000000..1a915faf98
--- /dev/null
+++ b/platform/linuxbsd/fontconfig-so_wrap.c
@@ -0,0 +1,2091 @@
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by ./generate-wrapper.py 0.3 on 2022-07-29 05:40:07
+// flags: ./generate-wrapper.py --include /usr/include/fontconfig/fontconfig.h --sys-include <fontconfig/fontconfig.h> --soname libfontconfig.so --init-name fontconfig --output-header fontconfig-so_wrap.h --output-implementation fontconfig-so_wrap.c --omit-prefix FcCharSet
+//
+#include <stdint.h>
+
+#define FcBlanksCreate FcBlanksCreate_dylibloader_orig_fontconfig
+#define FcBlanksDestroy FcBlanksDestroy_dylibloader_orig_fontconfig
+#define FcBlanksAdd FcBlanksAdd_dylibloader_orig_fontconfig
+#define FcBlanksIsMember FcBlanksIsMember_dylibloader_orig_fontconfig
+#define FcCacheDir FcCacheDir_dylibloader_orig_fontconfig
+#define FcCacheCopySet FcCacheCopySet_dylibloader_orig_fontconfig
+#define FcCacheSubdir FcCacheSubdir_dylibloader_orig_fontconfig
+#define FcCacheNumSubdir FcCacheNumSubdir_dylibloader_orig_fontconfig
+#define FcCacheNumFont FcCacheNumFont_dylibloader_orig_fontconfig
+#define FcDirCacheUnlink FcDirCacheUnlink_dylibloader_orig_fontconfig
+#define FcDirCacheValid FcDirCacheValid_dylibloader_orig_fontconfig
+#define FcDirCacheClean FcDirCacheClean_dylibloader_orig_fontconfig
+#define FcCacheCreateTagFile FcCacheCreateTagFile_dylibloader_orig_fontconfig
+#define FcConfigHome FcConfigHome_dylibloader_orig_fontconfig
+#define FcConfigEnableHome FcConfigEnableHome_dylibloader_orig_fontconfig
+#define FcConfigFilename FcConfigFilename_dylibloader_orig_fontconfig
+#define FcConfigCreate FcConfigCreate_dylibloader_orig_fontconfig
+#define FcConfigReference FcConfigReference_dylibloader_orig_fontconfig
+#define FcConfigDestroy FcConfigDestroy_dylibloader_orig_fontconfig
+#define FcConfigSetCurrent FcConfigSetCurrent_dylibloader_orig_fontconfig
+#define FcConfigGetCurrent FcConfigGetCurrent_dylibloader_orig_fontconfig
+#define FcConfigUptoDate FcConfigUptoDate_dylibloader_orig_fontconfig
+#define FcConfigBuildFonts FcConfigBuildFonts_dylibloader_orig_fontconfig
+#define FcConfigGetFontDirs FcConfigGetFontDirs_dylibloader_orig_fontconfig
+#define FcConfigGetConfigDirs FcConfigGetConfigDirs_dylibloader_orig_fontconfig
+#define FcConfigGetConfigFiles FcConfigGetConfigFiles_dylibloader_orig_fontconfig
+#define FcConfigGetCache FcConfigGetCache_dylibloader_orig_fontconfig
+#define FcConfigGetBlanks FcConfigGetBlanks_dylibloader_orig_fontconfig
+#define FcConfigGetCacheDirs FcConfigGetCacheDirs_dylibloader_orig_fontconfig
+#define FcConfigGetRescanInterval FcConfigGetRescanInterval_dylibloader_orig_fontconfig
+#define FcConfigSetRescanInterval FcConfigSetRescanInterval_dylibloader_orig_fontconfig
+#define FcConfigGetFonts FcConfigGetFonts_dylibloader_orig_fontconfig
+#define FcConfigAppFontAddFile FcConfigAppFontAddFile_dylibloader_orig_fontconfig
+#define FcConfigAppFontAddDir FcConfigAppFontAddDir_dylibloader_orig_fontconfig
+#define FcConfigAppFontClear FcConfigAppFontClear_dylibloader_orig_fontconfig
+#define FcConfigSubstituteWithPat FcConfigSubstituteWithPat_dylibloader_orig_fontconfig
+#define FcConfigSubstitute FcConfigSubstitute_dylibloader_orig_fontconfig
+#define FcConfigGetSysRoot FcConfigGetSysRoot_dylibloader_orig_fontconfig
+#define FcConfigSetSysRoot FcConfigSetSysRoot_dylibloader_orig_fontconfig
+#define FcValuePrint FcValuePrint_dylibloader_orig_fontconfig
+#define FcPatternPrint FcPatternPrint_dylibloader_orig_fontconfig
+#define FcFontSetPrint FcFontSetPrint_dylibloader_orig_fontconfig
+#define FcGetDefaultLangs FcGetDefaultLangs_dylibloader_orig_fontconfig
+#define FcDefaultSubstitute FcDefaultSubstitute_dylibloader_orig_fontconfig
+#define FcFileIsDir FcFileIsDir_dylibloader_orig_fontconfig
+#define FcFileScan FcFileScan_dylibloader_orig_fontconfig
+#define FcDirScan FcDirScan_dylibloader_orig_fontconfig
+#define FcDirSave FcDirSave_dylibloader_orig_fontconfig
+#define FcDirCacheLoad FcDirCacheLoad_dylibloader_orig_fontconfig
+#define FcDirCacheRescan FcDirCacheRescan_dylibloader_orig_fontconfig
+#define FcDirCacheRead FcDirCacheRead_dylibloader_orig_fontconfig
+#define FcDirCacheLoadFile FcDirCacheLoadFile_dylibloader_orig_fontconfig
+#define FcDirCacheUnload FcDirCacheUnload_dylibloader_orig_fontconfig
+#define FcFreeTypeQuery FcFreeTypeQuery_dylibloader_orig_fontconfig
+#define FcFontSetCreate FcFontSetCreate_dylibloader_orig_fontconfig
+#define FcFontSetDestroy FcFontSetDestroy_dylibloader_orig_fontconfig
+#define FcFontSetAdd FcFontSetAdd_dylibloader_orig_fontconfig
+#define FcInitLoadConfig FcInitLoadConfig_dylibloader_orig_fontconfig
+#define FcInitLoadConfigAndFonts FcInitLoadConfigAndFonts_dylibloader_orig_fontconfig
+#define FcInit FcInit_dylibloader_orig_fontconfig
+#define FcFini FcFini_dylibloader_orig_fontconfig
+#define FcGetVersion FcGetVersion_dylibloader_orig_fontconfig
+#define FcInitReinitialize FcInitReinitialize_dylibloader_orig_fontconfig
+#define FcInitBringUptoDate FcInitBringUptoDate_dylibloader_orig_fontconfig
+#define FcGetLangs FcGetLangs_dylibloader_orig_fontconfig
+#define FcLangNormalize FcLangNormalize_dylibloader_orig_fontconfig
+#define FcLangGetCharSet FcLangGetCharSet_dylibloader_orig_fontconfig
+#define FcLangSetCreate FcLangSetCreate_dylibloader_orig_fontconfig
+#define FcLangSetDestroy FcLangSetDestroy_dylibloader_orig_fontconfig
+#define FcLangSetCopy FcLangSetCopy_dylibloader_orig_fontconfig
+#define FcLangSetAdd FcLangSetAdd_dylibloader_orig_fontconfig
+#define FcLangSetDel FcLangSetDel_dylibloader_orig_fontconfig
+#define FcLangSetHasLang FcLangSetHasLang_dylibloader_orig_fontconfig
+#define FcLangSetCompare FcLangSetCompare_dylibloader_orig_fontconfig
+#define FcLangSetContains FcLangSetContains_dylibloader_orig_fontconfig
+#define FcLangSetEqual FcLangSetEqual_dylibloader_orig_fontconfig
+#define FcLangSetHash FcLangSetHash_dylibloader_orig_fontconfig
+#define FcLangSetGetLangs FcLangSetGetLangs_dylibloader_orig_fontconfig
+#define FcLangSetUnion FcLangSetUnion_dylibloader_orig_fontconfig
+#define FcLangSetSubtract FcLangSetSubtract_dylibloader_orig_fontconfig
+#define FcObjectSetCreate FcObjectSetCreate_dylibloader_orig_fontconfig
+#define FcObjectSetAdd FcObjectSetAdd_dylibloader_orig_fontconfig
+#define FcObjectSetDestroy FcObjectSetDestroy_dylibloader_orig_fontconfig
+#define FcObjectSetVaBuild FcObjectSetVaBuild_dylibloader_orig_fontconfig
+#define FcObjectSetBuild FcObjectSetBuild_dylibloader_orig_fontconfig
+#define FcFontSetList FcFontSetList_dylibloader_orig_fontconfig
+#define FcFontList FcFontList_dylibloader_orig_fontconfig
+#define FcAtomicCreate FcAtomicCreate_dylibloader_orig_fontconfig
+#define FcAtomicLock FcAtomicLock_dylibloader_orig_fontconfig
+#define FcAtomicNewFile FcAtomicNewFile_dylibloader_orig_fontconfig
+#define FcAtomicOrigFile FcAtomicOrigFile_dylibloader_orig_fontconfig
+#define FcAtomicReplaceOrig FcAtomicReplaceOrig_dylibloader_orig_fontconfig
+#define FcAtomicDeleteNew FcAtomicDeleteNew_dylibloader_orig_fontconfig
+#define FcAtomicUnlock FcAtomicUnlock_dylibloader_orig_fontconfig
+#define FcAtomicDestroy FcAtomicDestroy_dylibloader_orig_fontconfig
+#define FcFontSetMatch FcFontSetMatch_dylibloader_orig_fontconfig
+#define FcFontMatch FcFontMatch_dylibloader_orig_fontconfig
+#define FcFontRenderPrepare FcFontRenderPrepare_dylibloader_orig_fontconfig
+#define FcFontSetSort FcFontSetSort_dylibloader_orig_fontconfig
+#define FcFontSort FcFontSort_dylibloader_orig_fontconfig
+#define FcFontSetSortDestroy FcFontSetSortDestroy_dylibloader_orig_fontconfig
+#define FcMatrixCopy FcMatrixCopy_dylibloader_orig_fontconfig
+#define FcMatrixEqual FcMatrixEqual_dylibloader_orig_fontconfig
+#define FcMatrixMultiply FcMatrixMultiply_dylibloader_orig_fontconfig
+#define FcMatrixRotate FcMatrixRotate_dylibloader_orig_fontconfig
+#define FcMatrixScale FcMatrixScale_dylibloader_orig_fontconfig
+#define FcMatrixShear FcMatrixShear_dylibloader_orig_fontconfig
+#define FcNameRegisterObjectTypes FcNameRegisterObjectTypes_dylibloader_orig_fontconfig
+#define FcNameUnregisterObjectTypes FcNameUnregisterObjectTypes_dylibloader_orig_fontconfig
+#define FcNameGetObjectType FcNameGetObjectType_dylibloader_orig_fontconfig
+#define FcNameRegisterConstants FcNameRegisterConstants_dylibloader_orig_fontconfig
+#define FcNameUnregisterConstants FcNameUnregisterConstants_dylibloader_orig_fontconfig
+#define FcNameGetConstant FcNameGetConstant_dylibloader_orig_fontconfig
+#define FcNameConstant FcNameConstant_dylibloader_orig_fontconfig
+#define FcNameParse FcNameParse_dylibloader_orig_fontconfig
+#define FcNameUnparse FcNameUnparse_dylibloader_orig_fontconfig
+#define FcPatternCreate FcPatternCreate_dylibloader_orig_fontconfig
+#define FcPatternDuplicate FcPatternDuplicate_dylibloader_orig_fontconfig
+#define FcPatternReference FcPatternReference_dylibloader_orig_fontconfig
+#define FcPatternFilter FcPatternFilter_dylibloader_orig_fontconfig
+#define FcValueDestroy FcValueDestroy_dylibloader_orig_fontconfig
+#define FcValueEqual FcValueEqual_dylibloader_orig_fontconfig
+#define FcValueSave FcValueSave_dylibloader_orig_fontconfig
+#define FcPatternDestroy FcPatternDestroy_dylibloader_orig_fontconfig
+#define FcPatternEqual FcPatternEqual_dylibloader_orig_fontconfig
+#define FcPatternEqualSubset FcPatternEqualSubset_dylibloader_orig_fontconfig
+#define FcPatternHash FcPatternHash_dylibloader_orig_fontconfig
+#define FcPatternAdd FcPatternAdd_dylibloader_orig_fontconfig
+#define FcPatternAddWeak FcPatternAddWeak_dylibloader_orig_fontconfig
+#define FcPatternGet FcPatternGet_dylibloader_orig_fontconfig
+#define FcPatternGetWithBinding FcPatternGetWithBinding_dylibloader_orig_fontconfig
+#define FcPatternDel FcPatternDel_dylibloader_orig_fontconfig
+#define FcPatternRemove FcPatternRemove_dylibloader_orig_fontconfig
+#define FcPatternAddInteger FcPatternAddInteger_dylibloader_orig_fontconfig
+#define FcPatternAddDouble FcPatternAddDouble_dylibloader_orig_fontconfig
+#define FcPatternAddString FcPatternAddString_dylibloader_orig_fontconfig
+#define FcPatternAddMatrix FcPatternAddMatrix_dylibloader_orig_fontconfig
+#define FcPatternAddCharSet FcPatternAddCharSet_dylibloader_orig_fontconfig
+#define FcPatternAddBool FcPatternAddBool_dylibloader_orig_fontconfig
+#define FcPatternAddLangSet FcPatternAddLangSet_dylibloader_orig_fontconfig
+#define FcPatternAddRange FcPatternAddRange_dylibloader_orig_fontconfig
+#define FcPatternGetInteger FcPatternGetInteger_dylibloader_orig_fontconfig
+#define FcPatternGetDouble FcPatternGetDouble_dylibloader_orig_fontconfig
+#define FcPatternGetString FcPatternGetString_dylibloader_orig_fontconfig
+#define FcPatternGetMatrix FcPatternGetMatrix_dylibloader_orig_fontconfig
+#define FcPatternGetCharSet FcPatternGetCharSet_dylibloader_orig_fontconfig
+#define FcPatternGetBool FcPatternGetBool_dylibloader_orig_fontconfig
+#define FcPatternGetLangSet FcPatternGetLangSet_dylibloader_orig_fontconfig
+#define FcPatternGetRange FcPatternGetRange_dylibloader_orig_fontconfig
+#define FcPatternVaBuild FcPatternVaBuild_dylibloader_orig_fontconfig
+#define FcPatternBuild FcPatternBuild_dylibloader_orig_fontconfig
+#define FcPatternFormat FcPatternFormat_dylibloader_orig_fontconfig
+#define FcRangeCreateDouble FcRangeCreateDouble_dylibloader_orig_fontconfig
+#define FcRangeCreateInteger FcRangeCreateInteger_dylibloader_orig_fontconfig
+#define FcRangeDestroy FcRangeDestroy_dylibloader_orig_fontconfig
+#define FcRangeCopy FcRangeCopy_dylibloader_orig_fontconfig
+#define FcRangeGetDouble FcRangeGetDouble_dylibloader_orig_fontconfig
+#define FcWeightFromOpenType FcWeightFromOpenType_dylibloader_orig_fontconfig
+#define FcWeightToOpenType FcWeightToOpenType_dylibloader_orig_fontconfig
+#define FcStrCopy FcStrCopy_dylibloader_orig_fontconfig
+#define FcStrCopyFilename FcStrCopyFilename_dylibloader_orig_fontconfig
+#define FcStrPlus FcStrPlus_dylibloader_orig_fontconfig
+#define FcStrFree FcStrFree_dylibloader_orig_fontconfig
+#define FcStrDowncase FcStrDowncase_dylibloader_orig_fontconfig
+#define FcStrCmpIgnoreCase FcStrCmpIgnoreCase_dylibloader_orig_fontconfig
+#define FcStrCmp FcStrCmp_dylibloader_orig_fontconfig
+#define FcStrStrIgnoreCase FcStrStrIgnoreCase_dylibloader_orig_fontconfig
+#define FcStrStr FcStrStr_dylibloader_orig_fontconfig
+#define FcUtf8ToUcs4 FcUtf8ToUcs4_dylibloader_orig_fontconfig
+#define FcUtf8Len FcUtf8Len_dylibloader_orig_fontconfig
+#define FcUcs4ToUtf8 FcUcs4ToUtf8_dylibloader_orig_fontconfig
+#define FcUtf16ToUcs4 FcUtf16ToUcs4_dylibloader_orig_fontconfig
+#define FcUtf16Len FcUtf16Len_dylibloader_orig_fontconfig
+#define FcStrDirname FcStrDirname_dylibloader_orig_fontconfig
+#define FcStrBasename FcStrBasename_dylibloader_orig_fontconfig
+#define FcStrSetCreate FcStrSetCreate_dylibloader_orig_fontconfig
+#define FcStrSetMember FcStrSetMember_dylibloader_orig_fontconfig
+#define FcStrSetEqual FcStrSetEqual_dylibloader_orig_fontconfig
+#define FcStrSetAdd FcStrSetAdd_dylibloader_orig_fontconfig
+#define FcStrSetAddFilename FcStrSetAddFilename_dylibloader_orig_fontconfig
+#define FcStrSetDel FcStrSetDel_dylibloader_orig_fontconfig
+#define FcStrSetDestroy FcStrSetDestroy_dylibloader_orig_fontconfig
+#define FcStrListCreate FcStrListCreate_dylibloader_orig_fontconfig
+#define FcStrListFirst FcStrListFirst_dylibloader_orig_fontconfig
+#define FcStrListNext FcStrListNext_dylibloader_orig_fontconfig
+#define FcStrListDone FcStrListDone_dylibloader_orig_fontconfig
+#define FcConfigParseAndLoad FcConfigParseAndLoad_dylibloader_orig_fontconfig
+#define FcConfigParseAndLoadFromMemory FcConfigParseAndLoadFromMemory_dylibloader_orig_fontconfig
+#include <fontconfig/fontconfig.h>
+#undef FcBlanksCreate
+#undef FcBlanksDestroy
+#undef FcBlanksAdd
+#undef FcBlanksIsMember
+#undef FcCacheDir
+#undef FcCacheCopySet
+#undef FcCacheSubdir
+#undef FcCacheNumSubdir
+#undef FcCacheNumFont
+#undef FcDirCacheUnlink
+#undef FcDirCacheValid
+#undef FcDirCacheClean
+#undef FcCacheCreateTagFile
+#undef FcConfigHome
+#undef FcConfigEnableHome
+#undef FcConfigFilename
+#undef FcConfigCreate
+#undef FcConfigReference
+#undef FcConfigDestroy
+#undef FcConfigSetCurrent
+#undef FcConfigGetCurrent
+#undef FcConfigUptoDate
+#undef FcConfigBuildFonts
+#undef FcConfigGetFontDirs
+#undef FcConfigGetConfigDirs
+#undef FcConfigGetConfigFiles
+#undef FcConfigGetCache
+#undef FcConfigGetBlanks
+#undef FcConfigGetCacheDirs
+#undef FcConfigGetRescanInterval
+#undef FcConfigSetRescanInterval
+#undef FcConfigGetFonts
+#undef FcConfigAppFontAddFile
+#undef FcConfigAppFontAddDir
+#undef FcConfigAppFontClear
+#undef FcConfigSubstituteWithPat
+#undef FcConfigSubstitute
+#undef FcConfigGetSysRoot
+#undef FcConfigSetSysRoot
+#undef FcValuePrint
+#undef FcPatternPrint
+#undef FcFontSetPrint
+#undef FcGetDefaultLangs
+#undef FcDefaultSubstitute
+#undef FcFileIsDir
+#undef FcFileScan
+#undef FcDirScan
+#undef FcDirSave
+#undef FcDirCacheLoad
+#undef FcDirCacheRescan
+#undef FcDirCacheRead
+#undef FcDirCacheLoadFile
+#undef FcDirCacheUnload
+#undef FcFreeTypeQuery
+#undef FcFontSetCreate
+#undef FcFontSetDestroy
+#undef FcFontSetAdd
+#undef FcInitLoadConfig
+#undef FcInitLoadConfigAndFonts
+#undef FcInit
+#undef FcFini
+#undef FcGetVersion
+#undef FcInitReinitialize
+#undef FcInitBringUptoDate
+#undef FcGetLangs
+#undef FcLangNormalize
+#undef FcLangGetCharSet
+#undef FcLangSetCreate
+#undef FcLangSetDestroy
+#undef FcLangSetCopy
+#undef FcLangSetAdd
+#undef FcLangSetDel
+#undef FcLangSetHasLang
+#undef FcLangSetCompare
+#undef FcLangSetContains
+#undef FcLangSetEqual
+#undef FcLangSetHash
+#undef FcLangSetGetLangs
+#undef FcLangSetUnion
+#undef FcLangSetSubtract
+#undef FcObjectSetCreate
+#undef FcObjectSetAdd
+#undef FcObjectSetDestroy
+#undef FcObjectSetVaBuild
+#undef FcObjectSetBuild
+#undef FcFontSetList
+#undef FcFontList
+#undef FcAtomicCreate
+#undef FcAtomicLock
+#undef FcAtomicNewFile
+#undef FcAtomicOrigFile
+#undef FcAtomicReplaceOrig
+#undef FcAtomicDeleteNew
+#undef FcAtomicUnlock
+#undef FcAtomicDestroy
+#undef FcFontSetMatch
+#undef FcFontMatch
+#undef FcFontRenderPrepare
+#undef FcFontSetSort
+#undef FcFontSort
+#undef FcFontSetSortDestroy
+#undef FcMatrixCopy
+#undef FcMatrixEqual
+#undef FcMatrixMultiply
+#undef FcMatrixRotate
+#undef FcMatrixScale
+#undef FcMatrixShear
+#undef FcNameRegisterObjectTypes
+#undef FcNameUnregisterObjectTypes
+#undef FcNameGetObjectType
+#undef FcNameRegisterConstants
+#undef FcNameUnregisterConstants
+#undef FcNameGetConstant
+#undef FcNameConstant
+#undef FcNameParse
+#undef FcNameUnparse
+#undef FcPatternCreate
+#undef FcPatternDuplicate
+#undef FcPatternReference
+#undef FcPatternFilter
+#undef FcValueDestroy
+#undef FcValueEqual
+#undef FcValueSave
+#undef FcPatternDestroy
+#undef FcPatternEqual
+#undef FcPatternEqualSubset
+#undef FcPatternHash
+#undef FcPatternAdd
+#undef FcPatternAddWeak
+#undef FcPatternGet
+#undef FcPatternGetWithBinding
+#undef FcPatternDel
+#undef FcPatternRemove
+#undef FcPatternAddInteger
+#undef FcPatternAddDouble
+#undef FcPatternAddString
+#undef FcPatternAddMatrix
+#undef FcPatternAddCharSet
+#undef FcPatternAddBool
+#undef FcPatternAddLangSet
+#undef FcPatternAddRange
+#undef FcPatternGetInteger
+#undef FcPatternGetDouble
+#undef FcPatternGetString
+#undef FcPatternGetMatrix
+#undef FcPatternGetCharSet
+#undef FcPatternGetBool
+#undef FcPatternGetLangSet
+#undef FcPatternGetRange
+#undef FcPatternVaBuild
+#undef FcPatternBuild
+#undef FcPatternFormat
+#undef FcRangeCreateDouble
+#undef FcRangeCreateInteger
+#undef FcRangeDestroy
+#undef FcRangeCopy
+#undef FcRangeGetDouble
+#undef FcWeightFromOpenType
+#undef FcWeightToOpenType
+#undef FcStrCopy
+#undef FcStrCopyFilename
+#undef FcStrPlus
+#undef FcStrFree
+#undef FcStrDowncase
+#undef FcStrCmpIgnoreCase
+#undef FcStrCmp
+#undef FcStrStrIgnoreCase
+#undef FcStrStr
+#undef FcUtf8ToUcs4
+#undef FcUtf8Len
+#undef FcUcs4ToUtf8
+#undef FcUtf16ToUcs4
+#undef FcUtf16Len
+#undef FcStrDirname
+#undef FcStrBasename
+#undef FcStrSetCreate
+#undef FcStrSetMember
+#undef FcStrSetEqual
+#undef FcStrSetAdd
+#undef FcStrSetAddFilename
+#undef FcStrSetDel
+#undef FcStrSetDestroy
+#undef FcStrListCreate
+#undef FcStrListFirst
+#undef FcStrListNext
+#undef FcStrListDone
+#undef FcConfigParseAndLoad
+#undef FcConfigParseAndLoadFromMemory
+#include <dlfcn.h>
+#include <stdio.h>
+FcBlanks* (*FcBlanksCreate_dylibloader_wrapper_fontconfig)( void);
+void (*FcBlanksDestroy_dylibloader_wrapper_fontconfig)( FcBlanks*);
+FcBool (*FcBlanksAdd_dylibloader_wrapper_fontconfig)( FcBlanks*, FcChar32);
+FcBool (*FcBlanksIsMember_dylibloader_wrapper_fontconfig)( FcBlanks*, FcChar32);
+const FcChar8* (*FcCacheDir_dylibloader_wrapper_fontconfig)(const FcCache*);
+FcFontSet* (*FcCacheCopySet_dylibloader_wrapper_fontconfig)(const FcCache*);
+const FcChar8* (*FcCacheSubdir_dylibloader_wrapper_fontconfig)(const FcCache*, int);
+int (*FcCacheNumSubdir_dylibloader_wrapper_fontconfig)(const FcCache*);
+int (*FcCacheNumFont_dylibloader_wrapper_fontconfig)(const FcCache*);
+FcBool (*FcDirCacheUnlink_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*);
+FcBool (*FcDirCacheValid_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcBool (*FcDirCacheClean_dylibloader_wrapper_fontconfig)(const FcChar8*, FcBool);
+void (*FcCacheCreateTagFile_dylibloader_wrapper_fontconfig)(const FcConfig*);
+FcChar8* (*FcConfigHome_dylibloader_wrapper_fontconfig)( void);
+FcBool (*FcConfigEnableHome_dylibloader_wrapper_fontconfig)( FcBool);
+FcChar8* (*FcConfigFilename_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcConfig* (*FcConfigCreate_dylibloader_wrapper_fontconfig)( void);
+FcConfig* (*FcConfigReference_dylibloader_wrapper_fontconfig)( FcConfig*);
+void (*FcConfigDestroy_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcBool (*FcConfigSetCurrent_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcConfig* (*FcConfigGetCurrent_dylibloader_wrapper_fontconfig)( void);
+FcBool (*FcConfigUptoDate_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcBool (*FcConfigBuildFonts_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcStrList* (*FcConfigGetFontDirs_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcStrList* (*FcConfigGetConfigDirs_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcStrList* (*FcConfigGetConfigFiles_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcChar8* (*FcConfigGetCache_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcBlanks* (*FcConfigGetBlanks_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcStrList* (*FcConfigGetCacheDirs_dylibloader_wrapper_fontconfig)(const FcConfig*);
+int (*FcConfigGetRescanInterval_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcBool (*FcConfigSetRescanInterval_dylibloader_wrapper_fontconfig)( FcConfig*, int);
+FcFontSet* (*FcConfigGetFonts_dylibloader_wrapper_fontconfig)( FcConfig*, FcSetName);
+FcBool (*FcConfigAppFontAddFile_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*);
+FcBool (*FcConfigAppFontAddDir_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*);
+void (*FcConfigAppFontClear_dylibloader_wrapper_fontconfig)( FcConfig*);
+FcBool (*FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcPattern*, FcMatchKind);
+FcBool (*FcConfigSubstitute_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcMatchKind);
+const FcChar8* (*FcConfigGetSysRoot_dylibloader_wrapper_fontconfig)(const FcConfig*);
+void (*FcConfigSetSysRoot_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*);
+void (*FcValuePrint_dylibloader_wrapper_fontconfig)(const FcValue);
+void (*FcPatternPrint_dylibloader_wrapper_fontconfig)(const FcPattern*);
+void (*FcFontSetPrint_dylibloader_wrapper_fontconfig)(const FcFontSet*);
+FcStrSet* (*FcGetDefaultLangs_dylibloader_wrapper_fontconfig)( void);
+void (*FcDefaultSubstitute_dylibloader_wrapper_fontconfig)( FcPattern*);
+FcBool (*FcFileIsDir_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcBool (*FcFileScan_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*, FcFileCache*, FcBlanks*,const FcChar8*, FcBool);
+FcBool (*FcDirScan_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*, FcFileCache*, FcBlanks*,const FcChar8*, FcBool);
+FcBool (*FcDirSave_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*,const FcChar8*);
+FcCache* (*FcDirCacheLoad_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*, FcChar8**);
+FcCache* (*FcDirCacheRescan_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*);
+FcCache* (*FcDirCacheRead_dylibloader_wrapper_fontconfig)(const FcChar8*, FcBool, FcConfig*);
+FcCache* (*FcDirCacheLoadFile_dylibloader_wrapper_fontconfig)(const FcChar8*,struct stat*);
+void (*FcDirCacheUnload_dylibloader_wrapper_fontconfig)( FcCache*);
+FcPattern* (*FcFreeTypeQuery_dylibloader_wrapper_fontconfig)(const FcChar8*, int, FcBlanks*, int*);
+FcFontSet* (*FcFontSetCreate_dylibloader_wrapper_fontconfig)( void);
+void (*FcFontSetDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*);
+FcBool (*FcFontSetAdd_dylibloader_wrapper_fontconfig)( FcFontSet*, FcPattern*);
+FcConfig* (*FcInitLoadConfig_dylibloader_wrapper_fontconfig)( void);
+FcConfig* (*FcInitLoadConfigAndFonts_dylibloader_wrapper_fontconfig)( void);
+FcBool (*FcInit_dylibloader_wrapper_fontconfig)( void);
+void (*FcFini_dylibloader_wrapper_fontconfig)( void);
+int (*FcGetVersion_dylibloader_wrapper_fontconfig)( void);
+FcBool (*FcInitReinitialize_dylibloader_wrapper_fontconfig)( void);
+FcBool (*FcInitBringUptoDate_dylibloader_wrapper_fontconfig)( void);
+FcStrSet* (*FcGetLangs_dylibloader_wrapper_fontconfig)( void);
+FcChar8* (*FcLangNormalize_dylibloader_wrapper_fontconfig)(const FcChar8*);
+const FcCharSet* (*FcLangGetCharSet_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcLangSet* (*FcLangSetCreate_dylibloader_wrapper_fontconfig)( void);
+void (*FcLangSetDestroy_dylibloader_wrapper_fontconfig)( FcLangSet*);
+FcLangSet* (*FcLangSetCopy_dylibloader_wrapper_fontconfig)(const FcLangSet*);
+FcBool (*FcLangSetAdd_dylibloader_wrapper_fontconfig)( FcLangSet*,const FcChar8*);
+FcBool (*FcLangSetDel_dylibloader_wrapper_fontconfig)( FcLangSet*,const FcChar8*);
+FcLangResult (*FcLangSetHasLang_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcChar8*);
+FcLangResult (*FcLangSetCompare_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+FcBool (*FcLangSetContains_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+FcBool (*FcLangSetEqual_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+FcChar32 (*FcLangSetHash_dylibloader_wrapper_fontconfig)(const FcLangSet*);
+FcStrSet* (*FcLangSetGetLangs_dylibloader_wrapper_fontconfig)(const FcLangSet*);
+FcLangSet* (*FcLangSetUnion_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+FcLangSet* (*FcLangSetSubtract_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+FcObjectSet* (*FcObjectSetCreate_dylibloader_wrapper_fontconfig)( void);
+FcBool (*FcObjectSetAdd_dylibloader_wrapper_fontconfig)( FcObjectSet*,const char*);
+void (*FcObjectSetDestroy_dylibloader_wrapper_fontconfig)( FcObjectSet*);
+FcObjectSet* (*FcObjectSetVaBuild_dylibloader_wrapper_fontconfig)(const char*, va_list);
+FcObjectSet* (*FcObjectSetBuild_dylibloader_wrapper_fontconfig)(const char*,...);
+FcFontSet* (*FcFontSetList_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcObjectSet*);
+FcFontSet* (*FcFontList_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcObjectSet*);
+FcAtomic* (*FcAtomicCreate_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcBool (*FcAtomicLock_dylibloader_wrapper_fontconfig)( FcAtomic*);
+FcChar8* (*FcAtomicNewFile_dylibloader_wrapper_fontconfig)( FcAtomic*);
+FcChar8* (*FcAtomicOrigFile_dylibloader_wrapper_fontconfig)( FcAtomic*);
+FcBool (*FcAtomicReplaceOrig_dylibloader_wrapper_fontconfig)( FcAtomic*);
+void (*FcAtomicDeleteNew_dylibloader_wrapper_fontconfig)( FcAtomic*);
+void (*FcAtomicUnlock_dylibloader_wrapper_fontconfig)( FcAtomic*);
+void (*FcAtomicDestroy_dylibloader_wrapper_fontconfig)( FcAtomic*);
+FcPattern* (*FcFontSetMatch_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcResult*);
+FcPattern* (*FcFontMatch_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcResult*);
+FcPattern* (*FcFontRenderPrepare_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcPattern*);
+FcFontSet* (*FcFontSetSort_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcBool, FcCharSet**, FcResult*);
+FcFontSet* (*FcFontSort_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcBool, FcCharSet**, FcResult*);
+void (*FcFontSetSortDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*);
+FcMatrix* (*FcMatrixCopy_dylibloader_wrapper_fontconfig)(const FcMatrix*);
+FcBool (*FcMatrixEqual_dylibloader_wrapper_fontconfig)(const FcMatrix*,const FcMatrix*);
+void (*FcMatrixMultiply_dylibloader_wrapper_fontconfig)( FcMatrix*,const FcMatrix*,const FcMatrix*);
+void (*FcMatrixRotate_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double);
+void (*FcMatrixScale_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double);
+void (*FcMatrixShear_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double);
+FcBool (*FcNameRegisterObjectTypes_dylibloader_wrapper_fontconfig)(const FcObjectType*, int);
+FcBool (*FcNameUnregisterObjectTypes_dylibloader_wrapper_fontconfig)(const FcObjectType*, int);
+const FcObjectType* (*FcNameGetObjectType_dylibloader_wrapper_fontconfig)(const char*);
+FcBool (*FcNameRegisterConstants_dylibloader_wrapper_fontconfig)(const FcConstant*, int);
+FcBool (*FcNameUnregisterConstants_dylibloader_wrapper_fontconfig)(const FcConstant*, int);
+const FcConstant* (*FcNameGetConstant_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcBool (*FcNameConstant_dylibloader_wrapper_fontconfig)(const FcChar8*, int*);
+FcPattern* (*FcNameParse_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcChar8* (*FcNameUnparse_dylibloader_wrapper_fontconfig)( FcPattern*);
+FcPattern* (*FcPatternCreate_dylibloader_wrapper_fontconfig)( void);
+FcPattern* (*FcPatternDuplicate_dylibloader_wrapper_fontconfig)(const FcPattern*);
+void (*FcPatternReference_dylibloader_wrapper_fontconfig)( FcPattern*);
+FcPattern* (*FcPatternFilter_dylibloader_wrapper_fontconfig)( FcPattern*,const FcObjectSet*);
+void (*FcValueDestroy_dylibloader_wrapper_fontconfig)( FcValue);
+FcBool (*FcValueEqual_dylibloader_wrapper_fontconfig)( FcValue, FcValue);
+FcValue (*FcValueSave_dylibloader_wrapper_fontconfig)( FcValue);
+void (*FcPatternDestroy_dylibloader_wrapper_fontconfig)( FcPattern*);
+FcBool (*FcPatternEqual_dylibloader_wrapper_fontconfig)(const FcPattern*,const FcPattern*);
+FcBool (*FcPatternEqualSubset_dylibloader_wrapper_fontconfig)(const FcPattern*,const FcPattern*,const FcObjectSet*);
+FcChar32 (*FcPatternHash_dylibloader_wrapper_fontconfig)(const FcPattern*);
+FcBool (*FcPatternAdd_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcValue, FcBool);
+FcBool (*FcPatternAddWeak_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcValue, FcBool);
+FcResult (*FcPatternGet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcValue*);
+FcResult (*FcPatternGetWithBinding_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcValue*, FcValueBinding*);
+FcBool (*FcPatternDel_dylibloader_wrapper_fontconfig)( FcPattern*,const char*);
+FcBool (*FcPatternRemove_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, int);
+FcBool (*FcPatternAddInteger_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, int);
+FcBool (*FcPatternAddDouble_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, double);
+FcBool (*FcPatternAddString_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcChar8*);
+FcBool (*FcPatternAddMatrix_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcMatrix*);
+FcBool (*FcPatternAddCharSet_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcCharSet*);
+FcBool (*FcPatternAddBool_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcBool);
+FcBool (*FcPatternAddLangSet_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcLangSet*);
+FcBool (*FcPatternAddRange_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcRange*);
+FcResult (*FcPatternGetInteger_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, int*);
+FcResult (*FcPatternGetDouble_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, double*);
+FcResult (*FcPatternGetString_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcChar8**);
+FcResult (*FcPatternGetMatrix_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcMatrix**);
+FcResult (*FcPatternGetCharSet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcCharSet**);
+FcResult (*FcPatternGetBool_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcBool*);
+FcResult (*FcPatternGetLangSet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcLangSet**);
+FcResult (*FcPatternGetRange_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcRange**);
+FcPattern* (*FcPatternVaBuild_dylibloader_wrapper_fontconfig)( FcPattern*, va_list);
+FcPattern* (*FcPatternBuild_dylibloader_wrapper_fontconfig)( FcPattern*,...);
+FcChar8* (*FcPatternFormat_dylibloader_wrapper_fontconfig)( FcPattern*,const FcChar8*);
+FcRange* (*FcRangeCreateDouble_dylibloader_wrapper_fontconfig)( double, double);
+FcRange* (*FcRangeCreateInteger_dylibloader_wrapper_fontconfig)( FcChar32, FcChar32);
+void (*FcRangeDestroy_dylibloader_wrapper_fontconfig)( FcRange*);
+FcRange* (*FcRangeCopy_dylibloader_wrapper_fontconfig)(const FcRange*);
+FcBool (*FcRangeGetDouble_dylibloader_wrapper_fontconfig)(const FcRange*, double*, double*);
+int (*FcWeightFromOpenType_dylibloader_wrapper_fontconfig)( int);
+int (*FcWeightToOpenType_dylibloader_wrapper_fontconfig)( int);
+FcChar8* (*FcStrCopy_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcChar8* (*FcStrCopyFilename_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcChar8* (*FcStrPlus_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+void (*FcStrFree_dylibloader_wrapper_fontconfig)( FcChar8*);
+FcChar8* (*FcStrDowncase_dylibloader_wrapper_fontconfig)(const FcChar8*);
+int (*FcStrCmpIgnoreCase_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+int (*FcStrCmp_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+const FcChar8* (*FcStrStrIgnoreCase_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+const FcChar8* (*FcStrStr_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+int (*FcUtf8ToUcs4_dylibloader_wrapper_fontconfig)(const FcChar8*, FcChar32*, int);
+FcBool (*FcUtf8Len_dylibloader_wrapper_fontconfig)(const FcChar8*, int, int*, int*);
+int (*FcUcs4ToUtf8_dylibloader_wrapper_fontconfig)( FcChar32, FcChar8 [6]);
+int (*FcUtf16ToUcs4_dylibloader_wrapper_fontconfig)(const FcChar8*, FcEndian, FcChar32*, int);
+FcBool (*FcUtf16Len_dylibloader_wrapper_fontconfig)(const FcChar8*, FcEndian, int, int*, int*);
+FcChar8* (*FcStrDirname_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcChar8* (*FcStrBasename_dylibloader_wrapper_fontconfig)(const FcChar8*);
+FcStrSet* (*FcStrSetCreate_dylibloader_wrapper_fontconfig)( void);
+FcBool (*FcStrSetMember_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*);
+FcBool (*FcStrSetEqual_dylibloader_wrapper_fontconfig)( FcStrSet*, FcStrSet*);
+FcBool (*FcStrSetAdd_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*);
+FcBool (*FcStrSetAddFilename_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*);
+FcBool (*FcStrSetDel_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*);
+void (*FcStrSetDestroy_dylibloader_wrapper_fontconfig)( FcStrSet*);
+FcStrList* (*FcStrListCreate_dylibloader_wrapper_fontconfig)( FcStrSet*);
+void (*FcStrListFirst_dylibloader_wrapper_fontconfig)( FcStrList*);
+FcChar8* (*FcStrListNext_dylibloader_wrapper_fontconfig)( FcStrList*);
+void (*FcStrListDone_dylibloader_wrapper_fontconfig)( FcStrList*);
+FcBool (*FcConfigParseAndLoad_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*, FcBool);
+FcBool (*FcConfigParseAndLoadFromMemory_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*, FcBool);
+int initialize_fontconfig(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libfontconfig.so", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// FcBlanksCreate
+ *(void **) (&FcBlanksCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcBlanksCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcBlanksDestroy
+ *(void **) (&FcBlanksDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcBlanksDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcBlanksAdd
+ *(void **) (&FcBlanksAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcBlanksAdd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcBlanksIsMember
+ *(void **) (&FcBlanksIsMember_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcBlanksIsMember");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCacheDir
+ *(void **) (&FcCacheDir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheDir");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCacheCopySet
+ *(void **) (&FcCacheCopySet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheCopySet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCacheSubdir
+ *(void **) (&FcCacheSubdir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheSubdir");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCacheNumSubdir
+ *(void **) (&FcCacheNumSubdir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheNumSubdir");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCacheNumFont
+ *(void **) (&FcCacheNumFont_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheNumFont");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirCacheUnlink
+ *(void **) (&FcDirCacheUnlink_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheUnlink");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirCacheValid
+ *(void **) (&FcDirCacheValid_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheValid");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirCacheClean
+ *(void **) (&FcDirCacheClean_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheClean");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcCacheCreateTagFile
+ *(void **) (&FcCacheCreateTagFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcCacheCreateTagFile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigHome
+ *(void **) (&FcConfigHome_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigHome");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigEnableHome
+ *(void **) (&FcConfigEnableHome_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigEnableHome");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigFilename
+ *(void **) (&FcConfigFilename_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigFilename");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigCreate
+ *(void **) (&FcConfigCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigReference
+ *(void **) (&FcConfigReference_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigReference");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigDestroy
+ *(void **) (&FcConfigDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigSetCurrent
+ *(void **) (&FcConfigSetCurrent_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSetCurrent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetCurrent
+ *(void **) (&FcConfigGetCurrent_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetCurrent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigUptoDate
+ *(void **) (&FcConfigUptoDate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigUptoDate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigBuildFonts
+ *(void **) (&FcConfigBuildFonts_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigBuildFonts");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetFontDirs
+ *(void **) (&FcConfigGetFontDirs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetFontDirs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetConfigDirs
+ *(void **) (&FcConfigGetConfigDirs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetConfigDirs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetConfigFiles
+ *(void **) (&FcConfigGetConfigFiles_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetConfigFiles");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetCache
+ *(void **) (&FcConfigGetCache_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetCache");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetBlanks
+ *(void **) (&FcConfigGetBlanks_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetBlanks");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetCacheDirs
+ *(void **) (&FcConfigGetCacheDirs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetCacheDirs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetRescanInterval
+ *(void **) (&FcConfigGetRescanInterval_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetRescanInterval");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigSetRescanInterval
+ *(void **) (&FcConfigSetRescanInterval_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSetRescanInterval");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetFonts
+ *(void **) (&FcConfigGetFonts_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetFonts");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigAppFontAddFile
+ *(void **) (&FcConfigAppFontAddFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigAppFontAddFile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigAppFontAddDir
+ *(void **) (&FcConfigAppFontAddDir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigAppFontAddDir");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigAppFontClear
+ *(void **) (&FcConfigAppFontClear_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigAppFontClear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigSubstituteWithPat
+ *(void **) (&FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSubstituteWithPat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigSubstitute
+ *(void **) (&FcConfigSubstitute_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSubstitute");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigGetSysRoot
+ *(void **) (&FcConfigGetSysRoot_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigGetSysRoot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigSetSysRoot
+ *(void **) (&FcConfigSetSysRoot_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigSetSysRoot");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcValuePrint
+ *(void **) (&FcValuePrint_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcValuePrint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternPrint
+ *(void **) (&FcPatternPrint_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternPrint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontSetPrint
+ *(void **) (&FcFontSetPrint_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetPrint");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcGetDefaultLangs
+ *(void **) (&FcGetDefaultLangs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcGetDefaultLangs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDefaultSubstitute
+ *(void **) (&FcDefaultSubstitute_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDefaultSubstitute");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFileIsDir
+ *(void **) (&FcFileIsDir_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFileIsDir");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFileScan
+ *(void **) (&FcFileScan_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFileScan");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirScan
+ *(void **) (&FcDirScan_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirScan");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirSave
+ *(void **) (&FcDirSave_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirSave");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirCacheLoad
+ *(void **) (&FcDirCacheLoad_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheLoad");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirCacheRescan
+ *(void **) (&FcDirCacheRescan_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheRescan");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirCacheRead
+ *(void **) (&FcDirCacheRead_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheRead");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirCacheLoadFile
+ *(void **) (&FcDirCacheLoadFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheLoadFile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcDirCacheUnload
+ *(void **) (&FcDirCacheUnload_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcDirCacheUnload");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFreeTypeQuery
+ *(void **) (&FcFreeTypeQuery_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFreeTypeQuery");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontSetCreate
+ *(void **) (&FcFontSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontSetDestroy
+ *(void **) (&FcFontSetDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontSetAdd
+ *(void **) (&FcFontSetAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetAdd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcInitLoadConfig
+ *(void **) (&FcInitLoadConfig_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInitLoadConfig");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcInitLoadConfigAndFonts
+ *(void **) (&FcInitLoadConfigAndFonts_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInitLoadConfigAndFonts");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcInit
+ *(void **) (&FcInit_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInit");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFini
+ *(void **) (&FcFini_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFini");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcGetVersion
+ *(void **) (&FcGetVersion_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcGetVersion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcInitReinitialize
+ *(void **) (&FcInitReinitialize_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInitReinitialize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcInitBringUptoDate
+ *(void **) (&FcInitBringUptoDate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcInitBringUptoDate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcGetLangs
+ *(void **) (&FcGetLangs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcGetLangs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangNormalize
+ *(void **) (&FcLangNormalize_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangNormalize");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangGetCharSet
+ *(void **) (&FcLangGetCharSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangGetCharSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetCreate
+ *(void **) (&FcLangSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetDestroy
+ *(void **) (&FcLangSetDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetCopy
+ *(void **) (&FcLangSetCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetCopy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetAdd
+ *(void **) (&FcLangSetAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetAdd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetDel
+ *(void **) (&FcLangSetDel_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetDel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetHasLang
+ *(void **) (&FcLangSetHasLang_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetHasLang");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetCompare
+ *(void **) (&FcLangSetCompare_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetCompare");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetContains
+ *(void **) (&FcLangSetContains_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetContains");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetEqual
+ *(void **) (&FcLangSetEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetEqual");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetHash
+ *(void **) (&FcLangSetHash_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetHash");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetGetLangs
+ *(void **) (&FcLangSetGetLangs_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetGetLangs");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetUnion
+ *(void **) (&FcLangSetUnion_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetUnion");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcLangSetSubtract
+ *(void **) (&FcLangSetSubtract_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcLangSetSubtract");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcObjectSetCreate
+ *(void **) (&FcObjectSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcObjectSetAdd
+ *(void **) (&FcObjectSetAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetAdd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcObjectSetDestroy
+ *(void **) (&FcObjectSetDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcObjectSetVaBuild
+ *(void **) (&FcObjectSetVaBuild_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetVaBuild");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcObjectSetBuild
+ *(void **) (&FcObjectSetBuild_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcObjectSetBuild");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontSetList
+ *(void **) (&FcFontSetList_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontList
+ *(void **) (&FcFontList_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontList");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcAtomicCreate
+ *(void **) (&FcAtomicCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcAtomicLock
+ *(void **) (&FcAtomicLock_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicLock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcAtomicNewFile
+ *(void **) (&FcAtomicNewFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicNewFile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcAtomicOrigFile
+ *(void **) (&FcAtomicOrigFile_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicOrigFile");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcAtomicReplaceOrig
+ *(void **) (&FcAtomicReplaceOrig_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicReplaceOrig");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcAtomicDeleteNew
+ *(void **) (&FcAtomicDeleteNew_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicDeleteNew");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcAtomicUnlock
+ *(void **) (&FcAtomicUnlock_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicUnlock");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcAtomicDestroy
+ *(void **) (&FcAtomicDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcAtomicDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontSetMatch
+ *(void **) (&FcFontSetMatch_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetMatch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontMatch
+ *(void **) (&FcFontMatch_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontMatch");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontRenderPrepare
+ *(void **) (&FcFontRenderPrepare_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontRenderPrepare");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontSetSort
+ *(void **) (&FcFontSetSort_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetSort");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontSort
+ *(void **) (&FcFontSort_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSort");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcFontSetSortDestroy
+ *(void **) (&FcFontSetSortDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcFontSetSortDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcMatrixCopy
+ *(void **) (&FcMatrixCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixCopy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcMatrixEqual
+ *(void **) (&FcMatrixEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixEqual");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcMatrixMultiply
+ *(void **) (&FcMatrixMultiply_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixMultiply");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcMatrixRotate
+ *(void **) (&FcMatrixRotate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixRotate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcMatrixScale
+ *(void **) (&FcMatrixScale_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixScale");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcMatrixShear
+ *(void **) (&FcMatrixShear_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcMatrixShear");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcNameRegisterObjectTypes
+ *(void **) (&FcNameRegisterObjectTypes_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameRegisterObjectTypes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcNameUnregisterObjectTypes
+ *(void **) (&FcNameUnregisterObjectTypes_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameUnregisterObjectTypes");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcNameGetObjectType
+ *(void **) (&FcNameGetObjectType_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameGetObjectType");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcNameRegisterConstants
+ *(void **) (&FcNameRegisterConstants_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameRegisterConstants");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcNameUnregisterConstants
+ *(void **) (&FcNameUnregisterConstants_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameUnregisterConstants");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcNameGetConstant
+ *(void **) (&FcNameGetConstant_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameGetConstant");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcNameConstant
+ *(void **) (&FcNameConstant_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameConstant");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcNameParse
+ *(void **) (&FcNameParse_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameParse");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcNameUnparse
+ *(void **) (&FcNameUnparse_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcNameUnparse");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternCreate
+ *(void **) (&FcPatternCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternDuplicate
+ *(void **) (&FcPatternDuplicate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternDuplicate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternReference
+ *(void **) (&FcPatternReference_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternReference");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternFilter
+ *(void **) (&FcPatternFilter_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternFilter");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcValueDestroy
+ *(void **) (&FcValueDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcValueDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcValueEqual
+ *(void **) (&FcValueEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcValueEqual");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcValueSave
+ *(void **) (&FcValueSave_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcValueSave");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternDestroy
+ *(void **) (&FcPatternDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternEqual
+ *(void **) (&FcPatternEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternEqual");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternEqualSubset
+ *(void **) (&FcPatternEqualSubset_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternEqualSubset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternHash
+ *(void **) (&FcPatternHash_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternHash");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAdd
+ *(void **) (&FcPatternAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAdd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAddWeak
+ *(void **) (&FcPatternAddWeak_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddWeak");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGet
+ *(void **) (&FcPatternGet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGetWithBinding
+ *(void **) (&FcPatternGetWithBinding_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetWithBinding");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternDel
+ *(void **) (&FcPatternDel_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternDel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternRemove
+ *(void **) (&FcPatternRemove_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternRemove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAddInteger
+ *(void **) (&FcPatternAddInteger_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddInteger");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAddDouble
+ *(void **) (&FcPatternAddDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddDouble");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAddString
+ *(void **) (&FcPatternAddString_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAddMatrix
+ *(void **) (&FcPatternAddMatrix_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddMatrix");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAddCharSet
+ *(void **) (&FcPatternAddCharSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddCharSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAddBool
+ *(void **) (&FcPatternAddBool_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddBool");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAddLangSet
+ *(void **) (&FcPatternAddLangSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddLangSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternAddRange
+ *(void **) (&FcPatternAddRange_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternAddRange");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGetInteger
+ *(void **) (&FcPatternGetInteger_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetInteger");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGetDouble
+ *(void **) (&FcPatternGetDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetDouble");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGetString
+ *(void **) (&FcPatternGetString_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetString");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGetMatrix
+ *(void **) (&FcPatternGetMatrix_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetMatrix");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGetCharSet
+ *(void **) (&FcPatternGetCharSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetCharSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGetBool
+ *(void **) (&FcPatternGetBool_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetBool");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGetLangSet
+ *(void **) (&FcPatternGetLangSet_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetLangSet");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternGetRange
+ *(void **) (&FcPatternGetRange_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternGetRange");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternVaBuild
+ *(void **) (&FcPatternVaBuild_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternVaBuild");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternBuild
+ *(void **) (&FcPatternBuild_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternBuild");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcPatternFormat
+ *(void **) (&FcPatternFormat_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcPatternFormat");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcRangeCreateDouble
+ *(void **) (&FcRangeCreateDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeCreateDouble");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcRangeCreateInteger
+ *(void **) (&FcRangeCreateInteger_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeCreateInteger");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcRangeDestroy
+ *(void **) (&FcRangeDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcRangeCopy
+ *(void **) (&FcRangeCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeCopy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcRangeGetDouble
+ *(void **) (&FcRangeGetDouble_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcRangeGetDouble");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcWeightFromOpenType
+ *(void **) (&FcWeightFromOpenType_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcWeightFromOpenType");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcWeightToOpenType
+ *(void **) (&FcWeightToOpenType_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcWeightToOpenType");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrCopy
+ *(void **) (&FcStrCopy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrCopy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrCopyFilename
+ *(void **) (&FcStrCopyFilename_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrCopyFilename");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrPlus
+ *(void **) (&FcStrPlus_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrPlus");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrFree
+ *(void **) (&FcStrFree_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrFree");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrDowncase
+ *(void **) (&FcStrDowncase_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrDowncase");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrCmpIgnoreCase
+ *(void **) (&FcStrCmpIgnoreCase_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrCmpIgnoreCase");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrCmp
+ *(void **) (&FcStrCmp_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrCmp");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrStrIgnoreCase
+ *(void **) (&FcStrStrIgnoreCase_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrStrIgnoreCase");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrStr
+ *(void **) (&FcStrStr_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrStr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcUtf8ToUcs4
+ *(void **) (&FcUtf8ToUcs4_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUtf8ToUcs4");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcUtf8Len
+ *(void **) (&FcUtf8Len_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUtf8Len");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcUcs4ToUtf8
+ *(void **) (&FcUcs4ToUtf8_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUcs4ToUtf8");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcUtf16ToUcs4
+ *(void **) (&FcUtf16ToUcs4_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUtf16ToUcs4");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcUtf16Len
+ *(void **) (&FcUtf16Len_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcUtf16Len");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrDirname
+ *(void **) (&FcStrDirname_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrDirname");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrBasename
+ *(void **) (&FcStrBasename_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrBasename");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrSetCreate
+ *(void **) (&FcStrSetCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrSetMember
+ *(void **) (&FcStrSetMember_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetMember");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrSetEqual
+ *(void **) (&FcStrSetEqual_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetEqual");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrSetAdd
+ *(void **) (&FcStrSetAdd_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetAdd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrSetAddFilename
+ *(void **) (&FcStrSetAddFilename_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetAddFilename");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrSetDel
+ *(void **) (&FcStrSetDel_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetDel");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrSetDestroy
+ *(void **) (&FcStrSetDestroy_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrSetDestroy");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrListCreate
+ *(void **) (&FcStrListCreate_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrListCreate");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrListFirst
+ *(void **) (&FcStrListFirst_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrListFirst");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrListNext
+ *(void **) (&FcStrListNext_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrListNext");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcStrListDone
+ *(void **) (&FcStrListDone_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcStrListDone");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigParseAndLoad
+ *(void **) (&FcConfigParseAndLoad_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigParseAndLoad");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// FcConfigParseAndLoadFromMemory
+ *(void **) (&FcConfigParseAndLoadFromMemory_dylibloader_wrapper_fontconfig) = dlsym(handle, "FcConfigParseAndLoadFromMemory");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/fontconfig-so_wrap.h b/platform/linuxbsd/fontconfig-so_wrap.h
new file mode 100644
index 0000000000..f0794cce8b
--- /dev/null
+++ b/platform/linuxbsd/fontconfig-so_wrap.h
@@ -0,0 +1,770 @@
+#ifndef DYLIBLOAD_WRAPPER_FONTCONFIG
+#define DYLIBLOAD_WRAPPER_FONTCONFIG
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by ./generate-wrapper.py 0.3 on 2022-07-29 05:40:07
+// flags: ./generate-wrapper.py --include /usr/include/fontconfig/fontconfig.h --sys-include <fontconfig/fontconfig.h> --soname libfontconfig.so --init-name fontconfig --output-header fontconfig-so_wrap.h --output-implementation fontconfig-so_wrap.c --omit-prefix FcCharSet
+//
+#include <stdint.h>
+
+#define FcBlanksCreate FcBlanksCreate_dylibloader_orig_fontconfig
+#define FcBlanksDestroy FcBlanksDestroy_dylibloader_orig_fontconfig
+#define FcBlanksAdd FcBlanksAdd_dylibloader_orig_fontconfig
+#define FcBlanksIsMember FcBlanksIsMember_dylibloader_orig_fontconfig
+#define FcCacheDir FcCacheDir_dylibloader_orig_fontconfig
+#define FcCacheCopySet FcCacheCopySet_dylibloader_orig_fontconfig
+#define FcCacheSubdir FcCacheSubdir_dylibloader_orig_fontconfig
+#define FcCacheNumSubdir FcCacheNumSubdir_dylibloader_orig_fontconfig
+#define FcCacheNumFont FcCacheNumFont_dylibloader_orig_fontconfig
+#define FcDirCacheUnlink FcDirCacheUnlink_dylibloader_orig_fontconfig
+#define FcDirCacheValid FcDirCacheValid_dylibloader_orig_fontconfig
+#define FcDirCacheClean FcDirCacheClean_dylibloader_orig_fontconfig
+#define FcCacheCreateTagFile FcCacheCreateTagFile_dylibloader_orig_fontconfig
+#define FcConfigHome FcConfigHome_dylibloader_orig_fontconfig
+#define FcConfigEnableHome FcConfigEnableHome_dylibloader_orig_fontconfig
+#define FcConfigFilename FcConfigFilename_dylibloader_orig_fontconfig
+#define FcConfigCreate FcConfigCreate_dylibloader_orig_fontconfig
+#define FcConfigReference FcConfigReference_dylibloader_orig_fontconfig
+#define FcConfigDestroy FcConfigDestroy_dylibloader_orig_fontconfig
+#define FcConfigSetCurrent FcConfigSetCurrent_dylibloader_orig_fontconfig
+#define FcConfigGetCurrent FcConfigGetCurrent_dylibloader_orig_fontconfig
+#define FcConfigUptoDate FcConfigUptoDate_dylibloader_orig_fontconfig
+#define FcConfigBuildFonts FcConfigBuildFonts_dylibloader_orig_fontconfig
+#define FcConfigGetFontDirs FcConfigGetFontDirs_dylibloader_orig_fontconfig
+#define FcConfigGetConfigDirs FcConfigGetConfigDirs_dylibloader_orig_fontconfig
+#define FcConfigGetConfigFiles FcConfigGetConfigFiles_dylibloader_orig_fontconfig
+#define FcConfigGetCache FcConfigGetCache_dylibloader_orig_fontconfig
+#define FcConfigGetBlanks FcConfigGetBlanks_dylibloader_orig_fontconfig
+#define FcConfigGetCacheDirs FcConfigGetCacheDirs_dylibloader_orig_fontconfig
+#define FcConfigGetRescanInterval FcConfigGetRescanInterval_dylibloader_orig_fontconfig
+#define FcConfigSetRescanInterval FcConfigSetRescanInterval_dylibloader_orig_fontconfig
+#define FcConfigGetFonts FcConfigGetFonts_dylibloader_orig_fontconfig
+#define FcConfigAppFontAddFile FcConfigAppFontAddFile_dylibloader_orig_fontconfig
+#define FcConfigAppFontAddDir FcConfigAppFontAddDir_dylibloader_orig_fontconfig
+#define FcConfigAppFontClear FcConfigAppFontClear_dylibloader_orig_fontconfig
+#define FcConfigSubstituteWithPat FcConfigSubstituteWithPat_dylibloader_orig_fontconfig
+#define FcConfigSubstitute FcConfigSubstitute_dylibloader_orig_fontconfig
+#define FcConfigGetSysRoot FcConfigGetSysRoot_dylibloader_orig_fontconfig
+#define FcConfigSetSysRoot FcConfigSetSysRoot_dylibloader_orig_fontconfig
+#define FcValuePrint FcValuePrint_dylibloader_orig_fontconfig
+#define FcPatternPrint FcPatternPrint_dylibloader_orig_fontconfig
+#define FcFontSetPrint FcFontSetPrint_dylibloader_orig_fontconfig
+#define FcGetDefaultLangs FcGetDefaultLangs_dylibloader_orig_fontconfig
+#define FcDefaultSubstitute FcDefaultSubstitute_dylibloader_orig_fontconfig
+#define FcFileIsDir FcFileIsDir_dylibloader_orig_fontconfig
+#define FcFileScan FcFileScan_dylibloader_orig_fontconfig
+#define FcDirScan FcDirScan_dylibloader_orig_fontconfig
+#define FcDirSave FcDirSave_dylibloader_orig_fontconfig
+#define FcDirCacheLoad FcDirCacheLoad_dylibloader_orig_fontconfig
+#define FcDirCacheRescan FcDirCacheRescan_dylibloader_orig_fontconfig
+#define FcDirCacheRead FcDirCacheRead_dylibloader_orig_fontconfig
+#define FcDirCacheLoadFile FcDirCacheLoadFile_dylibloader_orig_fontconfig
+#define FcDirCacheUnload FcDirCacheUnload_dylibloader_orig_fontconfig
+#define FcFreeTypeQuery FcFreeTypeQuery_dylibloader_orig_fontconfig
+#define FcFontSetCreate FcFontSetCreate_dylibloader_orig_fontconfig
+#define FcFontSetDestroy FcFontSetDestroy_dylibloader_orig_fontconfig
+#define FcFontSetAdd FcFontSetAdd_dylibloader_orig_fontconfig
+#define FcInitLoadConfig FcInitLoadConfig_dylibloader_orig_fontconfig
+#define FcInitLoadConfigAndFonts FcInitLoadConfigAndFonts_dylibloader_orig_fontconfig
+#define FcInit FcInit_dylibloader_orig_fontconfig
+#define FcFini FcFini_dylibloader_orig_fontconfig
+#define FcGetVersion FcGetVersion_dylibloader_orig_fontconfig
+#define FcInitReinitialize FcInitReinitialize_dylibloader_orig_fontconfig
+#define FcInitBringUptoDate FcInitBringUptoDate_dylibloader_orig_fontconfig
+#define FcGetLangs FcGetLangs_dylibloader_orig_fontconfig
+#define FcLangNormalize FcLangNormalize_dylibloader_orig_fontconfig
+#define FcLangGetCharSet FcLangGetCharSet_dylibloader_orig_fontconfig
+#define FcLangSetCreate FcLangSetCreate_dylibloader_orig_fontconfig
+#define FcLangSetDestroy FcLangSetDestroy_dylibloader_orig_fontconfig
+#define FcLangSetCopy FcLangSetCopy_dylibloader_orig_fontconfig
+#define FcLangSetAdd FcLangSetAdd_dylibloader_orig_fontconfig
+#define FcLangSetDel FcLangSetDel_dylibloader_orig_fontconfig
+#define FcLangSetHasLang FcLangSetHasLang_dylibloader_orig_fontconfig
+#define FcLangSetCompare FcLangSetCompare_dylibloader_orig_fontconfig
+#define FcLangSetContains FcLangSetContains_dylibloader_orig_fontconfig
+#define FcLangSetEqual FcLangSetEqual_dylibloader_orig_fontconfig
+#define FcLangSetHash FcLangSetHash_dylibloader_orig_fontconfig
+#define FcLangSetGetLangs FcLangSetGetLangs_dylibloader_orig_fontconfig
+#define FcLangSetUnion FcLangSetUnion_dylibloader_orig_fontconfig
+#define FcLangSetSubtract FcLangSetSubtract_dylibloader_orig_fontconfig
+#define FcObjectSetCreate FcObjectSetCreate_dylibloader_orig_fontconfig
+#define FcObjectSetAdd FcObjectSetAdd_dylibloader_orig_fontconfig
+#define FcObjectSetDestroy FcObjectSetDestroy_dylibloader_orig_fontconfig
+#define FcObjectSetVaBuild FcObjectSetVaBuild_dylibloader_orig_fontconfig
+#define FcObjectSetBuild FcObjectSetBuild_dylibloader_orig_fontconfig
+#define FcFontSetList FcFontSetList_dylibloader_orig_fontconfig
+#define FcFontList FcFontList_dylibloader_orig_fontconfig
+#define FcAtomicCreate FcAtomicCreate_dylibloader_orig_fontconfig
+#define FcAtomicLock FcAtomicLock_dylibloader_orig_fontconfig
+#define FcAtomicNewFile FcAtomicNewFile_dylibloader_orig_fontconfig
+#define FcAtomicOrigFile FcAtomicOrigFile_dylibloader_orig_fontconfig
+#define FcAtomicReplaceOrig FcAtomicReplaceOrig_dylibloader_orig_fontconfig
+#define FcAtomicDeleteNew FcAtomicDeleteNew_dylibloader_orig_fontconfig
+#define FcAtomicUnlock FcAtomicUnlock_dylibloader_orig_fontconfig
+#define FcAtomicDestroy FcAtomicDestroy_dylibloader_orig_fontconfig
+#define FcFontSetMatch FcFontSetMatch_dylibloader_orig_fontconfig
+#define FcFontMatch FcFontMatch_dylibloader_orig_fontconfig
+#define FcFontRenderPrepare FcFontRenderPrepare_dylibloader_orig_fontconfig
+#define FcFontSetSort FcFontSetSort_dylibloader_orig_fontconfig
+#define FcFontSort FcFontSort_dylibloader_orig_fontconfig
+#define FcFontSetSortDestroy FcFontSetSortDestroy_dylibloader_orig_fontconfig
+#define FcMatrixCopy FcMatrixCopy_dylibloader_orig_fontconfig
+#define FcMatrixEqual FcMatrixEqual_dylibloader_orig_fontconfig
+#define FcMatrixMultiply FcMatrixMultiply_dylibloader_orig_fontconfig
+#define FcMatrixRotate FcMatrixRotate_dylibloader_orig_fontconfig
+#define FcMatrixScale FcMatrixScale_dylibloader_orig_fontconfig
+#define FcMatrixShear FcMatrixShear_dylibloader_orig_fontconfig
+#define FcNameRegisterObjectTypes FcNameRegisterObjectTypes_dylibloader_orig_fontconfig
+#define FcNameUnregisterObjectTypes FcNameUnregisterObjectTypes_dylibloader_orig_fontconfig
+#define FcNameGetObjectType FcNameGetObjectType_dylibloader_orig_fontconfig
+#define FcNameRegisterConstants FcNameRegisterConstants_dylibloader_orig_fontconfig
+#define FcNameUnregisterConstants FcNameUnregisterConstants_dylibloader_orig_fontconfig
+#define FcNameGetConstant FcNameGetConstant_dylibloader_orig_fontconfig
+#define FcNameConstant FcNameConstant_dylibloader_orig_fontconfig
+#define FcNameParse FcNameParse_dylibloader_orig_fontconfig
+#define FcNameUnparse FcNameUnparse_dylibloader_orig_fontconfig
+#define FcPatternCreate FcPatternCreate_dylibloader_orig_fontconfig
+#define FcPatternDuplicate FcPatternDuplicate_dylibloader_orig_fontconfig
+#define FcPatternReference FcPatternReference_dylibloader_orig_fontconfig
+#define FcPatternFilter FcPatternFilter_dylibloader_orig_fontconfig
+#define FcValueDestroy FcValueDestroy_dylibloader_orig_fontconfig
+#define FcValueEqual FcValueEqual_dylibloader_orig_fontconfig
+#define FcValueSave FcValueSave_dylibloader_orig_fontconfig
+#define FcPatternDestroy FcPatternDestroy_dylibloader_orig_fontconfig
+#define FcPatternEqual FcPatternEqual_dylibloader_orig_fontconfig
+#define FcPatternEqualSubset FcPatternEqualSubset_dylibloader_orig_fontconfig
+#define FcPatternHash FcPatternHash_dylibloader_orig_fontconfig
+#define FcPatternAdd FcPatternAdd_dylibloader_orig_fontconfig
+#define FcPatternAddWeak FcPatternAddWeak_dylibloader_orig_fontconfig
+#define FcPatternGet FcPatternGet_dylibloader_orig_fontconfig
+#define FcPatternGetWithBinding FcPatternGetWithBinding_dylibloader_orig_fontconfig
+#define FcPatternDel FcPatternDel_dylibloader_orig_fontconfig
+#define FcPatternRemove FcPatternRemove_dylibloader_orig_fontconfig
+#define FcPatternAddInteger FcPatternAddInteger_dylibloader_orig_fontconfig
+#define FcPatternAddDouble FcPatternAddDouble_dylibloader_orig_fontconfig
+#define FcPatternAddString FcPatternAddString_dylibloader_orig_fontconfig
+#define FcPatternAddMatrix FcPatternAddMatrix_dylibloader_orig_fontconfig
+#define FcPatternAddCharSet FcPatternAddCharSet_dylibloader_orig_fontconfig
+#define FcPatternAddBool FcPatternAddBool_dylibloader_orig_fontconfig
+#define FcPatternAddLangSet FcPatternAddLangSet_dylibloader_orig_fontconfig
+#define FcPatternAddRange FcPatternAddRange_dylibloader_orig_fontconfig
+#define FcPatternGetInteger FcPatternGetInteger_dylibloader_orig_fontconfig
+#define FcPatternGetDouble FcPatternGetDouble_dylibloader_orig_fontconfig
+#define FcPatternGetString FcPatternGetString_dylibloader_orig_fontconfig
+#define FcPatternGetMatrix FcPatternGetMatrix_dylibloader_orig_fontconfig
+#define FcPatternGetCharSet FcPatternGetCharSet_dylibloader_orig_fontconfig
+#define FcPatternGetBool FcPatternGetBool_dylibloader_orig_fontconfig
+#define FcPatternGetLangSet FcPatternGetLangSet_dylibloader_orig_fontconfig
+#define FcPatternGetRange FcPatternGetRange_dylibloader_orig_fontconfig
+#define FcPatternVaBuild FcPatternVaBuild_dylibloader_orig_fontconfig
+#define FcPatternBuild FcPatternBuild_dylibloader_orig_fontconfig
+#define FcPatternFormat FcPatternFormat_dylibloader_orig_fontconfig
+#define FcRangeCreateDouble FcRangeCreateDouble_dylibloader_orig_fontconfig
+#define FcRangeCreateInteger FcRangeCreateInteger_dylibloader_orig_fontconfig
+#define FcRangeDestroy FcRangeDestroy_dylibloader_orig_fontconfig
+#define FcRangeCopy FcRangeCopy_dylibloader_orig_fontconfig
+#define FcRangeGetDouble FcRangeGetDouble_dylibloader_orig_fontconfig
+#define FcWeightFromOpenType FcWeightFromOpenType_dylibloader_orig_fontconfig
+#define FcWeightToOpenType FcWeightToOpenType_dylibloader_orig_fontconfig
+#define FcStrCopy FcStrCopy_dylibloader_orig_fontconfig
+#define FcStrCopyFilename FcStrCopyFilename_dylibloader_orig_fontconfig
+#define FcStrPlus FcStrPlus_dylibloader_orig_fontconfig
+#define FcStrFree FcStrFree_dylibloader_orig_fontconfig
+#define FcStrDowncase FcStrDowncase_dylibloader_orig_fontconfig
+#define FcStrCmpIgnoreCase FcStrCmpIgnoreCase_dylibloader_orig_fontconfig
+#define FcStrCmp FcStrCmp_dylibloader_orig_fontconfig
+#define FcStrStrIgnoreCase FcStrStrIgnoreCase_dylibloader_orig_fontconfig
+#define FcStrStr FcStrStr_dylibloader_orig_fontconfig
+#define FcUtf8ToUcs4 FcUtf8ToUcs4_dylibloader_orig_fontconfig
+#define FcUtf8Len FcUtf8Len_dylibloader_orig_fontconfig
+#define FcUcs4ToUtf8 FcUcs4ToUtf8_dylibloader_orig_fontconfig
+#define FcUtf16ToUcs4 FcUtf16ToUcs4_dylibloader_orig_fontconfig
+#define FcUtf16Len FcUtf16Len_dylibloader_orig_fontconfig
+#define FcStrDirname FcStrDirname_dylibloader_orig_fontconfig
+#define FcStrBasename FcStrBasename_dylibloader_orig_fontconfig
+#define FcStrSetCreate FcStrSetCreate_dylibloader_orig_fontconfig
+#define FcStrSetMember FcStrSetMember_dylibloader_orig_fontconfig
+#define FcStrSetEqual FcStrSetEqual_dylibloader_orig_fontconfig
+#define FcStrSetAdd FcStrSetAdd_dylibloader_orig_fontconfig
+#define FcStrSetAddFilename FcStrSetAddFilename_dylibloader_orig_fontconfig
+#define FcStrSetDel FcStrSetDel_dylibloader_orig_fontconfig
+#define FcStrSetDestroy FcStrSetDestroy_dylibloader_orig_fontconfig
+#define FcStrListCreate FcStrListCreate_dylibloader_orig_fontconfig
+#define FcStrListFirst FcStrListFirst_dylibloader_orig_fontconfig
+#define FcStrListNext FcStrListNext_dylibloader_orig_fontconfig
+#define FcStrListDone FcStrListDone_dylibloader_orig_fontconfig
+#define FcConfigParseAndLoad FcConfigParseAndLoad_dylibloader_orig_fontconfig
+#define FcConfigParseAndLoadFromMemory FcConfigParseAndLoadFromMemory_dylibloader_orig_fontconfig
+#include <fontconfig/fontconfig.h>
+#undef FcBlanksCreate
+#undef FcBlanksDestroy
+#undef FcBlanksAdd
+#undef FcBlanksIsMember
+#undef FcCacheDir
+#undef FcCacheCopySet
+#undef FcCacheSubdir
+#undef FcCacheNumSubdir
+#undef FcCacheNumFont
+#undef FcDirCacheUnlink
+#undef FcDirCacheValid
+#undef FcDirCacheClean
+#undef FcCacheCreateTagFile
+#undef FcConfigHome
+#undef FcConfigEnableHome
+#undef FcConfigFilename
+#undef FcConfigCreate
+#undef FcConfigReference
+#undef FcConfigDestroy
+#undef FcConfigSetCurrent
+#undef FcConfigGetCurrent
+#undef FcConfigUptoDate
+#undef FcConfigBuildFonts
+#undef FcConfigGetFontDirs
+#undef FcConfigGetConfigDirs
+#undef FcConfigGetConfigFiles
+#undef FcConfigGetCache
+#undef FcConfigGetBlanks
+#undef FcConfigGetCacheDirs
+#undef FcConfigGetRescanInterval
+#undef FcConfigSetRescanInterval
+#undef FcConfigGetFonts
+#undef FcConfigAppFontAddFile
+#undef FcConfigAppFontAddDir
+#undef FcConfigAppFontClear
+#undef FcConfigSubstituteWithPat
+#undef FcConfigSubstitute
+#undef FcConfigGetSysRoot
+#undef FcConfigSetSysRoot
+#undef FcValuePrint
+#undef FcPatternPrint
+#undef FcFontSetPrint
+#undef FcGetDefaultLangs
+#undef FcDefaultSubstitute
+#undef FcFileIsDir
+#undef FcFileScan
+#undef FcDirScan
+#undef FcDirSave
+#undef FcDirCacheLoad
+#undef FcDirCacheRescan
+#undef FcDirCacheRead
+#undef FcDirCacheLoadFile
+#undef FcDirCacheUnload
+#undef FcFreeTypeQuery
+#undef FcFontSetCreate
+#undef FcFontSetDestroy
+#undef FcFontSetAdd
+#undef FcInitLoadConfig
+#undef FcInitLoadConfigAndFonts
+#undef FcInit
+#undef FcFini
+#undef FcGetVersion
+#undef FcInitReinitialize
+#undef FcInitBringUptoDate
+#undef FcGetLangs
+#undef FcLangNormalize
+#undef FcLangGetCharSet
+#undef FcLangSetCreate
+#undef FcLangSetDestroy
+#undef FcLangSetCopy
+#undef FcLangSetAdd
+#undef FcLangSetDel
+#undef FcLangSetHasLang
+#undef FcLangSetCompare
+#undef FcLangSetContains
+#undef FcLangSetEqual
+#undef FcLangSetHash
+#undef FcLangSetGetLangs
+#undef FcLangSetUnion
+#undef FcLangSetSubtract
+#undef FcObjectSetCreate
+#undef FcObjectSetAdd
+#undef FcObjectSetDestroy
+#undef FcObjectSetVaBuild
+#undef FcObjectSetBuild
+#undef FcFontSetList
+#undef FcFontList
+#undef FcAtomicCreate
+#undef FcAtomicLock
+#undef FcAtomicNewFile
+#undef FcAtomicOrigFile
+#undef FcAtomicReplaceOrig
+#undef FcAtomicDeleteNew
+#undef FcAtomicUnlock
+#undef FcAtomicDestroy
+#undef FcFontSetMatch
+#undef FcFontMatch
+#undef FcFontRenderPrepare
+#undef FcFontSetSort
+#undef FcFontSort
+#undef FcFontSetSortDestroy
+#undef FcMatrixCopy
+#undef FcMatrixEqual
+#undef FcMatrixMultiply
+#undef FcMatrixRotate
+#undef FcMatrixScale
+#undef FcMatrixShear
+#undef FcNameRegisterObjectTypes
+#undef FcNameUnregisterObjectTypes
+#undef FcNameGetObjectType
+#undef FcNameRegisterConstants
+#undef FcNameUnregisterConstants
+#undef FcNameGetConstant
+#undef FcNameConstant
+#undef FcNameParse
+#undef FcNameUnparse
+#undef FcPatternCreate
+#undef FcPatternDuplicate
+#undef FcPatternReference
+#undef FcPatternFilter
+#undef FcValueDestroy
+#undef FcValueEqual
+#undef FcValueSave
+#undef FcPatternDestroy
+#undef FcPatternEqual
+#undef FcPatternEqualSubset
+#undef FcPatternHash
+#undef FcPatternAdd
+#undef FcPatternAddWeak
+#undef FcPatternGet
+#undef FcPatternGetWithBinding
+#undef FcPatternDel
+#undef FcPatternRemove
+#undef FcPatternAddInteger
+#undef FcPatternAddDouble
+#undef FcPatternAddString
+#undef FcPatternAddMatrix
+#undef FcPatternAddCharSet
+#undef FcPatternAddBool
+#undef FcPatternAddLangSet
+#undef FcPatternAddRange
+#undef FcPatternGetInteger
+#undef FcPatternGetDouble
+#undef FcPatternGetString
+#undef FcPatternGetMatrix
+#undef FcPatternGetCharSet
+#undef FcPatternGetBool
+#undef FcPatternGetLangSet
+#undef FcPatternGetRange
+#undef FcPatternVaBuild
+#undef FcPatternBuild
+#undef FcPatternFormat
+#undef FcRangeCreateDouble
+#undef FcRangeCreateInteger
+#undef FcRangeDestroy
+#undef FcRangeCopy
+#undef FcRangeGetDouble
+#undef FcWeightFromOpenType
+#undef FcWeightToOpenType
+#undef FcStrCopy
+#undef FcStrCopyFilename
+#undef FcStrPlus
+#undef FcStrFree
+#undef FcStrDowncase
+#undef FcStrCmpIgnoreCase
+#undef FcStrCmp
+#undef FcStrStrIgnoreCase
+#undef FcStrStr
+#undef FcUtf8ToUcs4
+#undef FcUtf8Len
+#undef FcUcs4ToUtf8
+#undef FcUtf16ToUcs4
+#undef FcUtf16Len
+#undef FcStrDirname
+#undef FcStrBasename
+#undef FcStrSetCreate
+#undef FcStrSetMember
+#undef FcStrSetEqual
+#undef FcStrSetAdd
+#undef FcStrSetAddFilename
+#undef FcStrSetDel
+#undef FcStrSetDestroy
+#undef FcStrListCreate
+#undef FcStrListFirst
+#undef FcStrListNext
+#undef FcStrListDone
+#undef FcConfigParseAndLoad
+#undef FcConfigParseAndLoadFromMemory
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define FcBlanksCreate FcBlanksCreate_dylibloader_wrapper_fontconfig
+#define FcBlanksDestroy FcBlanksDestroy_dylibloader_wrapper_fontconfig
+#define FcBlanksAdd FcBlanksAdd_dylibloader_wrapper_fontconfig
+#define FcBlanksIsMember FcBlanksIsMember_dylibloader_wrapper_fontconfig
+#define FcCacheDir FcCacheDir_dylibloader_wrapper_fontconfig
+#define FcCacheCopySet FcCacheCopySet_dylibloader_wrapper_fontconfig
+#define FcCacheSubdir FcCacheSubdir_dylibloader_wrapper_fontconfig
+#define FcCacheNumSubdir FcCacheNumSubdir_dylibloader_wrapper_fontconfig
+#define FcCacheNumFont FcCacheNumFont_dylibloader_wrapper_fontconfig
+#define FcDirCacheUnlink FcDirCacheUnlink_dylibloader_wrapper_fontconfig
+#define FcDirCacheValid FcDirCacheValid_dylibloader_wrapper_fontconfig
+#define FcDirCacheClean FcDirCacheClean_dylibloader_wrapper_fontconfig
+#define FcCacheCreateTagFile FcCacheCreateTagFile_dylibloader_wrapper_fontconfig
+#define FcConfigHome FcConfigHome_dylibloader_wrapper_fontconfig
+#define FcConfigEnableHome FcConfigEnableHome_dylibloader_wrapper_fontconfig
+#define FcConfigFilename FcConfigFilename_dylibloader_wrapper_fontconfig
+#define FcConfigCreate FcConfigCreate_dylibloader_wrapper_fontconfig
+#define FcConfigReference FcConfigReference_dylibloader_wrapper_fontconfig
+#define FcConfigDestroy FcConfigDestroy_dylibloader_wrapper_fontconfig
+#define FcConfigSetCurrent FcConfigSetCurrent_dylibloader_wrapper_fontconfig
+#define FcConfigGetCurrent FcConfigGetCurrent_dylibloader_wrapper_fontconfig
+#define FcConfigUptoDate FcConfigUptoDate_dylibloader_wrapper_fontconfig
+#define FcConfigBuildFonts FcConfigBuildFonts_dylibloader_wrapper_fontconfig
+#define FcConfigGetFontDirs FcConfigGetFontDirs_dylibloader_wrapper_fontconfig
+#define FcConfigGetConfigDirs FcConfigGetConfigDirs_dylibloader_wrapper_fontconfig
+#define FcConfigGetConfigFiles FcConfigGetConfigFiles_dylibloader_wrapper_fontconfig
+#define FcConfigGetCache FcConfigGetCache_dylibloader_wrapper_fontconfig
+#define FcConfigGetBlanks FcConfigGetBlanks_dylibloader_wrapper_fontconfig
+#define FcConfigGetCacheDirs FcConfigGetCacheDirs_dylibloader_wrapper_fontconfig
+#define FcConfigGetRescanInterval FcConfigGetRescanInterval_dylibloader_wrapper_fontconfig
+#define FcConfigSetRescanInterval FcConfigSetRescanInterval_dylibloader_wrapper_fontconfig
+#define FcConfigGetFonts FcConfigGetFonts_dylibloader_wrapper_fontconfig
+#define FcConfigAppFontAddFile FcConfigAppFontAddFile_dylibloader_wrapper_fontconfig
+#define FcConfigAppFontAddDir FcConfigAppFontAddDir_dylibloader_wrapper_fontconfig
+#define FcConfigAppFontClear FcConfigAppFontClear_dylibloader_wrapper_fontconfig
+#define FcConfigSubstituteWithPat FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig
+#define FcConfigSubstitute FcConfigSubstitute_dylibloader_wrapper_fontconfig
+#define FcConfigGetSysRoot FcConfigGetSysRoot_dylibloader_wrapper_fontconfig
+#define FcConfigSetSysRoot FcConfigSetSysRoot_dylibloader_wrapper_fontconfig
+#define FcValuePrint FcValuePrint_dylibloader_wrapper_fontconfig
+#define FcPatternPrint FcPatternPrint_dylibloader_wrapper_fontconfig
+#define FcFontSetPrint FcFontSetPrint_dylibloader_wrapper_fontconfig
+#define FcGetDefaultLangs FcGetDefaultLangs_dylibloader_wrapper_fontconfig
+#define FcDefaultSubstitute FcDefaultSubstitute_dylibloader_wrapper_fontconfig
+#define FcFileIsDir FcFileIsDir_dylibloader_wrapper_fontconfig
+#define FcFileScan FcFileScan_dylibloader_wrapper_fontconfig
+#define FcDirScan FcDirScan_dylibloader_wrapper_fontconfig
+#define FcDirSave FcDirSave_dylibloader_wrapper_fontconfig
+#define FcDirCacheLoad FcDirCacheLoad_dylibloader_wrapper_fontconfig
+#define FcDirCacheRescan FcDirCacheRescan_dylibloader_wrapper_fontconfig
+#define FcDirCacheRead FcDirCacheRead_dylibloader_wrapper_fontconfig
+#define FcDirCacheLoadFile FcDirCacheLoadFile_dylibloader_wrapper_fontconfig
+#define FcDirCacheUnload FcDirCacheUnload_dylibloader_wrapper_fontconfig
+#define FcFreeTypeQuery FcFreeTypeQuery_dylibloader_wrapper_fontconfig
+#define FcFontSetCreate FcFontSetCreate_dylibloader_wrapper_fontconfig
+#define FcFontSetDestroy FcFontSetDestroy_dylibloader_wrapper_fontconfig
+#define FcFontSetAdd FcFontSetAdd_dylibloader_wrapper_fontconfig
+#define FcInitLoadConfig FcInitLoadConfig_dylibloader_wrapper_fontconfig
+#define FcInitLoadConfigAndFonts FcInitLoadConfigAndFonts_dylibloader_wrapper_fontconfig
+#define FcInit FcInit_dylibloader_wrapper_fontconfig
+#define FcFini FcFini_dylibloader_wrapper_fontconfig
+#define FcGetVersion FcGetVersion_dylibloader_wrapper_fontconfig
+#define FcInitReinitialize FcInitReinitialize_dylibloader_wrapper_fontconfig
+#define FcInitBringUptoDate FcInitBringUptoDate_dylibloader_wrapper_fontconfig
+#define FcGetLangs FcGetLangs_dylibloader_wrapper_fontconfig
+#define FcLangNormalize FcLangNormalize_dylibloader_wrapper_fontconfig
+#define FcLangGetCharSet FcLangGetCharSet_dylibloader_wrapper_fontconfig
+#define FcLangSetCreate FcLangSetCreate_dylibloader_wrapper_fontconfig
+#define FcLangSetDestroy FcLangSetDestroy_dylibloader_wrapper_fontconfig
+#define FcLangSetCopy FcLangSetCopy_dylibloader_wrapper_fontconfig
+#define FcLangSetAdd FcLangSetAdd_dylibloader_wrapper_fontconfig
+#define FcLangSetDel FcLangSetDel_dylibloader_wrapper_fontconfig
+#define FcLangSetHasLang FcLangSetHasLang_dylibloader_wrapper_fontconfig
+#define FcLangSetCompare FcLangSetCompare_dylibloader_wrapper_fontconfig
+#define FcLangSetContains FcLangSetContains_dylibloader_wrapper_fontconfig
+#define FcLangSetEqual FcLangSetEqual_dylibloader_wrapper_fontconfig
+#define FcLangSetHash FcLangSetHash_dylibloader_wrapper_fontconfig
+#define FcLangSetGetLangs FcLangSetGetLangs_dylibloader_wrapper_fontconfig
+#define FcLangSetUnion FcLangSetUnion_dylibloader_wrapper_fontconfig
+#define FcLangSetSubtract FcLangSetSubtract_dylibloader_wrapper_fontconfig
+#define FcObjectSetCreate FcObjectSetCreate_dylibloader_wrapper_fontconfig
+#define FcObjectSetAdd FcObjectSetAdd_dylibloader_wrapper_fontconfig
+#define FcObjectSetDestroy FcObjectSetDestroy_dylibloader_wrapper_fontconfig
+#define FcObjectSetVaBuild FcObjectSetVaBuild_dylibloader_wrapper_fontconfig
+#define FcObjectSetBuild FcObjectSetBuild_dylibloader_wrapper_fontconfig
+#define FcFontSetList FcFontSetList_dylibloader_wrapper_fontconfig
+#define FcFontList FcFontList_dylibloader_wrapper_fontconfig
+#define FcAtomicCreate FcAtomicCreate_dylibloader_wrapper_fontconfig
+#define FcAtomicLock FcAtomicLock_dylibloader_wrapper_fontconfig
+#define FcAtomicNewFile FcAtomicNewFile_dylibloader_wrapper_fontconfig
+#define FcAtomicOrigFile FcAtomicOrigFile_dylibloader_wrapper_fontconfig
+#define FcAtomicReplaceOrig FcAtomicReplaceOrig_dylibloader_wrapper_fontconfig
+#define FcAtomicDeleteNew FcAtomicDeleteNew_dylibloader_wrapper_fontconfig
+#define FcAtomicUnlock FcAtomicUnlock_dylibloader_wrapper_fontconfig
+#define FcAtomicDestroy FcAtomicDestroy_dylibloader_wrapper_fontconfig
+#define FcFontSetMatch FcFontSetMatch_dylibloader_wrapper_fontconfig
+#define FcFontMatch FcFontMatch_dylibloader_wrapper_fontconfig
+#define FcFontRenderPrepare FcFontRenderPrepare_dylibloader_wrapper_fontconfig
+#define FcFontSetSort FcFontSetSort_dylibloader_wrapper_fontconfig
+#define FcFontSort FcFontSort_dylibloader_wrapper_fontconfig
+#define FcFontSetSortDestroy FcFontSetSortDestroy_dylibloader_wrapper_fontconfig
+#define FcMatrixCopy FcMatrixCopy_dylibloader_wrapper_fontconfig
+#define FcMatrixEqual FcMatrixEqual_dylibloader_wrapper_fontconfig
+#define FcMatrixMultiply FcMatrixMultiply_dylibloader_wrapper_fontconfig
+#define FcMatrixRotate FcMatrixRotate_dylibloader_wrapper_fontconfig
+#define FcMatrixScale FcMatrixScale_dylibloader_wrapper_fontconfig
+#define FcMatrixShear FcMatrixShear_dylibloader_wrapper_fontconfig
+#define FcNameRegisterObjectTypes FcNameRegisterObjectTypes_dylibloader_wrapper_fontconfig
+#define FcNameUnregisterObjectTypes FcNameUnregisterObjectTypes_dylibloader_wrapper_fontconfig
+#define FcNameGetObjectType FcNameGetObjectType_dylibloader_wrapper_fontconfig
+#define FcNameRegisterConstants FcNameRegisterConstants_dylibloader_wrapper_fontconfig
+#define FcNameUnregisterConstants FcNameUnregisterConstants_dylibloader_wrapper_fontconfig
+#define FcNameGetConstant FcNameGetConstant_dylibloader_wrapper_fontconfig
+#define FcNameConstant FcNameConstant_dylibloader_wrapper_fontconfig
+#define FcNameParse FcNameParse_dylibloader_wrapper_fontconfig
+#define FcNameUnparse FcNameUnparse_dylibloader_wrapper_fontconfig
+#define FcPatternCreate FcPatternCreate_dylibloader_wrapper_fontconfig
+#define FcPatternDuplicate FcPatternDuplicate_dylibloader_wrapper_fontconfig
+#define FcPatternReference FcPatternReference_dylibloader_wrapper_fontconfig
+#define FcPatternFilter FcPatternFilter_dylibloader_wrapper_fontconfig
+#define FcValueDestroy FcValueDestroy_dylibloader_wrapper_fontconfig
+#define FcValueEqual FcValueEqual_dylibloader_wrapper_fontconfig
+#define FcValueSave FcValueSave_dylibloader_wrapper_fontconfig
+#define FcPatternDestroy FcPatternDestroy_dylibloader_wrapper_fontconfig
+#define FcPatternEqual FcPatternEqual_dylibloader_wrapper_fontconfig
+#define FcPatternEqualSubset FcPatternEqualSubset_dylibloader_wrapper_fontconfig
+#define FcPatternHash FcPatternHash_dylibloader_wrapper_fontconfig
+#define FcPatternAdd FcPatternAdd_dylibloader_wrapper_fontconfig
+#define FcPatternAddWeak FcPatternAddWeak_dylibloader_wrapper_fontconfig
+#define FcPatternGet FcPatternGet_dylibloader_wrapper_fontconfig
+#define FcPatternGetWithBinding FcPatternGetWithBinding_dylibloader_wrapper_fontconfig
+#define FcPatternDel FcPatternDel_dylibloader_wrapper_fontconfig
+#define FcPatternRemove FcPatternRemove_dylibloader_wrapper_fontconfig
+#define FcPatternAddInteger FcPatternAddInteger_dylibloader_wrapper_fontconfig
+#define FcPatternAddDouble FcPatternAddDouble_dylibloader_wrapper_fontconfig
+#define FcPatternAddString FcPatternAddString_dylibloader_wrapper_fontconfig
+#define FcPatternAddMatrix FcPatternAddMatrix_dylibloader_wrapper_fontconfig
+#define FcPatternAddCharSet FcPatternAddCharSet_dylibloader_wrapper_fontconfig
+#define FcPatternAddBool FcPatternAddBool_dylibloader_wrapper_fontconfig
+#define FcPatternAddLangSet FcPatternAddLangSet_dylibloader_wrapper_fontconfig
+#define FcPatternAddRange FcPatternAddRange_dylibloader_wrapper_fontconfig
+#define FcPatternGetInteger FcPatternGetInteger_dylibloader_wrapper_fontconfig
+#define FcPatternGetDouble FcPatternGetDouble_dylibloader_wrapper_fontconfig
+#define FcPatternGetString FcPatternGetString_dylibloader_wrapper_fontconfig
+#define FcPatternGetMatrix FcPatternGetMatrix_dylibloader_wrapper_fontconfig
+#define FcPatternGetCharSet FcPatternGetCharSet_dylibloader_wrapper_fontconfig
+#define FcPatternGetBool FcPatternGetBool_dylibloader_wrapper_fontconfig
+#define FcPatternGetLangSet FcPatternGetLangSet_dylibloader_wrapper_fontconfig
+#define FcPatternGetRange FcPatternGetRange_dylibloader_wrapper_fontconfig
+#define FcPatternVaBuild FcPatternVaBuild_dylibloader_wrapper_fontconfig
+#define FcPatternBuild FcPatternBuild_dylibloader_wrapper_fontconfig
+#define FcPatternFormat FcPatternFormat_dylibloader_wrapper_fontconfig
+#define FcRangeCreateDouble FcRangeCreateDouble_dylibloader_wrapper_fontconfig
+#define FcRangeCreateInteger FcRangeCreateInteger_dylibloader_wrapper_fontconfig
+#define FcRangeDestroy FcRangeDestroy_dylibloader_wrapper_fontconfig
+#define FcRangeCopy FcRangeCopy_dylibloader_wrapper_fontconfig
+#define FcRangeGetDouble FcRangeGetDouble_dylibloader_wrapper_fontconfig
+#define FcWeightFromOpenType FcWeightFromOpenType_dylibloader_wrapper_fontconfig
+#define FcWeightToOpenType FcWeightToOpenType_dylibloader_wrapper_fontconfig
+#define FcStrCopy FcStrCopy_dylibloader_wrapper_fontconfig
+#define FcStrCopyFilename FcStrCopyFilename_dylibloader_wrapper_fontconfig
+#define FcStrPlus FcStrPlus_dylibloader_wrapper_fontconfig
+#define FcStrFree FcStrFree_dylibloader_wrapper_fontconfig
+#define FcStrDowncase FcStrDowncase_dylibloader_wrapper_fontconfig
+#define FcStrCmpIgnoreCase FcStrCmpIgnoreCase_dylibloader_wrapper_fontconfig
+#define FcStrCmp FcStrCmp_dylibloader_wrapper_fontconfig
+#define FcStrStrIgnoreCase FcStrStrIgnoreCase_dylibloader_wrapper_fontconfig
+#define FcStrStr FcStrStr_dylibloader_wrapper_fontconfig
+#define FcUtf8ToUcs4 FcUtf8ToUcs4_dylibloader_wrapper_fontconfig
+#define FcUtf8Len FcUtf8Len_dylibloader_wrapper_fontconfig
+#define FcUcs4ToUtf8 FcUcs4ToUtf8_dylibloader_wrapper_fontconfig
+#define FcUtf16ToUcs4 FcUtf16ToUcs4_dylibloader_wrapper_fontconfig
+#define FcUtf16Len FcUtf16Len_dylibloader_wrapper_fontconfig
+#define FcStrDirname FcStrDirname_dylibloader_wrapper_fontconfig
+#define FcStrBasename FcStrBasename_dylibloader_wrapper_fontconfig
+#define FcStrSetCreate FcStrSetCreate_dylibloader_wrapper_fontconfig
+#define FcStrSetMember FcStrSetMember_dylibloader_wrapper_fontconfig
+#define FcStrSetEqual FcStrSetEqual_dylibloader_wrapper_fontconfig
+#define FcStrSetAdd FcStrSetAdd_dylibloader_wrapper_fontconfig
+#define FcStrSetAddFilename FcStrSetAddFilename_dylibloader_wrapper_fontconfig
+#define FcStrSetDel FcStrSetDel_dylibloader_wrapper_fontconfig
+#define FcStrSetDestroy FcStrSetDestroy_dylibloader_wrapper_fontconfig
+#define FcStrListCreate FcStrListCreate_dylibloader_wrapper_fontconfig
+#define FcStrListFirst FcStrListFirst_dylibloader_wrapper_fontconfig
+#define FcStrListNext FcStrListNext_dylibloader_wrapper_fontconfig
+#define FcStrListDone FcStrListDone_dylibloader_wrapper_fontconfig
+#define FcConfigParseAndLoad FcConfigParseAndLoad_dylibloader_wrapper_fontconfig
+#define FcConfigParseAndLoadFromMemory FcConfigParseAndLoadFromMemory_dylibloader_wrapper_fontconfig
+extern FcBlanks* (*FcBlanksCreate_dylibloader_wrapper_fontconfig)( void);
+extern void (*FcBlanksDestroy_dylibloader_wrapper_fontconfig)( FcBlanks*);
+extern FcBool (*FcBlanksAdd_dylibloader_wrapper_fontconfig)( FcBlanks*, FcChar32);
+extern FcBool (*FcBlanksIsMember_dylibloader_wrapper_fontconfig)( FcBlanks*, FcChar32);
+extern const FcChar8* (*FcCacheDir_dylibloader_wrapper_fontconfig)(const FcCache*);
+extern FcFontSet* (*FcCacheCopySet_dylibloader_wrapper_fontconfig)(const FcCache*);
+extern const FcChar8* (*FcCacheSubdir_dylibloader_wrapper_fontconfig)(const FcCache*, int);
+extern int (*FcCacheNumSubdir_dylibloader_wrapper_fontconfig)(const FcCache*);
+extern int (*FcCacheNumFont_dylibloader_wrapper_fontconfig)(const FcCache*);
+extern FcBool (*FcDirCacheUnlink_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*);
+extern FcBool (*FcDirCacheValid_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcBool (*FcDirCacheClean_dylibloader_wrapper_fontconfig)(const FcChar8*, FcBool);
+extern void (*FcCacheCreateTagFile_dylibloader_wrapper_fontconfig)(const FcConfig*);
+extern FcChar8* (*FcConfigHome_dylibloader_wrapper_fontconfig)( void);
+extern FcBool (*FcConfigEnableHome_dylibloader_wrapper_fontconfig)( FcBool);
+extern FcChar8* (*FcConfigFilename_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcConfig* (*FcConfigCreate_dylibloader_wrapper_fontconfig)( void);
+extern FcConfig* (*FcConfigReference_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern void (*FcConfigDestroy_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcBool (*FcConfigSetCurrent_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcConfig* (*FcConfigGetCurrent_dylibloader_wrapper_fontconfig)( void);
+extern FcBool (*FcConfigUptoDate_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcBool (*FcConfigBuildFonts_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcStrList* (*FcConfigGetFontDirs_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcStrList* (*FcConfigGetConfigDirs_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcStrList* (*FcConfigGetConfigFiles_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcChar8* (*FcConfigGetCache_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcBlanks* (*FcConfigGetBlanks_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcStrList* (*FcConfigGetCacheDirs_dylibloader_wrapper_fontconfig)(const FcConfig*);
+extern int (*FcConfigGetRescanInterval_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcBool (*FcConfigSetRescanInterval_dylibloader_wrapper_fontconfig)( FcConfig*, int);
+extern FcFontSet* (*FcConfigGetFonts_dylibloader_wrapper_fontconfig)( FcConfig*, FcSetName);
+extern FcBool (*FcConfigAppFontAddFile_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*);
+extern FcBool (*FcConfigAppFontAddDir_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*);
+extern void (*FcConfigAppFontClear_dylibloader_wrapper_fontconfig)( FcConfig*);
+extern FcBool (*FcConfigSubstituteWithPat_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcPattern*, FcMatchKind);
+extern FcBool (*FcConfigSubstitute_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcMatchKind);
+extern const FcChar8* (*FcConfigGetSysRoot_dylibloader_wrapper_fontconfig)(const FcConfig*);
+extern void (*FcConfigSetSysRoot_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*);
+extern void (*FcValuePrint_dylibloader_wrapper_fontconfig)(const FcValue);
+extern void (*FcPatternPrint_dylibloader_wrapper_fontconfig)(const FcPattern*);
+extern void (*FcFontSetPrint_dylibloader_wrapper_fontconfig)(const FcFontSet*);
+extern FcStrSet* (*FcGetDefaultLangs_dylibloader_wrapper_fontconfig)( void);
+extern void (*FcDefaultSubstitute_dylibloader_wrapper_fontconfig)( FcPattern*);
+extern FcBool (*FcFileIsDir_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcBool (*FcFileScan_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*, FcFileCache*, FcBlanks*,const FcChar8*, FcBool);
+extern FcBool (*FcDirScan_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*, FcFileCache*, FcBlanks*,const FcChar8*, FcBool);
+extern FcBool (*FcDirSave_dylibloader_wrapper_fontconfig)( FcFontSet*, FcStrSet*,const FcChar8*);
+extern FcCache* (*FcDirCacheLoad_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*, FcChar8**);
+extern FcCache* (*FcDirCacheRescan_dylibloader_wrapper_fontconfig)(const FcChar8*, FcConfig*);
+extern FcCache* (*FcDirCacheRead_dylibloader_wrapper_fontconfig)(const FcChar8*, FcBool, FcConfig*);
+extern FcCache* (*FcDirCacheLoadFile_dylibloader_wrapper_fontconfig)(const FcChar8*,struct stat*);
+extern void (*FcDirCacheUnload_dylibloader_wrapper_fontconfig)( FcCache*);
+extern FcPattern* (*FcFreeTypeQuery_dylibloader_wrapper_fontconfig)(const FcChar8*, int, FcBlanks*, int*);
+extern FcFontSet* (*FcFontSetCreate_dylibloader_wrapper_fontconfig)( void);
+extern void (*FcFontSetDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*);
+extern FcBool (*FcFontSetAdd_dylibloader_wrapper_fontconfig)( FcFontSet*, FcPattern*);
+extern FcConfig* (*FcInitLoadConfig_dylibloader_wrapper_fontconfig)( void);
+extern FcConfig* (*FcInitLoadConfigAndFonts_dylibloader_wrapper_fontconfig)( void);
+extern FcBool (*FcInit_dylibloader_wrapper_fontconfig)( void);
+extern void (*FcFini_dylibloader_wrapper_fontconfig)( void);
+extern int (*FcGetVersion_dylibloader_wrapper_fontconfig)( void);
+extern FcBool (*FcInitReinitialize_dylibloader_wrapper_fontconfig)( void);
+extern FcBool (*FcInitBringUptoDate_dylibloader_wrapper_fontconfig)( void);
+extern FcStrSet* (*FcGetLangs_dylibloader_wrapper_fontconfig)( void);
+extern FcChar8* (*FcLangNormalize_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern const FcCharSet* (*FcLangGetCharSet_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcLangSet* (*FcLangSetCreate_dylibloader_wrapper_fontconfig)( void);
+extern void (*FcLangSetDestroy_dylibloader_wrapper_fontconfig)( FcLangSet*);
+extern FcLangSet* (*FcLangSetCopy_dylibloader_wrapper_fontconfig)(const FcLangSet*);
+extern FcBool (*FcLangSetAdd_dylibloader_wrapper_fontconfig)( FcLangSet*,const FcChar8*);
+extern FcBool (*FcLangSetDel_dylibloader_wrapper_fontconfig)( FcLangSet*,const FcChar8*);
+extern FcLangResult (*FcLangSetHasLang_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcChar8*);
+extern FcLangResult (*FcLangSetCompare_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+extern FcBool (*FcLangSetContains_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+extern FcBool (*FcLangSetEqual_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+extern FcChar32 (*FcLangSetHash_dylibloader_wrapper_fontconfig)(const FcLangSet*);
+extern FcStrSet* (*FcLangSetGetLangs_dylibloader_wrapper_fontconfig)(const FcLangSet*);
+extern FcLangSet* (*FcLangSetUnion_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+extern FcLangSet* (*FcLangSetSubtract_dylibloader_wrapper_fontconfig)(const FcLangSet*,const FcLangSet*);
+extern FcObjectSet* (*FcObjectSetCreate_dylibloader_wrapper_fontconfig)( void);
+extern FcBool (*FcObjectSetAdd_dylibloader_wrapper_fontconfig)( FcObjectSet*,const char*);
+extern void (*FcObjectSetDestroy_dylibloader_wrapper_fontconfig)( FcObjectSet*);
+extern FcObjectSet* (*FcObjectSetVaBuild_dylibloader_wrapper_fontconfig)(const char*, va_list);
+extern FcObjectSet* (*FcObjectSetBuild_dylibloader_wrapper_fontconfig)(const char*,...);
+extern FcFontSet* (*FcFontSetList_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcObjectSet*);
+extern FcFontSet* (*FcFontList_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcObjectSet*);
+extern FcAtomic* (*FcAtomicCreate_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcBool (*FcAtomicLock_dylibloader_wrapper_fontconfig)( FcAtomic*);
+extern FcChar8* (*FcAtomicNewFile_dylibloader_wrapper_fontconfig)( FcAtomic*);
+extern FcChar8* (*FcAtomicOrigFile_dylibloader_wrapper_fontconfig)( FcAtomic*);
+extern FcBool (*FcAtomicReplaceOrig_dylibloader_wrapper_fontconfig)( FcAtomic*);
+extern void (*FcAtomicDeleteNew_dylibloader_wrapper_fontconfig)( FcAtomic*);
+extern void (*FcAtomicUnlock_dylibloader_wrapper_fontconfig)( FcAtomic*);
+extern void (*FcAtomicDestroy_dylibloader_wrapper_fontconfig)( FcAtomic*);
+extern FcPattern* (*FcFontSetMatch_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcResult*);
+extern FcPattern* (*FcFontMatch_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcResult*);
+extern FcPattern* (*FcFontRenderPrepare_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcPattern*);
+extern FcFontSet* (*FcFontSetSort_dylibloader_wrapper_fontconfig)( FcConfig*, FcFontSet**, int, FcPattern*, FcBool, FcCharSet**, FcResult*);
+extern FcFontSet* (*FcFontSort_dylibloader_wrapper_fontconfig)( FcConfig*, FcPattern*, FcBool, FcCharSet**, FcResult*);
+extern void (*FcFontSetSortDestroy_dylibloader_wrapper_fontconfig)( FcFontSet*);
+extern FcMatrix* (*FcMatrixCopy_dylibloader_wrapper_fontconfig)(const FcMatrix*);
+extern FcBool (*FcMatrixEqual_dylibloader_wrapper_fontconfig)(const FcMatrix*,const FcMatrix*);
+extern void (*FcMatrixMultiply_dylibloader_wrapper_fontconfig)( FcMatrix*,const FcMatrix*,const FcMatrix*);
+extern void (*FcMatrixRotate_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double);
+extern void (*FcMatrixScale_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double);
+extern void (*FcMatrixShear_dylibloader_wrapper_fontconfig)( FcMatrix*, double, double);
+extern FcBool (*FcNameRegisterObjectTypes_dylibloader_wrapper_fontconfig)(const FcObjectType*, int);
+extern FcBool (*FcNameUnregisterObjectTypes_dylibloader_wrapper_fontconfig)(const FcObjectType*, int);
+extern const FcObjectType* (*FcNameGetObjectType_dylibloader_wrapper_fontconfig)(const char*);
+extern FcBool (*FcNameRegisterConstants_dylibloader_wrapper_fontconfig)(const FcConstant*, int);
+extern FcBool (*FcNameUnregisterConstants_dylibloader_wrapper_fontconfig)(const FcConstant*, int);
+extern const FcConstant* (*FcNameGetConstant_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcBool (*FcNameConstant_dylibloader_wrapper_fontconfig)(const FcChar8*, int*);
+extern FcPattern* (*FcNameParse_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcChar8* (*FcNameUnparse_dylibloader_wrapper_fontconfig)( FcPattern*);
+extern FcPattern* (*FcPatternCreate_dylibloader_wrapper_fontconfig)( void);
+extern FcPattern* (*FcPatternDuplicate_dylibloader_wrapper_fontconfig)(const FcPattern*);
+extern void (*FcPatternReference_dylibloader_wrapper_fontconfig)( FcPattern*);
+extern FcPattern* (*FcPatternFilter_dylibloader_wrapper_fontconfig)( FcPattern*,const FcObjectSet*);
+extern void (*FcValueDestroy_dylibloader_wrapper_fontconfig)( FcValue);
+extern FcBool (*FcValueEqual_dylibloader_wrapper_fontconfig)( FcValue, FcValue);
+extern FcValue (*FcValueSave_dylibloader_wrapper_fontconfig)( FcValue);
+extern void (*FcPatternDestroy_dylibloader_wrapper_fontconfig)( FcPattern*);
+extern FcBool (*FcPatternEqual_dylibloader_wrapper_fontconfig)(const FcPattern*,const FcPattern*);
+extern FcBool (*FcPatternEqualSubset_dylibloader_wrapper_fontconfig)(const FcPattern*,const FcPattern*,const FcObjectSet*);
+extern FcChar32 (*FcPatternHash_dylibloader_wrapper_fontconfig)(const FcPattern*);
+extern FcBool (*FcPatternAdd_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcValue, FcBool);
+extern FcBool (*FcPatternAddWeak_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcValue, FcBool);
+extern FcResult (*FcPatternGet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcValue*);
+extern FcResult (*FcPatternGetWithBinding_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcValue*, FcValueBinding*);
+extern FcBool (*FcPatternDel_dylibloader_wrapper_fontconfig)( FcPattern*,const char*);
+extern FcBool (*FcPatternRemove_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, int);
+extern FcBool (*FcPatternAddInteger_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, int);
+extern FcBool (*FcPatternAddDouble_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, double);
+extern FcBool (*FcPatternAddString_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcChar8*);
+extern FcBool (*FcPatternAddMatrix_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcMatrix*);
+extern FcBool (*FcPatternAddCharSet_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcCharSet*);
+extern FcBool (*FcPatternAddBool_dylibloader_wrapper_fontconfig)( FcPattern*,const char*, FcBool);
+extern FcBool (*FcPatternAddLangSet_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcLangSet*);
+extern FcBool (*FcPatternAddRange_dylibloader_wrapper_fontconfig)( FcPattern*,const char*,const FcRange*);
+extern FcResult (*FcPatternGetInteger_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, int*);
+extern FcResult (*FcPatternGetDouble_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, double*);
+extern FcResult (*FcPatternGetString_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcChar8**);
+extern FcResult (*FcPatternGetMatrix_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcMatrix**);
+extern FcResult (*FcPatternGetCharSet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcCharSet**);
+extern FcResult (*FcPatternGetBool_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcBool*);
+extern FcResult (*FcPatternGetLangSet_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcLangSet**);
+extern FcResult (*FcPatternGetRange_dylibloader_wrapper_fontconfig)(const FcPattern*,const char*, int, FcRange**);
+extern FcPattern* (*FcPatternVaBuild_dylibloader_wrapper_fontconfig)( FcPattern*, va_list);
+extern FcPattern* (*FcPatternBuild_dylibloader_wrapper_fontconfig)( FcPattern*,...);
+extern FcChar8* (*FcPatternFormat_dylibloader_wrapper_fontconfig)( FcPattern*,const FcChar8*);
+extern FcRange* (*FcRangeCreateDouble_dylibloader_wrapper_fontconfig)( double, double);
+extern FcRange* (*FcRangeCreateInteger_dylibloader_wrapper_fontconfig)( FcChar32, FcChar32);
+extern void (*FcRangeDestroy_dylibloader_wrapper_fontconfig)( FcRange*);
+extern FcRange* (*FcRangeCopy_dylibloader_wrapper_fontconfig)(const FcRange*);
+extern FcBool (*FcRangeGetDouble_dylibloader_wrapper_fontconfig)(const FcRange*, double*, double*);
+extern int (*FcWeightFromOpenType_dylibloader_wrapper_fontconfig)( int);
+extern int (*FcWeightToOpenType_dylibloader_wrapper_fontconfig)( int);
+extern FcChar8* (*FcStrCopy_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcChar8* (*FcStrCopyFilename_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcChar8* (*FcStrPlus_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+extern void (*FcStrFree_dylibloader_wrapper_fontconfig)( FcChar8*);
+extern FcChar8* (*FcStrDowncase_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern int (*FcStrCmpIgnoreCase_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+extern int (*FcStrCmp_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+extern const FcChar8* (*FcStrStrIgnoreCase_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+extern const FcChar8* (*FcStrStr_dylibloader_wrapper_fontconfig)(const FcChar8*,const FcChar8*);
+extern int (*FcUtf8ToUcs4_dylibloader_wrapper_fontconfig)(const FcChar8*, FcChar32*, int);
+extern FcBool (*FcUtf8Len_dylibloader_wrapper_fontconfig)(const FcChar8*, int, int*, int*);
+extern int (*FcUcs4ToUtf8_dylibloader_wrapper_fontconfig)( FcChar32, FcChar8 [6]);
+extern int (*FcUtf16ToUcs4_dylibloader_wrapper_fontconfig)(const FcChar8*, FcEndian, FcChar32*, int);
+extern FcBool (*FcUtf16Len_dylibloader_wrapper_fontconfig)(const FcChar8*, FcEndian, int, int*, int*);
+extern FcChar8* (*FcStrDirname_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcChar8* (*FcStrBasename_dylibloader_wrapper_fontconfig)(const FcChar8*);
+extern FcStrSet* (*FcStrSetCreate_dylibloader_wrapper_fontconfig)( void);
+extern FcBool (*FcStrSetMember_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*);
+extern FcBool (*FcStrSetEqual_dylibloader_wrapper_fontconfig)( FcStrSet*, FcStrSet*);
+extern FcBool (*FcStrSetAdd_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*);
+extern FcBool (*FcStrSetAddFilename_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*);
+extern FcBool (*FcStrSetDel_dylibloader_wrapper_fontconfig)( FcStrSet*,const FcChar8*);
+extern void (*FcStrSetDestroy_dylibloader_wrapper_fontconfig)( FcStrSet*);
+extern FcStrList* (*FcStrListCreate_dylibloader_wrapper_fontconfig)( FcStrSet*);
+extern void (*FcStrListFirst_dylibloader_wrapper_fontconfig)( FcStrList*);
+extern FcChar8* (*FcStrListNext_dylibloader_wrapper_fontconfig)( FcStrList*);
+extern void (*FcStrListDone_dylibloader_wrapper_fontconfig)( FcStrList*);
+extern FcBool (*FcConfigParseAndLoad_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*, FcBool);
+extern FcBool (*FcConfigParseAndLoadFromMemory_dylibloader_wrapper_fontconfig)( FcConfig*,const FcChar8*, FcBool);
+int initialize_fontconfig(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp
index 1e93334e40..fa3f7fbfea 100644
--- a/platform/linuxbsd/freedesktop_screensaver.cpp
+++ b/platform/linuxbsd/freedesktop_screensaver.cpp
@@ -34,7 +34,7 @@
#include "core/config/project_settings.h"
-#include <dbus/dbus.h>
+#include "dbus-so_wrap.h"
#define BUS_OBJECT_NAME "org.freedesktop.ScreenSaver"
#define BUS_OBJECT_PATH "/org/freedesktop/ScreenSaver"
@@ -126,4 +126,13 @@ void FreeDesktopScreenSaver::uninhibit() {
dbus_connection_unref(bus);
}
+FreeDesktopScreenSaver::FreeDesktopScreenSaver() {
+#ifdef DEBUG_ENABLED
+ int dylibloader_verbose = 1;
+#else
+ int dylibloader_verbose = 0;
+#endif
+ unsupported = (initialize_dbus(dylibloader_verbose) != 0);
+}
+
#endif // DBUS_ENABLED
diff --git a/platform/linuxbsd/freedesktop_screensaver.h b/platform/linuxbsd/freedesktop_screensaver.h
index b2303791bd..1a8b010cd5 100644
--- a/platform/linuxbsd/freedesktop_screensaver.h
+++ b/platform/linuxbsd/freedesktop_screensaver.h
@@ -28,9 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef FREEDESKTOP_SCREENSAVER_H
+#define FREEDESKTOP_SCREENSAVER_H
+
#ifdef DBUS_ENABLED
-#include <dbus/dbus.h>
#include <stdint.h>
class FreeDesktopScreenSaver {
@@ -39,9 +41,11 @@ private:
bool unsupported = false;
public:
- FreeDesktopScreenSaver() {}
+ FreeDesktopScreenSaver();
void inhibit();
void uninhibit();
};
#endif // DBUS_ENABLED
+
+#endif // FREEDESKTOP_SCREENSAVER_H
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/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index b73d4dc626..e306c1054b 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -52,6 +52,10 @@
#include <sys/types.h>
#include <unistd.h>
+#ifdef FONTCONFIG_ENABLED
+#include "fontconfig-so_wrap.h"
+#endif
+
void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
@@ -327,6 +331,98 @@ uint64_t OS_LinuxBSD::get_embedded_pck_offset() const {
return off;
}
+Vector<String> OS_LinuxBSD::get_system_fonts() const {
+#ifdef FONTCONFIG_ENABLED
+ if (!font_config_initialized) {
+ ERR_FAIL_V_MSG(Vector<String>(), "Unable to load fontconfig, system font support is disabled.");
+ }
+ HashSet<String> font_names;
+ Vector<String> ret;
+
+ FcConfig *config = FcInitLoadConfigAndFonts();
+ ERR_FAIL_COND_V(!config, ret);
+
+ FcObjectSet *object_set = FcObjectSetBuild(FC_FAMILY, nullptr);
+ ERR_FAIL_COND_V(!object_set, ret);
+
+ static const char *allowed_formats[] = { "TrueType", "CFF" };
+ for (size_t i = 0; i < sizeof(allowed_formats) / sizeof(const char *); i++) {
+ FcPattern *pattern = FcPatternCreate();
+ ERR_CONTINUE(!pattern);
+
+ FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
+ FcPatternAddString(pattern, FC_FONTFORMAT, reinterpret_cast<const FcChar8 *>(allowed_formats[i]));
+
+ FcFontSet *font_set = FcFontList(config, pattern, object_set);
+ if (font_set) {
+ for (int j = 0; j < font_set->nfont; j++) {
+ char *family_name = nullptr;
+ if (FcPatternGetString(font_set->fonts[j], FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) {
+ if (family_name) {
+ font_names.insert(String::utf8(family_name));
+ }
+ }
+ }
+ FcFontSetDestroy(font_set);
+ }
+ FcPatternDestroy(pattern);
+ }
+ FcObjectSetDestroy(object_set);
+
+ for (const String &E : font_names) {
+ ret.push_back(E);
+ }
+ return ret;
+#else
+ ERR_FAIL_V_MSG(Vector<String>(), "Godot was compiled without fontconfig, system font support is disabled.");
+#endif
+}
+
+String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
+#ifdef FONTCONFIG_ENABLED
+ if (!font_config_initialized) {
+ ERR_FAIL_V_MSG(String(), "Unable to load fontconfig, system font support is disabled.");
+ }
+
+ String ret;
+
+ FcConfig *config = FcInitLoadConfigAndFonts();
+ ERR_FAIL_COND_V(!config, ret);
+
+ FcObjectSet *object_set = FcObjectSetBuild(FC_FAMILY, FC_FILE, nullptr);
+ ERR_FAIL_COND_V(!object_set, ret);
+
+ FcPattern *pattern = FcPatternCreate();
+ if (pattern) {
+ FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
+ FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
+ FcPatternAddInteger(pattern, FC_WEIGHT, p_bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL);
+ FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
+
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcResult result;
+ FcPattern *match = FcFontMatch(0, pattern, &result);
+ if (match) {
+ char *file_name = nullptr;
+ if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
+ if (file_name) {
+ ret = String::utf8(file_name);
+ }
+ }
+
+ FcPatternDestroy(match);
+ }
+ FcPatternDestroy(pattern);
+ }
+ FcObjectSetDestroy(object_set);
+ return ret;
+#else
+ ERR_FAIL_V_MSG(String(), "Godot was compiled without fontconfig, system font support is disabled.");
+#endif
+}
+
String OS_LinuxBSD::get_config_path() const {
if (has_environment("XDG_CONFIG_HOME")) {
if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
@@ -644,4 +740,13 @@ OS_LinuxBSD::OS_LinuxBSD() {
#ifdef X11_ENABLED
DisplayServerX11::register_x11_driver();
#endif
+
+#ifdef FONTCONFIG_ENABLED
+#ifdef DEBUG_ENABLED
+ int dylibloader_verbose = 1;
+#else
+ int dylibloader_verbose = 0;
+#endif
+ font_config_initialized = (initialize_fontconfig(dylibloader_verbose) == 0);
+#endif // FONTCONFIG_ENABLED
}
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index 3f97b86eae..cc4e91e885 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -45,6 +45,10 @@ class OS_LinuxBSD : public OS_Unix {
bool force_quit;
+#ifdef FONTCONFIG_ENABLED
+ bool font_config_initialized = false;
+#endif
+
#ifdef JOYDEV_ENABLED
JoypadLinux *joypad = nullptr;
#endif
@@ -80,6 +84,9 @@ public:
virtual uint64_t get_embedded_pck_offset() const override;
+ virtual Vector<String> get_system_fonts() const override;
+ virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override;
+
virtual String get_config_path() const override;
virtual String get_data_path() const override;
virtual String get_cache_path() const override;
@@ -105,4 +112,4 @@ public:
OS_LinuxBSD();
};
-#endif
+#endif // OS_LINUXBSD_H
diff --git a/platform/linuxbsd/vulkan_context_x11.h b/platform/linuxbsd/vulkan_context_x11.h
index a89afa2eff..0c4a6cd278 100644
--- a/platform/linuxbsd/vulkan_context_x11.h
+++ b/platform/linuxbsd/vulkan_context_x11.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VULKAN_DEVICE_X11_H
-#define VULKAN_DEVICE_X11_H
+#ifndef VULKAN_CONTEXT_X11_H
+#define VULKAN_CONTEXT_X11_H
#include "drivers/vulkan/vulkan_context.h"
#include <X11/Xlib.h>
@@ -44,4 +44,4 @@ public:
~VulkanContextX11();
};
-#endif // VULKAN_DEVICE_X11_H
+#endif // VULKAN_CONTEXT_X11_H
diff --git a/platform/macos/SCsub b/platform/macos/SCsub
new file mode 100644
index 0000000000..d0856c709a
--- /dev/null
+++ b/platform/macos/SCsub
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+
+Import("env")
+
+from platform_methods import run_in_subprocess
+import platform_macos_builders
+
+files = [
+ "os_macos.mm",
+ "godot_application.mm",
+ "godot_application_delegate.mm",
+ "crash_handler_macos.mm",
+ "macos_terminal_logger.mm",
+ "display_server_macos.mm",
+ "godot_content_view.mm",
+ "godot_window_delegate.mm",
+ "godot_window.mm",
+ "key_mapping_macos.mm",
+ "godot_main_macos.mm",
+ "dir_access_macos.mm",
+ "tts_macos.mm",
+ "joypad_macos.cpp",
+ "vulkan_context_macos.mm",
+ "gl_manager_macos_legacy.mm",
+]
+
+prog = env.add_program("#bin/godot", files)
+
+if env["debug_symbols"] and env["separate_debug_symbols"]:
+ env.AddPostAction(prog, run_in_subprocess(platform_macos_builders.make_debug_macos))
diff --git a/platform/osx/crash_handler_osx.h b/platform/macos/crash_handler_macos.h
index 72938e5e0a..c9b0e77dc4 100644
--- a/platform/osx/crash_handler_osx.h
+++ b/platform/macos/crash_handler_macos.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* crash_handler_osx.h */
+/* crash_handler_macos.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CRASH_HANDLER_OSX_H
-#define CRASH_HANDLER_OSX_H
+#ifndef CRASH_HANDLER_MACOS_H
+#define CRASH_HANDLER_MACOS_H
class CrashHandler {
bool disabled;
@@ -44,4 +44,4 @@ public:
~CrashHandler();
};
-#endif // CRASH_HANDLER_OSX_H
+#endif // CRASH_HANDLER_MACOS_H
diff --git a/platform/osx/crash_handler_osx.mm b/platform/macos/crash_handler_macos.mm
index a798ba3b46..74bd012f0c 100644
--- a/platform/osx/crash_handler_osx.mm
+++ b/platform/macos/crash_handler_macos.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* crash_handler_osx.mm */
+/* crash_handler_macos.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "crash_handler_osx.h"
+#include "crash_handler_macos.h"
#include "core/config/project_settings.h"
#include "core/os/os.h"
diff --git a/platform/osx/detect.py b/platform/macos/detect.py
index 8d848d2094..20e7afa772 100644
--- a/platform/osx/detect.py
+++ b/platform/macos/detect.py
@@ -8,7 +8,7 @@ def is_active():
def get_name():
- return "OSX"
+ return "macOS"
def can_build():
@@ -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):
@@ -67,7 +98,7 @@ def configure(env):
## Architecture
- # Mac OS X no longer runs on 32-bit since 10.7 which is unsupported since 2014
+ # macOS no longer runs on 32-bit since 10.7 which is unsupported since 2014
# As such, we only support 64-bit
env["bits"] = "64"
@@ -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"])
@@ -101,7 +134,7 @@ def configure(env):
env["CC"] = "clang"
env["CXX"] = "clang++"
- detect_darwin_sdk_path("osx", env)
+ detect_darwin_sdk_path("macos", env)
env.Append(CCFLAGS=["-isysroot", "$MACOS_SDK_PATH"])
env.Append(LINKFLAGS=["-isysroot", "$MACOS_SDK_PATH"])
@@ -158,8 +191,10 @@ def configure(env):
## Flags
- env.Prepend(CPPPATH=["#platform/osx"])
- env.Append(CPPDEFINES=["OSX_ENABLED", "UNIX_ENABLED", "APPLE_STYLE_KEYS", "COREAUDIO_ENABLED", "COREMIDI_ENABLED"])
+ env.Prepend(CPPPATH=["#platform/macos"])
+ env.Append(
+ CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED", "APPLE_STYLE_KEYS", "COREAUDIO_ENABLED", "COREMIDI_ENABLED"]
+ )
env.Append(
LINKFLAGS=[
"-framework",
@@ -197,4 +232,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/dir_access_osx.h b/platform/macos/dir_access_macos.h
index 3c66c81d4f..920e69ef3e 100644
--- a/platform/osx/dir_access_osx.h
+++ b/platform/macos/dir_access_macos.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* dir_access_osx.h */
+/* dir_access_macos.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef DIR_ACCESS_OSX_H
-#define DIR_ACCESS_OSX_H
+#ifndef DIR_ACCESS_MACOS_H
+#define DIR_ACCESS_MACOS_H
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
@@ -41,15 +41,16 @@
#include "core/io/dir_access.h"
#include "drivers/unix/dir_access_unix.h"
-class DirAccessOSX : public DirAccessUnix {
+class DirAccessMacOS : public DirAccessUnix {
protected:
- virtual String fix_unicode_name(const char *p_name) const;
+ virtual String fix_unicode_name(const char *p_name) const 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 bool is_hidden(const String &p_name);
+ virtual bool is_hidden(const String &p_name) override;
};
-#endif //UNIX ENABLED
-#endif
+#endif // UNIX ENABLED || LIBC_FILEIO_ENABLED
+
+#endif // DIR_ACCESS_MACOS_H
diff --git a/platform/osx/dir_access_osx.mm b/platform/macos/dir_access_macos.mm
index 6bafb9470d..94d937a7dc 100644
--- a/platform/osx/dir_access_osx.mm
+++ b/platform/macos/dir_access_macos.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* dir_access_osx.mm */
+/* dir_access_macos.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "dir_access_osx.h"
+#include "dir_access_macos.h"
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
@@ -37,7 +37,7 @@
#import <AppKit/NSWorkspace.h>
#import <Foundation/Foundation.h>
-String DirAccessOSX::fix_unicode_name(const char *p_name) const {
+String DirAccessMacOS::fix_unicode_name(const char *p_name) const {
String fname;
NSString *nsstr = [[NSString stringWithUTF8String:p_name] precomposedStringWithCanonicalMapping];
@@ -46,14 +46,14 @@ String DirAccessOSX::fix_unicode_name(const char *p_name) const {
return fname;
}
-int DirAccessOSX::get_drive_count() {
+int DirAccessMacOS::get_drive_count() {
NSArray *res_keys = [NSArray arrayWithObjects:NSURLVolumeURLKey, NSURLIsSystemImmutableKey, nil];
NSArray *vols = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:res_keys options:NSVolumeEnumerationSkipHiddenVolumes];
return [vols count];
}
-String DirAccessOSX::get_drive(int p_drive) {
+String DirAccessMacOS::get_drive(int p_drive) {
NSArray *res_keys = [NSArray arrayWithObjects:NSURLVolumeURLKey, NSURLIsSystemImmutableKey, nil];
NSArray *vols = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:res_keys options:NSVolumeEnumerationSkipHiddenVolumes];
int count = [vols count];
@@ -68,7 +68,7 @@ String DirAccessOSX::get_drive(int p_drive) {
return volname;
}
-bool DirAccessOSX::is_hidden(const String &p_name) {
+bool DirAccessMacOS::is_hidden(const String &p_name) {
String f = get_current_dir().plus_file(p_name);
NSURL *url = [NSURL fileURLWithPath:@(f.utf8().get_data())];
NSNumber *hidden = nil;
@@ -78,4 +78,4 @@ bool DirAccessOSX::is_hidden(const String &p_name) {
return [hidden boolValue];
}
-#endif //posix_enabled
+#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
diff --git a/platform/osx/display_server_osx.h b/platform/macos/display_server_macos.h
index 9575cb29a2..54c479fc81 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/macos/display_server_macos.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* display_server_osx.h */
+/* display_server_macos.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef DISPLAY_SERVER_OSX_H
-#define DISPLAY_SERVER_OSX_H
+#ifndef DISPLAY_SERVER_MACOS_H
+#define DISPLAY_SERVER_MACOS_H
#define BitMap _QDBitMap // Suppress deprecated QuickDraw definition.
@@ -37,12 +37,12 @@
#include "servers/display_server.h"
#if defined(GLES3_ENABLED)
-#include "gl_manager_osx_legacy.h"
+#include "gl_manager_macos_legacy.h"
#endif // GLES3_ENABLED
#if defined(VULKAN_ENABLED)
#include "drivers/vulkan/rendering_device_vulkan.h"
-#include "platform/osx/vulkan_context_osx.h"
+#include "platform/macos/vulkan_context_macos.h"
#endif // VULKAN_ENABLED
#import <AppKit/AppKit.h>
@@ -50,19 +50,20 @@
#import <ApplicationServices/ApplicationServices.h>
#import <CoreVideo/CoreVideo.h>
#import <Foundation/Foundation.h>
+#import <IOKit/pwr_mgt/IOPMLib.h>
#undef BitMap
#undef CursorShape
-class DisplayServerOSX : public DisplayServer {
- GDCLASS(DisplayServerOSX, DisplayServer)
+class DisplayServerMacOS : public DisplayServer {
+ GDCLASS(DisplayServerMacOS, DisplayServer)
_THREAD_SAFE_CLASS_
public:
struct KeyEvent {
WindowID window_id = INVALID_WINDOW_ID;
- unsigned int osx_state = false;
+ unsigned int macos_state = false;
bool pressed = false;
bool echo = false;
bool raw = false;
@@ -115,10 +116,10 @@ public:
private:
#if defined(GLES3_ENABLED)
- GLManager_OSX *gl_manager = nullptr;
+ GLManager_MacOS *gl_manager = nullptr;
#endif
#if defined(VULKAN_ENABLED)
- VulkanContextOSX *context_vulkan = nullptr;
+ VulkanContextMacOS *context_vulkan = nullptr;
RenderingDeviceVulkan *rendering_device_vulkan = nullptr;
#endif
String rendering_driver;
@@ -171,6 +172,8 @@ private:
HashMap<WindowID, WindowData> windows;
+ IOPMAssertionID screen_keep_on_assertion = kIOPMNullAssertionID;
+
const NSMenu *_get_menu_root(const String &p_menu_root) const;
NSMenu *_get_menu_root(const String &p_menu_root);
@@ -203,7 +206,7 @@ public:
void send_event(NSEvent *p_event);
void send_window_event(const WindowData &p_wd, WindowEvent p_event);
void release_pressed_events();
- void get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> r_state) const;
+ void get_key_modifier_state(unsigned int p_macos_state, Ref<InputEventWithModifiers> r_state) const;
void update_mouse_pos(WindowData &p_wd, NSPoint p_location_in_window);
void push_to_key_event_buffer(const KeyEvent &p_event);
void update_im_text(const Point2i &p_selection, const String &p_text);
@@ -299,6 +302,8 @@ public:
virtual float screen_get_max_scale() const override;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual void screen_set_keep_on(bool p_enable) override;
+ virtual bool screen_is_kept_on() const override;
virtual Vector<int> get_window_list() const override;
@@ -397,10 +402,10 @@ public:
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
- static void register_osx_driver();
+ static void register_macos_driver();
- DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
- ~DisplayServerOSX();
+ DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ ~DisplayServerMacOS();
};
-#endif // DISPLAY_SERVER_OSX_H
+#endif // DISPLAY_SERVER_MACOS_H
diff --git a/platform/osx/display_server_osx.mm b/platform/macos/display_server_macos.mm
index b6a5813bd0..e228007246 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/macos/display_server_macos.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* display_server_osx.mm */
+/* display_server_macos.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,17 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "display_server_osx.h"
+#include "display_server_macos.h"
#include "godot_content_view.h"
#include "godot_menu_item.h"
#include "godot_window.h"
#include "godot_window_delegate.h"
-#include "key_mapping_osx.h"
-#include "os_osx.h"
+#include "key_mapping_macos.h"
+#include "os_macos.h"
-#include "tts_osx.h"
+#include "tts_macos.h"
+#include "core/config/project_settings.h"
#include "core/io/marshalls.h"
#include "core/math/geometry_2d.h"
#include "core/os/keyboard.h"
@@ -60,7 +61,7 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#endif
-const NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) const {
+const NSMenu *DisplayServerMacOS::_get_menu_root(const String &p_menu_root) const {
const NSMenu *menu = nullptr;
if (p_menu_root == "") {
// Main menu.
@@ -81,7 +82,7 @@ const NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) const
return menu;
}
-NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) {
+NSMenu *DisplayServerMacOS::_get_menu_root(const String &p_menu_root) {
NSMenu *menu = nullptr;
if (p_menu_root == "") {
// Main menu.
@@ -105,7 +106,7 @@ NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) {
return menu;
}
-DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect) {
+DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect) {
WindowID id;
const float scale = screen_get_max_scale();
{
@@ -193,7 +194,7 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, V
return id;
}
-void DisplayServerOSX::_update_window_style(WindowData p_wd) {
+void DisplayServerMacOS::_update_window_style(WindowData p_wd) {
bool borderless_full = false;
if (p_wd.borderless) {
@@ -222,7 +223,7 @@ void DisplayServerOSX::_update_window_style(WindowData p_wd) {
}
}
-void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window) {
+void DisplayServerMacOS::_set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
@@ -267,7 +268,7 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
}
}
-void DisplayServerOSX::_update_displays_arrangement() {
+void DisplayServerMacOS::_update_displays_arrangement() {
origin = Point2i();
for (int i = 0; i < get_screen_count(); i++) {
@@ -282,20 +283,20 @@ void DisplayServerOSX::_update_displays_arrangement() {
displays_arrangement_dirty = false;
}
-Point2i DisplayServerOSX::_get_screens_origin() const {
+Point2i DisplayServerMacOS::_get_screens_origin() const {
// Returns the native top-left screen coordinate of the smallest rectangle
// that encompasses all screens. Needed in get_screen_position(),
// window_get_position, and window_set_position()
// to convert between OS X native screen coordinates and the ones expected by Godot.
if (displays_arrangement_dirty) {
- const_cast<DisplayServerOSX *>(this)->_update_displays_arrangement();
+ const_cast<DisplayServerMacOS *>(this)->_update_displays_arrangement();
}
return origin;
}
-Point2i DisplayServerOSX::_get_native_screen_position(int p_screen) const {
+Point2i DisplayServerMacOS::_get_native_screen_position(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if ((NSUInteger)p_screen < [screenArray count]) {
NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame];
@@ -306,18 +307,18 @@ Point2i DisplayServerOSX::_get_native_screen_position(int p_screen) const {
return Point2i();
}
-void DisplayServerOSX::_displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+void DisplayServerMacOS::_displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) {
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (ds) {
ds->displays_arrangement_dirty = true;
}
}
-void DisplayServerOSX::_dispatch_input_events(const Ref<InputEvent> &p_event) {
- ((DisplayServerOSX *)(get_singleton()))->_dispatch_input_event(p_event);
+void DisplayServerMacOS::_dispatch_input_events(const Ref<InputEvent> &p_event) {
+ ((DisplayServerMacOS *)(get_singleton()))->_dispatch_input_event(p_event);
}
-void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) {
+void DisplayServerMacOS::_dispatch_input_event(const Ref<InputEvent> &p_event) {
_THREAD_SAFE_METHOD_
if (!in_dispatch_input_event) {
in_dispatch_input_event = true;
@@ -334,7 +335,7 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) {
if (windows.has(E->get())) {
Callable callable = windows[E->get()].input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
in_dispatch_input_event = false;
@@ -348,7 +349,7 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) {
if (windows.has(event_from_window->get_window_id())) {
Callable callable = windows[event_from_window->get_window_id()].input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
} else {
@@ -356,7 +357,7 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) {
for (KeyValue<WindowID, WindowData> &E : windows) {
Callable callable = E.value.input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
}
@@ -364,12 +365,12 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) {
}
}
-void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) {
+void DisplayServerMacOS::_push_input(const Ref<InputEvent> &p_event) {
Ref<InputEvent> ev = p_event;
Input::get_singleton()->parse_input_event(ev);
}
-void DisplayServerOSX::_process_key_events() {
+void DisplayServerMacOS::_process_key_events() {
Ref<InputEventKey> k;
for (int i = 0; i < key_event_pos; i++) {
const KeyEvent &ke = key_event_buffer[i];
@@ -378,7 +379,7 @@ void DisplayServerOSX::_process_key_events() {
k.instantiate();
k->set_window_id(ke.window_id);
- get_key_modifier_state(ke.osx_state, k);
+ get_key_modifier_state(ke.macos_state, k);
k->set_pressed(ke.pressed);
k->set_echo(ke.echo);
k->set_keycode(ke.keycode);
@@ -392,7 +393,7 @@ void DisplayServerOSX::_process_key_events() {
k.instantiate();
k->set_window_id(ke.window_id);
- get_key_modifier_state(ke.osx_state, k);
+ get_key_modifier_state(ke.macos_state, k);
k->set_pressed(ke.pressed);
k->set_echo(ke.echo);
k->set_keycode(Key::NONE);
@@ -405,7 +406,7 @@ void DisplayServerOSX::_process_key_events() {
k.instantiate();
k->set_window_id(ke.window_id);
- get_key_modifier_state(ke.osx_state, k);
+ get_key_modifier_state(ke.macos_state, k);
k->set_pressed(ke.pressed);
k->set_echo(ke.echo);
k->set_keycode(ke.keycode);
@@ -423,7 +424,7 @@ void DisplayServerOSX::_process_key_events() {
key_event_pos = 0;
}
-void DisplayServerOSX::_update_keyboard_layouts() {
+void DisplayServerMacOS::_update_keyboard_layouts() {
kbd_layouts.clear();
current_layout = 0;
@@ -468,14 +469,14 @@ void DisplayServerOSX::_update_keyboard_layouts() {
keyboard_layout_dirty = false;
}
-void DisplayServerOSX::_keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+void DisplayServerMacOS::_keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) {
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (ds) {
ds->keyboard_layout_dirty = true;
}
}
-NSImage *DisplayServerOSX::_convert_to_nsimg(Ref<Image> &p_image) const {
+NSImage *DisplayServerMacOS::_convert_to_nsimg(Ref<Image> &p_image) const {
p_image->convert(Image::FORMAT_RGBA8);
NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
@@ -509,7 +510,7 @@ NSImage *DisplayServerOSX::_convert_to_nsimg(Ref<Image> &p_image) const {
return nsimg;
}
-NSCursor *DisplayServerOSX::_cursor_from_selector(SEL p_selector, SEL p_fallback) {
+NSCursor *DisplayServerMacOS::_cursor_from_selector(SEL p_selector, SEL p_fallback) {
if ([NSCursor respondsToSelector:p_selector]) {
id object = [NSCursor performSelector:p_selector];
if ([object isKindOfClass:[NSCursor class]]) {
@@ -523,11 +524,11 @@ NSCursor *DisplayServerOSX::_cursor_from_selector(SEL p_selector, SEL p_fallback
return [NSCursor arrowCursor];
}
-NSMenu *DisplayServerOSX::get_dock_menu() const {
+NSMenu *DisplayServerMacOS::get_dock_menu() const {
return dock_menu;
}
-void DisplayServerOSX::menu_callback(id p_sender) {
+void DisplayServerMacOS::menu_callback(id p_sender) {
if (![p_sender representedObject]) {
return;
}
@@ -555,20 +556,20 @@ void DisplayServerOSX::menu_callback(id p_sender) {
Variant *tagp = &tag;
Variant ret;
Callable::CallError ce;
- value->callback.call((const Variant **)&tagp, 1, ret, ce);
+ value->callback.callp((const Variant **)&tagp, 1, ret, ce);
}
}
}
-bool DisplayServerOSX::has_window(WindowID p_window) const {
+bool DisplayServerMacOS::has_window(WindowID p_window) const {
return windows.has(p_window);
}
-DisplayServerOSX::WindowData &DisplayServerOSX::get_window(WindowID p_window) {
+DisplayServerMacOS::WindowData &DisplayServerMacOS::get_window(WindowID p_window) {
return windows[p_window];
}
-void DisplayServerOSX::send_event(NSEvent *p_event) {
+void DisplayServerMacOS::send_event(NSEvent *p_event) {
// Special case handling of command-period, which is traditionally a special
// shortcut in macOS and doesn't arrive at our regular keyDown handler.
if ([p_event type] == NSEventTypeKeyDown) {
@@ -577,7 +578,7 @@ void DisplayServerOSX::send_event(NSEvent *p_event) {
k.instantiate();
get_key_modifier_state([p_event modifierFlags], k);
- k->set_window_id(DisplayServerOSX::INVALID_WINDOW_ID);
+ k->set_window_id(DisplayServerMacOS::INVALID_WINDOW_ID);
k->set_pressed(true);
k->set_keycode(Key::PERIOD);
k->set_physical_keycode(Key::PERIOD);
@@ -588,7 +589,7 @@ void DisplayServerOSX::send_event(NSEvent *p_event) {
}
}
-void DisplayServerOSX::send_window_event(const WindowData &wd, WindowEvent p_event) {
+void DisplayServerMacOS::send_window_event(const WindowData &wd, WindowEvent p_event) {
_THREAD_SAFE_METHOD_
if (!wd.event_callback.is_null()) {
@@ -596,25 +597,25 @@ void DisplayServerOSX::send_window_event(const WindowData &wd, WindowEvent p_eve
Variant *eventp = &event;
Variant ret;
Callable::CallError ce;
- wd.event_callback.call((const Variant **)&eventp, 1, ret, ce);
+ wd.event_callback.callp((const Variant **)&eventp, 1, ret, ce);
}
}
-void DisplayServerOSX::release_pressed_events() {
+void DisplayServerMacOS::release_pressed_events() {
_THREAD_SAFE_METHOD_
if (Input::get_singleton()) {
Input::get_singleton()->release_pressed_events();
}
}
-void DisplayServerOSX::get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> r_state) const {
- r_state->set_shift_pressed((p_osx_state & NSEventModifierFlagShift));
- r_state->set_ctrl_pressed((p_osx_state & NSEventModifierFlagControl));
- r_state->set_alt_pressed((p_osx_state & NSEventModifierFlagOption));
- r_state->set_meta_pressed((p_osx_state & NSEventModifierFlagCommand));
+void DisplayServerMacOS::get_key_modifier_state(unsigned int p_macos_state, Ref<InputEventWithModifiers> r_state) const {
+ r_state->set_shift_pressed((p_macos_state & NSEventModifierFlagShift));
+ r_state->set_ctrl_pressed((p_macos_state & NSEventModifierFlagControl));
+ r_state->set_alt_pressed((p_macos_state & NSEventModifierFlagOption));
+ r_state->set_meta_pressed((p_macos_state & NSEventModifierFlagCommand));
}
-void DisplayServerOSX::update_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPoint p_location_in_window) {
+void DisplayServerMacOS::update_mouse_pos(DisplayServerMacOS::WindowData &p_wd, NSPoint p_location_in_window) {
const NSRect content_rect = [p_wd.window_view frame];
const float scale = screen_get_max_scale();
p_wd.mouse_pos.x = p_location_in_window.x * scale;
@@ -622,33 +623,33 @@ void DisplayServerOSX::update_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPo
Input::get_singleton()->set_mouse_position(p_wd.mouse_pos);
}
-void DisplayServerOSX::push_to_key_event_buffer(const DisplayServerOSX::KeyEvent &p_event) {
+void DisplayServerMacOS::push_to_key_event_buffer(const DisplayServerMacOS::KeyEvent &p_event) {
if (key_event_pos >= key_event_buffer.size()) {
key_event_buffer.resize(1 + key_event_pos);
}
key_event_buffer.write[key_event_pos++] = p_event;
}
-void DisplayServerOSX::update_im_text(const Point2i &p_selection, const String &p_text) {
+void DisplayServerMacOS::update_im_text(const Point2i &p_selection, const String &p_text) {
im_selection = p_selection;
im_text = p_text;
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE);
}
-void DisplayServerOSX::set_last_focused_window(WindowID p_window) {
+void DisplayServerMacOS::set_last_focused_window(WindowID p_window) {
last_focused_window = p_window;
}
-void DisplayServerOSX::set_is_resizing(bool p_is_resizing) {
+void DisplayServerMacOS::set_is_resizing(bool p_is_resizing) {
is_resizing = p_is_resizing;
}
-bool DisplayServerOSX::get_is_resizing() const {
+bool DisplayServerMacOS::get_is_resizing() const {
return is_resizing;
}
-void DisplayServerOSX::window_update(WindowID p_window) {
+void DisplayServerMacOS::window_update(WindowID p_window) {
#if defined(GLES3_ENABLED)
if (gl_manager) {
gl_manager->window_update(p_window);
@@ -656,7 +657,7 @@ void DisplayServerOSX::window_update(WindowID p_window) {
#endif
}
-void DisplayServerOSX::window_destroy(WindowID p_window) {
+void DisplayServerMacOS::window_destroy(WindowID p_window) {
#if defined(GLES3_ENABLED)
if (gl_manager) {
gl_manager->window_destroy(p_window);
@@ -670,7 +671,7 @@ void DisplayServerOSX::window_destroy(WindowID p_window) {
windows.erase(p_window);
}
-void DisplayServerOSX::window_resize(WindowID p_window, int p_width, int p_height) {
+void DisplayServerMacOS::window_resize(WindowID p_window, int p_width, int p_height) {
#if defined(GLES3_ENABLED)
if (gl_manager) {
gl_manager->window_resize(p_window, p_width, p_height);
@@ -683,7 +684,7 @@ void DisplayServerOSX::window_resize(WindowID p_window, int p_width, int p_heigh
#endif
}
-bool DisplayServerOSX::has_feature(Feature p_feature) const {
+bool DisplayServerMacOS::has_feature(Feature p_feature) const {
switch (p_feature) {
case FEATURE_GLOBAL_MENU:
case FEATURE_SUBWINDOWS:
@@ -709,16 +710,16 @@ bool DisplayServerOSX::has_feature(Feature p_feature) const {
return false;
}
-String DisplayServerOSX::get_name() const {
- return "OSX";
+String DisplayServerMacOS::get_name() const {
+ return "macOS";
}
-void DisplayServerOSX::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+void DisplayServerMacOS::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
if (menu) {
- String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
+ String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
NSMenuItem *menu_item;
if (p_index != -1) {
menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index];
@@ -731,17 +732,17 @@ void DisplayServerOSX::global_menu_add_item(const String &p_menu_root, const Str
obj->checkable_type = CHECKABLE_TYPE_NONE;
obj->max_states = 0;
obj->state = 0;
- [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)];
+ [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)];
[menu_item setRepresentedObject:obj];
}
}
-void DisplayServerOSX::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+void DisplayServerMacOS::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
if (menu) {
- String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
+ String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
NSMenuItem *menu_item;
if (p_index != -1) {
menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index];
@@ -754,17 +755,17 @@ void DisplayServerOSX::global_menu_add_check_item(const String &p_menu_root, con
obj->checkable_type = CHECKABLE_TYPE_CHECK_BOX;
obj->max_states = 0;
obj->state = 0;
- [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)];
+ [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)];
[menu_item setRepresentedObject:obj];
}
}
-void DisplayServerOSX::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+void DisplayServerMacOS::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
if (menu) {
- String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
+ String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
NSMenuItem *menu_item;
if (p_index != -1) {
menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index];
@@ -786,17 +787,17 @@ void DisplayServerOSX::global_menu_add_icon_item(const String &p_menu_root, cons
obj->img->resize(16, 16, Image::INTERPOLATE_LANCZOS);
[menu_item setImage:_convert_to_nsimg(obj->img)];
}
- [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)];
+ [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)];
[menu_item setRepresentedObject:obj];
}
}
-void DisplayServerOSX::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+void DisplayServerMacOS::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
if (menu) {
- String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
+ String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
NSMenuItem *menu_item;
if (p_index != -1) {
menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index];
@@ -818,17 +819,17 @@ void DisplayServerOSX::global_menu_add_icon_check_item(const String &p_menu_root
obj->img->resize(16, 16, Image::INTERPOLATE_LANCZOS);
[menu_item setImage:_convert_to_nsimg(obj->img)];
}
- [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)];
+ [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)];
[menu_item setRepresentedObject:obj];
}
}
-void DisplayServerOSX::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+void DisplayServerMacOS::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
if (menu) {
- String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
+ String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
NSMenuItem *menu_item;
if (p_index != -1) {
menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index];
@@ -841,17 +842,17 @@ void DisplayServerOSX::global_menu_add_radio_check_item(const String &p_menu_roo
obj->checkable_type = CHECKABLE_TYPE_RADIO_BUTTON;
obj->max_states = 0;
obj->state = 0;
- [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)];
+ [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)];
[menu_item setRepresentedObject:obj];
}
}
-void DisplayServerOSX::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+void DisplayServerMacOS::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
if (menu) {
- String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
+ String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
NSMenuItem *menu_item;
if (p_index != -1) {
menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index];
@@ -873,17 +874,17 @@ void DisplayServerOSX::global_menu_add_icon_radio_check_item(const String &p_men
obj->img->resize(16, 16, Image::INTERPOLATE_LANCZOS);
[menu_item setImage:_convert_to_nsimg(obj->img)];
}
- [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)];
+ [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)];
[menu_item setRepresentedObject:obj];
}
}
-void DisplayServerOSX::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+void DisplayServerMacOS::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
if (menu) {
- String keycode = KeyMappingOSX::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
+ String keycode = KeyMappingMacOS::keycode_get_native_string(p_accel & KeyModifierMask::CODE_MASK);
NSMenuItem *menu_item;
if (p_index != -1) {
menu_item = [menu insertItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()] atIndex:p_index];
@@ -896,12 +897,12 @@ void DisplayServerOSX::global_menu_add_multistate_item(const String &p_menu_root
obj->checkable_type = CHECKABLE_TYPE_NONE;
obj->max_states = p_max_states;
obj->state = p_default_state;
- [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_accel)];
+ [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_accel)];
[menu_item setRepresentedObject:obj];
}
}
-void DisplayServerOSX::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) {
+void DisplayServerMacOS::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -926,7 +927,7 @@ void DisplayServerOSX::global_menu_add_submenu_item(const String &p_menu_root, c
}
}
-void DisplayServerOSX::global_menu_add_separator(const String &p_menu_root, int p_index) {
+void DisplayServerMacOS::global_menu_add_separator(const String &p_menu_root, int p_index) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -939,7 +940,7 @@ void DisplayServerOSX::global_menu_add_separator(const String &p_menu_root, int
}
}
-int DisplayServerOSX::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const {
+int DisplayServerMacOS::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -950,7 +951,7 @@ int DisplayServerOSX::global_menu_get_item_index_from_text(const String &p_menu_
return -1;
}
-int DisplayServerOSX::global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const {
+int DisplayServerMacOS::global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -969,7 +970,7 @@ int DisplayServerOSX::global_menu_get_item_index_from_tag(const String &p_menu_r
return -1;
}
-bool DisplayServerOSX::global_menu_is_item_checked(const String &p_menu_root, int p_idx) const {
+bool DisplayServerMacOS::global_menu_is_item_checked(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -982,7 +983,7 @@ bool DisplayServerOSX::global_menu_is_item_checked(const String &p_menu_root, in
return false;
}
-bool DisplayServerOSX::global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const {
+bool DisplayServerMacOS::global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -998,7 +999,7 @@ bool DisplayServerOSX::global_menu_is_item_checkable(const String &p_menu_root,
return false;
}
-bool DisplayServerOSX::global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const {
+bool DisplayServerMacOS::global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1014,7 +1015,7 @@ bool DisplayServerOSX::global_menu_is_item_radio_checkable(const String &p_menu_
return false;
}
-Callable DisplayServerOSX::global_menu_get_item_callback(const String &p_menu_root, int p_idx) const {
+Callable DisplayServerMacOS::global_menu_get_item_callback(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1030,7 +1031,7 @@ Callable DisplayServerOSX::global_menu_get_item_callback(const String &p_menu_ro
return Callable();
}
-Variant DisplayServerOSX::global_menu_get_item_tag(const String &p_menu_root, int p_idx) const {
+Variant DisplayServerMacOS::global_menu_get_item_tag(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1046,7 +1047,7 @@ Variant DisplayServerOSX::global_menu_get_item_tag(const String &p_menu_root, in
return Variant();
}
-String DisplayServerOSX::global_menu_get_item_text(const String &p_menu_root, int p_idx) const {
+String DisplayServerMacOS::global_menu_get_item_text(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1059,7 +1060,7 @@ String DisplayServerOSX::global_menu_get_item_text(const String &p_menu_root, in
return String();
}
-String DisplayServerOSX::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const {
+String DisplayServerMacOS::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1079,7 +1080,7 @@ String DisplayServerOSX::global_menu_get_item_submenu(const String &p_menu_root,
return String();
}
-Key DisplayServerOSX::global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const {
+Key DisplayServerMacOS::global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1110,7 +1111,7 @@ Key DisplayServerOSX::global_menu_get_item_accelerator(const String &p_menu_root
return Key::NONE;
}
-bool DisplayServerOSX::global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const {
+bool DisplayServerMacOS::global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1123,7 +1124,7 @@ bool DisplayServerOSX::global_menu_is_item_disabled(const String &p_menu_root, i
return false;
}
-String DisplayServerOSX::global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const {
+String DisplayServerMacOS::global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1136,7 +1137,7 @@ String DisplayServerOSX::global_menu_get_item_tooltip(const String &p_menu_root,
return String();
}
-int DisplayServerOSX::global_menu_get_item_state(const String &p_menu_root, int p_idx) const {
+int DisplayServerMacOS::global_menu_get_item_state(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1152,7 +1153,7 @@ int DisplayServerOSX::global_menu_get_item_state(const String &p_menu_root, int
return 0;
}
-int DisplayServerOSX::global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const {
+int DisplayServerMacOS::global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1168,7 +1169,7 @@ int DisplayServerOSX::global_menu_get_item_max_states(const String &p_menu_root,
return 0;
}
-Ref<Texture2D> DisplayServerOSX::global_menu_get_item_icon(const String &p_menu_root, int p_idx) const {
+Ref<Texture2D> DisplayServerMacOS::global_menu_get_item_icon(const String &p_menu_root, int p_idx) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1178,10 +1179,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);
}
}
}
@@ -1189,7 +1187,7 @@ Ref<Texture2D> DisplayServerOSX::global_menu_get_item_icon(const String &p_menu_
return Ref<Texture2D>();
}
-void DisplayServerOSX::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) {
+void DisplayServerMacOS::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1208,7 +1206,7 @@ void DisplayServerOSX::global_menu_set_item_checked(const String &p_menu_root, i
}
}
-void DisplayServerOSX::global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable) {
+void DisplayServerMacOS::global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1224,7 +1222,7 @@ void DisplayServerOSX::global_menu_set_item_checkable(const String &p_menu_root,
}
}
-void DisplayServerOSX::global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable) {
+void DisplayServerMacOS::global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1240,7 +1238,7 @@ void DisplayServerOSX::global_menu_set_item_radio_checkable(const String &p_menu
}
}
-void DisplayServerOSX::global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) {
+void DisplayServerMacOS::global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1256,7 +1254,7 @@ void DisplayServerOSX::global_menu_set_item_callback(const String &p_menu_root,
}
}
-void DisplayServerOSX::global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) {
+void DisplayServerMacOS::global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1272,7 +1270,7 @@ void DisplayServerOSX::global_menu_set_item_tag(const String &p_menu_root, int p
}
}
-void DisplayServerOSX::global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text) {
+void DisplayServerMacOS::global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1287,7 +1285,7 @@ void DisplayServerOSX::global_menu_set_item_text(const String &p_menu_root, int
}
}
-void DisplayServerOSX::global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu) {
+void DisplayServerMacOS::global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1311,7 +1309,7 @@ void DisplayServerOSX::global_menu_set_item_submenu(const String &p_menu_root, i
}
}
-void DisplayServerOSX::global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode) {
+void DisplayServerMacOS::global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1321,14 +1319,14 @@ void DisplayServerOSX::global_menu_set_item_accelerator(const String &p_menu_roo
}
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
if (menu_item) {
- [menu_item setKeyEquivalentModifierMask:KeyMappingOSX::keycode_get_native_mask(p_keycode)];
- String keycode = KeyMappingOSX::keycode_get_native_string(p_keycode & KeyModifierMask::CODE_MASK);
+ [menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_keycode)];
+ String keycode = KeyMappingMacOS::keycode_get_native_string(p_keycode & KeyModifierMask::CODE_MASK);
[menu_item setKeyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()]];
}
}
}
-void DisplayServerOSX::global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled) {
+void DisplayServerMacOS::global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1343,7 +1341,7 @@ void DisplayServerOSX::global_menu_set_item_disabled(const String &p_menu_root,
}
}
-void DisplayServerOSX::global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) {
+void DisplayServerMacOS::global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1358,7 +1356,7 @@ void DisplayServerOSX::global_menu_set_item_tooltip(const String &p_menu_root, i
}
}
-void DisplayServerOSX::global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state) {
+void DisplayServerMacOS::global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1376,7 +1374,7 @@ void DisplayServerOSX::global_menu_set_item_state(const String &p_menu_root, int
}
}
-void DisplayServerOSX::global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states) {
+void DisplayServerMacOS::global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1394,7 +1392,7 @@ void DisplayServerOSX::global_menu_set_item_max_states(const String &p_menu_root
}
}
-void DisplayServerOSX::global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon) {
+void DisplayServerMacOS::global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1421,7 +1419,7 @@ void DisplayServerOSX::global_menu_set_item_icon(const String &p_menu_root, int
}
}
-int DisplayServerOSX::global_menu_get_item_count(const String &p_menu_root) const {
+int DisplayServerMacOS::global_menu_get_item_count(const String &p_menu_root) const {
_THREAD_SAFE_METHOD_
const NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1432,7 +1430,7 @@ int DisplayServerOSX::global_menu_get_item_count(const String &p_menu_root) cons
}
}
-void DisplayServerOSX::global_menu_remove_item(const String &p_menu_root, int p_idx) {
+void DisplayServerMacOS::global_menu_remove_item(const String &p_menu_root, int p_idx) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1444,7 +1442,7 @@ void DisplayServerOSX::global_menu_remove_item(const String &p_menu_root, int p_
}
}
-void DisplayServerOSX::global_menu_clear(const String &p_menu_root) {
+void DisplayServerMacOS::global_menu_clear(const String &p_menu_root) {
_THREAD_SAFE_METHOD_
NSMenu *menu = _get_menu_root(p_menu_root);
@@ -1458,42 +1456,42 @@ void DisplayServerOSX::global_menu_clear(const String &p_menu_root) {
}
}
-bool DisplayServerOSX::tts_is_speaking() const {
+bool DisplayServerMacOS::tts_is_speaking() const {
ERR_FAIL_COND_V(!tts, false);
return [tts isSpeaking];
}
-bool DisplayServerOSX::tts_is_paused() const {
+bool DisplayServerMacOS::tts_is_paused() const {
ERR_FAIL_COND_V(!tts, false);
return [tts isPaused];
}
-Array DisplayServerOSX::tts_get_voices() const {
+Array DisplayServerMacOS::tts_get_voices() const {
ERR_FAIL_COND_V(!tts, Array());
return [tts getVoices];
}
-void DisplayServerOSX::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
+void DisplayServerMacOS::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
ERR_FAIL_COND(!tts);
[tts speak:p_text voice:p_voice volume:p_volume pitch:p_pitch rate:p_rate utterance_id:p_utterance_id interrupt:p_interrupt];
}
-void DisplayServerOSX::tts_pause() {
+void DisplayServerMacOS::tts_pause() {
ERR_FAIL_COND(!tts);
[tts pauseSpeaking];
}
-void DisplayServerOSX::tts_resume() {
+void DisplayServerMacOS::tts_resume() {
ERR_FAIL_COND(!tts);
[tts resumeSpeaking];
}
-void DisplayServerOSX::tts_stop() {
+void DisplayServerMacOS::tts_stop() {
ERR_FAIL_COND(!tts);
[tts stopSpeaking];
}
-Error DisplayServerOSX::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {
+Error DisplayServerMacOS::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {
_THREAD_SAFE_METHOD_
NSAlert *window = [[NSAlert alloc] init];
@@ -1525,13 +1523,13 @@ Error DisplayServerOSX::dialog_show(String p_title, String p_description, Vector
Variant *buttonp = &button;
Variant ret;
Callable::CallError ce;
- p_callback.call((const Variant **)&buttonp, 1, ret, ce);
+ p_callback.callp((const Variant **)&buttonp, 1, ret, ce);
}
return OK;
}
-Error DisplayServerOSX::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) {
+Error DisplayServerMacOS::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) {
_THREAD_SAFE_METHOD_
NSAlert *window = [[NSAlert alloc] init];
@@ -1557,13 +1555,13 @@ Error DisplayServerOSX::dialog_input_text(String p_title, String p_description,
Variant *textp = &text;
Variant ret;
Callable::CallError ce;
- p_callback.call((const Variant **)&textp, 1, ret, ce);
+ p_callback.callp((const Variant **)&textp, 1, ret, ce);
}
return OK;
}
-void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
+void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) {
_THREAD_SAFE_METHOD_
if (p_mode == mouse_mode) {
@@ -1618,11 +1616,11 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
}
}
-DisplayServer::MouseMode DisplayServerOSX::mouse_get_mode() const {
+DisplayServer::MouseMode DisplayServerMacOS::mouse_get_mode() const {
return mouse_mode;
}
-bool DisplayServerOSX::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp) {
+bool DisplayServerMacOS::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp) {
_THREAD_SAFE_METHOD_
if (ignore_warp) {
@@ -1644,7 +1642,7 @@ bool DisplayServerOSX::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSP
List<WarpEvent>::Element *F = warp_events.front();
while (F) {
if (F->get().timestamp < p_timestamp) {
- List<DisplayServerOSX::WarpEvent>::Element *E = F;
+ List<DisplayServerMacOS::WarpEvent>::Element *E = F;
r_delta.x -= E->get().delta.x;
r_delta.y -= E->get().delta.y;
F = F->next();
@@ -1672,7 +1670,7 @@ bool DisplayServerOSX::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSP
// Save warp data.
last_warp = [[NSProcessInfo processInfo] systemUptime];
- DisplayServerOSX::WarpEvent ev;
+ DisplayServerMacOS::WarpEvent ev;
ev.timestamp = last_warp;
ev.delta = r_delta;
warp_events.push_back(ev);
@@ -1681,7 +1679,7 @@ bool DisplayServerOSX::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSP
return false;
}
-void DisplayServerOSX::warp_mouse(const Point2i &p_position) {
+void DisplayServerMacOS::warp_mouse(const Point2i &p_position) {
_THREAD_SAFE_METHOD_
if (mouse_mode != MOUSE_MODE_CAPTURED) {
@@ -1708,7 +1706,7 @@ void DisplayServerOSX::warp_mouse(const Point2i &p_position) {
}
}
-Point2i DisplayServerOSX::mouse_get_position() const {
+Point2i DisplayServerMacOS::mouse_get_position() const {
_THREAD_SAFE_METHOD_
const NSPoint mouse_pos = [NSEvent mouseLocation];
@@ -1727,15 +1725,15 @@ Point2i DisplayServerOSX::mouse_get_position() const {
return Vector2i();
}
-void DisplayServerOSX::mouse_set_button_state(MouseButton p_state) {
+void DisplayServerMacOS::mouse_set_button_state(MouseButton p_state) {
last_button_state = p_state;
}
-MouseButton DisplayServerOSX::mouse_get_button_state() const {
+MouseButton DisplayServerMacOS::mouse_get_button_state() const {
return last_button_state;
}
-void DisplayServerOSX::clipboard_set(const String &p_text) {
+void DisplayServerMacOS::clipboard_set(const String &p_text) {
_THREAD_SAFE_METHOD_
NSString *copiedString = [NSString stringWithUTF8String:p_text.utf8().get_data()];
@@ -1746,7 +1744,7 @@ void DisplayServerOSX::clipboard_set(const String &p_text) {
[pasteboard writeObjects:copiedStringArray];
}
-String DisplayServerOSX::clipboard_get() const {
+String DisplayServerMacOS::clipboard_get() const {
_THREAD_SAFE_METHOD_
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
@@ -1767,14 +1765,14 @@ String DisplayServerOSX::clipboard_get() const {
return ret;
}
-int DisplayServerOSX::get_screen_count() const {
+int DisplayServerMacOS::get_screen_count() const {
_THREAD_SAFE_METHOD_
NSArray *screenArray = [NSScreen screens];
return [screenArray count];
}
-Point2i DisplayServerOSX::screen_get_position(int p_screen) const {
+Point2i DisplayServerMacOS::screen_get_position(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
@@ -1788,7 +1786,7 @@ Point2i DisplayServerOSX::screen_get_position(int p_screen) const {
return position;
}
-Size2i DisplayServerOSX::screen_get_size(int p_screen) const {
+Size2i DisplayServerMacOS::screen_get_size(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
@@ -1805,7 +1803,7 @@ Size2i DisplayServerOSX::screen_get_size(int p_screen) const {
return Size2i();
}
-int DisplayServerOSX::screen_get_dpi(int p_screen) const {
+int DisplayServerMacOS::screen_get_dpi(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
@@ -1829,7 +1827,7 @@ int DisplayServerOSX::screen_get_dpi(int p_screen) const {
return 72;
}
-float DisplayServerOSX::screen_get_scale(int p_screen) const {
+float DisplayServerMacOS::screen_get_scale(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
@@ -1847,14 +1845,14 @@ float DisplayServerOSX::screen_get_scale(int p_screen) const {
return 1.f;
}
-float DisplayServerOSX::screen_get_max_scale() const {
+float DisplayServerMacOS::screen_get_max_scale() const {
_THREAD_SAFE_METHOD_
// Note: Do not update max display scale on screen configuration change, existing editor windows can't be rescaled on the fly.
return display_max_scale;
}
-Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const {
+Rect2i DisplayServerMacOS::screen_get_usable_rect(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
@@ -1876,7 +1874,7 @@ Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const {
return Rect2i();
}
-float DisplayServerOSX::screen_get_refresh_rate(int p_screen) const {
+float DisplayServerMacOS::screen_get_refresh_rate(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
@@ -1894,7 +1892,25 @@ float DisplayServerOSX::screen_get_refresh_rate(int p_screen) const {
return SCREEN_REFRESH_RATE_FALLBACK;
}
-Vector<DisplayServer::WindowID> DisplayServerOSX::get_window_list() const {
+bool DisplayServerMacOS::screen_is_kept_on() const {
+ return (screen_keep_on_assertion);
+}
+
+void DisplayServerMacOS::screen_set_keep_on(bool p_enable) {
+ if (screen_keep_on_assertion) {
+ IOPMAssertionRelease(screen_keep_on_assertion);
+ screen_keep_on_assertion = kIOPMNullAssertionID;
+ }
+
+ if (p_enable) {
+ String app_name_string = ProjectSettings::get_singleton()->get("application/config/name");
+ NSString *name = [NSString stringWithUTF8String:(app_name_string.is_empty() ? "Godot Engine" : app_name_string.utf8().get_data())];
+ NSString *reason = @"Godot Engine running with display/window/energy_saving/keep_screen_on = true";
+ IOPMAssertionCreateWithDescription(kIOPMAssertPreventUserIdleDisplaySleep, (__bridge CFStringRef)name, (__bridge CFStringRef)reason, (__bridge CFStringRef)reason, nullptr, 0, nullptr, &screen_keep_on_assertion);
+ }
+}
+
+Vector<DisplayServer::WindowID> DisplayServerMacOS::get_window_list() const {
_THREAD_SAFE_METHOD_
Vector<int> ret;
@@ -1904,7 +1920,7 @@ Vector<DisplayServer::WindowID> DisplayServerOSX::get_window_list() const {
return ret;
}
-DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_vsync_mode, p_rect);
@@ -1917,7 +1933,7 @@ DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, V
return id;
}
-void DisplayServerOSX::show_window(WindowID p_id) {
+void DisplayServerMacOS::show_window(WindowID p_id) {
WindowData &wd = windows[p_id];
popup_open(p_id);
@@ -1928,7 +1944,7 @@ void DisplayServerOSX::show_window(WindowID p_id) {
}
}
-void DisplayServerOSX::delete_sub_window(WindowID p_id) {
+void DisplayServerMacOS::delete_sub_window(WindowID p_id) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_id));
@@ -1940,7 +1956,7 @@ void DisplayServerOSX::delete_sub_window(WindowID p_id) {
[wd.window_object close];
}
-void DisplayServerOSX::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerMacOS::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -1948,7 +1964,7 @@ void DisplayServerOSX::window_set_rect_changed_callback(const Callable &p_callab
wd.rect_changed_callback = p_callable;
}
-void DisplayServerOSX::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerMacOS::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -1956,7 +1972,7 @@ void DisplayServerOSX::window_set_window_event_callback(const Callable &p_callab
wd.event_callback = p_callable;
}
-void DisplayServerOSX::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerMacOS::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -1964,21 +1980,21 @@ void DisplayServerOSX::window_set_input_event_callback(const Callable &p_callabl
wd.input_event_callback = p_callable;
}
-void DisplayServerOSX::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerMacOS::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
wd.input_text_callback = p_callable;
}
-void DisplayServerOSX::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) {
+void DisplayServerMacOS::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
wd.drop_files_callback = p_callable;
}
-void DisplayServerOSX::window_set_title(const String &p_title, WindowID p_window) {
+void DisplayServerMacOS::window_set_title(const String &p_title, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -1987,7 +2003,7 @@ void DisplayServerOSX::window_set_title(const String &p_title, WindowID p_window
[wd.window_object setTitle:[NSString stringWithUTF8String:p_title.utf8().get_data()]];
}
-void DisplayServerOSX::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) {
+void DisplayServerMacOS::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -1996,7 +2012,7 @@ void DisplayServerOSX::window_set_mouse_passthrough(const Vector<Vector2> &p_reg
wd.mpath = p_region;
}
-int DisplayServerOSX::window_get_current_screen(WindowID p_window) const {
+int DisplayServerMacOS::window_get_current_screen(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), -1);
const WindowData &wd = windows[p_window];
@@ -2005,12 +2021,16 @@ int DisplayServerOSX::window_get_current_screen(WindowID p_window) const {
return (index == NSNotFound) ? 0 : index;
}
-void DisplayServerOSX::window_set_current_screen(int p_screen, WindowID p_window) {
+void DisplayServerMacOS::window_set_current_screen(int p_screen, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
+ if (window_get_current_screen(p_window) == p_screen) {
+ return;
+ }
+
bool was_fullscreen = false;
if (wd.fullscreen) {
// Temporary exit fullscreen mode to move window.
@@ -2027,7 +2047,7 @@ void DisplayServerOSX::window_set_current_screen(int p_screen, WindowID p_window
}
}
-void DisplayServerOSX::window_set_exclusive(WindowID p_window, bool p_exclusive) {
+void DisplayServerMacOS::window_set_exclusive(WindowID p_window, bool p_exclusive) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
@@ -2045,7 +2065,7 @@ void DisplayServerOSX::window_set_exclusive(WindowID p_window, bool p_exclusive)
}
}
-Point2i DisplayServerOSX::window_get_position(WindowID p_window) const {
+Point2i DisplayServerMacOS::window_get_position(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), Point2i());
@@ -2068,7 +2088,7 @@ Point2i DisplayServerOSX::window_get_position(WindowID p_window) const {
return pos;
}
-void DisplayServerOSX::window_set_position(const Point2i &p_position, WindowID p_window) {
+void DisplayServerMacOS::window_set_position(const Point2i &p_position, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -2096,7 +2116,7 @@ void DisplayServerOSX::window_set_position(const Point2i &p_position, WindowID p
update_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
}
-void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent) {
+void DisplayServerMacOS::window_set_transient(WindowID p_window, WindowID p_parent) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(p_window == p_parent);
@@ -2135,7 +2155,7 @@ void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent
}
}
-void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_window) {
+void DisplayServerMacOS::window_set_max_size(const Size2i p_size, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -2155,7 +2175,7 @@ void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_windo
}
}
-Size2i DisplayServerOSX::window_get_max_size(WindowID p_window) const {
+Size2i DisplayServerMacOS::window_get_max_size(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
@@ -2163,7 +2183,7 @@ Size2i DisplayServerOSX::window_get_max_size(WindowID p_window) const {
return wd.max_size;
}
-void DisplayServerOSX::window_set_min_size(const Size2i p_size, WindowID p_window) {
+void DisplayServerMacOS::window_set_min_size(const Size2i p_size, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -2183,7 +2203,7 @@ void DisplayServerOSX::window_set_min_size(const Size2i p_size, WindowID p_windo
}
}
-Size2i DisplayServerOSX::window_get_min_size(WindowID p_window) const {
+Size2i DisplayServerMacOS::window_get_min_size(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
@@ -2192,7 +2212,7 @@ Size2i DisplayServerOSX::window_get_min_size(WindowID p_window) const {
return wd.min_size;
}
-void DisplayServerOSX::window_set_size(const Size2i p_size, WindowID p_window) {
+void DisplayServerMacOS::window_set_size(const Size2i p_size, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -2216,7 +2236,7 @@ void DisplayServerOSX::window_set_size(const Size2i p_size, WindowID p_window) {
_update_window_style(wd);
}
-Size2i DisplayServerOSX::window_get_size(WindowID p_window) const {
+Size2i DisplayServerMacOS::window_get_size(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
@@ -2224,7 +2244,7 @@ Size2i DisplayServerOSX::window_get_size(WindowID p_window) const {
return wd.size;
}
-Size2i DisplayServerOSX::window_get_real_size(WindowID p_window) const {
+Size2i DisplayServerMacOS::window_get_real_size(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
@@ -2233,7 +2253,7 @@ Size2i DisplayServerOSX::window_get_real_size(WindowID p_window) const {
return Size2i(frame.size.width, frame.size.height) * screen_get_max_scale();
}
-void DisplayServerOSX::window_set_mode(WindowMode p_mode, WindowID p_window) {
+void DisplayServerMacOS::window_set_mode(WindowMode p_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -2302,7 +2322,7 @@ void DisplayServerOSX::window_set_mode(WindowMode p_mode, WindowID p_window) {
}
}
-DisplayServer::WindowMode DisplayServerOSX::window_get_mode(WindowID p_window) const {
+DisplayServer::WindowMode DisplayServerMacOS::window_get_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), WINDOW_MODE_WINDOWED);
@@ -2324,11 +2344,11 @@ DisplayServer::WindowMode DisplayServerOSX::window_get_mode(WindowID p_window) c
return WINDOW_MODE_WINDOWED;
}
-bool DisplayServerOSX::window_is_maximize_allowed(WindowID p_window) const {
+bool DisplayServerMacOS::window_is_maximize_allowed(WindowID p_window) const {
return true;
}
-void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) {
+void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -2403,7 +2423,7 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
}
}
-bool DisplayServerOSX::window_get_flag(WindowFlags p_flag, WindowID p_window) const {
+bool DisplayServerMacOS::window_get_flag(WindowFlags p_flag, WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), false);
@@ -2439,12 +2459,12 @@ bool DisplayServerOSX::window_get_flag(WindowFlags p_flag, WindowID p_window) co
return false;
}
-void DisplayServerOSX::window_request_attention(WindowID p_window) {
+void DisplayServerMacOS::window_request_attention(WindowID p_window) {
// It's app global, ignore window id.
[NSApp requestUserAttention:NSCriticalRequest];
}
-void DisplayServerOSX::window_move_to_foreground(WindowID p_window) {
+void DisplayServerMacOS::window_move_to_foreground(WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -2458,11 +2478,11 @@ void DisplayServerOSX::window_move_to_foreground(WindowID p_window) {
}
}
-bool DisplayServerOSX::window_can_draw(WindowID p_window) const {
+bool DisplayServerMacOS::window_can_draw(WindowID p_window) const {
return window_get_mode(p_window) != WINDOW_MODE_MINIMIZED;
}
-bool DisplayServerOSX::can_any_window_draw() const {
+bool DisplayServerMacOS::can_any_window_draw() const {
_THREAD_SAFE_METHOD_
for (const KeyValue<WindowID, WindowData> &E : windows) {
@@ -2473,7 +2493,7 @@ bool DisplayServerOSX::can_any_window_draw() const {
return false;
}
-void DisplayServerOSX::window_set_ime_active(const bool p_active, WindowID p_window) {
+void DisplayServerMacOS::window_set_ime_active(const bool p_active, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -2486,7 +2506,7 @@ void DisplayServerOSX::window_set_ime_active(const bool p_active, WindowID p_win
}
}
-void DisplayServerOSX::window_set_ime_position(const Point2i &p_pos, WindowID p_window) {
+void DisplayServerMacOS::window_set_ime_position(const Point2i &p_pos, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -2495,7 +2515,7 @@ void DisplayServerOSX::window_set_ime_position(const Point2i &p_pos, WindowID p_
wd.im_position = p_pos;
}
-DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Point2i &p_position) const {
+DisplayServer::WindowID DisplayServerMacOS::get_window_at_screen_position(const Point2i &p_position) const {
Point2i position = p_position;
position.y *= -1;
position += _get_screens_origin();
@@ -2510,7 +2530,7 @@ DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Po
return INVALID_WINDOW_ID;
}
-int64_t DisplayServerOSX::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const {
+int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const {
ERR_FAIL_COND_V(!windows.has(p_window), 0);
switch (p_handle_type) {
case DISPLAY_HANDLE: {
@@ -2528,27 +2548,27 @@ int64_t DisplayServerOSX::window_get_native_handle(HandleType p_handle_type, Win
}
}
-void DisplayServerOSX::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
+void DisplayServerMacOS::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
windows[p_window].instance_id = p_instance;
}
-ObjectID DisplayServerOSX::window_get_attached_instance_id(WindowID p_window) const {
+ObjectID DisplayServerMacOS::window_get_attached_instance_id(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), ObjectID());
return windows[p_window].instance_id;
}
-void DisplayServerOSX::gl_window_make_current(DisplayServer::WindowID p_window_id) {
+void DisplayServerMacOS::gl_window_make_current(DisplayServer::WindowID p_window_id) {
#if defined(GLES3_ENABLED)
gl_manager->window_make_current(p_window_id);
#endif
}
-void DisplayServerOSX::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+void DisplayServerMacOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(GLES3_ENABLED)
if (gl_manager) {
@@ -2562,7 +2582,7 @@ void DisplayServerOSX::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mo
#endif
}
-DisplayServer::VSyncMode DisplayServerOSX::window_get_vsync_mode(WindowID p_window) const {
+DisplayServer::VSyncMode DisplayServerMacOS::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(GLES3_ENABLED)
if (gl_manager) {
@@ -2577,15 +2597,15 @@ DisplayServer::VSyncMode DisplayServerOSX::window_get_vsync_mode(WindowID p_wind
return DisplayServer::VSYNC_ENABLED;
}
-Point2i DisplayServerOSX::ime_get_selection() const {
+Point2i DisplayServerMacOS::ime_get_selection() const {
return im_selection;
}
-String DisplayServerOSX::ime_get_text() const {
+String DisplayServerMacOS::ime_get_text() const {
return im_text;
}
-void DisplayServerOSX::cursor_update_shape() {
+void DisplayServerMacOS::cursor_update_shape() {
_THREAD_SAFE_METHOD_
if (cursors[cursor_shape] != nullptr) {
@@ -2649,7 +2669,7 @@ void DisplayServerOSX::cursor_update_shape() {
}
}
-void DisplayServerOSX::cursor_set_shape(CursorShape p_shape) {
+void DisplayServerMacOS::cursor_set_shape(CursorShape p_shape) {
_THREAD_SAFE_METHOD_
ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
@@ -2667,11 +2687,11 @@ void DisplayServerOSX::cursor_set_shape(CursorShape p_shape) {
cursor_update_shape();
}
-DisplayServerOSX::CursorShape DisplayServerOSX::cursor_get_shape() const {
+DisplayServerMacOS::CursorShape DisplayServerMacOS::cursor_get_shape() const {
return cursor_shape;
}
-void DisplayServerOSX::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+void DisplayServerMacOS::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
_THREAD_SAFE_METHOD_
if (p_cursor.is_valid()) {
@@ -2783,20 +2803,20 @@ void DisplayServerOSX::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu
}
}
-bool DisplayServerOSX::get_swap_cancel_ok() {
+bool DisplayServerMacOS::get_swap_cancel_ok() {
return false;
}
-int DisplayServerOSX::keyboard_get_layout_count() const {
+int DisplayServerMacOS::keyboard_get_layout_count() const {
if (keyboard_layout_dirty) {
- const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts();
+ const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts();
}
return kbd_layouts.size();
}
-void DisplayServerOSX::keyboard_set_current_layout(int p_index) {
+void DisplayServerMacOS::keyboard_set_current_layout(int p_index) {
if (keyboard_layout_dirty) {
- const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts();
+ const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts();
}
ERR_FAIL_INDEX(p_index, kbd_layouts.size());
@@ -2824,44 +2844,44 @@ void DisplayServerOSX::keyboard_set_current_layout(int p_index) {
}
}
-int DisplayServerOSX::keyboard_get_current_layout() const {
+int DisplayServerMacOS::keyboard_get_current_layout() const {
if (keyboard_layout_dirty) {
- const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts();
+ const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts();
}
return current_layout;
}
-String DisplayServerOSX::keyboard_get_layout_language(int p_index) const {
+String DisplayServerMacOS::keyboard_get_layout_language(int p_index) const {
if (keyboard_layout_dirty) {
- const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts();
+ const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts();
}
ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), "");
return kbd_layouts[p_index].code;
}
-String DisplayServerOSX::keyboard_get_layout_name(int p_index) const {
+String DisplayServerMacOS::keyboard_get_layout_name(int p_index) const {
if (keyboard_layout_dirty) {
- const_cast<DisplayServerOSX *>(this)->_update_keyboard_layouts();
+ const_cast<DisplayServerMacOS *>(this)->_update_keyboard_layouts();
}
ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), "");
return kbd_layouts[p_index].name;
}
-Key DisplayServerOSX::keyboard_get_keycode_from_physical(Key p_keycode) const {
+Key DisplayServerMacOS::keyboard_get_keycode_from_physical(Key p_keycode) const {
if (p_keycode == Key::PAUSE) {
return p_keycode;
}
Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK;
Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK;
- unsigned int osx_keycode = KeyMappingOSX::unmap_key((Key)keycode_no_mod);
- return (Key)(KeyMappingOSX::remap_key(osx_keycode, 0) | modifiers);
+ unsigned int macos_keycode = KeyMappingMacOS::unmap_key((Key)keycode_no_mod);
+ return (Key)(KeyMappingMacOS::remap_key(macos_keycode, 0) | modifiers);
}
-void DisplayServerOSX::process_events() {
+void DisplayServerMacOS::process_events() {
_THREAD_SAFE_METHOD_
while (true) {
@@ -2904,7 +2924,7 @@ void DisplayServerOSX::process_events() {
}
}
-void DisplayServerOSX::force_process_and_drop_events() {
+void DisplayServerMacOS::force_process_and_drop_events() {
_THREAD_SAFE_METHOD_
drop_events = true;
@@ -2912,19 +2932,21 @@ void DisplayServerOSX::force_process_and_drop_events() {
drop_events = false;
}
-void DisplayServerOSX::release_rendering_thread() {
+void DisplayServerMacOS::release_rendering_thread() {
}
-void DisplayServerOSX::make_rendering_thread() {
+void DisplayServerMacOS::make_rendering_thread() {
}
-void DisplayServerOSX::swap_buffers() {
+void DisplayServerMacOS::swap_buffers() {
#if defined(GLES3_ENABLED)
- gl_manager->swap_buffers();
+ if (gl_manager) {
+ gl_manager->swap_buffers();
+ }
#endif
}
-void DisplayServerOSX::set_native_icon(const String &p_filename) {
+void DisplayServerMacOS::set_native_icon(const String &p_filename) {
_THREAD_SAFE_METHOD_
Ref<FileAccess> f = FileAccess::open(p_filename, FileAccess::READ);
@@ -2944,7 +2966,7 @@ void DisplayServerOSX::set_native_icon(const String &p_filename) {
[NSApp setApplicationIconImage:icon];
}
-void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) {
+void DisplayServerMacOS::set_icon(const Ref<Image> &p_icon) {
_THREAD_SAFE_METHOD_
Ref<Image> img = p_icon;
@@ -2983,15 +3005,15 @@ void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) {
[NSApp setApplicationIconImage:nsimg];
}
-DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerMacOS::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ DisplayServer *ds = memnew(DisplayServerMacOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan or OpenGL versions.", "Unable to initialize Video driver");
}
return ds;
}
-Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
+Vector<String> DisplayServerMacOS::get_rendering_drivers_func() {
Vector<String> drivers;
#if defined(VULKAN_ENABLED)
@@ -3004,11 +3026,11 @@ Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
return drivers;
}
-void DisplayServerOSX::register_osx_driver() {
- register_create_function("osx", create_func, get_rendering_drivers_func);
+void DisplayServerMacOS::register_macos_driver() {
+ register_create_function("macos", create_func, get_rendering_drivers_func);
}
-DisplayServer::WindowID DisplayServerOSX::window_get_active_popup() const {
+DisplayServer::WindowID DisplayServerMacOS::window_get_active_popup() const {
const List<WindowID>::Element *E = popup_list.back();
if (E) {
return E->get();
@@ -3017,7 +3039,7 @@ DisplayServer::WindowID DisplayServerOSX::window_get_active_popup() const {
}
}
-void DisplayServerOSX::window_set_popup_safe_rect(WindowID p_window, const Rect2i &p_rect) {
+void DisplayServerMacOS::window_set_popup_safe_rect(WindowID p_window, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -3025,7 +3047,7 @@ void DisplayServerOSX::window_set_popup_safe_rect(WindowID p_window, const Rect2
wd.parent_safe_rect = p_rect;
}
-Rect2i DisplayServerOSX::window_get_popup_safe_rect(WindowID p_window) const {
+Rect2i DisplayServerMacOS::window_get_popup_safe_rect(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), Rect2i());
@@ -3033,7 +3055,7 @@ Rect2i DisplayServerOSX::window_get_popup_safe_rect(WindowID p_window) const {
return wd.parent_safe_rect;
}
-void DisplayServerOSX::popup_open(WindowID p_window) {
+void DisplayServerMacOS::popup_open(WindowID p_window) {
_THREAD_SAFE_METHOD_
WindowData &wd = windows[p_window];
@@ -3051,7 +3073,7 @@ void DisplayServerOSX::popup_open(WindowID p_window) {
}
}
if (C) {
- send_window_event(windows[C->get()], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
+ send_window_event(windows[C->get()], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST);
}
if (was_empty && popup_list.is_empty()) {
@@ -3063,7 +3085,7 @@ void DisplayServerOSX::popup_open(WindowID p_window) {
}
}
-void DisplayServerOSX::popup_close(WindowID p_window) {
+void DisplayServerMacOS::popup_close(WindowID p_window) {
_THREAD_SAFE_METHOD_
bool was_empty = popup_list.is_empty();
@@ -3073,7 +3095,7 @@ void DisplayServerOSX::popup_close(WindowID p_window) {
WindowID win_id = E->get();
popup_list.erase(E);
- send_window_event(windows[win_id], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
+ send_window_event(windows[win_id], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST);
E = F;
}
if (!was_empty && popup_list.is_empty()) {
@@ -3082,7 +3104,7 @@ void DisplayServerOSX::popup_close(WindowID p_window) {
}
}
-bool DisplayServerOSX::mouse_process_popups(bool p_close) {
+bool DisplayServerMacOS::mouse_process_popups(bool p_close) {
_THREAD_SAFE_METHOD_
bool was_empty = popup_list.is_empty();
@@ -3091,7 +3113,7 @@ bool DisplayServerOSX::mouse_process_popups(bool p_close) {
// Close all popups.
List<WindowID>::Element *E = popup_list.front();
if (E) {
- send_window_event(windows[E->get()], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
+ send_window_event(windows[E->get()], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST);
closed = true;
}
if (!was_empty) {
@@ -3123,7 +3145,7 @@ bool DisplayServerOSX::mouse_process_popups(bool p_close) {
}
}
if (C) {
- send_window_event(windows[C->get()], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
+ send_window_event(windows[C->get()], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST);
closed = true;
}
if (!was_empty && popup_list.is_empty()) {
@@ -3134,7 +3156,7 @@ bool DisplayServerOSX::mouse_process_popups(bool p_close) {
return closed;
}
-DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
@@ -3161,7 +3183,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
CGDisplayRegisterReconfigurationCallback(_displays_arrangement_changed, nullptr);
// Init TTS
- tts = [[TTS_OSX alloc] init];
+ tts = [[TTS_MacOS alloc] init];
NSMenuItem *menu_item;
NSString *title;
@@ -3215,8 +3237,8 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
- GLManager_OSX::ContextType opengl_api_type = GLManager_OSX::GLES_3_0_COMPATIBLE;
- gl_manager = memnew(GLManager_OSX(opengl_api_type));
+ GLManager_MacOS::ContextType opengl_api_type = GLManager_MacOS::GLES_3_0_COMPATIBLE;
+ gl_manager = memnew(GLManager_MacOS(opengl_api_type));
if (gl_manager->initialize() != OK) {
memdelete(gl_manager);
gl_manager = nullptr;
@@ -3228,7 +3250,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
#endif
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
- context_vulkan = memnew(VulkanContextOSX);
+ context_vulkan = memnew(VulkanContextMacOS);
if (context_vulkan->initialize() != OK) {
memdelete(context_vulkan);
context_vulkan = nullptr;
@@ -3263,9 +3285,16 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
RendererCompositorRD::make_current();
}
#endif
+
+ screen_set_keep_on(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true));
}
-DisplayServerOSX::~DisplayServerOSX() {
+DisplayServerMacOS::~DisplayServerMacOS() {
+ if (screen_keep_on_assertion) {
+ IOPMAssertionRelease(screen_keep_on_assertion);
+ screen_keep_on_assertion = kIOPMNullAssertionID;
+ }
+
// Destroy all windows.
for (HashMap<WindowID, WindowData>::Iterator E = windows.begin(); E;) {
HashMap<WindowID, WindowData>::Iterator F = E;
diff --git a/platform/osx/export/codesign.cpp b/platform/macos/export/codesign.cpp
index fd044c00cc..fd044c00cc 100644
--- a/platform/osx/export/codesign.cpp
+++ b/platform/macos/export/codesign.cpp
diff --git a/platform/osx/export/codesign.h b/platform/macos/export/codesign.h
index 3a08c0ea86..fea7b117d0 100644
--- a/platform/osx/export/codesign.h
+++ b/platform/macos/export/codesign.h
@@ -38,8 +38,8 @@
// - Requirements code generator is not implemented (only hard-coded requirements for the ad-hoc signing is supported).
// - RFC5652/CMS blob generation is not implemented, supports ad-hoc signing only.
-#ifndef CODESIGN_H
-#define CODESIGN_H
+#ifndef MACOS_CODESIGN_H
+#define MACOS_CODESIGN_H
#include "core/crypto/crypto_core.h"
#include "core/io/dir_access.h"
@@ -365,4 +365,4 @@ public:
#endif // MODULE_REGEX_ENABLED
-#endif // CODESIGN_H
+#endif // MACOS_CODESIGN_H
diff --git a/platform/osx/export/export.cpp b/platform/macos/export/export.cpp
index bd35b39e9e..ff7457081f 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/macos/export/export.cpp
@@ -32,11 +32,11 @@
#include "export_plugin.h"
-void register_osx_exporter() {
+void register_macos_exporter() {
EDITOR_DEF("export/macos/force_builtin_codesign", false);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::BOOL, "export/macos/force_builtin_codesign", PROPERTY_HINT_NONE));
- Ref<EditorExportPlatformOSX> platform;
+ Ref<EditorExportPlatformMacOS> platform;
platform.instantiate();
EditorExport::get_singleton()->add_export_platform(platform);
diff --git a/platform/iphone/export/export.h b/platform/macos/export/export.h
index adb3c23957..260c691209 100644
--- a/platform/iphone/export/export.h
+++ b/platform/macos/export/export.h
@@ -28,9 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef IPHONE_EXPORT_H
-#define IPHONE_EXPORT_H
+#ifndef MACOS_EXPORT_H
+#define MACOS_EXPORT_H
-void register_iphone_exporter();
+void register_macos_exporter();
-#endif // IPHONE_EXPORT_H
+#endif // MACOS_EXPORT_H
diff --git a/platform/osx/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index 7010709123..bcc2636c07 100644
--- a/platform/osx/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -32,12 +32,13 @@
#include "codesign.h"
+#include "core/string/translation.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "modules/modules_enabled.gen.h" // For regex.
-void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
+void EditorExportPlatformMacOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
if (p_preset->get("texture_format/s3tc")) {
r_features->push_back("s3tc");
}
@@ -47,11 +48,10 @@ void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset>
if (p_preset->get("texture_format/etc2")) {
r_features->push_back("etc2");
}
-
- r_features->push_back("64");
+ r_features->push_back(p_preset->get("binary_format/architecture"));
}
-bool EditorExportPlatformOSX::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const {
+bool EditorExportPlatformMacOS::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const {
// These options are not supported by built-in codesign, used on non macOS host.
if (!OS::get_singleton()->has_feature("macos")) {
if (p_option == "codesign/identity" || p_option == "codesign/timestamp" || p_option == "codesign/hardened_runtime" || p_option == "codesign/custom_options" || p_option.begins_with("notarization/")) {
@@ -68,7 +68,8 @@ bool EditorExportPlatformOSX::get_export_option_visibility(const String &p_optio
return true;
}
-void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) {
+void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options) {
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "universal,x86_64,arm64", PROPERTY_USAGE_STORAGE), "universal"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
@@ -214,7 +215,7 @@ void _rgba8_to_packbits_encode(int p_ch, int p_size, Vector<uint8_t> &p_source,
memcpy(&p_dest.write[ofs], result.ptr(), res_size);
}
-void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
+void EditorExportPlatformMacOS::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
Ref<ImageTexture> it = memnew(ImageTexture);
Vector<uint8_t> data;
@@ -252,9 +253,9 @@ 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);
+ ResourceSaver::save(it, path);
{
Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
@@ -320,7 +321,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
p_data = data;
}
-void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary) {
+void EditorExportPlatformMacOS::_fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary) {
String str;
String strnew;
str.parse_utf8((const char *)plist.ptr(), plist.size());
@@ -407,14 +408,14 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
}
/**
- * If we're running the OSX version of the Godot editor we'll:
+ * If we're running the macOS version of the Godot editor we'll:
* - export our application bundle to a temporary folder
* - attempt to code sign it
* - and then wrap it up in a DMG
*/
-Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
-#ifdef OSX_ENABLED
+Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+#ifdef MACOS_ENABLED
List<String> args;
args.push_back("altool");
@@ -468,7 +469,7 @@ Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset
return OK;
}
-Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn) {
+Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn) {
bool force_builtin_codesign = EditorSettings::get_singleton()->get("export/macos/force_builtin_codesign");
bool ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-");
@@ -476,7 +477,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
print_verbose("using built-in codesign...");
#ifdef MODULE_REGEX_ENABLED
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
if (p_preset->get("codesign/timestamp") && p_warn) {
add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Timestamping is not compatible with ad-hoc signature, and was disabled!"));
}
@@ -566,9 +567,9 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
}
}
-Error EditorExportPlatformOSX::_code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path,
+Error EditorExportPlatformMacOS::_code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path,
const String &p_ent_path, bool p_should_error_on_non_code) {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
static Vector<String> extensions_to_sign;
if (extensions_to_sign.is_empty()) {
@@ -615,7 +616,7 @@ Error EditorExportPlatformOSX::_code_sign_directory(const Ref<EditorExportPreset
return OK;
}
-Error EditorExportPlatformOSX::_copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path,
+Error EditorExportPlatformMacOS::_copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path,
const String &p_in_app_path, bool p_sign_enabled,
const Ref<EditorExportPreset> &p_preset, const String &p_ent_path,
bool p_should_error_on_non_code_sign) {
@@ -644,14 +645,14 @@ Error EditorExportPlatformOSX::_copy_and_sign_files(Ref<DirAccess> &dir_access,
return err;
}
-Error EditorExportPlatformOSX::_export_osx_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin,
+Error EditorExportPlatformMacOS::_export_macos_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin,
const String &p_app_path_name, Ref<DirAccess> &dir_access,
bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset,
const String &p_ent_path) {
Error error{ OK };
- const Vector<String> &osx_plugins{ p_editor_export_plugin->get_osx_plugin_files() };
- for (int i = 0; i < osx_plugins.size(); ++i) {
- String src_path{ ProjectSettings::get_singleton()->globalize_path(osx_plugins[i]) };
+ const Vector<String> &macos_plugins{ p_editor_export_plugin->get_macos_plugin_files() };
+ for (int i = 0; i < macos_plugins.size(); ++i) {
+ String src_path{ ProjectSettings::get_singleton()->globalize_path(macos_plugins[i]) };
String path_in_app{ p_app_path_name + "/Contents/PlugIns/" + src_path.get_file() };
error = _copy_and_sign_files(dir_access, src_path, path_in_app, p_sign_enabled, p_preset, p_ent_path, false);
if (error != OK) {
@@ -661,7 +662,7 @@ Error EditorExportPlatformOSX::_export_osx_plugins_for(Ref<EditorExportPlugin> p
return error;
}
-Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name) {
+Error EditorExportPlatformMacOS::_create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name) {
List<String> args;
if (FileAccess::exists(p_dmg_path)) {
@@ -697,7 +698,7 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin
return OK;
}
-Error EditorExportPlatformOSX::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) {
+Error EditorExportPlatformMacOS::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
if (f.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Debug Script Export"), vformat(TTR("Could not open file \"%s\"."), p_path));
@@ -706,19 +707,30 @@ Error EditorExportPlatformOSX::_export_debug_script(const Ref<EditorExportPreset
f->store_line("#!/bin/sh");
f->store_line("echo -ne '\\033c\\033]0;" + p_app_name + "\\a'");
- f->store_line("function realpath() { python -c \"import os,sys; print(os.path.realpath(sys.argv[1]))\" \"$0\"; }");
- f->store_line("base_path=\"$(dirname \"$(realpath \"$0\")\")\"");
- f->store_line("\"$base_path/" + p_pkg_name + "\" \"$@\"");
+ f->store_line("");
+ f->store_line("function app_realpath() {");
+ f->store_line(" SOURCE=$1");
+ f->store_line(" while [ -h \"$SOURCE\" ]; do");
+ f->store_line(" DIR=$(dirname \"$SOURCE\")");
+ f->store_line(" SOURCE=$(readlink \"$SOURCE\")");
+ f->store_line(" [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE");
+ f->store_line(" done");
+ f->store_line(" echo \"$( cd -P \"$( dirname \"$SOURCE\" )\" >/dev/null 2>&1 && pwd )\"");
+ f->store_line("}");
+ f->store_line("");
+ f->store_line("BASE_PATH=\"$(app_realpath \"${BASH_SOURCE[0]}\")\"");
+ f->store_line("\"$BASE_PATH/" + p_pkg_name + "\" \"$@\"");
+ f->store_line("");
return OK;
}
-Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
String src_pkg_name;
- EditorProgress ep("export", "Exporting for OSX", 3, true);
+ EditorProgress ep("export", "Exporting for macOS", 3, true);
if (p_debug) {
src_pkg_name = p_preset->get("custom_template/debug");
@@ -728,7 +740,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (src_pkg_name.is_empty()) {
String err;
- src_pkg_name = find_export_template("osx.zip", &err);
+ src_pkg_name = find_export_template("macos.zip", &err);
if (src_pkg_name.is_empty()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("Export template not found."));
return ERR_FILE_NOT_FOUND;
@@ -755,7 +767,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
int ret = unzGoToFirstFile(src_pkg_zip);
- String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64";
+ String architecture = p_preset->get("binary_format/architecture");
+ String binary_to_use = "godot_macos_" + String(p_debug ? "debug" : "release") + "." + architecture;
String pkg_name;
if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
@@ -984,7 +997,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
unzCloseCurrentFile(src_pkg_zip);
// Write.
- file = file.replace_first("osx_template.app/", "");
+ file = file.replace_first("macos_template.app/", "");
if (((info.external_fa >> 16L) & 0120000) == 0120000) {
#ifndef UNIX_ENABLED
@@ -1053,19 +1066,19 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
if (data.size() > 0) {
- if (file.find("/data.mono.osx.64.release_debug/") != -1) {
+ if (file.find("/data.mono.macos.release_debug." + architecture + "/") != -1) {
if (!p_debug) {
ret = unzGoToNextFile(src_pkg_zip);
continue; // skip
}
- file = file.replace("/data.mono.osx.64.release_debug/", "/GodotSharp/");
+ file = file.replace("/data.mono.macos.release_debug." + architecture + "/", "/GodotSharp/");
}
- if (file.find("/data.mono.osx.64.release/") != -1) {
+ if (file.find("/data.mono.macos.release." + architecture + "/") != -1) {
if (p_debug) {
ret = unzGoToNextFile(src_pkg_zip);
continue; // skip
}
- file = file.replace("/data.mono.osx.64.release/", "/GodotSharp/");
+ file = file.replace("/data.mono.macos.release." + architecture + "/", "/GodotSharp/");
}
if (file.ends_with(".dylib")) {
@@ -1086,6 +1099,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);
@@ -1298,7 +1312,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
bool ad_hoc = true;
if (err == OK) {
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
String sign_identity = p_preset->get("codesign/identity");
#else
String sign_identity = "-";
@@ -1329,7 +1343,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
Vector<Ref<EditorExportPlugin>> export_plugins{ EditorExport::get_singleton()->get_export_plugins() };
for (int i = 0; i < export_plugins.size(); ++i) {
- err = _export_osx_plugins_for(export_plugins[i], tmp_app_path_name, da, sign_enabled, p_preset, ent_path);
+ err = _export_macos_plugins_for(export_plugins[i], tmp_app_path_name, da, sign_enabled, p_preset, ent_path);
if (err != OK) {
break;
}
@@ -1386,7 +1400,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
}
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
bool noto_enabled = p_preset->get("notarization/enable");
if (err == OK && noto_enabled) {
if (export_format == "app") {
@@ -1419,7 +1433,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
return err;
}
-void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name) {
+void EditorExportPlatformMacOS::_zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name) {
String dir = p_folder.is_empty() ? p_root_path : p_root_path.plus_file(p_folder);
Ref<DirAccess> da = DirAccess::open(dir);
@@ -1536,7 +1550,7 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
da->list_dir_end();
}
-bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
+bool EditorExportPlatformMacOS::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
bool valid = false;
@@ -1559,7 +1573,7 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset
// Look for export templates (official templates, check only is custom templates are not set).
if (!dvalid || !rvalid) {
- dvalid = exists_export_template("osx.zip", &err);
+ dvalid = exists_export_template("macos.zip", &err);
rvalid = dvalid; // Both in the same ZIP.
}
@@ -1575,7 +1589,7 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset
bool sign_enabled = p_preset->get("codesign/enable");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
bool noto_enabled = p_preset->get("notarization/enable");
bool ad_hoc = ((p_preset->get("codesign/identity") == "") || (p_preset->get("codesign/identity") == "-"));
@@ -1664,11 +1678,9 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset
return valid;
}
-EditorExportPlatformOSX::EditorExportPlatformOSX() {
- Ref<Image> img = memnew(Image(_osx_logo));
- logo.instantiate();
- logo->create_from_image(img);
+EditorExportPlatformMacOS::EditorExportPlatformMacOS() {
+ logo = ImageTexture::create_from_image(memnew(Image(_macos_logo)));
}
-EditorExportPlatformOSX::~EditorExportPlatformOSX() {
+EditorExportPlatformMacOS::~EditorExportPlatformMacOS() {
}
diff --git a/platform/osx/export/export_plugin.h b/platform/macos/export/export_plugin.h
index ec97d4139f..21bc380d55 100644
--- a/platform/osx/export/export_plugin.h
+++ b/platform/macos/export/export_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef OSX_EXPORT_PLUGIN_H
-#define OSX_EXPORT_PLUGIN_H
+#ifndef MACOS_EXPORT_PLUGIN_H
+#define MACOS_EXPORT_PLUGIN_H
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
@@ -39,14 +39,14 @@
#include "core/io/zip_io.h"
#include "core/os/os.h"
#include "core/version.h"
-#include "editor/editor_export.h"
#include "editor/editor_settings.h"
-#include "platform/osx/logo.gen.h"
+#include "editor/export/editor_export.h"
+#include "platform/macos/logo.gen.h"
#include <sys/stat.h>
-class EditorExportPlatformOSX : public EditorExportPlatform {
- GDCLASS(EditorExportPlatformOSX, EditorExportPlatform);
+class EditorExportPlatformMacOS : public EditorExportPlatform {
+ GDCLASS(EditorExportPlatformMacOS, EditorExportPlatform);
int version_code = 0;
@@ -61,7 +61,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
Error _copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path, const String &p_in_app_path,
bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path,
bool p_should_error_on_non_code_sign);
- Error _export_osx_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, const String &p_app_path_name,
+ Error _export_macos_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, const String &p_app_path_name,
Ref<DirAccess> &dir_access, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset,
const String &p_ent_path);
Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name);
@@ -69,7 +69,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path);
bool use_codesign() const { return true; }
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
bool use_dmg() const { return true; }
#else
bool use_dmg() const { return false; }
@@ -99,7 +99,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
}
protected:
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
virtual void get_export_options(List<ExportOption> *r_options) override;
virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const override;
@@ -121,7 +121,7 @@ public:
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override;
- virtual void get_platform_features(List<String> *r_features) override {
+ virtual void get_platform_features(List<String> *r_features) const override {
r_features->push_back("pc");
r_features->push_back("s3tc");
r_features->push_back("macos");
@@ -130,8 +130,8 @@ public:
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override {
}
- EditorExportPlatformOSX();
- ~EditorExportPlatformOSX();
+ EditorExportPlatformMacOS();
+ ~EditorExportPlatformMacOS();
};
-#endif
+#endif // MACOS_EXPORT_PLUGIN_H
diff --git a/platform/osx/export/lipo.cpp b/platform/macos/export/lipo.cpp
index 82baf18c52..82baf18c52 100644
--- a/platform/osx/export/lipo.cpp
+++ b/platform/macos/export/lipo.cpp
diff --git a/platform/osx/export/lipo.h b/platform/macos/export/lipo.h
index 0e419be17e..516ef99860 100644
--- a/platform/osx/export/lipo.h
+++ b/platform/macos/export/lipo.h
@@ -30,8 +30,8 @@
// Universal / Universal 2 fat binary file creator and extractor.
-#ifndef LIPO_H
-#define LIPO_H
+#ifndef MACOS_LIPO_H
+#define MACOS_LIPO_H
#include "core/io/file_access.h"
#include "core/object/ref_counted.h"
@@ -73,4 +73,4 @@ public:
#endif // MODULE_REGEX_ENABLED
-#endif // LIPO_H
+#endif // MACOS_LIPO_H
diff --git a/platform/osx/export/macho.cpp b/platform/macos/export/macho.cpp
index e6e67eff06..e6e67eff06 100644
--- a/platform/osx/export/macho.cpp
+++ b/platform/macos/export/macho.cpp
diff --git a/platform/osx/export/macho.h b/platform/macos/export/macho.h
index 6cfc3c44f5..7ef0d9067e 100644
--- a/platform/osx/export/macho.h
+++ b/platform/macos/export/macho.h
@@ -30,8 +30,8 @@
// Mach-O binary object file format parser and editor.
-#ifndef MACHO_H
-#define MACHO_H
+#ifndef MACOS_MACHO_H
+#define MACOS_MACHO_H
#include "core/crypto/crypto.h"
#include "core/crypto/crypto_core.h"
@@ -212,4 +212,4 @@ public:
#endif // MODULE_REGEX_ENABLED
-#endif // MACHO_H
+#endif // MACOS_MACHO_H
diff --git a/platform/osx/export/plist.cpp b/platform/macos/export/plist.cpp
index 36de9dd34b..36de9dd34b 100644
--- a/platform/osx/export/plist.cpp
+++ b/platform/macos/export/plist.cpp
diff --git a/platform/osx/export/plist.h b/platform/macos/export/plist.h
index ba9eaec196..79cb928d0a 100644
--- a/platform/osx/export/plist.h
+++ b/platform/macos/export/plist.h
@@ -30,8 +30,8 @@
// Property list file format (application/x-plist) parser, property list ASN-1 serialization.
-#ifndef PLIST_H
-#define PLIST_H
+#ifndef MACOS_PLIST_H
+#define MACOS_PLIST_H
#include "core/crypto/crypto_core.h"
#include "core/io/file_access.h"
@@ -113,4 +113,4 @@ public:
#endif // MODULE_REGEX_ENABLED
-#endif // PLIST_H
+#endif // MACOS_PLIST_H
diff --git a/platform/osx/gl_manager_osx_legacy.h b/platform/macos/gl_manager_macos_legacy.h
index 2d4913a7a6..8752086551 100644
--- a/platform/osx/gl_manager_osx_legacy.h
+++ b/platform/macos/gl_manager_macos_legacy.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gl_manager_osx_legacy.h */
+/* gl_manager_macos_legacy.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GL_MANAGER_OSX_LEGACY_H
-#define GL_MANAGER_OSX_LEGACY_H
+#ifndef GL_MANAGER_MACOS_LEGACY_H
+#define GL_MANAGER_MACOS_LEGACY_H
-#if defined(OSX_ENABLED) && defined(GLES3_ENABLED)
+#if defined(MACOS_ENABLED) && defined(GLES3_ENABLED)
#include "core/error/error_list.h"
#include "core/os/os.h"
@@ -42,7 +42,7 @@
#import <ApplicationServices/ApplicationServices.h>
#import <CoreVideo/CoreVideo.h>
-class GLManager_OSX {
+class GLManager_MacOS {
public:
enum ContextType {
GLES_3_0_COMPATIBLE,
@@ -89,9 +89,10 @@ public:
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
- GLManager_OSX(ContextType p_context_type);
- ~GLManager_OSX();
+ GLManager_MacOS(ContextType p_context_type);
+ ~GLManager_MacOS();
};
-#endif // OSX_ENABLED && GLES3_ENABLED
-#endif // GL_MANAGER_OSX_LEGACY_H
+#endif // MACOS_ENABLED && GLES3_ENABLED
+
+#endif // GL_MANAGER_MACOS_LEGACY_H
diff --git a/platform/osx/gl_manager_osx_legacy.mm b/platform/macos/gl_manager_macos_legacy.mm
index c769d7f5c5..e6bb7aaa85 100644
--- a/platform/osx/gl_manager_osx_legacy.mm
+++ b/platform/macos/gl_manager_macos_legacy.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gl_manager_osx_legacy.mm */
+/* gl_manager_macos_legacy.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,15 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gl_manager_osx_legacy.h"
+#include "gl_manager_macos_legacy.h"
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
#ifdef GLES3_ENABLED
#include <stdio.h>
#include <stdlib.h>
-Error GLManager_OSX::create_context(GLWindow &win) {
+Error GLManager_MacOS::create_context(GLWindow &win) {
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAClosestPolicy,
@@ -62,7 +62,7 @@ Error GLManager_OSX::create_context(GLWindow &win) {
return OK;
}
-Error GLManager_OSX::window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height) {
+Error GLManager_MacOS::window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height) {
GLWindow win;
win.width = p_width;
win.height = p_height;
@@ -78,7 +78,7 @@ Error GLManager_OSX::window_create(DisplayServer::WindowID p_window_id, id p_vie
return OK;
}
-void GLManager_OSX::window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {
+void GLManager_MacOS::window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {
if (!windows.has(p_window_id)) {
return;
}
@@ -102,7 +102,7 @@ void GLManager_OSX::window_resize(DisplayServer::WindowID p_window_id, int p_wid
[win.context update];
}
-int GLManager_OSX::window_get_width(DisplayServer::WindowID p_window_id) {
+int GLManager_MacOS::window_get_width(DisplayServer::WindowID p_window_id) {
if (!windows.has(p_window_id)) {
return 0;
}
@@ -111,7 +111,7 @@ int GLManager_OSX::window_get_width(DisplayServer::WindowID p_window_id) {
return win.width;
}
-int GLManager_OSX::window_get_height(DisplayServer::WindowID p_window_id) {
+int GLManager_MacOS::window_get_height(DisplayServer::WindowID p_window_id) {
if (!windows.has(p_window_id)) {
return 0;
}
@@ -120,7 +120,7 @@ int GLManager_OSX::window_get_height(DisplayServer::WindowID p_window_id) {
return win.height;
}
-void GLManager_OSX::window_destroy(DisplayServer::WindowID p_window_id) {
+void GLManager_MacOS::window_destroy(DisplayServer::WindowID p_window_id) {
if (!windows.has(p_window_id)) {
return;
}
@@ -132,7 +132,7 @@ void GLManager_OSX::window_destroy(DisplayServer::WindowID p_window_id) {
windows.erase(p_window_id);
}
-void GLManager_OSX::release_current() {
+void GLManager_MacOS::release_current() {
if (current_window == DisplayServer::INVALID_WINDOW_ID) {
return;
}
@@ -140,7 +140,7 @@ void GLManager_OSX::release_current() {
[NSOpenGLContext clearCurrentContext];
}
-void GLManager_OSX::window_make_current(DisplayServer::WindowID p_window_id) {
+void GLManager_MacOS::window_make_current(DisplayServer::WindowID p_window_id) {
if (current_window == p_window_id) {
return;
}
@@ -154,7 +154,7 @@ void GLManager_OSX::window_make_current(DisplayServer::WindowID p_window_id) {
current_window = p_window_id;
}
-void GLManager_OSX::make_current() {
+void GLManager_MacOS::make_current() {
if (current_window == DisplayServer::INVALID_WINDOW_ID) {
return;
}
@@ -166,13 +166,13 @@ void GLManager_OSX::make_current() {
[win.context makeCurrentContext];
}
-void GLManager_OSX::swap_buffers() {
+void GLManager_MacOS::swap_buffers() {
for (const KeyValue<DisplayServer::WindowID, GLWindow> &E : windows) {
[E.value.context flushBuffer];
}
}
-void GLManager_OSX::window_update(DisplayServer::WindowID p_window_id) {
+void GLManager_MacOS::window_update(DisplayServer::WindowID p_window_id) {
if (!windows.has(p_window_id)) {
return;
}
@@ -181,7 +181,7 @@ void GLManager_OSX::window_update(DisplayServer::WindowID p_window_id) {
[win.context update];
}
-void GLManager_OSX::window_set_per_pixel_transparency_enabled(DisplayServer::WindowID p_window_id, bool p_enabled) {
+void GLManager_MacOS::window_set_per_pixel_transparency_enabled(DisplayServer::WindowID p_window_id, bool p_enabled) {
if (!windows.has(p_window_id)) {
return;
}
@@ -197,11 +197,11 @@ void GLManager_OSX::window_set_per_pixel_transparency_enabled(DisplayServer::Win
[win.context update];
}
-Error GLManager_OSX::initialize() {
+Error GLManager_MacOS::initialize() {
return OK;
}
-void GLManager_OSX::set_use_vsync(bool p_use) {
+void GLManager_MacOS::set_use_vsync(bool p_use) {
use_vsync = p_use;
CGLContextObj ctx = CGLGetCurrentContext();
@@ -212,17 +212,17 @@ void GLManager_OSX::set_use_vsync(bool p_use) {
}
}
-bool GLManager_OSX::is_using_vsync() const {
+bool GLManager_MacOS::is_using_vsync() const {
return use_vsync;
}
-GLManager_OSX::GLManager_OSX(ContextType p_context_type) {
+GLManager_MacOS::GLManager_MacOS(ContextType p_context_type) {
context_type = p_context_type;
}
-GLManager_OSX::~GLManager_OSX() {
+GLManager_MacOS::~GLManager_MacOS() {
release_current();
}
#endif // GLES3_ENABLED
-#endif // OSX
+#endif // MACOS_ENABLED
diff --git a/platform/osx/godot_application.h b/platform/macos/godot_application.h
index 8d48a659f3..8d48a659f3 100644
--- a/platform/osx/godot_application.h
+++ b/platform/macos/godot_application.h
diff --git a/platform/osx/godot_application.mm b/platform/macos/godot_application.mm
index 13313a025a..3f71c77fd1 100644
--- a/platform/osx/godot_application.mm
+++ b/platform/macos/godot_application.mm
@@ -30,12 +30,12 @@
#include "godot_application.h"
-#include "display_server_osx.h"
+#include "display_server_macos.h"
@implementation GodotApplication
- (void)sendEvent:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (ds) {
if ([event type] == NSEventTypeLeftMouseDown || [event type] == NSEventTypeRightMouseDown || [event type] == NSEventTypeOtherMouseDown) {
if (ds->mouse_process_popups()) {
diff --git a/platform/osx/godot_application_delegate.h b/platform/macos/godot_application_delegate.h
index 8eec762d8f..f5b67b580f 100644
--- a/platform/osx/godot_application_delegate.h
+++ b/platform/macos/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/macos/godot_application_delegate.mm
index dc82075c44..bacdcc2bc4 100644
--- a/platform/osx/godot_application_delegate.mm
+++ b/platform/macos/godot_application_delegate.mm
@@ -30,8 +30,8 @@
#include "godot_application_delegate.h"
-#include "display_server_osx.h"
-#include "os_osx.h"
+#include "display_server_macos.h"
+#include "os_macos.h"
@implementation GodotApplicationDelegate
@@ -67,8 +67,54 @@
}
}
+- (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_MacOS *os = (OS_MacOS *)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();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (ds) {
ds->mouse_process_popups(true);
}
@@ -84,14 +130,14 @@
}
- (void)globalMenuCallback:(id)sender {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (ds) {
return ds->menu_callback(sender);
}
}
- (NSMenu *)applicationDockMenu:(NSApplication *)sender {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (ds) {
return ds->get_dock_menu();
} else {
@@ -99,35 +145,16 @@
}
}
-- (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();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (ds) {
- ds->send_window_event(ds->get_window(DisplayServerOSX::MAIN_WINDOW_ID), DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
+ ds->send_window_event(ds->get_window(DisplayServerMacOS::MAIN_WINDOW_ID), DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST);
}
return NSTerminateCancel;
}
- (void)showAbout:(id)sender {
- OS_OSX *os = (OS_OSX *)OS::get_singleton();
+ OS_MacOS *os = (OS_MacOS *)OS::get_singleton();
if (os && os->get_main_loop()) {
os->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT);
}
diff --git a/platform/osx/godot_content_view.h b/platform/macos/godot_content_view.h
index 7942d716dc..353305aec1 100644
--- a/platform/osx/godot_content_view.h
+++ b/platform/macos/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/macos/godot_content_view.mm
index e96f0a8098..dbed969901 100644
--- a/platform/osx/godot_content_view.mm
+++ b/platform/macos/godot_content_view.mm
@@ -30,8 +30,8 @@
#include "godot_content_view.h"
-#include "display_server_osx.h"
-#include "key_mapping_osx.h"
+#include "display_server_macos.h"
+#include "key_mapping_macos.h"
@implementation GodotContentView
@@ -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, *)) {
@@ -55,7 +56,7 @@
return self;
}
-- (void)setWindowID:(DisplayServerOSX::WindowID)wid {
+- (void)setWindowID:(DisplayServerMacOS::WindowID)wid {
window_id = wid;
}
@@ -66,7 +67,7 @@
}
- (void)updateLayer {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
ds->window_update(window_id);
[super updateLayer];
}
@@ -105,12 +106,12 @@
return;
}
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
if (wd.im_active) {
ime_input_event_in_progress = true;
ds->update_im_text(Point2i(selectedRange.location, selectedRange.length), String::utf8([[marked_text mutableString] UTF8String]));
@@ -125,12 +126,12 @@
ime_input_event_in_progress = false;
[[marked_text mutableString] setString:@""];
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
if (wd.im_active) {
ds->update_im_text(Point2i(), String());
}
@@ -149,12 +150,12 @@
}
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return NSMakeRect(0, 0, 0, 0);
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
const NSRect content_rect = [wd.window_view frame];
const float scale = ds->screen_get_max_scale();
NSRect point_in_window_rect = NSMakeRect(wd.im_position.x / scale, content_rect.size.height - (wd.im_position.y / scale) - 1, 0, 0);
@@ -190,7 +191,7 @@
return;
}
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
[self cancelComposition];
return;
@@ -209,10 +210,10 @@
continue;
}
- DisplayServerOSX::KeyEvent ke;
+ DisplayServerMacOS::KeyEvent ke;
ke.window_id = window_id;
- ke.osx_state = [event modifierFlags];
+ ke.macos_state = [event modifierFlags];
ke.pressed = true;
ke.echo = false;
ke.raw = false; // IME input event.
@@ -236,12 +237,12 @@
}
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return NO;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
if (!wd.drop_files_callback.is_null()) {
Vector<String> files;
NSPasteboard *pboard = [sender draggingPasteboard];
@@ -266,7 +267,7 @@
Variant *vp = &v;
Variant ret;
Callable::CallError ce;
- wd.drop_files_callback.call((const Variant **)&vp, 1, ret, ce);
+ wd.drop_files_callback.callp((const Variant **)&vp, 1, ret, ce);
}
return NO;
@@ -275,12 +276,12 @@
// MARK: Focus
- (BOOL)canBecomeKeyView {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return YES;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
return !wd.no_focus && !wd.is_popup;
}
@@ -291,7 +292,7 @@
// MARK: Mouse
- (void)cursorUpdate:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds) {
return;
}
@@ -300,12 +301,12 @@
}
- (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index mask:(MouseButton)mask pressed:(bool)pressed {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
MouseButton last_button_state = ds->mouse_get_button_state();
if (pressed) {
@@ -355,12 +356,12 @@
}
- (void)mouseMoved:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
NSPoint delta = NSMakePoint([event deltaX], [event deltaY]);
NSPoint mpos = [event locationInWindow];
@@ -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());
@@ -431,38 +438,38 @@
}
- (void)mouseExited:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
if (ds->mouse_get_mode() != DisplayServer::MOUSE_MODE_CAPTURED) {
- ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_EXIT);
+ ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_MOUSE_EXIT);
}
}
- (void)mouseEntered:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
if (ds->mouse_get_mode() != DisplayServer::MOUSE_MODE_CAPTURED) {
- ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_ENTER);
+ ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_MOUSE_ENTER);
}
ds->cursor_update_shape();
}
- (void)magnifyWithEvent:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
Ref<InputEventMagnifyGesture> ev;
ev.instantiate();
@@ -490,12 +497,12 @@
// MARK: Keyboard
- (void)keyDown:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
ignore_momentum_scroll = true;
@@ -504,7 +511,7 @@
NSString *characters = [event characters];
NSUInteger length = [characters length];
- if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]))) {
+ if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]))) {
// Fallback unicode character handler used if IME is not active.
Char16String text;
text.resize([characters length] + 1);
@@ -516,28 +523,28 @@
for (int i = 0; i < u32text.length(); i++) {
const char32_t codepoint = u32text[i];
- DisplayServerOSX::KeyEvent ke;
+ DisplayServerMacOS::KeyEvent ke;
ke.window_id = window_id;
- ke.osx_state = [event modifierFlags];
+ ke.macos_state = [event modifierFlags];
ke.pressed = true;
ke.echo = [event isARepeat];
- ke.keycode = KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]);
- ke.physical_keycode = KeyMappingOSX::translate_key([event keyCode]);
+ ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]);
+ ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
ke.raw = true;
ke.unicode = codepoint;
ds->push_to_key_event_buffer(ke);
}
} else {
- DisplayServerOSX::KeyEvent ke;
+ DisplayServerMacOS::KeyEvent ke;
ke.window_id = window_id;
- ke.osx_state = [event modifierFlags];
+ ke.macos_state = [event modifierFlags];
ke.pressed = true;
ke.echo = [event isARepeat];
- ke.keycode = KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]);
- ke.physical_keycode = KeyMappingOSX::translate_key([event keyCode]);
+ ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]);
+ ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
ke.raw = false;
ke.unicode = 0;
@@ -552,7 +559,7 @@
}
- (void)flagsChanged:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
@@ -560,7 +567,7 @@
// Ignore all input if IME input is in progress
if (!ime_input_event_in_progress) {
- DisplayServerOSX::KeyEvent ke;
+ DisplayServerMacOS::KeyEvent ke;
ke.window_id = window_id;
ke.echo = false;
@@ -601,9 +608,9 @@
return;
}
- ke.osx_state = mod;
- ke.keycode = KeyMappingOSX::remap_key(key, mod);
- ke.physical_keycode = KeyMappingOSX::translate_key(key);
+ ke.macos_state = mod;
+ ke.keycode = KeyMappingMacOS::remap_key(key, mod);
+ ke.physical_keycode = KeyMappingMacOS::translate_key(key);
ke.unicode = 0;
ds->push_to_key_event_buffer(ke);
@@ -611,12 +618,12 @@
}
- (void)keyUp:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
// Ignore all input if IME input is in progress.
if (!ime_input_event_in_progress) {
@@ -624,7 +631,7 @@
NSUInteger length = [characters length];
// Fallback unicode character handler used if IME is not active.
- if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]))) {
+ if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]))) {
Char16String text;
text.resize([characters length] + 1);
[characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])];
@@ -634,28 +641,28 @@
for (int i = 0; i < u32text.length(); i++) {
const char32_t codepoint = u32text[i];
- DisplayServerOSX::KeyEvent ke;
+ DisplayServerMacOS::KeyEvent ke;
ke.window_id = window_id;
- ke.osx_state = [event modifierFlags];
+ ke.macos_state = [event modifierFlags];
ke.pressed = false;
ke.echo = [event isARepeat];
- ke.keycode = KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]);
- ke.physical_keycode = KeyMappingOSX::translate_key([event keyCode]);
+ ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]);
+ ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
ke.raw = true;
ke.unicode = codepoint;
ds->push_to_key_event_buffer(ke);
}
} else {
- DisplayServerOSX::KeyEvent ke;
+ DisplayServerMacOS::KeyEvent ke;
ke.window_id = window_id;
- ke.osx_state = [event modifierFlags];
+ ke.macos_state = [event modifierFlags];
ke.pressed = false;
ke.echo = [event isARepeat];
- ke.keycode = KeyMappingOSX::remap_key([event keyCode], [event modifierFlags]);
- ke.physical_keycode = KeyMappingOSX::translate_key([event keyCode]);
+ ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags]);
+ ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
ke.raw = true;
ke.unicode = 0;
@@ -667,12 +674,12 @@
// MARK: Scroll and pan
- (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
MouseButton mask = mouse_button_to_mask(button);
Ref<InputEventMouseButton> sc;
@@ -706,12 +713,12 @@
}
- (void)processPanEvent:(NSEvent *)event dx:(double)dx dy:(double)dy {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
Ref<InputEventPanGesture> pg;
pg.instantiate();
@@ -725,12 +732,12 @@
}
- (void)scrollWheel:(NSEvent *)event {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
ds->update_mouse_pos(wd, [event locationInWindow]);
double delta_x = [event scrollingDeltaX];
diff --git a/platform/osx/godot_main_osx.mm b/platform/macos/godot_main_macos.mm
index 053a7f4a1d..66071f1404 100644
--- a/platform/osx/godot_main_osx.mm
+++ b/platform/macos/godot_main_macos.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* godot_main_osx.mm */
+/* godot_main_macos.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -30,7 +30,7 @@
#include "main/main.h"
-#include "os_osx.h"
+#include "os_macos.h"
#include <string.h>
#include <unistd.h>
@@ -68,22 +68,17 @@ int main(int argc, char **argv) {
printf("Current path: %s\n", cwd);
#endif
- OS_OSX os;
+ OS_MacOS os;
Error err;
// 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/godot_menu_item.h b/platform/macos/godot_menu_item.h
index 2c12897f10..2c12897f10 100644
--- a/platform/osx/godot_menu_item.h
+++ b/platform/macos/godot_menu_item.h
diff --git a/platform/osx/godot_window.h b/platform/macos/godot_window.h
index 16ff101142..9fc5599e86 100644
--- a/platform/osx/godot_window.h
+++ b/platform/macos/godot_window.h
@@ -44,4 +44,4 @@
@end
-#endif //GODOT_WINDOW_H
+#endif // GODOT_WINDOW_H
diff --git a/platform/osx/godot_window.mm b/platform/macos/godot_window.mm
index d43853a94b..e205e7546d 100644
--- a/platform/osx/godot_window.mm
+++ b/platform/macos/godot_window.mm
@@ -30,7 +30,7 @@
#include "godot_window.h"
-#include "display_server_osx.h"
+#include "display_server_macos.h"
@implementation GodotWindow
@@ -40,29 +40,29 @@
return self;
}
-- (void)setWindowID:(DisplayServerOSX::WindowID)wid {
+- (void)setWindowID:(DisplayServerMacOS::WindowID)wid {
window_id = wid;
}
- (BOOL)canBecomeKeyWindow {
// Required for NSWindowStyleMaskBorderless windows.
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return YES;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
return !wd.no_focus && !wd.is_popup;
}
- (BOOL)canBecomeMainWindow {
// Required for NSWindowStyleMaskBorderless windows.
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return YES;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
return !wd.no_focus && !wd.is_popup;
}
diff --git a/platform/osx/godot_window_delegate.h b/platform/macos/godot_window_delegate.h
index 8a1f681fcd..98c226aa2f 100644
--- a/platform/osx/godot_window_delegate.h
+++ b/platform/macos/godot_window_delegate.h
@@ -44,4 +44,4 @@
@end
-#endif //GODOT_WINDOW_DELEGATE_H
+#endif // GODOT_WINDOW_DELEGATE_H
diff --git a/platform/osx/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm
index 521127f01b..2d9329ab3c 100644
--- a/platform/osx/godot_window_delegate.mm
+++ b/platform/macos/godot_window_delegate.mm
@@ -30,7 +30,7 @@
#include "godot_window_delegate.h"
-#include "display_server_osx.h"
+#include "display_server_macos.h"
@implementation GodotWindowDelegate
@@ -39,42 +39,42 @@
}
- (BOOL)windowShouldClose:(id)sender {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return YES;
}
- ds->send_window_event(ds->get_window(window_id), DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
+ ds->send_window_event(ds->get_window(window_id), DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST);
return NO;
}
- (void)windowWillClose:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
ds->popup_close(window_id);
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
while (wd.transient_children.size()) {
- ds->window_set_transient(*wd.transient_children.begin(), DisplayServerOSX::INVALID_WINDOW_ID);
+ ds->window_set_transient(*wd.transient_children.begin(), DisplayServerMacOS::INVALID_WINDOW_ID);
}
- if (wd.transient_parent != DisplayServerOSX::INVALID_WINDOW_ID) {
- ds->window_set_transient(window_id, DisplayServerOSX::INVALID_WINDOW_ID);
+ if (wd.transient_parent != DisplayServerMacOS::INVALID_WINDOW_ID) {
+ ds->window_set_transient(window_id, DisplayServerMacOS::INVALID_WINDOW_ID);
}
ds->window_destroy(window_id);
}
- (void)windowDidEnterFullScreen:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
wd.fullscreen = true;
// Reset window size limits.
[wd.window_object setContentMinSize:NSMakeSize(0, 0)];
@@ -85,12 +85,12 @@
}
- (void)windowDidExitFullScreen:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
wd.fullscreen = false;
// Set window size limits.
@@ -119,12 +119,12 @@
}
- (void)windowDidChangeBackingProperties:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
CGFloat new_scale_factor = [wd.window_object backingScaleFactor];
CGFloat old_scale_factor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue];
@@ -137,7 +137,7 @@
wd.size.width = content_rect.size.width * scale;
wd.size.height = content_rect.size.height * scale;
- ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_DPI_CHANGE);
+ ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_DPI_CHANGE);
CALayer *layer = [wd.window_view layer];
if (layer) {
@@ -150,26 +150,26 @@
}
- (void)windowWillStartLiveResize:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (ds) {
ds->set_is_resizing(true);
}
}
- (void)windowDidEndLiveResize:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (ds) {
ds->set_is_resizing(false);
}
}
- (void)windowDidResize:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
const NSRect content_rect = [wd.window_view frame];
const float scale = ds->screen_get_max_scale();
wd.size.width = content_rect.size.width * scale;
@@ -187,17 +187,17 @@
Variant *sizep = &size;
Variant ret;
Callable::CallError ce;
- wd.rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce);
+ wd.rect_changed_callback.callp((const Variant **)&sizep, 1, ret, ce);
}
}
- (void)windowDidMove:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
ds->release_pressed_events();
if (!wd.rect_changed_callback.is_null()) {
@@ -205,17 +205,17 @@
Variant *sizep = &size;
Variant ret;
Callable::CallError ce;
- wd.rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce);
+ wd.rect_changed_callback.callp((const Variant **)&sizep, 1, ret, ce);
}
}
- (void)windowDidBecomeKey:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
if (ds->mouse_get_mode() == DisplayServer::MOUSE_MODE_CAPTURED) {
const NSRect content_rect = [wd.window_view frame];
@@ -228,43 +228,43 @@
}
ds->set_last_focused_window(window_id);
- ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN);
+ ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN);
}
- (void)windowDidResignKey:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
ds->release_pressed_events();
- ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_OUT);
+ ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT);
}
- (void)windowDidMiniaturize:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
ds->release_pressed_events();
- ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_OUT);
+ ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT);
}
- (void)windowDidDeminiaturize:(NSNotification *)notification {
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
return;
}
- DisplayServerOSX::WindowData &wd = ds->get_window(window_id);
+ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
ds->set_last_focused_window(window_id);
- ds->send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN);
+ ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN);
}
@end
diff --git a/platform/osx/joypad_osx.cpp b/platform/macos/joypad_macos.cpp
index be9567e17c..1ddcfec1b5 100644
--- a/platform/osx/joypad_osx.cpp
+++ b/platform/macos/joypad_macos.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* joypad_osx.cpp */
+/* joypad_macos.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "joypad_osx.h"
+#include "joypad_macos.h"
#include <machine/endian.h>
#define GODOT_JOY_LOOP_RUN_MODE CFSTR("GodotJoypad")
-static JoypadOSX *self = nullptr;
+static JoypadMacOS *self = nullptr;
joypad::joypad() {
ff_constant_force.lMagnitude = 10000;
@@ -235,7 +235,7 @@ static bool is_joypad(IOHIDDeviceRef p_device_ref) {
return true;
}
-void JoypadOSX::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) {
+void JoypadMacOS::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) {
if (p_res != kIOReturnSuccess || have_device(p_device)) {
return;
}
@@ -258,7 +258,7 @@ void JoypadOSX::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) {
IOHIDDeviceScheduleWithRunLoop(p_device, CFRunLoopGetCurrent(), GODOT_JOY_LOOP_RUN_MODE);
}
-void JoypadOSX::_device_removed(IOReturn p_res, IOHIDDeviceRef p_device) {
+void JoypadMacOS::_device_removed(IOReturn p_res, IOHIDDeviceRef p_device) {
int device = get_joy_ref(p_device);
ERR_FAIL_COND(device == -1);
@@ -278,7 +278,7 @@ static String _hex_str(uint8_t p_byte) {
return ret;
}
-bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) {
+bool JoypadMacOS::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) {
p_joy->device_ref = p_device_ref;
// Get device name.
String name;
@@ -445,7 +445,7 @@ static HatMask process_hat_value(int p_min, int p_max, int p_value, bool p_offse
return hat_value;
}
-void JoypadOSX::poll_joypads() const {
+void JoypadMacOS::poll_joypads() const {
while (CFRunLoopRunInMode(GODOT_JOY_LOOP_RUN_MODE, 0, TRUE) == kCFRunLoopRunHandledSource) {
// No-op. Pending callbacks will fire.
}
@@ -456,7 +456,7 @@ static float axis_correct(int p_value, int p_min, int p_max) {
return 2.0f * (p_value - p_min) / (p_max - p_min) - 1.0f;
}
-void JoypadOSX::process_joypads() {
+void JoypadMacOS::process_joypads() {
poll_joypads();
for (int i = 0; i < device_list.size(); i++) {
@@ -494,7 +494,7 @@ void JoypadOSX::process_joypads() {
}
}
-void JoypadOSX::joypad_vibration_start(int p_id, float p_magnitude, float p_duration, uint64_t p_timestamp) {
+void JoypadMacOS::joypad_vibration_start(int p_id, float p_magnitude, float p_duration, uint64_t p_timestamp) {
joypad *joy = &device_list.write[get_joy_index(p_id)];
joy->ff_timestamp = p_timestamp;
joy->ff_effect.dwDuration = p_duration * FF_SECONDS;
@@ -503,13 +503,13 @@ void JoypadOSX::joypad_vibration_start(int p_id, float p_magnitude, float p_dura
FFEffectStart(joy->ff_object, 1, 0);
}
-void JoypadOSX::joypad_vibration_stop(int p_id, uint64_t p_timestamp) {
+void JoypadMacOS::joypad_vibration_stop(int p_id, uint64_t p_timestamp) {
joypad *joy = &device_list.write[get_joy_index(p_id)];
joy->ff_timestamp = p_timestamp;
FFEffectStop(joy->ff_object);
}
-int JoypadOSX::get_joy_index(int p_id) const {
+int JoypadMacOS::get_joy_index(int p_id) const {
for (int i = 0; i < device_list.size(); i++) {
if (device_list[i].id == p_id) {
return i;
@@ -518,7 +518,7 @@ int JoypadOSX::get_joy_index(int p_id) const {
return -1;
}
-int JoypadOSX::get_joy_ref(IOHIDDeviceRef p_device) const {
+int JoypadMacOS::get_joy_ref(IOHIDDeviceRef p_device) const {
for (int i = 0; i < device_list.size(); i++) {
if (device_list[i].device_ref == p_device) {
return i;
@@ -527,7 +527,7 @@ int JoypadOSX::get_joy_ref(IOHIDDeviceRef p_device) const {
return -1;
}
-bool JoypadOSX::have_device(IOHIDDeviceRef p_device) const {
+bool JoypadMacOS::have_device(IOHIDDeviceRef p_device) const {
for (int i = 0; i < device_list.size(); i++) {
if (device_list[i].device_ref == p_device) {
return true;
@@ -561,7 +561,7 @@ static CFDictionaryRef create_match_dictionary(const UInt32 page, const UInt32 u
return retval;
}
-void JoypadOSX::config_hid_manager(CFArrayRef p_matching_array) const {
+void JoypadMacOS::config_hid_manager(CFArrayRef p_matching_array) const {
CFRunLoopRef runloop = CFRunLoopGetCurrent();
IOReturn ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
ERR_FAIL_COND(ret != kIOReturnSuccess);
@@ -576,7 +576,7 @@ void JoypadOSX::config_hid_manager(CFArrayRef p_matching_array) const {
}
}
-JoypadOSX::JoypadOSX(Input *in) {
+JoypadMacOS::JoypadMacOS(Input *in) {
self = this;
input = in;
@@ -604,7 +604,7 @@ JoypadOSX::JoypadOSX(Input *in) {
}
}
-JoypadOSX::~JoypadOSX() {
+JoypadMacOS::~JoypadMacOS() {
for (int i = 0; i < device_list.size(); i++) {
device_list.write[i].free();
}
diff --git a/platform/osx/joypad_osx.h b/platform/macos/joypad_macos.h
index 3f89048ce6..4b14fed6d5 100644
--- a/platform/osx/joypad_osx.h
+++ b/platform/macos/joypad_macos.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* joypad_osx.h */
+/* joypad_macos.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef JOYPADOSX_H
-#define JOYPADOSX_H
+#ifndef JOYPAD_MACOS_H
+#define JOYPAD_MACOS_H
#ifdef MACOS_10_0_4
#import <IOKit/hidsystem/IOHIDUsageTables.h>
@@ -88,7 +88,7 @@ struct joypad {
joypad();
};
-class JoypadOSX {
+class JoypadMacOS {
enum {
JOYPADS_MAX = 16,
};
@@ -117,8 +117,8 @@ public:
void _device_added(IOReturn p_res, IOHIDDeviceRef p_device);
void _device_removed(IOReturn p_res, IOHIDDeviceRef p_device);
- JoypadOSX(Input *in);
- ~JoypadOSX();
+ JoypadMacOS(Input *in);
+ ~JoypadMacOS();
};
-#endif // JOYPADOSX_H
+#endif // JOYPAD_MACOS_H
diff --git a/platform/osx/key_mapping_osx.h b/platform/macos/key_mapping_macos.h
index 252cc907bb..fc5b791e44 100644
--- a/platform/osx/key_mapping_osx.h
+++ b/platform/macos/key_mapping_macos.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* key_mapping_osx.h */
+/* key_mapping_macos.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef KEY_MAPPING_OSX_H
-#define KEY_MAPPING_OSX_H
+#ifndef KEY_MAPPING_MACOS_H
+#define KEY_MAPPING_MACOS_H
#include "core/os/keyboard.h"
-class KeyMappingOSX {
- KeyMappingOSX() {}
+class KeyMappingMacOS {
+ KeyMappingMacOS() {}
static bool is_numpad_key(unsigned int key);
@@ -49,4 +49,4 @@ public:
static unsigned int keycode_get_native_mask(Key p_keycode);
};
-#endif // KEY_MAPPING_OSX_H
+#endif // KEY_MAPPING_MACOS_H
diff --git a/platform/osx/key_mapping_osx.mm b/platform/macos/key_mapping_macos.mm
index 0bf6bc7d1c..f6cff7124b 100644
--- a/platform/osx/key_mapping_osx.mm
+++ b/platform/macos/key_mapping_macos.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* key_mapping_osx.mm */
+/* key_mapping_macos.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,12 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "key_mapping_osx.h"
+#include "key_mapping_macos.h"
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
-bool KeyMappingOSX::is_numpad_key(unsigned int key) {
+bool KeyMappingMacOS::is_numpad_key(unsigned int key) {
static const unsigned int table[] = {
0x41, /* kVK_ANSI_KeypadDecimal */
0x43, /* kVK_ANSI_KeypadMultiply */
@@ -65,7 +65,7 @@ bool KeyMappingOSX::is_numpad_key(unsigned int key) {
}
// Keyboard symbol translation table.
-static const Key _osx_to_godot_table[128] = {
+static const Key _macos_to_godot_table[128] = {
/* 00 */ Key::A,
/* 01 */ Key::S,
/* 02 */ Key::D,
@@ -197,18 +197,18 @@ static const Key _osx_to_godot_table[128] = {
};
// Translates a OS X keycode to a Godot keycode.
-Key KeyMappingOSX::translate_key(unsigned int key) {
+Key KeyMappingMacOS::translate_key(unsigned int key) {
if (key >= 128) {
return Key::UNKNOWN;
}
- return _osx_to_godot_table[key];
+ return _macos_to_godot_table[key];
}
-// Translates a Godot keycode back to a OSX keycode.
-unsigned int KeyMappingOSX::unmap_key(Key key) {
+// Translates a Godot keycode back to a macOS keycode.
+unsigned int KeyMappingMacOS::unmap_key(Key key) {
for (int i = 0; i <= 126; i++) {
- if (_osx_to_godot_table[i] == key) {
+ if (_macos_to_godot_table[i] == key) {
return i;
}
}
@@ -279,7 +279,7 @@ static const _KeyCodeMap _keycodes[55] = {
};
// Remap key according to current keyboard layout.
-Key KeyMappingOSX::remap_key(unsigned int key, unsigned int state) {
+Key KeyMappingMacOS::remap_key(unsigned int key, unsigned int state) {
if (is_numpad_key(key)) {
return translate_key(key);
}
@@ -463,7 +463,7 @@ static const _KeyCodeText _native_keycodes[] = {
/* clang-format on */
};
-String KeyMappingOSX::keycode_get_native_string(Key p_keycode) {
+String KeyMappingMacOS::keycode_get_native_string(Key p_keycode) {
const _KeyCodeText *kct = &_native_keycodes[0];
while (kct->text) {
@@ -475,7 +475,7 @@ String KeyMappingOSX::keycode_get_native_string(Key p_keycode) {
return String();
}
-unsigned int KeyMappingOSX::keycode_get_native_mask(Key p_keycode) {
+unsigned int KeyMappingMacOS::keycode_get_native_mask(Key p_keycode) {
unsigned int mask = 0;
if ((p_keycode & KeyModifierMask::CTRL) != Key::NONE) {
mask |= NSEventModifierFlagControl;
diff --git a/platform/osx/logo.png b/platform/macos/logo.png
index b5a660b165..b5a660b165 100644
--- a/platform/osx/logo.png
+++ b/platform/macos/logo.png
Binary files differ
diff --git a/platform/osx/osx_terminal_logger.h b/platform/macos/macos_terminal_logger.h
index 8413509c4b..a811a5cbaf 100644
--- a/platform/osx/osx_terminal_logger.h
+++ b/platform/macos/macos_terminal_logger.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* osx_terminal_logger.h */
+/* macos_terminal_logger.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,17 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef OSX_TERMINAL_LOGGER_H
-#define OSX_TERMINAL_LOGGER_H
+#ifndef MACOS_TERMINAL_LOGGER_H
+#define MACOS_TERMINAL_LOGGER_H
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
#include "core/io/logger.h"
-class OSXTerminalLogger : public StdLogger {
+class MacOSTerminalLogger : public StdLogger {
public:
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR) override;
};
-#endif // OSX_ENABLED
-#endif // OSX_TERMINAL_LOGGER_H
+#endif // MACOS_ENABLED
+
+#endif // MACOS_TERMINAL_LOGGER_H
diff --git a/platform/osx/osx_terminal_logger.mm b/platform/macos/macos_terminal_logger.mm
index 48e26f42bf..b5ea2938ee 100644
--- a/platform/osx/osx_terminal_logger.mm
+++ b/platform/macos/macos_terminal_logger.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* osx_terminal_logger.mm */
+/* macos_terminal_logger.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "osx_terminal_logger.h"
+#include "macos_terminal_logger.h"
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
#include <os/log.h>
-void OSXTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) {
+void MacOSTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) {
if (!should_log(true)) {
return;
}
@@ -79,4 +79,4 @@ void OSXTerminalLogger::log_error(const char *p_function, const char *p_file, in
}
}
-#endif // OSX_ENABLED
+#endif // MACOS_ENABLED
diff --git a/platform/osx/os_osx.h b/platform/macos/os_macos.h
index e4ec411c96..a1eb0f7f69 100644
--- a/platform/osx/os_osx.h
+++ b/platform/macos/os_macos.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* os_osx.h */
+/* os_macos.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,21 +28,21 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef OS_OSX_H
-#define OS_OSX_H
+#ifndef OS_MACOS_H
+#define OS_MACOS_H
#include "core/input/input.h"
-#include "crash_handler_osx.h"
+#include "crash_handler_macos.h"
#include "drivers/coreaudio/audio_driver_coreaudio.h"
#include "drivers/coremidi/midi_driver_coremidi.h"
#include "drivers/unix/os_unix.h"
-#include "joypad_osx.h"
+#include "joypad_macos.h"
#include "servers/audio_server.h"
-class OS_OSX : public OS_Unix {
+class OS_MacOS : public OS_Unix {
bool force_quit = false;
- JoypadOSX *joypad_osx = nullptr;
+ JoypadMacOS *joypad_macos = nullptr;
#ifdef COREAUDIO_ENABLED
AudioDriverCoreAudio audio_driver;
@@ -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;
@@ -97,6 +97,8 @@ public:
virtual String get_locale() const override;
+ virtual Vector<String> get_system_fonts() const override;
+ virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override;
virtual String get_executable_path() const override;
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
@@ -113,8 +115,8 @@ public:
void run();
- OS_OSX();
- ~OS_OSX();
+ OS_MacOS();
+ ~OS_MacOS();
};
-#endif
+#endif // OS_MACOS_H
diff --git a/platform/osx/os_osx.mm b/platform/macos/os_macos.mm
index a8fa56e34b..cc550043de 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/macos/os_macos.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* os_osx.mm */
+/* os_macos.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,16 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "os_osx.h"
+#include "os_macos.h"
#include "core/version_generated.gen.h"
#include "main/main.h"
-#include "dir_access_osx.h"
-#include "display_server_osx.h"
+#include "dir_access_macos.h"
+#include "display_server_macos.h"
#include "godot_application.h"
#include "godot_application_delegate.h"
-#include "osx_terminal_logger.h"
+#include "macos_terminal_logger.h"
#include <dlfcn.h>
#include <libproc.h>
@@ -45,7 +45,7 @@
#include <os/log.h>
#include <sys/sysctl.h>
-_FORCE_INLINE_ String OS_OSX::get_framework_executable(const String &p_path) {
+_FORCE_INLINE_ String OS_MacOS::get_framework_executable(const String &p_path) {
// Append framework executable name, or return as is if p_path is not a framework.
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (da->dir_exists(p_path) && da->file_exists(p_path.plus_file(p_path.get_file().get_basename()))) {
@@ -55,10 +55,10 @@ _FORCE_INLINE_ String OS_OSX::get_framework_executable(const String &p_path) {
}
}
-void OS_OSX::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context) {
+void OS_MacOS::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context) {
// Prevent main loop from sleeping and redraw window during resize / modal popups.
- DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (get_singleton()->get_main_loop() && ds && (get_singleton()->get_render_thread_mode() != RENDER_SEPARATE_THREAD || !ds->get_is_resizing())) {
Main::force_redraw();
if (!Main::is_iterating()) { // Avoid cyclic loop.
@@ -69,13 +69,13 @@ void OS_OSX::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActi
CFRunLoopWakeUp(CFRunLoopGetCurrent()); // Prevent main loop from sleeping.
}
-void OS_OSX::initialize() {
+void OS_MacOS::initialize() {
crash_handler.initialize();
initialize_core();
}
-String OS_OSX::get_processor_name() const {
+String OS_MacOS::get_processor_name() const {
char buffer[256];
size_t buffer_len = 256;
if (sysctlbyname("machdep.cpu.brand_string", &buffer, &buffer_len, NULL, 0) == 0) {
@@ -84,35 +84,35 @@ String OS_OSX::get_processor_name() const {
ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string."));
}
-void OS_OSX::initialize_core() {
+void OS_MacOS::initialize_core() {
OS_Unix::initialize_core();
- DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_RESOURCES);
- DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_USERDATA);
- DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_FILESYSTEM);
+ DirAccess::make_default<DirAccessMacOS>(DirAccess::ACCESS_RESOURCES);
+ DirAccess::make_default<DirAccessMacOS>(DirAccess::ACCESS_USERDATA);
+ DirAccess::make_default<DirAccessMacOS>(DirAccess::ACCESS_FILESYSTEM);
}
-void OS_OSX::finalize() {
+void OS_MacOS::finalize() {
#ifdef COREMIDI_ENABLED
midi_driver.close();
#endif
delete_main_loop();
- if (joypad_osx) {
- memdelete(joypad_osx);
+ if (joypad_macos) {
+ memdelete(joypad_macos);
}
}
-void OS_OSX::initialize_joypads() {
- joypad_osx = memnew(JoypadOSX(Input::get_singleton()));
+void OS_MacOS::initialize_joypads() {
+ joypad_macos = memnew(JoypadMacOS(Input::get_singleton()));
}
-void OS_OSX::set_main_loop(MainLoop *p_main_loop) {
+void OS_MacOS::set_main_loop(MainLoop *p_main_loop) {
main_loop = p_main_loop;
}
-void OS_OSX::delete_main_loop() {
+void OS_MacOS::delete_main_loop() {
if (!main_loop) {
return;
}
@@ -121,19 +121,19 @@ void OS_OSX::delete_main_loop() {
main_loop = nullptr;
}
-String OS_OSX::get_open_with_filename() const {
- return open_with_filename;
+void OS_MacOS::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_MacOS::get_cmdline_platform_args() const {
+ return launch_service_args;
}
-String OS_OSX::get_name() const {
+String OS_MacOS::get_name() const {
return "macOS";
}
-void OS_OSX::alert(const String &p_alert, const String &p_title) {
+void OS_MacOS::alert(const String &p_alert, const String &p_title) {
NSAlert *window = [[NSAlert alloc] init];
NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()];
NSString *ns_alert = [NSString stringWithUTF8String:p_alert.utf8().get_data()];
@@ -150,7 +150,7 @@ void OS_OSX::alert(const String &p_alert, const String &p_title) {
}
}
-Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
+Error OS_MacOS::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
String path = get_framework_executable(p_path);
if (!FileAccess::exists(path)) {
@@ -173,11 +173,11 @@ Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle,
return OK;
}
-MainLoop *OS_OSX::get_main_loop() const {
+MainLoop *OS_MacOS::get_main_loop() const {
return main_loop;
}
-String OS_OSX::get_config_path() const {
+String OS_MacOS::get_config_path() const {
// The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well.
if (has_environment("XDG_CONFIG_HOME")) {
if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
@@ -192,7 +192,7 @@ String OS_OSX::get_config_path() const {
return ".";
}
-String OS_OSX::get_data_path() const {
+String OS_MacOS::get_data_path() const {
// The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well.
if (has_environment("XDG_DATA_HOME")) {
if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
@@ -204,7 +204,7 @@ String OS_OSX::get_data_path() const {
return get_config_path();
}
-String OS_OSX::get_cache_path() const {
+String OS_MacOS::get_cache_path() const {
// The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on macOS as well.
if (has_environment("XDG_CACHE_HOME")) {
if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
@@ -219,7 +219,7 @@ String OS_OSX::get_cache_path() const {
return get_config_path();
}
-String OS_OSX::get_bundle_resource_dir() const {
+String OS_MacOS::get_bundle_resource_dir() const {
String ret;
NSBundle *main = [NSBundle mainBundle];
@@ -230,7 +230,7 @@ String OS_OSX::get_bundle_resource_dir() const {
return ret;
}
-String OS_OSX::get_bundle_icon_path() const {
+String OS_MacOS::get_bundle_icon_path() const {
String ret;
NSBundle *main = [NSBundle mainBundle];
@@ -244,11 +244,11 @@ String OS_OSX::get_bundle_icon_path() const {
}
// Get properly capitalized engine name for system paths
-String OS_OSX::get_godot_dir_name() const {
+String OS_MacOS::get_godot_dir_name() const {
return String(VERSION_SHORT_NAME).capitalize();
}
-String OS_OSX::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
+String OS_MacOS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
NSSearchPathDirectory id;
bool found = true;
@@ -287,7 +287,7 @@ String OS_OSX::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
return ret;
}
-Error OS_OSX::shell_open(String p_uri) {
+Error OS_MacOS::shell_open(String p_uri) {
NSString *string = [NSString stringWithUTF8String:p_uri.utf8().get_data()];
NSURL *uri = [[NSURL alloc] initWithString:string];
// Escape special characters in filenames
@@ -298,12 +298,86 @@ Error OS_OSX::shell_open(String p_uri) {
return OK;
}
-String OS_OSX::get_locale() const {
+String OS_MacOS::get_locale() const {
NSString *locale_code = [[NSLocale preferredLanguages] objectAtIndex:0];
return String([locale_code UTF8String]).replace("-", "_");
}
-String OS_OSX::get_executable_path() const {
+Vector<String> OS_MacOS::get_system_fonts() const {
+ HashSet<String> font_names;
+ CFArrayRef fonts = CTFontManagerCopyAvailableFontFamilyNames();
+ if (fonts) {
+ for (CFIndex i = 0; i < CFArrayGetCount(fonts); i++) {
+ CFStringRef cf_name = (CFStringRef)CFArrayGetValueAtIndex(fonts, i);
+ if (cf_name && (CFStringGetLength(cf_name) > 0) && (CFStringCompare(cf_name, CFSTR("LastResort"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && (CFStringGetCharacterAtIndex(cf_name, 0) != '.')) {
+ NSString *ns_name = (__bridge NSString *)cf_name;
+ font_names.insert(String::utf8([ns_name UTF8String]));
+ }
+ }
+ CFRelease(fonts);
+ }
+
+ Vector<String> ret;
+ for (const String &E : font_names) {
+ ret.push_back(E);
+ }
+ return ret;
+}
+
+String OS_MacOS::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
+ String ret;
+
+ String font_name = p_font_name;
+ if (font_name.to_lower() == "sans-serif") {
+ font_name = "Helvetica";
+ } else if (font_name.to_lower() == "serif") {
+ font_name = "Times";
+ } else if (font_name.to_lower() == "monospace") {
+ font_name = "Courier";
+ } else if (font_name.to_lower() == "fantasy") {
+ font_name = "Papyrus";
+ } else if (font_name.to_lower() == "cursive") {
+ font_name = "Apple Chancery";
+ };
+
+ CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
+
+ CTFontSymbolicTraits traits = 0;
+ if (p_bold) {
+ traits |= kCTFontBoldTrait;
+ }
+ if (p_italic) {
+ traits |= kCTFontItalicTrait;
+ }
+
+ CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
+ CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
+ CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
+
+ CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
+ CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
+ CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
+
+ CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes);
+ if (font) {
+ CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(font, kCTFontURLAttribute);
+ if (url) {
+ NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]];
+ ret = String::utf8([font_path UTF8String]);
+ CFRelease(url);
+ }
+ CFRelease(font);
+ }
+
+ CFRelease(attributes);
+ CFRelease(traits_dict);
+ CFRelease(sym_traits);
+ CFRelease(name);
+
+ return ret;
+}
+
+String OS_MacOS::get_executable_path() const {
char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
int pid = getpid();
pid_t ret = proc_pidpath(pid, pathbuf, sizeof(pathbuf));
@@ -317,7 +391,7 @@ String OS_OSX::get_executable_path() const {
}
}
-Error OS_OSX::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
+Error OS_MacOS::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
// Use NSWorkspace if path is an .app bundle.
NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
NSBundle *bundle = [NSBundle bundleWithURL:url];
@@ -375,7 +449,7 @@ Error OS_OSX::create_process(const String &p_path, const List<String> &p_argumen
}
}
-Error OS_OSX::create_instance(const List<String> &p_arguments, ProcessID *r_child_id) {
+Error OS_MacOS::create_instance(const List<String> &p_arguments, ProcessID *r_child_id) {
// If executable is bundled, always execute editor instances as an app bundle to ensure app window is registered and activated correctly.
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
if (nsappname != nil) {
@@ -387,7 +461,7 @@ Error OS_OSX::create_instance(const List<String> &p_arguments, ProcessID *r_chil
}
}
-String OS_OSX::get_unique_id() const {
+String OS_MacOS::get_unique_id() const {
static String serial_number;
if (serial_number.is_empty()) {
@@ -412,19 +486,19 @@ String OS_OSX::get_unique_id() const {
return serial_number;
}
-bool OS_OSX::_check_internal_feature_support(const String &p_feature) {
+bool OS_MacOS::_check_internal_feature_support(const String &p_feature) {
return p_feature == "pc";
}
-void OS_OSX::disable_crash_handler() {
+void OS_MacOS::disable_crash_handler() {
crash_handler.disable();
}
-bool OS_OSX::is_disable_crash_handler() const {
+bool OS_MacOS::is_disable_crash_handler() const {
return crash_handler.is_disabled();
}
-Error OS_OSX::move_to_trash(const String &p_path) {
+Error OS_MacOS::move_to_trash(const String &p_path) {
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
NSError *err;
@@ -437,7 +511,7 @@ Error OS_OSX::move_to_trash(const String &p_path) {
return OK;
}
-void OS_OSX::run() {
+void OS_MacOS::run() {
force_quit = false;
if (!main_loop) {
@@ -452,7 +526,7 @@ void OS_OSX::run() {
if (DisplayServer::get_singleton()) {
DisplayServer::get_singleton()->process_events(); // Get rid of pending events.
}
- joypad_osx->process_joypads();
+ joypad_macos->process_joypads();
if (Main::iteration()) {
quit = true;
@@ -465,19 +539,19 @@ void OS_OSX::run() {
main_loop->finalize();
}
-OS_OSX::OS_OSX() {
+OS_MacOS::OS_MacOS() {
main_loop = nullptr;
force_quit = false;
Vector<Logger *> loggers;
- loggers.push_back(memnew(OSXTerminalLogger));
+ loggers.push_back(memnew(MacOSTerminalLogger));
_set_logger(memnew(CompositeLogger(loggers)));
#ifdef COREAUDIO_ENABLED
AudioDriverManager::add_driver(&audio_driver);
#endif
- DisplayServerOSX::register_osx_driver();
+ DisplayServerMacOS::register_macos_driver();
// Implicitly create shared NSApplication instance.
[GodotApplication sharedApplication];
@@ -518,7 +592,7 @@ OS_OSX::OS_OSX() {
[NSApp activateIgnoringOtherApps:YES];
}
-OS_OSX::~OS_OSX() {
+OS_MacOS::~OS_MacOS() {
CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), pre_wait_observer, kCFRunLoopCommonModes);
CFRelease(pre_wait_observer);
}
diff --git a/platform/osx/platform_config.h b/platform/macos/platform_config.h
index e114606b82..e114606b82 100644
--- a/platform/osx/platform_config.h
+++ b/platform/macos/platform_config.h
diff --git a/platform/osx/platform_osx_builders.py b/platform/macos/platform_macos_builders.py
index 953ed479db..3a1cc92bd2 100644
--- a/platform/osx/platform_osx_builders.py
+++ b/platform/macos/platform_macos_builders.py
@@ -7,7 +7,7 @@ import os
from platform_methods import subprocess_main
-def make_debug_osx(target, source, env):
+def make_debug_macos(target, source, env):
if env["macports_clang"] != "no":
mpprefix = os.environ.get("MACPORTS_PREFIX", "/opt/local")
mpclangver = env["macports_clang"]
diff --git a/platform/osx/tts_osx.h b/platform/macos/tts_macos.h
index 449418e48f..344676868a 100644
--- a/platform/osx/tts_osx.h
+++ b/platform/macos/tts_macos.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* tts_osx.h */
+/* tts_macos.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef TTS_OSX_H
-#define TTS_OSX_H
+#ifndef TTS_MACOS_H
+#define TTS_MACOS_H
#include "core/string/ustring.h"
#include "core/templates/list.h"
@@ -45,7 +45,7 @@
#import <AVFoundation/AVFoundation.h>
#endif
-@interface TTS_OSX : NSObject <AVSpeechSynthesizerDelegate> {
+@interface TTS_MacOS : NSObject <AVSpeechSynthesizerDelegate> {
// AVSpeechSynthesizer
bool speaking;
HashMap<id, int> ids;
@@ -68,4 +68,4 @@
- (Array)getVoices;
@end
-#endif // TTS_OSX_H
+#endif // TTS_MACOS_H
diff --git a/platform/osx/tts_osx.mm b/platform/macos/tts_macos.mm
index e6a5236cd9..3c101b9531 100644
--- a/platform/osx/tts_osx.mm
+++ b/platform/macos/tts_macos.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* tts_osx.mm */
+/* tts_macos.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,9 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "tts_osx.h"
+#include "tts_macos.h"
-@implementation TTS_OSX
+@implementation TTS_MacOS
- (id)init {
self = [super init];
diff --git a/platform/osx/vulkan_context_osx.h b/platform/macos/vulkan_context_macos.h
index ade0f4a4c9..579c42b042 100644
--- a/platform/osx/vulkan_context_osx.h
+++ b/platform/macos/vulkan_context_macos.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* vulkan_context_osx.h */
+/* vulkan_context_macos.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,20 +28,20 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VULKAN_DEVICE_OSX_H
-#define VULKAN_DEVICE_OSX_H
+#ifndef VULKAN_CONTEXT_MACOS_H
+#define VULKAN_CONTEXT_MACOS_H
#include "drivers/vulkan/vulkan_context.h"
#import <AppKit/AppKit.h>
-class VulkanContextOSX : public VulkanContext {
+class VulkanContextMacOS : public VulkanContext {
virtual const char *_get_platform_surface_extension() const;
public:
Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height);
- VulkanContextOSX();
- ~VulkanContextOSX();
+ VulkanContextMacOS();
+ ~VulkanContextMacOS();
};
-#endif // VULKAN_DEVICE_OSX_H
+#endif // VULKAN_CONTEXT_MACOS_H
diff --git a/platform/osx/vulkan_context_osx.mm b/platform/macos/vulkan_context_macos.mm
index bdabc24c28..cf317f3c68 100644
--- a/platform/osx/vulkan_context_osx.mm
+++ b/platform/macos/vulkan_context_macos.mm
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* vulkan_context_osx.mm */
+/* vulkan_context_macos.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,18 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "vulkan_context_osx.h"
+#include "vulkan_context_macos.h"
#ifdef USE_VOLK
#include <volk.h>
#else
#include <vulkan/vulkan.h>
#endif
-const char *VulkanContextOSX::_get_platform_surface_extension() const {
+const char *VulkanContextMacOS::_get_platform_surface_extension() const {
return VK_MVK_MACOS_SURFACE_EXTENSION_NAME;
}
-Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height) {
+Error VulkanContextMacOS::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, id p_window, int p_width, int p_height) {
VkMacOSSurfaceCreateInfoMVK createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = nullptr;
@@ -52,8 +52,8 @@ Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, Displ
return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
-VulkanContextOSX::VulkanContextOSX() {
+VulkanContextMacOS::VulkanContextMacOS() {
}
-VulkanContextOSX::~VulkanContextOSX() {
+VulkanContextMacOS::~VulkanContextMacOS() {
}
diff --git a/platform/osx/SCsub b/platform/osx/SCsub
deleted file mode 100644
index 3a4c95613d..0000000000
--- a/platform/osx/SCsub
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-
-from platform_methods import run_in_subprocess
-import platform_osx_builders
-
-files = [
- "os_osx.mm",
- "godot_application.mm",
- "godot_application_delegate.mm",
- "crash_handler_osx.mm",
- "osx_terminal_logger.mm",
- "display_server_osx.mm",
- "godot_content_view.mm",
- "godot_window_delegate.mm",
- "godot_window.mm",
- "key_mapping_osx.mm",
- "godot_main_osx.mm",
- "dir_access_osx.mm",
- "tts_osx.mm",
- "joypad_osx.cpp",
- "vulkan_context_osx.mm",
- "gl_manager_osx_legacy.mm",
-]
-
-prog = env.add_program("#bin/godot", files)
-
-if env["debug_symbols"] and env["separate_debug_symbols"]:
- env.AddPostAction(prog, run_in_subprocess(platform_osx_builders.make_debug_osx))
diff --git a/platform/register_platform_apis.h b/platform/register_platform_apis.h
index 8b6d23a7a4..9dd90d9b20 100644
--- a/platform/register_platform_apis.h
+++ b/platform/register_platform_apis.h
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef REGISTER_APIS_H
-#define REGISTER_APIS_H
+#ifndef REGISTER_PLATFORM_APIS_H
+#define REGISTER_PLATFORM_APIS_H
void register_platform_apis();
void unregister_platform_apis();
-#endif
+#endif // REGISTER_PLATFORM_APIS_H
diff --git a/platform/uwp/app_uwp.h b/platform/uwp/app_uwp.h
index 9aadcfac75..82ad3ca01a 100644
--- a/platform/uwp/app_uwp.h
+++ b/platform/uwp/app_uwp.h
@@ -112,4 +112,5 @@ namespace GodotUWP
}
/* clang-format on */
+
#endif // APP_UWP_H
diff --git a/platform/uwp/export/app_packager.h b/platform/uwp/export/app_packager.h
index dc5a5259ec..18db3eb806 100644
--- a/platform/uwp/export/app_packager.h
+++ b/platform/uwp/export/app_packager.h
@@ -40,7 +40,7 @@
#include "core/io/zip_io.h"
#include "core/object/class_db.h"
#include "core/version.h"
-#include "editor/editor_export.h"
+#include "editor/export/editor_export_platform.h"
#include "thirdparty/minizip/unzip.h"
#include "thirdparty/minizip/zip.h"
@@ -146,4 +146,4 @@ public:
~AppxPackager();
};
-#endif
+#endif // UWP_APP_PACKAGER_H
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index efba006985..31105824a5 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -30,6 +30,7 @@
#include "export.h"
+#include "editor/editor_settings.h"
#include "export_plugin.h"
void register_uwp_exporter() {
diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp
index 01683c656c..070c46242f 100644
--- a/platform/uwp/export/export_plugin.cpp
+++ b/platform/uwp/export/export_plugin.cpp
@@ -30,6 +30,7 @@
#include "export_plugin.h"
+#include "editor/editor_settings.h"
#include "platform/uwp/logo.gen.h"
String EditorExportPlatformUWP::get_name() const {
@@ -49,27 +50,17 @@ Ref<Texture2D> EditorExportPlatformUWP::get_logo() const {
return logo;
}
-void EditorExportPlatformUWP::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
+void EditorExportPlatformUWP::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
r_features->push_back("s3tc");
r_features->push_back("etc");
- switch ((int)p_preset->get("architecture/target")) {
- case EditorExportPlatformUWP::ARM: {
- r_features->push_back("arm");
- } break;
- case EditorExportPlatformUWP::X86: {
- r_features->push_back("32");
- } break;
- case EditorExportPlatformUWP::X64: {
- r_features->push_back("64");
- } break;
- }
+ r_features->push_back(p_preset->get("binary_format/architecture"));
}
void EditorExportPlatformUWP::get_export_options(List<ExportOption> *r_options) {
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "architecture/target", PROPERTY_HINT_ENUM, "arm,x86,x64"), 1));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32,arm32"), "x86_64"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), ""));
@@ -143,23 +134,18 @@ bool EditorExportPlatformUWP::can_export(const Ref<EditorExportPreset> &p_preset
bool valid = false;
// Look for export templates (first official, and if defined custom templates).
-
- Platform arch = (Platform)(int)(p_preset->get("architecture/target"));
- String platform_infix;
- switch (arch) {
- case EditorExportPlatformUWP::ARM: {
- platform_infix = "arm";
- } break;
- case EditorExportPlatformUWP::X86: {
- platform_infix = "x86";
- } break;
- case EditorExportPlatformUWP::X64: {
- platform_infix = "x64";
- } break;
+ String arch = p_preset->get("binary_format/architecture");
+ String arch_infix;
+ if (arch == "arm32") {
+ arch_infix = "arm";
+ } else if (arch == "x86_32") {
+ arch_infix = "x86";
+ } else if (arch == "x86_64") {
+ arch_infix = "x64";
}
- bool dvalid = exists_export_template("uwp_" + platform_infix + "_debug.zip", &err);
- bool rvalid = exists_export_template("uwp_" + platform_infix + "_release.zip", &err);
+ bool dvalid = exists_export_template("uwp_" + arch_infix + "_debug.zip", &err);
+ bool rvalid = exists_export_template("uwp_" + arch_infix + "_release.zip", &err);
if (p_preset->get("custom_template/debug") != "") {
dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
@@ -263,25 +249,21 @@ Error EditorExportPlatformUWP::export_project(const Ref<EditorExportPreset> &p_p
src_appx = src_appx.strip_edges();
- Platform arch = (Platform)(int)p_preset->get("architecture/target");
+ String arch = p_preset->get("binary_format/architecture");
if (src_appx.is_empty()) {
- String err, infix;
- switch (arch) {
- case ARM: {
- infix = "_arm_";
- } break;
- case X86: {
- infix = "_x86_";
- } break;
- case X64: {
- infix = "_x64_";
- } break;
+ String err, arch_infix;
+ if (arch == "arm32") {
+ arch_infix = "arm";
+ } else if (arch == "x86_32") {
+ arch_infix = "x86";
+ } else if (arch == "x86_64") {
+ arch_infix = "x64";
}
if (p_debug) {
- src_appx = find_export_template("uwp" + infix + "debug.zip", &err);
+ src_appx = find_export_template("uwp_" + arch_infix + "_debug.zip", &err);
} else {
- src_appx = find_export_template("uwp" + infix + "release.zip", &err);
+ src_appx = find_export_template("uwp_" + arch_infix + "_release.zip", &err);
}
if (src_appx.is_empty()) {
EditorNode::add_io_error(err);
@@ -494,7 +476,7 @@ Error EditorExportPlatformUWP::export_project(const Ref<EditorExportPreset> &p_p
return OK;
}
-void EditorExportPlatformUWP::get_platform_features(List<String> *r_features) {
+void EditorExportPlatformUWP::get_platform_features(List<String> *r_features) const {
r_features->push_back("pc");
r_features->push_back("uwp");
}
@@ -503,7 +485,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/uwp/export/export_plugin.h b/platform/uwp/export/export_plugin.h
index d92687075c..4a3c5db377 100644
--- a/platform/uwp/export/export_plugin.h
+++ b/platform/uwp/export/export_plugin.h
@@ -39,9 +39,9 @@
#include "core/io/zip_io.h"
#include "core/object/class_db.h"
#include "core/version.h"
-#include "editor/editor_export.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
+#include "editor/export/editor_export_platform.h"
#include "thirdparty/minizip/unzip.h"
#include "thirdparty/minizip/zip.h"
@@ -90,12 +90,6 @@ class EditorExportPlatformUWP : public EditorExportPlatform {
Ref<ImageTexture> logo;
- enum Platform {
- ARM,
- X86,
- X64
- };
-
bool _valid_resource_name(const String &p_name) const {
if (p_name.is_empty()) {
return false;
@@ -215,8 +209,8 @@ class EditorExportPlatformUWP : public EditorExportPlatform {
String version = itos(p_preset->get("version/major")) + "." + itos(p_preset->get("version/minor")) + "." + itos(p_preset->get("version/build")) + "." + itos(p_preset->get("version/revision"));
result = result.replace("$version_string$", version);
- Platform arch = (Platform)(int)p_preset->get("architecture/target");
- String architecture = arch == ARM ? "arm" : (arch == X86 ? "x86" : "x64");
+ String arch = p_preset->get("binary_format/architecture");
+ String architecture = arch == "arm32" ? "arm" : (arch == "x86_32" ? "x86" : "x64");
result = result.replace("$architecture$", architecture);
result = result.replace("$display_name$", String(p_preset->get("package/display_name")).is_empty() ? (String)ProjectSettings::get_singleton()->get("application/config/name") : String(p_preset->get("package/display_name")));
@@ -431,7 +425,7 @@ public:
virtual Ref<Texture2D> get_logo() const override;
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
virtual void get_export_options(List<ExportOption> *r_options) override;
@@ -439,11 +433,11 @@ public:
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
- virtual void get_platform_features(List<String> *r_features) override;
+ virtual void get_platform_features(List<String> *r_features) const override;
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override;
EditorExportPlatformUWP();
};
-#endif
+#endif // UWP_EXPORT_PLUGIN_H
diff --git a/platform/uwp/joypad_uwp.h b/platform/uwp/joypad_uwp.h
index 0869f1961d..81f84152b9 100644
--- a/platform/uwp/joypad_uwp.h
+++ b/platform/uwp/joypad_uwp.h
@@ -78,4 +78,4 @@ private:
void joypad_vibration_stop(int p_device, uint64_t p_timestamp);
};
-#endif
+#endif // JOYPAD_UWP_H
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 1614bfdcc3..7bc4c6047c 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -557,6 +557,7 @@ uint64_t OS_UWP::get_ticks_usec() const {
void OS_UWP::process_events() {
joypad->process_controllers();
process_key_events();
+ input->flush_buffered_events();
}
void OS_UWP::process_key_events() {
@@ -715,7 +716,7 @@ bool OS_UWP::has_virtual_keyboard() const {
return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch;
}
-void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
InputPane ^ pane = InputPane::GetForCurrentView();
pane->TryShow();
}
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index bddf63ff18..fe61f60548 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -231,7 +231,7 @@ public:
virtual bool has_touchscreen_ui_hint() const;
virtual bool has_virtual_keyboard() const;
- virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
+ virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
virtual void hide_virtual_keyboard();
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr);
@@ -252,4 +252,4 @@ public:
~OS_UWP();
};
-#endif
+#endif // OS_UWP_H
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index b82fe5e7ad..dd2df1f004 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -198,7 +198,6 @@ def configure_msvc(env, manual_msvc_config):
elif env["target"] == "debug":
env.AppendUnique(CCFLAGS=["/Zi", "/FS", "/Od", "/EHsc"])
# Allow big objects. Only needed for debug, see MinGW branch for rationale.
- env.AppendUnique(CCFLAGS=["/bigobj"])
env.Append(LINKFLAGS=["/DEBUG"])
if env["debug_symbols"]:
@@ -221,6 +220,10 @@ def configure_msvc(env, manual_msvc_config):
env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"])
env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding.
env.AppendUnique(CXXFLAGS=["/TP"]) # assume all sources are C++
+ # Once it was thought that only debug builds would be too large,
+ # but this has recently stopped being true. See the mingw function
+ # for notes on why this shouldn't be enabled for gcc
+ env.AppendUnique(CCFLAGS=["/bigobj"])
if manual_msvc_config: # should be automatic if SCons found it
if os.getenv("WindowsSdkDir") is not None:
@@ -267,6 +270,7 @@ def configure_msvc(env, manual_msvc_config):
"bcrypt",
"Avrt",
"dwmapi",
+ "dwrite",
]
if env["vulkan"]:
@@ -438,6 +442,7 @@ def configure_mingw(env):
"avrt",
"uuid",
"dwmapi",
+ "dwrite",
]
)
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 998b0882b3..a975d09a9d 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -531,10 +531,43 @@ DisplayServer::ScreenOrientation DisplayServerWindows::screen_get_orientation(in
}
void DisplayServerWindows::screen_set_keep_on(bool p_enable) {
+ if (keep_screen_on == p_enable) {
+ return;
+ }
+
+ if (p_enable) {
+ const String reason = "Godot Engine running with display/window/energy_saving/keep_screen_on = true";
+ Char16String reason_utf16 = reason.utf16();
+
+ REASON_CONTEXT context;
+ context.Version = POWER_REQUEST_CONTEXT_VERSION;
+ context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
+ context.Reason.SimpleReasonString = (LPWSTR)(reason_utf16.ptrw());
+ power_request = PowerCreateRequest(&context);
+ if (power_request == INVALID_HANDLE_VALUE) {
+ print_error("Failed to enable screen_keep_on.");
+ return;
+ }
+ if (PowerSetRequest(power_request, POWER_REQUEST_TYPE::PowerRequestSystemRequired) == 0) {
+ print_error("Failed to request system sleep override.");
+ return;
+ }
+ if (PowerSetRequest(power_request, POWER_REQUEST_TYPE::PowerRequestDisplayRequired) == 0) {
+ print_error("Failed to request display timeout override.");
+ return;
+ }
+ } else {
+ PowerClearRequest(power_request, POWER_REQUEST_TYPE::PowerRequestSystemRequired);
+ PowerClearRequest(power_request, POWER_REQUEST_TYPE::PowerRequestDisplayRequired);
+ CloseHandle(power_request);
+ power_request = nullptr;
+ }
+
+ keep_screen_on = p_enable;
}
bool DisplayServerWindows::screen_is_kept_on() const {
- return false;
+ return keep_screen_on;
}
Vector<DisplayServer::WindowID> DisplayServerWindows::get_window_list() const {
@@ -656,7 +689,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
}
@@ -2033,7 +2068,7 @@ void DisplayServerWindows::_send_window_event(const WindowData &wd, WindowEvent
Variant *eventp = &event;
Variant ret;
Callable::CallError ce;
- wd.event_callback.call((const Variant **)&eventp, 1, ret, ce);
+ wd.event_callback.callp((const Variant **)&eventp, 1, ret, ce);
}
}
@@ -2060,7 +2095,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
if (windows.has(E->get())) {
Callable callable = windows[E->get()].input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
in_dispatch_input_event = false;
@@ -2074,7 +2109,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
if (windows.has(event_from_window->get_window_id())) {
Callable callable = windows[event_from_window->get_window_id()].input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
} else {
@@ -2082,7 +2117,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
for (const KeyValue<WindowID, WindowData> &E : windows) {
const Callable callable = E.value.input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
}
@@ -2380,7 +2415,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
case WM_MOUSELEAVE: {
old_invalid = true;
- outside = true;
+ windows[window_id].mouse_outside = true;
_send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_EXIT);
@@ -2490,6 +2525,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 +2545,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);
@@ -2607,7 +2645,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
- if (outside) {
+ if (windows[window_id].mouse_outside) {
// Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
@@ -2617,7 +2655,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
CursorShape c = cursor_shape;
cursor_shape = CURSOR_MAX;
cursor_set_shape(c);
- outside = false;
+ windows[window_id].mouse_outside = false;
// Once-off notification, must call again.
track_mouse_leave_event(hWnd);
@@ -2640,6 +2678,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);
@@ -2707,7 +2746,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
- if (outside) {
+ if (windows[window_id].mouse_outside) {
// Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
@@ -2717,7 +2756,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
CursorShape c = cursor_shape;
cursor_shape = CURSOR_MAX;
cursor_set_shape(c);
- outside = false;
+ windows[window_id].mouse_outside = false;
// Once-off notification, must call again.
track_mouse_leave_event(hWnd);
@@ -2742,14 +2781,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);
@@ -3030,7 +3072,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
const Variant *args[] = { &size };
Variant ret;
Callable::CallError ce;
- window.rect_changed_callback.call(args, 1, ret, ce);
+ window.rect_changed_callback.callp(args, 1, ret, ce);
}
}
@@ -3190,7 +3232,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
Variant *vp = &v;
Variant ret;
Callable::CallError ce;
- windows[window_id].drop_files_callback.call((const Variant **)&vp, 1, ret, ce);
+ windows[window_id].drop_files_callback.callp((const Variant **)&vp, 1, ret, ce);
}
} break;
default: {
@@ -3360,8 +3402,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;
@@ -3449,6 +3491,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
windows.erase(id);
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create Windows OS window.");
}
+ if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
+ wd.fullscreen = true;
+ if (p_mode == WINDOW_MODE_FULLSCREEN) {
+ wd.multiwindow_fs = true;
+ }
+ }
if (p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
wd.pre_fs_valid = true;
}
@@ -3484,8 +3532,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;
@@ -3599,13 +3647,14 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
old_invalid = true;
mouse_mode = MOUSE_MODE_VISIBLE;
- outside = true;
-
rendering_driver = p_rendering_driver;
// Init TTS
tts = memnew(TTS_Windows);
+ // Enforce default keep screen on value.
+ screen_set_keep_on(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true));
+
// Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
if (wintab_lib) {
@@ -3809,6 +3858,9 @@ DisplayServerWindows::~DisplayServerWindows() {
SetWindowLongPtr(windows[MAIN_WINDOW_ID].hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
}
+ // Close power request handle.
+ screen_set_keep_on(false);
+
#ifdef GLES3_ENABLED
// destroy windows .. NYI?
// FIXME wglDeleteContext is never called
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index fc89517774..db9b589304 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
@@ -301,7 +313,6 @@ class DisplayServerWindows : public DisplayServer {
int key_event_pos;
bool old_invalid;
- bool outside;
int old_x, old_y;
Point2i center;
@@ -320,6 +331,8 @@ class DisplayServerWindows : public DisplayServer {
HINSTANCE hInstance; // Holds The Instance Of The Application
String rendering_driver;
bool app_focused = false;
+ bool keep_screen_on = false;
+ HANDLE power_request;
TTS_Windows *tts = nullptr;
@@ -357,11 +370,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;
@@ -373,6 +388,7 @@ class DisplayServerWindows : public DisplayServer {
Size2 window_rect;
Point2 last_pos;
+ bool mouse_outside = true;
ObjectID instance_id;
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 0fa2913218..20320470b8 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -30,6 +30,7 @@
#include "export.h"
+#include "editor/export/editor_export.h"
#include "export_plugin.h"
void register_windows_exporter() {
@@ -48,12 +49,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/export/export.h b/platform/windows/export/export.h
index 09399f2bee..1054e04b1e 100644
--- a/platform/windows/export/export.h
+++ b/platform/windows/export/export.h
@@ -33,4 +33,4 @@
void register_windows_exporter();
-#endif
+#endif // WINDOWS_EXPORT_H
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index 16c67345e0..febef5ad12 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -104,7 +104,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
}
String EditorExportPlatformWindows::get_template_file_name(const String &p_target, const String &p_arch) const {
- return "windows_" + p_arch + "_" + p_target + ".exe";
+ return "windows_" + p_target + "_" + p_arch + ".exe";
}
List<String> EditorExportPlatformWindows::get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const {
@@ -123,6 +123,7 @@ bool EditorExportPlatformWindows::get_export_option_visibility(const String &p_o
void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) {
EditorExportPlatformPC::get_export_options(r_options);
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32"), "x86_64"));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0));
@@ -230,13 +231,13 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
String str;
Error err = OS::get_singleton()->execute(rcedit_path, args, &str, nullptr, true);
if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) {
- add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable, configure rcedit path in the Editor Settings (Export > Windows > Rcedit)."));
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable. Configure rcedit path in the Editor Settings (Export > Windows > Rcedit), or disable \"Application > Modify Resources\" in the export preset."));
return err;
}
print_line("rcedit (" + p_path + "): " + str);
if (str.find("Fatal error") != -1) {
- add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("rcedit failed to modify executable:\n%s"), str));
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("rcedit failed to modify executable: %s."), str));
return FAILED;
}
@@ -378,7 +379,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
String str;
Error err = OS::get_singleton()->execute(signtool_path, args, &str, nullptr, true);
if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) {
- add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start signtool executable, configure signtool path in the Editor Settings (Export > Windows > Signtool)."));
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start signtool executable. Configure signtool path in the Editor Settings (Export > Windows > Signtool), or disable \"Codesign\" in the export preset."));
return err;
}
@@ -388,7 +389,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
#else
if (str.find("Failed") != -1) {
#endif
- add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Signtool failed to sign executable:\n%s"), str));
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Signtool failed to sign executable: %s."), str));
return FAILED;
}
diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h
index 51f98365a9..b9e59829a0 100644
--- a/platform/windows/export/export_plugin.h
+++ b/platform/windows/export/export_plugin.h
@@ -33,8 +33,8 @@
#include "core/io/file_access.h"
#include "core/os/os.h"
-#include "editor/editor_export.h"
#include "editor/editor_settings.h"
+#include "editor/export/editor_export_platform_pc.h"
#include "platform/windows/logo.gen.h"
class EditorExportPlatformWindows : public EditorExportPlatformPC {
@@ -54,4 +54,4 @@ public:
virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override;
};
-#endif
+#endif // WINDOWS_EXPORT_PLUGIN_H
diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis
index bb855e4ac8..cdd1c14978 100644
--- a/platform/windows/godot.natvis
+++ b/platform/windows/godot.natvis
@@ -40,11 +40,13 @@
<DisplayString Condition="type == Variant::TRANSFORM2D">{_data._transform2d}</DisplayString>
<DisplayString Condition="type == Variant::AABB">{_data._aabb}</DisplayString>
<DisplayString Condition="type == Variant::BASIS">{_data._basis}</DisplayString>
- <DisplayString Condition="type == Variant::TRANSFORM3D">{_data._transform}</DisplayString>
+ <DisplayString Condition="type == Variant::TRANSFORM3D">{_data._transform3d}</DisplayString>
+ <DisplayString Condition="type == Variant::PROJECTION">{_data._projection}</DisplayString>
<DisplayString Condition="type == Variant::STRING">{*(String *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::VECTOR2">{*(Vector2 *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::RECT2">{*(Rect2 *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::VECTOR3">{*(Vector3 *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::VECTOR4">{*(Vector4 *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::PLANE">{*(Plane *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::QUATERNION">{*(Quaternion *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::COLOR">{*(Color *)_data._mem}</DisplayString>
@@ -72,7 +74,7 @@
<Item Name="[value]" Condition="type == Variant::TRANSFORM2D">_data._transform2d</Item>
<Item Name="[value]" Condition="type == Variant::AABB">_data._aabb</Item>
<Item Name="[value]" Condition="type == Variant::BASIS">_data._basis</Item>
- <Item Name="[value]" Condition="type == Variant::TRANSFORM3D">_data._transform</Item>
+ <Item Name="[value]" Condition="type == Variant::TRANSFORM3D">_data._transform3d</Item>
<Item Name="[value]" Condition="type == Variant::STRING">*(String *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::VECTOR2">*(Vector2 *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::RECT2">*(Rect2 *)_data._mem</Item>
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/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 6f414c094c..ad4be950cc 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -48,6 +48,7 @@
#include <avrt.h>
#include <bcrypt.h>
#include <direct.h>
+#include <dwrite.h>
#include <knownfolders.h>
#include <process.h>
#include <regstr.h>
@@ -621,6 +622,135 @@ Error OS_Windows::set_cwd(const String &p_cwd) {
return OK;
}
+Vector<String> OS_Windows::get_system_fonts() const {
+ Vector<String> ret;
+ HashSet<String> font_names;
+
+ ComAutoreleaseRef<IDWriteFactory> dwrite_factory;
+ HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory.reference));
+ ERR_FAIL_COND_V(FAILED(hr) || dwrite_factory.is_null(), ret);
+
+ ComAutoreleaseRef<IDWriteFontCollection> font_collection;
+ hr = dwrite_factory->GetSystemFontCollection(&font_collection.reference, false);
+ ERR_FAIL_COND_V(FAILED(hr) || font_collection.is_null(), ret);
+
+ UINT32 family_count = font_collection->GetFontFamilyCount();
+ for (UINT32 i = 0; i < family_count; i++) {
+ ComAutoreleaseRef<IDWriteFontFamily> family;
+ hr = font_collection->GetFontFamily(i, &family.reference);
+ ERR_CONTINUE(FAILED(hr) || family.is_null());
+
+ ComAutoreleaseRef<IDWriteLocalizedStrings> family_names;
+ hr = family->GetFamilyNames(&family_names.reference);
+ ERR_CONTINUE(FAILED(hr) || family_names.is_null());
+
+ UINT32 index = 0;
+ BOOL exists = false;
+ UINT32 length = 0;
+ Char16String name;
+
+ hr = family_names->FindLocaleName(L"en-us", &index, &exists);
+ ERR_CONTINUE(FAILED(hr));
+
+ hr = family_names->GetStringLength(index, &length);
+ ERR_CONTINUE(FAILED(hr));
+
+ name.resize(length + 1);
+ hr = family_names->GetString(index, (WCHAR *)name.ptrw(), length + 1);
+ ERR_CONTINUE(FAILED(hr));
+
+ font_names.insert(String::utf16(name.ptr(), length));
+ }
+
+ for (const String &E : font_names) {
+ ret.push_back(E);
+ }
+ return ret;
+}
+
+String OS_Windows::get_system_font_path(const String &p_font_name, bool p_bold, bool p_italic) const {
+ String font_name = p_font_name;
+ if (font_name.to_lower() == "sans-serif") {
+ font_name = "Arial";
+ } else if (font_name.to_lower() == "serif") {
+ font_name = "Times New Roman";
+ } else if (font_name.to_lower() == "monospace") {
+ font_name = "Courier New";
+ } else if (font_name.to_lower() == "cursive") {
+ font_name = "Comic Sans MS";
+ } else if (font_name.to_lower() == "fantasy") {
+ font_name = "Gabriola";
+ }
+
+ ComAutoreleaseRef<IDWriteFactory> dwrite_factory;
+ HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory.reference));
+ ERR_FAIL_COND_V(FAILED(hr) || dwrite_factory.is_null(), String());
+
+ ComAutoreleaseRef<IDWriteFontCollection> font_collection;
+ hr = dwrite_factory->GetSystemFontCollection(&font_collection.reference, false);
+ ERR_FAIL_COND_V(FAILED(hr) || font_collection.is_null(), String());
+
+ UINT32 index = 0;
+ BOOL exists = false;
+ font_collection->FindFamilyName((const WCHAR *)font_name.utf16().get_data(), &index, &exists);
+ if (FAILED(hr)) {
+ return String();
+ }
+
+ ComAutoreleaseRef<IDWriteFontFamily> family;
+ hr = font_collection->GetFontFamily(index, &family.reference);
+ if (FAILED(hr) || family.is_null()) {
+ return String();
+ }
+
+ ComAutoreleaseRef<IDWriteFont> dwrite_font;
+ hr = family->GetFirstMatchingFont(p_bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, p_italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, &dwrite_font.reference);
+ if (FAILED(hr) || dwrite_font.is_null()) {
+ return String();
+ }
+
+ ComAutoreleaseRef<IDWriteFontFace> dwrite_face;
+ hr = dwrite_font->CreateFontFace(&dwrite_face.reference);
+ if (FAILED(hr) || dwrite_face.is_null()) {
+ return String();
+ }
+
+ UINT32 number_of_files = 0;
+ hr = dwrite_face->GetFiles(&number_of_files, nullptr);
+ if (FAILED(hr)) {
+ return String();
+ }
+ Vector<ComAutoreleaseRef<IDWriteFontFile>> files;
+ files.resize(number_of_files);
+ hr = dwrite_face->GetFiles(&number_of_files, (IDWriteFontFile **)files.ptrw());
+ if (FAILED(hr)) {
+ return String();
+ }
+
+ for (UINT32 i = 0; i < number_of_files; i++) {
+ void const *reference_key = nullptr;
+ UINT32 reference_key_size = 0;
+ ComAutoreleaseRef<IDWriteLocalFontFileLoader> loader;
+
+ hr = files.write[i]->GetLoader((IDWriteFontFileLoader **)&loader.reference);
+ if (FAILED(hr) || loader.is_null()) {
+ continue;
+ }
+ hr = files.write[i]->GetReferenceKey(&reference_key, &reference_key_size);
+ if (FAILED(hr)) {
+ continue;
+ }
+
+ WCHAR file_path[MAX_PATH];
+ hr = loader->GetFilePathFromKey(reference_key, reference_key_size, &file_path[0], MAX_PATH);
+ if (FAILED(hr)) {
+ continue;
+ }
+ return String::utf16((const char16_t *)&file_path[0]);
+ }
+ return String();
+}
+
String OS_Windows::get_executable_path() const {
WCHAR bufname[4096];
GetModuleFileNameW(nullptr, bufname, 4096);
@@ -951,9 +1081,9 @@ String OS_Windows::get_user_data_dir() const {
}
String OS_Windows::get_unique_id() const {
- HW_PROFILE_INFO HwProfInfo;
- ERR_FAIL_COND_V(!GetCurrentHwProfile(&HwProfInfo), "");
- return String::utf16((const char16_t *)(HwProfInfo.szHwProfileGuid), HW_PROFILE_GUIDLEN);
+ HW_PROFILE_INFOA HwProfInfo;
+ ERR_FAIL_COND_V(!GetCurrentHwProfileA(&HwProfInfo), "");
+ return String((HwProfInfo.szHwProfileGuid), HW_PROFILE_GUIDLEN);
}
bool OS_Windows::_check_internal_feature_support(const String &p_feature) {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index dc702c66e1..80fc860738 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -62,6 +62,26 @@
#define WINDOWS_DEBUG_OUTPUT_ENABLED
#endif
+template <class T>
+class ComAutoreleaseRef {
+public:
+ T *reference = nullptr;
+
+ _FORCE_INLINE_ T *operator->() { return reference; }
+ _FORCE_INLINE_ const T *operator->() const { return reference; }
+ _FORCE_INLINE_ T *operator*() { return reference; }
+ _FORCE_INLINE_ const T *operator*() const { return reference; }
+ _FORCE_INLINE_ bool is_valid() const { return reference != nullptr; }
+ _FORCE_INLINE_ bool is_null() const { return reference == nullptr; }
+ ComAutoreleaseRef() {}
+ ~ComAutoreleaseRef() {
+ if (reference != nullptr) {
+ reference->Release();
+ reference = nullptr;
+ }
+ }
+};
+
class JoypadWindows;
class OS_Windows : public OS {
#ifdef STDOUT_FILE
@@ -147,6 +167,9 @@ public:
virtual String get_environment(const String &p_var) const override;
virtual bool set_environment(const String &p_var, const String &p_value) const override;
+ virtual Vector<String> get_system_fonts() const override;
+ virtual String get_system_font_path(const String &p_font_name, bool p_bold = false, bool p_italic = false) const override;
+
virtual String get_executable_path() const override;
virtual String get_locale() const override;
@@ -185,4 +208,4 @@ public:
~OS_Windows();
};
-#endif
+#endif // OS_WINDOWS_H
diff --git a/platform/windows/vulkan_context_win.h b/platform/windows/vulkan_context_win.h
index e68f0125ca..d5950a129a 100644
--- a/platform/windows/vulkan_context_win.h
+++ b/platform/windows/vulkan_context_win.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VULKAN_DEVICE_WIN_H
-#define VULKAN_DEVICE_WIN_H
+#ifndef VULKAN_CONTEXT_WIN_H
+#define VULKAN_CONTEXT_WIN_H
#include "drivers/vulkan/vulkan_context.h"
@@ -46,4 +46,4 @@ public:
~VulkanContextWindows();
};
-#endif // VULKAN_DEVICE_WIN_H
+#endif // VULKAN_CONTEXT_WIN_H
diff --git a/platform/windows/windows_terminal_logger.h b/platform/windows/windows_terminal_logger.h
index 1045f12201..348a49c845 100644
--- a/platform/windows/windows_terminal_logger.h
+++ b/platform/windows/windows_terminal_logger.h
@@ -44,4 +44,4 @@ public:
#endif
-#endif
+#endif // WINDOWS_TERMINAL_LOGGER_H
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/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h
index 3a41f810dc..ec38795a1a 100644
--- a/scene/2d/animated_sprite_2d.h
+++ b/scene/2d/animated_sprite_2d.h
@@ -114,4 +114,4 @@ public:
AnimatedSprite2D();
};
-#endif // ANIMATED_SPRITE_H
+#endif // ANIMATED_SPRITE_2D_H
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index dfc1016c84..7890348314 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -184,8 +184,8 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
E->value.rc = 0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree), make_binds(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree), make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree).bind(objid));
if (E->value.in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
}
@@ -277,8 +277,8 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
E->value.rc = 0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree), make_binds(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree), make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree).bind(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree).bind(objid));
if (E->value.in_tree) {
emit_signal(SceneStringNames::get_singleton()->area_entered, node);
}
diff --git a/scene/2d/audio_listener_2d.h b/scene/2d/audio_listener_2d.h
index 172d388efc..5cd1bfb251 100644
--- a/scene/2d/audio_listener_2d.h
+++ b/scene/2d/audio_listener_2d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef LISTENER_2D_H
-#define LISTENER_2D_H
+#ifndef AUDIO_LISTENER_2D_H
+#define AUDIO_LISTENER_2D_H
#include "scene/2d/node_2d.h"
#include "scene/main/window.h"
@@ -56,4 +56,4 @@ public:
bool is_current() const;
};
-#endif
+#endif // AUDIO_LISTENER_2D_H
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index eaab58c4ae..94d22111ea 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -69,7 +69,7 @@ void AudioStreamPlayer2D::_notification(int p_what) {
if (setplay.get() >= 0 && stream.is_valid()) {
active.set();
- Ref<AudioStreamPlayback> new_playback = stream->instance_playback();
+ Ref<AudioStreamPlayback> new_playback = stream->instantiate_playback();
ERR_FAIL_COND_MSG(new_playback.is_null(), "Failed to instantiate playback.");
AudioServer::get_singleton()->start_playback_stream(new_playback, _get_actual_bus(), volume_vector, setplay.get(), pitch_scale);
stream_playbacks.push_back(new_playback);
diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h
index a22782fe44..d1c4dc4fdf 100644
--- a/scene/2d/audio_stream_player_2d.h
+++ b/scene/2d/audio_stream_player_2d.h
@@ -135,4 +135,4 @@ public:
~AudioStreamPlayer2D();
};
-#endif
+#endif // AUDIO_STREAM_PLAYER_2D_H
diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h
index 4e7cac1f3e..1f2d5810b0 100644
--- a/scene/2d/back_buffer_copy.h
+++ b/scene/2d/back_buffer_copy.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BACKBUFFERCOPY_H
-#define BACKBUFFERCOPY_H
+#ifndef BACK_BUFFER_COPY_H
+#define BACK_BUFFER_COPY_H
#include "scene/2d/node_2d.h"
@@ -71,4 +71,4 @@ public:
VARIANT_ENUM_CAST(BackBufferCopy::CopyMode);
-#endif // BACKBUFFERCOPY_H
+#endif // BACK_BUFFER_COPY_H
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 2616d1f09e..c43a796170 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -247,8 +247,8 @@ void Camera2D::_notification(int p_what) {
add_to_group(canvas_group_name);
_update_process_callback();
- _update_scroll();
first = true;
+ _update_scroll();
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -439,7 +439,9 @@ void Camera2D::clear_current() {
void Camera2D::set_limit(Side p_side, int p_limit) {
ERR_FAIL_INDEX((int)p_side, 4);
limit[p_side] = p_limit;
- update();
+ Point2 old_smoothed_camera_pos = smoothed_camera_pos;
+ _update_scroll();
+ smoothed_camera_pos = old_smoothed_camera_pos;
}
int Camera2D::get_limit(Side p_side) const {
diff --git a/scene/2d/canvas_group.h b/scene/2d/canvas_group.h
index 9bc1772ee2..557e7e23dc 100644
--- a/scene/2d/canvas_group.h
+++ b/scene/2d/canvas_group.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CANVASGROUP_H
-#define CANVASGROUP_H
+#ifndef CANVAS_GROUP_H
+#define CANVAS_GROUP_H
#include "scene/2d/node_2d.h"
@@ -56,4 +56,4 @@ public:
~CanvasGroup();
};
-#endif // CANVASGROUP_H
+#endif // CANVAS_GROUP_H
diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h
index ec37449f8f..1fd54898f8 100644
--- a/scene/2d/canvas_modulate.h
+++ b/scene/2d/canvas_modulate.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CANVASMODULATE_H
-#define CANVASMODULATE_H
+#ifndef CANVAS_MODULATE_H
+#define CANVAS_MODULATE_H
#include "scene/2d/node_2d.h"
@@ -52,4 +52,4 @@ public:
~CanvasModulate();
};
-#endif // CANVASMODULATE_H
+#endif // CANVAS_MODULATE_H
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index 913003c7e6..26204a3b1a 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 {
@@ -1466,7 +1470,7 @@ CPUParticles2D::CPUParticles2D() {
set_emitting(true);
set_amount(8);
- set_use_local_coordinates(true);
+ set_use_local_coordinates(false);
set_param_min(PARAM_INITIAL_LINEAR_VELOCITY, 0);
set_param_min(PARAM_ANGULAR_VELOCITY, 0);
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index 6edd75e62a..075421a26d 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."));
@@ -661,7 +660,7 @@ GPUParticles2D::GPUParticles2D() {
set_explosiveness_ratio(0);
set_randomness_ratio(0);
set_visibility_rect(Rect2(Vector2(-100, -100), Vector2(200, 200)));
- set_use_local_coordinates(true);
+ set_use_local_coordinates(false);
set_draw_order(DRAW_ORDER_LIFETIME);
set_speed_scale(1);
set_fixed_fps(30);
diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h
index 3c7f4cd9b5..a4231cc45d 100644
--- a/scene/2d/gpu_particles_2d.h
+++ b/scene/2d/gpu_particles_2d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PARTICLES_2D_H
-#define PARTICLES_2D_H
+#ifndef GPU_PARTICLES_2D_H
+#define GPU_PARTICLES_2D_H
#include "scene/2d/node_2d.h"
@@ -167,4 +167,4 @@ public:
VARIANT_ENUM_CAST(GPUParticles2D::DrawOrder)
VARIANT_ENUM_CAST(GPUParticles2D::EmitFlags)
-#endif // PARTICLES_2D_H
+#endif // GPU_PARTICLES_2D_H
diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h
index 4acfeaf781..b61e23464a 100644
--- a/scene/2d/light_occluder_2d.h
+++ b/scene/2d/light_occluder_2d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef LIGHTOCCLUDER2D_H
-#define LIGHTOCCLUDER2D_H
+#ifndef LIGHT_OCCLUDER_2D_H
+#define LIGHT_OCCLUDER_2D_H
#include "scene/2d/node_2d.h"
@@ -111,4 +111,4 @@ public:
~LightOccluder2D();
};
-#endif // LIGHTOCCLUDER2D_H
+#endif // LIGHT_OCCLUDER_2D_H
diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h
index 5322c5a5fe..27c510171a 100644
--- a/scene/2d/line_2d.h
+++ b/scene/2d/line_2d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef LINE2D_H
-#define LINE2D_H
+#ifndef LINE_2D_H
+#define LINE_2D_H
#include "node_2d.h"
@@ -138,4 +138,4 @@ private:
bool _antialiased = false;
};
-#endif // LINE2D_H
+#endif // LINE_2D_H
diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h
index 032a15cad2..76eba20058 100644
--- a/scene/2d/navigation_agent_2d.h
+++ b/scene/2d/navigation_agent_2d.h
@@ -163,4 +163,4 @@ private:
void _check_distance_to_target();
};
-#endif
+#endif // NAVIGATION_AGENT_2D_H
diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h
index 948cf5b61a..afda05956a 100644
--- a/scene/2d/navigation_obstacle_2d.h
+++ b/scene/2d/navigation_obstacle_2d.h
@@ -74,4 +74,4 @@ private:
real_t estimate_agent_radius() const;
};
-#endif
+#endif // NAVIGATION_OBSTACLE_2D_H
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 6e8fd891cb..cdf7c5afa9 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -35,6 +35,7 @@
#include "core/os/mutex.h"
#include "scene/resources/world_2d.h"
#include "servers/navigation_server_2d.h"
+#include "servers/navigation_server_3d.h"
#include "thirdparty/misc/polypartition.h"
@@ -371,9 +372,11 @@ void NavigationRegion2D::set_enabled(bool p_enabled) {
NavigationServer2D::get_singleton_mut()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
}
- if (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) {
+#ifdef DEBUG_ENABLED
+ if (Engine::get_singleton()->is_editor_hint() || NavigationServer3D::get_singleton()->get_debug_enabled()) {
update();
}
+#endif // DEBUG_ENABLED
}
bool NavigationRegion2D::is_enabled() const {
@@ -419,7 +422,7 @@ real_t NavigationRegion2D::get_enter_cost() const {
void NavigationRegion2D::set_travel_cost(real_t p_travel_cost) {
ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
travel_cost = MAX(p_travel_cost, 0.0);
- NavigationServer2D::get_singleton()->region_set_enter_cost(region, travel_cost);
+ NavigationServer2D::get_singleton()->region_set_travel_cost(region, travel_cost);
}
real_t NavigationRegion2D::get_travel_cost() const {
@@ -462,7 +465,8 @@ void NavigationRegion2D::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) {
+#ifdef DEBUG_ENABLED
+ if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer3D::get_singleton()->get_debug_enabled()) && navpoly.is_valid()) {
Vector<Vector2> verts = navpoly->get_vertices();
if (verts.size() < 3) {
return;
@@ -470,11 +474,11 @@ void NavigationRegion2D::_notification(int p_what) {
Color color;
if (enabled) {
- color = get_tree()->get_debug_navigation_color();
+ color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color();
} else {
- color = get_tree()->get_debug_navigation_disabled_color();
+ color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_disabled_color();
}
- Color doors_color = color.lightened(0.2);
+ Color doors_color = NavigationServer3D::get_singleton()->get_debug_navigation_edge_connection_color();
RandomPCG rand;
@@ -516,6 +520,7 @@ void NavigationRegion2D::_notification(int p_what) {
draw_arc(b, radius, angle - Math_PI / 2.0, angle + Math_PI / 2.0, 10, doors_color);
}
}
+#endif // DEBUG_ENABLED
} break;
}
}
@@ -552,10 +557,13 @@ void NavigationRegion2D::_navpoly_changed() {
NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly);
}
}
+
void NavigationRegion2D::_map_changed(RID p_map) {
- if (enabled && get_world_2d()->get_navigation_map() == p_map) {
+#ifdef DEBUG_ENABLED
+ if (is_inside_tree() && get_world_2d()->get_navigation_map() == p_map) {
update();
}
+#endif // DEBUG_ENABLED
}
TypedArray<String> NavigationRegion2D::get_configuration_warnings() const {
@@ -605,8 +613,18 @@ NavigationRegion2D::NavigationRegion2D() {
region = NavigationServer2D::get_singleton()->region_create();
NavigationServer2D::get_singleton()->region_set_enter_cost(region, get_enter_cost());
NavigationServer2D::get_singleton()->region_set_travel_cost(region, get_travel_cost());
+
+#ifdef DEBUG_ENABLED
+ NavigationServer3D::get_singleton_mut()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
+ NavigationServer3D::get_singleton_mut()->connect("navigation_debug_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
+#endif // DEBUG_ENABLED
}
NavigationRegion2D::~NavigationRegion2D() {
NavigationServer2D::get_singleton()->free(region);
+
+#ifdef DEBUG_ENABLED
+ NavigationServer3D::get_singleton_mut()->disconnect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
+ NavigationServer3D::get_singleton_mut()->disconnect("navigation_debug_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
+#endif // DEBUG_ENABLED
}
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 473c34768f..0d8a31e6bb 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NODE2D_H
-#define NODE2D_H
+#ifndef NODE_2D_H
+#define NODE_2D_H
#include "scene/main/canvas_item.h"
@@ -124,4 +124,4 @@ public:
Node2D() {}
};
-#endif // NODE2D_H
+#endif // NODE_2D_H
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index 8eb48ffb30..9862c4bfb1 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -304,6 +304,7 @@ void PathFollow2D::_bind_methods() {
}
void PathFollow2D::set_offset(real_t p_offset) {
+ ERR_FAIL_COND(!isfinite(p_offset));
offset = p_offset;
if (path) {
if (path->get_curve().is_valid()) {
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index e60a5ed034..ce22f32b01 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -387,8 +387,8 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p
//E->value.rc=0;
E->value.in_scene = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree), make_binds(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree), make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree).bind(objid));
if (E->value.in_scene) {
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
}
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index 8953813452..68e5ffdcf9 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -240,7 +240,7 @@ void RayCast2D::_draw_debug_shape() {
Transform2D xf;
xf.rotate(target_position.angle());
- xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
+ xf.translate_local(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
Vector<Vector2> pts = {
xf.xform(Vector2(arrow_size, 0)),
diff --git a/scene/2d/shape_cast_2d.cpp b/scene/2d/shape_cast_2d.cpp
index ae810156a2..316988d298 100644
--- a/scene/2d/shape_cast_2d.cpp
+++ b/scene/2d/shape_cast_2d.cpp
@@ -217,7 +217,7 @@ void ShapeCast2D::_notification(int p_what) {
if (shape.is_null()) {
break;
}
- Color draw_col = get_tree()->get_debug_collisions_color();
+ Color draw_col = collided ? Color(1.0, 0.01, 0) : get_tree()->get_debug_collisions_color();
if (!enabled) {
float g = draw_col.get_v();
draw_col.r = g;
@@ -235,18 +235,25 @@ void ShapeCast2D::_notification(int p_what) {
// Draw an arrow indicating where the ShapeCast is pointing to.
if (target_position != Vector2()) {
- Transform2D xf;
- xf.rotate(target_position.angle());
- xf.translate(Vector2(target_position.length(), 0));
+ const real_t max_arrow_size = 6;
+ const real_t line_width = 1.4;
+ bool no_line = target_position.length() < line_width;
+ real_t arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size);
- draw_line(Vector2(), target_position, draw_col, 2);
+ if (no_line) {
+ arrow_size = target_position.length();
+ } else {
+ draw_line(Vector2(), target_position - target_position.normalized() * arrow_size, draw_col, line_width);
+ }
- float tsize = 8;
+ Transform2D xf;
+ xf.rotate(target_position.angle());
+ xf.translate_local(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
Vector<Vector2> pts = {
- xf.xform(Vector2(tsize, 0)),
- xf.xform(Vector2(0, Math_SQRT12 * tsize)),
- xf.xform(Vector2(0, -Math_SQRT12 * tsize))
+ xf.xform(Vector2(arrow_size, 0)),
+ xf.xform(Vector2(0, 0.5 * arrow_size)),
+ xf.xform(Vector2(0, -0.5 * arrow_size))
};
Vector<Color> cols = { draw_col, draw_col, draw_col };
@@ -291,6 +298,8 @@ void ShapeCast2D::_update_shapecast_state() {
collision_safe_fraction = 0.0;
collision_unsafe_fraction = 0.0;
+ bool prev_collision_state = collided;
+
if (target_position != Vector2()) {
dss->cast_motion(params, collision_safe_fraction, collision_unsafe_fraction);
if (collision_unsafe_fraction < 1.0) {
@@ -314,6 +323,10 @@ void ShapeCast2D::_update_shapecast_state() {
}
}
collided = !result.is_empty();
+
+ if (prev_collision_state != collided) {
+ update();
+ }
}
void ShapeCast2D::force_shapecast_update() {
diff --git a/scene/2d/shape_cast_2d.h b/scene/2d/shape_cast_2d.h
index 7ff080aed0..660e52f189 100644
--- a/scene/2d/shape_cast_2d.h
+++ b/scene/2d/shape_cast_2d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHAPE_CAST_2D
-#define SHAPE_CAST_2D
+#ifndef SHAPE_CAST_2D_H
+#define SHAPE_CAST_2D_H
#include "scene/2d/node_2d.h"
#include "scene/resources/shape_2d.h"
@@ -120,4 +120,4 @@ public:
TypedArray<String> get_configuration_warnings() const override;
};
-#endif
+#endif // SHAPE_CAST_2D_H
diff --git a/scene/2d/sprite_2d.h b/scene/2d/sprite_2d.h
index 6893e92d4a..5b33bb6802 100644
--- a/scene/2d/sprite_2d.h
+++ b/scene/2d/sprite_2d.h
@@ -125,4 +125,4 @@ public:
~Sprite2D();
};
-#endif // SPRITE_H
+#endif // SPRITE_2D_H
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 9c4b0feea2..5ba8c95a06 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()));
@@ -2651,7 +2652,7 @@ void TileMap::clear_layer(int p_layer) {
// Remove all tiles.
_clear_layer_internals(p_layer);
layers[p_layer].tile_map.clear();
-
+ _recreate_layer_internals(p_layer);
used_rect_cache_dirty = true;
}
@@ -2661,6 +2662,7 @@ void TileMap::clear() {
for (unsigned int i = 0; i < layers.size(); i++) {
layers[i].tile_map.clear();
}
+ _recreate_internals();
used_rect_cache_dirty = true;
}
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 0ac94b9d45..012bf01df9 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -130,7 +130,7 @@ public:
}
String to_string() const {
- return vformat("Constraint {pos:%s, bit:%d, terrain:%d, priotity:%d}", base_cell_coords, bit, terrain, priority);
+ return vformat("Constraint {pos:%s, bit:%d, terrain:%d, priority:%d}", base_cell_coords, bit, terrain, priority);
}
Vector2i get_base_cell_coords() const {
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index 4a4a2a1da0..9dea69cd64 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -131,7 +131,7 @@ void TouchScreenButton::_notification(int p_what) {
pos = texture_normal->get_size() * 0.5;
}
- draw_set_transform_matrix(get_canvas_transform().translated(pos));
+ draw_set_transform_matrix(get_canvas_transform().translated_local(pos));
shape->draw(get_canvas_item(), draw_col);
}
} break;
@@ -258,7 +258,7 @@ bool TouchScreenButton::_is_point_inside(const Point2 &p_point) {
pos = texture_normal->get_size() * 0.5;
}
- touched = shape->collide(Transform2D().translated(pos), unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5)));
+ touched = shape->collide(Transform2D().translated_local(pos), unit_rect, Transform2D(0, coord + Vector2(0.5, 0.5)));
}
if (bitmask.is_valid()) {
diff --git a/scene/2d/visible_on_screen_notifier_2d.h b/scene/2d/visible_on_screen_notifier_2d.h
index 38b508e2f6..ac7fad95a5 100644
--- a/scene/2d/visible_on_screen_notifier_2d.h
+++ b/scene/2d/visible_on_screen_notifier_2d.h
@@ -102,4 +102,4 @@ public:
VARIANT_ENUM_CAST(VisibleOnScreenEnabler2D::EnableMode);
-#endif // VISIBILITY_NOTIFIER_2D_H
+#endif // VISIBLE_ON_SCREEN_NOTIFIER_2D_H
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index fb0c59daa1..e9e19488e9 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -239,8 +239,8 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
E->value.rc = 0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree), make_binds(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree), make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree).bind(objid));
if (E->value.in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
}
@@ -426,8 +426,8 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
E->value.rc = 0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree), make_binds(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree), make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree).bind(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree).bind(objid));
if (E->value.in_tree) {
emit_signal(SceneStringNames::get_singleton()->area_entered, node);
}
diff --git a/scene/3d/audio_listener_3d.h b/scene/3d/audio_listener_3d.h
index ebc37673ed..44c49f526e 100644
--- a/scene/3d/audio_listener_3d.h
+++ b/scene/3d/audio_listener_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef LISTENER_3D_H
-#define LISTENER_3D_H
+#ifndef AUDIO_LISTENER_3D_H
+#define AUDIO_LISTENER_3D_H
#include "scene/3d/node_3d.h"
@@ -67,4 +67,4 @@ public:
~AudioListener3D();
};
-#endif
+#endif // AUDIO_LISTENER_3D_H
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 824ea0407e..65b00742ee 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -281,7 +281,7 @@ void AudioStreamPlayer3D::_notification(int p_what) {
if (setplay.get() >= 0 && stream.is_valid()) {
active.set();
- Ref<AudioStreamPlayback> new_playback = stream->instance_playback();
+ Ref<AudioStreamPlayback> new_playback = stream->instantiate_playback();
ERR_FAIL_COND_MSG(new_playback.is_null(), "Failed to instantiate playback.");
HashMap<StringName, Vector<AudioFrame>> bus_map;
bus_map[_get_actual_bus()] = volume_vector;
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
index 85ece6d8d5..647b18a4a7 100644
--- a/scene/3d/audio_stream_player_3d.h
+++ b/scene/3d/audio_stream_player_3d.h
@@ -196,4 +196,5 @@ public:
VARIANT_ENUM_CAST(AudioStreamPlayer3D::AttenuationModel)
VARIANT_ENUM_CAST(AudioStreamPlayer3D::DopplerTracking)
+
#endif // AUDIO_STREAM_PLAYER_3D_H
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..3224361a25 100644
--- a/scene/3d/bone_attachment_3d.h
+++ b/scene/3d/bone_attachment_3d.h
@@ -28,10 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BONE_ATTACHMENT_H
-#define BONE_ATTACHMENT_H
+#ifndef BONE_ATTACHMENT_3D_H
+#define BONE_ATTACHMENT_3D_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;
@@ -93,4 +99,4 @@ public:
BoneAttachment3D();
};
-#endif // BONE_ATTACHMENT_H
+#endif // BONE_ATTACHMENT_3D_H
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 10348b1eb6..f654373ee5 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -31,7 +31,7 @@
#include "camera_3d.h"
#include "collision_object_3d.h"
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "scene/main/viewport.h"
void Camera3D::_update_audio_listener_state() {
@@ -197,7 +197,7 @@ void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, rea
update_gizmos();
}
-void Camera3D::set_projection(Camera3D::Projection p_mode) {
+void Camera3D::set_projection(ProjectionType p_mode) {
if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM) {
mode = p_mode;
_update_camera_mode();
@@ -265,7 +265,7 @@ Vector3 Camera3D::project_local_ray_normal(const Point2 &p_pos) const {
if (mode == PROJECTION_ORTHOGONAL) {
ray = Vector3(0, 0, -1);
} else {
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
Vector2 screen_he = cm.get_viewport_half_extents();
ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -near).normalized();
@@ -314,7 +314,7 @@ Vector<Vector3> Camera3D::get_near_plane_points() const {
Size2 viewport_size = get_viewport()->get_visible_rect().size;
- CameraMatrix cm;
+ Projection cm;
if (mode == PROJECTION_ORTHOGONAL) {
cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
@@ -340,7 +340,7 @@ Point2 Camera3D::unproject_position(const Vector3 &p_pos) const {
Size2 viewport_size = get_viewport()->get_visible_rect().size;
- CameraMatrix cm;
+ Projection cm;
if (mode == PROJECTION_ORTHOGONAL) {
cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
@@ -368,7 +368,7 @@ Vector3 Camera3D::project_position(const Point2 &p_point, real_t p_z_depth) cons
}
Size2 viewport_size = get_viewport()->get_visible_rect().size;
- CameraMatrix cm;
+ Projection cm;
if (mode == PROJECTION_ORTHOGONAL) {
cm.set_orthogonal(size, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH);
@@ -507,7 +507,7 @@ void Camera3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1,degrees"), "set_fov", "get_fov");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,16384,0.01,suffix:m"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,16384,0.001,suffix:m"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_frustum_offset", "get_frustum_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp,suffix:m"), "set_near", "get_near");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp,suffix:m"), "set_far", "get_far");
@@ -544,7 +544,7 @@ real_t Camera3D::get_far() const {
return far;
}
-Camera3D::Projection Camera3D::get_projection() const {
+Camera3D::ProjectionType Camera3D::get_projection() const {
return mode;
}
@@ -607,7 +607,7 @@ Vector<Plane> Camera3D::get_frustum() const {
ERR_FAIL_COND_V(!is_inside_world(), Vector<Plane>());
Size2 viewport_size = get_viewport()->get_visible_rect().size;
- CameraMatrix cm;
+ Projection cm;
if (mode == PROJECTION_PERSPECTIVE) {
cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
} else {
diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h
index 9f2f8ceed1..cedd976890 100644
--- a/scene/3d/camera_3d.h
+++ b/scene/3d/camera_3d.h
@@ -40,7 +40,7 @@ class Camera3D : public Node3D {
GDCLASS(Camera3D, Node3D);
public:
- enum Projection {
+ enum ProjectionType {
PROJECTION_PERSPECTIVE,
PROJECTION_ORTHOGONAL,
PROJECTION_FRUSTUM
@@ -62,7 +62,7 @@ private:
bool current = false;
Viewport *viewport = nullptr;
- Projection mode = PROJECTION_PERSPECTIVE;
+ ProjectionType mode = PROJECTION_PERSPECTIVE;
real_t fov = 0.0;
real_t size = 1.0;
@@ -112,7 +112,7 @@ public:
void set_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far);
void set_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far);
void set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, real_t p_z_far);
- void set_projection(Camera3D::Projection p_mode);
+ void set_projection(Camera3D::ProjectionType p_mode);
void make_current();
void clear_current(bool p_enable_next = true);
@@ -127,7 +127,7 @@ public:
real_t get_near() const;
Vector2 get_frustum_offset() const;
- Projection get_projection() const;
+ ProjectionType get_projection() const;
void set_fov(real_t p_fov);
void set_size(real_t p_size);
@@ -181,8 +181,8 @@ public:
~Camera3D();
};
-VARIANT_ENUM_CAST(Camera3D::Projection);
+VARIANT_ENUM_CAST(Camera3D::ProjectionType);
VARIANT_ENUM_CAST(Camera3D::KeepAspect);
VARIANT_ENUM_CAST(Camera3D::DopplerTracking);
-#endif
+#endif // CAMERA_3D_H
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index a36357555a..9a5d4f5480 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -319,7 +319,7 @@ bool CollisionObject3D::_are_collision_shapes_visible() {
void CollisionObject3D::_update_shape_data(uint32_t p_owner) {
if (_are_collision_shapes_visible()) {
if (debug_shapes_to_update.is_empty()) {
- callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferred({}, 0);
+ callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferredp({}, 0);
}
debug_shapes_to_update.insert(p_owner);
}
@@ -365,8 +365,7 @@ void CollisionObject3D::_update_debug_shapes() {
RS::get_singleton()->instance_set_scenario(s.debug_shape, get_world_3d()->get_scenario());
if (!s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_shape_changed))) {
- s.shape->connect("changed", callable_mp(this, &CollisionObject3D::_shape_changed),
- varray(s.shape), CONNECT_DEFERRED);
+ s.shape->connect("changed", callable_mp(this, &CollisionObject3D::_shape_changed).bind(s.shape), CONNECT_DEFERRED);
}
++debug_shapes_count;
@@ -404,6 +403,9 @@ void CollisionObject3D::_on_transform_changed() {
debug_shape_old_transform = get_global_transform();
for (KeyValue<uint32_t, ShapeData> &E : shapes) {
ShapeData &shapedata = E.value;
+ if (shapedata.disabled) {
+ continue; // If disabled then there are no debug shapes to update.
+ }
const ShapeData::ShapeBase *shapes = shapedata.shapes.ptr();
for (int i = 0; i < shapedata.shapes.size(); i++) {
RS::get_singleton()->instance_set_transform(shapes[i].debug_shape, debug_shape_old_transform * shapedata.xform);
diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h
index 098f573551..3ec3aa0fc1 100644
--- a/scene/3d/collision_object_3d.h
+++ b/scene/3d/collision_object_3d.h
@@ -166,4 +166,4 @@ public:
VARIANT_ENUM_CAST(CollisionObject3D::DisableMode);
-#endif // COLLISION_OBJECT__H
+#endif // COLLISION_OBJECT_3D_H
diff --git a/scene/3d/collision_polygon_3d.h b/scene/3d/collision_polygon_3d.h
index a24d485af2..74e5867a2f 100644
--- a/scene/3d/collision_polygon_3d.h
+++ b/scene/3d/collision_polygon_3d.h
@@ -79,4 +79,4 @@ public:
CollisionPolygon3D();
};
-#endif // COLLISION_POLYGON_H
+#endif // COLLISION_POLYGON_3D_H
diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h
index 5c32230942..124c0d166d 100644
--- a/scene/3d/collision_shape_3d.h
+++ b/scene/3d/collision_shape_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COLLISION_SHAPE_H
-#define COLLISION_SHAPE_H
+#ifndef COLLISION_SHAPE_3D_H
+#define COLLISION_SHAPE_3D_H
#include "scene/3d/node_3d.h"
#include "scene/resources/shape_3d.h"
@@ -68,4 +68,4 @@ public:
~CollisionShape3D();
};
-#endif // BODY_VOLUME_H
+#endif // COLLISION_SHAPE_3D_H
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/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h
index 7f225ee98d..e26c301038 100644
--- a/scene/3d/cpu_particles_3d.h
+++ b/scene/3d/cpu_particles_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CPU_PARTICLES_H
-#define CPU_PARTICLES_H
+#ifndef CPU_PARTICLES_3D_H
+#define CPU_PARTICLES_3D_H
#include "scene/3d/visual_instance_3d.h"
@@ -138,7 +138,7 @@ private:
real_t randomness_ratio = 0.0;
double lifetime_randomness = 0.0;
double speed_scale = 1.0;
- bool local_coords = true;
+ bool local_coords = false;
int fixed_fps = 0;
bool fractional_delta = true;
@@ -317,4 +317,4 @@ VARIANT_ENUM_CAST(CPUParticles3D::Parameter)
VARIANT_ENUM_CAST(CPUParticles3D::ParticleFlags)
VARIANT_ENUM_CAST(CPUParticles3D::EmissionShape)
-#endif // CPU_PARTICLES_H
+#endif // CPU_PARTICLES_3D_H
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index ab07f33ace..0112f24e0c 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);
}
@@ -215,11 +215,13 @@ void Decal::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cull_mask"), &Decal::get_cull_mask);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,suffix:m"), "set_extents", "get_extents");
+
ADD_GROUP("Textures", "texture_");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_NORMAL);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_orm", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ORM);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_emission", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION);
+
ADD_GROUP("Parameters", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_emission_energy", "get_emission_energy");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
@@ -227,13 +229,16 @@ void Decal::_bind_methods() {
// A Normal Fade of 1.0 causes the decal to be invisible even if fully perpendicular to a surface.
// Due to this, limit Normal Fade to 0.999.
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,0.999,0.001"), "set_normal_fade", "get_normal_fade");
+
ADD_GROUP("Vertical Fade", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "upper_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_upper_fade", "get_upper_fade");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lower_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_lower_fade", "get_lower_fade");
+
ADD_GROUP("Distance Fade", "distance_fade_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin", PROPERTY_HINT_NONE, "suffix:m"), "set_distance_fade_begin", "get_distance_fade_begin");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length", PROPERTY_HINT_NONE, "suffix:m"), "set_distance_fade_length", "get_distance_fade_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_begin", "get_distance_fade_begin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_length", "get_distance_fade_length");
+
ADD_GROUP("Cull Mask", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
diff --git a/scene/3d/decal.h b/scene/3d/decal.h
index d5990272c6..38da4c14e3 100644
--- a/scene/3d/decal.h
+++ b/scene/3d/decal.h
@@ -57,8 +57,8 @@ private:
real_t upper_fade = 0.3;
real_t lower_fade = 0.3;
bool distance_fade_enabled = false;
- real_t distance_fade_begin = 10.0;
- real_t distance_fade_length = 1.0;
+ real_t distance_fade_begin = 40.0;
+ real_t distance_fade_length = 10.0;
protected:
static void _bind_methods();
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index d18c452ca7..2ee126e161 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -222,7 +222,7 @@ void GPUParticles3D::set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh) {
draw_passes.write[p_pass] = p_mesh;
if (Engine::get_singleton()->is_editor_hint() && draw_passes.write[p_pass].is_valid()) {
- draw_passes.write[p_pass]->connect("changed", callable_mp((Node *)this, &Node::update_configuration_warnings), varray(), CONNECT_DEFERRED);
+ draw_passes.write[p_pass]->connect("changed", callable_mp((Node *)this, &Node::update_configuration_warnings), CONNECT_DEFERRED);
}
RID mesh_rid;
@@ -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."));
@@ -631,7 +631,7 @@ GPUParticles3D::GPUParticles3D() {
set_randomness_ratio(0);
set_trail_length(0.3);
set_visibility_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)));
- set_use_local_coordinates(true);
+ set_use_local_coordinates(false);
set_draw_passes(1);
set_draw_order(DRAW_ORDER_INDEX);
set_speed_scale(1);
diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h
index adce45a0a9..0c745dd734 100644
--- a/scene/3d/gpu_particles_3d.h
+++ b/scene/3d/gpu_particles_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PARTICLES_H
-#define PARTICLES_H
+#ifndef GPU_PARTICLES_3D_H
+#define GPU_PARTICLES_3D_H
#include "scene/3d/visual_instance_3d.h"
#include "scene/resources/skin.h"
@@ -179,4 +179,4 @@ VARIANT_ENUM_CAST(GPUParticles3D::DrawOrder)
VARIANT_ENUM_CAST(GPUParticles3D::TransformAlign)
VARIANT_ENUM_CAST(GPUParticles3D::EmitFlags)
-#endif // PARTICLES_H
+#endif // GPU_PARTICLES_3D_H
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
index da0789ccd5..1cfd889272 100644
--- a/scene/3d/gpu_particles_collision_3d.cpp
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -30,6 +30,7 @@
#include "gpu_particles_collision_3d.h"
+#include "core/object/worker_thread_pool.h"
#include "mesh_instance_3d.h"
#include "scene/3d/camera_3d.h"
#include "scene/main/viewport.h"
@@ -126,6 +127,10 @@ GPUParticlesCollisionBox3D::~GPUParticlesCollisionBox3D() {
void GPUParticlesCollisionSDF3D::_find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes) {
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
if (mi && mi->is_visible_in_tree()) {
+ if ((mi->get_layer_mask() & bake_mask) == 0) {
+ return;
+ }
+
Ref<Mesh> mesh = mi->get_mesh();
if (mesh.is_valid()) {
AABB aabb = mesh->get_aabb();
@@ -339,15 +344,12 @@ void GPUParticlesCollisionSDF3D::_compute_sdf_z(uint32_t p_z, ComputeSDFParams *
}
void GPUParticlesCollisionSDF3D::_compute_sdf(ComputeSDFParams *params) {
- ThreadWorkPool work_pool;
- work_pool.init();
- work_pool.begin_work(params->size.z, this, &GPUParticlesCollisionSDF3D::_compute_sdf_z, params);
- while (!work_pool.is_done_dispatching()) {
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GPUParticlesCollisionSDF3D::_compute_sdf_z, params, params->size.z);
+ while (!WorkerThreadPool::get_singleton()->is_group_task_completed(group_task)) {
OS::get_singleton()->delay_usec(10000);
- bake_step_function(work_pool.get_work_index() * 100 / params->size.z, "Baking SDF");
+ bake_step_function(WorkerThreadPool::get_singleton()->get_group_processed_element_count(group_task) * 100 / params->size.z, "Baking SDF");
}
- work_pool.end_work();
- work_pool.finish();
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
}
Vector3i GPUParticlesCollisionSDF3D::get_estimated_cell_size() const {
@@ -447,7 +449,7 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() {
//compute bvh
- ERR_FAIL_COND_V(faces.size() <= 1, Ref<Image>());
+ ERR_FAIL_COND_V_MSG(faces.size() <= 1, Ref<Image>(), "No faces detected during GPUParticlesCollisionSDF3D bake. Check whether there are visible meshes matching the bake mask within its extents.");
LocalVector<FacePos> face_pos;
@@ -501,6 +503,16 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() {
return ret;
}
+TypedArray<String> GPUParticlesCollisionSDF3D::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (bake_mask == 0) {
+ warnings.push_back(RTR("The Bake Mask has no bits enabled, which means baking will not produce any collision for this GPUParticlesCollisionSDF3D.\nTo resolve this, enable at least one bit in the Bake Mask property."));
+ }
+
+ return warnings;
+}
+
void GPUParticlesCollisionSDF3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionSDF3D::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionSDF3D::get_extents);
@@ -514,9 +526,15 @@ void GPUParticlesCollisionSDF3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &GPUParticlesCollisionSDF3D::set_thickness);
ClassDB::bind_method(D_METHOD("get_thickness"), &GPUParticlesCollisionSDF3D::get_thickness);
+ ClassDB::bind_method(D_METHOD("set_bake_mask", "mask"), &GPUParticlesCollisionSDF3D::set_bake_mask);
+ ClassDB::bind_method(D_METHOD("get_bake_mask"), &GPUParticlesCollisionSDF3D::get_bake_mask);
+ ClassDB::bind_method(D_METHOD("set_bake_mask_value", "layer_number", "value"), &GPUParticlesCollisionSDF3D::set_bake_mask_value);
+ ClassDB::bind_method(D_METHOD("get_bake_mask_value", "layer_number"), &GPUParticlesCollisionSDF3D::get_bake_mask_value);
+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "16,32,64,128,256,512,suffix:px"), "set_resolution", "get_resolution");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "thickness", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,suffix:m"), "set_thickness", "get_thickness");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_bake_mask", "get_bake_mask");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture");
BIND_ENUM_CONSTANT(RESOLUTION_16);
@@ -555,6 +573,31 @@ GPUParticlesCollisionSDF3D::Resolution GPUParticlesCollisionSDF3D::get_resolutio
return resolution;
}
+void GPUParticlesCollisionSDF3D::set_bake_mask(uint32_t p_mask) {
+ bake_mask = p_mask;
+ update_configuration_warnings();
+}
+
+uint32_t GPUParticlesCollisionSDF3D::get_bake_mask() const {
+ return bake_mask;
+}
+
+void GPUParticlesCollisionSDF3D::set_bake_mask_value(int p_layer_number, bool p_value) {
+ ERR_FAIL_COND_MSG(p_layer_number < 1 || p_layer_number > 20, vformat("The render layer number (%d) must be between 1 and 20 (inclusive).", p_layer_number));
+ uint32_t mask = get_bake_mask();
+ if (p_value) {
+ mask |= 1 << (p_layer_number - 1);
+ } else {
+ mask &= ~(1 << (p_layer_number - 1));
+ }
+ set_bake_mask(mask);
+}
+
+bool GPUParticlesCollisionSDF3D::get_bake_mask_value(int p_layer_number) const {
+ ERR_FAIL_COND_V_MSG(p_layer_number < 1 || p_layer_number > 20, false, vformat("The render layer number (%d) must be between 1 and 20 (inclusive).", p_layer_number));
+ return bake_mask & (1 << (p_layer_number - 1));
+}
+
void GPUParticlesCollisionSDF3D::set_texture(const Ref<Texture3D> &p_texture) {
texture = p_texture;
RID tex = texture.is_valid() ? texture->get_rid() : RID();
diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h
index 4b2cb930fa..712bd015ff 100644
--- a/scene/3d/gpu_particles_collision_3d.h
+++ b/scene/3d/gpu_particles_collision_3d.h
@@ -110,6 +110,7 @@ public:
private:
Vector3 extents = Vector3(1, 1, 1);
Resolution resolution = RESOLUTION_64;
+ uint32_t bake_mask = 0xFFFFFFFF;
Ref<Texture3D> texture;
float thickness = 1.0;
@@ -161,6 +162,8 @@ protected:
static void _bind_methods();
public:
+ virtual TypedArray<String> get_configuration_warnings() const override;
+
void set_thickness(float p_thickness);
float get_thickness() const;
@@ -170,6 +173,12 @@ public:
void set_resolution(Resolution p_resolution);
Resolution get_resolution() const;
+ void set_bake_mask(uint32_t p_mask);
+ uint32_t get_bake_mask() const;
+
+ void set_bake_mask_value(int p_layer_number, bool p_enable);
+ bool get_bake_mask_value(int p_layer_number) const;
+
void set_texture(const Ref<Texture3D> &p_texture);
Ref<Texture3D> get_texture() const;
diff --git a/scene/3d/importer_mesh_instance_3d.h b/scene/3d/importer_mesh_instance_3d.h
index 3daf06771d..223b6fc80a 100644
--- a/scene/3d/importer_mesh_instance_3d.h
+++ b/scene/3d/importer_mesh_instance_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SCENE_IMPORTER_MESH_INSTANCE_3D_H
-#define SCENE_IMPORTER_MESH_INSTANCE_3D_H
+#ifndef IMPORTER_MESH_INSTANCE_3D_H
+#define IMPORTER_MESH_INSTANCE_3D_H
#include "scene/3d/node_3d.h"
#include "scene/resources/immediate_mesh.h"
@@ -61,4 +61,5 @@ public:
void set_skeleton_path(const NodePath &p_path);
NodePath get_skeleton_path() const;
};
-#endif
+
+#endif // IMPORTER_MESH_INSTANCE_3D_H
diff --git a/scene/3d/joint_3d.cpp b/scene/3d/joint_3d.cpp
index 0b824ef28b..b0509475a7 100644
--- a/scene/3d/joint_3d.cpp
+++ b/scene/3d/joint_3d.cpp
@@ -737,7 +737,8 @@ void Generic6DOFJoint3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flag_z", "flag", "value"), &Generic6DOFJoint3D::set_flag_z);
ClassDB::bind_method(D_METHOD("get_flag_z", "flag"), &Generic6DOFJoint3D::get_flag_z);
- // X
+ ADD_GROUP("Linear Limit", "linear_limit_");
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_x", "get_param_x", PARAM_LINEAR_UPPER_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_x", "get_param_x", PARAM_LINEAR_LOWER_LIMIT);
@@ -745,15 +746,53 @@ void Generic6DOFJoint3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING);
+
+ ADD_GROUP("Linear Motor", "linear_motor_");
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
+
+ ADD_GROUP("Linear Spring", "linear_spring_");
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_SPRING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_STIFFNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/damping"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
+
+ ADD_GROUP("Angular Limit", "angular_limit_");
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_x", "_get_angular_hi_limit_x");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_x", "_get_angular_lo_limit_x");
@@ -763,68 +802,15 @@ void Generic6DOFJoint3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/erp"), "set_param_x", "get_param_x", PARAM_ANGULAR_ERP);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
-
- // Y
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
-
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y");
-
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_LIMIT_SOFTNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/erp"), "set_param_y", "get_param_y", PARAM_ANGULAR_ERP);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
-
- // Z
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/upper_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/lower_distance", PROPERTY_HINT_NONE, "suffix:m"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/target_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
-
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z");
@@ -834,10 +820,32 @@ void Generic6DOFJoint3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/erp"), "set_param_z", "get_param_z", PARAM_ANGULAR_ERP);
+ ADD_GROUP("Angular Motor", "angular_motor_");
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_MOTOR);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+ ADD_GROUP("Angular Spring", "angular_spring_");
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT);
+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_SPRING);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_STIFFNESS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/damping"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_DAMPING);
diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp
index 0849b2c631..712a37e745 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);
@@ -130,7 +126,7 @@ void Label3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_draw_flag", "get_draw_flag", FLAG_DISABLE_DEPTH_TEST);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_draw_flag", "get_draw_flag", FLAG_FIXED_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode", "get_alpha_cut_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_priority", PROPERTY_HINT_RANGE, itos(RS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(RS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_render_priority", "get_render_priority");
ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_render_priority", PROPERTY_HINT_RANGE, itos(RS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(RS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_outline_render_priority", "get_outline_render_priority");
@@ -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;
@@ -507,10 +452,10 @@ void Label3D::_shape() {
}
lines_rid.clear();
- uint16_t autowrap_flags = TextServer::BREAK_MANDATORY;
+ BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY;
switch (autowrap_mode) {
case TextServer::AUTOWRAP_WORD_SMART:
- autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY;
+ autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY;
break;
case TextServer::AUTOWRAP_WORD:
autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
@@ -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/light_3d.cpp b/scene/3d/light_3d.cpp
index 6c999d85e2..53c072c318 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -224,7 +224,7 @@ bool Light3D::is_editor_only() const {
}
void Light3D::_validate_property(PropertyInfo &property) const {
- if (!shadow && (property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_blur" || property.name == "distance_fade_shadow")) {
+ if (!shadow && (property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_opacity" || property.name == "shadow_blur" || property.name == "distance_fade_shadow")) {
property.usage = PROPERTY_USAGE_NO_EDITOR;
}
@@ -291,6 +291,7 @@ void Light3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_SPECULAR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI/SDFGI only)"), "set_bake_mode", "get_bake_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
+
ADD_GROUP("Shadow", "shadow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BIAS);
@@ -298,13 +299,18 @@ void Light3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_OPACITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BLUR);
+
+ ADD_GROUP("Distance Fade", "distance_fade_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enabled"), "set_enable_distance_fade", "is_distance_fade_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_begin", "get_distance_fade_begin");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_shadow", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_shadow", "get_distance_fade_shadow");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_length", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_distance_fade_length", "get_distance_fade_length");
+
ADD_GROUP("Editor", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
+
ADD_GROUP("", "");
BIND_ENUM_CONSTANT(PARAM_ENERGY);
@@ -323,6 +329,7 @@ void Light3D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE);
+ BIND_ENUM_CONSTANT(PARAM_SHADOW_OPACITY);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR);
BIND_ENUM_CONSTANT(PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS);
@@ -370,6 +377,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
set_param(PARAM_SHADOW_FADE_START, 0.8);
set_param(PARAM_SHADOW_PANCAKE_SIZE, 20.0);
+ set_param(PARAM_SHADOW_OPACITY, 1.0);
set_param(PARAM_SHADOW_BLUR, 1.0);
set_param(PARAM_SHADOW_BIAS, 0.03);
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index 6ff332df5a..ef003e133d 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -54,6 +54,7 @@ public:
PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS,
PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
+ PARAM_SHADOW_OPACITY = RS::LIGHT_PARAM_SHADOW_OPACITY,
PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR,
PARAM_SHADOW_VOLUMETRIC_FOG_FADE = RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS,
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index abe942b97a..6b6a2eff9e 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -146,7 +146,7 @@ Array LightmapGIData::_get_light_textures_data() const {
texture_image->create(slice_width, slice_height * texture_slice_count, false, images[0]->get_format());
for (int j = 0; j < texture_slice_count; j++) {
- texture_image->blit_rect(images[i * slices_per_texture + j], Rect2(0, 0, slice_width, slice_height), Point2(0, slice_height * j));
+ texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j));
}
String texture_path = texture_count > 1 ? base_name + "_" + itos(i) + ".exr" : base_name + ".exr";
@@ -291,7 +291,7 @@ void LightmapGIData::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data);
ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK), "set_light_texture", "get_light_texture"); // property usage default but no save
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR), "set_light_texture", "get_light_texture"); // property usage default but no save
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data");
@@ -1219,7 +1219,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
}
data->set_path(p_image_data_path);
- Error err = ResourceSaver::save(p_image_data_path, data);
+ Error err = ResourceSaver::save(data);
if (err != OK) {
return BAKE_ERROR_CANT_CREATE_IMAGE;
diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h
index f7a23c776a..85150b833f 100644
--- a/scene/3d/lightmap_gi.h
+++ b/scene/3d/lightmap_gi.h
@@ -271,4 +271,4 @@ VARIANT_ENUM_CAST(LightmapGI::GenerateProbes);
VARIANT_ENUM_CAST(LightmapGI::BakeError);
VARIANT_ENUM_CAST(LightmapGI::EnvironmentMode);
-#endif // BAKED_LIGHTMAP_H
+#endif // LIGHTMAP_GI_H
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index dc9c64fa41..48d76b9a88 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef MESH_INSTANCE_H
-#define MESH_INSTANCE_H
+#ifndef MESH_INSTANCE_3D_H
+#define MESH_INSTANCE_3D_H
#include "core/templates/local_vector.h"
#include "scene/3d/visual_instance_3d.h"
@@ -98,4 +98,4 @@ public:
~MeshInstance3D();
};
-#endif
+#endif // MESH_INSTANCE_3D_H
diff --git a/scene/3d/multimesh_instance_3d.h b/scene/3d/multimesh_instance_3d.h
index 111f1e9c09..2fa8dd965f 100644
--- a/scene/3d/multimesh_instance_3d.h
+++ b/scene/3d/multimesh_instance_3d.h
@@ -53,4 +53,4 @@ public:
~MultiMeshInstance3D();
};
-#endif // MULTIMESH_INSTANCE_H
+#endif // MULTIMESH_INSTANCE_3D_H
diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h
index 0a00d769c3..e05f0287f7 100644
--- a/scene/3d/navigation_agent_3d.h
+++ b/scene/3d/navigation_agent_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NAVIGATION_AGENT_H
-#define NAVIGATION_AGENT_H
+#ifndef NAVIGATION_AGENT_3D_H
+#define NAVIGATION_AGENT_3D_H
#include "scene/main/node.h"
@@ -175,4 +175,4 @@ private:
void _check_distance_to_target();
};
-#endif
+#endif // NAVIGATION_AGENT_3D_H
diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h
index 0ddde64c0e..0316fc37a8 100644
--- a/scene/3d/navigation_obstacle_3d.h
+++ b/scene/3d/navigation_obstacle_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NAVIGATION_OBSTACLE_H
-#define NAVIGATION_OBSTACLE_H
+#ifndef NAVIGATION_OBSTACLE_3D_H
+#define NAVIGATION_OBSTACLE_3D_H
#include "scene/3d/node_3d.h"
@@ -73,4 +73,4 @@ private:
real_t estimate_agent_radius() const;
};
-#endif
+#endif // NAVIGATION_OBSTACLE_3D_H
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index 2a8149c6f6..4150b01651 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -49,14 +49,29 @@ void NavigationRegion3D::set_enabled(bool p_enabled) {
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
}
- if (debug_view) {
- MeshInstance3D *dm = Object::cast_to<MeshInstance3D>(debug_view);
- if (is_enabled()) {
- dm->set_material_override(get_tree()->get_debug_navigation_material());
+#ifdef DEBUG_ENABLED
+ if (debug_instance.is_valid()) {
+ if (!is_enabled()) {
+ if (debug_mesh.is_valid()) {
+ if (debug_mesh->get_surface_count() > 0) {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_disabled_material()->get_rid());
+ }
+ if (debug_mesh->get_surface_count() > 1) {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 1, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_disabled_material()->get_rid());
+ }
+ }
} else {
- dm->set_material_override(get_tree()->get_debug_navigation_disabled_material());
+ if (debug_mesh.is_valid()) {
+ if (debug_mesh->get_surface_count() > 0) {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, RID());
+ }
+ if (debug_mesh->get_surface_count() > 1) {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 1, RID());
+ }
+ }
}
}
+#endif // DEBUG_ENABLED
update_gizmos();
}
@@ -104,7 +119,7 @@ real_t NavigationRegion3D::get_enter_cost() const {
void NavigationRegion3D::set_travel_cost(real_t p_travel_cost) {
ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
travel_cost = MAX(p_travel_cost, 0.0);
- NavigationServer3D::get_singleton()->region_set_enter_cost(region, travel_cost);
+ NavigationServer3D::get_singleton()->region_set_travel_cost(region, travel_cost);
}
real_t NavigationRegion3D::get_travel_cost() const {
@@ -124,30 +139,36 @@ void NavigationRegion3D::_notification(int p_what) {
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
}
- if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) {
- MeshInstance3D *dm = memnew(MeshInstance3D);
- dm->set_mesh(navmesh->get_debug_mesh());
- if (is_enabled()) {
- dm->set_material_override(get_tree()->get_debug_navigation_material());
- } else {
- dm->set_material_override(get_tree()->get_debug_navigation_disabled_material());
- }
- add_child(dm);
- debug_view = dm;
+#ifdef DEBUG_ENABLED
+ if (NavigationServer3D::get_singleton()->get_debug_enabled()) {
+ _update_debug_mesh();
}
+#endif // DEBUG_ENABLED
+
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform());
+
+#ifdef DEBUG_ENABLED
+ if (is_inside_tree() && debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
+ }
+#endif // DEBUG_ENABLED
+
} break;
case NOTIFICATION_EXIT_TREE: {
NavigationServer3D::get_singleton()->region_set_map(region, RID());
- if (debug_view) {
- debug_view->queue_delete();
- debug_view = nullptr;
+#ifdef DEBUG_ENABLED
+ if (debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_instance, false);
+ }
+ if (debug_edge_connections_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
}
+#endif // DEBUG_ENABLED
} break;
}
}
@@ -169,20 +190,21 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes
NavigationServer3D::get_singleton()->region_set_navmesh(region, p_navmesh);
- if (debug_view == nullptr && is_inside_tree() && navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) {
- MeshInstance3D *dm = memnew(MeshInstance3D);
- dm->set_mesh(navmesh->get_debug_mesh());
- if (is_enabled()) {
- dm->set_material_override(get_tree()->get_debug_navigation_material());
+#ifdef DEBUG_ENABLED
+ if (is_inside_tree() && NavigationServer3D::get_singleton()->get_debug_enabled()) {
+ if (navmesh.is_valid()) {
+ _update_debug_mesh();
+ _update_debug_edge_connections_mesh();
} else {
- dm->set_material_override(get_tree()->get_debug_navigation_disabled_material());
+ if (debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_instance, false);
+ }
+ if (debug_edge_connections_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
+ }
}
- add_child(dm);
- debug_view = dm;
- }
- if (debug_view && navmesh.is_valid()) {
- Object::cast_to<MeshInstance3D>(debug_view)->set_mesh(navmesh->get_debug_mesh());
}
+#endif // DEBUG_ENABLED
emit_signal(SNAME("navigation_mesh_changed"));
@@ -287,13 +309,31 @@ void NavigationRegion3D::_bind_methods() {
void NavigationRegion3D::_navigation_changed() {
update_gizmos();
update_configuration_warnings();
+
+#ifdef DEBUG_ENABLED
+ _update_debug_edge_connections_mesh();
+#endif // DEBUG_ENABLED
+}
+
+#ifdef DEBUG_ENABLED
+void NavigationRegion3D::_navigation_map_changed(RID p_map) {
+ if (is_inside_tree() && p_map == get_world_3d()->get_navigation_map()) {
+ _update_debug_edge_connections_mesh();
+ }
}
+#endif // DEBUG_ENABLED
NavigationRegion3D::NavigationRegion3D() {
set_notify_transform(true);
region = NavigationServer3D::get_singleton()->region_create();
NavigationServer3D::get_singleton()->region_set_enter_cost(region, get_enter_cost());
NavigationServer3D::get_singleton()->region_set_travel_cost(region, get_travel_cost());
+
+#ifdef DEBUG_ENABLED
+ NavigationServer3D::get_singleton_mut()->connect("map_changed", callable_mp(this, &NavigationRegion3D::_navigation_map_changed));
+ NavigationServer3D::get_singleton_mut()->connect("navigation_debug_changed", callable_mp(this, &NavigationRegion3D::_update_debug_mesh));
+ NavigationServer3D::get_singleton_mut()->connect("navigation_debug_changed", callable_mp(this, &NavigationRegion3D::_update_debug_edge_connections_mesh));
+#endif // DEBUG_ENABLED
}
NavigationRegion3D::~NavigationRegion3D() {
@@ -301,4 +341,245 @@ NavigationRegion3D::~NavigationRegion3D() {
navmesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
NavigationServer3D::get_singleton()->free(region);
+
+#ifdef DEBUG_ENABLED
+ NavigationServer3D::get_singleton_mut()->disconnect("map_changed", callable_mp(this, &NavigationRegion3D::_navigation_map_changed));
+ NavigationServer3D::get_singleton_mut()->disconnect("navigation_debug_changed", callable_mp(this, &NavigationRegion3D::_update_debug_mesh));
+ NavigationServer3D::get_singleton_mut()->disconnect("navigation_debug_changed", callable_mp(this, &NavigationRegion3D::_update_debug_edge_connections_mesh));
+ if (debug_instance.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_instance);
+ }
+ if (debug_mesh.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_mesh->get_rid());
+ }
+ if (debug_edge_connections_instance.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_edge_connections_instance);
+ }
+ if (debug_edge_connections_mesh.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_edge_connections_mesh->get_rid());
+ }
+#endif // DEBUG_ENABLED
+}
+
+#ifdef DEBUG_ENABLED
+void NavigationRegion3D::_update_debug_mesh() {
+ if (!NavigationServer3D::get_singleton()->get_debug_enabled()) {
+ if (debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_instance, false);
+ }
+ return;
+ }
+
+ if (!navmesh.is_valid()) {
+ if (debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_instance, false);
+ }
+ return;
+ }
+
+ if (!debug_instance.is_valid()) {
+ debug_instance = RenderingServer::get_singleton()->instance_create();
+ }
+
+ if (!debug_mesh.is_valid()) {
+ debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
+ }
+
+ debug_mesh->clear_surfaces();
+
+ bool enabled_geometry_face_random_color = NavigationServer3D::get_singleton()->get_debug_navigation_enable_geometry_face_random_color();
+ bool enabled_edge_lines = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines();
+
+ Vector<Vector3> vertices = navmesh->get_vertices();
+ if (vertices.size() == 0) {
+ return;
+ }
+
+ int polygon_count = navmesh->get_polygon_count();
+ if (polygon_count == 0) {
+ return;
+ }
+
+ Vector<Vector3> face_vertex_array;
+ face_vertex_array.resize(polygon_count * 3);
+
+ Vector<Color> face_color_array;
+ if (enabled_geometry_face_random_color) {
+ face_color_array.resize(polygon_count * 3);
+ }
+
+ Vector<Vector3> line_vertex_array;
+ if (enabled_edge_lines) {
+ line_vertex_array.resize(polygon_count * 6);
+ }
+
+ Color debug_navigation_geometry_face_color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color();
+
+ Ref<StandardMaterial3D> face_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_material();
+ Ref<StandardMaterial3D> line_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_material();
+
+ Color polygon_color = debug_navigation_geometry_face_color;
+
+ for (int i = 0; i < polygon_count; i++) {
+ if (enabled_geometry_face_random_color) {
+ polygon_color = debug_navigation_geometry_face_color * (Color(Math::randf(), Math::randf(), Math::randf()));
+ }
+
+ Vector<int> polygon = navmesh->get_polygon(i);
+
+ face_vertex_array.push_back(vertices[polygon[0]]);
+ face_vertex_array.push_back(vertices[polygon[1]]);
+ face_vertex_array.push_back(vertices[polygon[2]]);
+ if (enabled_geometry_face_random_color) {
+ face_color_array.push_back(polygon_color);
+ face_color_array.push_back(polygon_color);
+ face_color_array.push_back(polygon_color);
+ }
+
+ if (enabled_edge_lines) {
+ line_vertex_array.push_back(vertices[polygon[0]]);
+ line_vertex_array.push_back(vertices[polygon[1]]);
+ line_vertex_array.push_back(vertices[polygon[1]]);
+ line_vertex_array.push_back(vertices[polygon[2]]);
+ line_vertex_array.push_back(vertices[polygon[2]]);
+ line_vertex_array.push_back(vertices[polygon[0]]);
+ }
+ }
+
+ Array face_mesh_array;
+ face_mesh_array.resize(Mesh::ARRAY_MAX);
+ face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array;
+ if (enabled_geometry_face_random_color) {
+ face_mesh_array[Mesh::ARRAY_COLOR] = face_color_array;
+ }
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array);
+ debug_mesh->surface_set_material(0, face_material);
+
+ if (enabled_edge_lines) {
+ Array line_mesh_array;
+ line_mesh_array.resize(Mesh::ARRAY_MAX);
+ line_mesh_array[Mesh::ARRAY_VERTEX] = line_vertex_array;
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, line_mesh_array);
+ debug_mesh->surface_set_material(1, line_material);
+ }
+
+ RS::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid());
+ if (is_inside_tree()) {
+ RS::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario());
+ RS::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
+ }
+ if (!is_enabled()) {
+ if (debug_mesh.is_valid()) {
+ if (debug_mesh->get_surface_count() > 0) {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_disabled_material()->get_rid());
+ }
+ if (debug_mesh->get_surface_count() > 1) {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 1, NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_disabled_material()->get_rid());
+ }
+ }
+ } else {
+ if (debug_mesh.is_valid()) {
+ if (debug_mesh->get_surface_count() > 0) {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, RID());
+ }
+ if (debug_mesh->get_surface_count() > 1) {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 1, RID());
+ }
+ }
+ }
+}
+#endif // DEBUG_ENABLED
+
+#ifdef DEBUG_ENABLED
+void NavigationRegion3D::_update_debug_edge_connections_mesh() {
+ if (!NavigationServer3D::get_singleton()->get_debug_enabled()) {
+ if (debug_edge_connections_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
+ }
+ return;
+ }
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ if (!navmesh.is_valid()) {
+ if (debug_edge_connections_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
+ }
+ return;
+ }
+
+ if (!debug_edge_connections_instance.is_valid()) {
+ debug_edge_connections_instance = RenderingServer::get_singleton()->instance_create();
+ }
+
+ if (!debug_edge_connections_mesh.is_valid()) {
+ debug_edge_connections_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
+ }
+
+ debug_edge_connections_mesh->clear_surfaces();
+
+ float edge_connection_margin = NavigationServer3D::get_singleton()->map_get_edge_connection_margin(get_world_3d()->get_navigation_map());
+ float half_edge_connection_margin = edge_connection_margin * 0.5;
+ int connections_count = NavigationServer3D::get_singleton()->region_get_connections_count(region);
+
+ if (connections_count == 0) {
+ RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
+ return;
+ }
+
+ Vector<Vector3> vertex_array;
+
+ for (int i = 0; i < connections_count; i++) {
+ Vector3 connection_pathway_start = NavigationServer3D::get_singleton()->region_get_connection_pathway_start(region, i);
+ Vector3 connection_pathway_end = NavigationServer3D::get_singleton()->region_get_connection_pathway_end(region, i);
+
+ Vector3 direction_start_end = connection_pathway_start.direction_to(connection_pathway_end);
+ Vector3 direction_end_start = connection_pathway_end.direction_to(connection_pathway_start);
+
+ Vector3 start_right_dir = direction_start_end.cross(Vector3(0, 1, 0));
+ Vector3 start_left_dir = -start_right_dir;
+
+ Vector3 end_right_dir = direction_end_start.cross(Vector3(0, 1, 0));
+ Vector3 end_left_dir = -end_right_dir;
+
+ Vector3 left_start_pos = connection_pathway_start + (start_left_dir * half_edge_connection_margin);
+ Vector3 right_start_pos = connection_pathway_start + (start_right_dir * half_edge_connection_margin);
+ Vector3 left_end_pos = connection_pathway_end + (end_right_dir * half_edge_connection_margin);
+ Vector3 right_end_pos = connection_pathway_end + (end_left_dir * half_edge_connection_margin);
+
+ vertex_array.push_back(right_end_pos);
+ vertex_array.push_back(left_start_pos);
+ vertex_array.push_back(right_start_pos);
+
+ vertex_array.push_back(left_end_pos);
+ vertex_array.push_back(right_end_pos);
+ vertex_array.push_back(right_start_pos);
+ }
+
+ if (vertex_array.size() == 0) {
+ return;
+ }
+
+ Ref<StandardMaterial3D> edge_connections_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_edge_connections_material();
+
+ Array mesh_array;
+ mesh_array.resize(Mesh::ARRAY_MAX);
+ mesh_array[Mesh::ARRAY_VERTEX] = vertex_array;
+
+ debug_edge_connections_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, mesh_array);
+ debug_edge_connections_mesh->surface_set_material(0, edge_connections_material);
+
+ RS::get_singleton()->instance_set_base(debug_edge_connections_instance, debug_edge_connections_mesh->get_rid());
+ RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, is_visible_in_tree());
+ if (is_inside_tree()) {
+ RS::get_singleton()->instance_set_scenario(debug_edge_connections_instance, get_world_3d()->get_scenario());
+ }
+
+ bool enable_edge_connections = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_connections();
+ if (!enable_edge_connections) {
+ RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
+ }
}
+#endif // DEBUG_ENABLED
diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h
index aaaf5dd3b8..ba326abb46 100644
--- a/scene/3d/navigation_region_3d.h
+++ b/scene/3d/navigation_region_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NAVIGATION_REGION_H
-#define NAVIGATION_REGION_H
+#ifndef NAVIGATION_REGION_3D_H
+#define NAVIGATION_REGION_3D_H
#include "scene/3d/node_3d.h"
#include "scene/resources/navigation_mesh.h"
@@ -44,11 +44,22 @@ class NavigationRegion3D : public Node3D {
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
- Node *debug_view = nullptr;
Thread bake_thread;
void _navigation_changed();
+#ifdef DEBUG_ENABLED
+ RID debug_instance;
+ RID debug_edge_connections_instance;
+ Ref<ArrayMesh> debug_mesh;
+ Ref<ArrayMesh> debug_edge_connections_mesh;
+
+private:
+ void _update_debug_mesh();
+ void _update_debug_edge_connections_mesh();
+ void _navigation_map_changed(RID p_map);
+#endif // DEBUG_ENABLED
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -85,4 +96,4 @@ public:
~NavigationRegion3D();
};
-#endif // NAVIGATION_REGION_H
+#endif // NAVIGATION_REGION_3D_H
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 4c00250162..1de85d57a3 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.
@@ -711,7 +733,7 @@ void Node3D::rotate_z(real_t p_angle) {
void Node3D::translate(const Vector3 &p_offset) {
Transform3D t = get_transform();
- t.translate(p_offset);
+ t.translate_local(p_offset);
set_transform(t);
}
@@ -719,7 +741,7 @@ void Node3D::translate_object_local(const Vector3 &p_offset) {
Transform3D t = get_transform();
Transform3D s;
- s.translate(p_offset);
+ s.translate_local(p_offset);
set_transform(t * s);
}
@@ -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/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index 66d0a8c4e2..c1c309fdbe 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -670,7 +670,7 @@ OccluderInstance3D::BakeError OccluderInstance3D::bake_scene(Node *p_from_node,
occ->set_arrays(vertices, indices);
- Error err = ResourceSaver::save(p_occluder_path, occ);
+ Error err = ResourceSaver::save(occ, p_occluder_path);
if (err != OK) {
return BAKE_ERROR_CANT_SAVE;
diff --git a/scene/3d/occluder_instance_3d.h b/scene/3d/occluder_instance_3d.h
index ed6610074e..11d731b989 100644
--- a/scene/3d/occluder_instance_3d.h
+++ b/scene/3d/occluder_instance_3d.h
@@ -211,4 +211,4 @@ public:
~OccluderInstance3D();
};
-#endif
+#endif // OCCLUDER_INSTANCE_3D_H
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index f53e783fbd..25226ad384 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -296,7 +296,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
}
}
- t.translate(Vector3(h_offset, v_offset, 0));
+ t.translate_local(Vector3(h_offset, v_offset, 0));
} else {
t.origin = pos + Vector3(h_offset, v_offset, 0);
}
@@ -397,6 +397,7 @@ void PathFollow3D::_bind_methods() {
}
void PathFollow3D::set_offset(real_t p_offset) {
+ ERR_FAIL_COND(!isfinite(p_offset));
prev_offset = offset;
offset = p_offset;
diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h
index 7c7284534e..b4cc6db7e3 100644
--- a/scene/3d/path_3d.h
+++ b/scene/3d/path_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PATH_H
-#define PATH_H
+#ifndef PATH_3D_H
+#define PATH_3D_H
#include "scene/3d/node_3d.h"
#include "scene/resources/curve.h"
@@ -119,4 +119,4 @@ public:
VARIANT_ENUM_CAST(PathFollow3D::RotationMode);
-#endif // PATH_H
+#endif // PATH_3D_H
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 30f7a025fa..993608c306 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -439,8 +439,8 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p
//E->value.rc=0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree), make_binds(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree), make_binds(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree).bind(objid));
if (E->value.in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_entered, node);
}
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 22dcb218bc..e4a41be6c0 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -784,4 +784,4 @@ private:
VARIANT_ENUM_CAST(PhysicalBone3D::JointType);
VARIANT_ENUM_CAST(PhysicalBone3D::DampMode);
-#endif // PHYSICS_BODY__H
+#endif // PHYSICS_BODY_3D_H
diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h
index c69c910efb..aa62f6927e 100644
--- a/scene/3d/ray_cast_3d.h
+++ b/scene/3d/ray_cast_3d.h
@@ -126,4 +126,4 @@ public:
RayCast3D();
};
-#endif // RAY_CAST_H
+#endif // RAY_CAST_3D_H
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index 424976d895..a161717ece 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef REFLECTIONPROBE_H
-#define REFLECTIONPROBE_H
+#ifndef REFLECTION_PROBE_H
+#define REFLECTION_PROBE_H
#include "scene/3d/visual_instance_3d.h"
@@ -121,4 +121,4 @@ public:
VARIANT_ENUM_CAST(ReflectionProbe::AmbientMode);
VARIANT_ENUM_CAST(ReflectionProbe::UpdateMode);
-#endif // REFLECTIONPROBE_H
+#endif // REFLECTION_PROBE_H
diff --git a/scene/3d/remote_transform_3d.h b/scene/3d/remote_transform_3d.h
index 03bb253578..ab134c1261 100644
--- a/scene/3d/remote_transform_3d.h
+++ b/scene/3d/remote_transform_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef REMOTETRANSFORM_H
-#define REMOTETRANSFORM_H
+#ifndef REMOTE_TRANSFORM_3D_H
+#define REMOTE_TRANSFORM_3D_H
#include "scene/3d/node_3d.h"
@@ -75,4 +75,4 @@ public:
RemoteTransform3D();
};
-#endif // REMOTETRANSFORM_H
+#endif // REMOTE_TRANSFORM_3D_H
diff --git a/scene/3d/shape_cast_3d.cpp b/scene/3d/shape_cast_3d.cpp
new file mode 100644
index 0000000000..d324e09df5
--- /dev/null
+++ b/scene/3d/shape_cast_3d.cpp
@@ -0,0 +1,634 @@
+/*************************************************************************/
+/* shape_cast_3d.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 "shape_cast_3d.h"
+
+#include "collision_object_3d.h"
+#include "mesh_instance_3d.h"
+#include "scene/resources/concave_polygon_shape_3d.h"
+
+void ShapeCast3D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ _update_debug_shape_vertices();
+ }
+ if (enabled && !Engine::get_singleton()->is_editor_hint()) {
+ set_physics_process_internal(true);
+ } else {
+ set_physics_process_internal(false);
+ }
+
+ if (get_tree()->is_debugging_collisions_hint()) {
+ _update_debug_shape();
+ }
+
+ if (Object::cast_to<CollisionObject3D>(get_parent())) {
+ if (exclude_parent_body) {
+ exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
+ } else {
+ exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
+ }
+ }
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ if (enabled) {
+ set_physics_process_internal(false);
+ }
+
+ if (debug_shape) {
+ _clear_debug_shape();
+ }
+ } break;
+
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ if (!enabled) {
+ break;
+ }
+
+ bool prev_collision_state = collided;
+ _update_shapecast_state();
+ if (get_tree()->is_debugging_collisions_hint()) {
+ if (prev_collision_state != collided) {
+ _update_debug_shape_material(true);
+ }
+ if (collided) {
+ _update_debug_shape();
+ }
+ if (prev_collision_state == collided && !collided) {
+ _update_debug_shape();
+ }
+ }
+ } break;
+ }
+}
+
+void ShapeCast3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &ShapeCast3D::resource_changed);
+
+ ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &ShapeCast3D::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"), &ShapeCast3D::is_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_shape", "shape"), &ShapeCast3D::set_shape);
+ ClassDB::bind_method(D_METHOD("get_shape"), &ShapeCast3D::get_shape);
+
+ ClassDB::bind_method(D_METHOD("set_target_position", "local_point"), &ShapeCast3D::set_target_position);
+ ClassDB::bind_method(D_METHOD("get_target_position"), &ShapeCast3D::get_target_position);
+
+ ClassDB::bind_method(D_METHOD("set_margin", "margin"), &ShapeCast3D::set_margin);
+ ClassDB::bind_method(D_METHOD("get_margin"), &ShapeCast3D::get_margin);
+
+ ClassDB::bind_method(D_METHOD("set_max_results", "max_results"), &ShapeCast3D::set_max_results);
+ ClassDB::bind_method(D_METHOD("get_max_results"), &ShapeCast3D::get_max_results);
+
+ ClassDB::bind_method(D_METHOD("is_colliding"), &ShapeCast3D::is_colliding);
+ ClassDB::bind_method(D_METHOD("get_collision_count"), &ShapeCast3D::get_collision_count);
+
+ ClassDB::bind_method(D_METHOD("force_shapecast_update"), &ShapeCast3D::force_shapecast_update);
+
+ ClassDB::bind_method(D_METHOD("get_collider", "index"), &ShapeCast3D::get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_shape", "index"), &ShapeCast3D::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_point", "index"), &ShapeCast3D::get_collision_point);
+ ClassDB::bind_method(D_METHOD("get_collision_normal", "index"), &ShapeCast3D::get_collision_normal);
+
+ ClassDB::bind_method(D_METHOD("get_closest_collision_safe_fraction"), &ShapeCast3D::get_closest_collision_safe_fraction);
+ ClassDB::bind_method(D_METHOD("get_closest_collision_unsafe_fraction"), &ShapeCast3D::get_closest_collision_unsafe_fraction);
+
+ ClassDB::bind_method(D_METHOD("add_exception_rid", "rid"), &ShapeCast3D::add_exception_rid);
+ ClassDB::bind_method(D_METHOD("add_exception", "node"), &ShapeCast3D::add_exception);
+
+ ClassDB::bind_method(D_METHOD("remove_exception_rid", "rid"), &ShapeCast3D::remove_exception_rid);
+ ClassDB::bind_method(D_METHOD("remove_exception", "node"), &ShapeCast3D::remove_exception);
+
+ ClassDB::bind_method(D_METHOD("clear_exceptions"), &ShapeCast3D::clear_exceptions);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &ShapeCast3D::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &ShapeCast3D::get_collision_mask);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask_value", "layer_number", "value"), &ShapeCast3D::set_collision_mask_value);
+ ClassDB::bind_method(D_METHOD("get_collision_mask_value", "layer_number"), &ShapeCast3D::get_collision_mask_value);
+
+ ClassDB::bind_method(D_METHOD("set_exclude_parent_body", "mask"), &ShapeCast3D::set_exclude_parent_body);
+ ClassDB::bind_method(D_METHOD("get_exclude_parent_body"), &ShapeCast3D::get_exclude_parent_body);
+
+ ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &ShapeCast3D::set_collide_with_areas);
+ ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &ShapeCast3D::is_collide_with_areas_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &ShapeCast3D::set_collide_with_bodies);
+ ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &ShapeCast3D::is_collide_with_bodies_enabled);
+
+ ClassDB::bind_method(D_METHOD("_get_collision_result"), &ShapeCast3D::_get_collision_result);
+
+ ClassDB::bind_method(D_METHOD("set_debug_shape_custom_color", "debug_shape_custom_color"), &ShapeCast3D::set_debug_shape_custom_color);
+ ClassDB::bind_method(D_METHOD("get_debug_shape_custom_color"), &ShapeCast3D::get_debug_shape_custom_color);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position", PROPERTY_HINT_NONE, "suffix:m"), "set_target_position", "get_target_position");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01,suffix:m"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_results"), "set_max_results", "get_max_results");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "", "_get_collision_result");
+
+ ADD_GROUP("Collide With", "collide_with");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
+
+ ADD_GROUP("Debug Shape", "debug_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_shape_custom_color"), "set_debug_shape_custom_color", "get_debug_shape_custom_color");
+}
+
+TypedArray<String> ShapeCast3D::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node3D::get_configuration_warnings();
+
+ if (shape.is_null()) {
+ warnings.push_back(RTR("This node cannot interact with other objects unless a Shape3D is assigned."));
+ }
+ if (shape.is_valid() && Object::cast_to<ConcavePolygonShape3D>(*shape)) {
+ warnings.push_back(RTR("ShapeCast3D does not support ConcavePolygonShape3Ds. Collisions will not be reported."));
+ }
+ return warnings;
+}
+
+void ShapeCast3D::set_enabled(bool p_enabled) {
+ enabled = p_enabled;
+ update_gizmos();
+
+ if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) {
+ set_physics_process_internal(p_enabled);
+ }
+ if (!p_enabled) {
+ collided = false;
+ }
+
+ if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) {
+ if (p_enabled) {
+ _update_debug_shape();
+ } else {
+ _clear_debug_shape();
+ }
+ }
+}
+
+bool ShapeCast3D::is_enabled() const {
+ return enabled;
+}
+
+void ShapeCast3D::set_target_position(const Vector3 &p_point) {
+ target_position = p_point;
+ if (is_inside_tree()) {
+ _update_debug_shape();
+ }
+ update_gizmos();
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ if (is_inside_tree()) {
+ _update_debug_shape_vertices();
+ }
+ } else if (debug_shape) {
+ _update_debug_shape();
+ }
+}
+
+Vector3 ShapeCast3D::get_target_position() const {
+ return target_position;
+}
+
+void ShapeCast3D::set_margin(real_t p_margin) {
+ margin = p_margin;
+}
+
+real_t ShapeCast3D::get_margin() const {
+ return margin;
+}
+
+void ShapeCast3D::set_max_results(int p_max_results) {
+ max_results = p_max_results;
+}
+
+int ShapeCast3D::get_max_results() const {
+ return max_results;
+}
+
+void ShapeCast3D::set_collision_mask(uint32_t p_mask) {
+ collision_mask = p_mask;
+}
+
+uint32_t ShapeCast3D::get_collision_mask() const {
+ return collision_mask;
+}
+
+void ShapeCast3D::set_collision_mask_value(int p_layer_number, bool p_value) {
+ ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive.");
+ ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive.");
+ uint32_t mask = get_collision_mask();
+ if (p_value) {
+ mask |= 1 << (p_layer_number - 1);
+ } else {
+ mask &= ~(1 << (p_layer_number - 1));
+ }
+ set_collision_mask(mask);
+}
+
+bool ShapeCast3D::get_collision_mask_value(int p_layer_number) const {
+ ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive.");
+ ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive.");
+ return get_collision_mask() & (1 << (p_layer_number - 1));
+}
+
+int ShapeCast3D::get_collision_count() const {
+ return result.size();
+}
+
+bool ShapeCast3D::is_colliding() const {
+ return collided;
+}
+
+Object *ShapeCast3D::get_collider(int p_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), nullptr, "No collider found.");
+
+ if (result[p_idx].collider_id.is_null()) {
+ return nullptr;
+ }
+ return ObjectDB::get_instance(result[p_idx].collider_id);
+}
+
+int ShapeCast3D::get_collider_shape(int p_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), -1, "No collider shape found.");
+ return result[p_idx].shape;
+}
+
+Vector3 ShapeCast3D::get_collision_point(int p_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), Vector3(), "No collision point found.");
+ return result[p_idx].point;
+}
+
+Vector3 ShapeCast3D::get_collision_normal(int p_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), Vector3(), "No collision normal found.");
+ return result[p_idx].normal;
+}
+
+real_t ShapeCast3D::get_closest_collision_safe_fraction() const {
+ return collision_safe_fraction;
+}
+
+real_t ShapeCast3D::get_closest_collision_unsafe_fraction() const {
+ return collision_unsafe_fraction;
+}
+
+void ShapeCast3D::resource_changed(Ref<Resource> p_res) {
+ if (is_inside_tree()) {
+ _update_debug_shape();
+ }
+ update_gizmos();
+}
+
+void ShapeCast3D::set_shape(const Ref<Shape3D> &p_shape) {
+ if (p_shape == shape) {
+ return;
+ }
+ if (!shape.is_null()) {
+ shape->unregister_owner(this);
+ }
+ shape = p_shape;
+ if (!shape.is_null()) {
+ shape->register_owner(this);
+ }
+ if (p_shape.is_valid()) {
+ shape_rid = shape->get_rid();
+ }
+
+ if (is_inside_tree()) {
+ _update_debug_shape();
+ }
+
+ update_gizmos();
+ update_configuration_warnings();
+}
+
+Ref<Shape3D> ShapeCast3D::get_shape() const {
+ return shape;
+}
+
+void ShapeCast3D::set_exclude_parent_body(bool p_exclude_parent_body) {
+ if (exclude_parent_body == p_exclude_parent_body) {
+ return;
+ }
+ exclude_parent_body = p_exclude_parent_body;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+ if (Object::cast_to<CollisionObject3D>(get_parent())) {
+ if (exclude_parent_body) {
+ exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
+ } else {
+ exclude.erase(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
+ }
+ }
+}
+
+bool ShapeCast3D::get_exclude_parent_body() const {
+ return exclude_parent_body;
+}
+
+void ShapeCast3D::_update_shapecast_state() {
+ result.clear();
+
+ ERR_FAIL_COND_MSG(shape.is_null(), "Null reference to shape. ShapeCast3D requires a Shape3D to sweep for collisions.");
+
+ Ref<World3D> w3d = get_world_3d();
+ ERR_FAIL_COND(w3d.is_null());
+
+ PhysicsDirectSpaceState3D *dss = PhysicsServer3D::get_singleton()->space_get_direct_state(w3d->get_space());
+ ERR_FAIL_COND(!dss);
+
+ Transform3D gt = get_global_transform();
+
+ PhysicsDirectSpaceState3D::ShapeParameters params;
+ params.shape_rid = shape_rid;
+ params.transform = gt;
+ params.motion = gt.basis.xform(target_position);
+ params.margin = margin;
+ params.exclude = exclude;
+ params.collision_mask = collision_mask;
+ params.collide_with_bodies = collide_with_bodies;
+ params.collide_with_areas = collide_with_areas;
+
+ collision_safe_fraction = 0.0;
+ collision_unsafe_fraction = 0.0;
+
+ if (target_position != Vector3()) {
+ dss->cast_motion(params, collision_safe_fraction, collision_unsafe_fraction);
+ if (collision_unsafe_fraction < 1.0) {
+ // Move shape transform to the point of impact,
+ // so we can collect contact info at that point.
+ gt.set_origin(gt.get_origin() + params.motion * (collision_unsafe_fraction + CMP_EPSILON));
+ params.transform = gt;
+ }
+ }
+ // Regardless of whether the shape is stuck or it's moved along
+ // the motion vector, we'll only consider static collisions from now on.
+ params.motion = Vector3();
+
+ bool intersected = true;
+ while (intersected && result.size() < max_results) {
+ PhysicsDirectSpaceState3D::ShapeRestInfo info;
+ intersected = dss->rest_info(params, &info);
+ if (intersected) {
+ result.push_back(info);
+ params.exclude.insert(info.rid);
+ }
+ }
+ collided = !result.is_empty();
+}
+
+void ShapeCast3D::force_shapecast_update() {
+ _update_shapecast_state();
+}
+
+void ShapeCast3D::add_exception_rid(const RID &p_rid) {
+ exclude.insert(p_rid);
+}
+
+void ShapeCast3D::add_exception(const Object *p_object) {
+ ERR_FAIL_NULL(p_object);
+ const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object);
+ if (!co) {
+ return;
+ }
+ add_exception_rid(co->get_rid());
+}
+
+void ShapeCast3D::remove_exception_rid(const RID &p_rid) {
+ exclude.erase(p_rid);
+}
+
+void ShapeCast3D::remove_exception(const Object *p_object) {
+ ERR_FAIL_NULL(p_object);
+ const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object);
+ if (!co) {
+ return;
+ }
+ remove_exception_rid(co->get_rid());
+}
+
+void ShapeCast3D::clear_exceptions() {
+ exclude.clear();
+}
+
+void ShapeCast3D::set_collide_with_areas(bool p_clip) {
+ collide_with_areas = p_clip;
+}
+
+bool ShapeCast3D::is_collide_with_areas_enabled() const {
+ return collide_with_areas;
+}
+
+void ShapeCast3D::set_collide_with_bodies(bool p_clip) {
+ collide_with_bodies = p_clip;
+}
+
+bool ShapeCast3D::is_collide_with_bodies_enabled() const {
+ return collide_with_bodies;
+}
+
+Array ShapeCast3D::_get_collision_result() const {
+ Array ret;
+
+ for (int i = 0; i < result.size(); ++i) {
+ const PhysicsDirectSpaceState3D::ShapeRestInfo &sri = result[i];
+
+ Dictionary col;
+ col["point"] = sri.point;
+ col["normal"] = sri.normal;
+ col["rid"] = sri.rid;
+ col["collider"] = ObjectDB::get_instance(sri.collider_id);
+ col["collider_id"] = sri.collider_id;
+ col["shape"] = sri.shape;
+ col["linear_velocity"] = sri.linear_velocity;
+
+ ret.push_back(col);
+ }
+ return ret;
+}
+
+void ShapeCast3D::_update_debug_shape_vertices() {
+ debug_shape_vertices.clear();
+ debug_line_vertices.clear();
+
+ if (!shape.is_null()) {
+ debug_shape_vertices.append_array(shape->get_debug_mesh_lines());
+ for (int i = 0; i < debug_shape_vertices.size(); i++) {
+ debug_shape_vertices.set(i, debug_shape_vertices[i] + Vector3(target_position * get_closest_collision_safe_fraction()));
+ }
+ }
+
+ if (target_position == Vector3()) {
+ return;
+ }
+
+ debug_line_vertices.push_back(Vector3());
+ debug_line_vertices.push_back(target_position);
+}
+
+const Vector<Vector3> &ShapeCast3D::get_debug_shape_vertices() const {
+ return debug_shape_vertices;
+}
+
+const Vector<Vector3> &ShapeCast3D::get_debug_line_vertices() const {
+ return debug_line_vertices;
+}
+
+void ShapeCast3D::set_debug_shape_custom_color(const Color &p_color) {
+ debug_shape_custom_color = p_color;
+ if (debug_material.is_valid()) {
+ _update_debug_shape_material();
+ }
+}
+
+Ref<StandardMaterial3D> ShapeCast3D::get_debug_material() {
+ _update_debug_shape_material();
+ return debug_material;
+}
+
+const Color &ShapeCast3D::get_debug_shape_custom_color() const {
+ return debug_shape_custom_color;
+}
+
+void ShapeCast3D::_create_debug_shape() {
+ _update_debug_shape_material();
+
+ Ref<ArrayMesh> mesh = memnew(ArrayMesh);
+
+ MeshInstance3D *mi = memnew(MeshInstance3D);
+ mi->set_mesh(mesh);
+
+ add_child(mi);
+ debug_shape = mi;
+}
+
+void ShapeCast3D::_update_debug_shape_material(bool p_check_collision) {
+ if (!debug_material.is_valid()) {
+ Ref<StandardMaterial3D> material = memnew(StandardMaterial3D);
+ debug_material = material;
+
+ material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ // Use double-sided rendering so that the RayCast can be seen if the camera is inside.
+ material->set_cull_mode(BaseMaterial3D::CULL_DISABLED);
+ material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA);
+ }
+
+ Color color = debug_shape_custom_color;
+ if (color == Color(0.0, 0.0, 0.0)) {
+ // Use the default debug shape color defined in the Project Settings.
+ color = get_tree()->get_debug_collisions_color();
+ }
+
+ if (p_check_collision && collided) {
+ if ((color.get_h() < 0.055 || color.get_h() > 0.945) && color.get_s() > 0.5 && color.get_v() > 0.5) {
+ // If base color is already quite reddish, highlight collision with green color
+ color = Color(0.0, 1.0, 0.0, color.a);
+ } else {
+ // Else, highlight collision with red color
+ color = Color(1.0, 0, 0, color.a);
+ }
+ }
+
+ Ref<StandardMaterial3D> material = static_cast<Ref<StandardMaterial3D>>(debug_material);
+ material->set_albedo(color);
+}
+
+void ShapeCast3D::_update_debug_shape() {
+ if (!enabled) {
+ return;
+ }
+
+ if (!debug_shape) {
+ _create_debug_shape();
+ }
+
+ _update_debug_shape_vertices();
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+
+ MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
+ Ref<ArrayMesh> mesh = mi->get_mesh();
+ if (!mesh.is_valid()) {
+ return;
+ }
+
+ mesh->clear_surfaces();
+
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+
+ uint32_t flags = 0;
+ int surface_count = 0;
+
+ if (!debug_shape_vertices.is_empty()) {
+ a[Mesh::ARRAY_VERTEX] = debug_shape_vertices;
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
+ mesh->surface_set_material(surface_count, debug_material);
+ ++surface_count;
+ }
+
+ if (!debug_line_vertices.is_empty()) {
+ a[Mesh::ARRAY_VERTEX] = debug_line_vertices;
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
+ mesh->surface_set_material(surface_count, debug_material);
+ ++surface_count;
+ }
+}
+
+void ShapeCast3D::_clear_debug_shape() {
+ if (!debug_shape) {
+ return;
+ }
+
+ MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
+ if (mi->is_inside_tree()) {
+ mi->queue_delete();
+ } else {
+ memdelete(mi);
+ }
+
+ debug_shape = nullptr;
+}
+
+ShapeCast3D::~ShapeCast3D() {
+ if (!shape.is_null()) {
+ shape->unregister_owner(this);
+ }
+}
diff --git a/scene/3d/shape_cast_3d.h b/scene/3d/shape_cast_3d.h
new file mode 100644
index 0000000000..5bda15e4b0
--- /dev/null
+++ b/scene/3d/shape_cast_3d.h
@@ -0,0 +1,142 @@
+/*************************************************************************/
+/* shape_cast_3d.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 SHAPE_CAST_3D_H
+#define SHAPE_CAST_3D_H
+
+#include "scene/3d/node_3d.h"
+#include "scene/resources/shape_3d.h"
+
+class ShapeCast3D : public Node3D {
+ GDCLASS(ShapeCast3D, Node3D);
+
+ bool enabled = true;
+ void resource_changed(Ref<Resource> p_res);
+
+ Ref<Shape3D> shape;
+ RID shape_rid;
+ Vector3 target_position = Vector3(0, -1, 0);
+
+ HashSet<RID> exclude;
+ real_t margin = 0.0;
+ uint32_t collision_mask = 1;
+ bool exclude_parent_body = true;
+ bool collide_with_areas = false;
+ bool collide_with_bodies = true;
+
+ Node *debug_shape = nullptr;
+ Ref<Material> debug_material;
+ Color debug_shape_custom_color = Color(0.0, 0.0, 0.0);
+ Vector<Vector3> debug_shape_vertices;
+ Vector<Vector3> debug_line_vertices;
+
+ void _create_debug_shape();
+ void _update_debug_shape();
+ void _update_debug_shape_material(bool p_check_collision = false);
+ void _update_debug_shape_vertices();
+ void _clear_debug_shape();
+
+ // Result
+ int max_results = 32;
+ Vector<PhysicsDirectSpaceState3D::ShapeRestInfo> result;
+ bool collided = false;
+ real_t collision_safe_fraction = 1.0;
+ real_t collision_unsafe_fraction = 1.0;
+
+ Array _get_collision_result() const;
+
+ ~ShapeCast3D();
+
+protected:
+ void _notification(int p_what);
+ void _update_shapecast_state();
+ static void _bind_methods();
+
+public:
+ void set_collide_with_areas(bool p_clip);
+ bool is_collide_with_areas_enabled() const;
+
+ void set_collide_with_bodies(bool p_clip);
+ bool is_collide_with_bodies_enabled() const;
+
+ void set_enabled(bool p_enabled);
+ bool is_enabled() const;
+
+ void set_shape(const Ref<Shape3D> &p_shape);
+ Ref<Shape3D> get_shape() const;
+
+ void set_target_position(const Vector3 &p_point);
+ Vector3 get_target_position() const;
+
+ void set_margin(real_t p_margin);
+ real_t get_margin() const;
+
+ void set_max_results(int p_max_results);
+ int get_max_results() const;
+
+ void set_collision_mask(uint32_t p_mask);
+ uint32_t get_collision_mask() const;
+
+ void set_collision_mask_value(int p_layer_number, bool p_value);
+ bool get_collision_mask_value(int p_layer_number) const;
+
+ void set_exclude_parent_body(bool p_exclude_parent_body);
+ bool get_exclude_parent_body() const;
+
+ const Color &get_debug_shape_custom_color() const;
+ void set_debug_shape_custom_color(const Color &p_color);
+
+ const Vector<Vector3> &get_debug_shape_vertices() const;
+ const Vector<Vector3> &get_debug_line_vertices() const;
+
+ Ref<StandardMaterial3D> get_debug_material();
+
+ int get_collision_count() const;
+ Object *get_collider(int p_idx) const;
+ int get_collider_shape(int p_idx) const;
+ Vector3 get_collision_point(int p_idx) const;
+ Vector3 get_collision_normal(int p_idx) const;
+
+ real_t get_closest_collision_safe_fraction() const;
+ real_t get_closest_collision_unsafe_fraction() const;
+
+ void force_shapecast_update();
+ bool is_colliding() const;
+
+ void add_exception_rid(const RID &p_rid);
+ void add_exception(const Object *p_object);
+ void remove_exception_rid(const RID &p_rid);
+ void remove_exception(const Object *p_object);
+ void clear_exceptions();
+
+ virtual TypedArray<String> get_configuration_warnings() const override;
+};
+
+#endif // SHAPE_CAST_3D_H
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index fbd5f31dd5..4c38fccc8b 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -493,6 +493,19 @@ int Skeleton3D::get_bone_axis_forward_enum(int p_bone) {
return bones[p_bone].rest_bone_forward_axis;
}
+void Skeleton3D::set_motion_scale(float p_motion_scale) {
+ if (p_motion_scale <= 0) {
+ motion_scale = 1;
+ ERR_FAIL_MSG("Motion scale must be larger than 0.");
+ }
+ motion_scale = p_motion_scale;
+}
+
+float Skeleton3D::get_motion_scale() const {
+ ERR_FAIL_COND_V(motion_scale <= 0, 1);
+ return motion_scale;
+}
+
// Skeleton creation api
void Skeleton3D::add_bone(const String &p_name) {
@@ -639,6 +652,7 @@ void Skeleton3D::remove_bone_child(int p_bone, int p_child) {
}
Vector<int> Skeleton3D::get_parentless_bones() {
+ _update_process_order();
return parentless_bones;
}
@@ -765,8 +779,6 @@ void Skeleton3D::_make_dirty() {
}
void Skeleton3D::localize_rests() {
- _update_process_order();
-
Vector<int> bones_to_process = get_parentless_bones();
while (bones_to_process.size() > 0) {
int current_bone_idx = bones_to_process[0];
@@ -958,7 +970,6 @@ Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() {
skin.instantiate();
skin->set_bind_count(bones.size());
- _update_process_order(); // Just in case.
// Pose changed, rebuild cache of inverses.
const Bone *bonesptr = bones.ptr();
@@ -1257,6 +1268,9 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_update_all_bone_transforms"), &Skeleton3D::force_update_all_bone_transforms);
ClassDB::bind_method(D_METHOD("force_update_bone_child_transform", "bone_idx"), &Skeleton3D::force_update_bone_children_transforms);
+ ClassDB::bind_method(D_METHOD("set_motion_scale", "motion_scale"), &Skeleton3D::set_motion_scale);
+ ClassDB::bind_method(D_METHOD("get_motion_scale"), &Skeleton3D::get_motion_scale);
+
// Helper functions
ClassDB::bind_method(D_METHOD("global_pose_to_world_transform", "global_pose"), &Skeleton3D::global_pose_to_world_transform);
ClassDB::bind_method(D_METHOD("world_transform_to_global_pose", "world_transform"), &Skeleton3D::world_transform_to_global_pose);
@@ -1280,15 +1294,13 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_modification_stack"), &Skeleton3D::get_modification_stack);
ClassDB::bind_method(D_METHOD("execute_modifications", "delta", "execution_mode"), &Skeleton3D::execute_modifications);
-#ifndef _3D_DISABLED
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "motion_scale", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater"), "set_motion_scale", "get_motion_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_rest_only"), "set_show_rest_only", "is_show_rest_only");
+#ifndef _3D_DISABLED
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones");
#endif // _3D_DISABLED
-#ifdef TOOLS_ENABLED
ADD_SIGNAL(MethodInfo("pose_updated"));
-#endif // TOOLS_ENABLED
-
ADD_SIGNAL(MethodInfo("bone_pose_changed", PropertyInfo(Variant::INT, "bone_idx")));
ADD_SIGNAL(MethodInfo("bone_enabled_changed", PropertyInfo(Variant::INT, "bone_idx")));
ADD_SIGNAL(MethodInfo("show_rest_only_changed"));
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index cb4c82d232..8b69410a39 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -146,6 +146,7 @@ private:
bool rest_dirty = false;
bool show_rest_only = false;
+ float motion_scale = 1.0;
uint64_t version = 1;
@@ -211,6 +212,9 @@ public:
bool is_show_rest_only() const;
void clear_bones();
+ void set_motion_scale(float p_motion_scale);
+ float get_motion_scale() const;
+
// posing api
void set_bone_pose_position(int p_bone, const Vector3 &p_position);
@@ -288,4 +292,4 @@ public:
~Skeleton3D();
};
-#endif
+#endif // SKELETON_3D_H
diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h
index 0f656187de..6ae86a2bf6 100644
--- a/scene/3d/skeleton_ik_3d.h
+++ b/scene/3d/skeleton_ik_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETON_IK_H
-#define SKELETON_IK_H
+#ifndef SKELETON_IK_3D_H
+#define SKELETON_IK_3D_H
#ifndef _3D_DISABLED
@@ -192,4 +192,4 @@ private:
#endif // _3D_DISABLED
-#endif // SKELETON_IK_H
+#endif // SKELETON_IK_3D_H
diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_dynamic_body_3d.cpp
index d68e7fd527..15f050defb 100644
--- a/scene/3d/soft_dynamic_body_3d.cpp
+++ b/scene/3d/soft_dynamic_body_3d.cpp
@@ -83,7 +83,16 @@ void SoftDynamicBodyRenderingServerHandler::set_vertex(int p_vertex_id, const vo
}
void SoftDynamicBodyRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) {
- memcpy(&write_buffer[p_vertex_id * stride + offset_normal], p_vector3, sizeof(float) * 3);
+ // Store normal vector in A2B10G10R10 format.
+ Vector3 n;
+ memcpy(&n, p_vector3, sizeof(Vector3));
+ n *= Vector3(0.5, 0.5, 0.5);
+ n += Vector3(0.5, 0.5, 0.5);
+ uint32_t value = 0;
+ value |= CLAMP(int(n.x * 1023.0), 0, 1023);
+ value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
+ memcpy(&write_buffer[p_vertex_id * stride + offset_normal], &value, sizeof(uint32_t));
}
void SoftDynamicBodyRenderingServerHandler::set_aabb(const AABB &p_aabb) {
diff --git a/scene/3d/soft_dynamic_body_3d.h b/scene/3d/soft_dynamic_body_3d.h
index e11e5c73df..04f3365f72 100644
--- a/scene/3d/soft_dynamic_body_3d.h
+++ b/scene/3d/soft_dynamic_body_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SOFT_DYNAMIC_BODY_H
-#define SOFT_DYNAMIC_BODY_H
+#ifndef SOFT_DYNAMIC_BODY_3D_H
+#define SOFT_DYNAMIC_BODY_3D_H
#include "scene/3d/mesh_instance_3d.h"
#include "servers/physics_server_3d.h"
@@ -199,4 +199,4 @@ private:
VARIANT_ENUM_CAST(SoftDynamicBody3D::DisableMode);
-#endif // SOFT_DYNAMIC_BODY_H
+#endif // SOFT_DYNAMIC_BODY_3D_H
diff --git a/scene/3d/spring_arm_3d.h b/scene/3d/spring_arm_3d.h
index 0b5307acf7..1a6f03abe4 100644
--- a/scene/3d/spring_arm_3d.h
+++ b/scene/3d/spring_arm_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SPRING_ARM_H
-#define SPRING_ARM_H
+#ifndef SPRING_ARM_3D_H
+#define SPRING_ARM_3D_H
#include "scene/3d/node_3d.h"
@@ -68,4 +68,4 @@ private:
void process_spring();
};
-#endif
+#endif // SPRING_ARM_3D_H
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 55b55d924c..ef2b9e1ce5 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -377,7 +377,7 @@ SpriteBase3D::SpriteBase3D() {
RS::get_singleton()->material_set_param(material, "uv1_scale", Vector3(1, 1, 1));
RS::get_singleton()->material_set_param(material, "uv2_offset", Vector3(0, 0, 0));
RS::get_singleton()->material_set_param(material, "uv2_scale", Vector3(1, 1, 1));
- RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.98);
+ RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.5);
mesh = RenderingServer::get_singleton()->mesh_create();
@@ -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/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h
index 0ef8bd7482..2f3a37af2a 100644
--- a/scene/3d/vehicle_body_3d.h
+++ b/scene/3d/vehicle_body_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VEHICLE_BODY_H
-#define VEHICLE_BODY_H
+#ifndef VEHICLE_BODY_3D_H
+#define VEHICLE_BODY_3D_H
#include "scene/3d/physics_body_3d.h"
@@ -210,4 +210,4 @@ public:
VehicleBody3D();
};
-#endif // VEHICLE_BODY_H
+#endif // VEHICLE_BODY_3D_H
diff --git a/scene/3d/velocity_tracker_3d.h b/scene/3d/velocity_tracker_3d.h
index 7fdcacc9c1..6b27cdffc2 100644
--- a/scene/3d/velocity_tracker_3d.h
+++ b/scene/3d/velocity_tracker_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SPATIAL_VELOCITY_TRACKER_H
-#define SPATIAL_VELOCITY_TRACKER_H
+#ifndef VELOCITY_TRACKER_3D_H
+#define VELOCITY_TRACKER_3D_H
#include "scene/3d/node_3d.h"
@@ -58,4 +58,4 @@ public:
VelocityTracker3D();
};
-#endif // SPATIAL_VELOCITY_TRACKER_H
+#endif // VELOCITY_TRACKER_3D_H
diff --git a/scene/3d/visible_on_screen_notifier_3d.h b/scene/3d/visible_on_screen_notifier_3d.h
index fe17f1e444..60461569f4 100644
--- a/scene/3d/visible_on_screen_notifier_3d.h
+++ b/scene/3d/visible_on_screen_notifier_3d.h
@@ -96,4 +96,4 @@ public:
VARIANT_ENUM_CAST(VisibleOnScreenEnabler3D::EnableMode);
-#endif // VISIBILITY_NOTIFIER_H
+#endif // VISIBLE_ON_SCREEN_NOTIFIER_3D_H
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index 69917f6992..5af06cff29 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -227,8 +227,8 @@ const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringNa
StringName *r = instance_uniform_property_remap.getptr(p_name);
if (!r) {
String s = p_name;
- if (s.begins_with("shader_params/")) {
- StringName name = s.replace("shader_params/", "");
+ if (s.begins_with("shader_uniforms/")) {
+ StringName name = s.replace("shader_uniforms/", "");
instance_uniform_property_remap[p_name] = name;
return instance_uniform_property_remap.getptr(p_name);
}
@@ -242,7 +242,7 @@ const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringNa
bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) {
const StringName *r = _instance_uniform_get_remap(p_name);
if (r) {
- set_shader_instance_uniform(*r, p_value);
+ set_instance_shader_uniform(*r, p_value);
return true;
}
#ifndef DISABLE_DEPRECATED
@@ -262,7 +262,7 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value)
bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
const StringName *r = _instance_uniform_get_remap(p_name);
if (r) {
- r_ret = get_shader_instance_uniform(*r);
+ r_ret = get_instance_shader_uniform(*r);
return true;
}
@@ -271,10 +271,10 @@ bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
List<PropertyInfo> pinfo;
- RS::get_singleton()->instance_geometry_get_shader_parameter_list(get_instance(), &pinfo);
+ RS::get_singleton()->instance_geometry_get_shader_uniform_list(get_instance(), &pinfo);
for (PropertyInfo &pi : pinfo) {
bool has_def_value = false;
- Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), pi.name);
+ Variant def_value = RS::get_singleton()->instance_geometry_get_shader_uniform_default_value(get_instance(), pi.name);
if (def_value.get_type() != Variant::NIL) {
has_def_value = true;
}
@@ -284,7 +284,7 @@ void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
pi.usage = PROPERTY_USAGE_EDITOR | (has_def_value ? PROPERTY_USAGE_CHECKABLE : PROPERTY_USAGE_NONE); //do not save if not changed
}
- pi.name = "shader_params/" + pi.name;
+ pi.name = "shader_uniforms/" + pi.name;
p_list->push_back(pi);
}
}
@@ -319,24 +319,24 @@ float GeometryInstance3D::get_lod_bias() const {
return lod_bias;
}
-void GeometryInstance3D::set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value) {
+void GeometryInstance3D::set_instance_shader_uniform(const StringName &p_uniform, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
- Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), p_uniform);
- RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, def_value);
+ Variant def_value = RS::get_singleton()->instance_geometry_get_shader_uniform_default_value(get_instance(), p_uniform);
+ RS::get_singleton()->instance_geometry_set_shader_uniform(get_instance(), p_uniform, def_value);
instance_uniforms.erase(p_value);
} else {
instance_uniforms[p_uniform] = p_value;
if (p_value.get_type() == Variant::OBJECT) {
RID tex_id = p_value;
- RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, tex_id);
+ RS::get_singleton()->instance_geometry_set_shader_uniform(get_instance(), p_uniform, tex_id);
} else {
- RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, p_value);
+ RS::get_singleton()->instance_geometry_set_shader_uniform(get_instance(), p_uniform, p_value);
}
}
}
-Variant GeometryInstance3D::get_shader_instance_uniform(const StringName &p_uniform) const {
- return RS::get_singleton()->instance_geometry_get_shader_parameter(get_instance(), p_uniform);
+Variant GeometryInstance3D::get_instance_shader_uniform(const StringName &p_uniform) const {
+ return RS::get_singleton()->instance_geometry_get_shader_uniform(get_instance(), p_uniform);
}
void GeometryInstance3D::set_custom_aabb(AABB aabb) {
@@ -434,8 +434,8 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_visibility_range_fade_mode", "mode"), &GeometryInstance3D::set_visibility_range_fade_mode);
ClassDB::bind_method(D_METHOD("get_visibility_range_fade_mode"), &GeometryInstance3D::get_visibility_range_fade_mode);
- ClassDB::bind_method(D_METHOD("set_shader_instance_uniform", "uniform", "value"), &GeometryInstance3D::set_shader_instance_uniform);
- ClassDB::bind_method(D_METHOD("get_shader_instance_uniform", "uniform"), &GeometryInstance3D::get_shader_instance_uniform);
+ ClassDB::bind_method(D_METHOD("set_instance_shader_uniform", "uniform", "value"), &GeometryInstance3D::set_instance_shader_uniform);
+ ClassDB::bind_method(D_METHOD("get_instance_shader_uniform", "uniform"), &GeometryInstance3D::get_instance_shader_uniform);
ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance3D::set_extra_cull_margin);
ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance3D::get_extra_cull_margin);
@@ -461,15 +461,16 @@ void GeometryInstance3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01,suffix:m"), "set_extra_cull_margin", "get_extra_cull_margin");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_occlusion_culling"), "set_ignore_occlusion_culling", "is_ignoring_occlusion_culling");
+
ADD_GROUP("Global Illumination", "gi_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI only)"), "set_gi_mode", "get_gi_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, String::utf8("1×,2×,4×,8×")), "set_lightmap_scale", "get_lightmap_scale");
ADD_GROUP("Visibility Range", "visibility_range_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_begin", "get_visibility_range_begin");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_begin_margin", "get_visibility_range_begin_margin");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_end", "get_visibility_range_end");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,suffix:m"), "set_visibility_range_end_margin", "get_visibility_range_end_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_visibility_range_begin", "get_visibility_range_begin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_visibility_range_begin_margin", "get_visibility_range_begin_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_visibility_range_end", "get_visibility_range_end");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01,or_greater,suffix:m"), "set_visibility_range_end_margin", "get_visibility_range_end_margin");
ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_range_fade_mode", PROPERTY_HINT_ENUM, "Disabled,Self,Dependencies"), "set_visibility_range_fade_mode", "get_visibility_range_fade_mode");
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF);
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index 9e0d9b9a2a..f7cdcbf411 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VISUAL_INSTANCE_H
-#define VISUAL_INSTANCE_H
+#ifndef VISUAL_INSTANCE_3D_H
+#define VISUAL_INSTANCE_3D_H
#include "scene/3d/node_3d.h"
@@ -178,8 +178,8 @@ public:
void set_lightmap_scale(LightmapScale p_scale);
LightmapScale get_lightmap_scale() const;
- void set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value);
- Variant get_shader_instance_uniform(const StringName &p_uniform) const;
+ void set_instance_shader_uniform(const StringName &p_uniform, const Variant &p_value);
+ Variant get_instance_shader_uniform(const StringName &p_uniform) const;
void set_custom_aabb(AABB aabb);
@@ -196,4 +196,4 @@ VARIANT_ENUM_CAST(GeometryInstance3D::LightmapScale);
VARIANT_ENUM_CAST(GeometryInstance3D::GIMode);
VARIANT_ENUM_CAST(GeometryInstance3D::VisibilityRangeFadeMode);
-#endif
+#endif // VISUAL_INSTANCE_3D_H
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/3d/voxel_gi.h b/scene/3d/voxel_gi.h
index e1a38dd7a0..6d173dea87 100644
--- a/scene/3d/voxel_gi.h
+++ b/scene/3d/voxel_gi.h
@@ -49,9 +49,9 @@ class VoxelGIData : public Resource {
float energy = 1.0;
float bias = 1.5;
float normal_bias = 0.0;
- float propagation = 0.7;
+ float propagation = 0.5;
bool interior = false;
- bool use_two_bounces = false;
+ bool use_two_bounces = true;
protected:
static void _bind_methods();
diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h
index 0179795ddc..68bce768b7 100644
--- a/scene/3d/voxelizer.h
+++ b/scene/3d/voxelizer.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VOXEL_LIGHT_BAKER_H
-#define VOXEL_LIGHT_BAKER_H
+#ifndef VOXELIZER_H
+#define VOXELIZER_H
#include "scene/resources/multimesh.h"
@@ -129,4 +129,4 @@ public:
Voxelizer();
};
-#endif // VOXEL_LIGHT_BAKER_H
+#endif // VOXELIZER_H
diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h
index 8dbb57364c..9955aa72a8 100644
--- a/scene/3d/world_environment.h
+++ b/scene/3d/world_environment.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SCENARIO_FX_H
-#define SCENARIO_FX_H
+#ifndef WORLD_ENVIRONMENT_H
+#define WORLD_ENVIRONMENT_H
#include "scene/main/node.h"
#include "scene/resources/camera_effects.h"
@@ -60,4 +60,4 @@ public:
WorldEnvironment();
};
-#endif
+#endif // WORLD_ENVIRONMENT_H
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index 1dad6078b4..40a43043c6 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -120,7 +120,7 @@ Vector3 XRCamera3D::project_local_ray_normal(const Point2 &p_pos) const {
Vector3 ray;
// Just use the first view, if multiple views are supported this function has no good result
- CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
+ Projection cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
Vector2 screen_he = cm.get_viewport_half_extents();
ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -get_near()).normalized();
@@ -143,7 +143,7 @@ Point2 XRCamera3D::unproject_position(const Vector3 &p_pos) const {
Size2 viewport_size = get_viewport()->get_visible_rect().size;
// Just use the first view, if multiple views are supported this function has no good result
- CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
+ Projection cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
Plane p(get_camera_transform().xform_inv(p_pos), 1.0);
@@ -173,7 +173,7 @@ Vector3 XRCamera3D::project_position(const Point2 &p_point, real_t p_z_depth) co
Size2 viewport_size = get_viewport()->get_visible_rect().size;
// Just use the first view, if multiple views are supported this function has no good result
- CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
+ Projection cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
Vector2 vp_he = cm.get_viewport_half_extents();
@@ -202,7 +202,7 @@ Vector<Plane> XRCamera3D::get_frustum() const {
Size2 viewport_size = get_viewport()->get_visible_rect().size;
// TODO Just use the first view for now, this is mostly for debugging so we may look into using our combined projection here.
- CameraMatrix cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
+ Projection cm = xr_interface->get_projection_for_view(0, viewport_size.aspect(), get_near(), get_far());
return cm.get_projection_planes(get_camera_transform());
};
diff --git a/scene/SCsub b/scene/SCsub
index a7b23af598..92288211bb 100644
--- a/scene/SCsub
+++ b/scene/SCsub
@@ -9,7 +9,6 @@ env.add_source_files(env.scene_sources, "*.cpp")
# Chain load SCsubs
SConscript("main/SCsub")
-SConscript("multiplayer/SCsub")
SConscript("gui/SCsub")
if not env["disable_3d"]:
SConscript("3d/SCsub")
diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp
index 594f98410e..b42e426f51 100644
--- a/scene/animation/animation_blend_space_1d.cpp
+++ b/scene/animation/animation_blend_space_1d.cpp
@@ -78,6 +78,9 @@ void AnimationNodeBlendSpace1D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_value_label", "text"), &AnimationNodeBlendSpace1D::set_value_label);
ClassDB::bind_method(D_METHOD("get_value_label"), &AnimationNodeBlendSpace1D::get_value_label);
+ ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace1D::set_use_sync);
+ ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace1D::is_using_sync);
+
ClassDB::bind_method(D_METHOD("_add_blend_point", "index", "node"), &AnimationNodeBlendSpace1D::_add_blend_point);
for (int i = 0; i < MAX_BLEND_POINTS; i++) {
@@ -89,6 +92,7 @@ void AnimationNodeBlendSpace1D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_space", "get_max_space");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_value_label", "get_value_label");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync");
}
void AnimationNodeBlendSpace1D::get_child_nodes(List<ChildNode> *r_child_nodes) {
@@ -117,7 +121,7 @@ void AnimationNodeBlendSpace1D::add_blend_point(const Ref<AnimationRootNode> &p_
blend_points[p_at_index].node = p_node;
blend_points[p_at_index].position = p_position;
- blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), CONNECT_REFERENCE_COUNTED);
blend_points_used++;
emit_signal(SNAME("tree_changed"));
@@ -138,7 +142,7 @@ void AnimationNodeBlendSpace1D::set_blend_point_node(int p_point, const Ref<Anim
}
blend_points[p_point].node = p_node;
- blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), CONNECT_REFERENCE_COUNTED);
emit_signal(SNAME("tree_changed"));
}
@@ -211,6 +215,14 @@ String AnimationNodeBlendSpace1D::get_value_label() const {
return value_label;
}
+void AnimationNodeBlendSpace1D::set_use_sync(bool p_sync) {
+ sync = p_sync;
+}
+
+bool AnimationNodeBlendSpace1D::is_using_sync() const {
+ return sync;
+}
+
void AnimationNodeBlendSpace1D::_add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node) {
if (p_index == blend_points_used) {
add_blend_point(p_node, 0);
@@ -226,7 +238,7 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_see
if (blend_points_used == 1) {
// only one point available, just play that animation
- return blend_node(blend_points[0].name, blend_points[0].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false);
+ return blend_node(blend_points[0].name, blend_points[0].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true);
}
double blend_pos = get_parameter(blend_position);
@@ -295,9 +307,12 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_see
double max_time_remaining = 0.0;
for (int i = 0; i < blend_points_used; i++) {
- double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, weights[i], FILTER_IGNORE, false);
-
- max_time_remaining = MAX(max_time_remaining, remaining);
+ if (i == point_lower || i == point_higher) {
+ double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, weights[i], FILTER_IGNORE, true);
+ max_time_remaining = MAX(max_time_remaining, remaining);
+ } else {
+ blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync);
+ }
}
return max_time_remaining;
diff --git a/scene/animation/animation_blend_space_1d.h b/scene/animation/animation_blend_space_1d.h
index b2075c8c93..346e8a3a2f 100644
--- a/scene/animation/animation_blend_space_1d.h
+++ b/scene/animation/animation_blend_space_1d.h
@@ -63,6 +63,8 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode {
StringName blend_position = "blend_position";
protected:
+ bool sync = false;
+
virtual void _validate_property(PropertyInfo &property) const override;
static void _bind_methods();
@@ -93,6 +95,9 @@ public:
void set_value_label(const String &p_label);
String get_value_label() const;
+ void set_use_sync(bool p_sync);
+ bool is_using_sync() const;
+
double process(double p_time, bool p_seek, bool p_seek_root) override;
String get_caption() const override;
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index acdce2d7de..6b5851a977 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -80,7 +80,7 @@ void AnimationNodeBlendSpace2D::add_blend_point(const Ref<AnimationRootNode> &p_
blend_points[p_at_index].node = p_node;
blend_points[p_at_index].position = p_position;
- blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), CONNECT_REFERENCE_COUNTED);
blend_points_used++;
_queue_auto_triangles();
@@ -102,7 +102,7 @@ void AnimationNodeBlendSpace2D::set_blend_point_node(int p_point, const Ref<Anim
blend_points[p_point].node->disconnect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed));
}
blend_points[p_point].node = p_node;
- blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), CONNECT_REFERENCE_COUNTED);
emit_signal(SNAME("tree_changed"));
}
@@ -502,7 +502,7 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see
for (int j = 0; j < 3; j++) {
if (i == triangle_points[j]) {
//blend with the given weight
- double t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, blend_weights[j], FILTER_IGNORE, false);
+ double t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, blend_weights[j], FILTER_IGNORE, true);
if (first || t < mind) {
mind = t;
first = false;
@@ -513,8 +513,7 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see
}
if (!found) {
- //ignore
- blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, false);
+ blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync);
}
}
} else {
@@ -539,16 +538,22 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see
na_n->set_backward(na_c->is_backward());
}
//see how much animation remains
- from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, p_seek_root, 0.0, FILTER_IGNORE, false);
+ from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, p_seek_root, 0.0, FILTER_IGNORE, true);
}
- mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_seek_root, 1.0, FILTER_IGNORE, false);
+ mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_seek_root, 1.0, FILTER_IGNORE, true);
length_internal = from + mind;
closest = new_closest;
} else {
- mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false);
+ mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true);
+ }
+
+ for (int i = 0; i < blend_points_used; i++) {
+ if (i != closest) {
+ blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync);
+ }
}
}
@@ -604,6 +609,14 @@ AnimationNodeBlendSpace2D::BlendMode AnimationNodeBlendSpace2D::get_blend_mode()
return blend_mode;
}
+void AnimationNodeBlendSpace2D::set_use_sync(bool p_sync) {
+ sync = p_sync;
+}
+
+bool AnimationNodeBlendSpace2D::is_using_sync() const {
+ return sync;
+}
+
void AnimationNodeBlendSpace2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_blend_point", "node", "pos", "at_index"), &AnimationNodeBlendSpace2D::add_blend_point, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("set_blend_point_position", "point", "pos"), &AnimationNodeBlendSpace2D::set_blend_point_position);
@@ -644,6 +657,9 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_blend_mode", "mode"), &AnimationNodeBlendSpace2D::set_blend_mode);
ClassDB::bind_method(D_METHOD("get_blend_mode"), &AnimationNodeBlendSpace2D::get_blend_mode);
+ ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace2D::set_use_sync);
+ ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace2D::is_using_sync);
+
ClassDB::bind_method(D_METHOD("_update_triangles"), &AnimationNodeBlendSpace2D::_update_triangles);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_auto_triangles", "get_auto_triangles");
@@ -661,6 +677,7 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "x_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_x_label", "get_x_label");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "y_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_y_label", "get_y_label");
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NO_EDITOR), "set_blend_mode", "get_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync");
ADD_SIGNAL(MethodInfo("triangles_updated"));
BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED);
diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h
index 01f53ed25a..689b96e356 100644
--- a/scene/animation/animation_blend_space_2d.h
+++ b/scene/animation/animation_blend_space_2d.h
@@ -88,6 +88,8 @@ protected:
void _tree_changed();
protected:
+ bool sync = false;
+
virtual void _validate_property(PropertyInfo &property) const override;
static void _bind_methods();
@@ -137,6 +139,9 @@ public:
void set_blend_mode(BlendMode p_blend_mode);
BlendMode get_blend_mode() const;
+ void set_use_sync(bool p_sync);
+ bool is_using_sync() const;
+
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name) override;
AnimationNodeBlendSpace2D();
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 4f6975deb1..fe2fb1b7a1 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -179,6 +179,26 @@ AnimationNodeAnimation::AnimationNodeAnimation() {
////////////////////////////////////////////////////////
+void AnimationNodeSync::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeSync::set_use_sync);
+ ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeSync::is_using_sync);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
+}
+
+void AnimationNodeSync::set_use_sync(bool p_sync) {
+ sync = p_sync;
+}
+
+bool AnimationNodeSync::is_using_sync() const {
+ return sync;
+}
+
+AnimationNodeSync::AnimationNodeSync() {
+}
+
+////////////////////////////////////////////////////////
+
void AnimationNodeOneShot::get_parameter_list(List<PropertyInfo> *r_list) const {
r_list->push_back(PropertyInfo(Variant::BOOL, active));
r_list->push_back(PropertyInfo(Variant::BOOL, prev_active, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
@@ -276,7 +296,7 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo
}
if (!active) {
- return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync);
+ return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, sync);
}
}
@@ -313,12 +333,12 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo
double main_rem;
if (mix == MIX_MODE_ADD) {
- main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync);
+ main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, sync);
} else {
- main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_BLEND, !sync);
+ main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_BLEND, sync);
}
- double os_rem = blend_input(1, os_seek ? time : p_time, os_seek, p_seek_root, blend, FILTER_PASS, false);
+ double os_rem = blend_input(1, os_seek ? time : p_time, os_seek, p_seek_root, blend, FILTER_PASS, true);
if (do_start) {
remaining = os_rem;
@@ -343,14 +363,6 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo
return MAX(main_rem, remaining);
}
-void AnimationNodeOneShot::set_use_sync(bool p_sync) {
- sync = p_sync;
-}
-
-bool AnimationNodeOneShot::is_using_sync() const {
- return sync;
-}
-
void AnimationNodeOneShot::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fadein_time", "time"), &AnimationNodeOneShot::set_fadein_time);
ClassDB::bind_method(D_METHOD("get_fadein_time"), &AnimationNodeOneShot::get_fadein_time);
@@ -370,9 +382,6 @@ void AnimationNodeOneShot::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mix_mode", "mode"), &AnimationNodeOneShot::set_mix_mode);
ClassDB::bind_method(D_METHOD("get_mix_mode"), &AnimationNodeOneShot::get_mix_mode);
- ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeOneShot::set_use_sync);
- ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeOneShot::is_using_sync);
-
ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_mode", PROPERTY_HINT_ENUM, "Blend,Add"), "set_mix_mode", "get_mix_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadein_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_fadein_time", "get_fadein_time");
@@ -384,9 +393,6 @@ void AnimationNodeOneShot::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_autorestart_delay", "get_autorestart_delay");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_random_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_autorestart_random_delay", "get_autorestart_random_delay");
- ADD_GROUP("", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
-
BIND_ENUM_CONSTANT(MIX_MODE_BLEND);
BIND_ENUM_CONSTANT(MIX_MODE_ADD);
}
@@ -410,31 +416,19 @@ String AnimationNodeAdd2::get_caption() const {
return "Add2";
}
-void AnimationNodeAdd2::set_use_sync(bool p_sync) {
- sync = p_sync;
-}
-
-bool AnimationNodeAdd2::is_using_sync() const {
- return sync;
-}
-
bool AnimationNodeAdd2::has_filter() const {
return true;
}
double AnimationNodeAdd2::process(double p_time, bool p_seek, bool p_seek_root) {
double amount = get_parameter(add_amount);
- double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync);
- blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, !sync);
+ double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, sync);
+ blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, sync);
return rem0;
}
void AnimationNodeAdd2::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd2::set_use_sync);
- ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd2::is_using_sync);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
}
AnimationNodeAdd2::AnimationNodeAdd2() {
@@ -456,32 +450,20 @@ String AnimationNodeAdd3::get_caption() const {
return "Add3";
}
-void AnimationNodeAdd3::set_use_sync(bool p_sync) {
- sync = p_sync;
-}
-
-bool AnimationNodeAdd3::is_using_sync() const {
- return sync;
-}
-
bool AnimationNodeAdd3::has_filter() const {
return true;
}
double AnimationNodeAdd3::process(double p_time, bool p_seek, bool p_seek_root) {
double amount = get_parameter(add_amount);
- blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_PASS, !sync);
- double rem0 = blend_input(1, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync);
- blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_PASS, !sync);
+ blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_PASS, sync);
+ double rem0 = blend_input(1, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, sync);
+ blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_PASS, sync);
return rem0;
}
void AnimationNodeAdd3::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd3::set_use_sync);
- ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd3::is_using_sync);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
}
AnimationNodeAdd3::AnimationNodeAdd3() {
@@ -507,29 +489,17 @@ String AnimationNodeBlend2::get_caption() const {
double AnimationNodeBlend2::process(double p_time, bool p_seek, bool p_seek_root) {
double amount = get_parameter(blend_amount);
- double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - amount, FILTER_BLEND, !sync);
- double rem1 = blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, !sync);
+ double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - amount, FILTER_BLEND, sync);
+ double rem1 = blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, sync);
return amount > 0.5 ? rem1 : rem0; //hacky but good enough
}
-void AnimationNodeBlend2::set_use_sync(bool p_sync) {
- sync = p_sync;
-}
-
-bool AnimationNodeBlend2::is_using_sync() const {
- return sync;
-}
-
bool AnimationNodeBlend2::has_filter() const {
return true;
}
void AnimationNodeBlend2::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend2::set_use_sync);
- ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend2::is_using_sync);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
}
AnimationNodeBlend2::AnimationNodeBlend2() {
@@ -551,35 +521,22 @@ String AnimationNodeBlend3::get_caption() const {
return "Blend3";
}
-void AnimationNodeBlend3::set_use_sync(bool p_sync) {
- sync = p_sync;
-}
-
-bool AnimationNodeBlend3::is_using_sync() const {
- return sync;
-}
-
double AnimationNodeBlend3::process(double p_time, bool p_seek, bool p_seek_root) {
double amount = get_parameter(blend_amount);
- double rem0 = blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_IGNORE, !sync);
- double rem1 = blend_input(1, p_time, p_seek, p_seek_root, 1.0 - ABS(amount), FILTER_IGNORE, !sync);
- double rem2 = blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_IGNORE, !sync);
+ double rem0 = blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_IGNORE, sync);
+ double rem1 = blend_input(1, p_time, p_seek, p_seek_root, 1.0 - ABS(amount), FILTER_IGNORE, sync);
+ double rem2 = blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_IGNORE, sync);
return amount > 0.5 ? rem2 : (amount < -0.5 ? rem0 : rem1); //hacky but good enough
}
void AnimationNodeBlend3::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend3::set_use_sync);
- ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend3::is_using_sync);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
}
AnimationNodeBlend3::AnimationNodeBlend3() {
add_input("-blend");
add_input("in");
add_input("+blend");
- sync = false;
}
/////////////////////////////////
@@ -599,9 +556,9 @@ String AnimationNodeTimeScale::get_caption() const {
double AnimationNodeTimeScale::process(double p_time, bool p_seek, bool p_seek_root) {
double scale = get_parameter(this->scale);
if (p_seek) {
- return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, false);
+ return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, true);
} else {
- return blend_input(0, p_time * scale, false, p_seek_root, 1.0, FILTER_IGNORE, false);
+ return blend_input(0, p_time * scale, false, p_seek_root, 1.0, FILTER_IGNORE, true);
}
}
@@ -629,13 +586,13 @@ String AnimationNodeTimeSeek::get_caption() const {
double AnimationNodeTimeSeek::process(double p_time, bool p_seek, bool p_seek_root) {
double seek_pos = get_parameter(this->seek_pos);
if (p_seek) {
- return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, false);
+ return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, true);
} else if (seek_pos >= 0) {
- double ret = blend_input(0, seek_pos, true, true, 1.0, FILTER_IGNORE, false);
+ double ret = blend_input(0, seek_pos, true, true, 1.0, FILTER_IGNORE, true);
set_parameter(this->seek_pos, -1.0); //reset
return ret;
} else {
- return blend_input(0, p_time, false, p_seek_root, 1.0, FILTER_IGNORE, false);
+ return blend_input(0, p_time, false, p_seek_root, 1.0, FILTER_IGNORE, true);
}
}
@@ -727,6 +684,14 @@ float AnimationNodeTransition::get_cross_fade_time() const {
return xfade;
}
+void AnimationNodeTransition::set_from_start(bool p_from_start) {
+ from_start = p_from_start;
+}
+
+bool AnimationNodeTransition::is_from_start() const {
+ return from_start;
+}
+
double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_root) {
int current = get_parameter(this->current);
int prev = get_parameter(this->prev);
@@ -753,9 +718,15 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_
double rem = 0.0;
+ for (int i = 0; i < enabled_inputs; i++) {
+ if (i != current && i != prev) {
+ blend_input(i, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync);
+ }
+ }
+
if (prev < 0) { // process current animation, check for transition
- rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false);
+ rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true);
if (p_seek) {
time = p_time;
@@ -771,18 +742,18 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_
float blend = xfade == 0 ? 0 : (prev_xfading / xfade);
- if (!p_seek && switched) { //just switched, seek to start of current
+ if (from_start && !p_seek && switched) { //just switched, seek to start of current
- rem = blend_input(current, 0, true, p_seek_root, 1.0 - blend, FILTER_IGNORE, false);
+ rem = blend_input(current, 0, true, p_seek_root, 1.0 - blend, FILTER_IGNORE, true);
} else {
- rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_IGNORE, false);
+ rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_IGNORE, true);
}
- if (p_seek) { // don't seek prev animation
- blend_input(prev, 0, false, p_seek_root, blend, FILTER_IGNORE, false);
+ if (p_seek) {
+ blend_input(prev, p_time, true, p_seek_root, blend, FILTER_IGNORE, true);
time = p_time;
} else {
- blend_input(prev, p_time, false, p_seek_root, blend, FILTER_IGNORE, false);
+ blend_input(prev, p_time, false, p_seek_root, blend, FILTER_IGNORE, true);
time += p_time;
prev_xfading -= p_time;
if (prev_xfading < 0) {
@@ -824,8 +795,12 @@ void AnimationNodeTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_cross_fade_time", "time"), &AnimationNodeTransition::set_cross_fade_time);
ClassDB::bind_method(D_METHOD("get_cross_fade_time"), &AnimationNodeTransition::get_cross_fade_time);
+ ClassDB::bind_method(D_METHOD("set_from_start", "from_start"), &AnimationNodeTransition::set_from_start);
+ ClassDB::bind_method(D_METHOD("is_from_start"), &AnimationNodeTransition::is_from_start);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_cross_fade_time", "get_cross_fade_time");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "from_start"), "set_from_start", "is_from_start");
for (int i = 0; i < MAX_INPUTS; i++) {
ADD_PROPERTYI(PropertyInfo(Variant::STRING, "input_" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_input_caption", "get_input_caption", i);
@@ -846,7 +821,7 @@ String AnimationNodeOutput::get_caption() const {
}
double AnimationNodeOutput::process(double p_time, bool p_seek, bool p_seek_root) {
- return blend_input(0, p_time, p_seek, p_seek_root, 1.0);
+ return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true);
}
AnimationNodeOutput::AnimationNodeOutput() {
@@ -869,8 +844,8 @@ void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNod
emit_changed();
emit_signal(SNAME("tree_changed"));
- p_node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendTree::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
- p_node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed), varray(p_name), CONNECT_REFERENCE_COUNTED);
+ p_node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendTree::_tree_changed), CONNECT_REFERENCE_COUNTED);
+ p_node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed).bind(p_name), CONNECT_REFERENCE_COUNTED);
}
Ref<AnimationNode> AnimationNodeBlendTree::get_node(const StringName &p_name) const {
@@ -970,7 +945,7 @@ void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringN
}
}
//connection must be done with new name
- nodes[p_new_name].node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed), varray(p_new_name), CONNECT_REFERENCE_COUNTED);
+ nodes[p_new_name].node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed).bind(p_new_name), CONNECT_REFERENCE_COUNTED);
emit_signal(SNAME("tree_changed"));
}
@@ -1060,7 +1035,7 @@ String AnimationNodeBlendTree::get_caption() const {
double AnimationNodeBlendTree::process(double p_time, bool p_seek, bool p_seek_root) {
Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output].node;
- return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, p_seek_root, 1.0);
+ return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true);
}
void AnimationNodeBlendTree::get_node_list(List<StringName> *r_list) {
diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h
index 0a2305b8d6..d35ff04f30 100644
--- a/scene/animation/animation_blend_tree.h
+++ b/scene/animation/animation_blend_tree.h
@@ -77,8 +77,23 @@ private:
VARIANT_ENUM_CAST(AnimationNodeAnimation::PlayMode)
-class AnimationNodeOneShot : public AnimationNode {
- GDCLASS(AnimationNodeOneShot, AnimationNode);
+class AnimationNodeSync : public AnimationNode {
+ GDCLASS(AnimationNodeSync, AnimationNode);
+
+protected:
+ bool sync = false;
+
+ static void _bind_methods();
+
+public:
+ void set_use_sync(bool p_sync);
+ bool is_using_sync() const;
+
+ AnimationNodeSync();
+};
+
+class AnimationNodeOneShot : public AnimationNodeSync {
+ GDCLASS(AnimationNodeOneShot, AnimationNodeSync);
public:
enum MixMode {
@@ -95,8 +110,6 @@ private:
float autorestart_random_delay = 0.0;
MixMode mix = MIX_MODE_BLEND;
- bool sync = false;
-
/* bool active;
bool do_start;
float time;
@@ -134,9 +147,6 @@ public:
void set_mix_mode(MixMode p_mix);
MixMode get_mix_mode() const;
- void set_use_sync(bool p_sync);
- bool is_using_sync() const;
-
virtual bool has_filter() const override;
virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
@@ -145,11 +155,10 @@ public:
VARIANT_ENUM_CAST(AnimationNodeOneShot::MixMode)
-class AnimationNodeAdd2 : public AnimationNode {
- GDCLASS(AnimationNodeAdd2, AnimationNode);
+class AnimationNodeAdd2 : public AnimationNodeSync {
+ GDCLASS(AnimationNodeAdd2, AnimationNodeSync);
StringName add_amount = PNAME("add_amount");
- bool sync = false;
protected:
static void _bind_methods();
@@ -160,20 +169,16 @@ public:
virtual String get_caption() const override;
- void set_use_sync(bool p_sync);
- bool is_using_sync() const;
-
virtual bool has_filter() const override;
virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
AnimationNodeAdd2();
};
-class AnimationNodeAdd3 : public AnimationNode {
- GDCLASS(AnimationNodeAdd3, AnimationNode);
+class AnimationNodeAdd3 : public AnimationNodeSync {
+ GDCLASS(AnimationNodeAdd3, AnimationNodeSync);
StringName add_amount = PNAME("add_amount");
- bool sync = false;
protected:
static void _bind_methods();
@@ -184,20 +189,16 @@ public:
virtual String get_caption() const override;
- void set_use_sync(bool p_sync);
- bool is_using_sync() const;
-
virtual bool has_filter() const override;
virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
AnimationNodeAdd3();
};
-class AnimationNodeBlend2 : public AnimationNode {
- GDCLASS(AnimationNodeBlend2, AnimationNode);
+class AnimationNodeBlend2 : public AnimationNodeSync {
+ GDCLASS(AnimationNodeBlend2, AnimationNodeSync);
StringName blend_amount = PNAME("blend_amount");
- bool sync = false;
protected:
static void _bind_methods();
@@ -209,18 +210,14 @@ public:
virtual String get_caption() const override;
virtual double process(double p_time, bool p_seek, bool p_seek_root) override;
- void set_use_sync(bool p_sync);
- bool is_using_sync() const;
-
virtual bool has_filter() const override;
AnimationNodeBlend2();
};
-class AnimationNodeBlend3 : public AnimationNode {
- GDCLASS(AnimationNodeBlend3, AnimationNode);
+class AnimationNodeBlend3 : public AnimationNodeSync {
+ GDCLASS(AnimationNodeBlend3, AnimationNodeSync);
StringName blend_amount = PNAME("blend_amount");
- bool sync;
protected:
static void _bind_methods();
@@ -231,9 +228,6 @@ public:
virtual String get_caption() const override;
- void set_use_sync(bool p_sync);
- bool is_using_sync() const;
-
double process(double p_time, bool p_seek, bool p_seek_root) override;
AnimationNodeBlend3();
};
@@ -276,8 +270,8 @@ public:
AnimationNodeTimeSeek();
};
-class AnimationNodeTransition : public AnimationNode {
- GDCLASS(AnimationNodeTransition, AnimationNode);
+class AnimationNodeTransition : public AnimationNodeSync {
+ GDCLASS(AnimationNodeTransition, AnimationNodeSync);
enum {
MAX_INPUTS = 32
@@ -304,6 +298,7 @@ class AnimationNodeTransition : public AnimationNode {
StringName prev_current = "prev_current";
float xfade = 0.0;
+ bool from_start = true;
void _update_inputs();
@@ -329,6 +324,9 @@ public:
void set_cross_fade_time(float p_fade);
float get_cross_fade_time() const;
+ void set_from_start(bool p_from_start);
+ bool is_from_start() const;
+
double process(double p_time, bool p_seek, bool p_seek_root) override;
AnimationNodeTransition();
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index 2ee7f4fa43..793967d9ad 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -395,7 +395,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
current = p_state_machine->start_node;
}
- len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 1.0, AnimationNode::FILTER_IGNORE, false);
+ len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 1.0, AnimationNode::FILTER_IGNORE, true);
pos_current = 0;
}
@@ -420,10 +420,10 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
}
}
- float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_seek_root, fade_blend, AnimationNode::FILTER_IGNORE, false);
+ float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_seek_root, fade_blend, AnimationNode::FILTER_IGNORE, true);
if (fading_from != StringName()) {
- p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_seek_root, 1.0 - fade_blend, AnimationNode::FILTER_IGNORE, false);
+ p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_seek_root, 1.0 - fade_blend, AnimationNode::FILTER_IGNORE, true);
}
//guess playback position
@@ -577,12 +577,12 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
}
current = next;
if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_SYNC) {
- len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, false);
+ len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true);
pos_current = MIN(pos_current, len_current);
- p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, false);
+ p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true);
} else {
- len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, false);
+ len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true);
pos_current = 0;
}
@@ -630,7 +630,7 @@ bool AnimationNodeStateMachinePlayback::_check_advance_condition(const Ref<Anima
Node *expression_base = tree_base->get_node_or_null(advance_expression_base_node_path);
if (expression_base) {
Ref<Expression> exp = transition->expression;
- bool ret = exp->execute(Array(), tree_base, false, Engine::get_singleton()->is_editor_hint()); // Avoids allowing the user to crash the system with an expression by only allowing const calls.
+ bool ret = exp->execute(Array(), expression_base, false, Engine::get_singleton()->is_editor_hint()); // Avoids allowing the user to crash the system with an expression by only allowing const calls.
if (!exp->has_execute_failed()) {
if (ret) {
return true;
@@ -723,7 +723,7 @@ void AnimationNodeStateMachine::add_node(const StringName &p_name, Ref<Animation
emit_changed();
emit_signal(SNAME("tree_changed"));
- p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED);
}
void AnimationNodeStateMachine::replace_node(const StringName &p_name, Ref<AnimationNode> p_node) {
@@ -743,7 +743,7 @@ void AnimationNodeStateMachine::replace_node(const StringName &p_name, Ref<Anima
emit_changed();
emit_signal(SNAME("tree_changed"));
- p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED);
}
bool AnimationNodeStateMachine::can_edit_node(const StringName &p_name) const {
@@ -830,20 +830,12 @@ void AnimationNodeStateMachine::rename_node(const StringName &p_name, const Stri
anodesm->state_machine_name = p_new_name;
}
- for (int i = 0; i < transitions.size(); i++) {
- if (transitions[i].local_from == p_name) {
- _rename_transition(transitions[i].from, String(transitions[i].from).replace_first(p_name, p_new_name));
- }
-
- if (transitions[i].local_to == p_name) {
- _rename_transition(transitions[i].to, String(transitions[i].to).replace_first(p_name, p_new_name));
- }
- }
+ _rename_transitions(p_name, p_new_name);
emit_signal("tree_changed");
}
-void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, const StringName &p_new_name) {
+void AnimationNodeStateMachine::_rename_transitions(const StringName &p_name, const StringName &p_new_name) {
if (updating_transitions) {
return;
}
@@ -854,12 +846,16 @@ void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, con
Vector<String> path = String(transitions[i].to).split("/");
if (path.size() > 1) {
if (path[0] == "..") {
- prev_state_machine->_rename_transition(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name);
+ prev_state_machine->_rename_transitions(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name);
} else {
- ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_to].node)->_rename_transition("../" + p_name, "../" + p_new_name);
+ ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_to].node)->_rename_transitions("../" + p_name, "../" + p_new_name);
}
}
+ if (transitions[i].local_from == p_name) {
+ transitions.write[i].local_from = p_new_name;
+ }
+
transitions.write[i].from = p_new_name;
}
@@ -867,12 +863,16 @@ void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, con
Vector<String> path = String(transitions[i].from).split("/");
if (path.size() > 1) {
if (path[0] == "..") {
- prev_state_machine->_rename_transition(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name);
+ prev_state_machine->_rename_transitions(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name);
} else {
- ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_from].node)->_rename_transition("../" + p_name, "../" + p_new_name);
+ ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_from].node)->_rename_transitions("../" + p_name, "../" + p_new_name);
}
}
+ if (transitions[i].local_to == p_name) {
+ transitions.write[i].local_to = p_new_name;
+ }
+
transitions.write[i].to = p_new_name;
}
@@ -1032,7 +1032,7 @@ void AnimationNodeStateMachine::add_transition(const StringName &p_from, const S
tr.local_to = local_to;
tr.transition = p_transition;
- tr.transition->connect("advance_condition_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ tr.transition->connect("advance_condition_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED);
transitions.push_back(tr);
diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h
index d4e58ca3d3..ead914db7a 100644
--- a/scene/animation/animation_node_state_machine.h
+++ b/scene/animation/animation_node_state_machine.h
@@ -185,7 +185,7 @@ private:
void _tree_changed();
void _remove_transition(const Ref<AnimationNodeStateMachineTransition> p_transition);
- void _rename_transition(const StringName &p_name, const StringName &p_new_name);
+ void _rename_transitions(const StringName &p_name, const StringName &p_new_name);
bool _can_connect(const StringName &p_name, Vector<AnimationNodeStateMachine *> p_parents = Vector<AnimationNodeStateMachine *>());
StringName _get_shortest_path(const StringName &p_path) const;
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 2e87dbf9da..636c9e26a5 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -64,7 +64,7 @@ void AnimatedValuesBackup::restore() const {
if (arr.size() == 3) {
Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_position(entry->bone_idx, arr[0]);
Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_rotation(entry->bone_idx, arr[1]);
- Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[0]);
+ Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[2]);
}
}
}
@@ -325,7 +325,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
{
if (!child->is_connected("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed))) {
- child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed), make_binds(child), CONNECT_ONESHOT);
+ child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed).bind(child), CONNECT_ONESHOT);
}
}
@@ -370,6 +370,10 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
node_cache->node_3d = nullptr;
ERR_CONTINUE(node_cache->bone_idx < 0);
}
+ Transform3D rest = node_cache->skeleton->get_bone_rest(bone_idx);
+ node_cache->init_loc = rest.origin;
+ node_cache->init_rot = rest.basis.get_rotation_quaternion();
+ node_cache->init_scale = rest.basis.get_scale();
} else {
// no property, just use spatialnode
node_cache->skeleton = nullptr;
@@ -450,6 +454,23 @@ static void _call_object(Object *p_object, const StringName &p_method, const Vec
}
}
+Variant AnimationPlayer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx) {
+ switch (p_anim->track_get_type(p_track)) {
+#ifndef _3D_DISABLED
+ case Animation::TYPE_POSITION_3D: {
+ if (p_object_idx >= 0) {
+ const Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_object);
+ return Vector3(p_value) * skel->get_motion_scale();
+ }
+ return p_value;
+ } break;
+#endif // _3D_DISABLED
+ default: {
+ } break;
+ }
+ return p_value;
+}
+
void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) {
_ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
@@ -494,14 +515,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (err != OK) {
continue;
}
+ loc = _post_process_key_value(a, i, loc, nc->node_3d, nc->bone_idx);
if (nc->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
cache_update[cache_update_size++] = nc;
nc->accum_pass = accum_pass;
nc->loc_accum = loc;
- nc->rot_accum = Quaternion();
- nc->scale_accum = Vector3();
+ nc->rot_accum = nc->init_rot;
+ nc->scale_accum = nc->init_scale;
} else {
nc->loc_accum = nc->loc_accum.lerp(loc, p_interp);
}
@@ -521,14 +543,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (err != OK) {
continue;
}
+ rot = _post_process_key_value(a, i, rot, nc->node_3d, nc->bone_idx);
if (nc->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
cache_update[cache_update_size++] = nc;
nc->accum_pass = accum_pass;
- nc->loc_accum = Vector3();
+ nc->loc_accum = nc->init_loc;
nc->rot_accum = rot;
- nc->scale_accum = Vector3();
+ nc->scale_accum = nc->init_scale;
} else {
nc->rot_accum = nc->rot_accum.slerp(rot, p_interp);
}
@@ -548,13 +571,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (err != OK) {
continue;
}
+ scale = _post_process_key_value(a, i, scale, nc->node_3d, nc->bone_idx);
if (nc->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
cache_update[cache_update_size++] = nc;
nc->accum_pass = accum_pass;
- nc->loc_accum = Vector3();
- nc->rot_accum = Quaternion();
+ nc->loc_accum = nc->init_loc;
+ nc->rot_accum = nc->init_rot;
nc->scale_accum = scale;
} else {
nc->scale_accum = nc->scale_accum.lerp(scale, p_interp);
@@ -575,6 +599,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (err != OK) {
continue;
}
+ blend = _post_process_key_value(a, i, blend, nc->node_blend_shape, nc->blend_shape_idx);
if (nc->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
@@ -627,9 +652,9 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (p_time < first_key_time) {
double c = Math::ease(p_time / first_key_time, transition);
Variant first_value = a->track_get_key_value(i, first_key);
+ first_value = _post_process_key_value(a, i, first_value, nc->node);
Variant interp_value;
Variant::interpolate(pa->capture, first_value, c, interp_value);
-
if (pa->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX);
cache_update_prop[cache_update_prop_size++] = pa;
@@ -649,6 +674,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (value == Variant()) {
continue;
}
+ value = _post_process_key_value(a, i, value, nc->node);
if (pa->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX);
@@ -665,6 +691,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
for (int &F : indices) {
Variant value = a->track_get_key_value(i, F);
+ value = _post_process_key_value(a, i, value, nc->node);
switch (pa->special) {
case SP_NONE: {
bool valid;
@@ -749,6 +776,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
TrackNodeCache::BezierAnim *ba = &E->value;
real_t bezier = a->bezier_track_interpolate(i, p_time);
+ bezier = _post_process_key_value(a, i, bezier, nc->node);
if (ba->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_bezier_size >= NODE_CACHE_UPDATE_MAX);
cache_update_bezier[cache_update_bezier_size++] = ba;
@@ -1173,11 +1201,15 @@ void AnimationPlayer::_animation_process(double p_delta) {
emit_signal(SceneStringNames::get_singleton()->animation_changed, old, new_name);
}
} else {
- //stop();
playing = false;
_set_process(false);
if (end_notify) {
emit_signal(SceneStringNames::get_singleton()->animation_finished, playback.assigned);
+
+ if (movie_quit_on_finish && OS::get_singleton()->has_feature("movie")) {
+ print_line(vformat("Movie Maker mode is enabled. Quitting on animation finish as requested by: %s", get_path()));
+ get_tree()->quit();
+ }
}
}
end_reached = false;
@@ -1345,9 +1377,9 @@ Error AnimationPlayer::add_animation_library(const StringName &p_name, const Ref
animation_libraries.insert(insert_pos, ald);
- ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name));
- ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name));
- ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_name));
+ ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_name));
+ ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_name));
+ ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_name));
_animation_set_cache_update();
@@ -1385,7 +1417,7 @@ void AnimationPlayer::remove_animation_library(const StringName &p_name) {
}
void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) {
- Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), CONNECT_REFERENCE_COUNTED);
}
void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) {
@@ -1411,9 +1443,9 @@ void AnimationPlayer::rename_animation_library(const StringName &p_name, const S
animation_libraries[i].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added));
animation_libraries[i].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed));
- animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name));
- animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name));
- animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_new_name));
+ animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_new_name));
+ animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_new_name));
+ animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_new_name));
for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[i].library->animations) {
StringName old_name = p_name == StringName() ? K.key : StringName(String(p_name) + "/" + String(K.key));
@@ -1864,6 +1896,14 @@ AnimationPlayer::AnimationMethodCallMode AnimationPlayer::get_method_call_mode()
return method_call_mode;
}
+void AnimationPlayer::set_movie_quit_on_finish_enabled(bool p_enabled) {
+ movie_quit_on_finish = p_enabled;
+}
+
+bool AnimationPlayer::is_movie_quit_on_finish_enabled() const {
+ return movie_quit_on_finish;
+}
+
void AnimationPlayer::_set_process(bool p_process, bool p_force) {
if (processing == p_process && !p_force) {
return;
@@ -2084,6 +2124,9 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_method_call_mode", "mode"), &AnimationPlayer::set_method_call_mode);
ClassDB::bind_method(D_METHOD("get_method_call_mode"), &AnimationPlayer::get_method_call_mode);
+ ClassDB::bind_method(D_METHOD("set_movie_quit_on_finish_enabled"), &AnimationPlayer::set_movie_quit_on_finish_enabled);
+ ClassDB::bind_method(D_METHOD("is_movie_quit_on_finish_enabled"), &AnimationPlayer::is_movie_quit_on_finish_enabled);
+
ClassDB::bind_method(D_METHOD("get_current_animation_position"), &AnimationPlayer::get_current_animation_position);
ClassDB::bind_method(D_METHOD("get_current_animation_length"), &AnimationPlayer::get_current_animation_length);
@@ -2105,6 +2148,8 @@ void AnimationPlayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed", PROPERTY_HINT_RANGE, "-64,64,0.01"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTY(PropertyInfo(Variant::INT, "method_call_mode", PROPERTY_HINT_ENUM, "Deferred,Immediate"), "set_method_call_mode", "get_method_call_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "movie_quit_on_finish"), "set_movie_quit_on_finish_enabled", "is_movie_quit_on_finish_enabled");
+
ADD_SIGNAL(MethodInfo("animation_finished", PropertyInfo(Variant::STRING_NAME, "anim_name")));
ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING_NAME, "old_name"), PropertyInfo(Variant::STRING_NAME, "new_name")));
ADD_SIGNAL(MethodInfo("animation_started", PropertyInfo(Variant::STRING_NAME, "anim_name")));
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index d3eb37a345..b6d8dab1ed 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -109,6 +109,9 @@ private:
bool loc_used = false;
bool rot_used = false;
bool scale_used = false;
+ Vector3 init_loc = Vector3(0, 0, 0);
+ Quaternion init_rot = Quaternion(0, 0, 0, 1);
+ Vector3 init_scale = Vector3(1, 1, 1);
Vector3 loc_accum;
Quaternion rot_accum;
@@ -259,6 +262,7 @@ private:
bool reset_on_save = true;
AnimationProcessCallback process_callback = ANIMATION_PROCESS_IDLE;
AnimationMethodCallMode method_call_mode = ANIMATION_METHOD_CALL_DEFERRED;
+ bool movie_quit_on_finish = false;
bool processing = false;
bool active = true;
@@ -313,6 +317,8 @@ protected:
static void _bind_methods();
+ virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1);
+
public:
StringName find_animation(const Ref<Animation> &p_animation) const;
StringName find_animation_library(const Ref<Animation> &p_animation) const;
@@ -368,6 +374,9 @@ public:
void set_method_call_mode(AnimationMethodCallMode p_mode);
AnimationMethodCallMode get_method_call_mode() const;
+ void set_movie_quit_on_finish_enabled(bool p_enabled);
+ bool is_movie_quit_on_finish_enabled() const;
+
void seek(double p_time, bool p_update = false);
void seek_delta(double p_time, float p_delta);
float get_current_animation_position() const;
@@ -395,4 +404,4 @@ public:
VARIANT_ENUM_CAST(AnimationPlayer::AnimationProcessCallback);
VARIANT_ENUM_CAST(AnimationPlayer::AnimationMethodCallMode);
-#endif
+#endif // ANIMATION_PLAYER_H
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 8c8822ac3f..14cf64afad 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -150,7 +150,7 @@ void AnimationNode::make_invalid(const String &p_reason) {
state->invalid_reasons += String::utf8("• ") + p_reason;
}
-double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_optimize) {
+double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_sync) {
ERR_FAIL_INDEX_V(p_input, inputs.size(), 0);
ERR_FAIL_COND_V(!state, 0);
@@ -169,7 +169,7 @@ double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool
//inputs.write[p_input].last_pass = state->last_pass;
real_t activity = 0.0;
- double ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_optimize, &activity);
+ double ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_sync, &activity);
Vector<AnimationTree::Activity> *activity_ptr = state->tree->input_activity_map.getptr(base_path);
@@ -180,11 +180,11 @@ double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool
return ret;
}
-double AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_optimize) {
- return _blend_node(p_sub_path, Vector<StringName>(), this, p_node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_optimize);
+double AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_sync) {
+ return _blend_node(p_sub_path, Vector<StringName>(), this, p_node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_sync);
}
-double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_optimize, real_t *r_max) {
+double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_sync, real_t *r_max) {
ERR_FAIL_COND_V(!p_node.is_valid(), 0);
ERR_FAIL_COND_V(!state, 0);
@@ -292,9 +292,11 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri
}
// If tracks for blending don't exist for one of the animations, Rest or RESET animation is blended as init animation instead.
- // Then, blend weight is 0 means that the init animation blend weight is 1.
+ // Then blend weight is 0 means that the init animation blend weight is 1.
+ // In that case, processing only the animation with the lacking track will not process the lacking track, and will not properly apply the Reset value.
+ // This means that all tracks which the animations in the branch that may be blended have must be processed.
// Therefore, the blending process must be executed even if the blend weight is 0.
- if (!p_seek && p_optimize && !any_valid) {
+ if (!p_seek && !p_sync && !any_valid) {
return p_node->_pre_process(new_path, new_parent, state, 0, p_seek, p_seek_root, p_connections);
}
return p_node->_pre_process(new_path, new_parent, state, p_time, p_seek, p_seek_root, p_connections);
@@ -428,8 +430,8 @@ void AnimationNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_get_filters"), &AnimationNode::_get_filters);
ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "seek_root", "blend", "pingponged"), &AnimationNode::blend_animation, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "seek_root", "blend", "filter", "optimize"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true));
- ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "seek_root", "blend", "filter", "optimize"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "seek_root", "blend", "filter", "sync"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "seek_root", "blend", "filter", "sync"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true));
ClassDB::bind_method(D_METHOD("set_parameter", "name", "value"), &AnimationNode::set_parameter);
ClassDB::bind_method(D_METHOD("get_parameter", "name"), &AnimationNode::get_parameter);
@@ -587,7 +589,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
}
if (!child->is_connected("tree_exited", callable_mp(this, &AnimationTree::_node_removed))) {
- child->connect("tree_exited", callable_mp(this, &AnimationTree::_node_removed), varray(child));
+ child->connect("tree_exited", callable_mp(this, &AnimationTree::_node_removed).bind(child));
}
switch (track_type) {
@@ -1052,7 +1054,9 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ loc[0] = _post_process_key_value(a, i, loc[0], t->object, t->bone_idx);
a->position_track_interpolate(i, (double)a->get_length(), &loc[1]);
+ loc[1] = _post_process_key_value(a, i, loc[1], t->object, t->bone_idx);
t->loc += (loc[1] - loc[0]) * blend;
prev_time = 0;
}
@@ -1062,7 +1066,9 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ loc[0] = _post_process_key_value(a, i, loc[0], t->object, t->bone_idx);
a->position_track_interpolate(i, 0, &loc[1]);
+ loc[1] = _post_process_key_value(a, i, loc[1], t->object, t->bone_idx);
t->loc += (loc[1] - loc[0]) * blend;
prev_time = (double)a->get_length();
}
@@ -1072,8 +1078,10 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ loc[0] = _post_process_key_value(a, i, loc[0], t->object, t->bone_idx);
a->position_track_interpolate(i, time, &loc[1]);
+ loc[1] = _post_process_key_value(a, i, loc[1], t->object, t->bone_idx);
t->loc += (loc[1] - loc[0]) * blend;
prev_time = !backward ? 0 : (double)a->get_length();
@@ -1090,6 +1098,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ loc = _post_process_key_value(a, i, loc, t->object, t->bone_idx);
t->loc += (loc - t->init_loc) * blend;
}
@@ -1148,7 +1157,9 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ rot[0] = _post_process_key_value(a, i, rot[0], t->object, t->bone_idx);
a->rotation_track_interpolate(i, (double)a->get_length(), &rot[1]);
+ rot[1] = _post_process_key_value(a, i, rot[1], t->object, t->bone_idx);
t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = 0;
}
@@ -1158,6 +1169,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ rot[0] = _post_process_key_value(a, i, rot[0], t->object, t->bone_idx);
a->rotation_track_interpolate(i, 0, &rot[1]);
t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = (double)a->get_length();
@@ -1168,8 +1180,10 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ rot[0] = _post_process_key_value(a, i, rot[0], t->object, t->bone_idx);
a->rotation_track_interpolate(i, time, &rot[1]);
+ rot[1] = _post_process_key_value(a, i, rot[1], t->object, t->bone_idx);
t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = !backward ? 0 : (double)a->get_length();
@@ -1186,6 +1200,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ rot = _post_process_key_value(a, i, rot, t->object, t->bone_idx);
t->rot = (t->rot * Quaternion().slerp(t->init_rot.inverse() * rot, blend)).normalized();
}
@@ -1244,8 +1259,10 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ scale[0] = _post_process_key_value(a, i, scale[0], t->object, t->bone_idx);
a->scale_track_interpolate(i, (double)a->get_length(), &scale[1]);
t->scale += (scale[1] - scale[0]) * blend;
+ scale[1] = _post_process_key_value(a, i, scale[1], t->object, t->bone_idx);
prev_time = 0;
}
} else {
@@ -1254,7 +1271,9 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ scale[0] = _post_process_key_value(a, i, scale[0], t->object, t->bone_idx);
a->scale_track_interpolate(i, 0, &scale[1]);
+ scale[1] = _post_process_key_value(a, i, scale[1], t->object, t->bone_idx);
t->scale += (scale[1] - scale[0]) * blend;
prev_time = (double)a->get_length();
}
@@ -1264,8 +1283,10 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ scale[0] = _post_process_key_value(a, i, scale[0], t->object, t->bone_idx);
a->scale_track_interpolate(i, time, &scale[1]);
+ scale[1] = _post_process_key_value(a, i, scale[1], t->object, t->bone_idx);
t->scale += (scale[1] - scale[0]) * blend;
prev_time = !backward ? 0 : (double)a->get_length();
@@ -1282,6 +1303,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ scale = _post_process_key_value(a, i, scale, t->object, t->bone_idx);
t->scale += (scale - t->init_scale) * blend;
}
@@ -1304,6 +1326,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (err != OK) {
continue;
}
+ value = _post_process_key_value(a, i, value, t->object, t->shape_index);
t->value += (value - t->init_value) * blend;
#endif // _3D_DISABLED
@@ -1315,6 +1338,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) {
Variant value = a->value_track_interpolate(i, time);
+ value = _post_process_key_value(a, i, value, t->object);
if (value == Variant()) {
continue;
@@ -1342,12 +1366,14 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
Variant value = a->track_get_key_value(i, idx);
+ value = _post_process_key_value(a, i, value, t->object);
t->object->set_indexed(t->subpath, value);
} else {
List<int> indices;
a->value_track_get_key_indices(i, time, delta, &indices, pingponged);
for (int &F : indices) {
Variant value = a->track_get_key_value(i, F);
+ value = _post_process_key_value(a, i, value, t->object);
t->object->set_indexed(t->subpath, value);
}
}
@@ -1386,6 +1412,7 @@ void AnimationTree::_process_graph(double p_delta) {
TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track);
real_t bezier = a->bezier_track_interpolate(i, time);
+ bezier = _post_process_key_value(a, i, bezier, t->object);
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
@@ -1661,6 +1688,23 @@ void AnimationTree::_process_graph(double p_delta) {
}
}
+Variant AnimationTree::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx) {
+ switch (p_anim->track_get_type(p_track)) {
+#ifndef _3D_DISABLED
+ case Animation::TYPE_POSITION_3D: {
+ if (p_object_idx >= 0) {
+ const Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_object);
+ return Vector3(p_value) * skel->get_motion_scale();
+ }
+ return p_value;
+ } break;
+#endif // _3D_DISABLED
+ default: {
+ } break;
+ }
+ return p_value;
+}
+
void AnimationTree::advance(real_t p_time) {
_process_graph(p_time);
}
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 0bfe615c9b..99851d140e 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef ANIMATION_GRAPH_PLAYER_H
-#define ANIMATION_GRAPH_PLAYER_H
+#ifndef ANIMATION_TREE_H
+#define ANIMATION_TREE_H
#include "animation_player.h"
#include "scene/3d/node_3d.h"
@@ -99,12 +99,12 @@ public:
Array _get_filters() const;
void _set_filters(const Array &p_filters);
friend class AnimationNodeBlendTree;
- double _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, real_t *r_max = nullptr);
+ double _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true, real_t *r_max = nullptr);
protected:
void blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_seek_root, real_t p_blend, int p_pingponged = 0);
- double blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
- double blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
+ double blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true);
+ double blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true);
void make_invalid(const String &p_reason);
AnimationTree *get_animation_tree() const;
@@ -321,6 +321,8 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1);
+
public:
void set_tree_root(const Ref<AnimationNode> &p_root);
Ref<AnimationNode> get_tree_root() const;
@@ -359,4 +361,4 @@ public:
VARIANT_ENUM_CAST(AnimationTree::AnimationProcessCallback)
-#endif // ANIMATION_GRAPH_PLAYER_H
+#endif // ANIMATION_TREE_H
diff --git a/scene/animation/easing_equations.h b/scene/animation/easing_equations.h
index 6d246c7a93..094829e406 100644
--- a/scene/animation/easing_equations.h
+++ b/scene/animation/easing_equations.h
@@ -402,4 +402,4 @@ static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
}
}; // namespace back
-#endif
+#endif // EASING_EQUATIONS_H
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 5457da472f..dbc71cd9e7 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -464,6 +464,17 @@ Variant Tween::interpolate_variant(Variant p_initial_val, Variant p_delta_val, f
APPLY_EQUATION(columns[2][1]);
return r;
}
+ case Variant::VECTOR4: {
+ Vector4 i = p_initial_val;
+ Vector4 d = p_delta_val;
+ Vector4 r;
+
+ APPLY_EQUATION(x);
+ APPLY_EQUATION(y);
+ APPLY_EQUATION(z);
+ APPLY_EQUATION(w);
+ return r;
+ }
case Variant::QUATERNION: {
Quaternion i = p_initial_val;
@@ -853,7 +864,7 @@ bool CallbackTweener::step(float &r_delta) {
if (elapsed_time >= delay) {
Variant result;
Callable::CallError ce;
- callback.call(nullptr, 0, result, ce);
+ callback.callp(nullptr, 0, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(false, "Error calling method from CallbackTweener: " + Variant::get_callable_error_text(callback, nullptr, 0, ce));
}
@@ -924,7 +935,7 @@ bool MethodTweener::step(float &r_delta) {
Variant result;
Callable::CallError ce;
- callback.call(argptr, 1, result, ce);
+ callback.callp(argptr, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(false, "Error calling method from MethodTweener: " + Variant::get_callable_error_text(callback, argptr, 1, ce));
}
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index 40268405cf..b57ec2e5e7 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -283,4 +283,4 @@ private:
Callable callback;
};
-#endif
+#endif // TWEEN_H
diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp
index efb647af29..04debcab05 100644
--- a/scene/audio/audio_stream_player.cpp
+++ b/scene/audio/audio_stream_player.cpp
@@ -136,7 +136,7 @@ void AudioStreamPlayer::play(float p_from_pos) {
if (stream->is_monophonic() && is_playing()) {
stop();
}
- Ref<AudioStreamPlayback> stream_playback = stream->instance_playback();
+ Ref<AudioStreamPlayback> stream_playback = stream->instantiate_playback();
ERR_FAIL_COND_MSG(stream_playback.is_null(), "Failed to instantiate playback.");
AudioServer::get_singleton()->start_playback_stream(stream_playback, bus, _get_volume_vector(), p_from_pos, pitch_scale);
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index e9c33b1839..4c5a63e52c 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -299,7 +299,7 @@ void SceneDebugger::_save_node(ObjectID id, const String &p_path) {
Ref<PackedScene> ps = memnew(PackedScene);
ps->pack(node);
- ResourceSaver::save(p_path, ps);
+ ResourceSaver::save(ps, p_path);
}
void SceneDebugger::_send_object_id(ObjectID p_id, int p_max_size) {
diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h
index 4ed126d36e..911363f45d 100644
--- a/scene/debugger/scene_debugger.h
+++ b/scene/debugger/scene_debugger.h
@@ -174,4 +174,4 @@ public:
};
#endif
-#endif
+#endif // SCENE_DEBUGGER_H
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index ba3852ec98..7cf8de6432 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -155,4 +155,4 @@ public:
ButtonGroup();
};
-#endif
+#endif // BASE_BUTTON_H
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 1371c9cd57..0a163b65ff 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -34,39 +34,14 @@
#include "servers/rendering_server.h"
Size2 Button::get_minimum_size() const {
- Size2 minsize = text_buf->get_size();
- if (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
- minsize.width = 0;
- }
-
- if (!expand_icon) {
- Ref<Texture2D> _icon;
- if (icon.is_null() && has_theme_icon(SNAME("icon"))) {
- _icon = Control::get_theme_icon(SNAME("icon"));
- } else {
- _icon = icon;
- }
-
- if (!_icon.is_null()) {
- minsize.height = MAX(minsize.height, _icon->get_height());
-
- if (icon_alignment != HORIZONTAL_ALIGNMENT_CENTER) {
- minsize.width += _icon->get_width();
- if (!xl_text.is_empty()) {
- minsize.width += get_theme_constant(SNAME("h_separation"));
- }
- } else {
- minsize.width = MAX(minsize.width, _icon->get_width());
- }
- }
- }
- if (!xl_text.is_empty()) {
- Ref<Font> font = get_theme_font(SNAME("font"));
- float font_height = font->get_height(get_theme_font_size(SNAME("font_size")));
- minsize.height = MAX(font_height, minsize.height);
+ Ref<Texture2D> _icon;
+ if (icon.is_null() && has_theme_icon(SNAME("icon"))) {
+ _icon = Control::get_theme_icon(SNAME("icon"));
+ } else {
+ _icon = icon;
}
- return get_theme_stylebox(SNAME("normal"))->get_minimum_size() + minsize;
+ return get_minimum_size_for_text_and_icon("", _icon);
}
void Button::_set_internal_margin(Side p_side, float p_value) {
@@ -283,7 +258,8 @@ void Button::_notification(int p_what) {
}
if (icon_region.size.width > 0) {
- draw_texture_rect_region(_icon, icon_region, Rect2(Point2(), _icon->get_size()), color_icon);
+ Rect2 icon_region_rounded = Rect2(icon_region.position.round(), icon_region.size.round());
+ draw_texture_rect(_icon, icon_region_rounded, false, color_icon);
}
}
@@ -347,24 +323,67 @@ 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;
}
}
-void Button::_shape() {
+Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Texture2D> p_icon) const {
+ Ref<TextParagraph> paragraph;
+ if (p_text.is_empty()) {
+ paragraph = text_buf;
+ } else {
+ paragraph.instantiate();
+ const_cast<Button *>(this)->_shape(paragraph, p_text);
+ }
+
+ Size2 minsize = paragraph->get_size();
+ if (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
+ minsize.width = 0;
+ }
+
+ if (!expand_icon && !p_icon.is_null()) {
+ minsize.height = MAX(minsize.height, p_icon->get_height());
+
+ if (icon_alignment != HORIZONTAL_ALIGNMENT_CENTER) {
+ minsize.width += p_icon->get_width();
+ if (!xl_text.is_empty() || !p_text.is_empty()) {
+ minsize.width += get_theme_constant(SNAME("hseparation"));
+ }
+ } else {
+ minsize.width = MAX(minsize.width, p_icon->get_width());
+ }
+ }
+
+ if (!xl_text.is_empty() || !p_text.is_empty()) {
+ Ref<Font> font = get_theme_font(SNAME("font"));
+ float font_height = font->get_height(get_theme_font_size(SNAME("font_size")));
+ minsize.height = MAX(font_height, minsize.height);
+ }
+
+ return get_theme_stylebox(SNAME("normal"))->get_minimum_size() + minsize;
+}
+
+void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
+ if (p_paragraph.is_null()) {
+ p_paragraph = text_buf;
+ }
+
+ if (p_text.is_empty()) {
+ p_text = xl_text;
+ }
+
Ref<Font> font = get_theme_font(SNAME("font"));
int font_size = get_theme_font_size(SNAME("font_size"));
- text_buf->clear();
+ p_paragraph->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
- text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
+ p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
- text_buf->set_direction((TextServer::Direction)text_direction);
+ p_paragraph->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->set_text_overrun_behavior(overrun_behavior);
+ p_paragraph->add_string(p_text, font, font_size, language);
+ p_paragraph->set_text_overrun_behavior(overrun_behavior);
}
void Button::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
@@ -409,29 +428,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 +508,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 +515,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 +531,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,11 +538,15 @@ 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) {
text_buf.instantiate();
- text_buf->set_flags(TextServer::BREAK_MANDATORY);
+ text_buf->set_break_flags(TextServer::BREAK_MANDATORY);
set_mouse_filter(MOUSE_FILTER_STOP);
set_text(p_text);
diff --git a/scene/gui/button.h b/scene/gui/button.h
index a1d71195cb..23b5c78166 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;
@@ -55,20 +54,18 @@ private:
HorizontalAlignment icon_alignment = HORIZONTAL_ALIGNMENT_LEFT;
float _internal_margin[4] = {};
- void _shape();
+ void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = "");
protected:
void _set_internal_margin(Side p_side, float p_value);
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;
+ Size2 get_minimum_size_for_text_and_icon(const String &p_text, Ref<Texture2D> p_icon) const;
+
void set_text(const String &p_text);
String get_text() const;
@@ -78,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;
@@ -107,4 +100,4 @@ public:
~Button();
};
-#endif
+#endif // BUTTON_H
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 22e9763929..8968c1cc17 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;
@@ -369,7 +407,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}
/* Ctrl + Hover symbols */
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
if (k->get_keycode() == Key::META) {
#else
if (k->get_keycode() == Key::CTRL) {
@@ -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..08bd91a368 100644
--- a/scene/gui/code_edit.h
+++ b/scene/gui/code_edit.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CODEEDIT_H
-#define CODEEDIT_H
+#ifndef CODE_EDIT_H
+#define CODE_EDIT_H
#include "scene/gui/text_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 */
@@ -428,4 +433,4 @@ public:
VARIANT_ENUM_CAST(CodeEdit::CodeCompletionKind);
-#endif // CODEEDIT_H
+#endif // CODE_EDIT_H
diff --git a/scene/gui/color_mode.cpp b/scene/gui/color_mode.cpp
new file mode 100644
index 0000000000..ebd86e0937
--- /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(margin, size.x)), false);
+ 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(margin, size.x)), false);
+ 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..8cbe14c492 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.
@@ -167,6 +171,9 @@ uniform float v = 1.0;
void fragment() {
float x = UV.x - 0.5;
float y = UV.y - 0.5;
+ float h = atan(y, x) / (2.0 * M_PI);
+ float s = sqrt(x * x + y * y) * 2.0;
+ vec3 col = okhsl_to_srgb(vec3(h, s, v));
x += 0.001;
y += 0.001;
float b = float(sqrt(x * x + y * y) < 0.5);
@@ -176,9 +183,6 @@ void fragment() {
float b3 = float(sqrt(x * x + y * y) < 0.5);
x += 0.002;
float b4 = float(sqrt(x * x + y * y) < 0.5);
- float s = sqrt(x * x + y * y);
- float h = atan(y, x) / (2.0*M_PI);
- vec3 col = okhsl_to_srgb(vec3(h, s, v));
COLOR = vec4(col, (b + b2 + b3 + b4) / 4.00);
})");
}
@@ -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,15 +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) {
- h = color.get_ok_hsl_h();
- s = color.get_ok_hsl_s();
- v = color.get_ok_hsl_l();
- } else {
- h = color.get_h();
- s = color.get_s();
- v = color.get_v();
- }
+ _copy_color_to_hsv();
last_color = color;
}
@@ -353,27 +312,113 @@ 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).bind(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;
+}
+
+void ColorPicker::_copy_color_to_hsv() {
+ 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();
+ } else {
+ h = color.get_h();
+ s = color.get_s();
+ v = color.get_v();
+ }
+}
+
+void ColorPicker::_copy_hsv_to_color() {
+ if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, color.a);
+ } else {
+ color.set_hsv(h, s, v, color.a);
+ }
+}
+
+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 +442,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 +458,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 +507,18 @@ 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;
+
+ _copy_color_to_hsv();
+
_update_controls();
_update_color();
}
ColorPicker::PickerShapeType ColorPicker::get_picker_shape() const {
- return picker_type;
+ return current_shape;
}
inline int ColorPicker::_get_preset_size() {
@@ -500,11 +529,26 @@ void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
ColorPresetButton *btn_preset = memnew(ColorPresetButton(p_color));
btn_preset->set_preset_color(p_color);
btn_preset->set_custom_minimum_size(Size2(p_size, p_size));
- btn_preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input), varray(p_color));
+ btn_preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input).bind(p_color));
btn_preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1)));
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 +608,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) {
@@ -642,8 +654,7 @@ void ColorPicker::_sample_input(const Ref<InputEvent> &p_event) {
const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
if (rect_old.has_point(mb->get_position())) {
// Revert to the old color when left-clicking the old color sample.
- color = old_color;
- _update_color();
+ set_pick_color(old_color);
emit_signal(SNAME("color_changed"), color);
}
}
@@ -690,6 +701,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 +710,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 +772,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 +786,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 +798,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 +824,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 +846,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) {
- circle_mat->set_shader_param("v", v);
+ if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) {
+ circle_mat->set_shader_uniform("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());
@@ -950,16 +900,14 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
v = 1.0 - (y - c->get_position().y - corner_y) / real_size.y;
}
}
+
changing_color = true;
- if (picker_type == SHAPE_OKHSL_CIRCLE) {
- color.set_ok_hsl(h, s, v, color.a);
- } else if (picker_type != SHAPE_OKHSL_CIRCLE) {
- color.set_hsv(h, s, v, color.a);
- }
- last_color = color;
+ _copy_hsv_to_color();
+ last_color = color;
set_pick_color(color);
_update_color();
+
if (!deferred_mode_enabled) {
emit_signal(SNAME("color_changed"), color);
}
@@ -981,7 +929,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,14 +950,12 @@ 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) {
- color.set_hsv(h, s, v, color.a);
- } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
- color.set_ok_hsl(h, s, v, color.a);
- }
+
+ _copy_hsv_to_color();
last_color = color;
set_pick_color(color);
_update_color();
+
if (!deferred_mode_enabled) {
emit_signal(SNAME("color_changed"), color);
}
@@ -1018,12 +964,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,14 +978,12 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
} else {
changing_color = false;
}
- if (picker_type != SHAPE_OKHSL_CIRCLE) {
- color.set_hsv(h, s, v, color.a);
- } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
- color.set_ok_hsl(h, s, v, color.a);
- }
+
+ _copy_hsv_to_color();
last_color = color;
set_pick_color(color);
_update_color();
+
if (!deferred_mode_enabled) {
emit_signal(SNAME("color_changed"), color);
} else if (!bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) {
@@ -1053,19 +998,17 @@ 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) {
- color.set_hsv(h, s, v, color.a);
- } else if (hsv_mode_enabled && picker_type == SHAPE_OKHSL_CIRCLE) {
- color.set_ok_hsl(h, s, v, color.a);
- }
+
+ _copy_hsv_to_color();
last_color = color;
set_pick_color(color);
_update_color();
+
if (!deferred_mode_enabled) {
emit_signal(SNAME("color_changed"), color);
}
@@ -1078,7 +1021,6 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event, const Color &p_c
if (bev.is_valid()) {
if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) {
set_pick_color(p_color);
- _update_color();
emit_signal(SNAME("color_changed"), p_color);
} else if (bev->is_pressed() && bev->get_button_index() == MouseButton::RIGHT && presets_enabled) {
erase_preset(p_color);
@@ -1130,11 +1072,11 @@ void ColorPicker::_screen_pick_pressed() {
screen = memnew(Control);
r->add_child(screen);
screen->set_as_top_level(true);
- screen->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ screen->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
screen->set_default_cursor_shape(CURSOR_POINTING_HAND);
screen->connect("gui_input", callable_mp(this, &ColorPicker::_screen_input));
// It immediately toggles off in the first press otherwise.
- screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed"), varray(false));
+ screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed").bind(false));
} else {
screen->show();
}
@@ -1153,21 +1095,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 +1158,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 +1171,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 +1186,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,21 +1203,24 @@ 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->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input).bind(uv_edit));
uv_edit->set_mouse_filter(MOUSE_FILTER_PASS);
uv_edit->set_h_size_flags(SIZE_EXPAND_FILL);
uv_edit->set_v_size_flags(SIZE_EXPAND_FILL);
- uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, uv_edit));
+ uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(0, uv_edit));
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 +1233,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);
-
- 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]);
-
- 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));
+ GridContainer *gc = memnew(GridContainer);
- scroll[i]->set_min(0);
- scroll[i]->set_page(0);
- scroll[i]->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbr->add_child(gc);
+ gc->set_h_size_flags(SIZE_EXPAND_FILL);
+ gc->set_columns(3);
- 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 +1272,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 +1289,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->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(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));
+ wheel_uv->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input).bind(wheel_uv));
+ wheel_uv->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(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));
+ w_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw).bind(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() {
@@ -1503,7 +1457,7 @@ void ColorPickerButton::_update_picker() {
popup = memnew(PopupPanel);
popup->set_wrap_controls(true);
picker = memnew(ColorPicker);
- picker->set_anchors_and_offsets_preset(PRESET_WIDE);
+ picker->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
popup->add_child(picker);
add_child(popup, false, INTERNAL_MODE_FRONT);
picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed));
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 953be032ec..05b760b109 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,12 @@ private:
float v = 0.0;
Color last_color;
+ void _copy_color_to_hsv();
+ void _copy_hsv_to_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 +186,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 +214,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 +222,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 +237,7 @@ public:
void set_focus_on_line_edit();
ColorPicker();
+ ~ColorPicker();
};
class ColorPickerButton : public Button {
@@ -239,4 +278,6 @@ 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 118e77c009..06aa913eb1 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -50,6 +50,9 @@
#include "editor/plugins/control_editor_plugin.h"
#endif
+// Editor plugin interoperability.
+
+// TODO: Decouple controls from their editor plugin and get rid of this.
#ifdef TOOLS_ENABLED
Dictionary Control::_edit_get_state() const {
Dictionary s;
@@ -181,6 +184,49 @@ Size2 Control::_edit_get_minimum_size() const {
}
#endif
+// Editor integration.
+
+void Control::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
+ Node::get_argument_options(p_function, p_idx, r_options);
+
+ if (p_idx == 0) {
+ List<StringName> sn;
+ String pf = p_function;
+ if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color") {
+ Theme::get_default()->get_color_list(get_class(), &sn);
+ } else if (pf == "add_theme_style_override" || pf == "has_theme_style" || pf == "has_theme_style_override" || pf == "get_theme_style") {
+ Theme::get_default()->get_stylebox_list(get_class(), &sn);
+ } else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font") {
+ Theme::get_default()->get_font_list(get_class(), &sn);
+ } else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size") {
+ Theme::get_default()->get_font_size_list(get_class(), &sn);
+ } else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant") {
+ Theme::get_default()->get_constant_list(get_class(), &sn);
+ }
+
+ sn.sort_custom<StringName::AlphCompare>();
+ for (const StringName &name : sn) {
+ r_options->push_back(String(name).quote());
+ }
+ }
+}
+
+TypedArray<String> Control::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (data.mouse_filter == MOUSE_FILTER_IGNORE && !data.tooltip.is_empty()) {
+ warnings.push_back(RTR("The Hint Tooltip won't be displayed as the control's Mouse Filter is set to \"Ignore\". To solve this, set the Mouse Filter to \"Stop\" or \"Pass\"."));
+ }
+
+ return warnings;
+}
+
+bool Control::is_text_field() const {
+ return false;
+}
+
+// Dynamic properties.
+
String Control::properties_managed_by_container[] = {
"offset_left",
"offset_top",
@@ -196,58 +242,6 @@ String Control::properties_managed_by_container[] = {
"size"
};
-void Control::accept_event() {
- if (is_inside_tree()) {
- get_viewport()->_gui_accept_event();
- }
-}
-
-void Control::set_custom_minimum_size(const Size2 &p_custom) {
- if (p_custom == data.custom_minimum_size) {
- return;
- }
- data.custom_minimum_size = p_custom;
- update_minimum_size();
-}
-
-Size2 Control::get_custom_minimum_size() const {
- return data.custom_minimum_size;
-}
-
-void Control::_update_minimum_size_cache() {
- Size2 minsize = get_minimum_size();
- minsize.x = MAX(minsize.x, data.custom_minimum_size.x);
- minsize.y = MAX(minsize.y, data.custom_minimum_size.y);
-
- bool size_changed = false;
- if (data.minimum_size_cache != minsize) {
- size_changed = true;
- }
-
- data.minimum_size_cache = minsize;
- data.minimum_size_valid = true;
-
- if (size_changed) {
- update_minimum_size();
- }
-}
-
-Size2 Control::get_combined_minimum_size() const {
- if (!data.minimum_size_valid) {
- const_cast<Control *>(this)->_update_minimum_size_cache();
- }
- return data.minimum_size_cache;
-}
-
-Transform2D Control::_get_internal_transform() const {
- Transform2D rot_scale;
- rot_scale.set_rotation_and_scale(data.rotation, data.scale);
- Transform2D offset;
- offset.set_origin(-data.pivot_offset);
-
- return offset.affine_inverse() * (rot_scale * offset);
-}
-
bool Control::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
if (!name.begins_with("theme_override")) {
@@ -258,21 +252,21 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) {
if (name.begins_with("theme_override_icons/")) {
String dname = name.get_slicec('/', 1);
if (data.icon_override.has(dname)) {
- data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed));
+ data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
}
data.icon_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
} else if (name.begins_with("theme_override_styles/")) {
String dname = name.get_slicec('/', 1);
if (data.style_override.has(dname)) {
- data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed));
+ data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
}
data.style_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
} else if (name.begins_with("theme_override_fonts/")) {
String dname = name.get_slicec('/', 1);
if (data.font_override.has(dname)) {
- data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed));
+ data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
}
data.font_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
@@ -318,21 +312,6 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
-void Control::_update_minimum_size() {
- if (!is_inside_tree()) {
- return;
- }
-
- Size2 minsize = get_combined_minimum_size();
- data.updating_last_minimum_size = false;
-
- if (minsize != data.last_minimum_size) {
- data.last_minimum_size = minsize;
- _size_changed();
- emit_signal(SceneStringNames::get_singleton()->minimum_size_changed);
- }
-}
-
bool Control::_get(const StringName &p_name, Variant &r_ret) const {
String sname = p_name;
if (!sname.begins_with("theme_override")) {
@@ -586,6 +565,12 @@ void Control::_validate_property(PropertyInfo &property) const {
}
}
+// Global relations.
+
+bool Control::is_top_level_control() const {
+ return is_inside_tree() && (!data.parent_canvas_item && !data.RI && is_set_as_top_level());
+}
+
Control *Control::get_parent_control() const {
return data.parent;
}
@@ -594,97 +579,64 @@ Window *Control::get_parent_window() const {
return data.parent_window;
}
-void Control::set_layout_direction(Control::LayoutDirection p_direction) {
- ERR_FAIL_INDEX((int)p_direction, 4);
-
- data.layout_dir = p_direction;
- data.is_rtl_dirty = true;
-
- propagate_notification(NOTIFICATION_LAYOUT_DIRECTION_CHANGED);
-}
+Control *Control::get_root_parent_control() const {
+ const CanvasItem *ci = this;
+ const Control *root = this;
-Control::LayoutDirection Control::get_layout_direction() const {
- return data.layout_dir;
-}
+ while (ci) {
+ const Control *c = Object::cast_to<Control>(ci);
+ if (c) {
+ root = c;
-bool Control::is_layout_rtl() const {
- if (data.is_rtl_dirty) {
- const_cast<Control *>(this)->data.is_rtl_dirty = false;
- if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) {
- Window *parent_window = get_parent_window();
- Control *parent_control = get_parent_control();
- if (parent_control) {
- const_cast<Control *>(this)->data.is_rtl = parent_control->is_layout_rtl();
- } else if (parent_window) {
- const_cast<Control *>(this)->data.is_rtl = parent_window->is_layout_rtl();
- } else {
- if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
- const_cast<Control *>(this)->data.is_rtl = true;
- } else {
- String locale = TranslationServer::get_singleton()->get_tool_locale();
- const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
- }
- }
- } else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) {
- if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
- const_cast<Control *>(this)->data.is_rtl = true;
- } else {
- String locale = TranslationServer::get_singleton()->get_tool_locale();
- const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
+ if (c->data.RI || c->is_top_level_control()) {
+ break;
}
- } else {
- const_cast<Control *>(this)->data.is_rtl = (data.layout_dir == LAYOUT_DIRECTION_RTL);
}
- }
- return data.is_rtl;
-}
-void Control::set_auto_translate(bool p_enable) {
- if (p_enable == data.auto_translate) {
- return;
+ ci = ci->get_parent_item();
}
- data.auto_translate = p_enable;
-
- notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED);
-}
-
-bool Control::is_auto_translating() const {
- return data.auto_translate;
-}
-
-void Control::_clear_size_warning() {
- data.size_warning = false;
+ return const_cast<Control *>(root);
}
-//moved theme configuration here, so controls can set up even if still not inside active scene
-
-void Control::add_child_notify(Node *p_child) {
- Control *child_c = Object::cast_to<Control>(p_child);
-
- if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
- _propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
+Rect2 Control::get_parent_anchorable_rect() const {
+ if (!is_inside_tree()) {
+ return Rect2();
}
- Window *child_w = Object::cast_to<Window>(p_child);
+ Rect2 parent_rect;
+ if (data.parent_canvas_item) {
+ parent_rect = data.parent_canvas_item->get_anchorable_rect();
+ } else {
+#ifdef TOOLS_ENABLED
+ Node *edited_root = get_tree()->get_edited_scene_root();
+ if (edited_root && (this == edited_root || edited_root->is_ancestor_of(this))) {
+ parent_rect.size = Size2(ProjectSettings::get_singleton()->get("display/window/size/viewport_width"), ProjectSettings::get_singleton()->get("display/window/size/viewport_height"));
+ } else {
+ parent_rect = get_viewport()->get_visible_rect();
+ }
- if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
- _propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
+#else
+ parent_rect = get_viewport()->get_visible_rect();
+#endif
}
+
+ return parent_rect;
}
-void Control::remove_child_notify(Node *p_child) {
- Control *child_c = Object::cast_to<Control>(p_child);
+Size2 Control::get_parent_area_size() const {
+ return get_parent_anchorable_rect().size;
+}
- if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) {
- _propagate_theme_changed(child_c, nullptr, nullptr);
- }
+// Positioning and sizing.
- Window *child_w = Object::cast_to<Window>(p_child);
+Transform2D Control::_get_internal_transform() const {
+ Transform2D rot_scale;
+ rot_scale.set_rotation_and_scale(data.rotation, data.scale);
+ Transform2D offset;
+ offset.set_origin(-data.pivot_offset);
- if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) {
- _propagate_theme_changed(child_w, nullptr, nullptr);
- }
+ return offset.affine_inverse() * (rot_scale * offset);
}
void Control::_update_canvas_item_transform() {
@@ -699,815 +651,146 @@ void Control::_update_canvas_item_transform() {
RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform);
}
-void Control::_notification(int p_notification) {
- switch (p_notification) {
- case NOTIFICATION_POST_ENTER_TREE: {
- data.minimum_size_valid = false;
- data.is_rtl_dirty = true;
- _size_changed();
- } break;
-
- case NOTIFICATION_EXIT_TREE: {
- release_focus();
- get_viewport()->_gui_remove_control(this);
- } break;
-
- case NOTIFICATION_READY: {
-#ifdef DEBUG_ENABLED
- connect("ready", callable_mp(this, &Control::_clear_size_warning), varray(), CONNECT_DEFERRED | CONNECT_ONESHOT);
-#endif
- } break;
-
- case NOTIFICATION_ENTER_CANVAS: {
- data.parent = Object::cast_to<Control>(get_parent());
- data.parent_window = Object::cast_to<Window>(get_parent());
- data.is_rtl_dirty = true;
-
- if (data.theme.is_null()) {
- if (data.parent && (data.parent->data.theme_owner || data.parent->data.theme_owner_window)) {
- data.theme_owner = data.parent->data.theme_owner;
- data.theme_owner_window = data.parent->data.theme_owner_window;
- notification(NOTIFICATION_THEME_CHANGED);
- } else if (data.parent_window && (data.parent_window->theme_owner || data.parent_window->theme_owner_window)) {
- data.theme_owner = data.parent_window->theme_owner;
- data.theme_owner_window = data.parent_window->theme_owner_window;
- notification(NOTIFICATION_THEME_CHANGED);
- }
- }
-
- CanvasItem *node = this;
- bool has_parent_control = false;
-
- while (!node->is_set_as_top_level()) {
- CanvasItem *parent = Object::cast_to<CanvasItem>(node->get_parent());
- if (!parent) {
- break;
- }
-
- Control *parent_control = Object::cast_to<Control>(parent);
- if (parent_control) {
- has_parent_control = true;
- break;
- }
-
- node = parent;
- }
-
- if (has_parent_control) {
- // Do nothing, has a parent control.
- } else {
- // Is a regular root control or top_level.
- Viewport *viewport = get_viewport();
- ERR_FAIL_COND(!viewport);
- data.RI = viewport->_gui_add_root_control(this);
- }
-
- data.parent_canvas_item = get_parent_item();
-
- if (data.parent_canvas_item) {
- data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed));
- } else {
- // Connect viewport.
- Viewport *viewport = get_viewport();
- ERR_FAIL_COND(!viewport);
- viewport->connect("size_changed", callable_mp(this, &Control::_size_changed));
- }
- } break;
-
- case NOTIFICATION_EXIT_CANVAS: {
- if (data.parent_canvas_item) {
- data.parent_canvas_item->disconnect("item_rect_changed", callable_mp(this, &Control::_size_changed));
- data.parent_canvas_item = nullptr;
- } else if (!is_set_as_top_level()) {
- //disconnect viewport
- Viewport *viewport = get_viewport();
- ERR_FAIL_COND(!viewport);
- viewport->disconnect("size_changed", callable_mp(this, &Control::_size_changed));
- }
-
- if (data.RI) {
- get_viewport()->_gui_remove_root_control(data.RI);
- data.RI = nullptr;
- }
-
- data.parent = nullptr;
- data.parent_canvas_item = nullptr;
- data.parent_window = nullptr;
- data.is_rtl_dirty = true;
- } break;
-
- case NOTIFICATION_MOVED_IN_PARENT: {
- // some parents need to know the order of the children to draw (like TabContainer)
- // update if necessary
- if (data.parent) {
- data.parent->update();
- }
- update();
-
- if (data.RI) {
- get_viewport()->_gui_set_root_order_dirty();
- }
- } break;
-
- case NOTIFICATION_RESIZED: {
- emit_signal(SceneStringNames::get_singleton()->resized);
- } break;
-
- case NOTIFICATION_DRAW: {
- _update_canvas_item_transform();
- RenderingServer::get_singleton()->canvas_item_set_custom_rect(get_canvas_item(), !data.disable_visibility_clip, Rect2(Point2(), get_size()));
- RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), data.clip_contents);
- } break;
-
- case NOTIFICATION_MOUSE_ENTER: {
- emit_signal(SceneStringNames::get_singleton()->mouse_entered);
- } break;
-
- case NOTIFICATION_MOUSE_EXIT: {
- emit_signal(SceneStringNames::get_singleton()->mouse_exited);
- } break;
-
- case NOTIFICATION_FOCUS_ENTER: {
- emit_signal(SceneStringNames::get_singleton()->focus_entered);
- update();
- } break;
-
- case NOTIFICATION_FOCUS_EXIT: {
- emit_signal(SceneStringNames::get_singleton()->focus_exited);
- update();
- } break;
-
- case NOTIFICATION_THEME_CHANGED: {
- update_minimum_size();
- update();
- } break;
-
- case NOTIFICATION_VISIBILITY_CHANGED: {
- if (!is_visible_in_tree()) {
- if (get_viewport() != nullptr) {
- get_viewport()->_gui_hide_control(this);
- }
- } else {
- data.minimum_size_valid = false;
- _update_minimum_size();
- _size_changed();
- }
- } break;
-
- case NOTIFICATION_TRANSLATION_CHANGED:
- case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
- if (is_inside_tree()) {
- data.is_rtl_dirty = true;
- _size_changed();
- }
- } break;
- }
-}
-
-bool Control::has_point(const Point2 &p_point) const {
- bool ret;
- if (GDVIRTUAL_CALL(_has_point, p_point, ret)) {
- return ret;
- }
- return Rect2(Point2(), get_size()).has_point(p_point);
-}
-
-void Control::set_drag_forwarding(Object *p_target) {
- if (p_target) {
- data.drag_owner = p_target->get_instance_id();
- } else {
- data.drag_owner = ObjectID();
- }
-}
-
-Variant Control::get_drag_data(const Point2 &p_point) {
- if (data.drag_owner.is_valid()) {
- Object *obj = ObjectDB::get_instance(data.drag_owner);
- if (obj) {
- return obj->call("_get_drag_data_fw", p_point, this);
- }
- }
-
- Variant dd;
- if (GDVIRTUAL_CALL(_get_drag_data, p_point, dd)) {
- return dd;
- }
-
- return Variant();
-}
-
-bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
- if (data.drag_owner.is_valid()) {
- Object *obj = ObjectDB::get_instance(data.drag_owner);
- if (obj) {
- return obj->call("_can_drop_data_fw", p_point, p_data, this);
- }
- }
-
- bool ret;
- if (GDVIRTUAL_CALL(_can_drop_data, p_point, p_data, ret)) {
- return ret;
- }
- return false;
-}
-
-void Control::drop_data(const Point2 &p_point, const Variant &p_data) {
- if (data.drag_owner.is_valid()) {
- Object *obj = ObjectDB::get_instance(data.drag_owner);
- if (obj) {
- obj->call("_drop_data_fw", p_point, p_data, this);
- return;
- }
- }
-
- GDVIRTUAL_CALL(_drop_data, p_point, p_data);
-}
-
-void Control::force_drag(const Variant &p_data, Control *p_control) {
- ERR_FAIL_COND(!is_inside_tree());
- ERR_FAIL_COND(p_data.get_type() == Variant::NIL);
-
- get_viewport()->_gui_force_drag(this, p_data, p_control);
-}
-
-void Control::set_drag_preview(Control *p_control) {
- ERR_FAIL_COND(!is_inside_tree());
- ERR_FAIL_COND(!get_viewport()->gui_is_dragging());
- get_viewport()->_gui_set_drag_preview(this, p_control);
-}
-
-bool Control::is_drag_successful() const {
- return is_inside_tree() && get_viewport()->gui_is_drag_successful();
-}
-
-void Control::_call_gui_input(const Ref<InputEvent> &p_event) {
- emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); //signal should be first, so it's possible to override an event (and then accept it)
- if (!is_inside_tree() || get_viewport()->is_input_handled()) {
- return; //input was handled, abort
- }
- GDVIRTUAL_CALL(_gui_input, p_event);
- if (!is_inside_tree() || get_viewport()->is_input_handled()) {
- return; //input was handled, abort
- }
- gui_input(p_event);
-}
-void Control::gui_input(const Ref<InputEvent> &p_event) {
+Transform2D Control::get_transform() const {
+ Transform2D xform = _get_internal_transform();
+ xform[2] += get_position();
+ return xform;
}
-Size2 Control::get_minimum_size() const {
- Vector2 ms;
- if (GDVIRTUAL_CALL(_get_minimum_size, ms)) {
- return ms;
- }
- return Vector2();
-}
+/// Anchors and offsets.
-template <class T>
-T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) {
- ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, T(), "At least one theme type must be specified.");
-
- // First, look through each control or window node in the branch, until no valid parent can be found.
- // Only nodes with a theme resource attached are considered.
- Control *theme_owner = p_theme_owner;
- Window *theme_owner_window = p_theme_owner_window;
-
- while (theme_owner || theme_owner_window) {
- // For each theme resource check the theme types provided and see if p_name exists with any of them.
- for (const StringName &E : p_theme_types) {
- if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) {
- return theme_owner->data.theme->get_theme_item(p_data_type, p_name, E);
- }
-
- if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) {
- return theme_owner_window->theme->get_theme_item(p_data_type, p_name, E);
- }
- }
-
- Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
- Control *parent_c = Object::cast_to<Control>(parent);
- if (parent_c) {
- theme_owner = parent_c->data.theme_owner;
- theme_owner_window = parent_c->data.theme_owner_window;
- } else {
- Window *parent_w = Object::cast_to<Window>(parent);
- if (parent_w) {
- theme_owner = parent_w->theme_owner;
- theme_owner_window = parent_w->theme_owner_window;
- } else {
- theme_owner = nullptr;
- theme_owner_window = nullptr;
- }
- }
- }
-
- // Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
- for (const StringName &E : p_theme_types) {
- if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) {
- return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E);
- }
- }
- }
-
- // Lastly, fall back on the items defined in the default Theme, if they exist.
- for (const StringName &E : p_theme_types) {
- if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) {
- return Theme::get_default()->get_theme_item(p_data_type, p_name, E);
- }
- }
- // If they don't exist, use any type to return the default/empty value.
- return Theme::get_default()->get_theme_item(p_data_type, p_name, p_theme_types[0]);
+void Control::_set_anchor(Side p_side, real_t p_anchor) {
+ set_anchor(p_side, p_anchor);
}
-bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) {
- ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, false, "At least one theme type must be specified.");
-
- // First, look through each control or window node in the branch, until no valid parent can be found.
- // Only nodes with a theme resource attached are considered.
- Control *theme_owner = p_theme_owner;
- Window *theme_owner_window = p_theme_owner_window;
-
- while (theme_owner || theme_owner_window) {
- // For each theme resource check the theme types provided and see if p_name exists with any of them.
- for (const StringName &E : p_theme_types) {
- if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) {
- return true;
- }
-
- if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) {
- return true;
- }
- }
-
- Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
- Control *parent_c = Object::cast_to<Control>(parent);
- if (parent_c) {
- theme_owner = parent_c->data.theme_owner;
- theme_owner_window = parent_c->data.theme_owner_window;
- } else {
- Window *parent_w = Object::cast_to<Window>(parent);
- if (parent_w) {
- theme_owner = parent_w->theme_owner;
- theme_owner_window = parent_w->theme_owner_window;
- } else {
- theme_owner = nullptr;
- theme_owner_window = nullptr;
- }
- }
- }
+void Control::set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset, bool p_push_opposite_anchor) {
+ ERR_FAIL_INDEX((int)p_side, 4);
- // Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
- for (const StringName &E : p_theme_types) {
- if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) {
- return true;
- }
- }
- }
+ Rect2 parent_rect = get_parent_anchorable_rect();
+ real_t parent_range = (p_side == SIDE_LEFT || p_side == SIDE_RIGHT) ? parent_rect.size.x : parent_rect.size.y;
+ real_t previous_pos = data.offset[p_side] + data.anchor[p_side] * parent_range;
+ real_t previous_opposite_pos = data.offset[(p_side + 2) % 4] + data.anchor[(p_side + 2) % 4] * parent_range;
- // Lastly, fall back on the items defined in the default Theme, if they exist.
- for (const StringName &E : p_theme_types) {
- if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) {
- return true;
- }
- }
- return false;
-}
+ data.anchor[p_side] = p_anchor;
-void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
- if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(data.theme_type_variation) != StringName()) {
- Theme::get_project_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
+ if (((p_side == SIDE_LEFT || p_side == SIDE_TOP) && data.anchor[p_side] > data.anchor[(p_side + 2) % 4]) ||
+ ((p_side == SIDE_RIGHT || p_side == SIDE_BOTTOM) && data.anchor[p_side] < data.anchor[(p_side + 2) % 4])) {
+ if (p_push_opposite_anchor) {
+ data.anchor[(p_side + 2) % 4] = data.anchor[p_side];
} else {
- Theme::get_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
- }
- } else {
- Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list);
- }
-}
-
-Ref<Texture2D> Control::get_theme_icon(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<Texture2D> *tex = data.icon_override.getptr(p_name);
- if (tex) {
- return *tex;
- }
- }
-
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return get_theme_item_in_types<Ref<Texture2D>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
-}
-
-Ref<StyleBox> Control::get_theme_stylebox(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<StyleBox> *style = data.style_override.getptr(p_name);
- if (style) {
- return *style;
- }
- }
-
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return get_theme_item_in_types<Ref<StyleBox>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
-}
-
-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) {
- return *font;
- }
- }
-
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return get_theme_item_in_types<Ref<Font>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
-}
-
-int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
- const int *font_size = data.font_size_override.getptr(p_name);
- if (font_size && (*font_size) > 0) {
- return *font_size;
+ data.anchor[p_side] = data.anchor[(p_side + 2) % 4];
}
}
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
-}
-
-Color Control::get_theme_color(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 Color *color = data.color_override.getptr(p_name);
- if (color) {
- return *color;
+ if (!p_keep_offset) {
+ data.offset[p_side] = previous_pos - data.anchor[p_side] * parent_range;
+ if (p_push_opposite_anchor) {
+ data.offset[(p_side + 2) % 4] = previous_opposite_pos - data.anchor[(p_side + 2) % 4] * parent_range;
}
}
-
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return get_theme_item_in_types<Color>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
-}
-
-int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
- const int *constant = data.constant_override.getptr(p_name);
- if (constant) {
- return *constant;
- }
+ if (is_inside_tree()) {
+ _size_changed();
}
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
-}
-
-bool Control::has_theme_icon_override(const StringName &p_name) const {
- const Ref<Texture2D> *tex = data.icon_override.getptr(p_name);
- return tex != nullptr;
-}
-
-bool Control::has_theme_stylebox_override(const StringName &p_name) const {
- const Ref<StyleBox> *style = data.style_override.getptr(p_name);
- return style != nullptr;
-}
-
-bool Control::has_theme_font_override(const StringName &p_name) const {
- const Ref<Font> *font = data.font_override.getptr(p_name);
- return font != nullptr;
-}
-
-bool Control::has_theme_font_size_override(const StringName &p_name) const {
- const int *font_size = data.font_size_override.getptr(p_name);
- return font_size != nullptr;
-}
-
-bool Control::has_theme_color_override(const StringName &p_name) const {
- const Color *color = data.color_override.getptr(p_name);
- return color != nullptr;
-}
-
-bool Control::has_theme_constant_override(const StringName &p_name) const {
- const int *constant = data.constant_override.getptr(p_name);
- return constant != nullptr;
+ update();
}
-bool Control::has_theme_icon(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) {
- if (has_theme_icon_override(p_name)) {
- return true;
- }
- }
+real_t Control::get_anchor(Side p_side) const {
+ ERR_FAIL_INDEX_V(int(p_side), 4, 0.0);
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
+ return data.anchor[p_side];
}
-bool Control::has_theme_stylebox(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) {
- if (has_theme_stylebox_override(p_name)) {
- return true;
- }
- }
+void Control::set_offset(Side p_side, real_t p_value) {
+ ERR_FAIL_INDEX((int)p_side, 4);
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
+ data.offset[p_side] = p_value;
+ _size_changed();
}
-bool Control::has_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) {
- if (has_theme_font_override(p_name)) {
- return true;
- }
- }
+real_t Control::get_offset(Side p_side) const {
+ ERR_FAIL_INDEX_V((int)p_side, 4, 0);
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
+ return data.offset[p_side];
}
-bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
- if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
- if (has_theme_font_size_override(p_name)) {
- return true;
- }
- }
-
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
+void Control::set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, bool p_push_opposite_anchor) {
+ set_anchor(p_side, p_anchor, false, p_push_opposite_anchor);
+ set_offset(p_side, p_pos);
}
-bool Control::has_theme_color(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) {
- if (has_theme_color_override(p_name)) {
- return true;
- }
- }
-
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
+void Control::set_begin(const Size2 &p_point) {
+ data.offset[0] = p_point.x;
+ data.offset[1] = p_point.y;
+ _size_changed();
}
-bool Control::has_theme_constant(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) {
- if (has_theme_constant_override(p_name)) {
- return true;
- }
- }
-
- List<StringName> theme_types;
- _get_theme_type_dependencies(p_theme_type, &theme_types);
- return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
+Size2 Control::get_begin() const {
+ return Size2(data.offset[0], data.offset[1]);
}
-float Control::fetch_theme_default_base_scale(Control *p_theme_owner, Window *p_theme_owner_window) {
- // First, look through each control or window node in the branch, until no valid parent can be found.
- // Only nodes with a theme resource attached are considered.
- // For each theme resource see if their assigned theme has the default value defined and valid.
- Control *theme_owner = p_theme_owner;
- Window *theme_owner_window = p_theme_owner_window;
-
- while (theme_owner || theme_owner_window) {
- if (theme_owner && theme_owner->data.theme->has_default_base_scale()) {
- return theme_owner->data.theme->get_default_base_scale();
- }
-
- if (theme_owner_window && theme_owner_window->theme->has_default_base_scale()) {
- return theme_owner_window->theme->get_default_base_scale();
- }
-
- Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
- Control *parent_c = Object::cast_to<Control>(parent);
- if (parent_c) {
- theme_owner = parent_c->data.theme_owner;
- theme_owner_window = parent_c->data.theme_owner_window;
- } else {
- Window *parent_w = Object::cast_to<Window>(parent);
- if (parent_w) {
- theme_owner = parent_w->theme_owner;
- theme_owner_window = parent_w->theme_owner_window;
- } else {
- theme_owner = nullptr;
- theme_owner_window = nullptr;
- }
- }
- }
-
- // Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_default_base_scale()) {
- return Theme::get_project_default()->get_default_base_scale();
- }
- }
-
- // Lastly, fall back on the default Theme.
- if (Theme::get_default()->has_default_base_scale()) {
- return Theme::get_default()->get_default_base_scale();
- }
- return Theme::get_fallback_base_scale();
+void Control::set_end(const Size2 &p_point) {
+ data.offset[2] = p_point.x;
+ data.offset[3] = p_point.y;
+ _size_changed();
}
-float Control::get_theme_default_base_scale() const {
- return fetch_theme_default_base_scale(data.theme_owner, data.theme_owner_window);
+Size2 Control::get_end() const {
+ return Size2(data.offset[2], data.offset[3]);
}
-Ref<Font> Control::fetch_theme_default_font(Control *p_theme_owner, Window *p_theme_owner_window) {
- // First, look through each control or window node in the branch, until no valid parent can be found.
- // Only nodes with a theme resource attached are considered.
- // For each theme resource see if their assigned theme has the default value defined and valid.
- Control *theme_owner = p_theme_owner;
- Window *theme_owner_window = p_theme_owner_window;
-
- while (theme_owner || theme_owner_window) {
- if (theme_owner && theme_owner->data.theme->has_default_font()) {
- return theme_owner->data.theme->get_default_font();
- }
-
- if (theme_owner_window && theme_owner_window->theme->has_default_font()) {
- return theme_owner_window->theme->get_default_font();
- }
-
- Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
- Control *parent_c = Object::cast_to<Control>(parent);
- if (parent_c) {
- theme_owner = parent_c->data.theme_owner;
- theme_owner_window = parent_c->data.theme_owner_window;
- } else {
- Window *parent_w = Object::cast_to<Window>(parent);
- if (parent_w) {
- theme_owner = parent_w->theme_owner;
- theme_owner_window = parent_w->theme_owner_window;
- } else {
- theme_owner = nullptr;
- theme_owner_window = nullptr;
- }
- }
- }
-
- // Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_default_font()) {
- return Theme::get_project_default()->get_default_font();
- }
- }
+void Control::set_h_grow_direction(GrowDirection p_direction) {
+ ERR_FAIL_INDEX((int)p_direction, 3);
- // Lastly, fall back on the default Theme.
- if (Theme::get_default()->has_default_font()) {
- return Theme::get_default()->get_default_font();
- }
- return Theme::get_fallback_font();
+ data.h_grow = p_direction;
+ _size_changed();
}
-Ref<Font> Control::get_theme_default_font() const {
- return fetch_theme_default_font(data.theme_owner, data.theme_owner_window);
+Control::GrowDirection Control::get_h_grow_direction() const {
+ return data.h_grow;
}
-int Control::fetch_theme_default_font_size(Control *p_theme_owner, Window *p_theme_owner_window) {
- // First, look through each control or window node in the branch, until no valid parent can be found.
- // Only nodes with a theme resource attached are considered.
- // For each theme resource see if their assigned theme has the default value defined and valid.
- Control *theme_owner = p_theme_owner;
- Window *theme_owner_window = p_theme_owner_window;
-
- while (theme_owner || theme_owner_window) {
- if (theme_owner && theme_owner->data.theme->has_default_font_size()) {
- return theme_owner->data.theme->get_default_font_size();
- }
-
- if (theme_owner_window && theme_owner_window->theme->has_default_font_size()) {
- return theme_owner_window->theme->get_default_font_size();
- }
-
- Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
- Control *parent_c = Object::cast_to<Control>(parent);
- if (parent_c) {
- theme_owner = parent_c->data.theme_owner;
- theme_owner_window = parent_c->data.theme_owner_window;
- } else {
- Window *parent_w = Object::cast_to<Window>(parent);
- if (parent_w) {
- theme_owner = parent_w->theme_owner;
- theme_owner_window = parent_w->theme_owner_window;
- } else {
- theme_owner = nullptr;
- theme_owner_window = nullptr;
- }
- }
- }
-
- // Secondly, check the project-defined Theme resource.
- if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_default_font_size()) {
- return Theme::get_project_default()->get_default_font_size();
- }
- }
+void Control::set_v_grow_direction(GrowDirection p_direction) {
+ ERR_FAIL_INDEX((int)p_direction, 3);
- // Lastly, fall back on the default Theme.
- if (Theme::get_default()->has_default_font_size()) {
- return Theme::get_default()->get_default_font_size();
- }
- return Theme::get_fallback_font_size();
+ data.v_grow = p_direction;
+ _size_changed();
}
-int Control::get_theme_default_font_size() const {
- return fetch_theme_default_font_size(data.theme_owner, data.theme_owner_window);
+Control::GrowDirection Control::get_v_grow_direction() const {
+ return data.v_grow;
}
-Rect2 Control::get_parent_anchorable_rect() const {
- if (!is_inside_tree()) {
- return Rect2();
- }
-
- Rect2 parent_rect;
- if (data.parent_canvas_item) {
- parent_rect = data.parent_canvas_item->get_anchorable_rect();
- } else {
-#ifdef TOOLS_ENABLED
- Node *edited_root = get_tree()->get_edited_scene_root();
- if (edited_root && (this == edited_root || edited_root->is_ancestor_of(this))) {
- parent_rect.size = Size2(ProjectSettings::get_singleton()->get("display/window/size/viewport_width"), ProjectSettings::get_singleton()->get("display/window/size/viewport_height"));
- } else {
- parent_rect = get_viewport()->get_visible_rect();
- }
+void Control::_compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]) {
+ Size2 parent_rect_size = get_parent_anchorable_rect().size;
+ ERR_FAIL_COND(parent_rect_size.x == 0.0);
+ ERR_FAIL_COND(parent_rect_size.y == 0.0);
-#else
- parent_rect = get_viewport()->get_visible_rect();
-#endif
+ real_t x = p_rect.position.x;
+ if (is_layout_rtl()) {
+ x = parent_rect_size.x - x - p_rect.size.x;
}
-
- return parent_rect;
-}
-
-Size2 Control::get_parent_area_size() const {
- return get_parent_anchorable_rect().size;
+ r_anchors[0] = (x - p_offsets[0]) / parent_rect_size.x;
+ r_anchors[1] = (p_rect.position.y - p_offsets[1]) / parent_rect_size.y;
+ r_anchors[2] = (x + p_rect.size.x - p_offsets[2]) / parent_rect_size.x;
+ r_anchors[3] = (p_rect.position.y + p_rect.size.y - p_offsets[3]) / parent_rect_size.y;
}
-void Control::_size_changed() {
- Rect2 parent_rect = get_parent_anchorable_rect();
-
- real_t edge_pos[4];
-
- for (int i = 0; i < 4; i++) {
- real_t area = parent_rect.size[i & 1];
- edge_pos[i] = data.offset[i] + (data.anchor[i] * area);
- }
-
- Point2 new_pos_cache = Point2(edge_pos[0], edge_pos[1]);
- Size2 new_size_cache = Point2(edge_pos[2], edge_pos[3]) - new_pos_cache;
-
- Size2 minimum_size = get_combined_minimum_size();
-
- if (minimum_size.width > new_size_cache.width) {
- if (data.h_grow == GROW_DIRECTION_BEGIN) {
- new_pos_cache.x += new_size_cache.width - minimum_size.width;
- } else if (data.h_grow == GROW_DIRECTION_BOTH) {
- new_pos_cache.x += 0.5 * (new_size_cache.width - minimum_size.width);
- }
-
- new_size_cache.width = minimum_size.width;
- }
+void Control::_compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]) {
+ Size2 parent_rect_size = get_parent_anchorable_rect().size;
+ real_t x = p_rect.position.x;
if (is_layout_rtl()) {
- new_pos_cache.x = parent_rect.size.x - new_pos_cache.x - new_size_cache.x;
- }
-
- if (minimum_size.height > new_size_cache.height) {
- if (data.v_grow == GROW_DIRECTION_BEGIN) {
- new_pos_cache.y += new_size_cache.height - minimum_size.height;
- } else if (data.v_grow == GROW_DIRECTION_BOTH) {
- new_pos_cache.y += 0.5 * (new_size_cache.height - minimum_size.height);
- }
-
- new_size_cache.height = minimum_size.height;
- }
-
- bool pos_changed = new_pos_cache != data.pos_cache;
- bool size_changed = new_size_cache != data.size_cache;
-
- data.pos_cache = new_pos_cache;
- data.size_cache = new_size_cache;
-
- if (is_inside_tree()) {
- if (size_changed) {
- notification(NOTIFICATION_RESIZED);
- }
- if (pos_changed || size_changed) {
- item_rect_changed(size_changed);
- _notify_transform();
- }
-
- if (pos_changed && !size_changed) {
- _update_canvas_item_transform(); //move because it won't be updated
- }
+ x = parent_rect_size.x - x - p_rect.size.x;
}
+ r_offsets[0] = x - (p_anchors[0] * parent_rect_size.x);
+ r_offsets[1] = p_rect.position.y - (p_anchors[1] * parent_rect_size.y);
+ r_offsets[2] = x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x);
+ r_offsets[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y);
}
+/// Presets and layout modes.
+
void Control::_set_layout_mode(LayoutMode p_mode) {
bool list_changed = false;
@@ -1557,47 +840,6 @@ Control::LayoutMode Control::_get_layout_mode() const {
return LayoutMode::LAYOUT_MODE_POSITION;
}
-void Control::set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset, bool p_push_opposite_anchor) {
- ERR_FAIL_INDEX((int)p_side, 4);
-
- Rect2 parent_rect = get_parent_anchorable_rect();
- real_t parent_range = (p_side == SIDE_LEFT || p_side == SIDE_RIGHT) ? parent_rect.size.x : parent_rect.size.y;
- real_t previous_pos = data.offset[p_side] + data.anchor[p_side] * parent_range;
- real_t previous_opposite_pos = data.offset[(p_side + 2) % 4] + data.anchor[(p_side + 2) % 4] * parent_range;
-
- data.anchor[p_side] = p_anchor;
-
- if (((p_side == SIDE_LEFT || p_side == SIDE_TOP) && data.anchor[p_side] > data.anchor[(p_side + 2) % 4]) ||
- ((p_side == SIDE_RIGHT || p_side == SIDE_BOTTOM) && data.anchor[p_side] < data.anchor[(p_side + 2) % 4])) {
- if (p_push_opposite_anchor) {
- data.anchor[(p_side + 2) % 4] = data.anchor[p_side];
- } else {
- data.anchor[p_side] = data.anchor[(p_side + 2) % 4];
- }
- }
-
- if (!p_keep_offset) {
- data.offset[p_side] = previous_pos - data.anchor[p_side] * parent_range;
- if (p_push_opposite_anchor) {
- data.offset[(p_side + 2) % 4] = previous_opposite_pos - data.anchor[(p_side + 2) % 4] * parent_range;
- }
- }
- if (is_inside_tree()) {
- _size_changed();
- }
-
- update();
-}
-
-void Control::_set_anchor(Side p_side, real_t p_anchor) {
- set_anchor(p_side, p_anchor);
-}
-
-void Control::set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, bool p_push_opposite_anchor) {
- set_anchor(p_side, p_anchor, false, p_push_opposite_anchor);
- set_offset(p_side, p_pos);
-}
-
void Control::_set_anchors_layout_preset(int p_preset) {
bool list_changed = false;
@@ -1642,7 +884,7 @@ void Control::_set_anchors_layout_preset(int p_preset) {
case PRESET_BOTTOM_WIDE:
case PRESET_VCENTER_WIDE:
case PRESET_HCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
set_offsets_preset(preset, LayoutPresetMode::PRESET_MODE_MINSIZE);
break;
}
@@ -1718,7 +960,7 @@ int Control::_get_anchors_layout_preset() const {
}
if (left == ANCHOR_BEGIN && right == ANCHOR_END && top == ANCHOR_BEGIN && bottom == ANCHOR_END) {
- return (int)LayoutPreset::PRESET_WIDE;
+ return (int)LayoutPreset::PRESET_FULL_RECT;
}
// Does not match any preset, return "Custom".
@@ -1737,7 +979,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets) {
case PRESET_BOTTOM_WIDE:
case PRESET_LEFT_WIDE:
case PRESET_HCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
set_anchor(SIDE_LEFT, ANCHOR_BEGIN, p_keep_offsets);
break;
@@ -1765,7 +1007,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets) {
case PRESET_RIGHT_WIDE:
case PRESET_TOP_WIDE:
case PRESET_VCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
set_anchor(SIDE_TOP, ANCHOR_BEGIN, p_keep_offsets);
break;
@@ -1807,7 +1049,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets) {
case PRESET_RIGHT_WIDE:
case PRESET_BOTTOM_WIDE:
case PRESET_HCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
set_anchor(SIDE_RIGHT, ANCHOR_END, p_keep_offsets);
break;
}
@@ -1835,7 +1077,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets) {
case PRESET_RIGHT_WIDE:
case PRESET_BOTTOM_WIDE:
case PRESET_VCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
set_anchor(SIDE_BOTTOM, ANCHOR_END, p_keep_offsets);
break;
}
@@ -1870,7 +1112,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz
case PRESET_BOTTOM_WIDE:
case PRESET_LEFT_WIDE:
case PRESET_HCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
data.offset[0] = x * (0.0 - data.anchor[0]) + p_margin + parent_rect.position.x;
break;
@@ -1898,7 +1140,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz
case PRESET_RIGHT_WIDE:
case PRESET_TOP_WIDE:
case PRESET_VCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
data.offset[1] = parent_rect.size.y * (0.0 - data.anchor[1]) + p_margin + parent_rect.position.y;
break;
@@ -1940,7 +1182,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz
case PRESET_RIGHT_WIDE:
case PRESET_BOTTOM_WIDE:
case PRESET_HCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
data.offset[2] = x * (1.0 - data.anchor[2]) - p_margin + parent_rect.position.x;
break;
}
@@ -1968,7 +1210,7 @@ void Control::set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz
case PRESET_RIGHT_WIDE:
case PRESET_BOTTOM_WIDE:
case PRESET_VCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
data.offset[3] = parent_rect.size.y * (1.0 - data.anchor[3]) - p_margin + parent_rect.position.y;
break;
}
@@ -2003,7 +1245,7 @@ void Control::set_grow_direction_preset(LayoutPreset p_preset) {
case PRESET_BOTTOM_WIDE:
case PRESET_VCENTER_WIDE:
case PRESET_HCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
set_h_grow_direction(GrowDirection::GROW_DIRECTION_BOTH);
break;
}
@@ -2031,49 +1273,43 @@ void Control::set_grow_direction_preset(LayoutPreset p_preset) {
case PRESET_RIGHT_WIDE:
case PRESET_VCENTER_WIDE:
case PRESET_HCENTER_WIDE:
- case PRESET_WIDE:
+ case PRESET_FULL_RECT:
set_v_grow_direction(GrowDirection::GROW_DIRECTION_BOTH);
break;
}
}
-real_t Control::get_anchor(Side p_side) const {
- ERR_FAIL_INDEX_V(int(p_side), 4, 0.0);
+/// Manual positioning.
- return data.anchor[p_side];
+void Control::_set_position(const Size2 &p_point) {
+ set_position(p_point);
}
-void Control::set_offset(Side p_side, real_t p_value) {
- ERR_FAIL_INDEX((int)p_side, 4);
-
- data.offset[p_side] = p_value;
+void Control::set_position(const Size2 &p_point, bool p_keep_offsets) {
+ if (p_keep_offsets) {
+ _compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor);
+ } else {
+ _compute_offsets(Rect2(p_point, data.size_cache), data.anchor, data.offset);
+ }
_size_changed();
}
-void Control::set_begin(const Size2 &p_point) {
- data.offset[0] = p_point.x;
- data.offset[1] = p_point.y;
- _size_changed();
+Size2 Control::get_position() const {
+ return data.pos_cache;
}
-void Control::set_end(const Size2 &p_point) {
- data.offset[2] = p_point.x;
- data.offset[3] = p_point.y;
- _size_changed();
+void Control::_set_global_position(const Point2 &p_point) {
+ set_global_position(p_point);
}
-real_t Control::get_offset(Side p_side) const {
- ERR_FAIL_INDEX_V((int)p_side, 4, 0);
-
- return data.offset[p_side];
-}
+void Control::set_global_position(const Point2 &p_point, bool p_keep_offsets) {
+ Transform2D inv;
-Size2 Control::get_begin() const {
- return Size2(data.offset[0], data.offset[1]);
-}
+ if (data.parent_canvas_item) {
+ inv = data.parent_canvas_item->get_global_transform().affine_inverse();
+ }
-Size2 Control::get_end() const {
- return Size2(data.offset[2], data.offset[3]);
+ set_position(inv.xform(p_point), p_keep_offsets);
}
Point2 Control::get_global_position() const {
@@ -2091,72 +1327,6 @@ Point2 Control::get_screen_position() const {
return global_pos;
}
-void Control::_set_global_position(const Point2 &p_point) {
- set_global_position(p_point);
-}
-
-void Control::set_global_position(const Point2 &p_point, bool p_keep_offsets) {
- Transform2D inv;
-
- if (data.parent_canvas_item) {
- inv = data.parent_canvas_item->get_global_transform().affine_inverse();
- }
-
- set_position(inv.xform(p_point), p_keep_offsets);
-}
-
-void Control::_compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]) {
- Size2 parent_rect_size = get_parent_anchorable_rect().size;
- ERR_FAIL_COND(parent_rect_size.x == 0.0);
- ERR_FAIL_COND(parent_rect_size.y == 0.0);
-
- real_t x = p_rect.position.x;
- if (is_layout_rtl()) {
- x = parent_rect_size.x - x - p_rect.size.x;
- }
- r_anchors[0] = (x - p_offsets[0]) / parent_rect_size.x;
- r_anchors[1] = (p_rect.position.y - p_offsets[1]) / parent_rect_size.y;
- r_anchors[2] = (x + p_rect.size.x - p_offsets[2]) / parent_rect_size.x;
- r_anchors[3] = (p_rect.position.y + p_rect.size.y - p_offsets[3]) / parent_rect_size.y;
-}
-
-void Control::_compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]) {
- Size2 parent_rect_size = get_parent_anchorable_rect().size;
-
- real_t x = p_rect.position.x;
- if (is_layout_rtl()) {
- x = parent_rect_size.x - x - p_rect.size.x;
- }
- r_offsets[0] = x - (p_anchors[0] * parent_rect_size.x);
- r_offsets[1] = p_rect.position.y - (p_anchors[1] * parent_rect_size.y);
- r_offsets[2] = x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x);
- r_offsets[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y);
-}
-
-void Control::_set_position(const Size2 &p_point) {
- set_position(p_point);
-}
-
-void Control::set_position(const Size2 &p_point, bool p_keep_offsets) {
- if (p_keep_offsets) {
- _compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor);
- } else {
- _compute_offsets(Rect2(p_point, data.size_cache), data.anchor, data.offset);
- }
- _size_changed();
-}
-
-void Control::set_rect(const Rect2 &p_rect) {
- for (int i = 0; i < 4; i++) {
- data.anchor[i] = ANCHOR_BEGIN;
- }
-
- _compute_offsets(p_rect, data.anchor, data.offset);
- if (is_inside_tree()) {
- _size_changed();
- }
-}
-
void Control::_set_size(const Size2 &p_size) {
#ifdef DEBUG_ENABLED
if (data.size_warning && (data.anchor[SIDE_LEFT] != data.anchor[SIDE_RIGHT] || data.anchor[SIDE_TOP] != data.anchor[SIDE_BOTTOM])) {
@@ -2184,10 +1354,6 @@ void Control::set_size(const Size2 &p_size, bool p_keep_offsets) {
_size_changed();
}
-Size2 Control::get_position() const {
- return data.pos_cache;
-}
-
Size2 Control::get_size() const {
return data.size_cache;
}
@@ -2196,6 +1362,21 @@ void Control::reset_size() {
set_size(Size2());
}
+void Control::set_rect(const Rect2 &p_rect) {
+ for (int i = 0; i < 4; i++) {
+ data.anchor[i] = ANCHOR_BEGIN;
+ }
+
+ _compute_offsets(p_rect, data.anchor, data.offset);
+ if (is_inside_tree()) {
+ _size_changed();
+ }
+}
+
+Rect2 Control::get_rect() const {
+ return Rect2(get_position(), get_size());
+}
+
Rect2 Control::get_global_rect() const {
return Rect2(get_global_position(), get_size());
}
@@ -2220,118 +1401,382 @@ Rect2 Control::get_window_rect() const {
return gr;
}
-Rect2 Control::get_rect() const {
- return Rect2(get_position(), get_size());
-}
-
Rect2 Control::get_anchorable_rect() const {
return Rect2(Point2(), get_size());
}
-void Control::begin_bulk_theme_override() {
- data.bulk_theme_override = true;
+void Control::set_scale(const Vector2 &p_scale) {
+ data.scale = p_scale;
+ // Avoid having 0 scale values, can lead to errors in physics and rendering.
+ if (data.scale.x == 0) {
+ data.scale.x = CMP_EPSILON;
+ }
+ if (data.scale.y == 0) {
+ data.scale.y = CMP_EPSILON;
+ }
+ update();
+ _notify_transform();
}
-void Control::end_bulk_theme_override() {
- ERR_FAIL_COND(!data.bulk_theme_override);
+Vector2 Control::get_scale() const {
+ return data.scale;
+}
- data.bulk_theme_override = false;
- _notify_theme_changed();
+void Control::set_rotation(real_t p_radians) {
+ data.rotation = p_radians;
+ update();
+ _notify_transform();
}
-void Control::add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) {
- ERR_FAIL_COND(!p_icon.is_valid());
+real_t Control::get_rotation() const {
+ return data.rotation;
+}
- if (data.icon_override.has(p_name)) {
- data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
+void Control::set_pivot_offset(const Vector2 &p_pivot) {
+ data.pivot_offset = p_pivot;
+ update();
+ _notify_transform();
+}
+
+Vector2 Control::get_pivot_offset() const {
+ return data.pivot_offset;
+}
+
+/// Sizes.
+
+void Control::_update_minimum_size() {
+ if (!is_inside_tree()) {
+ return;
}
- data.icon_override[p_name] = p_icon;
- data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED);
- _notify_theme_changed();
+ Size2 minsize = get_combined_minimum_size();
+ data.updating_last_minimum_size = false;
+
+ if (minsize != data.last_minimum_size) {
+ data.last_minimum_size = minsize;
+ _size_changed();
+ emit_signal(SceneStringNames::get_singleton()->minimum_size_changed);
+ }
}
-void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) {
- ERR_FAIL_COND(!p_style.is_valid());
+void Control::update_minimum_size() {
+ if (!is_inside_tree() || data.block_minimum_size_adjust) {
+ return;
+ }
- if (data.style_override.has(p_name)) {
- data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
+ Control *invalidate = this;
+
+ //invalidate cache upwards
+ while (invalidate && invalidate->data.minimum_size_valid) {
+ invalidate->data.minimum_size_valid = false;
+ if (invalidate->is_set_as_top_level()) {
+ break; // do not go further up
+ }
+ if (!invalidate->data.parent && get_parent()) {
+ Window *parent_window = Object::cast_to<Window>(get_parent());
+ if (parent_window && parent_window->is_wrapping_controls()) {
+ parent_window->child_controls_changed();
+ }
+ }
+ invalidate = invalidate->data.parent;
}
- data.style_override[p_name] = p_style;
- data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED);
- _notify_theme_changed();
+ if (!is_visible_in_tree()) {
+ return;
+ }
+
+ if (data.updating_last_minimum_size) {
+ return;
+ }
+
+ data.updating_last_minimum_size = true;
+
+ MessageQueue::get_singleton()->push_call(this, "_update_minimum_size");
}
-void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) {
- ERR_FAIL_COND(!p_font.is_valid());
+void Control::set_block_minimum_size_adjust(bool p_block) {
+ data.block_minimum_size_adjust = p_block;
+}
- if (data.font_override.has(p_name)) {
- data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
+bool Control::is_minimum_size_adjust_blocked() const {
+ return data.block_minimum_size_adjust;
+}
+
+Size2 Control::get_minimum_size() const {
+ Vector2 ms;
+ if (GDVIRTUAL_CALL(_get_minimum_size, ms)) {
+ return ms;
}
+ return Vector2();
+}
- data.font_override[p_name] = p_font;
- data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_override_changed), Vector<Variant>(), CONNECT_REFERENCE_COUNTED);
- _notify_theme_changed();
+void Control::set_custom_minimum_size(const Size2 &p_custom) {
+ if (p_custom == data.custom_minimum_size) {
+ return;
+ }
+ data.custom_minimum_size = p_custom;
+ update_minimum_size();
}
-void Control::add_theme_font_size_override(const StringName &p_name, int p_font_size) {
- data.font_size_override[p_name] = p_font_size;
- _notify_theme_changed();
+Size2 Control::get_custom_minimum_size() const {
+ return data.custom_minimum_size;
}
-void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) {
- data.color_override[p_name] = p_color;
- _notify_theme_changed();
+void Control::_update_minimum_size_cache() {
+ Size2 minsize = get_minimum_size();
+ minsize.x = MAX(minsize.x, data.custom_minimum_size.x);
+ minsize.y = MAX(minsize.y, data.custom_minimum_size.y);
+
+ bool size_changed = false;
+ if (data.minimum_size_cache != minsize) {
+ size_changed = true;
+ }
+
+ data.minimum_size_cache = minsize;
+ data.minimum_size_valid = true;
+
+ if (size_changed) {
+ update_minimum_size();
+ }
}
-void Control::add_theme_constant_override(const StringName &p_name, int p_constant) {
- data.constant_override[p_name] = p_constant;
- _notify_theme_changed();
+Size2 Control::get_combined_minimum_size() const {
+ if (!data.minimum_size_valid) {
+ const_cast<Control *>(this)->_update_minimum_size_cache();
+ }
+ return data.minimum_size_cache;
}
-void Control::remove_theme_icon_override(const StringName &p_name) {
- if (data.icon_override.has(p_name)) {
- data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
+void Control::_size_changed() {
+ Rect2 parent_rect = get_parent_anchorable_rect();
+
+ real_t edge_pos[4];
+
+ for (int i = 0; i < 4; i++) {
+ real_t area = parent_rect.size[i & 1];
+ edge_pos[i] = data.offset[i] + (data.anchor[i] * area);
}
- data.icon_override.erase(p_name);
- _notify_theme_changed();
+ Point2 new_pos_cache = Point2(edge_pos[0], edge_pos[1]);
+ Size2 new_size_cache = Point2(edge_pos[2], edge_pos[3]) - new_pos_cache;
+
+ Size2 minimum_size = get_combined_minimum_size();
+
+ if (minimum_size.width > new_size_cache.width) {
+ if (data.h_grow == GROW_DIRECTION_BEGIN) {
+ new_pos_cache.x += new_size_cache.width - minimum_size.width;
+ } else if (data.h_grow == GROW_DIRECTION_BOTH) {
+ new_pos_cache.x += 0.5 * (new_size_cache.width - minimum_size.width);
+ }
+
+ new_size_cache.width = minimum_size.width;
+ }
+
+ if (is_layout_rtl()) {
+ new_pos_cache.x = parent_rect.size.x - new_pos_cache.x - new_size_cache.x;
+ }
+
+ if (minimum_size.height > new_size_cache.height) {
+ if (data.v_grow == GROW_DIRECTION_BEGIN) {
+ new_pos_cache.y += new_size_cache.height - minimum_size.height;
+ } else if (data.v_grow == GROW_DIRECTION_BOTH) {
+ new_pos_cache.y += 0.5 * (new_size_cache.height - minimum_size.height);
+ }
+
+ new_size_cache.height = minimum_size.height;
+ }
+
+ bool pos_changed = new_pos_cache != data.pos_cache;
+ bool size_changed = new_size_cache != data.size_cache;
+
+ data.pos_cache = new_pos_cache;
+ data.size_cache = new_size_cache;
+
+ if (is_inside_tree()) {
+ if (size_changed) {
+ notification(NOTIFICATION_RESIZED);
+ }
+ if (pos_changed || size_changed) {
+ item_rect_changed(size_changed);
+ _notify_transform();
+ }
+
+ if (pos_changed && !size_changed) {
+ _update_canvas_item_transform(); //move because it won't be updated
+ }
+ }
}
-void Control::remove_theme_style_override(const StringName &p_name) {
- if (data.style_override.has(p_name)) {
- data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
+void Control::_clear_size_warning() {
+ data.size_warning = false;
+}
+
+// Container sizing.
+
+void Control::set_h_size_flags(int p_flags) {
+ if (data.h_size_flags == p_flags) {
+ return;
}
+ data.h_size_flags = p_flags;
+ emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+}
- data.style_override.erase(p_name);
- _notify_theme_changed();
+int Control::get_h_size_flags() const {
+ return data.h_size_flags;
}
-void Control::remove_theme_font_override(const StringName &p_name) {
- if (data.font_override.has(p_name)) {
- data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
+void Control::set_v_size_flags(int p_flags) {
+ if (data.v_size_flags == p_flags) {
+ return;
}
+ data.v_size_flags = p_flags;
+ emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+}
- data.font_override.erase(p_name);
- _notify_theme_changed();
+int Control::get_v_size_flags() const {
+ return data.v_size_flags;
}
-void Control::remove_theme_font_size_override(const StringName &p_name) {
- data.font_size_override.erase(p_name);
- _notify_theme_changed();
+void Control::set_stretch_ratio(real_t p_ratio) {
+ if (data.expand == p_ratio) {
+ return;
+ }
+
+ data.expand = p_ratio;
+ emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
}
-void Control::remove_theme_color_override(const StringName &p_name) {
- data.color_override.erase(p_name);
- _notify_theme_changed();
+real_t Control::get_stretch_ratio() const {
+ return data.expand;
}
-void Control::remove_theme_constant_override(const StringName &p_name) {
- data.constant_override.erase(p_name);
- _notify_theme_changed();
+// Input events.
+
+void Control::_call_gui_input(const Ref<InputEvent> &p_event) {
+ emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); //signal should be first, so it's possible to override an event (and then accept it)
+ if (!is_inside_tree() || get_viewport()->is_input_handled()) {
+ return; //input was handled, abort
+ }
+ GDVIRTUAL_CALL(_gui_input, p_event);
+ if (!is_inside_tree() || get_viewport()->is_input_handled()) {
+ return; //input was handled, abort
+ }
+ gui_input(p_event);
+}
+
+void Control::gui_input(const Ref<InputEvent> &p_event) {
+}
+
+void Control::accept_event() {
+ if (is_inside_tree()) {
+ get_viewport()->_gui_accept_event();
+ }
+}
+
+bool Control::has_point(const Point2 &p_point) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_has_point, p_point, ret)) {
+ return ret;
+ }
+ return Rect2(Point2(), get_size()).has_point(p_point);
+}
+
+void Control::set_mouse_filter(MouseFilter p_filter) {
+ ERR_FAIL_INDEX(p_filter, 3);
+ data.mouse_filter = p_filter;
+ notify_property_list_changed();
+ update_configuration_warnings();
}
+Control::MouseFilter Control::get_mouse_filter() const {
+ return data.mouse_filter;
+}
+
+void Control::set_force_pass_scroll_events(bool p_force_pass_scroll_events) {
+ data.force_pass_scroll_events = p_force_pass_scroll_events;
+}
+
+bool Control::is_force_pass_scroll_events() const {
+ return data.force_pass_scroll_events;
+}
+
+void Control::warp_mouse(const Point2 &p_position) {
+ ERR_FAIL_COND(!is_inside_tree());
+ get_viewport()->warp_mouse(get_global_transform_with_canvas().xform(p_position));
+}
+
+// Drag and drop handling.
+
+void Control::set_drag_forwarding(Object *p_target) {
+ if (p_target) {
+ data.drag_owner = p_target->get_instance_id();
+ } else {
+ data.drag_owner = ObjectID();
+ }
+}
+
+Variant Control::get_drag_data(const Point2 &p_point) {
+ if (data.drag_owner.is_valid()) {
+ Object *obj = ObjectDB::get_instance(data.drag_owner);
+ if (obj) {
+ return obj->call("_get_drag_data_fw", p_point, this);
+ }
+ }
+
+ Variant dd;
+ if (GDVIRTUAL_CALL(_get_drag_data, p_point, dd)) {
+ return dd;
+ }
+
+ return Variant();
+}
+
+bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
+ if (data.drag_owner.is_valid()) {
+ Object *obj = ObjectDB::get_instance(data.drag_owner);
+ if (obj) {
+ return obj->call("_can_drop_data_fw", p_point, p_data, this);
+ }
+ }
+
+ bool ret;
+ if (GDVIRTUAL_CALL(_can_drop_data, p_point, p_data, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void Control::drop_data(const Point2 &p_point, const Variant &p_data) {
+ if (data.drag_owner.is_valid()) {
+ Object *obj = ObjectDB::get_instance(data.drag_owner);
+ if (obj) {
+ obj->call("_drop_data_fw", p_point, p_data, this);
+ return;
+ }
+ }
+
+ GDVIRTUAL_CALL(_drop_data, p_point, p_data);
+}
+
+void Control::force_drag(const Variant &p_data, Control *p_control) {
+ ERR_FAIL_COND(!is_inside_tree());
+ ERR_FAIL_COND(p_data.get_type() == Variant::NIL);
+
+ get_viewport()->_gui_force_drag(this, p_data, p_control);
+}
+
+void Control::set_drag_preview(Control *p_control) {
+ ERR_FAIL_COND(!is_inside_tree());
+ ERR_FAIL_COND(!get_viewport()->gui_is_dragging());
+ get_viewport()->_gui_set_drag_preview(this, p_control);
+}
+
+bool Control::is_drag_successful() const {
+ return is_inside_tree() && get_viewport()->gui_is_drag_successful();
+}
+
+// Focus.
+
void Control::set_focus_mode(FocusMode p_focus_mode) {
ERR_FAIL_INDEX((int)p_focus_mode, 3);
@@ -2342,9 +1787,44 @@ void Control::set_focus_mode(FocusMode p_focus_mode) {
data.focus_mode = p_focus_mode;
}
+Control::FocusMode Control::get_focus_mode() const {
+ return data.focus_mode;
+}
+
+bool Control::has_focus() const {
+ return is_inside_tree() && get_viewport()->_gui_control_has_focus(this);
+}
+
+void Control::grab_focus() {
+ ERR_FAIL_COND(!is_inside_tree());
+
+ if (data.focus_mode == FOCUS_NONE) {
+ WARN_PRINT("This control can't grab focus. Use set_focus_mode() to allow a control to get focus.");
+ return;
+ }
+
+ get_viewport()->_gui_control_grab_focus(this);
+}
+
+void Control::grab_click_focus() {
+ ERR_FAIL_COND(!is_inside_tree());
+
+ get_viewport()->_gui_grab_click_focus(this);
+}
+
+void Control::release_focus() {
+ ERR_FAIL_COND(!is_inside_tree());
+
+ if (!has_focus()) {
+ return;
+ }
+
+ get_viewport()->gui_release_focus();
+}
+
static Control *_next_control(Control *p_from) {
if (p_from->is_set_as_top_level()) {
- return nullptr; // can't go above
+ return nullptr; // Can't go above.
}
Control *parent = Object::cast_to<Control>(p_from->get_parent());
@@ -2364,7 +1844,7 @@ static Control *_next_control(Control *p_from) {
return c;
}
- //no next in parent, try the same in parent
+ // No next in parent, try the same in parent.
return _next_control(parent);
}
@@ -2388,7 +1868,7 @@ Control *Control::find_next_valid_focus() const {
}
}
- // find next child
+ // Find next child.
Control *next_child = nullptr;
@@ -2404,7 +1884,7 @@ Control *Control::find_next_valid_focus() const {
if (!next_child) {
next_child = _next_control(from);
- if (!next_child) { //nothing else.. go up and find either window or subwindow
+ if (!next_child) { // Nothing else. Go up and find either window or subwindow.
next_child = const_cast<Control *>(this);
while (next_child && !next_child->is_set_as_top_level()) {
next_child = cast_to<Control>(next_child->get_parent());
@@ -2422,7 +1902,7 @@ Control *Control::find_next_valid_focus() const {
}
}
- if (next_child == this) { // no next control->
+ if (next_child == from || next_child == this) { // No next control.
return (get_focus_mode() == FOCUS_ALL) ? next_child : nullptr;
}
if (next_child) {
@@ -2454,7 +1934,7 @@ static Control *_prev_control(Control *p_from) {
return p_from;
}
- //no prev in parent, try the same in parent
+ // No prev in parent, try the same in parent.
return _prev_control(child);
}
@@ -2478,12 +1958,12 @@ Control *Control::find_prev_valid_focus() const {
}
}
- // find prev child
+ // Find prev child.
Control *prev_child = nullptr;
if (from->is_set_as_top_level() || !Object::cast_to<Control>(from->get_parent())) {
- //find last of the children
+ // Find last of the children.
prev_child = _prev_control(from);
@@ -2506,7 +1986,7 @@ Control *Control::find_prev_valid_focus() const {
}
}
- if (prev_child == this) { // no prev control->
+ if (prev_child == from || prev_child == this) { // No prev control.
return (get_focus_mode() == FOCUS_ALL) ? prev_child : nullptr;
}
@@ -2520,181 +2000,6 @@ Control *Control::find_prev_valid_focus() const {
return nullptr;
}
-Control::FocusMode Control::get_focus_mode() const {
- return data.focus_mode;
-}
-
-bool Control::has_focus() const {
- return is_inside_tree() && get_viewport()->_gui_control_has_focus(this);
-}
-
-void Control::grab_focus() {
- ERR_FAIL_COND(!is_inside_tree());
-
- if (data.focus_mode == FOCUS_NONE) {
- WARN_PRINT("This control can't grab focus. Use set_focus_mode() to allow a control to get focus.");
- return;
- }
-
- get_viewport()->_gui_control_grab_focus(this);
-}
-
-void Control::release_focus() {
- ERR_FAIL_COND(!is_inside_tree());
-
- if (!has_focus()) {
- return;
- }
-
- get_viewport()->gui_release_focus();
-}
-
-bool Control::is_top_level_control() const {
- return is_inside_tree() && (!data.parent_canvas_item && !data.RI && is_set_as_top_level());
-}
-
-void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) {
- Control *c = Object::cast_to<Control>(p_at);
-
- if (c && c != p_owner && c->data.theme.is_valid()) { // has a theme, this can't be propagated
- return;
- }
-
- Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr;
-
- if (w && w != p_owner_window && w->theme.is_valid()) { // has a theme, this can't be propagated
- return;
- }
-
- for (int i = 0; i < p_at->get_child_count(); i++) {
- CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i));
- if (child) {
- _propagate_theme_changed(child, p_owner, p_owner_window, p_assign);
- } else {
- Window *window = Object::cast_to<Window>(p_at->get_child(i));
- if (window) {
- _propagate_theme_changed(window, p_owner, p_owner_window, p_assign);
- }
- }
- }
-
- if (c) {
- if (p_assign) {
- c->data.theme_owner = p_owner;
- c->data.theme_owner_window = p_owner_window;
- }
- c->notification(Control::NOTIFICATION_THEME_CHANGED);
- c->emit_signal(SceneStringNames::get_singleton()->theme_changed);
- }
-
- if (w) {
- if (p_assign) {
- w->theme_owner = p_owner;
- w->theme_owner_window = p_owner_window;
- }
- w->notification(Window::NOTIFICATION_THEME_CHANGED);
- w->emit_signal(SceneStringNames::get_singleton()->theme_changed);
- }
-}
-
-void Control::_theme_changed() {
- _propagate_theme_changed(this, this, nullptr, false);
-}
-
-void Control::_notify_theme_changed() {
- if (!data.bulk_theme_override) {
- notification(NOTIFICATION_THEME_CHANGED);
- }
-}
-
-void Control::set_theme(const Ref<Theme> &p_theme) {
- if (data.theme == p_theme) {
- return;
- }
-
- if (data.theme.is_valid()) {
- data.theme->disconnect("changed", callable_mp(this, &Control::_theme_changed));
- }
-
- data.theme = p_theme;
- if (!p_theme.is_null()) {
- data.theme_owner = this;
- data.theme_owner_window = nullptr;
- _propagate_theme_changed(this, this, nullptr);
- } else {
- Control *parent_c = Object::cast_to<Control>(get_parent());
-
- if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
- Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window);
- } else {
- Window *parent_w = cast_to<Window>(get_parent());
- if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
- Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window);
- } else {
- Control::_propagate_theme_changed(this, nullptr, nullptr);
- }
- }
- }
-
- if (data.theme.is_valid()) {
- data.theme->connect("changed", callable_mp(this, &Control::_theme_changed), varray(), CONNECT_DEFERRED);
- }
-}
-
-Ref<Theme> Control::get_theme() const {
- return data.theme;
-}
-
-void Control::set_theme_type_variation(const StringName &p_theme_type) {
- data.theme_type_variation = p_theme_type;
- _propagate_theme_changed(this, data.theme_owner, data.theme_owner_window);
-}
-
-StringName Control::get_theme_type_variation() const {
- return data.theme_type_variation;
-}
-
-void Control::set_tooltip(const String &p_tooltip) {
- data.tooltip = p_tooltip;
- update_configuration_warnings();
-}
-
-String Control::get_tooltip(const Point2 &p_pos) const {
- return data.tooltip;
-}
-
-Control *Control::make_custom_tooltip(const String &p_text) const {
- Object *ret = nullptr;
- if (GDVIRTUAL_CALL(_make_custom_tooltip, p_text, ret)) {
- return Object::cast_to<Control>(ret);
- }
- return nullptr;
-}
-
-void Control::set_default_cursor_shape(CursorShape p_shape) {
- ERR_FAIL_INDEX(int(p_shape), CURSOR_MAX);
-
- data.default_cursor = p_shape;
-}
-
-Control::CursorShape Control::get_default_cursor_shape() const {
- return data.default_cursor;
-}
-
-Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const {
- return data.default_cursor;
-}
-
-Transform2D Control::get_transform() const {
- Transform2D xform = _get_internal_transform();
- xform[2] += get_position();
- return xform;
-}
-
-String Control::_get_tooltip() const {
- return data.tooltip;
-}
-
void Control::set_focus_neighbor(Side p_side, const NodePath &p_neighbor) {
ERR_FAIL_INDEX((int)p_side, 4);
data.focus_neighbor[p_side] = p_neighbor;
@@ -2861,273 +2166,1011 @@ void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, cons
}
}
-void Control::set_h_size_flags(int p_flags) {
- if (data.h_size_flags == p_flags) {
+// Rendering.
+
+void Control::set_default_cursor_shape(CursorShape p_shape) {
+ ERR_FAIL_INDEX(int(p_shape), CURSOR_MAX);
+
+ data.default_cursor = p_shape;
+}
+
+Control::CursorShape Control::get_default_cursor_shape() const {
+ return data.default_cursor;
+}
+
+Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const {
+ return data.default_cursor;
+}
+
+void Control::set_disable_visibility_clip(bool p_ignore) {
+ data.disable_visibility_clip = p_ignore;
+ update();
+}
+
+bool Control::is_visibility_clip_disabled() const {
+ return data.disable_visibility_clip;
+}
+
+void Control::set_clip_contents(bool p_clip) {
+ data.clip_contents = p_clip;
+ update();
+}
+
+bool Control::is_clipping_contents() {
+ return data.clip_contents;
+}
+
+// Theming.
+
+void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) {
+ Control *c = Object::cast_to<Control>(p_at);
+
+ if (c && c != p_owner && c->data.theme.is_valid()) { // has a theme, this can't be propagated
return;
}
- data.h_size_flags = p_flags;
- emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+
+ Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr;
+
+ if (w && w != p_owner_window && w->theme.is_valid()) { // has a theme, this can't be propagated
+ return;
+ }
+
+ for (int i = 0; i < p_at->get_child_count(); i++) {
+ CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i));
+ if (child) {
+ _propagate_theme_changed(child, p_owner, p_owner_window, p_assign);
+ } else {
+ Window *window = Object::cast_to<Window>(p_at->get_child(i));
+ if (window) {
+ _propagate_theme_changed(window, p_owner, p_owner_window, p_assign);
+ }
+ }
+ }
+
+ if (c) {
+ if (p_assign) {
+ c->data.theme_owner = p_owner;
+ c->data.theme_owner_window = p_owner_window;
+ }
+ c->notification(Control::NOTIFICATION_THEME_CHANGED);
+ c->emit_signal(SceneStringNames::get_singleton()->theme_changed);
+ }
+
+ if (w) {
+ if (p_assign) {
+ w->theme_owner = p_owner;
+ w->theme_owner_window = p_owner_window;
+ }
+ w->notification(Window::NOTIFICATION_THEME_CHANGED);
+ w->emit_signal(SceneStringNames::get_singleton()->theme_changed);
+ }
}
-int Control::get_h_size_flags() const {
- return data.h_size_flags;
+void Control::_theme_changed() {
+ _propagate_theme_changed(this, this, nullptr, false);
}
-void Control::set_v_size_flags(int p_flags) {
- if (data.v_size_flags == p_flags) {
- return;
+void Control::_theme_property_override_changed() {
+ notification(NOTIFICATION_THEME_CHANGED);
+ emit_signal(SceneStringNames::get_singleton()->theme_changed);
+ update_minimum_size(); // Overrides are likely to affect minimum size.
+}
+
+void Control::_notify_theme_changed() {
+ if (!data.bulk_theme_override) {
+ notification(NOTIFICATION_THEME_CHANGED);
}
- data.v_size_flags = p_flags;
- emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
}
-void Control::set_stretch_ratio(real_t p_ratio) {
- if (data.expand == p_ratio) {
+void Control::set_theme(const Ref<Theme> &p_theme) {
+ if (data.theme == p_theme) {
return;
}
- data.expand = p_ratio;
- emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+ if (data.theme.is_valid()) {
+ data.theme->disconnect("changed", callable_mp(this, &Control::_theme_changed));
+ }
+
+ data.theme = p_theme;
+ if (!p_theme.is_null()) {
+ data.theme_owner = this;
+ data.theme_owner_window = nullptr;
+ _propagate_theme_changed(this, this, nullptr);
+ } else {
+ Control *parent_c = Object::cast_to<Control>(get_parent());
+
+ if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
+ Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window);
+ } else {
+ Window *parent_w = cast_to<Window>(get_parent());
+ if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
+ Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window);
+ } else {
+ Control::_propagate_theme_changed(this, nullptr, nullptr);
+ }
+ }
+ }
+
+ if (data.theme.is_valid()) {
+ data.theme->connect("changed", callable_mp(this, &Control::_theme_changed), CONNECT_DEFERRED);
+ }
}
-real_t Control::get_stretch_ratio() const {
- return data.expand;
+Ref<Theme> Control::get_theme() const {
+ return data.theme;
}
-void Control::grab_click_focus() {
- ERR_FAIL_COND(!is_inside_tree());
+void Control::set_theme_type_variation(const StringName &p_theme_type) {
+ data.theme_type_variation = p_theme_type;
+ _propagate_theme_changed(this, data.theme_owner, data.theme_owner_window);
+}
- get_viewport()->_gui_grab_click_focus(this);
+StringName Control::get_theme_type_variation() const {
+ return data.theme_type_variation;
}
-void Control::update_minimum_size() {
- if (!is_inside_tree() || data.block_minimum_size_adjust) {
- return;
+/// Theme property lookup.
+
+template <class T>
+T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) {
+ ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, T(), "At least one theme type must be specified.");
+
+ // First, look through each control or window node in the branch, until no valid parent can be found.
+ // Only nodes with a theme resource attached are considered.
+ Control *theme_owner = p_theme_owner;
+ Window *theme_owner_window = p_theme_owner_window;
+
+ while (theme_owner || theme_owner_window) {
+ // For each theme resource check the theme types provided and see if p_name exists with any of them.
+ for (const StringName &E : p_theme_types) {
+ if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) {
+ return theme_owner->data.theme->get_theme_item(p_data_type, p_name, E);
+ }
+
+ if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) {
+ return theme_owner_window->theme->get_theme_item(p_data_type, p_name, E);
+ }
+ }
+
+ Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
+ Control *parent_c = Object::cast_to<Control>(parent);
+ if (parent_c) {
+ theme_owner = parent_c->data.theme_owner;
+ theme_owner_window = parent_c->data.theme_owner_window;
+ } else {
+ Window *parent_w = Object::cast_to<Window>(parent);
+ if (parent_w) {
+ theme_owner = parent_w->theme_owner;
+ theme_owner_window = parent_w->theme_owner_window;
+ } else {
+ theme_owner = nullptr;
+ theme_owner_window = nullptr;
+ }
+ }
}
- Control *invalidate = this;
+ // Secondly, check the project-defined Theme resource.
+ if (Theme::get_project_default().is_valid()) {
+ for (const StringName &E : p_theme_types) {
+ if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) {
+ return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E);
+ }
+ }
+ }
- //invalidate cache upwards
- while (invalidate && invalidate->data.minimum_size_valid) {
- invalidate->data.minimum_size_valid = false;
- if (invalidate->is_set_as_top_level()) {
- break; // do not go further up
+ // Lastly, fall back on the items defined in the default Theme, if they exist.
+ for (const StringName &E : p_theme_types) {
+ if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) {
+ return Theme::get_default()->get_theme_item(p_data_type, p_name, E);
}
- if (!invalidate->data.parent && get_parent()) {
- Window *parent_window = Object::cast_to<Window>(get_parent());
- if (parent_window && parent_window->is_wrapping_controls()) {
- parent_window->child_controls_changed();
+ }
+ // If they don't exist, use any type to return the default/empty value.
+ return Theme::get_default()->get_theme_item(p_data_type, p_name, p_theme_types[0]);
+}
+
+bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) {
+ ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, false, "At least one theme type must be specified.");
+
+ // First, look through each control or window node in the branch, until no valid parent can be found.
+ // Only nodes with a theme resource attached are considered.
+ Control *theme_owner = p_theme_owner;
+ Window *theme_owner_window = p_theme_owner_window;
+
+ while (theme_owner || theme_owner_window) {
+ // For each theme resource check the theme types provided and see if p_name exists with any of them.
+ for (const StringName &E : p_theme_types) {
+ if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) {
+ return true;
+ }
+
+ if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) {
+ return true;
+ }
+ }
+
+ Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
+ Control *parent_c = Object::cast_to<Control>(parent);
+ if (parent_c) {
+ theme_owner = parent_c->data.theme_owner;
+ theme_owner_window = parent_c->data.theme_owner_window;
+ } else {
+ Window *parent_w = Object::cast_to<Window>(parent);
+ if (parent_w) {
+ theme_owner = parent_w->theme_owner;
+ theme_owner_window = parent_w->theme_owner_window;
+ } else {
+ theme_owner = nullptr;
+ theme_owner_window = nullptr;
}
}
- invalidate = invalidate->data.parent;
}
- if (!is_visible_in_tree()) {
- return;
+ // Secondly, check the project-defined Theme resource.
+ if (Theme::get_project_default().is_valid()) {
+ for (const StringName &E : p_theme_types) {
+ if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) {
+ return true;
+ }
+ }
}
- if (data.updating_last_minimum_size) {
- return;
+ // Lastly, fall back on the items defined in the default Theme, if they exist.
+ for (const StringName &E : p_theme_types) {
+ if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) {
+ return true;
+ }
}
+ return false;
+}
- data.updating_last_minimum_size = true;
+void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
+ if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(data.theme_type_variation) != StringName()) {
+ Theme::get_project_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
+ } else {
+ Theme::get_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
+ }
+ } else {
+ Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list);
+ }
+}
- MessageQueue::get_singleton()->push_call(this, "_update_minimum_size");
+Ref<Texture2D> Control::get_theme_icon(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<Texture2D> *tex = data.icon_override.getptr(p_name);
+ if (tex) {
+ return *tex;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<Ref<Texture2D>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
}
-int Control::get_v_size_flags() const {
- return data.v_size_flags;
+Ref<StyleBox> Control::get_theme_stylebox(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<StyleBox> *style = data.style_override.getptr(p_name);
+ if (style) {
+ return *style;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<Ref<StyleBox>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
}
-void Control::set_mouse_filter(MouseFilter p_filter) {
- ERR_FAIL_INDEX(p_filter, 3);
- data.mouse_filter = p_filter;
- notify_property_list_changed();
- update_configuration_warnings();
+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) {
+ return *font;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<Ref<Font>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
}
-Control::MouseFilter Control::get_mouse_filter() const {
- return data.mouse_filter;
+int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
+ const int *font_size = data.font_size_override.getptr(p_name);
+ if (font_size && (*font_size) > 0) {
+ return *font_size;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
}
-void Control::set_force_pass_scroll_events(bool p_force_pass_scroll_events) {
- data.force_pass_scroll_events = p_force_pass_scroll_events;
+Color Control::get_theme_color(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 Color *color = data.color_override.getptr(p_name);
+ if (color) {
+ return *color;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<Color>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
}
-bool Control::is_force_pass_scroll_events() const {
- return data.force_pass_scroll_events;
+int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
+ const int *constant = data.constant_override.getptr(p_name);
+ if (constant) {
+ return *constant;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
}
-void Control::warp_mouse(const Point2 &p_position) {
- ERR_FAIL_COND(!is_inside_tree());
- get_viewport()->warp_mouse(get_global_transform_with_canvas().xform(p_position));
+bool Control::has_theme_icon(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) {
+ if (has_theme_icon_override(p_name)) {
+ return true;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
}
-bool Control::is_text_field() const {
- return false;
+bool Control::has_theme_stylebox(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) {
+ if (has_theme_stylebox_override(p_name)) {
+ return true;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
}
-Array Control::structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
- if (p_parser_type == TextServer::STRUCTURED_TEXT_CUSTOM) {
- Array ret;
- if (GDVIRTUAL_CALL(_structured_text_parser, p_args, p_text, ret)) {
- return ret;
- } else {
- return Array();
+bool Control::has_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) {
+ if (has_theme_font_override(p_name)) {
+ return true;
}
- } else {
- return TS->parse_structured_text(p_parser_type, p_args, p_text);
}
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
}
-void Control::set_rotation(real_t p_radians) {
- data.rotation = p_radians;
- update();
- _notify_transform();
+bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
+ if (has_theme_font_size_override(p_name)) {
+ return true;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
}
-real_t Control::get_rotation() const {
- return data.rotation;
+bool Control::has_theme_color(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) {
+ if (has_theme_color_override(p_name)) {
+ return true;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
}
-void Control::_override_changed() {
- notification(NOTIFICATION_THEME_CHANGED);
- emit_signal(SceneStringNames::get_singleton()->theme_changed);
- update_minimum_size(); // Overrides are likely to affect minimum size.
+bool Control::has_theme_constant(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) {
+ if (has_theme_constant_override(p_name)) {
+ return true;
+ }
+ }
+
+ List<StringName> theme_types;
+ _get_theme_type_dependencies(p_theme_type, &theme_types);
+ return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
}
-void Control::set_pivot_offset(const Vector2 &p_pivot) {
- data.pivot_offset = p_pivot;
- update();
- _notify_transform();
+/// Local property overrides.
+
+void Control::add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) {
+ ERR_FAIL_COND(!p_icon.is_valid());
+
+ if (data.icon_override.has(p_name)) {
+ data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
+ }
+
+ data.icon_override[p_name] = p_icon;
+ data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED);
+ _notify_theme_changed();
}
-Vector2 Control::get_pivot_offset() const {
- return data.pivot_offset;
+void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) {
+ ERR_FAIL_COND(!p_style.is_valid());
+
+ if (data.style_override.has(p_name)) {
+ data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
+ }
+
+ data.style_override[p_name] = p_style;
+ data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED);
+ _notify_theme_changed();
}
-void Control::set_scale(const Vector2 &p_scale) {
- data.scale = p_scale;
- // Avoid having 0 scale values, can lead to errors in physics and rendering.
- if (data.scale.x == 0) {
- data.scale.x = CMP_EPSILON;
+void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) {
+ ERR_FAIL_COND(!p_font.is_valid());
+
+ if (data.font_override.has(p_name)) {
+ data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
}
- if (data.scale.y == 0) {
- data.scale.y = CMP_EPSILON;
+
+ data.font_override[p_name] = p_font;
+ data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED);
+ _notify_theme_changed();
+}
+
+void Control::add_theme_font_size_override(const StringName &p_name, int p_font_size) {
+ data.font_size_override[p_name] = p_font_size;
+ _notify_theme_changed();
+}
+
+void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) {
+ data.color_override[p_name] = p_color;
+ _notify_theme_changed();
+}
+
+void Control::add_theme_constant_override(const StringName &p_name, int p_constant) {
+ data.constant_override[p_name] = p_constant;
+ _notify_theme_changed();
+}
+
+void Control::remove_theme_icon_override(const StringName &p_name) {
+ if (data.icon_override.has(p_name)) {
+ data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
}
- update();
- _notify_transform();
+
+ data.icon_override.erase(p_name);
+ _notify_theme_changed();
}
-Vector2 Control::get_scale() const {
- return data.scale;
+void Control::remove_theme_style_override(const StringName &p_name) {
+ if (data.style_override.has(p_name)) {
+ data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
+ }
+
+ data.style_override.erase(p_name);
+ _notify_theme_changed();
}
-Control *Control::get_root_parent_control() const {
- const CanvasItem *ci = this;
- const Control *root = this;
+void Control::remove_theme_font_override(const StringName &p_name) {
+ if (data.font_override.has(p_name)) {
+ data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
+ }
- while (ci) {
- const Control *c = Object::cast_to<Control>(ci);
- if (c) {
- root = c;
+ data.font_override.erase(p_name);
+ _notify_theme_changed();
+}
- if (c->data.RI || c->is_top_level_control()) {
- break;
+void Control::remove_theme_font_size_override(const StringName &p_name) {
+ data.font_size_override.erase(p_name);
+ _notify_theme_changed();
+}
+
+void Control::remove_theme_color_override(const StringName &p_name) {
+ data.color_override.erase(p_name);
+ _notify_theme_changed();
+}
+
+void Control::remove_theme_constant_override(const StringName &p_name) {
+ data.constant_override.erase(p_name);
+ _notify_theme_changed();
+}
+
+bool Control::has_theme_icon_override(const StringName &p_name) const {
+ const Ref<Texture2D> *tex = data.icon_override.getptr(p_name);
+ return tex != nullptr;
+}
+
+bool Control::has_theme_stylebox_override(const StringName &p_name) const {
+ const Ref<StyleBox> *style = data.style_override.getptr(p_name);
+ return style != nullptr;
+}
+
+bool Control::has_theme_font_override(const StringName &p_name) const {
+ const Ref<Font> *font = data.font_override.getptr(p_name);
+ return font != nullptr;
+}
+
+bool Control::has_theme_font_size_override(const StringName &p_name) const {
+ const int *font_size = data.font_size_override.getptr(p_name);
+ return font_size != nullptr;
+}
+
+bool Control::has_theme_color_override(const StringName &p_name) const {
+ const Color *color = data.color_override.getptr(p_name);
+ return color != nullptr;
+}
+
+bool Control::has_theme_constant_override(const StringName &p_name) const {
+ const int *constant = data.constant_override.getptr(p_name);
+ return constant != nullptr;
+}
+
+/// Default theme properties.
+
+float Control::fetch_theme_default_base_scale(Control *p_theme_owner, Window *p_theme_owner_window) {
+ // First, look through each control or window node in the branch, until no valid parent can be found.
+ // Only nodes with a theme resource attached are considered.
+ // For each theme resource see if their assigned theme has the default value defined and valid.
+ Control *theme_owner = p_theme_owner;
+ Window *theme_owner_window = p_theme_owner_window;
+
+ while (theme_owner || theme_owner_window) {
+ if (theme_owner && theme_owner->data.theme->has_default_base_scale()) {
+ return theme_owner->data.theme->get_default_base_scale();
+ }
+
+ if (theme_owner_window && theme_owner_window->theme->has_default_base_scale()) {
+ return theme_owner_window->theme->get_default_base_scale();
+ }
+
+ Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
+ Control *parent_c = Object::cast_to<Control>(parent);
+ if (parent_c) {
+ theme_owner = parent_c->data.theme_owner;
+ theme_owner_window = parent_c->data.theme_owner_window;
+ } else {
+ Window *parent_w = Object::cast_to<Window>(parent);
+ if (parent_w) {
+ theme_owner = parent_w->theme_owner;
+ theme_owner_window = parent_w->theme_owner_window;
+ } else {
+ theme_owner = nullptr;
+ theme_owner_window = nullptr;
}
}
+ }
- ci = ci->get_parent_item();
+ // Secondly, check the project-defined Theme resource.
+ if (Theme::get_project_default().is_valid()) {
+ if (Theme::get_project_default()->has_default_base_scale()) {
+ return Theme::get_project_default()->get_default_base_scale();
+ }
}
- return const_cast<Control *>(root);
+ // Lastly, fall back on the default Theme.
+ if (Theme::get_default()->has_default_base_scale()) {
+ return Theme::get_default()->get_default_base_scale();
+ }
+ return Theme::get_fallback_base_scale();
}
-void Control::set_block_minimum_size_adjust(bool p_block) {
- data.block_minimum_size_adjust = p_block;
+float Control::get_theme_default_base_scale() const {
+ return fetch_theme_default_base_scale(data.theme_owner, data.theme_owner_window);
}
-bool Control::is_minimum_size_adjust_blocked() const {
- return data.block_minimum_size_adjust;
-}
+Ref<Font> Control::fetch_theme_default_font(Control *p_theme_owner, Window *p_theme_owner_window) {
+ // First, look through each control or window node in the branch, until no valid parent can be found.
+ // Only nodes with a theme resource attached are considered.
+ // For each theme resource see if their assigned theme has the default value defined and valid.
+ Control *theme_owner = p_theme_owner;
+ Window *theme_owner_window = p_theme_owner_window;
-void Control::set_disable_visibility_clip(bool p_ignore) {
- data.disable_visibility_clip = p_ignore;
- update();
+ while (theme_owner || theme_owner_window) {
+ if (theme_owner && theme_owner->data.theme->has_default_font()) {
+ return theme_owner->data.theme->get_default_font();
+ }
+
+ if (theme_owner_window && theme_owner_window->theme->has_default_font()) {
+ return theme_owner_window->theme->get_default_font();
+ }
+
+ Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
+ Control *parent_c = Object::cast_to<Control>(parent);
+ if (parent_c) {
+ theme_owner = parent_c->data.theme_owner;
+ theme_owner_window = parent_c->data.theme_owner_window;
+ } else {
+ Window *parent_w = Object::cast_to<Window>(parent);
+ if (parent_w) {
+ theme_owner = parent_w->theme_owner;
+ theme_owner_window = parent_w->theme_owner_window;
+ } else {
+ theme_owner = nullptr;
+ theme_owner_window = nullptr;
+ }
+ }
+ }
+
+ // Secondly, check the project-defined Theme resource.
+ if (Theme::get_project_default().is_valid()) {
+ if (Theme::get_project_default()->has_default_font()) {
+ return Theme::get_project_default()->get_default_font();
+ }
+ }
+
+ // Lastly, fall back on the default Theme.
+ if (Theme::get_default()->has_default_font()) {
+ return Theme::get_default()->get_default_font();
+ }
+ return Theme::get_fallback_font();
}
-bool Control::is_visibility_clip_disabled() const {
- return data.disable_visibility_clip;
+Ref<Font> Control::get_theme_default_font() const {
+ return fetch_theme_default_font(data.theme_owner, data.theme_owner_window);
}
-void Control::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
- Node::get_argument_options(p_function, p_idx, r_options);
+int Control::fetch_theme_default_font_size(Control *p_theme_owner, Window *p_theme_owner_window) {
+ // First, look through each control or window node in the branch, until no valid parent can be found.
+ // Only nodes with a theme resource attached are considered.
+ // For each theme resource see if their assigned theme has the default value defined and valid.
+ Control *theme_owner = p_theme_owner;
+ Window *theme_owner_window = p_theme_owner_window;
- if (p_idx == 0) {
- List<StringName> sn;
- String pf = p_function;
- if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color") {
- Theme::get_default()->get_color_list(get_class(), &sn);
- } else if (pf == "add_theme_style_override" || pf == "has_theme_style" || pf == "has_theme_style_override" || pf == "get_theme_style") {
- Theme::get_default()->get_stylebox_list(get_class(), &sn);
- } else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font") {
- Theme::get_default()->get_font_list(get_class(), &sn);
- } else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size") {
- Theme::get_default()->get_font_size_list(get_class(), &sn);
- } else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant") {
- Theme::get_default()->get_constant_list(get_class(), &sn);
+ while (theme_owner || theme_owner_window) {
+ if (theme_owner && theme_owner->data.theme->has_default_font_size()) {
+ return theme_owner->data.theme->get_default_font_size();
}
- sn.sort_custom<StringName::AlphCompare>();
- for (const StringName &name : sn) {
- r_options->push_back(String(name).quote());
+ if (theme_owner_window && theme_owner_window->theme->has_default_font_size()) {
+ return theme_owner_window->theme->get_default_font_size();
+ }
+
+ Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
+ Control *parent_c = Object::cast_to<Control>(parent);
+ if (parent_c) {
+ theme_owner = parent_c->data.theme_owner;
+ theme_owner_window = parent_c->data.theme_owner_window;
+ } else {
+ Window *parent_w = Object::cast_to<Window>(parent);
+ if (parent_w) {
+ theme_owner = parent_w->theme_owner;
+ theme_owner_window = parent_w->theme_owner_window;
+ } else {
+ theme_owner = nullptr;
+ theme_owner_window = nullptr;
+ }
}
}
+
+ // Secondly, check the project-defined Theme resource.
+ if (Theme::get_project_default().is_valid()) {
+ if (Theme::get_project_default()->has_default_font_size()) {
+ return Theme::get_project_default()->get_default_font_size();
+ }
+ }
+
+ // Lastly, fall back on the default Theme.
+ if (Theme::get_default()->has_default_font_size()) {
+ return Theme::get_default()->get_default_font_size();
+ }
+ return Theme::get_fallback_font_size();
}
-TypedArray<String> Control::get_configuration_warnings() const {
- TypedArray<String> warnings = Node::get_configuration_warnings();
+int Control::get_theme_default_font_size() const {
+ return fetch_theme_default_font_size(data.theme_owner, data.theme_owner_window);
+}
- if (data.mouse_filter == MOUSE_FILTER_IGNORE && !data.tooltip.is_empty()) {
- warnings.push_back(RTR("The Hint Tooltip won't be displayed as the control's Mouse Filter is set to \"Ignore\". To solve this, set the Mouse Filter to \"Stop\" or \"Pass\"."));
+/// Bulk actions.
+
+void Control::begin_bulk_theme_override() {
+ data.bulk_theme_override = true;
+}
+
+void Control::end_bulk_theme_override() {
+ ERR_FAIL_COND(!data.bulk_theme_override);
+
+ data.bulk_theme_override = false;
+ _notify_theme_changed();
+}
+
+// Internationalization.
+
+Array Control::structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ if (p_parser_type == TextServer::STRUCTURED_TEXT_CUSTOM) {
+ Array ret;
+ if (GDVIRTUAL_CALL(_structured_text_parser, p_args, p_text, ret)) {
+ return ret;
+ } else {
+ return Array();
+ }
+ } else {
+ return TS->parse_structured_text(p_parser_type, p_args, p_text);
}
+}
- return warnings;
+void Control::set_layout_direction(Control::LayoutDirection p_direction) {
+ ERR_FAIL_INDEX((int)p_direction, 4);
+
+ data.layout_dir = p_direction;
+ data.is_rtl_dirty = true;
+
+ propagate_notification(NOTIFICATION_LAYOUT_DIRECTION_CHANGED);
}
-void Control::set_clip_contents(bool p_clip) {
- data.clip_contents = p_clip;
- update();
+Control::LayoutDirection Control::get_layout_direction() const {
+ return data.layout_dir;
}
-bool Control::is_clipping_contents() {
- return data.clip_contents;
+bool Control::is_layout_rtl() const {
+ if (data.is_rtl_dirty) {
+ const_cast<Control *>(this)->data.is_rtl_dirty = false;
+ if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) {
+ Window *parent_window = get_parent_window();
+ Control *parent_control = get_parent_control();
+ if (parent_control) {
+ const_cast<Control *>(this)->data.is_rtl = parent_control->is_layout_rtl();
+ } else if (parent_window) {
+ const_cast<Control *>(this)->data.is_rtl = parent_window->is_layout_rtl();
+ } else {
+ if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
+ const_cast<Control *>(this)->data.is_rtl = true;
+ } else {
+ String locale = TranslationServer::get_singleton()->get_tool_locale();
+ const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
+ }
+ }
+ } else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) {
+ if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
+ const_cast<Control *>(this)->data.is_rtl = true;
+ } else {
+ String locale = TranslationServer::get_singleton()->get_tool_locale();
+ const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
+ }
+ } else {
+ const_cast<Control *>(this)->data.is_rtl = (data.layout_dir == LAYOUT_DIRECTION_RTL);
+ }
+ }
+ return data.is_rtl;
}
-void Control::set_h_grow_direction(GrowDirection p_direction) {
- ERR_FAIL_INDEX((int)p_direction, 3);
+void Control::set_auto_translate(bool p_enable) {
+ if (p_enable == data.auto_translate) {
+ return;
+ }
- data.h_grow = p_direction;
- _size_changed();
+ data.auto_translate = p_enable;
+
+ notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED);
}
-Control::GrowDirection Control::get_h_grow_direction() const {
- return data.h_grow;
+bool Control::is_auto_translating() const {
+ return data.auto_translate;
}
-void Control::set_v_grow_direction(GrowDirection p_direction) {
- ERR_FAIL_INDEX((int)p_direction, 3);
+// Extra properties.
- data.v_grow = p_direction;
- _size_changed();
+void Control::set_tooltip(const String &p_tooltip) {
+ data.tooltip = p_tooltip;
+ update_configuration_warnings();
}
-Control::GrowDirection Control::get_v_grow_direction() const {
- return data.v_grow;
+String Control::_get_tooltip() const {
+ return data.tooltip;
+}
+
+String Control::get_tooltip(const Point2 &p_pos) const {
+ return data.tooltip;
+}
+
+Control *Control::make_custom_tooltip(const String &p_text) const {
+ Object *ret = nullptr;
+ if (GDVIRTUAL_CALL(_make_custom_tooltip, p_text, ret)) {
+ return Object::cast_to<Control>(ret);
+ }
+ return nullptr;
+}
+
+// Base object overrides.
+
+void Control::add_child_notify(Node *p_child) {
+ Control *child_c = Object::cast_to<Control>(p_child);
+
+ if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
+ _propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
+ }
+
+ Window *child_w = Object::cast_to<Window>(p_child);
+
+ if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
+ _propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
+ }
+}
+
+void Control::remove_child_notify(Node *p_child) {
+ Control *child_c = Object::cast_to<Control>(p_child);
+
+ if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) {
+ _propagate_theme_changed(child_c, nullptr, nullptr);
+ }
+
+ Window *child_w = Object::cast_to<Window>(p_child);
+
+ if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) {
+ _propagate_theme_changed(child_w, nullptr, nullptr);
+ }
+}
+
+void Control::_notification(int p_notification) {
+ switch (p_notification) {
+ case NOTIFICATION_POST_ENTER_TREE: {
+ data.minimum_size_valid = false;
+ data.is_rtl_dirty = true;
+ _size_changed();
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ release_focus();
+ get_viewport()->_gui_remove_control(this);
+ } break;
+
+ case NOTIFICATION_READY: {
+#ifdef DEBUG_ENABLED
+ connect("ready", callable_mp(this, &Control::_clear_size_warning), CONNECT_DEFERRED | CONNECT_ONESHOT);
+#endif
+ } break;
+
+ case NOTIFICATION_ENTER_CANVAS: {
+ data.parent = Object::cast_to<Control>(get_parent());
+ data.parent_window = Object::cast_to<Window>(get_parent());
+ data.is_rtl_dirty = true;
+
+ if (data.theme.is_null()) {
+ if (data.parent && (data.parent->data.theme_owner || data.parent->data.theme_owner_window)) {
+ data.theme_owner = data.parent->data.theme_owner;
+ data.theme_owner_window = data.parent->data.theme_owner_window;
+ notification(NOTIFICATION_THEME_CHANGED);
+ } else if (data.parent_window && (data.parent_window->theme_owner || data.parent_window->theme_owner_window)) {
+ data.theme_owner = data.parent_window->theme_owner;
+ data.theme_owner_window = data.parent_window->theme_owner_window;
+ notification(NOTIFICATION_THEME_CHANGED);
+ }
+ }
+
+ CanvasItem *node = this;
+ bool has_parent_control = false;
+
+ while (!node->is_set_as_top_level()) {
+ CanvasItem *parent = Object::cast_to<CanvasItem>(node->get_parent());
+ if (!parent) {
+ break;
+ }
+
+ Control *parent_control = Object::cast_to<Control>(parent);
+ if (parent_control) {
+ has_parent_control = true;
+ break;
+ }
+
+ node = parent;
+ }
+
+ if (has_parent_control) {
+ // Do nothing, has a parent control.
+ } else {
+ // Is a regular root control or top_level.
+ Viewport *viewport = get_viewport();
+ ERR_FAIL_COND(!viewport);
+ data.RI = viewport->_gui_add_root_control(this);
+ }
+
+ data.parent_canvas_item = get_parent_item();
+
+ if (data.parent_canvas_item) {
+ data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed));
+ } else {
+ // Connect viewport.
+ Viewport *viewport = get_viewport();
+ ERR_FAIL_COND(!viewport);
+ viewport->connect("size_changed", callable_mp(this, &Control::_size_changed));
+ }
+ } break;
+
+ case NOTIFICATION_EXIT_CANVAS: {
+ if (data.parent_canvas_item) {
+ data.parent_canvas_item->disconnect("item_rect_changed", callable_mp(this, &Control::_size_changed));
+ data.parent_canvas_item = nullptr;
+ } else if (!is_set_as_top_level()) {
+ //disconnect viewport
+ Viewport *viewport = get_viewport();
+ ERR_FAIL_COND(!viewport);
+ viewport->disconnect("size_changed", callable_mp(this, &Control::_size_changed));
+ }
+
+ if (data.RI) {
+ get_viewport()->_gui_remove_root_control(data.RI);
+ data.RI = nullptr;
+ }
+
+ data.parent = nullptr;
+ data.parent_canvas_item = nullptr;
+ data.parent_window = nullptr;
+ data.is_rtl_dirty = true;
+ } break;
+
+ case NOTIFICATION_MOVED_IN_PARENT: {
+ // some parents need to know the order of the children to draw (like TabContainer)
+ // update if necessary
+ if (data.parent) {
+ data.parent->update();
+ }
+ update();
+
+ if (data.RI) {
+ get_viewport()->_gui_set_root_order_dirty();
+ }
+ } break;
+
+ case NOTIFICATION_RESIZED: {
+ emit_signal(SceneStringNames::get_singleton()->resized);
+ } break;
+
+ case NOTIFICATION_DRAW: {
+ _update_canvas_item_transform();
+ RenderingServer::get_singleton()->canvas_item_set_custom_rect(get_canvas_item(), !data.disable_visibility_clip, Rect2(Point2(), get_size()));
+ RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), data.clip_contents);
+ } break;
+
+ case NOTIFICATION_MOUSE_ENTER: {
+ emit_signal(SceneStringNames::get_singleton()->mouse_entered);
+ } break;
+
+ case NOTIFICATION_MOUSE_EXIT: {
+ emit_signal(SceneStringNames::get_singleton()->mouse_exited);
+ } break;
+
+ case NOTIFICATION_FOCUS_ENTER: {
+ emit_signal(SceneStringNames::get_singleton()->focus_entered);
+ update();
+ } break;
+
+ case NOTIFICATION_FOCUS_EXIT: {
+ emit_signal(SceneStringNames::get_singleton()->focus_exited);
+ update();
+ } break;
+
+ case NOTIFICATION_THEME_CHANGED: {
+ update_minimum_size();
+ update();
+ } break;
+
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible_in_tree()) {
+ if (get_viewport() != nullptr) {
+ get_viewport()->_gui_hide_control(this);
+ }
+ } else {
+ data.minimum_size_valid = false;
+ _update_minimum_size();
+ _size_changed();
+ }
+ } break;
+
+ case NOTIFICATION_TRANSLATION_CHANGED:
+ case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
+ if (is_inside_tree()) {
+ data.is_rtl_dirty = true;
+ _size_changed();
+ }
+ } break;
+ }
}
void Control::_bind_methods() {
- //ClassDB::bind_method(D_METHOD("_window_resize_event"),&Control::_window_resize_event);
ClassDB::bind_method(D_METHOD("_update_minimum_size"), &Control::_update_minimum_size);
ClassDB::bind_method(D_METHOD("accept_event"), &Control::accept_event);
@@ -3300,7 +3343,7 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode");
ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION);
- const String anchors_presets_options = "Custom:-1,PresetWide:15,"
+ const String anchors_presets_options = "Custom:-1,PresetFullRect:15,"
"PresetTopLeft:0,PresetTopRight:1,PresetBottomRight:3,PresetBottomLeft:2,"
"PresetCenterLeft:4,PresetCenterTop:5,PresetCenterRight:6,PresetCenterBottom:7,PresetCenter:8,"
"PresetLeftWide:9,PresetTopWide:10,PresetRightWide:11,PresetBottomWide:12,PresetVCenterWide:13,PresetHCenterWide:14";
@@ -3408,7 +3451,7 @@ void Control::_bind_methods() {
BIND_ENUM_CONSTANT(PRESET_BOTTOM_WIDE);
BIND_ENUM_CONSTANT(PRESET_VCENTER_WIDE);
BIND_ENUM_CONSTANT(PRESET_HCENTER_WIDE);
- BIND_ENUM_CONSTANT(PRESET_WIDE);
+ BIND_ENUM_CONSTANT(PRESET_FULL_RECT);
BIND_ENUM_CONSTANT(PRESET_MODE_MINSIZE);
BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_WIDTH);
diff --git a/scene/gui/control.h b/scene/gui/control.h
index f18dd99bff..9f17eccc3b 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -116,7 +116,7 @@ public:
PRESET_BOTTOM_WIDE,
PRESET_VCENTER_WIDE,
PRESET_HCENTER_WIDE,
- PRESET_WIDE
+ PRESET_FULL_RECT
};
enum LayoutPresetMode {
@@ -159,13 +159,16 @@ private:
};
struct Data {
- Point2 pos_cache;
- Size2 size_cache;
- Size2 minimum_size_cache;
- bool minimum_size_valid = false;
+ // Global relations.
- Size2 last_minimum_size;
- bool updating_last_minimum_size = false;
+ List<Control *>::Element *RI = nullptr;
+
+ Control *parent = nullptr;
+ Window *parent_window = nullptr;
+ CanvasItem *parent_canvas_item = nullptr;
+ ObjectID drag_owner;
+
+ // Positioning and sizing.
real_t offset[4] = { 0.0, 0.0, 0.0, 0.0 };
real_t anchor[4] = { ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN, ANCHOR_BEGIN };
@@ -173,49 +176,51 @@ private:
GrowDirection h_grow = GROW_DIRECTION_END;
GrowDirection v_grow = GROW_DIRECTION_END;
- LayoutDirection layout_dir = LAYOUT_DIRECTION_INHERITED;
- bool is_rtl_dirty = true;
- bool is_rtl = false;
-
- bool auto_translate = true;
-
real_t rotation = 0.0;
Vector2 scale = Vector2(1, 1);
Vector2 pivot_offset;
+
+ Point2 pos_cache;
+ Size2 size_cache;
+ Size2 minimum_size_cache;
+ bool minimum_size_valid = false;
+
+ Size2 last_minimum_size;
+ bool updating_last_minimum_size = false;
+ bool block_minimum_size_adjust = false;
+
bool size_warning = true;
+ // Container sizing.
+
int h_size_flags = SIZE_FILL;
int v_size_flags = SIZE_FILL;
real_t expand = 1.0;
Point2 custom_minimum_size;
+ // Input events and rendering.
+
MouseFilter mouse_filter = MOUSE_FILTER_STOP;
bool force_pass_scroll_events = true;
bool clip_contents = false;
-
- bool block_minimum_size_adjust = false;
bool disable_visibility_clip = false;
- Control *parent = nullptr;
- ObjectID drag_owner;
- Ref<Theme> theme;
- Control *theme_owner = nullptr;
- Window *theme_owner_window = nullptr;
- Window *parent_window = nullptr;
- StringName theme_type_variation;
-
- String tooltip;
CursorShape default_cursor = CURSOR_ARROW;
- List<Control *>::Element *RI = nullptr;
-
- CanvasItem *parent_canvas_item = nullptr;
+ // Focus.
NodePath focus_neighbor[4];
NodePath focus_next;
NodePath focus_prev;
+ // Theming.
+
+ Ref<Theme> theme;
+ Control *theme_owner = nullptr;
+ Window *theme_owner_window = nullptr;
+ StringName theme_type_variation;
+
bool bulk_theme_override = false;
Theme::ThemeIconMap icon_override;
Theme::ThemeStyleMap style_override;
@@ -224,50 +229,69 @@ private:
Theme::ThemeColorMap color_override;
Theme::ThemeConstantMap constant_override;
+ // Internationalization.
+
+ LayoutDirection layout_dir = LAYOUT_DIRECTION_INHERITED;
+ bool is_rtl_dirty = true;
+ bool is_rtl = false;
+
+ bool auto_translate = true;
+
+ // Extra properties.
+
+ String tooltip;
+
} data;
+ // Dynamic properties.
+
static constexpr unsigned properties_managed_by_container_count = 12;
static String properties_managed_by_container[properties_managed_by_container_count];
- void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest);
- Control *_get_focus_neighbor(Side p_side, int p_count = 0);
+ // Global relations.
+
+ friend class Viewport;
+ friend class Window;
+
+ // Positioning and sizing.
+
+ void _update_canvas_item_transform();
+ Transform2D _get_internal_transform() const;
void _set_anchor(Side p_side, real_t p_anchor);
void _set_position(const Point2 &p_point);
void _set_global_position(const Point2 &p_point);
void _set_size(const Size2 &p_size);
+ void _compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]);
+ void _compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]);
+
void _set_layout_mode(LayoutMode p_mode);
LayoutMode _get_layout_mode() const;
-
void _set_anchors_layout_preset(int p_preset);
int _get_anchors_layout_preset() const;
- void _theme_changed();
- void _notify_theme_changed();
-
+ void _update_minimum_size_cache();
void _update_minimum_size();
+ void _size_changed();
void _clear_size_warning();
- void _compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]);
- void _compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]);
-
- void _size_changed();
- String _get_tooltip() const;
+ // Input events.
- void _override_changed();
+ void _call_gui_input(const Ref<InputEvent> &p_event);
- void _update_canvas_item_transform();
+ // Focus.
- Transform2D _get_internal_transform() const;
+ void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest);
+ Control *_get_focus_neighbor(Side p_side, int p_count = 0);
- friend class Viewport;
+ // Theming.
- void _call_gui_input(const Ref<InputEvent> &p_event);
+ void _theme_changed();
+ void _theme_property_override_changed();
+ void _notify_theme_changed();
- void _update_minimum_size_cache();
- friend class Window;
static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true);
template <class T>
@@ -275,24 +299,31 @@ private:
static bool has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types);
_FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const;
-protected:
- virtual void add_child_notify(Node *p_child) override;
- virtual void remove_child_notify(Node *p_child) override;
+ // Extra properties.
- //virtual void _window_gui_input(InputEvent p_event);
+ String _get_tooltip() const;
- virtual Array structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+protected:
+ // Dynamic properties.
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 _validate_property(PropertyInfo &property) const override;
+ // Internationalization.
+
+ virtual Array structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+
+ // Base object overrides.
+
+ virtual void add_child_notify(Node *p_child) override;
+ virtual void remove_child_notify(Node *p_child) override;
+
void _notification(int p_notification);
static void _bind_methods();
- //bind helpers
+ // Exposed virtual methods.
GDVIRTUAL1RC(bool, _has_point, Vector2)
GDVIRTUAL2RC(Array, _structured_text_parser, Array, String)
@@ -307,8 +338,6 @@ protected:
public:
enum {
- /* NOTIFICATION_DRAW=30,
- NOTIFICATION_VISIBILITY_CHANGED=38*/
NOTIFICATION_RESIZED = 40,
NOTIFICATION_MOUSE_ENTER = 41,
NOTIFICATION_MOUSE_EXIT = 42,
@@ -318,10 +347,11 @@ public:
NOTIFICATION_SCROLL_BEGIN = 47,
NOTIFICATION_SCROLL_END = 48,
NOTIFICATION_LAYOUT_DIRECTION_CHANGED = 49,
-
};
- /* EDITOR */
+ // Editor plugin interoperability.
+
+ // TODO: Decouple controls from their editor plugin and get rid of this.
#ifdef TOOLS_ENABLED
virtual Dictionary _edit_get_state() const override;
virtual void _edit_set_state(const Dictionary &p_state) override;
@@ -347,56 +377,50 @@ public:
virtual Size2 _edit_get_minimum_size() const override;
#endif
- virtual void gui_input(const Ref<InputEvent> &p_event);
+ // Editor integration.
- void accept_event();
+ virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
+ TypedArray<String> get_configuration_warnings() const override;
- virtual Size2 get_minimum_size() const;
- virtual Size2 get_combined_minimum_size() const;
- virtual bool has_point(const Point2 &p_point) const;
- virtual void set_drag_forwarding(Object *p_target);
- virtual Variant get_drag_data(const Point2 &p_point);
- virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
- virtual void drop_data(const Point2 &p_point, const Variant &p_data);
- void set_drag_preview(Control *p_control);
- void force_drag(const Variant &p_data, Control *p_control);
- bool is_drag_successful() const;
+ virtual bool is_text_field() const;
- void set_custom_minimum_size(const Size2 &p_custom);
- Size2 get_custom_minimum_size() const;
+ // Global relations.
+
+ bool is_top_level_control() const;
Control *get_parent_control() const;
Window *get_parent_window() const;
+ Control *get_root_parent_control() const;
- void set_layout_direction(LayoutDirection p_direction);
- LayoutDirection get_layout_direction() const;
- virtual bool is_layout_rtl() const;
-
- void set_auto_translate(bool p_enable);
- bool is_auto_translating() const;
- _FORCE_INLINE_ String atr(const String p_string) const { return is_auto_translating() ? tr(p_string) : p_string; };
+ Size2 get_parent_area_size() const;
+ Rect2 get_parent_anchorable_rect() const;
- /* POSITIONING */
+ // Positioning and sizing.
- void set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets = true);
- void set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
- void set_anchors_and_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
- void set_grow_direction_preset(LayoutPreset p_preset);
+ virtual Transform2D get_transform() const override;
void set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset = true, bool p_push_opposite_anchor = true);
real_t get_anchor(Side p_side) const;
-
void set_offset(Side p_side, real_t p_value);
real_t get_offset(Side p_side) const;
-
void set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, bool p_push_opposite_anchor = true);
- void set_begin(const Point2 &p_point); // helper
- void set_end(const Point2 &p_point); // helper
-
+ // TODO: Rename to set_begin/end_offsets ?
+ void set_begin(const Point2 &p_point);
Point2 get_begin() const;
+ void set_end(const Point2 &p_point);
Point2 get_end() const;
+ void set_h_grow_direction(GrowDirection p_direction);
+ GrowDirection get_h_grow_direction() const;
+ void set_v_grow_direction(GrowDirection p_direction);
+ GrowDirection get_v_grow_direction() const;
+
+ void set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets = true);
+ void set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
+ void set_anchors_and_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
+ void set_grow_direction_preset(LayoutPreset p_preset);
+
void set_position(const Point2 &p_point, bool p_keep_offsets = false);
void set_global_position(const Point2 &p_point, bool p_keep_offsets = false);
Point2 get_position() const;
@@ -407,52 +431,72 @@ public:
Size2 get_size() const;
void reset_size();
+ void set_rect(const Rect2 &p_rect); // Reset anchors to begin and set rect, for faster container children sorting.
Rect2 get_rect() const;
Rect2 get_global_rect() const;
Rect2 get_screen_rect() const;
Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the rendering server
Rect2 get_anchorable_rect() const override;
- void set_rect(const Rect2 &p_rect); // Reset anchors to begin and set rect, for faster container children sorting.
-
+ void set_scale(const Vector2 &p_scale);
+ Vector2 get_scale() const;
void set_rotation(real_t p_radians);
real_t get_rotation() const;
-
- void set_h_grow_direction(GrowDirection p_direction);
- GrowDirection get_h_grow_direction() const;
-
- void set_v_grow_direction(GrowDirection p_direction);
- GrowDirection get_v_grow_direction() const;
-
void set_pivot_offset(const Vector2 &p_pivot);
Vector2 get_pivot_offset() const;
- void set_scale(const Vector2 &p_scale);
- Vector2 get_scale() const;
+ void update_minimum_size();
- void set_theme(const Ref<Theme> &p_theme);
- Ref<Theme> get_theme() const;
+ void set_block_minimum_size_adjust(bool p_block);
+ bool is_minimum_size_adjust_blocked() const;
- void set_theme_type_variation(const StringName &p_theme_type);
- StringName get_theme_type_variation() const;
+ virtual Size2 get_minimum_size() const;
+ virtual Size2 get_combined_minimum_size() const;
+
+ void set_custom_minimum_size(const Size2 &p_custom);
+ Size2 get_custom_minimum_size() const;
+
+ // Container sizing.
void set_h_size_flags(int p_flags);
int get_h_size_flags() const;
-
void set_v_size_flags(int p_flags);
int get_v_size_flags() const;
-
void set_stretch_ratio(real_t p_ratio);
real_t get_stretch_ratio() const;
- void update_minimum_size();
+ // Input events.
+
+ virtual void gui_input(const Ref<InputEvent> &p_event);
+ void accept_event();
+
+ virtual bool has_point(const Point2 &p_point) const;
+
+ void set_mouse_filter(MouseFilter p_filter);
+ MouseFilter get_mouse_filter() const;
+
+ void set_force_pass_scroll_events(bool p_force_pass_scroll_events);
+ bool is_force_pass_scroll_events() const;
+
+ void warp_mouse(const Point2 &p_position);
+
+ // Drag and drop handling.
+
+ virtual void set_drag_forwarding(Object *p_target);
+ virtual Variant get_drag_data(const Point2 &p_point);
+ virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
+ virtual void drop_data(const Point2 &p_point, const Variant &p_data);
+ void set_drag_preview(Control *p_control);
+ void force_drag(const Variant &p_data, Control *p_control);
+ bool is_drag_successful() const;
- /* FOCUS */
+ // Focus.
void set_focus_mode(FocusMode p_focus_mode);
FocusMode get_focus_mode() const;
bool has_focus() const;
void grab_focus();
+ void grab_click_focus();
void release_focus();
Control *find_next_valid_focus() const;
@@ -466,13 +510,25 @@ public:
void set_focus_previous(const NodePath &p_prev);
NodePath get_focus_previous() const;
- void set_mouse_filter(MouseFilter p_filter);
- MouseFilter get_mouse_filter() const;
+ // Rendering.
- void set_force_pass_scroll_events(bool p_force_pass_scroll_events);
- bool is_force_pass_scroll_events() const;
+ void set_default_cursor_shape(CursorShape p_shape);
+ CursorShape get_default_cursor_shape() const;
+ virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const;
+
+ void set_clip_contents(bool p_clip);
+ bool is_clipping_contents();
- /* SKINNING */
+ void set_disable_visibility_clip(bool p_ignore);
+ bool is_visibility_clip_disabled() const;
+
+ // Theming.
+
+ void set_theme(const Ref<Theme> &p_theme);
+ Ref<Theme> get_theme() const;
+
+ void set_theme_type_variation(const StringName &p_theme_type);
+ StringName get_theme_type_variation() const;
void begin_bulk_theme_override();
void end_bulk_theme_override();
@@ -520,44 +576,23 @@ public:
Ref<Font> get_theme_default_font() const;
int get_theme_default_font_size() const;
- /* TOOLTIP */
-
- void set_tooltip(const String &p_tooltip);
- virtual String get_tooltip(const Point2 &p_pos) const;
- virtual Control *make_custom_tooltip(const String &p_text) const;
-
- /* CURSOR */
-
- void set_default_cursor_shape(CursorShape p_shape);
- CursorShape get_default_cursor_shape() const;
- virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const;
-
- virtual Transform2D get_transform() const override;
-
- bool is_top_level_control() const;
+ // Internationalization.
- Size2 get_parent_area_size() const;
- Rect2 get_parent_anchorable_rect() const;
-
- void grab_click_focus();
-
- void warp_mouse(const Point2 &p_position);
-
- virtual bool is_text_field() const;
-
- Control *get_root_parent_control() const;
-
- void set_clip_contents(bool p_clip);
- bool is_clipping_contents();
+ void set_layout_direction(LayoutDirection p_direction);
+ LayoutDirection get_layout_direction() const;
+ virtual bool is_layout_rtl() const;
- void set_block_minimum_size_adjust(bool p_block);
- bool is_minimum_size_adjust_blocked() const;
+ void set_auto_translate(bool p_enable);
+ bool is_auto_translating() const;
+ _FORCE_INLINE_ String atr(const String p_string) const {
+ return is_auto_translating() ? tr(p_string) : p_string;
+ };
- void set_disable_visibility_clip(bool p_ignore);
- bool is_visibility_clip_disabled() const;
+ // Extra properties.
- virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
- TypedArray<String> get_configuration_warnings() const override;
+ void set_tooltip(const String &p_tooltip);
+ virtual String get_tooltip(const Point2 &p_pos) const;
+ virtual Control *make_custom_tooltip(const String &p_text) const;
Control() {}
};
@@ -574,4 +609,4 @@ VARIANT_ENUM_CAST(Control::LayoutMode);
VARIANT_ENUM_CAST(Control::LayoutDirection);
VARIANT_ENUM_CAST(Control::TextDirection);
-#endif
+#endif // CONTROL_H
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index a2b05ee50d..942b7d0bf9 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -161,6 +161,14 @@ bool AcceptDialog::has_autowrap() {
return label->get_autowrap_mode() != TextServer::AUTOWRAP_OFF;
}
+void AcceptDialog::set_ok_button_text(String p_ok_button_text) {
+ ok->set_text(p_ok_button_text);
+}
+
+String AcceptDialog::get_ok_button_text() const {
+ return ok->get_text();
+}
+
void AcceptDialog::register_text_enter(Control *p_line_edit) {
ERR_FAIL_NULL(p_line_edit);
LineEdit *line_edit = Object::cast_to<LineEdit>(p_line_edit);
@@ -253,7 +261,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin
}
if (!p_action.is_empty()) {
- button->connect("pressed", callable_mp(this, &AcceptDialog::_custom_action), varray(p_action));
+ button->connect("pressed", callable_mp(this, &AcceptDialog::_custom_action).bind(p_action));
}
return button;
@@ -262,7 +270,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin
Button *AcceptDialog::add_cancel_button(const String &p_cancel) {
String c = p_cancel;
if (p_cancel.is_empty()) {
- c = RTR("Cancel");
+ c = "Cancel";
}
Button *b = swap_cancel_ok ? add_button(c, true) : add_button(c);
b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed));
@@ -306,11 +314,15 @@ void AcceptDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text"), &AcceptDialog::get_text);
ClassDB::bind_method(D_METHOD("set_autowrap", "autowrap"), &AcceptDialog::set_autowrap);
ClassDB::bind_method(D_METHOD("has_autowrap"), &AcceptDialog::has_autowrap);
+ ClassDB::bind_method(D_METHOD("set_ok_button_text", "text"), &AcceptDialog::set_ok_button_text);
+ ClassDB::bind_method(D_METHOD("get_ok_button_text"), &AcceptDialog::get_ok_button_text);
ADD_SIGNAL(MethodInfo("confirmed"));
ADD_SIGNAL(MethodInfo("cancelled"));
ADD_SIGNAL(MethodInfo("custom_action", PropertyInfo(Variant::STRING_NAME, "action")));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "ok_button_text"), "set_ok_button_text", "get_ok_button_text");
+
ADD_GROUP("Dialog", "dialog");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "dialog_text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"), "set_hide_on_ok", "get_hide_on_ok");
@@ -349,7 +361,7 @@ AcceptDialog::AcceptDialog() {
hbc->add_spacer();
ok = memnew(Button);
- ok->set_text(RTR("OK"));
+ ok->set_text("OK");
hbc->add_child(ok);
hbc->add_spacer();
@@ -365,8 +377,20 @@ AcceptDialog::~AcceptDialog() {
// ConfirmationDialog
+void ConfirmationDialog::set_cancel_button_text(String p_cancel_button_text) {
+ cancel->set_text(p_cancel_button_text);
+}
+
+String ConfirmationDialog::get_cancel_button_text() const {
+ return cancel->get_text();
+}
+
void ConfirmationDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cancel_button"), &ConfirmationDialog::get_cancel_button);
+ ClassDB::bind_method(D_METHOD("set_cancel_button_text"), &ConfirmationDialog::set_cancel_button_text);
+ ClassDB::bind_method(D_METHOD("get_cancel_button_text"), &ConfirmationDialog::get_cancel_button_text);
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "cancel_button_text"), "set_cancel_button_text", "get_cancel_button_text");
}
Button *ConfirmationDialog::get_cancel_button() {
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index 41fd9c0a10..9ebf5ddfb2 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -97,6 +97,9 @@ public:
void set_autowrap(bool p_autowrap);
bool has_autowrap();
+ void set_ok_button_text(String p_ok_button_text);
+ String get_ok_button_text() const;
+
AcceptDialog();
~AcceptDialog();
};
@@ -110,7 +113,11 @@ protected:
public:
Button *get_cancel_button();
+
+ void set_cancel_button_text(String p_cancel_button_text);
+ String get_cancel_button_text() const;
+
ConfirmationDialog();
};
-#endif
+#endif // DIALOGS_H
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 0e0f8bde83..e26976a402 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);
@@ -423,10 +419,10 @@ void FileDialog::deselect_all() {
switch (mode) {
case FILE_MODE_OPEN_FILE:
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(RTR("Open"));
+ set_ok_button_text(RTR("Open"));
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(RTR("Select Current Folder"));
+ set_ok_button_text(RTR("Select Current Folder"));
break;
case FILE_MODE_OPEN_ANY:
case FILE_MODE_SAVE_FILE:
@@ -450,7 +446,7 @@ void FileDialog::_tree_selected() {
if (!d["dir"]) {
file->set_text(d["name"]);
} else if (mode == FILE_MODE_OPEN_DIR) {
- get_ok_button()->set_text(RTR("Select This Folder"));
+ set_ok_button_text(RTR("Select This Folder"));
}
get_ok_button()->set_disabled(_is_open_should_be_disabled());
@@ -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);
}
}
@@ -674,9 +673,13 @@ void FileDialog::clear_filters() {
invalidate();
}
-void FileDialog::add_filter(const String &p_filter) {
+void FileDialog::add_filter(const String &p_filter, const String &p_description) {
ERR_FAIL_COND_MSG(p_filter.begins_with("."), "Filter must be \"filename.extension\", can't start with dot.");
- filters.push_back(p_filter);
+ if (p_description.is_empty()) {
+ filters.push_back(p_filter);
+ } else {
+ filters.push_back(vformat("%s ; %s", p_filter, p_description));
+ }
update_filters();
invalidate();
}
@@ -704,9 +707,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 +733,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;
}
@@ -746,35 +768,35 @@ void FileDialog::set_file_mode(FileMode p_mode) {
mode = p_mode;
switch (mode) {
case FILE_MODE_OPEN_FILE:
- get_ok_button()->set_text(RTR("Open"));
+ set_ok_button_text(RTR("Open"));
if (mode_overrides_title) {
set_title(TTRC("Open a File"));
}
makedir->hide();
break;
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(RTR("Open"));
+ set_ok_button_text(RTR("Open"));
if (mode_overrides_title) {
set_title(TTRC("Open File(s)"));
}
makedir->hide();
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(RTR("Select Current Folder"));
+ set_ok_button_text(RTR("Select Current Folder"));
if (mode_overrides_title) {
set_title(TTRC("Open a Directory"));
}
makedir->show();
break;
case FILE_MODE_OPEN_ANY:
- get_ok_button()->set_text(RTR("Open"));
+ set_ok_button_text(RTR("Open"));
if (mode_overrides_title) {
set_title(TTRC("Open a File or Directory"));
}
makedir->show();
break;
case FILE_MODE_SAVE_FILE:
- get_ok_button()->set_text(RTR("Save"));
+ set_ok_button_text(RTR("Save"));
if (mode_overrides_title) {
set_title(TTRC("Save a File"));
}
@@ -810,6 +832,8 @@ void FileDialog::set_access(Access p_access) {
} break;
}
access = p_access;
+ root_prefix = "";
+ root_subfolder = "";
_update_drives();
invalidate();
update_filters();
@@ -832,10 +856,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 +872,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) {
@@ -887,7 +923,7 @@ void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_cancel_pressed"), &FileDialog::_cancel_pressed);
ClassDB::bind_method(D_METHOD("clear_filters"), &FileDialog::clear_filters);
- ClassDB::bind_method(D_METHOD("add_filter", "filter"), &FileDialog::add_filter);
+ ClassDB::bind_method(D_METHOD("add_filter", "filter", "description"), &FileDialog::add_filter, DEFVAL(""));
ClassDB::bind_method(D_METHOD("set_filters", "filters"), &FileDialog::set_filters);
ClassDB::bind_method(D_METHOD("get_filters"), &FileDialog::get_filters);
ClassDB::bind_method(D_METHOD("get_current_dir"), &FileDialog::get_current_dir);
@@ -904,6 +940,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 +954,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");
@@ -1021,7 +1060,7 @@ FileDialog::FileDialog() {
message = memnew(Label);
message->hide();
- message->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ message->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
message->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
tree->add_child(message);
@@ -1044,9 +1083,9 @@ FileDialog::FileDialog() {
_update_drives();
connect("confirmed", callable_mp(this, &FileDialog::_action_pressed));
- tree->connect("multi_selected", callable_mp(this, &FileDialog::_tree_multi_selected), varray(), CONNECT_DEFERRED);
- tree->connect("cell_selected", callable_mp(this, &FileDialog::_tree_selected), varray(), CONNECT_DEFERRED);
- tree->connect("item_activated", callable_mp(this, &FileDialog::_tree_item_activated), varray());
+ tree->connect("multi_selected", callable_mp(this, &FileDialog::_tree_multi_selected), CONNECT_DEFERRED);
+ tree->connect("cell_selected", callable_mp(this, &FileDialog::_tree_selected), CONNECT_DEFERRED);
+ tree->connect("item_activated", callable_mp(this, &FileDialog::_tree_item_activated));
tree->connect("nothing_selected", callable_mp(this, &FileDialog::deselect_all));
dir->connect("text_submitted", callable_mp(this, &FileDialog::_dir_submitted));
file->connect("text_submitted", callable_mp(this, &FileDialog::_file_submitted));
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 2e326d2949..4945094086 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;
@@ -148,7 +151,7 @@ protected:
public:
void popup_file_dialog();
void clear_filters();
- void add_filter(const String &p_filter);
+ void add_filter(const String &p_filter, const String &p_description = "");
void set_filters(const Vector<String> &p_filters);
Vector<String> get_filters() const;
@@ -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;
@@ -190,4 +196,4 @@ public:
VARIANT_ENUM_CAST(FileDialog::FileMode);
VARIANT_ENUM_CAST(FileDialog::Access);
-#endif
+#endif // FILE_DIALOG_H
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index 9459bed63b..cc27a6b7c2 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -437,6 +437,10 @@ ColorPicker *GradientEdit::get_picker() {
return picker;
}
+PopupPanel *GradientEdit::get_popup() {
+ return popup;
+}
+
void GradientEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("ramp_changed"));
}
diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h
index 3badcd45ba..b7c99f1f1c 100644
--- a/scene/gui/gradient_edit.h
+++ b/scene/gui/gradient_edit.h
@@ -75,6 +75,7 @@ public:
void set_interpolation_mode(Gradient::InterpolationMode p_interp_mode);
Gradient::InterpolationMode get_interpolation_mode();
ColorPicker *get_picker();
+ PopupPanel *get_popup();
virtual Size2 get_minimum_size() const override;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index c219eafbf7..09efee71a3 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -382,9 +382,9 @@ void GraphEdit::add_child_notify(Node *p_child) {
GraphNode *gn = Object::cast_to<GraphNode>(p_child);
if (gn) {
gn->set_scale(Vector2(zoom, zoom));
- gn->connect("position_offset_changed", callable_mp(this, &GraphEdit::_graph_node_moved), varray(gn));
- gn->connect("slot_updated", callable_mp(this, &GraphEdit::_graph_node_slot_updated), varray(gn));
- gn->connect("raise_request", callable_mp(this, &GraphEdit::_graph_node_raised), varray(gn));
+ gn->connect("position_offset_changed", callable_mp(this, &GraphEdit::_graph_node_moved).bind(gn));
+ gn->connect("slot_updated", callable_mp(this, &GraphEdit::_graph_node_slot_updated).bind(gn));
+ gn->connect("raise_request", callable_mp(this, &GraphEdit::_graph_node_raised).bind(gn));
gn->connect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::update));
gn->connect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::update));
_graph_node_moved(gn);
@@ -710,6 +710,9 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
int type = gn->get_connection_output_type(j);
if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_output_hotzone(gn, j, mpos, port_size)) {
+ if (!is_node_hover_valid(gn->get_name(), j, connecting_from, connecting_index)) {
+ continue;
+ }
connecting_target = true;
connecting_to = pos;
connecting_target_to = gn->get_name();
@@ -725,6 +728,9 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
int type = gn->get_connection_input_type(j);
if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_input_hotzone(gn, j, mpos, port_size)) {
+ if (!is_node_hover_valid(connecting_from, connecting_index, gn->get_name(), j)) {
+ continue;
+ }
connecting_target = true;
connecting_to = pos;
connecting_target_to = gn->get_name();
@@ -1453,6 +1459,14 @@ void GraphEdit::force_connection_drag_end() {
emit_signal(SNAME("connection_drag_ended"));
}
+bool GraphEdit::is_node_hover_valid(const StringName &p_from, const int p_from_port, const StringName &p_to, const int p_to_port) {
+ bool valid;
+ if (GDVIRTUAL_CALL(_is_node_hover_valid, p_from, p_from_port, p_to, p_to_port, valid)) {
+ return valid;
+ }
+ return true;
+}
+
void GraphEdit::set_panning_scheme(PanningScheme p_scheme) {
panning_scheme = p_scheme;
panner->set_control_scheme((ViewPanner::ControlScheme)p_scheme);
@@ -1809,7 +1823,20 @@ HashMap<int, Vector<StringName>> GraphEdit::_layering(const HashSet<StringName>
}
if (!selected) {
current_layer++;
+ uint32_t previous_size_z = z.size();
_set_operations(GraphEdit::UNION, z, u);
+ if (z.size() == previous_size_z) {
+ WARN_PRINT("Graph contains cycle(s). The cycle(s) will not be rearranged accurately.");
+ Vector<StringName> t;
+ if (l.has(0)) {
+ t.append_array(l[0]);
+ }
+ for (const StringName &E : p) {
+ t.push_back(E);
+ }
+ l.insert(0, t);
+ break;
+ }
}
selected = false;
}
@@ -2124,7 +2151,7 @@ void GraphEdit::arrange_nodes() {
HashSet<StringName> s;
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
GraphNode *p_from = Object::cast_to<GraphNode>(node_names[E->get().from]);
- if (E->get().to == gn->get_name() && p_from->is_selected()) {
+ if (E->get().to == gn->get_name() && p_from->is_selected() && E->get().to != E->get().from) {
if (!s.has(p_from->get_name())) {
s.insert(p_from->get_name());
}
@@ -2315,6 +2342,7 @@ void GraphEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_selected", "node"), &GraphEdit::set_selected);
GDVIRTUAL_BIND(_get_connection_line, "from", "to")
+ GDVIRTUAL_BIND(_is_node_hover_valid, "from", "from_slot", "to", "to_slot");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "right_disconnects"), "set_right_disconnects", "is_right_disconnects_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_scroll_ofs", "get_scroll_ofs");
@@ -2376,7 +2404,7 @@ GraphEdit::GraphEdit() {
top_layer = memnew(GraphEditFilter(this));
add_child(top_layer, false, INTERNAL_MODE_BACK);
top_layer->set_mouse_filter(MOUSE_FILTER_PASS);
- top_layer->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ top_layer->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
top_layer->connect("draw", callable_mp(this, &GraphEdit::_top_layer_draw));
top_layer->connect("gui_input", callable_mp(this, &GraphEdit::_top_layer_input));
top_layer->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key));
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 02e90e4717..cf35aeb8b2 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -280,6 +280,7 @@ protected:
GDVIRTUAL2RC(Vector<Vector2>, _get_connection_line, Vector2, Vector2)
GDVIRTUAL3R(bool, _is_in_input_hotzone, Object *, int, Vector2)
GDVIRTUAL3R(bool, _is_in_output_hotzone, Object *, int, Vector2)
+ GDVIRTUAL4R(bool, _is_node_hover_valid, StringName, int, StringName, int);
public:
Error connect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
@@ -287,6 +288,7 @@ public:
void disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
void clear_connections();
void force_connection_drag_end();
+ virtual bool is_node_hover_valid(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
void set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity);
@@ -365,4 +367,4 @@ public:
VARIANT_ENUM_CAST(GraphEdit::PanningScheme);
-#endif // GRAPHEdit_H
+#endif // GRAPH_EDIT_H
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 87706cd0d7..112b8c74af 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
@@ -488,7 +450,7 @@ void GraphNode::_validate_property(PropertyInfo &property) const {
Control::_validate_property(property);
GraphEdit *graph = Object::cast_to<GraphEdit>(get_parent());
if (graph) {
- if (property.name == "rect_position") {
+ if (property.name == "position") {
property.usage |= PROPERTY_USAGE_READ_ONLY;
}
}
@@ -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,11 @@ 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_GROUP("", "");
+
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/grid_container.cpp b/scene/gui/grid_container.cpp
index 6f8518a7b0..eaa6943ad2 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -41,8 +41,6 @@ void GridContainer::_notification(int p_what) {
int hsep = get_theme_constant(SNAME("h_separation"));
int vsep = get_theme_constant(SNAME("v_separation"));
- int max_col = MIN(get_child_count(), columns);
- int max_row = ceil((float)get_child_count() / (float)columns);
// Compute the per-column/per-row data.
int valid_controls_index = 0;
@@ -79,6 +77,9 @@ void GridContainer::_notification(int p_what) {
}
}
+ int max_col = MIN(valid_controls_index, columns);
+ int max_row = ceil((float)valid_controls_index / (float)columns);
+
// Consider all empty columns expanded.
for (int i = valid_controls_index; i < columns; i++) {
col_expanded.insert(i);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index aeb5338022..d0a25972f8 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -43,11 +43,11 @@ 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);
+ item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
} else {
- item.text_buf->set_flags(TextServer::BREAK_NONE);
+ item.text_buf->set_break_flags(TextServer::BREAK_NONE);
}
item.text_buf->set_text_overrun_behavior(text_overrun_behavior);
item.text_buf->set_max_lines_visible(max_text_lines);
@@ -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();
@@ -499,10 +470,10 @@ void ItemList::set_max_text_lines(int p_lines) {
max_text_lines = p_lines;
for (int i = 0; i < items.size(); i++) {
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
- items.write[i].text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
+ items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
items.write[i].text_buf->set_max_lines_visible(p_lines);
} else {
- items.write[i].text_buf->set_flags(TextServer::BREAK_NONE);
+ items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
}
}
shape_changed = true;
@@ -540,9 +511,9 @@ void ItemList::set_icon_mode(IconMode p_mode) {
icon_mode = p_mode;
for (int i = 0; i < items.size(); i++) {
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
- items.write[i].text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
+ items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
} else {
- items.write[i].text_buf->set_flags(TextServer::BREAK_NONE);
+ items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
}
}
shape_changed = true;
@@ -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..21bd22759c 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef ITEMLIST_H
-#define ITEMLIST_H
+#ifndef ITEM_LIST_H
+#define ITEM_LIST_H
#include "scene/gui/control.h"
#include "scene/gui/scroll_bar.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;
@@ -264,4 +259,4 @@ public:
VARIANT_ENUM_CAST(ItemList::SelectMode);
VARIANT_ENUM_CAST(ItemList::IconMode);
-#endif // ITEMLIST_H
+#endif // ITEM_LIST_H
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 82ab7c2e18..e7f48beb00 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -31,6 +31,7 @@
#include "label.h"
#include "core/config/project_settings.h"
+#include "core/core_string_names.h"
#include "core/string/print_string.h"
#include "core/string/translation.h"
@@ -64,17 +65,18 @@ bool Label::is_uppercase() const {
}
int Label::get_line_height(int p_line) const {
- Ref<Font> font = get_theme_font(SNAME("font"));
+ Ref<Font> font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_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 {
- return font->get_height(get_theme_font_size(SNAME("font_size")));
+ int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
+ return font->get_height(font_size);
}
}
@@ -83,7 +85,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);
}
@@ -92,21 +93,24 @@ void Label::_shape() {
} else {
TS->shaped_text_set_direction(text_rid, (TextServer::Direction)text_direction);
}
- const Ref<Font> &font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
+ const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
+ int font_size = settings.is_valid() ? settings->get_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;
@@ -119,10 +123,10 @@ void Label::_shape() {
}
lines_rid.clear();
- uint16_t autowrap_flags = TextServer::BREAK_MANDATORY;
+ BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY;
switch (autowrap_mode) {
case TextServer::AUTOWRAP_WORD_SMART:
- autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY;
+ autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY;
break;
case TextServer::AUTOWRAP_WORD:
autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
@@ -156,23 +160,23 @@ void Label::_shape() {
}
if (lines_dirty) {
- uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIM;
+ BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM;
switch (overrun_behavior) {
case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS:
- overrun_flags |= TextServer::OVERRUN_TRIM;
- overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
- overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
+ overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
break;
case TextServer::OVERRUN_TRIM_ELLIPSIS:
- overrun_flags |= TextServer::OVERRUN_TRIM;
- overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
break;
case TextServer::OVERRUN_TRIM_WORD:
- overrun_flags |= TextServer::OVERRUN_TRIM;
- overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
break;
case TextServer::OVERRUN_TRIM_CHAR:
- overrun_flags |= TextServer::OVERRUN_TRIM;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
break;
case TextServer::OVERRUN_NO_TRIMMING:
break;
@@ -184,7 +188,7 @@ void Label::_shape() {
int visible_lines = get_visible_line_count();
bool lines_hidden = visible_lines > 0 && visible_lines < lines_rid.size();
if (lines_hidden) {
- overrun_flags |= TextServer::OVERRUN_ENFORCE_ELLIPSIS;
+ overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS);
}
if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
for (int i = 0; i < lines_rid.size(); i++) {
@@ -202,7 +206,7 @@ void Label::_shape() {
for (int i = 0; i < lines_rid.size(); i++) {
if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
TS->shaped_text_fit_to_width(lines_rid[i], width);
- overrun_flags |= TextServer::OVERRUN_JUSTIFICATION_AWARE;
+ overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE);
TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
TS->shaped_text_fit_to_width(lines_rid[i], width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
} else {
@@ -221,9 +225,8 @@ void Label::_shape() {
}
void Label::_update_visible() {
- int line_spacing = get_theme_constant(SNAME("line_spacing"), SNAME("Label"));
+ int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"), SNAME("Label"));
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
- Ref<Font> font = get_theme_font(SNAME("font"));
int lines_visible = lines_rid.size();
if (max_lines_visible >= 0 && lines_visible > max_lines_visible) {
@@ -233,7 +236,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;
}
@@ -293,17 +296,19 @@ void Label::_notification(int p_what) {
RID ci = get_canvas_item();
+ bool has_settings = settings.is_valid();
+
Size2 string_size;
Size2 size = get_size();
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- Ref<Font> font = get_theme_font(SNAME("font"));
- Color font_color = get_theme_color(SNAME("font_color"));
- Color font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
- Point2 shadow_ofs(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
- int line_spacing = get_theme_constant(SNAME("line_spacing"));
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
- int shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
+ Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
+ Color font_color = has_settings ? settings->get_font_color() : get_theme_color(SNAME("font_color"));
+ Color font_shadow_color = has_settings ? settings->get_shadow_color() : get_theme_color(SNAME("font_shadow_color"));
+ Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : Point2(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
+ int line_spacing = has_settings ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"));
+ Color font_outline_color = has_settings ? settings->get_outline_color() : get_theme_color(SNAME("font_outline_color"));
+ int outline_size = has_settings ? settings->get_outline_size() : get_theme_constant(SNAME("outline_size"));
+ int shadow_outline_size = has_settings ? settings->get_shadow_size() : get_theme_constant(SNAME("shadow_outline_size"));
bool rtl = (TS->shaped_text_get_inferred_direction(text_rid) == TextServer::DIRECTION_RTL);
bool rtl_layout = is_layout_rtl();
@@ -314,7 +319,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 +339,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 +379,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 +532,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;
@@ -550,8 +555,10 @@ 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));
+ const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
+ int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
+
+ min_size.height = MAX(min_size.height, font->get_height(font_size) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM));
Size2 min_style = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
@@ -576,13 +583,12 @@ int Label::get_line_count() const {
}
int Label::get_visible_line_count() const {
- Ref<Font> font = get_theme_font(SNAME("font"));
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- int line_spacing = get_theme_constant(SNAME("line_spacing"));
+ int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"));
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;
}
@@ -639,6 +645,28 @@ void Label::set_text(const String &p_string) {
update_minimum_size();
}
+void Label::_invalidate() {
+ font_dirty = true;
+ update();
+}
+
+void Label::set_label_settings(const Ref<LabelSettings> &p_settings) {
+ if (settings != p_settings) {
+ if (settings.is_valid()) {
+ settings->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Label::_invalidate));
+ }
+ settings = p_settings;
+ if (settings.is_valid()) {
+ settings->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Label::_invalidate), CONNECT_REFERENCE_COUNTED);
+ }
+ _invalidate();
+ }
+}
+
+Ref<LabelSettings> Label::get_label_settings() const {
+ return settings;
+}
+
void Label::set_text_direction(Control::TextDirection p_text_direction) {
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (text_direction != p_text_direction) {
@@ -674,29 +702,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 +823,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);
@@ -875,11 +830,10 @@ void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_vertical_alignment"), &Label::get_vertical_alignment);
ClassDB::bind_method(D_METHOD("set_text", "text"), &Label::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &Label::get_text);
+ ClassDB::bind_method(D_METHOD("set_label_settings", "settings"), &Label::set_label_settings);
+ ClassDB::bind_method(D_METHOD("get_label_settings"), &Label::get_label_settings);
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);
@@ -910,6 +864,7 @@ void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override_options"), &Label::get_structured_text_bidi_override_options);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "label_settings", PROPERTY_HINT_RESOURCE_TYPE, "LabelSettings"), "set_label_settings", "get_label_settings");
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,Fill"), "set_vertical_alignment", "get_vertical_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
@@ -924,11 +879,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..cab5b36d68 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -32,6 +32,7 @@
#define LABEL_H
#include "scene/gui/control.h"
+#include "scene/resources/label_settings.h"
class Label : public Control {
GDCLASS(Label, Control);
@@ -53,7 +54,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;
@@ -66,18 +66,17 @@ private:
int lines_skipped = 0;
int max_lines_visible = -1;
+ Ref<LabelSettings> settings;
+
void _update_visible();
void _shape();
+ void _invalidate();
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;
@@ -90,13 +89,12 @@ public:
void set_text(const String &p_string);
String get_text() const;
+ void set_label_settings(const Ref<LabelSettings> &p_settings);
+ Ref<LabelSettings> get_label_settings() const;
+
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;
@@ -142,4 +140,4 @@ public:
~Label();
};
-#endif
+#endif // LABEL_H
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 540250c8e9..f315b2bbf1 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;
@@ -1523,9 +1513,9 @@ void LineEdit::clear() {
void LineEdit::show_virtual_keyboard() {
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) {
if (selection.enabled) {
- DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), false, max_length, selection.begin, selection.end);
+ DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), DisplayServer::VirtualKeyboardType(virtual_keyboard_type), max_length, selection.begin, selection.end);
} else {
- DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), false, max_length, caret_column);
+ DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), DisplayServer::VirtualKeyboardType(virtual_keyboard_type), max_length, caret_column);
}
}
}
@@ -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;
@@ -2050,6 +2040,14 @@ bool LineEdit::is_virtual_keyboard_enabled() const {
return virtual_keyboard_enabled;
}
+void LineEdit::set_virtual_keyboard_type(VirtualKeyboardType p_type) {
+ virtual_keyboard_type = p_type;
+}
+
+LineEdit::VirtualKeyboardType LineEdit::get_virtual_keyboard_type() const {
+ return virtual_keyboard_type;
+}
+
void LineEdit::set_middle_mouse_paste_enabled(bool p_enabled) {
middle_mouse_paste_enabled = p_enabled;
}
@@ -2142,7 +2140,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 +2224,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 +2249,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);
@@ -2340,6 +2288,8 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &LineEdit::is_context_menu_enabled);
ClassDB::bind_method(D_METHOD("set_virtual_keyboard_enabled", "enable"), &LineEdit::set_virtual_keyboard_enabled);
ClassDB::bind_method(D_METHOD("is_virtual_keyboard_enabled"), &LineEdit::is_virtual_keyboard_enabled);
+ ClassDB::bind_method(D_METHOD("set_virtual_keyboard_type", "type"), &LineEdit::set_virtual_keyboard_type);
+ ClassDB::bind_method(D_METHOD("get_virtual_keyboard_type"), &LineEdit::get_virtual_keyboard_type);
ClassDB::bind_method(D_METHOD("set_clear_button_enabled", "enable"), &LineEdit::set_clear_button_enabled);
ClassDB::bind_method(D_METHOD("is_clear_button_enabled"), &LineEdit::is_clear_button_enabled);
ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enable"), &LineEdit::set_shortcut_keys_enabled);
@@ -2389,6 +2339,15 @@ void LineEdit::_bind_methods() {
BIND_ENUM_CONSTANT(MENU_INSERT_SHY);
BIND_ENUM_CONSTANT(MENU_MAX);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_DEFAULT);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_MULTILINE);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER_DECIMAL);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PHONE);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_EMAIL_ADDRESS);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PASSWORD);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_URL);
+
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
@@ -2399,6 +2358,7 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_to_text_length"), "set_expand_to_text_length_enabled", "is_expand_to_text_length_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "virtual_keyboard_type", PROPERTY_HINT_ENUM, "Default,Multiline,Number,Decimal,Phone,Email,Password,URL"), "set_virtual_keyboard_type", "get_virtual_keyboard_type");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clear_button_enabled"), "set_clear_button_enabled", "is_clear_button_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled");
@@ -2406,18 +2366,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 +2470,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..a828479b0c 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -70,6 +70,17 @@ public:
MENU_MAX
};
+ enum VirtualKeyboardType {
+ KEYBOARD_TYPE_DEFAULT,
+ KEYBOARD_TYPE_MULTILINE,
+ KEYBOARD_TYPE_NUMBER,
+ KEYBOARD_TYPE_NUMBER_DECIMAL,
+ KEYBOARD_TYPE_PHONE,
+ KEYBOARD_TYPE_EMAIL_ADDRESS,
+ KEYBOARD_TYPE_PASSWORD,
+ KEYBOARD_TYPE_URL
+ };
+
private:
HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT;
@@ -105,7 +116,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;
@@ -121,6 +131,7 @@ private:
bool shortcut_keys_enabled = true;
bool virtual_keyboard_enabled = true;
+ VirtualKeyboardType virtual_keyboard_type = KEYBOARD_TYPE_DEFAULT;
bool middle_mouse_paste_enabled = true;
@@ -160,7 +171,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 +221,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 +256,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;
@@ -317,6 +323,9 @@ public:
void set_virtual_keyboard_enabled(bool p_enable);
bool is_virtual_keyboard_enabled() const;
+ void set_virtual_keyboard_type(VirtualKeyboardType p_type);
+ VirtualKeyboardType get_virtual_keyboard_type() const;
+
void set_middle_mouse_paste_enabled(bool p_enabled);
bool is_middle_mouse_paste_enabled() const;
@@ -341,5 +350,6 @@ public:
};
VARIANT_ENUM_CAST(LineEdit::MenuItems);
+VARIANT_ENUM_CAST(LineEdit::VirtualKeyboardType);
-#endif
+#endif // LINE_EDIT_H
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..12a6a7618f 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef LINKBUTTON_H
-#define LINKBUTTON_H
+#ifndef LINK_BUTTON_H
+#define LINK_BUTTON_H
#include "scene/gui/base_button.h"
#include "scene/resources/text_line.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;
@@ -95,4 +86,4 @@ public:
VARIANT_ENUM_CAST(LinkButton::UnderlineMode);
-#endif // LINKBUTTON_H
+#endif // LINK_BUTTON_H
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 316fee53fe..069a31d9d2 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -239,8 +239,8 @@ MenuButton::MenuButton(const String &p_text) :
popup = memnew(PopupMenu);
popup->hide();
add_child(popup, false, INTERNAL_MODE_FRONT);
- popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(true));
- popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(false));
+ popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(true));
+ popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(false));
}
MenuButton::~MenuButton() {
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index 0a6b46c796..97c0d21f1e 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -71,4 +71,4 @@ public:
~MenuButton();
};
-#endif
+#endif // MENU_BUTTON_H
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index a86f2bdbc1..c58513df17 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -35,7 +35,12 @@
static const int NONE_SELECTED = -1;
Size2 OptionButton::get_minimum_size() const {
- Size2 minsize = Button::get_minimum_size();
+ Size2 minsize;
+ if (fit_to_longest_item) {
+ minsize = _cached_size;
+ } else {
+ minsize = Button::get_minimum_size();
+ }
if (has_theme_icon(SNAME("arrow"))) {
const Size2 padding = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
@@ -107,6 +112,7 @@ void OptionButton::_notification(int p_what) {
_set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width());
}
}
+ _refresh_size_cache();
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -135,6 +141,10 @@ bool OptionButton::_set(const StringName &p_name, const Variant &p_value) {
_select(idx, false);
}
+ if (property == "text" || property == "icon") {
+ _queue_refresh_cache();
+ }
+
return valid;
}
return false;
@@ -208,6 +218,7 @@ void OptionButton::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_l
if (first_selectable) {
select(get_item_count() - 1);
}
+ _queue_refresh_cache();
}
void OptionButton::add_item(const String &p_label, int p_id) {
@@ -216,6 +227,7 @@ void OptionButton::add_item(const String &p_label, int p_id) {
if (first_selectable) {
select(get_item_count() - 1);
}
+ _queue_refresh_cache();
}
void OptionButton::set_item_text(int p_idx, const String &p_text) {
@@ -224,6 +236,7 @@ void OptionButton::set_item_text(int p_idx, const String &p_text) {
if (current == p_idx) {
set_text(p_text);
}
+ _queue_refresh_cache();
}
void OptionButton::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
@@ -232,6 +245,7 @@ void OptionButton::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
if (current == p_idx) {
set_icon(p_icon);
}
+ _queue_refresh_cache();
}
void OptionButton::set_item_id(int p_idx, int p_id) {
@@ -301,6 +315,7 @@ void OptionButton::set_item_count(int p_count) {
}
}
+ _refresh_size_cache();
notify_property_list_changed();
}
@@ -333,6 +348,19 @@ int OptionButton::get_item_count() const {
return popup->get_item_count();
}
+void OptionButton::set_fit_to_longest_item(bool p_fit) {
+ if (p_fit == fit_to_longest_item) {
+ return;
+ }
+ fit_to_longest_item = p_fit;
+
+ _refresh_size_cache();
+}
+
+bool OptionButton::is_fit_to_longest_item() const {
+ return fit_to_longest_item;
+}
+
void OptionButton::add_separator(const String &p_text) {
popup->add_separator(p_text);
}
@@ -341,6 +369,7 @@ void OptionButton::clear() {
popup->clear();
set_text("");
current = NONE_SELECTED;
+ _refresh_size_cache();
}
void OptionButton::_select(int p_which, bool p_emit) {
@@ -380,6 +409,29 @@ void OptionButton::_select_int(int p_which) {
_select(p_which, false);
}
+void OptionButton::_refresh_size_cache() {
+ cache_refresh_pending = false;
+
+ if (!fit_to_longest_item) {
+ return;
+ }
+
+ _cached_size = Vector2();
+ for (int i = 0; i < get_item_count(); i++) {
+ _cached_size = _cached_size.max(get_minimum_size_for_text_and_icon(get_item_text(i), get_item_icon(i)));
+ }
+ update_minimum_size();
+}
+
+void OptionButton::_queue_refresh_cache() {
+ if (cache_refresh_pending) {
+ return;
+ }
+ cache_refresh_pending = true;
+
+ callable_mp(this, &OptionButton::_refresh_size_cache).call_deferredp(nullptr, 0);
+}
+
void OptionButton::select(int p_idx) {
_select(p_idx, false);
}
@@ -405,6 +457,7 @@ void OptionButton::remove_item(int p_idx) {
if (current == p_idx) {
_select(NONE_SELECTED);
}
+ _queue_refresh_cache();
}
PopupMenu *OptionButton::get_popup() const {
@@ -453,10 +506,13 @@ void OptionButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_count"), &OptionButton::get_item_count);
ClassDB::bind_method(D_METHOD("has_selectable_items"), &OptionButton::has_selectable_items);
ClassDB::bind_method(D_METHOD("get_selectable_item", "from_last"), &OptionButton::get_selectable_item, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_fit_to_longest_item", "fit"), &OptionButton::set_fit_to_longest_item);
+ ClassDB::bind_method(D_METHOD("is_fit_to_longest_item"), &OptionButton::is_fit_to_longest_item);
// "selected" property must come after "item_count", otherwise GH-10213 occurs.
ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fit_to_longest_item"), "set_fit_to_longest_item", "is_fit_to_longest_item");
ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "index")));
ADD_SIGNAL(MethodInfo("item_focused", PropertyInfo(Variant::INT, "index")));
}
@@ -481,7 +537,8 @@ OptionButton::OptionButton(const String &p_text) :
add_child(popup, false, INTERNAL_MODE_FRONT);
popup->connect("index_pressed", callable_mp(this, &OptionButton::_selected));
popup->connect("id_focused", callable_mp(this, &OptionButton::_focused));
- popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false));
+ popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed).bind(false));
+ _refresh_size_cache();
}
OptionButton::~OptionButton() {
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index 7896132626..49b5eee910 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -39,11 +39,16 @@ class OptionButton : public Button {
PopupMenu *popup = nullptr;
int current = -1;
+ bool fit_to_longest_item = true;
+ Vector2 _cached_size;
+ bool cache_refresh_pending = false;
void _focused(int p_which);
void _selected(int p_which);
void _select(int p_which, bool p_emit = false);
void _select_int(int p_which);
+ void _refresh_size_cache();
+ void _queue_refresh_cache();
virtual void pressed() override;
@@ -85,6 +90,8 @@ public:
void set_item_count(int p_count);
int get_item_count() const;
+ void set_fit_to_longest_item(bool p_fit);
+ bool is_fit_to_longest_item() const;
void add_separator(const String &p_text = "");
@@ -105,4 +112,4 @@ public:
~OptionButton();
};
-#endif
+#endif // OPTION_BUTTON_H
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index b53c8be50f..70eb8722d0 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -79,4 +79,4 @@ public:
PopupPanel();
};
-#endif
+#endif // POPUP_H
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 5931c112eb..928bab8842 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);
@@ -1944,7 +1909,7 @@ void PopupMenu::popup(const Rect2 &p_bounds) {
PopupMenu::PopupMenu() {
// Margin Container
margin_container = memnew(MarginContainer);
- margin_container->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ margin_container->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
add_child(margin_container, false, INTERNAL_MODE_FRONT);
margin_container->connect("draw", callable_mp(this, &PopupMenu::_draw_background));
@@ -1956,7 +1921,7 @@ PopupMenu::PopupMenu() {
// The control which will display the items
control = memnew(Control);
control->set_clip_contents(false);
- control->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ control->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
control->set_h_size_flags(Control::SIZE_EXPAND_FILL);
control->set_v_size_flags(Control::SIZE_EXPAND_FILL);
scroll_container->add_child(control, false, INTERNAL_MODE_FRONT);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 8218c6122e..e203793c2e 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;
@@ -264,4 +260,4 @@ public:
~PopupMenu();
};
-#endif
+#endif // POPUP_MENU_H
diff --git a/scene/gui/range.h b/scene/gui/range.h
index 1274821bd1..87bd0d88af 100644
--- a/scene/gui/range.h
+++ b/scene/gui/range.h
@@ -106,4 +106,4 @@ public:
~Range();
};
-#endif
+#endif // RANGE_H
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 0516c8e722..984f20ee58 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -149,7 +149,12 @@ RichTextLabel::Item *RichTextLabel::_get_item_at_pos(RichTextLabel::Item *p_item
return it;
}
} break;
- case ITEM_NEWLINE:
+ case ITEM_NEWLINE: {
+ offset += 1;
+ if (offset == p_position) {
+ return it;
+ }
+ } break;
case ITEM_IMAGE:
case ITEM_TABLE: {
offset += 1;
@@ -219,16 +224,26 @@ void RichTextLabel::_update_line_font(ItemFrame *p_frame, int p_line, const Ref<
for (int i = 0; i < spans; i++) {
ItemText *it = reinterpret_cast<ItemText *>((uint64_t)TS->shaped_get_span_meta(t, i));
if (it) {
- Ref<Font> font = _find_font(it);
- if (font.is_null()) {
- font = p_base_font;
+ Ref<Font> font = p_base_font;
+ int font_size = p_base_font_size;
+
+ ItemFont *font_it = _find_font(it);
+ if (font_it) {
+ if (font_it->font.is_valid()) {
+ font = font_it->font;
+ }
+ if (font_it->font_size > 0) {
+ font_size = font_it->font_size;
+ }
+ }
+ ItemFontSize *font_size_it = _find_font_size(it);
+ if (font_size_it && font_size_it->font_size > 0) {
+ font_size = font_size_it->font_size;
}
- int font_size = _find_font_size(it);
- if (font_size == -1) {
- font_size = p_base_font_size;
+ 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)));
}
- Dictionary font_ftr = _find_font_features(it);
- TS->shaped_set_span_update_font(t, i, font->get_rids(), font_size, font_ftr);
}
}
@@ -263,7 +278,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);
}
@@ -424,10 +439,10 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
Line &l = p_frame->lines[p_line];
MutexLock lock(l.text_buf->get_mutex());
- uint16_t autowrap_flags = TextServer::BREAK_MANDATORY;
+ BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY;
switch (autowrap_mode) {
case TextServer::AUTOWRAP_WORD_SMART:
- autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY;
+ autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY;
break;
case TextServer::AUTOWRAP_WORD:
autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
@@ -441,7 +456,8 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
// Clear cache.
l.text_buf->clear();
- l.text_buf->set_flags(autowrap_flags | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_TRIM_EDGE_SPACES);
+ l.text_buf->set_break_flags(autowrap_flags);
+ l.text_buf->set_justification_flags(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_TRIM_EDGE_SPACES);
l.char_offset = *r_char_offset;
l.char_count = 0;
@@ -453,7 +469,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);
}
@@ -475,30 +491,45 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
l.dc_ol_color = dc->ol_color;
} break;
case ITEM_NEWLINE: {
- Ref<Font> font = _find_font(it);
- if (font.is_null()) {
- font = p_base_font;
+ Ref<Font> font = p_base_font;
+ int font_size = p_base_font_size;
+
+ ItemFont *font_it = _find_font(it);
+ if (font_it) {
+ if (font_it->font.is_valid()) {
+ font = font_it->font;
+ }
+ if (font_it->font_size > 0) {
+ font_size = font_it->font_size;
+ }
}
- int font_size = _find_font_size(it);
- if (font_size == -1) {
- font_size = p_base_font_size;
+ ItemFontSize *font_size_it = _find_font_size(it);
+ if (font_size_it && font_size_it->font_size > 0) {
+ font_size = font_size_it->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--;
} break;
case ITEM_TEXT: {
ItemText *t = static_cast<ItemText *>(it);
- Ref<Font> font = _find_font(it);
- if (font.is_null()) {
- font = p_base_font;
+ Ref<Font> font = p_base_font;
+ int font_size = p_base_font_size;
+
+ ItemFont *font_it = _find_font(it);
+ if (font_it) {
+ if (font_it->font.is_valid()) {
+ font = font_it->font;
+ }
+ if (font_it->font_size > 0) {
+ font_size = font_it->font_size;
+ }
}
- int font_size = _find_font_size(it);
- if (font_size == -1) {
- font_size = p_base_font_size;
+ ItemFontSize *font_size_it = _find_font_size(it);
+ if (font_size_it && font_size_it->font_size > 0) {
+ font_size = font_size_it->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 +537,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;
@@ -743,13 +774,21 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
}
if (!prefix.is_empty()) {
- Ref<Font> font = _find_font(l.from);
- if (font.is_null()) {
- font = get_theme_font(SNAME("normal_font"));
+ Ref<Font> font = get_theme_font(SNAME("normal_font"));
+ int font_size = get_theme_font_size(SNAME("normal_font_size"));
+
+ ItemFont *font_it = _find_font(l.from);
+ if (font_it) {
+ if (font_it->font.is_valid()) {
+ font = font_it->font;
+ }
+ if (font_it->font_size > 0) {
+ font_size = font_it->font_size;
+ }
}
- int font_size = _find_font_size(l.from);
- if (font_size == -1) {
- font_size = get_theme_font_size(SNAME("normal_font_size"));
+ ItemFontSize *font_size_it = _find_font_size(l.from);
+ if (font_size_it && font_size_it->font_size > 0) {
+ font_size = font_size_it->font_size;
}
if (rtl) {
float offx = 0.0f;
@@ -782,17 +821,18 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
off.y += line_spacing;
}
- RID rid = l.text_buf->get_line_rid(line);
if (p_ofs.y + off.y >= ctrl_size.height) {
break;
}
- if (p_ofs.y + off.y + TS->shaped_text_get_size(rid).y <= 0) {
- off.y += TS->shaped_text_get_size(rid).y;
+
+ const Size2 line_size = l.text_buf->get_line_size(line);
+ if (p_ofs.y + off.y + line_size.y <= 0) {
+ off.y += line_size.y;
continue;
}
float width = l.text_buf->get_width();
- float length = TS->shaped_text_get_width(rid);
+ float length = line_size.x;
// Draw line.
line_count++;
@@ -835,9 +875,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
}
+ RID rid = l.text_buf->get_line_rid(line);
//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 +1340,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;
@@ -1343,6 +1384,8 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Point2i &p_click, ItemFrame **r_click_frame, int *r_click_line, Item **r_click_item, int *r_click_char, bool p_table) {
Vector2 off;
+ bool line_clicked = false;
+ float text_rect_begin = 0.0;
int char_pos = -1;
Line &l = p_frame->lines[p_line];
MutexLock lock(l.text_buf->get_mutex());
@@ -1394,7 +1437,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++) {
@@ -1468,7 +1511,11 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
}
if (p_click.y >= rect.position.y && p_click.y <= rect.position.y + rect.size.y) {
- char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x);
+ if ((!rtl && p_click.x >= rect.position.x) || (rtl && p_click.x <= rect.position.x + rect.size.x)) {
+ char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x);
+ }
+ line_clicked = true;
+ text_rect_begin = rtl ? rect.position.x + rect.size.x : rect.position.x;
}
// If table hit was detected, and line hit is in the table bounds use table hit.
@@ -1491,27 +1538,49 @@ 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.
- if (char_pos >= 0) {
+ if (line_clicked) {
// Find item.
if (r_click_item != nullptr) {
Item *it = p_frame->lines[p_line].from;
Item *it_to = (p_line + 1 < (int)p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr;
- if (char_pos == p_frame->lines[p_line].char_count) {
- // Selection after the end of line, select last item.
- if (it_to != nullptr) {
- *r_click_item = _get_prev_item(it_to);
- } else {
- for (Item *i = it; i; i = _get_next_item(i)) {
- *r_click_item = i;
+ if (char_pos >= 0) {
+ *r_click_item = _get_item_at_pos(it, it_to, char_pos);
+ } else {
+ int stop = text_rect_begin;
+ *r_click_item = _find_indentable(it);
+ while (*r_click_item) {
+ Ref<Font> font = get_theme_font(SNAME("normal_font"));
+ int font_size = get_theme_font_size(SNAME("normal_font_size"));
+ ItemFont *font_it = _find_font(*r_click_item);
+ if (font_it) {
+ if (font_it->font.is_valid()) {
+ font = font_it->font;
+ }
+ if (font_it->font_size > 0) {
+ font_size = font_it->font_size;
+ }
}
+ ItemFontSize *font_size_it = _find_font_size(*r_click_item);
+ if (font_size_it && font_size_it->font_size > 0) {
+ font_size = font_size_it->font_size;
+ }
+ if (rtl) {
+ stop += tab_size * font->get_char_size(' ', font_size).width;
+ if (stop > p_click.x) {
+ break;
+ }
+ } else {
+ stop -= tab_size * font->get_char_size(' ', font_size).width;
+ if (stop < p_click.x) {
+ break;
+ }
+ }
+ *r_click_item = _find_indentable((*r_click_item)->parent);
}
- } else {
- // Selection in the line.
- *r_click_item = _get_item_at_pos(it, it_to, char_pos);
}
}
@@ -2068,34 +2137,47 @@ void RichTextLabel::_find_frame(Item *p_item, ItemFrame **r_frame, int *r_line)
}
}
-Ref<Font> RichTextLabel::_find_font(Item *p_item) {
+RichTextLabel::Item *RichTextLabel::_find_indentable(Item *p_item) {
+ Item *indentable = p_item;
+
+ while (indentable) {
+ if (indentable->type == ITEM_INDENT || indentable->type == ITEM_LIST) {
+ return indentable;
+ }
+ indentable = indentable->parent;
+ }
+
+ return indentable;
+}
+
+RichTextLabel::ItemFont *RichTextLabel::_find_font(Item *p_item) {
Item *fontitem = p_item;
while (fontitem) {
if (fontitem->type == ITEM_FONT) {
ItemFont *fi = static_cast<ItemFont *>(fontitem);
- return fi->font;
+ return fi;
}
fontitem = fontitem->parent;
}
- return Ref<Font>();
+ return nullptr;
}
-int RichTextLabel::_find_font_size(Item *p_item) {
+RichTextLabel::ItemFontSize *RichTextLabel::_find_font_size(Item *p_item) {
Item *sizeitem = p_item;
while (sizeitem) {
if (sizeitem->type == ITEM_FONT_SIZE) {
ItemFontSize *fi = static_cast<ItemFontSize *>(sizeitem);
- return fi->font_size;
+ return fi;
}
sizeitem = sizeitem->parent;
}
- return -1;
+ return nullptr;
}
int RichTextLabel::_find_outline_size(Item *p_item, int p_default) {
@@ -2113,21 +2195,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;
@@ -2196,26 +2263,42 @@ int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int
while (item) {
if (item->type == ITEM_INDENT) {
- Ref<Font> font = _find_font(item);
- if (font.is_null()) {
- font = p_base_font;
+ Ref<Font> font = p_base_font;
+ int font_size = p_base_font_size;
+
+ ItemFont *font_it = _find_font(item);
+ if (font_it) {
+ if (font_it->font.is_valid()) {
+ font = font_it->font;
+ }
+ if (font_it->font_size > 0) {
+ font_size = font_it->font_size;
+ }
}
- int font_size = _find_font_size(item);
- if (font_size == -1) {
- font_size = p_base_font_size;
+ ItemFontSize *font_size_it = _find_font_size(item);
+ if (font_size_it && font_size_it->font_size > 0) {
+ font_size = font_size_it->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);
- if (font.is_null()) {
- font = p_base_font;
+ Ref<Font> font = p_base_font;
+ int font_size = p_base_font_size;
+
+ ItemFont *font_it = _find_font(item);
+ if (font_it) {
+ if (font_it->font.is_valid()) {
+ font = font_it->font;
+ }
+ if (font_it->font_size > 0) {
+ font_size = font_it->font_size;
+ }
}
- int font_size = _find_font_size(item);
- if (font_size == -1) {
- font_size = p_base_font_size;
+ ItemFontSize *font_size_it = _find_font_size(item);
+ if (font_size_it && font_size_it->font_size > 0) {
+ font_size = font_size_it->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 +2667,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);
@@ -2892,7 +2975,7 @@ void RichTextLabel::push_dropcap(const String &p_string, const Ref<Font> &p_font
_add_item(item, false);
}
-void RichTextLabel::push_font(const Ref<Font> &p_font) {
+void RichTextLabel::push_font(const Ref<Font> &p_font, int p_size) {
_stop_thread();
MutexLock data_lock(data_mutex);
@@ -2901,6 +2984,7 @@ void RichTextLabel::push_font(const Ref<Font> &p_font) {
ItemFont *item = memnew(ItemFont);
item->font = p_font;
+ item->font_size = p_size;
_add_item(item, true);
}
@@ -2908,35 +2992,35 @@ void RichTextLabel::push_normal() {
Ref<Font> normal_font = get_theme_font(SNAME("normal_font"));
ERR_FAIL_COND(normal_font.is_null());
- push_font(normal_font);
+ push_font(normal_font, get_theme_font_size(SNAME("normal_font_size")));
}
void RichTextLabel::push_bold() {
Ref<Font> bold_font = get_theme_font(SNAME("bold_font"));
ERR_FAIL_COND(bold_font.is_null());
- push_font(bold_font);
+ push_font(bold_font, get_theme_font_size(SNAME("bold_font_size")));
}
void RichTextLabel::push_bold_italics() {
Ref<Font> bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
ERR_FAIL_COND(bold_italics_font.is_null());
- push_font(bold_italics_font);
+ push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size")));
}
void RichTextLabel::push_italics() {
Ref<Font> italics_font = get_theme_font(SNAME("italics_font"));
ERR_FAIL_COND(italics_font.is_null());
- push_font(italics_font);
+ push_font(italics_font, get_theme_font_size(SNAME("italics_font_size")));
}
void RichTextLabel::push_mono() {
Ref<Font> mono_font = get_theme_font(SNAME("mono_font"));
ERR_FAIL_COND(mono_font.is_null());
- push_font(mono_font);
+ push_font(mono_font, get_theme_font_size(SNAME("mono_font_size")));
}
void RichTextLabel::push_font_size(int p_font_size) {
@@ -2950,25 +3034,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);
}
@@ -3537,9 +3610,9 @@ void RichTextLabel::append_text(const String &p_bbcode) {
//use bold font
in_bold = true;
if (in_italics) {
- push_font(bold_italics_font);
+ push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size")));
} else {
- push_font(bold_font);
+ push_font(bold_font, get_theme_font_size(SNAME("bold_font_size")));
}
pos = brk_end + 1;
tag_stack.push_front(tag);
@@ -3547,15 +3620,15 @@ void RichTextLabel::append_text(const String &p_bbcode) {
//use italics font
in_italics = true;
if (in_bold) {
- push_font(bold_italics_font);
+ push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size")));
} else {
- push_font(italics_font);
+ push_font(italics_font, get_theme_font_size(SNAME("italics_font_size")));
}
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "code") {
//use monospace font
- push_font(mono_font);
+ push_font(mono_font, get_theme_font_size(SNAME("mono_font_size")));
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag.begins_with("table=")) {
@@ -3840,8 +3913,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 +4047,132 @@ 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 = normal_font;
+ int font_size = 0;
+ ItemFont *font_it = _find_font(current);
+ if (font_it) {
+ if (font_it->font.is_valid()) {
+ font = font_it->font;
+ }
+ if (font_it->font_size > 0) {
+ font_size = font_it->font_size;
+ }
+ }
+ 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, font_size);
}
- 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();
+ int fnt_size = 0;
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);
+ fnt_size = subtag_a[1].to_int();
+ } 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, fnt_size);
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");
@@ -4805,11 +4946,10 @@ void RichTextLabel::install_effect(const Variant effect) {
Ref<RichTextEffect> rteffect;
rteffect = effect;
- if (rteffect.is_valid()) {
- custom_effects.push_back(effect);
- if ((!text.is_empty()) && use_bbcode) {
- parse_bbcode(text);
- }
+ ERR_FAIL_COND_MSG(rteffect.is_null(), "Invalid RichTextEffect resource.");
+ custom_effects.push_back(effect);
+ if ((!text.is_empty()) && use_bbcode) {
+ parse_bbcode(text);
}
}
@@ -4852,9 +4992,8 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(INLINE_ALIGNMENT_CENTER));
ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline);
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", "font", "font_size"), &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 +5157,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..e5f0469c01 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -178,6 +178,7 @@ private:
struct ItemFont : public Item {
Ref<Font> font;
+ int font_size = 0;
ItemFont() { type = ITEM_FONT; }
};
@@ -186,11 +187,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; }
@@ -464,11 +460,11 @@ private:
String _roman(int p_num, bool p_capitalize) const;
String _letters(int p_num, bool p_capitalize) const;
+ Item *_find_indentable(Item *p_item);
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);
+ ItemFontSize *_find_font_size(Item *p_item);
+ ItemFont *_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);
@@ -523,9 +519,8 @@ public:
void add_newline();
bool remove_line(const int p_line);
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(const Ref<Font> &p_font, int p_size = 0);
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/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index f387f91a8b..48c57d9b1b 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -303,7 +303,7 @@ void ScrollBar::_notification(int p_what) {
if (drag_node) {
drag_node->connect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input));
- drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), varray(), CONNECT_ONESHOT);
+ drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), CONNECT_ONESHOT);
}
} break;
@@ -595,7 +595,7 @@ void ScrollBar::set_drag_node(const NodePath &p_path) {
if (drag_node) {
drag_node->connect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input));
- drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), varray(), CONNECT_ONESHOT);
+ drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), CONNECT_ONESHOT);
}
}
}
diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h
index 651edd1a74..1823f86a67 100644
--- a/scene/gui/scroll_bar.h
+++ b/scene/gui/scroll_bar.h
@@ -128,4 +128,4 @@ public:
ScrollBar(VERTICAL) { set_h_size_flags(0); }
};
-#endif
+#endif // SCROLL_BAR_H
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 871cc520e9..8fd547813d 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -38,9 +38,13 @@ Size2 ScrollContainer::get_minimum_size() const {
Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
Size2 min_size;
+ // Calculated in this function, as it needs to traverse all child controls once to calculate;
+ // and needs to be calculated before being used by update_scrollbars().
+ largest_child_min_size = Size2();
+
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
- if (!c) {
+ if (!c || !c->is_visible()) {
continue;
}
if (c->is_set_as_top_level()) {
@@ -49,22 +53,30 @@ Size2 ScrollContainer::get_minimum_size() const {
if (c == h_scroll || c == v_scroll) {
continue;
}
- Size2 minsize = c->get_combined_minimum_size();
- if (horizontal_scroll_mode == SCROLL_MODE_DISABLED) {
- min_size.x = MAX(min_size.x, minsize.x);
- }
- if (vertical_scroll_mode == SCROLL_MODE_DISABLED) {
- min_size.y = MAX(min_size.y, minsize.y);
- }
+ Size2 child_min_size = c->get_combined_minimum_size();
+
+ largest_child_min_size.x = MAX(largest_child_min_size.x, child_min_size.x);
+ largest_child_min_size.y = MAX(largest_child_min_size.y, child_min_size.y);
}
- if (h_scroll->is_visible_in_tree()) {
+ if (horizontal_scroll_mode == SCROLL_MODE_DISABLED) {
+ min_size.x = MAX(min_size.x, largest_child_min_size.x);
+ }
+ if (vertical_scroll_mode == SCROLL_MODE_DISABLED) {
+ min_size.y = MAX(min_size.y, largest_child_min_size.y);
+ }
+
+ bool h_scroll_show = horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.x > min_size.x);
+ bool v_scroll_show = vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.y > min_size.y);
+
+ if (h_scroll_show && h_scroll->get_parent() == this) {
min_size.y += h_scroll->get_minimum_size().y;
}
- if (v_scroll->is_visible_in_tree()) {
+ if (v_scroll_show && v_scroll->get_parent() == this) {
min_size.x += v_scroll->get_minimum_size().x;
}
+
min_size += sb->get_minimum_size();
return min_size;
}
@@ -254,8 +266,8 @@ void ScrollContainer::ensure_control_visible(Control *p_control) {
set_v_scroll(get_v_scroll() + (diff.y - global_rect.position.y));
}
-void ScrollContainer::_update_dimensions() {
- child_max_size = Size2(0, 0);
+void ScrollContainer::_reposition_children() {
+ update_scrollbars();
Size2 size = get_size();
Point2 ofs;
@@ -274,7 +286,7 @@ void ScrollContainer::_update_dimensions() {
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
- if (!c) {
+ if (!c || !c->is_visible()) {
continue;
}
if (c->is_set_as_top_level()) {
@@ -284,25 +296,13 @@ void ScrollContainer::_update_dimensions() {
continue;
}
Size2 minsize = c->get_combined_minimum_size();
- child_max_size.x = MAX(child_max_size.x, minsize.x);
- child_max_size.y = MAX(child_max_size.y, minsize.y);
Rect2 r = Rect2(-Size2(get_h_scroll(), get_v_scroll()), minsize);
- if (horizontal_scroll_mode == SCROLL_MODE_DISABLED || (!h_scroll->is_visible_in_tree() && c->get_h_size_flags() & SIZE_EXPAND)) {
- r.position.x = 0;
- if (c->get_h_size_flags() & SIZE_EXPAND) {
- r.size.width = MAX(size.width, minsize.width);
- } else {
- r.size.width = minsize.width;
- }
+ if (c->get_h_size_flags() & SIZE_EXPAND) {
+ r.size.width = MAX(size.width, minsize.width);
}
- if (vertical_scroll_mode == SCROLL_MODE_DISABLED || (!v_scroll->is_visible_in_tree() && c->get_v_size_flags() & SIZE_EXPAND)) {
- r.position.y = 0;
- if (c->get_v_size_flags() & SIZE_EXPAND) {
- r.size.height = MAX(size.height, minsize.height);
- } else {
- r.size.height = minsize.height;
- }
+ if (c->get_v_size_flags() & SIZE_EXPAND) {
+ r.size.height = MAX(size.height, minsize.height);
}
r.position += ofs;
if (rtl && v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) {
@@ -329,18 +329,16 @@ void ScrollContainer::_notification(int p_what) {
Viewport *viewport = get_viewport();
ERR_FAIL_COND(!viewport);
viewport->connect("gui_focus_changed", callable_mp(this, &ScrollContainer::_gui_focus_changed));
- _update_dimensions();
+ _reposition_children();
} break;
case NOTIFICATION_SORT_CHILDREN: {
- _update_dimensions();
+ _reposition_children();
} break;
case NOTIFICATION_DRAW: {
Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
draw_style_box(sb, Rect2(Vector2(), get_size()));
-
- update_scrollbars();
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@@ -418,36 +416,25 @@ void ScrollContainer::update_scrollbars() {
Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
size -= sb->get_minimum_size();
- Size2 hmin;
- Size2 vmin;
- if (horizontal_scroll_mode != SCROLL_MODE_DISABLED) {
- hmin = h_scroll->get_combined_minimum_size();
- }
- if (vertical_scroll_mode != SCROLL_MODE_DISABLED) {
- vmin = v_scroll->get_combined_minimum_size();
- }
-
- Size2 min = child_max_size;
+ Size2 hmin = h_scroll->get_combined_minimum_size();
+ Size2 vmin = v_scroll->get_combined_minimum_size();
- bool hide_scroll_h = horizontal_scroll_mode != SCROLL_MODE_SHOW_ALWAYS && (horizontal_scroll_mode == SCROLL_MODE_DISABLED || horizontal_scroll_mode == SCROLL_MODE_SHOW_NEVER || (horizontal_scroll_mode == SCROLL_MODE_AUTO && min.width <= size.width));
- bool hide_scroll_v = vertical_scroll_mode != SCROLL_MODE_SHOW_ALWAYS && (vertical_scroll_mode == SCROLL_MODE_DISABLED || vertical_scroll_mode == SCROLL_MODE_SHOW_NEVER || (vertical_scroll_mode == SCROLL_MODE_AUTO && min.height <= size.height));
+ h_scroll->set_visible(horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.width > size.width));
+ v_scroll->set_visible(vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.height > size.height));
- h_scroll->set_max(min.width);
- h_scroll->set_page(size.width - (hide_scroll_v ? 0 : vmin.width));
- h_scroll->set_visible(!hide_scroll_h);
+ h_scroll->set_max(largest_child_min_size.width);
+ h_scroll->set_page((v_scroll->is_visible() && v_scroll->get_parent() == this) ? size.width - vmin.width : size.width);
- v_scroll->set_max(min.height);
- v_scroll->set_page(size.height - (hide_scroll_h ? 0 : hmin.height));
- v_scroll->set_visible(!hide_scroll_v);
+ v_scroll->set_max(largest_child_min_size.height);
+ v_scroll->set_page((h_scroll->is_visible() && h_scroll->get_parent() == this) ? size.height - hmin.height : size.height);
// Avoid scrollbar overlapping.
- h_scroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, hide_scroll_v ? 0 : -vmin.width);
- v_scroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, hide_scroll_h ? 0 : -hmin.height);
+ h_scroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, (v_scroll->is_visible() && v_scroll->get_parent() == this) ? -vmin.width : 0);
+ v_scroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, (h_scroll->is_visible() && h_scroll->get_parent() == this) ? -hmin.height : 0);
}
void ScrollContainer::_scroll_moved(float) {
queue_sort();
- update();
};
void ScrollContainer::set_h_scroll(int p_pos) {
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index b9fcf64db6..bfa74cfd0f 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -50,7 +50,7 @@ private:
HScrollBar *h_scroll = nullptr;
VScrollBar *v_scroll = nullptr;
- Size2 child_max_size;
+ mutable Size2 largest_child_min_size; // The largest one among the min sizes of all available child controls.
void update_scrollbars();
@@ -75,7 +75,7 @@ protected:
Size2 get_minimum_size() const override;
void _gui_focus_changed(Control *p_control);
- void _update_dimensions();
+ void _reposition_children();
void _notification(int p_what);
void _scroll_moved(float);
@@ -116,4 +116,4 @@ public:
VARIANT_ENUM_CAST(ScrollContainer::ScrollMode);
-#endif
+#endif // SCROLL_CONTAINER_H
diff --git a/scene/gui/separator.h b/scene/gui/separator.h
index 1621bb3351..e6578a4d04 100644
--- a/scene/gui/separator.h
+++ b/scene/gui/separator.h
@@ -60,4 +60,4 @@ public:
HSeparator();
};
-#endif
+#endif // SEPARATOR_H
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 4b680f72cf..64c07007dc 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -96,15 +96,15 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
if (grab.active) {
Size2i size = get_size();
Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber"));
- float motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos;
+ double motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos;
if (orientation == VERTICAL) {
motion = -motion;
}
- float areasize = orientation == VERTICAL ? size.height - grabber->get_size().height : size.width - grabber->get_size().width;
+ double areasize = orientation == VERTICAL ? size.height - grabber->get_size().height : size.width - grabber->get_size().width;
if (areasize <= 0) {
return;
}
- float umotion = motion / float(areasize);
+ double umotion = motion / double(areasize);
set_as_ratio(grab.uvalue + umotion);
}
}
@@ -180,7 +180,7 @@ void Slider::_notification(int p_what) {
if (orientation == VERTICAL) {
int widget_width = style->get_minimum_size().width + style->get_center_size().width;
- float areasize = size.height - grabber->get_size().height;
+ double areasize = size.height - grabber->get_size().height;
style->draw(ci, Rect2i(Point2i(size.width / 2 - widget_width / 2, 0), Size2i(widget_width, size.height)));
grabber_area->draw(ci, Rect2i(Point2i((size.width - widget_width) / 2, size.height - areasize * ratio - grabber->get_size().height / 2), Size2i(widget_width, areasize * ratio + grabber->get_size().height / 2)));
@@ -197,7 +197,7 @@ void Slider::_notification(int p_what) {
grabber->draw(ci, Point2i(size.width / 2 - grabber->get_size().width / 2, size.height - ratio * areasize - grabber->get_size().height));
} else {
int widget_height = style->get_minimum_size().height + style->get_center_size().height;
- float areasize = size.width - grabber->get_size().width;
+ double areasize = size.width - grabber->get_size().width;
style->draw(ci, Rect2i(Point2i(0, (size.height - widget_height) / 2), Size2i(size.width, widget_height)));
grabber_area->draw(ci, Rect2i(Point2i(0, (size.height - widget_height) / 2), Size2i(areasize * ratio + grabber->get_size().width / 2, widget_height)));
@@ -218,11 +218,11 @@ void Slider::_notification(int p_what) {
}
}
-void Slider::set_custom_step(float p_custom_step) {
+void Slider::set_custom_step(double p_custom_step) {
custom_step = p_custom_step;
}
-float Slider::get_custom_step() const {
+double Slider::get_custom_step() const {
return custom_step;
}
diff --git a/scene/gui/slider.h b/scene/gui/slider.h
index 5fbfee2aec..5abaee27aa 100644
--- a/scene/gui/slider.h
+++ b/scene/gui/slider.h
@@ -38,14 +38,14 @@ class Slider : public Range {
struct Grab {
int pos = 0;
- float uvalue = 0.0;
+ double uvalue = 0.0;
bool active = false;
} grab;
int ticks = 0;
bool mouse_inside = false;
Orientation orientation;
- float custom_step = -1.0;
+ double custom_step = -1.0;
bool editable = true;
bool scrollable = true;
@@ -58,8 +58,8 @@ protected:
public:
virtual Size2 get_minimum_size() const override;
- void set_custom_step(float p_custom_step);
- float get_custom_step() const;
+ void set_custom_step(double p_custom_step);
+ double get_custom_step() const;
void set_ticks(int p_count);
int get_ticks() const;
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 890e349afb..8a7f52b0d9 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -88,7 +88,8 @@ void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) {
void SpinBox::_range_click_timeout() {
if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) {
bool up = get_local_mouse_position().y < (get_size().height / 2);
- set_value(get_value() + (up ? get_step() : -get_step()));
+ double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step();
+ set_value(get_value() + (up ? step : -step));
if (range_click_timer->is_one_shot()) {
range_click_timer->set_wait_time(0.075);
@@ -118,6 +119,8 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
+ double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step();
+
if (mb.is_valid() && mb->is_pressed()) {
bool up = mb->get_position().y < (get_size().height / 2);
@@ -125,7 +128,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) {
case MouseButton::LEFT: {
line_edit->grab_focus();
- set_value(get_value() + (up ? get_step() : -get_step()));
+ set_value(get_value() + (up ? step : -step));
range_click_timer->set_wait_time(0.6);
range_click_timer->set_one_shot(true);
@@ -140,13 +143,13 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) {
} break;
case MouseButton::WHEEL_UP: {
if (line_edit->has_focus()) {
- set_value(get_value() + get_step() * mb->get_factor());
+ set_value(get_value() + step * mb->get_factor());
accept_event();
}
} break;
case MouseButton::WHEEL_DOWN: {
if (line_edit->has_focus()) {
- set_value(get_value() - get_step() * mb->get_factor());
+ set_value(get_value() - step * mb->get_factor());
accept_event();
}
} break;
@@ -167,8 +170,8 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
if (drag.enabled) {
drag.diff_y += mm->get_relative().y;
- float diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8f) * SIGN(drag.diff_y);
- set_value(CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max()));
+ double diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8) * SIGN(drag.diff_y);
+ set_value(CLAMP(drag.base_val + step * diff_y, get_min(), get_max()));
} else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
drag.enabled = true;
@@ -272,7 +275,7 @@ void SpinBox::set_update_on_text_changed(bool p_enabled) {
update_on_text_changed = p_enabled;
if (p_enabled) {
- line_edit->connect("text_changed", callable_mp(this, &SpinBox::_text_changed), Vector<Variant>(), CONNECT_DEFERRED);
+ line_edit->connect("text_changed", callable_mp(this, &SpinBox::_text_changed), CONNECT_DEFERRED);
} else {
line_edit->disconnect("text_changed", callable_mp(this, &SpinBox::_text_changed));
}
@@ -294,6 +297,14 @@ void SpinBox::apply() {
_text_submitted(line_edit->get_text());
}
+void SpinBox::set_custom_arrow_step(double p_custom_arrow_step) {
+ custom_arrow_step = p_custom_arrow_step;
+}
+
+double SpinBox::get_custom_arrow_step() const {
+ return custom_arrow_step;
+}
+
void SpinBox::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &SpinBox::set_horizontal_alignment);
ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &SpinBox::get_horizontal_alignment);
@@ -302,6 +313,8 @@ void SpinBox::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_prefix", "prefix"), &SpinBox::set_prefix);
ClassDB::bind_method(D_METHOD("get_prefix"), &SpinBox::get_prefix);
ClassDB::bind_method(D_METHOD("set_editable", "enabled"), &SpinBox::set_editable);
+ ClassDB::bind_method(D_METHOD("set_custom_arrow_step", "arrow_step"), &SpinBox::set_custom_arrow_step);
+ ClassDB::bind_method(D_METHOD("get_custom_arrow_step"), &SpinBox::get_custom_arrow_step);
ClassDB::bind_method(D_METHOD("is_editable"), &SpinBox::is_editable);
ClassDB::bind_method(D_METHOD("set_update_on_text_changed", "enabled"), &SpinBox::set_update_on_text_changed);
ClassDB::bind_method(D_METHOD("get_update_on_text_changed"), &SpinBox::get_update_on_text_changed);
@@ -313,18 +326,19 @@ void SpinBox::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_on_text_changed"), "set_update_on_text_changed", "get_update_on_text_changed");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "prefix"), "set_prefix", "get_prefix");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_arrow_step"), "set_custom_arrow_step", "get_custom_arrow_step");
}
SpinBox::SpinBox() {
line_edit = memnew(LineEdit);
add_child(line_edit, false, INTERNAL_MODE_FRONT);
- line_edit->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ line_edit->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
line_edit->set_mouse_filter(MOUSE_FILTER_PASS);
line_edit->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT);
- line_edit->connect("text_submitted", callable_mp(this, &SpinBox::_text_submitted), Vector<Variant>(), CONNECT_DEFERRED);
- line_edit->connect("focus_exited", callable_mp(this, &SpinBox::_line_edit_focus_exit), Vector<Variant>(), CONNECT_DEFERRED);
+ line_edit->connect("text_submitted", callable_mp(this, &SpinBox::_text_submitted), CONNECT_DEFERRED);
+ line_edit->connect("focus_exited", callable_mp(this, &SpinBox::_line_edit_focus_exit), CONNECT_DEFERRED);
line_edit->connect("gui_input", callable_mp(this, &SpinBox::_line_edit_input));
range_click_timer = memnew(Timer);
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index d118b28334..0aae9efe78 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -52,15 +52,16 @@ class SpinBox : public Range {
String prefix;
String suffix;
+ double custom_arrow_step = 0.0;
void _line_edit_input(const Ref<InputEvent> &p_event);
struct Drag {
- float base_val = 0.0;
+ double base_val = 0.0;
bool allowed = false;
bool enabled = false;
Vector2 capture_pos;
- float diff_y = 0.0;
+ double diff_y = 0.0;
} drag;
void _line_edit_focus_exit();
@@ -95,6 +96,8 @@ public:
bool get_update_on_text_changed() const;
void apply();
+ void set_custom_arrow_step(const double p_custom_arrow_step);
+ double get_custom_arrow_step() const;
SpinBox();
};
diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h
index 55b7802aa4..5b488fb79e 100644
--- a/scene/gui/subviewport_container.h
+++ b/scene/gui/subviewport_container.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VIEWPORTCONTAINER_H
-#define VIEWPORTCONTAINER_H
+#ifndef SUBVIEWPORT_CONTAINER_H
+#define SUBVIEWPORT_CONTAINER_H
#include "scene/gui/container.h"
@@ -63,4 +63,4 @@ public:
SubViewportContainer();
};
-#endif // VIEWPORTCONTAINER_H
+#endif // SUBVIEWPORT_CONTAINER_H
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/tab_container.cpp b/scene/gui/tab_container.cpp
index fa929344d4..12f91a9873 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -233,7 +233,7 @@ void TabContainer::_repaint() {
if (i == current) {
c->show();
- c->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ c->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
if (tabs_visible) {
c->set_offset(SIDE_TOP, _get_top_margin());
@@ -312,7 +312,7 @@ Vector<Control *> TabContainer::_get_tab_controls() const {
Vector<Control *> controls;
for (int i = 0; i < get_child_count(); i++) {
Control *control = Object::cast_to<Control>(get_child(i));
- if (!control || control->is_set_as_top_level() || control == tab_bar) {
+ if (!control || control->is_set_as_top_level() || control == tab_bar || control == child_removing) {
continue;
}
@@ -549,7 +549,12 @@ void TabContainer::remove_child_notify(Node *p_child) {
return;
}
- tab_bar->remove_tab(get_tab_idx_from_control(c));
+ int idx = get_tab_idx_from_control(c);
+
+ // Before this, the tab control has not changed; after this, the tab control has changed.
+ child_removing = p_child;
+ tab_bar->remove_tab(idx);
+ child_removing = nullptr;
_update_margins();
if (get_tab_count() == 0) {
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index 9adaa0d844..60c8130939 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -46,6 +46,7 @@ class TabContainer : public Container {
bool drag_to_rearrange_enabled = false;
bool use_hidden_tabs_for_min_size = false;
bool theme_changing = false;
+ Node *child_removing = nullptr;
int _get_top_margin() const;
Vector<Control *> _get_tab_controls() const;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 5506616b7a..c023b06895 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);
}
@@ -448,8 +443,10 @@ void TextEdit::_notification(int p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
- _update_caches();
- _update_wrap_at_column(true);
+ if (is_inside_tree()) {
+ _update_caches();
+ _update_wrap_at_column(true);
+ }
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_IN: {
@@ -973,7 +970,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 {
@@ -1060,7 +1057,7 @@ void TextEdit::_notification(int p_what) {
const Variant *argp[] = { &args[0], &args[1], &args[2] };
Callable::CallError ce;
Variant ret;
- gutter.custom_draw_callback.call(argp, 3, ret, ce);
+ gutter.custom_draw_callback.callp(argp, 3, ret, ce);
}
} break;
}
@@ -1071,7 +1068,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;
@@ -1222,7 +1219,7 @@ void TextEdit::_notification(int p_what) {
if (brace_open_mismatch) {
current_color = brace_mismatch_color;
}
- Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, font->get_underline_thickness(font_size));
+ Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, MAX(font->get_underline_thickness(font_size) * get_theme_default_base_scale(), 1));
draw_rect(rect, current_color);
}
@@ -1231,7 +1228,7 @@ void TextEdit::_notification(int p_what) {
if (brace_close_mismatch) {
current_color = brace_mismatch_color;
}
- Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, font->get_underline_thickness(font_size));
+ Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, MAX(font->get_underline_thickness(font_size) * get_theme_default_base_scale(), 1));
draw_rect(rect, current_color);
}
}
@@ -1355,7 +1352,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;
}
@@ -1469,7 +1466,7 @@ void TextEdit::_notification(int p_what) {
caret_end = caret_start + post_text.length();
}
- DisplayServer::get_singleton()->virtual_keyboard_show(get_text(), get_global_rect(), true, -1, caret_start, caret_end);
+ DisplayServer::get_singleton()->virtual_keyboard_show(get_text(), get_global_rect(), DisplayServer::KEYBOARD_TYPE_MULTILINE, -1, caret_start, caret_end);
}
} break;
@@ -2573,7 +2570,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 +2579,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 +2650,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 +2664,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 {
@@ -2791,7 +2791,7 @@ String TextEdit::get_tooltip(const Point2 &p_pos) const {
const Variant *argp[] = { &args[0] };
Callable::CallError ce;
Variant ret;
- tooltip_callback.call(argp, 1, ret, ce);
+ tooltip_callback.callp(argp, 1, ret, ce);
ERR_FAIL_COND_V_MSG(ce.error != Callable::CallError::CALL_OK, "", "Failed to call custom tooltip.");
return ret;
}
@@ -2854,33 +2854,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 +4472,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 +5040,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 +5072,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 +5279,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 +5294,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 +5393,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 +5414,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 +5432,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 +5459,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 +6129,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/texture_button.h b/scene/gui/texture_button.h
index 5762949acd..9f6f7c1515 100644
--- a/scene/gui/texture_button.h
+++ b/scene/gui/texture_button.h
@@ -101,4 +101,5 @@ public:
};
VARIANT_ENUM_CAST(TextureButton::StretchMode);
+
#endif // TEXTURE_BUTTON_H
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index d3e7540790..1eb6c5a554 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());
@@ -754,7 +723,12 @@ TreeItem *TreeItem::get_next_visible(bool p_wrap) {
TreeItem *TreeItem::get_child(int p_idx) {
_create_children_cache();
+
+ if (p_idx < 0) {
+ p_idx += children_cache.size();
+ }
ERR_FAIL_INDEX_V(p_idx, children_cache.size(), nullptr);
+
return children_cache.get(p_idx);
}
@@ -1269,10 +1243,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 +1637,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 +1695,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;
}
@@ -1879,15 +1849,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
p_item->set_meta("__focus_rect", Rect2(r.position, r.size));
- if (rtl) {
- r.position.x = get_size().width - r.position.x - r.size.x;
- }
-
- if (p_item->cells[i].selected) {
- if (has_focus()) {
- cache.selected_focus->draw(ci, r);
- } else {
- cache.selected->draw(ci, r);
+ if (select_mode != SELECT_ROW) {
+ if (rtl) {
+ r.position.x = get_size().width - r.position.x - r.size.x;
+ }
+ if (p_item->cells[i].selected) {
+ if (has_focus()) {
+ cache.selected_focus->draw(ci, r);
+ } else {
+ cache.selected->draw(ci, r);
+ }
}
}
}
@@ -2850,6 +2821,9 @@ void Tree::value_editor_changed(double p_value) {
TreeItem::Cell &c = popup_edited_item->cells.write[popup_edited_item_col];
c.val = p_value;
+
+ text_editor->set_text(String::num(c.val, Math::range_step_decimals(c.step)));
+
item_edited(popup_edited_item_col, popup_edited_item);
update();
}
@@ -3002,6 +2976,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 +3499,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 +4183,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 +4462,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 +4948,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);
@@ -5063,7 +5024,7 @@ Tree::Tree() {
popup_editor_vb = memnew(VBoxContainer);
popup_editor->add_child(popup_editor_vb);
popup_editor_vb->add_theme_constant_override("separation", 0);
- popup_editor_vb->set_anchors_and_offsets_preset(PRESET_WIDE);
+ popup_editor_vb->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
text_editor = memnew(LineEdit);
popup_editor_vb->add_child(text_editor);
text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 0a8dd3204a..f0819e2980 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;
@@ -727,4 +719,5 @@ public:
VARIANT_ENUM_CAST(Tree::SelectMode);
VARIANT_ENUM_CAST(Tree::DropModeFlags);
-#endif
+
+#endif // TREE_H
diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp
index 86334882fa..f20a2ad67b 100644
--- a/scene/gui/video_stream_player.cpp
+++ b/scene/gui/video_stream_player.cpp
@@ -225,7 +225,7 @@ void VideoStreamPlayer::set_stream(const Ref<VideoStream> &p_stream) {
stream = p_stream;
if (stream.is_valid()) {
stream->set_audio_track(audio_track);
- playback = stream->instance_playback();
+ playback = stream->instantiate_playback();
} else {
playback = Ref<VideoStreamPlayback>();
}
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/gui/view_panner.cpp b/scene/gui/view_panner.cpp
index 892d0aba29..3b7f499a07 100644
--- a/scene/gui/view_panner.cpp
+++ b/scene/gui/view_panner.cpp
@@ -135,7 +135,7 @@ void ViewPanner::callback_helper(Callable p_callback, Vector<Variant> p_args) {
Variant result;
Callable::CallError ce;
- p_callback.call(argptr, p_args.size(), result, ce);
+ p_callback.callp(argptr, p_args.size(), result, ce);
}
void ViewPanner::set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback) {
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 3dc358a6c2..ce204c6aeb 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -64,9 +64,6 @@ void CanvasItem::_propagate_visibility_changed(bool p_parent_visible_in_tree) {
if (!visible) {
return;
}
- if (p_parent_visible_in_tree && first_draw) { // Avoid propagating it twice.
- first_draw = false;
- }
_handle_visibility_change(p_parent_visible_in_tree);
}
@@ -133,10 +130,6 @@ void CanvasItem::_update_callback() {
RenderingServer::get_singleton()->canvas_item_clear(get_canvas_item());
//todo updating = true - only allow drawing here
if (is_visible_in_tree()) {
- if (first_draw) {
- notification(NOTIFICATION_VISIBILITY_CHANGED);
- first_draw = false;
- }
drawing = true;
current_item_drawn = this;
notification(NOTIFICATION_DRAW);
@@ -230,16 +223,16 @@ void CanvasItem::_enter_canvas() {
RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, canvas);
- group = "root_canvas" + itos(canvas.get_id());
+ canvas_group = "root_canvas" + itos(canvas.get_id());
- add_to_group(group);
+ add_to_group(canvas_group);
if (canvas_layer) {
canvas_layer->reset_sort_index();
} else {
get_viewport()->gui_reset_canvas_sort_index();
}
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, group, SNAME("_top_level_raise_self"));
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, canvas_group, SNAME("_top_level_raise_self"));
} else {
CanvasItem *parent = get_parent_item();
@@ -258,14 +251,16 @@ void CanvasItem::_exit_canvas() {
notification(NOTIFICATION_EXIT_CANVAS, true); //reverse the notification
RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, RID());
canvas_layer = nullptr;
- group = StringName();
+ if (canvas_group != StringName()) {
+ remove_from_group(canvas_group);
+ canvas_group = StringName();
+ }
}
void CanvasItem::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
ERR_FAIL_COND(!is_inside_tree());
- first_draw = true;
Node *parent = get_parent();
if (parent) {
@@ -304,6 +299,10 @@ void CanvasItem::_notification(int p_what) {
}
}
+ RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, is_visible_in_tree()); // The visibility of the parent may change.
+ if (is_visible_in_tree()) {
+ notification(NOTIFICATION_VISIBILITY_CHANGED); // Considered invisible until entered.
+ }
_enter_canvas();
_update_texture_filter_changed(false);
@@ -319,8 +318,8 @@ void CanvasItem::_notification(int p_what) {
break;
}
- if (group != StringName()) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, group, "_top_level_raise_self");
+ if (canvas_group != StringName()) {
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, canvas_group, "_top_level_raise_self");
} else {
CanvasItem *p = get_parent_item();
ERR_FAIL_COND(!p);
@@ -658,24 +657,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, BitField<TextServer::JustificationFlag> p_jst_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_font_size, p_modulate, p_jst_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, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_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_multiline_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_modulate, p_brk_flags, p_jst_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, BitField<TextServer::JustificationFlag> p_jst_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_jst_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, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_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_brk_flags, p_jst_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 +923,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", "jst_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", "brk_flags", "jst_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), DEFVAL(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", "jst_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", "brk_flags", "jst_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), DEFVAL(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..38e0be1683 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -70,7 +70,7 @@ private:
mutable SelfList<Node> xform_change;
RID canvas_item;
- StringName group;
+ StringName canvas_group;
CanvasLayer *canvas_layer = nullptr;
@@ -83,7 +83,6 @@ private:
int light_mask = 1;
Window *window = nullptr;
- bool first_draw = false;
bool visible = true;
bool parent_visible_in_tree = false;
bool clip_children = false;
@@ -235,9 +234,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), BitField<TextServer::JustificationFlag> p_jst_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), BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_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_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), BitField<TextServer::JustificationFlag> p_jst_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), BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_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_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/http_request.h b/scene/main/http_request.h
index 49b4b1b30c..4b32188377 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef HTTPREQUEST_H
-#define HTTPREQUEST_H
+#ifndef HTTP_REQUEST_H
+#define HTTP_REQUEST_H
#include "core/io/http_client.h"
#include "core/os/thread.h"
@@ -162,4 +162,4 @@ public:
VARIANT_ENUM_CAST(HTTPRequest::Result);
-#endif // HTTPREQUEST_H
+#endif // HTTP_REQUEST_H
diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp
new file mode 100644
index 0000000000..95574042a8
--- /dev/null
+++ b/scene/main/multiplayer_api.cpp
@@ -0,0 +1,416 @@
+/*************************************************************************/
+/* multiplayer_api.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 "multiplayer_api.h"
+
+#include "core/debugger/engine_debugger.h"
+#include "core/io/marshalls.h"
+
+#include <stdint.h>
+
+#ifdef DEBUG_ENABLED
+#include "core/os/os.h"
+#endif
+
+StringName MultiplayerAPI::default_interface = StringName();
+
+void MultiplayerAPI::set_default_interface(const StringName &p_interface) {
+ ERR_FAIL_COND_MSG(!ClassDB::is_parent_class(p_interface, MultiplayerAPI::get_class_static()), vformat("Can't make %s the default multiplayer interface since it does not extend MultiplayerAPI.", p_interface));
+ default_interface = p_interface;
+}
+
+StringName MultiplayerAPI::get_default_interface() {
+ return default_interface;
+}
+
+Ref<MultiplayerAPI> MultiplayerAPI::create_default_interface() {
+ if (default_interface != StringName()) {
+ return Ref<MultiplayerAPI>(Object::cast_to<MultiplayerAPI>(ClassDB::instantiate(default_interface)));
+ }
+ return Ref<MultiplayerAPI>(memnew(MultiplayerAPIExtension));
+}
+
+// The variant is compressed and encoded; The first byte contains all the meta
+// information and the format is:
+// - The first LSB 5 bits are used for the variant type.
+// - The next two bits are used to store the encoding mode.
+// - The most significant is used to store the boolean value.
+#define VARIANT_META_TYPE_MASK 0x1F
+#define VARIANT_META_EMODE_MASK 0x60
+#define VARIANT_META_BOOL_MASK 0x80
+#define ENCODE_8 0 << 5
+#define ENCODE_16 1 << 5
+#define ENCODE_32 2 << 5
+#define ENCODE_64 3 << 5
+Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_allow_object_decoding) {
+ // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31
+ CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK);
+
+ uint8_t *buf = r_buffer;
+ r_len = 0;
+ uint8_t encode_mode = 0;
+
+ switch (p_variant.get_type()) {
+ case Variant::BOOL: {
+ if (buf) {
+ // We still have 1 free bit in the meta, so let's use it.
+ buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0;
+ buf[0] |= encode_mode | p_variant.get_type();
+ }
+ r_len += 1;
+ } break;
+ case Variant::INT: {
+ if (buf) {
+ // Reserve the first byte for the meta.
+ buf += 1;
+ }
+ r_len += 1;
+ int64_t val = p_variant;
+ if (val <= (int64_t)INT8_MAX && val >= (int64_t)INT8_MIN) {
+ // Use 8 bit
+ encode_mode = ENCODE_8;
+ if (buf) {
+ buf[0] = val;
+ }
+ r_len += 1;
+ } else if (val <= (int64_t)INT16_MAX && val >= (int64_t)INT16_MIN) {
+ // Use 16 bit
+ encode_mode = ENCODE_16;
+ if (buf) {
+ encode_uint16(val, buf);
+ }
+ r_len += 2;
+ } else if (val <= (int64_t)INT32_MAX && val >= (int64_t)INT32_MIN) {
+ // Use 32 bit
+ encode_mode = ENCODE_32;
+ if (buf) {
+ encode_uint32(val, buf);
+ }
+ r_len += 4;
+ } else {
+ // Use 64 bit
+ encode_mode = ENCODE_64;
+ if (buf) {
+ encode_uint64(val, buf);
+ }
+ r_len += 8;
+ }
+ // Store the meta
+ if (buf) {
+ buf -= 1;
+ buf[0] = encode_mode | p_variant.get_type();
+ }
+ } break;
+ default:
+ // Any other case is not yet compressed.
+ Error err = encode_variant(p_variant, r_buffer, r_len, p_allow_object_decoding);
+ if (err != OK) {
+ return err;
+ }
+ if (r_buffer) {
+ // The first byte is not used by the marshalling, so store the type
+ // so we know how to decompress and decode this variant.
+ r_buffer[0] = p_variant.get_type();
+ }
+ }
+
+ return OK;
+}
+
+Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding) {
+ const uint8_t *buf = p_buffer;
+ int len = p_len;
+
+ ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA);
+ uint8_t type = buf[0] & VARIANT_META_TYPE_MASK;
+ uint8_t encode_mode = buf[0] & VARIANT_META_EMODE_MASK;
+
+ ERR_FAIL_COND_V(type >= Variant::VARIANT_MAX, ERR_INVALID_DATA);
+
+ switch (type) {
+ case Variant::BOOL: {
+ bool val = (buf[0] & VARIANT_META_BOOL_MASK) > 0;
+ r_variant = val;
+ if (r_len) {
+ *r_len = 1;
+ }
+ } break;
+ case Variant::INT: {
+ buf += 1;
+ len -= 1;
+ if (r_len) {
+ *r_len = 1;
+ }
+ if (encode_mode == ENCODE_8) {
+ // 8 bits.
+ ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA);
+ int8_t val = buf[0];
+ r_variant = val;
+ if (r_len) {
+ (*r_len) += 1;
+ }
+ } else if (encode_mode == ENCODE_16) {
+ // 16 bits.
+ ERR_FAIL_COND_V(len < 2, ERR_INVALID_DATA);
+ int16_t val = decode_uint16(buf);
+ r_variant = val;
+ if (r_len) {
+ (*r_len) += 2;
+ }
+ } else if (encode_mode == ENCODE_32) {
+ // 32 bits.
+ ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
+ int32_t val = decode_uint32(buf);
+ r_variant = val;
+ if (r_len) {
+ (*r_len) += 4;
+ }
+ } else {
+ // 64 bits.
+ ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
+ int64_t val = decode_uint64(buf);
+ r_variant = val;
+ if (r_len) {
+ (*r_len) += 8;
+ }
+ }
+ } break;
+ default:
+ Error err = decode_variant(r_variant, p_buffer, p_len, r_len, p_allow_object_decoding);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+Error MultiplayerAPI::encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw, bool p_allow_object_decoding) {
+ r_len = 0;
+ int size = 0;
+
+ if (p_count == 0) {
+ if (r_raw) {
+ *r_raw = true;
+ }
+ return OK;
+ }
+
+ // Try raw encoding optimization.
+ if (r_raw && p_count == 1) {
+ *r_raw = false;
+ const Variant &v = *(p_variants[0]);
+ if (v.get_type() == Variant::PACKED_BYTE_ARRAY) {
+ *r_raw = true;
+ const PackedByteArray pba = v;
+ if (p_buffer) {
+ memcpy(p_buffer, pba.ptr(), pba.size());
+ }
+ r_len += pba.size();
+ } else {
+ encode_and_compress_variant(v, p_buffer, size, p_allow_object_decoding);
+ r_len += size;
+ }
+ return OK;
+ }
+
+ // Regular encoding.
+ for (int i = 0; i < p_count; i++) {
+ const Variant &v = *(p_variants[i]);
+ encode_and_compress_variant(v, p_buffer ? p_buffer + r_len : nullptr, size, p_allow_object_decoding);
+ r_len += size;
+ }
+ return OK;
+}
+
+Error MultiplayerAPI::decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw, bool p_allow_object_decoding) {
+ r_len = 0;
+ int argc = r_variants.size();
+ if (argc == 0 && p_raw) {
+ return OK;
+ }
+ ERR_FAIL_COND_V(p_raw && argc != 1, ERR_INVALID_DATA);
+ if (p_raw) {
+ r_len = p_len;
+ PackedByteArray pba;
+ pba.resize(p_len);
+ memcpy(pba.ptrw(), p_buffer, p_len);
+ r_variants.write[0] = pba;
+ return OK;
+ }
+
+ Vector<Variant> args;
+ Vector<const Variant *> argp;
+ args.resize(argc);
+
+ for (int i = 0; i < argc; i++) {
+ ERR_FAIL_COND_V_MSG(r_len >= p_len, ERR_INVALID_DATA, "Invalid packet received. Size too small.");
+
+ int vlen;
+ Error err = MultiplayerAPI::decode_and_decompress_variant(r_variants.write[i], &p_buffer[r_len], p_len - r_len, &vlen, p_allow_object_decoding);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid packet received. Unable to decode state variable.");
+ r_len += vlen;
+ }
+ return OK;
+}
+
+Error MultiplayerAPI::_rpc_bind(int p_peer, Object *p_object, const StringName &p_method, Array p_args) {
+ Vector<Variant> args;
+ Vector<const Variant *> argsp;
+ args.resize(p_args.size());
+ argsp.resize(p_args.size());
+ Variant *ptr = args.ptrw();
+ const Variant **pptr = argsp.ptrw();
+ for (int i = 0; i < p_args.size(); i++) {
+ ptr[i] = p_args[i];
+ pptr[i] = &ptr[i];
+ }
+ return rpcp(p_object, p_peer, p_method, argsp.size() ? argsp.ptrw() : nullptr, argsp.size());
+}
+
+void MultiplayerAPI::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("has_multiplayer_peer"), &MultiplayerAPI::has_multiplayer_peer);
+ ClassDB::bind_method(D_METHOD("get_multiplayer_peer"), &MultiplayerAPI::get_multiplayer_peer);
+ ClassDB::bind_method(D_METHOD("set_multiplayer_peer", "peer"), &MultiplayerAPI::set_multiplayer_peer);
+ ClassDB::bind_method(D_METHOD("get_unique_id"), &MultiplayerAPI::get_unique_id);
+ ClassDB::bind_method(D_METHOD("is_server"), &MultiplayerAPI::is_server);
+ ClassDB::bind_method(D_METHOD("get_remote_sender_id"), &MultiplayerAPI::get_remote_sender_id);
+ ClassDB::bind_method(D_METHOD("poll"), &MultiplayerAPI::poll);
+ ClassDB::bind_method(D_METHOD("rpc", "peer", "object", "method", "arguments"), &MultiplayerAPI::_rpc_bind, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("object_configuration_add", "object", "configuration"), &MultiplayerAPI::object_configuration_add);
+ ClassDB::bind_method(D_METHOD("object_configuration_remove", "object", "configuration"), &MultiplayerAPI::object_configuration_remove);
+
+ ClassDB::bind_method(D_METHOD("get_peers"), &MultiplayerAPI::get_peer_ids);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer_peer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerPeer", PROPERTY_USAGE_NONE), "set_multiplayer_peer", "get_multiplayer_peer");
+
+ ClassDB::bind_static_method("MultiplayerAPI", D_METHOD("set_default_interface", "interface_name"), &MultiplayerAPI::set_default_interface);
+ ClassDB::bind_static_method("MultiplayerAPI", D_METHOD("get_default_interface"), &MultiplayerAPI::get_default_interface);
+ ClassDB::bind_static_method("MultiplayerAPI", D_METHOD("create_default_interface"), &MultiplayerAPI::create_default_interface);
+
+ ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id")));
+ ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id")));
+ ADD_SIGNAL(MethodInfo("connected_to_server"));
+ ADD_SIGNAL(MethodInfo("connection_failed"));
+ ADD_SIGNAL(MethodInfo("server_disconnected"));
+
+ BIND_ENUM_CONSTANT(RPC_MODE_DISABLED);
+ BIND_ENUM_CONSTANT(RPC_MODE_ANY_PEER);
+ BIND_ENUM_CONSTANT(RPC_MODE_AUTHORITY);
+}
+
+/// MultiplayerAPIExtension
+
+Error MultiplayerAPIExtension::poll() {
+ int err;
+ if (GDVIRTUAL_CALL(_poll, err)) {
+ return (Error)err;
+ }
+ return OK;
+}
+
+void MultiplayerAPIExtension::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) {
+ GDVIRTUAL_CALL(_set_multiplayer_peer, p_peer);
+}
+
+Ref<MultiplayerPeer> MultiplayerAPIExtension::get_multiplayer_peer() {
+ Ref<MultiplayerPeer> peer;
+ if (GDVIRTUAL_CALL(_get_multiplayer_peer, peer)) {
+ return peer;
+ }
+ return nullptr;
+}
+
+int MultiplayerAPIExtension::get_unique_id() {
+ int id;
+ if (GDVIRTUAL_CALL(_get_unique_id, id)) {
+ return id;
+ }
+ return 1;
+}
+
+Vector<int> MultiplayerAPIExtension::get_peer_ids() {
+ Vector<int> ids;
+ if (GDVIRTUAL_CALL(_get_peer_ids, ids)) {
+ return ids;
+ }
+ return Vector<int>();
+}
+
+Error MultiplayerAPIExtension::rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+ if (!GDVIRTUAL_IS_OVERRIDDEN(_rpc)) {
+ return ERR_UNAVAILABLE;
+ }
+ Array args;
+ for (int i = 0; i < p_argcount; i++) {
+ args.push_back(*p_arg[i]);
+ }
+ int ret;
+ if (GDVIRTUAL_CALL(_rpc, p_peer_id, p_obj, p_method, args, ret)) {
+ return (Error)ret;
+ }
+ return FAILED;
+}
+
+int MultiplayerAPIExtension::get_remote_sender_id() {
+ int id;
+ if (GDVIRTUAL_CALL(_get_remote_sender_id, id)) {
+ return id;
+ }
+ return 0;
+}
+
+Error MultiplayerAPIExtension::object_configuration_add(Object *p_object, Variant p_config) {
+ int err;
+ if (GDVIRTUAL_CALL(_object_configuration_add, p_object, p_config, err)) {
+ return (Error)err;
+ }
+ return ERR_UNAVAILABLE;
+}
+
+Error MultiplayerAPIExtension::object_configuration_remove(Object *p_object, Variant p_config) {
+ int err;
+ if (GDVIRTUAL_CALL(_object_configuration_remove, p_object, p_config, err)) {
+ return (Error)err;
+ }
+ return ERR_UNAVAILABLE;
+}
+
+void MultiplayerAPIExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_poll);
+ GDVIRTUAL_BIND(_set_multiplayer_peer, "multiplayer_peer");
+ GDVIRTUAL_BIND(_get_multiplayer_peer);
+ GDVIRTUAL_BIND(_get_unique_id);
+ GDVIRTUAL_BIND(_get_peer_ids);
+ GDVIRTUAL_BIND(_rpc, "peer", "object", "method", "args");
+ GDVIRTUAL_BIND(_get_remote_sender_id);
+ GDVIRTUAL_BIND(_object_configuration_add, "object", "configuration");
+ GDVIRTUAL_BIND(_object_configuration_remove, "object", "configuration");
+}
diff --git a/scene/main/multiplayer_api.h b/scene/main/multiplayer_api.h
new file mode 100644
index 0000000000..c1d90d651e
--- /dev/null
+++ b/scene/main/multiplayer_api.h
@@ -0,0 +1,115 @@
+/*************************************************************************/
+/* multiplayer_api.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 MULTIPLAYER_API_H
+#define MULTIPLAYER_API_H
+
+#include "core/object/ref_counted.h"
+#include "scene/main/multiplayer_peer.h"
+
+class MultiplayerAPI : public RefCounted {
+ GDCLASS(MultiplayerAPI, RefCounted);
+
+private:
+ static StringName default_interface;
+
+protected:
+ static void _bind_methods();
+ Error _rpc_bind(int p_peer, Object *p_obj, const StringName &p_method, Array args = Array());
+
+public:
+ enum RPCMode {
+ RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
+ RPC_MODE_ANY_PEER, // Any peer can call this RPC
+ RPC_MODE_AUTHORITY, // Only the node's multiplayer authority (server by default) can call this RPC
+ };
+
+ static Ref<MultiplayerAPI> create_default_interface();
+ static void set_default_interface(const StringName &p_interface);
+ static StringName get_default_interface();
+
+ static Error encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len, bool p_allow_object_decoding);
+ static Error decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding);
+ static Error encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw = nullptr, bool p_allow_object_decoding = false);
+ static Error decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw = false, bool p_allow_object_decoding = false);
+
+ virtual Error poll() = 0;
+ virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) = 0;
+ virtual Ref<MultiplayerPeer> get_multiplayer_peer() = 0;
+ virtual int get_unique_id() = 0;
+ virtual Vector<int> get_peer_ids() = 0;
+
+ virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) = 0;
+ virtual int get_remote_sender_id() = 0;
+
+ virtual Error object_configuration_add(Object *p_object, Variant p_config) = 0;
+ virtual Error object_configuration_remove(Object *p_object, Variant p_config) = 0;
+
+ bool has_multiplayer_peer() { return get_multiplayer_peer().is_valid(); }
+ bool is_server() { return get_unique_id() == MultiplayerPeer::TARGET_PEER_SERVER; }
+
+ MultiplayerAPI() {}
+ virtual ~MultiplayerAPI() {}
+};
+
+VARIANT_ENUM_CAST(MultiplayerAPI::RPCMode);
+
+class MultiplayerAPIExtension : public MultiplayerAPI {
+ GDCLASS(MultiplayerAPIExtension, MultiplayerAPI);
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual Error poll() override;
+ virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) override;
+ virtual Ref<MultiplayerPeer> get_multiplayer_peer() override;
+ virtual int get_unique_id() override;
+ virtual Vector<int> get_peer_ids() override;
+
+ virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override;
+ virtual int get_remote_sender_id() override;
+
+ virtual Error object_configuration_add(Object *p_object, Variant p_config) override;
+ virtual Error object_configuration_remove(Object *p_object, Variant p_config) override;
+
+ // Extensions
+ GDVIRTUAL0R(int, _poll);
+ GDVIRTUAL1(_set_multiplayer_peer, Ref<MultiplayerPeer>);
+ GDVIRTUAL0R(Ref<MultiplayerPeer>, _get_multiplayer_peer);
+ GDVIRTUAL0RC(int, _get_unique_id);
+ GDVIRTUAL0RC(PackedInt32Array, _get_peer_ids);
+ GDVIRTUAL4R(int, _rpc, int, Object *, StringName, Array);
+ GDVIRTUAL0RC(int, _get_remote_sender_id);
+ GDVIRTUAL2R(int, _object_configuration_add, Object *, Variant);
+ GDVIRTUAL2R(int, _object_configuration_remove, Object *, Variant);
+};
+
+#endif // MULTIPLAYER_API_H
diff --git a/core/multiplayer/multiplayer_peer.cpp b/scene/main/multiplayer_peer.cpp
index b262903ce8..aad5baccab 100644
--- a/core/multiplayer/multiplayer_peer.cpp
+++ b/scene/main/multiplayer_peer.cpp
@@ -62,11 +62,11 @@ int MultiplayerPeer::get_transfer_channel() const {
return transfer_channel;
}
-void MultiplayerPeer::set_transfer_mode(Multiplayer::TransferMode p_mode) {
+void MultiplayerPeer::set_transfer_mode(TransferMode p_mode) {
transfer_mode = p_mode;
}
-Multiplayer::TransferMode MultiplayerPeer::get_transfer_mode() const {
+MultiplayerPeer::TransferMode MultiplayerPeer::get_transfer_mode() const {
return transfer_mode;
}
@@ -107,6 +107,10 @@ void MultiplayerPeer::_bind_methods() {
BIND_CONSTANT(TARGET_PEER_BROADCAST);
BIND_CONSTANT(TARGET_PEER_SERVER);
+ BIND_ENUM_CONSTANT(TRANSFER_MODE_UNRELIABLE);
+ BIND_ENUM_CONSTANT(TRANSFER_MODE_UNRELIABLE_ORDERED);
+ BIND_ENUM_CONSTANT(TRANSFER_MODE_RELIABLE);
+
ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("server_disconnected"));
@@ -130,6 +134,20 @@ Error MultiplayerPeerExtension::get_packet(const uint8_t **r_buffer, int &r_buff
if (GDVIRTUAL_CALL(_get_packet, r_buffer, &r_buffer_size, err)) {
return (Error)err;
}
+ if (GDVIRTUAL_IS_OVERRIDDEN(_get_packet_script)) {
+ if (!GDVIRTUAL_CALL(_get_packet_script, script_buffer)) {
+ return FAILED;
+ }
+
+ if (script_buffer.size() == 0) {
+ return Error::ERR_UNAVAILABLE;
+ }
+
+ *r_buffer = script_buffer.ptr();
+ r_buffer_size = script_buffer.size();
+
+ return Error::OK;
+ }
WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_packet_native is unimplemented!");
return FAILED;
}
@@ -139,6 +157,16 @@ Error MultiplayerPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer
if (GDVIRTUAL_CALL(_put_packet, p_buffer, p_buffer_size, err)) {
return (Error)err;
}
+ if (GDVIRTUAL_IS_OVERRIDDEN(_put_packet_script)) {
+ PackedByteArray a;
+ a.resize(p_buffer_size);
+ memcpy(a.ptrw(), p_buffer, p_buffer_size);
+
+ if (!GDVIRTUAL_CALL(_put_packet_script, a, err)) {
+ return FAILED;
+ }
+ return (Error)err;
+ }
WARN_PRINT_ONCE("MultiplayerPeerExtension::_put_packet_native is unimplemented!");
return FAILED;
}
@@ -167,17 +195,17 @@ int MultiplayerPeerExtension::get_transfer_channel() const {
return MultiplayerPeer::get_transfer_channel();
}
-void MultiplayerPeerExtension::set_transfer_mode(Multiplayer::TransferMode p_mode) {
+void MultiplayerPeerExtension::set_transfer_mode(TransferMode p_mode) {
if (GDVIRTUAL_CALL(_set_transfer_mode, p_mode)) {
return;
}
MultiplayerPeer::set_transfer_mode(p_mode);
}
-Multiplayer::TransferMode MultiplayerPeerExtension::get_transfer_mode() const {
+MultiplayerPeer::TransferMode MultiplayerPeerExtension::get_transfer_mode() const {
int mode;
if (GDVIRTUAL_CALL(_get_transfer_mode, mode)) {
- return (Multiplayer::TransferMode)mode;
+ return (MultiplayerPeer::TransferMode)mode;
}
return MultiplayerPeer::get_transfer_mode();
}
@@ -254,6 +282,9 @@ void MultiplayerPeerExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_available_packet_count);
GDVIRTUAL_BIND(_get_max_packet_size);
+ GDVIRTUAL_BIND(_get_packet_script)
+ GDVIRTUAL_BIND(_put_packet_script, "p_buffer");
+
GDVIRTUAL_BIND(_set_transfer_channel, "p_channel");
GDVIRTUAL_BIND(_get_transfer_channel);
diff --git a/core/multiplayer/multiplayer_peer.h b/scene/main/multiplayer_peer.h
index dee2be7b4b..8a012d7520 100644
--- a/core/multiplayer/multiplayer_peer.h
+++ b/scene/main/multiplayer_peer.h
@@ -28,11 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NETWORKED_MULTIPLAYER_PEER_H
-#define NETWORKED_MULTIPLAYER_PEER_H
+#ifndef MULTIPLAYER_PEER_H
+#define MULTIPLAYER_PEER_H
#include "core/io/packet_peer.h"
-#include "core/multiplayer/multiplayer.h"
#include "core/object/gdvirtual.gen.inc"
#include "core/object/script_language.h"
@@ -41,12 +40,19 @@
class MultiplayerPeer : public PacketPeer {
GDCLASS(MultiplayerPeer, PacketPeer);
+public:
+ enum TransferMode {
+ TRANSFER_MODE_UNRELIABLE,
+ TRANSFER_MODE_UNRELIABLE_ORDERED,
+ TRANSFER_MODE_RELIABLE
+ };
+
protected:
static void _bind_methods();
private:
int transfer_channel = 0;
- Multiplayer::TransferMode transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
+ TransferMode transfer_mode = TRANSFER_MODE_RELIABLE;
bool refuse_connections = false;
public:
@@ -63,8 +69,8 @@ public:
virtual void set_transfer_channel(int p_channel);
virtual int get_transfer_channel() const;
- virtual void set_transfer_mode(Multiplayer::TransferMode p_mode);
- virtual Multiplayer::TransferMode get_transfer_mode() const;
+ virtual void set_transfer_mode(TransferMode p_mode);
+ virtual TransferMode get_transfer_mode() const;
virtual void set_refuse_new_connections(bool p_enable);
virtual bool is_refusing_new_connections() const;
@@ -86,6 +92,7 @@ public:
};
VARIANT_ENUM_CAST(MultiplayerPeer::ConnectionStatus);
+VARIANT_ENUM_CAST(MultiplayerPeer::TransferMode);
class MultiplayerPeerExtension : public MultiplayerPeer {
GDCLASS(MultiplayerPeerExtension, MultiplayerPeer);
@@ -93,6 +100,8 @@ class MultiplayerPeerExtension : public MultiplayerPeer {
protected:
static void _bind_methods();
+ PackedByteArray script_buffer;
+
public:
/* PacketPeer */
virtual int get_available_packet_count() const override;
@@ -103,8 +112,8 @@ public:
/* MultiplayerPeer */
virtual void set_transfer_channel(int p_channel) override;
virtual int get_transfer_channel() const override;
- virtual void set_transfer_mode(Multiplayer::TransferMode p_mode) override;
- virtual Multiplayer::TransferMode get_transfer_mode() const override;
+ virtual void set_transfer_mode(TransferMode p_mode) override;
+ virtual TransferMode get_transfer_mode() const override;
virtual void set_target_peer(int p_peer_id) override;
virtual int get_packet_peer() const override;
@@ -126,6 +135,10 @@ public:
GDVIRTUAL2R(int, _put_packet, GDNativeConstPtr<const uint8_t>, int);
GDVIRTUAL0RC(int, _get_max_packet_size);
+ /* PacketPeer GDScript */
+ GDVIRTUAL0R(PackedByteArray, _get_packet_script);
+ GDVIRTUAL1R(int, _put_packet_script, PackedByteArray);
+
/* MultiplayerPeer GDExtension */
GDVIRTUAL1(_set_transfer_channel, int);
GDVIRTUAL0RC(int, _get_transfer_channel);
@@ -141,4 +154,4 @@ public:
GDVIRTUAL0RC(int, _get_connection_status);
};
-#endif // NETWORKED_MULTIPLAYER_PEER_H
+#endif // MULTIPLAYER_PEER_H
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 545ff68b72..ea9788de27 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -33,12 +33,12 @@
#include "core/config/project_settings.h"
#include "core/core_string_names.h"
#include "core/io/resource_loader.h"
-#include "core/multiplayer/multiplayer_api.h"
#include "core/object/message_queue.h"
#include "core/string/print_string.h"
#include "instance_placeholder.h"
#include "scene/animation/tween.h"
#include "scene/debugger/scene_debugger.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/resources/packed_scene.h"
#include "scene/scene_string_names.h"
#include "viewport.h"
@@ -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"));
}
}
@@ -582,35 +582,30 @@ bool Node::is_multiplayer_authority() const {
/***** RPC CONFIG ********/
-uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local, Multiplayer::TransferMode p_transfer_mode, int p_channel) {
- for (int i = 0; i < data.rpc_methods.size(); i++) {
- if (data.rpc_methods[i].name == p_method) {
- Multiplayer::RPCConfig &nd = data.rpc_methods.write[i];
- nd.rpc_mode = p_rpc_mode;
- nd.transfer_mode = p_transfer_mode;
- nd.call_local = p_call_local;
- nd.channel = p_channel;
- return i | (1 << 15);
- }
+void Node::rpc_config(const StringName &p_method, const Variant &p_config) {
+ if (data.rpc_config.get_type() != Variant::DICTIONARY) {
+ data.rpc_config = Dictionary();
+ }
+ Dictionary node_config = data.rpc_config;
+ if (p_config.get_type() == Variant::NIL) {
+ node_config.erase(p_method);
+ } else {
+ ERR_FAIL_COND(p_config.get_type() != Variant::DICTIONARY);
+ node_config[p_method] = p_config;
}
- // New method
- Multiplayer::RPCConfig nd;
- nd.name = p_method;
- nd.rpc_mode = p_rpc_mode;
- nd.transfer_mode = p_transfer_mode;
- nd.channel = p_channel;
- nd.call_local = p_call_local;
- data.rpc_methods.push_back(nd);
- return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15);
+}
+
+const Variant Node::get_node_rpc_config() const {
+ return data.rpc_config;
}
/***** RPC FUNCTIONS ********/
-void Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Error Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
- return;
+ return ERR_INVALID_PARAMETER;
}
Variant::Type type = p_args[0]->get_type();
@@ -618,28 +613,28 @@ void Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING_NAME;
- return;
+ return ERR_INVALID_PARAMETER;
}
StringName method = (*p_args[0]).operator StringName();
- rpcp(0, method, &p_args[1], p_argcount - 1);
-
+ Error err = rpcp(0, method, &p_args[1], p_argcount - 1);
r_error.error = Callable::CallError::CALL_OK;
+ return err;
}
-void Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Error Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 2) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 2;
- return;
+ return ERR_INVALID_PARAMETER;
}
if (p_args[0]->get_type() != Variant::INT) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::INT;
- return;
+ return ERR_INVALID_PARAMETER;
}
Variant::Type type = p_args[1]->get_type();
@@ -647,20 +642,20 @@ void Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallEr
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::STRING_NAME;
- return;
+ return ERR_INVALID_PARAMETER;
}
int peer_id = *p_args[0];
StringName method = (*p_args[1]).operator StringName();
- rpcp(peer_id, method, &p_args[2], p_argcount - 2);
-
+ Error err = rpcp(peer_id, method, &p_args[2], p_argcount - 2);
r_error.error = Callable::CallError::CALL_OK;
+ return err;
}
-void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
- ERR_FAIL_COND(!is_inside_tree());
- get_multiplayer()->rpcp(this, p_peer_id, p_method, p_arg, p_argcount);
+Error Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+ ERR_FAIL_COND_V(!is_inside_tree(), ERR_UNCONFIGURED);
+ return get_multiplayer()->rpcp(this, p_peer_id, p_method, p_arg, p_argcount);
}
Ref<MultiplayerAPI> Node::get_multiplayer() const {
@@ -670,10 +665,6 @@ Ref<MultiplayerAPI> Node::get_multiplayer() const {
return get_tree()->get_multiplayer(get_path());
}
-Vector<Multiplayer::RPCConfig> Node::get_node_rpc_methods() const {
- return data.rpc_methods;
-}
-
//////////// end of rpc
bool Node::can_process_notification(int p_what) const {
@@ -770,9 +761,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 +779,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 +798,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"));
}
}
@@ -2404,7 +2395,7 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
if (copy && copytarget) {
const Callable copy_callable = Callable(copytarget, E.callable.get_method());
if (!copy->is_connected(E.signal.get_name(), copy_callable)) {
- copy->connect(E.signal.get_name(), copy_callable, E.binds, E.flags);
+ copy->connect(E.signal.get_name(), copy_callable, E.flags);
}
}
}
@@ -2490,7 +2481,7 @@ void Node::_replace_connections_target(Node *p_new_target) {
c.signal.get_object()->disconnect(c.signal.get_name(), Callable(this, c.callable.get_method()));
bool valid = p_new_target->has_method(c.callable.get_method()) || Ref<Script>(p_new_target->get_script()).is_null() || Ref<Script>(p_new_target->get_script())->has_method(c.callable.get_method());
ERR_CONTINUE_MSG(!valid, vformat("Attempt to connect signal '%s.%s' to nonexistent method '%s.%s'.", c.signal.get_object()->get_class(), c.signal.get_name(), c.callable.get_object()->get_class(), c.callable.get_method()));
- c.signal.get_object()->connect(c.signal.get_name(), Callable(p_new_target, c.callable.get_method()), c.binds, c.flags);
+ c.signal.get_object()->connect(c.signal.get_name(), Callable(p_new_target, c.callable.get_method()), c.flags);
}
}
}
@@ -2888,7 +2879,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_multiplayer_authority"), &Node::is_multiplayer_authority);
ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer);
- ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "call_local", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(false), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("rpc_config", "method", "config"), &Node::rpc_config);
ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description);
ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
diff --git a/scene/main/node.h b/scene/main/node.h
index 3c4727f11c..ccd1d561d2 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -127,7 +127,7 @@ private:
Node *process_owner = nullptr;
int multiplayer_authority = 1; // Server by default.
- Vector<Multiplayer::RPCConfig> rpc_methods;
+ Variant rpc_config;
// Variables used to properly sort the node when processing, ignored otherwise.
// TODO: Should move all the stuff below to bits.
@@ -183,8 +183,8 @@ private:
TypedArray<Node> _get_children(bool p_include_internal = true) const;
Array _get_groups() const;
- void _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- void _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ Error _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ Error _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
_FORCE_INLINE_ bool _is_internal_front() const { return data.parent && data.pos < data.parent->data.internal_children_front; }
_FORCE_INLINE_ bool _is_internal_back() const { return data.parent && data.pos >= data.parent->data.children.size() - data.parent->data.internal_children_back; }
@@ -491,30 +491,16 @@ public:
int get_multiplayer_authority() const;
bool is_multiplayer_authority() const;
- uint16_t rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local = false, Multiplayer::TransferMode p_transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0); // config a local method for RPC
- Vector<Multiplayer::RPCConfig> get_node_rpc_methods() const;
+ void rpc_config(const StringName &p_method, const Variant &p_config); // config a local method for RPC
+ const Variant get_node_rpc_config() const;
template <typename... VarArgs>
- void rpc(const StringName &p_method, VarArgs... p_args) {
- Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
- const Variant *argptrs[sizeof...(p_args) + 1];
- for (uint32_t i = 0; i < sizeof...(p_args); i++) {
- argptrs[i] = &args[i];
- }
- rpcp(0, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
- }
+ Error rpc(const StringName &p_method, VarArgs... p_args);
template <typename... VarArgs>
- void rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args) {
- Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
- const Variant *argptrs[sizeof...(p_args) + 1];
- for (uint32_t i = 0; i < sizeof...(p_args); i++) {
- argptrs[i] = &args[i];
- }
- rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
- }
+ Error rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args);
- void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
+ Error rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
Ref<MultiplayerAPI> get_multiplayer() const;
@@ -526,4 +512,22 @@ VARIANT_ENUM_CAST(Node::DuplicateFlags);
typedef HashSet<Node *, Node::Comparator> NodeSet;
-#endif
+// Template definitions must be in the header so they are always fully initialized before their usage.
+// See this StackOverflow question for more information: https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file
+
+template <typename... VarArgs>
+Error Node::rpc(const StringName &p_method, VarArgs... p_args) {
+ return rpc_id(0, p_method, p_args...);
+}
+
+template <typename... VarArgs>
+Error Node::rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ return rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+}
+
+#endif // NODE_H
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 18f69ecc82..644fb3e9cc 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -34,9 +34,9 @@
#include "core/debugger/engine_debugger.h"
#include "core/input/input.h"
#include "core/io/dir_access.h"
+#include "core/io/image_loader.h"
#include "core/io/marshalls.h"
#include "core/io/resource_loader.h"
-#include "core/multiplayer/multiplayer_api.h"
#include "core/object/message_queue.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
@@ -44,6 +44,7 @@
#include "node.h"
#include "scene/animation/tween.h"
#include "scene/debugger/scene_debugger.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/viewport.h"
#include "scene/resources/font.h"
#include "scene/resources/material.h"
@@ -412,9 +413,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 +450,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
@@ -1212,19 +1213,17 @@ void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePat
if (p_root_path.is_empty()) {
ERR_FAIL_COND(!p_multiplayer.is_valid());
if (multiplayer.is_valid()) {
- multiplayer->set_root_path(NodePath());
+ multiplayer->object_configuration_remove(nullptr, NodePath("/" + root->get_name()));
}
multiplayer = p_multiplayer;
- multiplayer->set_root_path("/" + root->get_name());
+ multiplayer->object_configuration_add(nullptr, NodePath("/" + root->get_name()));
} else {
+ if (custom_multiplayers.has(p_root_path)) {
+ custom_multiplayers[p_root_path]->object_configuration_remove(nullptr, p_root_path);
+ }
if (p_multiplayer.is_valid()) {
custom_multiplayers[p_root_path] = p_multiplayer;
- p_multiplayer->set_root_path(p_root_path);
- } else {
- if (custom_multiplayers.has(p_root_path)) {
- custom_multiplayers[p_root_path]->set_root_path(NodePath());
- custom_multiplayers.erase(p_root_path);
- }
+ p_multiplayer->object_configuration_add(nullptr, p_root_path);
}
}
}
@@ -1414,7 +1413,7 @@ SceneTree::SceneTree() {
#endif // _3D_DISABLED
// Initialize network state.
- set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI)));
+ set_multiplayer(MultiplayerAPI::create_default_interface());
root->set_as_audio_listener_2d(true);
current_scene = nullptr;
@@ -1446,25 +1445,48 @@ SceneTree::SceneTree() {
bool snap_2d_vertices = GLOBAL_DEF("rendering/2d/snap/snap_2d_vertices_to_pixel", false);
root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
- int shadowmap_size = GLOBAL_DEF("rendering/shadows/shadow_atlas/size", 4096);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384"));
- GLOBAL_DEF("rendering/shadows/shadow_atlas/size.mobile", 2048);
- bool shadowmap_16_bits = GLOBAL_DEF("rendering/shadows/shadow_atlas/16_bits", true);
- int atlas_q0 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_0_subdiv", 2);
- int atlas_q1 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_1_subdiv", 2);
- int atlas_q2 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_2_subdiv", 3);
- int atlas_q3 = GLOBAL_DEF("rendering/shadows/shadow_atlas/quadrant_3_subdiv", 4);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadow_atlas/quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/shadow_atlas/quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
-
- root->set_shadow_atlas_size(shadowmap_size);
- root->set_shadow_atlas_16_bits(shadowmap_16_bits);
- root->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0));
- root->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1));
- root->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
- root->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
+ // We setup VRS for the main viewport here, in the editor this will have little effect.
+ const int vrs_mode = GLOBAL_DEF("rendering/vrs/mode", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/vrs/mode", PropertyInfo(Variant::INT, "rendering/vrs/mode", PROPERTY_HINT_ENUM, String::utf8("Disabled,Texture,XR")));
+ root->set_vrs_mode(Viewport::VRSMode(vrs_mode));
+ const String vrs_texture_path = String(GLOBAL_DEF("rendering/vrs/texture", String())).strip_edges();
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/vrs/texture",
+ PropertyInfo(Variant::STRING,
+ "rendering/vrs/texture",
+ PROPERTY_HINT_FILE, "*.png"));
+ if (vrs_mode == 1 && !vrs_texture_path.is_empty()) {
+ Ref<Image> vrs_image;
+ vrs_image.instantiate();
+ Error load_err = ImageLoader::load_image(vrs_texture_path, vrs_image);
+ if (load_err) {
+ ERR_PRINT("Non-existing or invalid VRS texture at '" + vrs_texture_path + "'.");
+ } else {
+ Ref<ImageTexture> vrs_texture;
+ vrs_texture.instantiate();
+ vrs_texture->create_from_image(vrs_image);
+ root->set_vrs_texture(vrs_texture);
+ }
+ }
+
+ int shadowmap_size = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size", 4096);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_size", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"));
+ GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size.mobile", 2048);
+ bool shadowmap_16_bits = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_16_bits", true);
+ int atlas_q0 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", 2);
+ int atlas_q1 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", 2);
+ int atlas_q2 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", 3);
+ int atlas_q3 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", 4);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+
+ root->set_positional_shadow_atlas_size(shadowmap_size);
+ root->set_positional_shadow_atlas_16_bits(shadowmap_16_bits);
+ root->set_positional_shadow_atlas_quadrant_subdiv(0, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q0));
+ root->set_positional_shadow_atlas_quadrant_subdiv(1, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q1));
+ root->set_positional_shadow_atlas_quadrant_subdiv(2, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q2));
+ root->set_positional_shadow_atlas_quadrant_subdiv(3, Viewport::PositionalShadowAtlasQuadrantSubdiv(atlas_q3));
Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF("rendering/2d/sdf/oversize", 1)));
root->set_sdf_oversize(sdf_oversize);
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index a34aa8e2cd..a512feacc8 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -90,8 +90,8 @@ private:
Window *root = nullptr;
uint64_t tree_version = 1;
- double physics_process_time = 1.0;
- double process_time = 1.0;
+ double physics_process_time = 0.0;
+ double process_time = 0.0;
bool accept_quit = true;
bool quit_on_go_back = true;
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index 0049359cad..a621aea9c8 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -64,9 +64,9 @@ bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_valu
if (active) {
if (o->override.get_type() == Variant::OBJECT) {
RID tex_rid = p_value;
- RS::get_singleton()->global_variable_set_override(*r, tex_rid);
+ RS::get_singleton()->global_shader_uniform_set_override(*r, tex_rid);
} else {
- RS::get_singleton()->global_variable_set_override(*r, p_value);
+ RS::get_singleton()->global_shader_uniform_set_override(*r, p_value);
}
}
o->in_use = p_value.get_type() != Variant::NIL;
@@ -93,13 +93,13 @@ bool ShaderGlobalsOverride::_get(const StringName &p_name, Variant &r_ret) const
void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const {
Vector<StringName> variables;
- variables = RS::get_singleton()->global_variable_get_list();
+ variables = RS::get_singleton()->global_shader_uniform_get_list();
for (int i = 0; i < variables.size(); i++) {
PropertyInfo pinfo;
pinfo.name = "params/" + variables[i];
pinfo.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- switch (RS::get_singleton()->global_variable_get_type(variables[i])) {
+ switch (RS::get_singleton()->global_shader_uniform_get_type(variables[i])) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
pinfo.type = Variant::BOOL;
} break;
@@ -155,7 +155,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const
pinfo.type = Variant::VECTOR3;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- pinfo.type = Variant::QUATERNION;
+ pinfo.type = Variant::VECTOR4;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
pinfo.type = Variant::RECT2;
@@ -169,15 +169,15 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const
case RS::GLOBAL_VAR_TYPE_MAT3: {
pinfo.type = Variant::BASIS;
} break;
+ case RS::GLOBAL_VAR_TYPE_MAT4: {
+ pinfo.type = Variant::PROJECTION;
+ } break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
pinfo.type = Variant::TRANSFORM2D;
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
pinfo.type = Variant::TRANSFORM3D;
} break;
- case RS::GLOBAL_VAR_TYPE_MAT4: {
- pinfo.type = Variant::PACKED_INT32_ARRAY;
- } break;
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
pinfo.type = Variant::OBJECT;
pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE;
@@ -234,9 +234,9 @@ void ShaderGlobalsOverride::_activate() {
if (o->in_use && o->override.get_type() != Variant::NIL) {
if (o->override.get_type() == Variant::OBJECT) {
RID tex_rid = o->override;
- RS::get_singleton()->global_variable_set_override(E.key, tex_rid);
+ RS::get_singleton()->global_shader_uniform_set_override(E.key, tex_rid);
} else {
- RS::get_singleton()->global_variable_set_override(E.key, o->override);
+ RS::get_singleton()->global_shader_uniform_set_override(E.key, o->override);
}
}
@@ -258,7 +258,7 @@ void ShaderGlobalsOverride::_notification(int p_what) {
for (const KeyValue<StringName, Override> &E : overrides) {
const Override *o = &E.value;
if (o->in_use) {
- RS::get_singleton()->global_variable_set_override(E.key, Variant());
+ RS::get_singleton()->global_shader_uniform_set_override(E.key, Variant());
}
}
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 1ad011f867..4dd4c8419c 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;
@@ -1037,44 +1037,44 @@ Ref<ViewportTexture> Viewport::get_texture() const {
return default_texture;
}
-void Viewport::set_shadow_atlas_size(int p_size) {
- shadow_atlas_size = p_size;
- RS::get_singleton()->viewport_set_shadow_atlas_size(viewport, p_size, shadow_atlas_16_bits);
+void Viewport::set_positional_shadow_atlas_size(int p_size) {
+ positional_shadow_atlas_size = p_size;
+ RS::get_singleton()->viewport_set_positional_shadow_atlas_size(viewport, p_size, positional_shadow_atlas_16_bits);
}
-int Viewport::get_shadow_atlas_size() const {
- return shadow_atlas_size;
+int Viewport::get_positional_shadow_atlas_size() const {
+ return positional_shadow_atlas_size;
}
-void Viewport::set_shadow_atlas_16_bits(bool p_16_bits) {
- if (shadow_atlas_16_bits == p_16_bits) {
+void Viewport::set_positional_shadow_atlas_16_bits(bool p_16_bits) {
+ if (positional_shadow_atlas_16_bits == p_16_bits) {
return;
}
- shadow_atlas_16_bits = p_16_bits;
- RS::get_singleton()->viewport_set_shadow_atlas_size(viewport, shadow_atlas_size, shadow_atlas_16_bits);
+ positional_shadow_atlas_16_bits = p_16_bits;
+ RS::get_singleton()->viewport_set_positional_shadow_atlas_size(viewport, positional_shadow_atlas_size, positional_shadow_atlas_16_bits);
}
-bool Viewport::get_shadow_atlas_16_bits() const {
- return shadow_atlas_16_bits;
+bool Viewport::get_positional_shadow_atlas_16_bits() const {
+ return positional_shadow_atlas_16_bits;
}
-void Viewport::set_shadow_atlas_quadrant_subdiv(int p_quadrant, ShadowAtlasQuadrantSubdiv p_subdiv) {
+void Viewport::set_positional_shadow_atlas_quadrant_subdiv(int p_quadrant, PositionalShadowAtlasQuadrantSubdiv p_subdiv) {
ERR_FAIL_INDEX(p_quadrant, 4);
ERR_FAIL_INDEX(p_subdiv, SHADOW_ATLAS_QUADRANT_SUBDIV_MAX);
- if (shadow_atlas_quadrant_subdiv[p_quadrant] == p_subdiv) {
+ if (positional_shadow_atlas_quadrant_subdiv[p_quadrant] == p_subdiv) {
return;
}
- shadow_atlas_quadrant_subdiv[p_quadrant] = p_subdiv;
+ positional_shadow_atlas_quadrant_subdiv[p_quadrant] = p_subdiv;
static const int subdiv[SHADOW_ATLAS_QUADRANT_SUBDIV_MAX] = { 0, 1, 4, 16, 64, 256, 1024 };
- RS::get_singleton()->viewport_set_shadow_atlas_quadrant_subdivision(viewport, p_quadrant, subdiv[p_subdiv]);
+ RS::get_singleton()->viewport_set_positional_shadow_atlas_quadrant_subdivision(viewport, p_quadrant, subdiv[p_subdiv]);
}
-Viewport::ShadowAtlasQuadrantSubdiv Viewport::get_shadow_atlas_quadrant_subdiv(int p_quadrant) const {
+Viewport::PositionalShadowAtlasQuadrantSubdiv Viewport::get_positional_shadow_atlas_quadrant_subdiv(int p_quadrant) const {
ERR_FAIL_INDEX_V(p_quadrant, 4, SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED);
- return shadow_atlas_quadrant_subdiv[p_quadrant];
+ return positional_shadow_atlas_quadrant_subdiv[p_quadrant];
}
Transform2D Viewport::_get_input_pre_xform() const {
@@ -1215,7 +1215,7 @@ void Viewport::_gui_show_tooltip() {
panel->connect("mouse_entered", callable_mp(this, &Viewport::_gui_cancel_tooltip));
}
- base_tooltip->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ base_tooltip->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
panel->set_transient(true);
panel->set_flag(Window::FLAG_NO_FOCUS, true);
@@ -1234,13 +1234,23 @@ void Viewport::_gui_show_tooltip() {
Rect2i vr = window->get_usable_parent_rect();
if (r.size.x + r.position.x > vr.size.x + vr.position.x) {
- r.position.x = vr.position.x + vr.size.x - r.size.x;
+ // Place it in the opposite direction. If it fails, just hug the border.
+ r.position.x = gui.tooltip_pos.x - r.size.x - tooltip_offset.x;
+
+ if (r.position.x < vr.position.x) {
+ r.position.x = vr.position.x + vr.size.x - r.size.x;
+ }
} else if (r.position.x < vr.position.x) {
r.position.x = vr.position.x;
}
if (r.size.y + r.position.y > vr.size.y + vr.position.y) {
- r.position.y = vr.position.y + vr.size.y - r.size.y;
+ // Same as above.
+ r.position.y = gui.tooltip_pos.y - r.size.y - tooltip_offset.y;
+
+ if (r.position.y < vr.position.y) {
+ r.position.y = vr.position.y + vr.size.y - r.size.y;
+ }
} else if (r.position.y < vr.position.y) {
r.position.y = vr.position.y;
}
@@ -3080,6 +3090,41 @@ Viewport::DefaultCanvasItemTextureRepeat Viewport::get_default_canvas_item_textu
return default_canvas_item_texture_repeat;
}
+void Viewport::set_vrs_mode(Viewport::VRSMode p_vrs_mode) {
+ // Note, set this even if not supported on this hardware, it will only be used if it is but we want to save the value as set by the user.
+ vrs_mode = p_vrs_mode;
+
+ switch (p_vrs_mode) {
+ case VRS_TEXTURE: {
+ RS::get_singleton()->viewport_set_vrs_mode(viewport, RS::VIEWPORT_VRS_TEXTURE);
+ } break;
+ case VRS_XR: {
+ RS::get_singleton()->viewport_set_vrs_mode(viewport, RS::VIEWPORT_VRS_XR);
+ } break;
+ default: {
+ RS::get_singleton()->viewport_set_vrs_mode(viewport, RS::VIEWPORT_VRS_DISABLED);
+ } break;
+ }
+
+ notify_property_list_changed();
+}
+
+Viewport::VRSMode Viewport::get_vrs_mode() const {
+ return vrs_mode;
+}
+
+void Viewport::set_vrs_texture(Ref<Texture2D> p_texture) {
+ vrs_texture = p_texture;
+
+ // TODO need to add something here in case the RID changes
+ RID tex = p_texture.is_valid() ? p_texture->get_rid() : RID();
+ RS::get_singleton()->viewport_set_vrs_texture(viewport, tex);
+}
+
+Ref<Texture2D> Viewport::get_vrs_texture() const {
+ return vrs_texture;
+}
+
DisplayServer::WindowID Viewport::get_window_id() const {
return DisplayServer::MAIN_WINDOW_ID;
}
@@ -3586,17 +3631,17 @@ float Viewport::get_fsr_sharpness() const {
return fsr_sharpness;
}
-void Viewport::set_fsr_mipmap_bias(float p_fsr_mipmap_bias) {
- if (fsr_mipmap_bias == p_fsr_mipmap_bias) {
+void Viewport::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
+ if (texture_mipmap_bias == p_texture_mipmap_bias) {
return;
}
- fsr_mipmap_bias = p_fsr_mipmap_bias;
- RS::get_singleton()->viewport_set_fsr_mipmap_bias(viewport, p_fsr_mipmap_bias);
+ texture_mipmap_bias = p_texture_mipmap_bias;
+ RS::get_singleton()->viewport_set_texture_mipmap_bias(viewport, p_texture_mipmap_bias);
}
-float Viewport::get_fsr_mipmap_bias() const {
- return fsr_mipmap_bias;
+float Viewport::get_texture_mipmap_bias() const {
+ return texture_mipmap_bias;
}
#endif // _3D_DISABLED
@@ -3667,11 +3712,11 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_remove_focus_for_window"), &Viewport::_gui_remove_focus_for_window);
ClassDB::bind_method(D_METHOD("_post_gui_grab_click_focus"), &Viewport::_post_gui_grab_click_focus);
- ClassDB::bind_method(D_METHOD("set_shadow_atlas_size", "size"), &Viewport::set_shadow_atlas_size);
- ClassDB::bind_method(D_METHOD("get_shadow_atlas_size"), &Viewport::get_shadow_atlas_size);
+ ClassDB::bind_method(D_METHOD("set_positional_shadow_atlas_size", "size"), &Viewport::set_positional_shadow_atlas_size);
+ ClassDB::bind_method(D_METHOD("get_positional_shadow_atlas_size"), &Viewport::get_positional_shadow_atlas_size);
- ClassDB::bind_method(D_METHOD("set_shadow_atlas_16_bits", "enable"), &Viewport::set_shadow_atlas_16_bits);
- ClassDB::bind_method(D_METHOD("get_shadow_atlas_16_bits"), &Viewport::get_shadow_atlas_16_bits);
+ ClassDB::bind_method(D_METHOD("set_positional_shadow_atlas_16_bits", "enable"), &Viewport::set_positional_shadow_atlas_16_bits);
+ ClassDB::bind_method(D_METHOD("get_positional_shadow_atlas_16_bits"), &Viewport::get_positional_shadow_atlas_16_bits);
ClassDB::bind_method(D_METHOD("set_snap_controls_to_pixels", "enabled"), &Viewport::set_snap_controls_to_pixels);
ClassDB::bind_method(D_METHOD("is_snap_controls_to_pixels_enabled"), &Viewport::is_snap_controls_to_pixels_enabled);
@@ -3682,8 +3727,8 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_snap_2d_vertices_to_pixel", "enabled"), &Viewport::set_snap_2d_vertices_to_pixel);
ClassDB::bind_method(D_METHOD("is_snap_2d_vertices_to_pixel_enabled"), &Viewport::is_snap_2d_vertices_to_pixel_enabled);
- ClassDB::bind_method(D_METHOD("set_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv);
- ClassDB::bind_method(D_METHOD("get_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv);
+ ClassDB::bind_method(D_METHOD("set_positional_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_positional_shadow_atlas_quadrant_subdiv);
+ ClassDB::bind_method(D_METHOD("get_positional_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_positional_shadow_atlas_quadrant_subdiv);
ClassDB::bind_method(D_METHOD("set_input_as_handled"), &Viewport::set_input_as_handled);
ClassDB::bind_method(D_METHOD("is_input_handled"), &Viewport::is_input_handled);
@@ -3738,8 +3783,14 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fsr_sharpness", "fsr_sharpness"), &Viewport::set_fsr_sharpness);
ClassDB::bind_method(D_METHOD("get_fsr_sharpness"), &Viewport::get_fsr_sharpness);
- ClassDB::bind_method(D_METHOD("set_fsr_mipmap_bias", "fsr_mipmap_bias"), &Viewport::set_fsr_mipmap_bias);
- ClassDB::bind_method(D_METHOD("get_fsr_mipmap_bias"), &Viewport::get_fsr_mipmap_bias);
+ ClassDB::bind_method(D_METHOD("set_texture_mipmap_bias", "texture_mipmap_bias"), &Viewport::set_texture_mipmap_bias);
+ ClassDB::bind_method(D_METHOD("get_texture_mipmap_bias"), &Viewport::get_texture_mipmap_bias);
+
+ ClassDB::bind_method(D_METHOD("set_vrs_mode", "mode"), &Viewport::set_vrs_mode);
+ ClassDB::bind_method(D_METHOD("get_vrs_mode"), &Viewport::get_vrs_mode);
+
+ ClassDB::bind_method(D_METHOD("set_vrs_texture", "texture"), &Viewport::set_vrs_texture);
+ ClassDB::bind_method(D_METHOD("get_vrs_texture"), &Viewport::get_vrs_texture);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
@@ -3763,9 +3814,12 @@ void Viewport::_bind_methods() {
ADD_GROUP("Scaling 3D", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scaling_3d_mode", PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR 1.0 (Fast)"), "set_scaling_3d_mode", "get_scaling_3d_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scaling_3d_scale", PROPERTY_HINT_RANGE, "0.25,2.0,0.01"), "set_scaling_3d_scale", "get_scaling_3d_scale");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.1"), "set_fsr_mipmap_bias", "get_fsr_mipmap_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texture_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.001"), "set_texture_mipmap_bias", "get_texture_mipmap_bias");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1"), "set_fsr_sharpness", "get_fsr_sharpness");
#endif
+ ADD_GROUP("Variable Rate Shading", "vrs_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "vrs_mode", PROPERTY_HINT_ENUM, "Disabled,Texture,Depth buffer,XR"), "set_vrs_mode", "get_vrs_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "vrs_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_vrs_texture", "get_vrs_texture");
ADD_GROUP("Canvas Items", "canvas_item_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat");
@@ -3783,13 +3837,13 @@ void Viewport::_bind_methods() {
ADD_GROUP("SDF", "sdf_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), "set_sdf_oversize", "get_sdf_oversize");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), "set_sdf_scale", "get_sdf_scale");
- ADD_GROUP("Shadow Atlas", "shadow_atlas_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_atlas_16_bits"), "set_shadow_atlas_16_bits", "get_shadow_atlas_16_bits");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_1", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_2", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_3", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 3);
+ ADD_GROUP("Positional Shadow Atlas", "positional_shadow_atlas_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "positional_shadow_atlas_size"), "set_positional_shadow_atlas_size", "get_positional_shadow_atlas_size");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "positional_shadow_atlas_16_bits"), "set_positional_shadow_atlas_16_bits", "get_positional_shadow_atlas_16_bits");
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_1", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_2", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_3", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 3);
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_canvas_transform", "get_canvas_transform");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_canvas_transform", "get_global_canvas_transform");
@@ -3876,6 +3930,17 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(SDF_SCALE_50_PERCENT);
BIND_ENUM_CONSTANT(SDF_SCALE_25_PERCENT);
BIND_ENUM_CONSTANT(SDF_SCALE_MAX);
+
+ BIND_ENUM_CONSTANT(VRS_DISABLED);
+ BIND_ENUM_CONSTANT(VRS_TEXTURE);
+ BIND_ENUM_CONSTANT(VRS_XR);
+ BIND_ENUM_CONSTANT(VRS_MAX);
+}
+
+void Viewport::_validate_property(PropertyInfo &property) const {
+ if (vrs_mode != VRS_TEXTURE && (property.name == "vrs_texture")) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
}
Viewport::Viewport() {
@@ -3891,15 +3956,15 @@ Viewport::Viewport() {
canvas_layers.insert(nullptr); // This eases picking code (interpreted as the canvas of the Viewport).
- set_shadow_atlas_size(shadow_atlas_size);
+ set_positional_shadow_atlas_size(positional_shadow_atlas_size);
for (int i = 0; i < 4; i++) {
- shadow_atlas_quadrant_subdiv[i] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX;
+ positional_shadow_atlas_quadrant_subdiv[i] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX;
}
- set_shadow_atlas_quadrant_subdiv(0, SHADOW_ATLAS_QUADRANT_SUBDIV_4);
- set_shadow_atlas_quadrant_subdiv(1, SHADOW_ATLAS_QUADRANT_SUBDIV_4);
- set_shadow_atlas_quadrant_subdiv(2, SHADOW_ATLAS_QUADRANT_SUBDIV_16);
- set_shadow_atlas_quadrant_subdiv(3, SHADOW_ATLAS_QUADRANT_SUBDIV_64);
+ set_positional_shadow_atlas_quadrant_subdiv(0, SHADOW_ATLAS_QUADRANT_SUBDIV_4);
+ set_positional_shadow_atlas_quadrant_subdiv(1, SHADOW_ATLAS_QUADRANT_SUBDIV_4);
+ set_positional_shadow_atlas_quadrant_subdiv(2, SHADOW_ATLAS_QUADRANT_SUBDIV_16);
+ set_positional_shadow_atlas_quadrant_subdiv(3, SHADOW_ATLAS_QUADRANT_SUBDIV_64);
set_mesh_lod_threshold(mesh_lod_threshold);
@@ -3923,8 +3988,8 @@ Viewport::Viewport() {
float fsr_sharpness = GLOBAL_GET("rendering/scaling_3d/fsr_sharpness");
set_fsr_sharpness(fsr_sharpness);
- float fsr_mipmap_bias = GLOBAL_GET("rendering/scaling_3d/fsr_mipmap_bias");
- set_fsr_mipmap_bias(fsr_mipmap_bias);
+ float texture_mipmap_bias = GLOBAL_GET("rendering/textures/default_filters/texture_mipmap_bias");
+ set_texture_mipmap_bias(texture_mipmap_bias);
#endif // _3D_DISABLED
set_sdf_oversize(sdf_oversize); // Set to server.
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index a22a2acf49..4221baff06 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -95,7 +95,7 @@ public:
SCALING_3D_MODE_MAX
};
- enum ShadowAtlasQuadrantSubdiv {
+ enum PositionalShadowAtlasQuadrantSubdiv {
SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED,
SHADOW_ATLAS_QUADRANT_SUBDIV_1,
SHADOW_ATLAS_QUADRANT_SUBDIV_4,
@@ -197,6 +197,13 @@ public:
SUBWINDOW_CANVAS_LAYER = 1024
};
+ enum VRSMode {
+ VRS_DISABLED,
+ VRS_TEXTURE,
+ VRS_XR,
+ VRS_MAX
+ };
+
private:
friend class ViewportTexture;
@@ -286,9 +293,9 @@ private:
DebugDraw debug_draw = DEBUG_DRAW_DISABLED;
- int shadow_atlas_size = 2048;
- bool shadow_atlas_16_bits = true;
- ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4];
+ int positional_shadow_atlas_size = 2048;
+ bool positional_shadow_atlas_16_bits = true;
+ PositionalShadowAtlasQuadrantSubdiv positional_shadow_atlas_quadrant_subdiv[4];
MSAA msaa = MSAA_DISABLED;
ScreenSpaceAA screen_space_aa = SCREEN_SPACE_AA_DISABLED;
@@ -297,7 +304,7 @@ private:
Scaling3DMode scaling_3d_mode = SCALING_3D_MODE_BILINEAR;
float scaling_3d_scale = 1.0;
float fsr_sharpness = 0.2f;
- float fsr_mipmap_bias = 0.0f;
+ float texture_mipmap_bias = 0.0f;
bool use_debanding = false;
float mesh_lod_threshold = 1.0;
bool use_occlusion_culling = false;
@@ -333,6 +340,10 @@ private:
RID canvas_item;
};
+ // VRS
+ VRSMode vrs_mode = VRS_DISABLED;
+ Ref<Texture2D> vrs_texture;
+
struct GUI {
// info used when this is a window
@@ -502,14 +513,14 @@ public:
Ref<ViewportTexture> get_texture() const;
- void set_shadow_atlas_size(int p_size);
- int get_shadow_atlas_size() const;
+ void set_positional_shadow_atlas_size(int p_size);
+ int get_positional_shadow_atlas_size() const;
- void set_shadow_atlas_16_bits(bool p_16_bits);
- bool get_shadow_atlas_16_bits() const;
+ void set_positional_shadow_atlas_16_bits(bool p_16_bits);
+ bool get_positional_shadow_atlas_16_bits() const;
- void set_shadow_atlas_quadrant_subdiv(int p_quadrant, ShadowAtlasQuadrantSubdiv p_subdiv);
- ShadowAtlasQuadrantSubdiv get_shadow_atlas_quadrant_subdiv(int p_quadrant) const;
+ void set_positional_shadow_atlas_quadrant_subdiv(int p_quadrant, PositionalShadowAtlasQuadrantSubdiv p_subdiv);
+ PositionalShadowAtlasQuadrantSubdiv get_positional_shadow_atlas_quadrant_subdiv(int p_quadrant) const;
void set_msaa(MSAA p_msaa);
MSAA get_msaa() const;
@@ -529,8 +540,8 @@ public:
void set_fsr_sharpness(float p_fsr_sharpness);
float get_fsr_sharpness() const;
- void set_fsr_mipmap_bias(float p_fsr_mipmap_bias);
- float get_fsr_mipmap_bias() const;
+ void set_texture_mipmap_bias(float p_texture_mipmap_bias);
+ float get_texture_mipmap_bias() const;
void set_use_debanding(bool p_use_debanding);
bool is_using_debanding() const;
@@ -604,6 +615,14 @@ public:
void set_default_canvas_item_texture_repeat(DefaultCanvasItemTextureRepeat p_repeat);
DefaultCanvasItemTextureRepeat get_default_canvas_item_texture_repeat() const;
+ // VRS
+
+ void set_vrs_mode(VRSMode p_vrs_mode);
+ VRSMode get_vrs_mode() const;
+
+ void set_vrs_texture(Ref<Texture2D> p_texture);
+ Ref<Texture2D> get_vrs_texture() const;
+
virtual DisplayServer::WindowID get_window_id() const = 0;
void set_embedding_subwindows(bool p_embed);
@@ -690,6 +709,7 @@ public:
bool is_using_xr();
#endif // _3D_DISABLED
+ virtual void _validate_property(PropertyInfo &property) const override;
Viewport();
~Viewport();
};
@@ -746,16 +766,17 @@ public:
};
VARIANT_ENUM_CAST(Viewport::Scaling3DMode);
VARIANT_ENUM_CAST(SubViewport::UpdateMode);
-VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
+VARIANT_ENUM_CAST(Viewport::PositionalShadowAtlasQuadrantSubdiv);
VARIANT_ENUM_CAST(Viewport::MSAA);
VARIANT_ENUM_CAST(Viewport::ScreenSpaceAA);
VARIANT_ENUM_CAST(Viewport::DebugDraw);
VARIANT_ENUM_CAST(Viewport::SDFScale);
VARIANT_ENUM_CAST(Viewport::SDFOversize);
+VARIANT_ENUM_CAST(Viewport::VRSMode);
VARIANT_ENUM_CAST(SubViewport::ClearMode);
VARIANT_ENUM_CAST(Viewport::RenderInfo);
VARIANT_ENUM_CAST(Viewport::RenderInfoType);
VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureFilter);
VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureRepeat);
-#endif
+#endif // VIEWPORT_H
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 73e8f537d9..bd72858ae6 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -1516,7 +1516,7 @@ void Window::_validate_property(PropertyInfo &property) const {
Transform2D Window::get_screen_transform() const {
Transform2D embedder_transform = Transform2D();
if (_get_embedder()) {
- embedder_transform.translate(get_position());
+ embedder_transform.translate_local(get_position());
embedder_transform = _get_embedder()->get_screen_transform() * embedder_transform;
}
return embedder_transform * Viewport::get_screen_transform();
diff --git a/scene/multiplayer/SCsub b/scene/multiplayer/SCsub
deleted file mode 100644
index fc61250247..0000000000
--- a/scene/multiplayer/SCsub
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-
-env.add_source_files(env.scene_sources, "*.cpp")
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index f70d57291f..a5842106fb 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -130,19 +130,16 @@
#include "scene/main/http_request.h"
#include "scene/main/instance_placeholder.h"
#include "scene/main/missing_node.h"
+#include "scene/main/multiplayer_api.h"
#include "scene/main/resource_preloader.h"
#include "scene/main/scene_tree.h"
#include "scene/main/timer.h"
#include "scene/main/viewport.h"
#include "scene/main/window.h"
-#include "scene/multiplayer/multiplayer_spawner.h"
-#include "scene/multiplayer/multiplayer_synchronizer.h"
-#include "scene/multiplayer/scene_cache_interface.h"
-#include "scene/multiplayer/scene_replication_interface.h"
-#include "scene/multiplayer/scene_rpc_interface.h"
#include "scene/resources/animation_library.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.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"
@@ -158,6 +155,7 @@
#include "scene/resources/gradient.h"
#include "scene/resources/height_map_shape_3d.h"
#include "scene/resources/immediate_mesh.h"
+#include "scene/resources/label_settings.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
#include "scene/resources/mesh_data_tool.h"
@@ -172,6 +170,7 @@
#include "scene/resources/segment_shape_2d.h"
#include "scene/resources/separation_ray_shape_2d.h"
#include "scene/resources/separation_ray_shape_3d.h"
+#include "scene/resources/shader_include.h"
#include "scene/resources/skeleton_modification_2d.h"
#include "scene/resources/skeleton_modification_2d_ccdik.h"
#include "scene/resources/skeleton_modification_2d_fabrik.h"
@@ -189,6 +188,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"
@@ -244,6 +244,7 @@
#include "scene/3d/ray_cast_3d.h"
#include "scene/3d/reflection_probe.h"
#include "scene/3d/remote_transform_3d.h"
+#include "scene/3d/shape_cast_3d.h"
#include "scene/3d/skeleton_3d.h"
#include "scene/3d/skeleton_ik_3d.h"
#include "scene/3d/soft_dynamic_body_3d.h"
@@ -270,6 +271,9 @@ static Ref<ResourceFormatLoaderCompressedTexture3D> resource_loader_texture_3d;
static Ref<ResourceFormatSaverShader> resource_saver_shader;
static Ref<ResourceFormatLoaderShader> resource_loader_shader;
+static Ref<ResourceFormatSaverShaderInclude> resource_saver_shader_include;
+static Ref<ResourceFormatLoaderShaderInclude> resource_loader_shader_include;
+
void register_scene_types() {
SceneStringNames::create();
@@ -298,6 +302,12 @@ void register_scene_types() {
resource_loader_shader.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_shader, true);
+ resource_saver_shader_include.instantiate();
+ ResourceSaver::add_resource_format_saver(resource_saver_shader_include, true);
+
+ resource_loader_shader_include.instantiate();
+ ResourceLoader::add_resource_format_loader(resource_loader_shader_include, true);
+
OS::get_singleton()->yield(); // may take time to init
GDREGISTER_CLASS(Object);
@@ -309,9 +319,13 @@ void register_scene_types() {
GDREGISTER_ABSTRACT_CLASS(Viewport);
GDREGISTER_CLASS(SubViewport);
GDREGISTER_CLASS(ViewportTexture);
+
+ GDREGISTER_ABSTRACT_CLASS(MultiplayerPeer);
+ GDREGISTER_CLASS(MultiplayerPeerExtension);
+ GDREGISTER_ABSTRACT_CLASS(MultiplayerAPI);
+ GDREGISTER_CLASS(MultiplayerAPIExtension);
+
GDREGISTER_CLASS(HTTPRequest);
- GDREGISTER_CLASS(MultiplayerSpawner);
- GDREGISTER_CLASS(MultiplayerSynchronizer);
GDREGISTER_CLASS(Timer);
GDREGISTER_CLASS(CanvasLayer);
GDREGISTER_CLASS(CanvasModulate);
@@ -437,6 +451,7 @@ void register_scene_types() {
GDREGISTER_CLASS(AnimationNodeStateMachine);
GDREGISTER_CLASS(AnimationNodeStateMachinePlayback);
+ GDREGISTER_CLASS(AnimationNodeSync);
GDREGISTER_CLASS(AnimationNodeStateMachineTransition);
GDREGISTER_CLASS(AnimationNodeOutput);
GDREGISTER_CLASS(AnimationNodeOneShot);
@@ -508,9 +523,7 @@ void register_scene_types() {
GDREGISTER_CLASS(GPUParticlesAttractorVectorField3D);
GDREGISTER_CLASS(CPUParticles3D);
GDREGISTER_CLASS(Position3D);
-
GDREGISTER_CLASS(RootMotionView);
- ClassDB::set_class_enabled("RootMotionView", false); // disabled by default, enabled by editor
OS::get_singleton()->yield(); // may take time to init
@@ -535,6 +548,7 @@ void register_scene_types() {
GDREGISTER_CLASS(CollisionShape3D);
GDREGISTER_CLASS(CollisionPolygon3D);
GDREGISTER_CLASS(RayCast3D);
+ GDREGISTER_CLASS(ShapeCast3D);
GDREGISTER_CLASS(MultiMeshInstance3D);
GDREGISTER_CLASS(Curve3D);
@@ -565,6 +579,7 @@ void register_scene_types() {
GDREGISTER_CLASS(Shader);
GDREGISTER_CLASS(VisualShader);
+ GDREGISTER_CLASS(ShaderInclude);
GDREGISTER_ABSTRACT_CLASS(VisualShaderNode);
GDREGISTER_CLASS(VisualShaderNodeCustom);
GDREGISTER_CLASS(VisualShaderNodeInput);
@@ -770,6 +785,7 @@ void register_scene_types() {
GDREGISTER_CLASS(QuadMesh);
GDREGISTER_CLASS(SphereMesh);
GDREGISTER_CLASS(TextMesh);
+ GDREGISTER_CLASS(TorusMesh);
GDREGISTER_CLASS(TubeTrailMesh);
GDREGISTER_CLASS(RibbonTrailMesh);
GDREGISTER_CLASS(PointMesh);
@@ -851,11 +867,15 @@ 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(SystemFont);
+
GDREGISTER_CLASS(Curve);
- GDREGISTER_CLASS(SceneReplicationConfig);
+ GDREGISTER_CLASS(LabelSettings);
GDREGISTER_CLASS(TextLine);
GDREGISTER_CLASS(TextParagraph);
@@ -871,6 +891,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);
@@ -879,7 +903,7 @@ void register_scene_types() {
GDREGISTER_CLASS(AudioStreamPlayer3D);
#endif
GDREGISTER_ABSTRACT_CLASS(VideoStream);
- GDREGISTER_CLASS(AudioStreamSample);
+ GDREGISTER_CLASS(AudioStreamWAV);
OS::get_singleton()->yield(); // may take time to init
@@ -915,9 +939,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");
@@ -1066,6 +1090,9 @@ void register_scene_types() {
ClassDB::add_compatibility_class("World", "World3D");
// Renamed during 4.0 alpha, added to ease transition between alphas.
+ ClassDB::add_compatibility_class("AudioStreamOGGVorbis", "AudioStreamOggVorbis");
+ ClassDB::add_compatibility_class("AudioStreamSample", "AudioStreamWAV");
+ ClassDB::add_compatibility_class("OGGPacketSequence", "OggPacketSequence");
ClassDB::add_compatibility_class("StreamCubemap", "CompressedCubemap");
ClassDB::add_compatibility_class("StreamCubemapArray", "CompressedCubemapArray");
ClassDB::add_compatibility_class("StreamTexture2D", "CompressedTexture2D");
@@ -1093,9 +1120,6 @@ void register_scene_types() {
}
SceneDebugger::initialize();
- SceneReplicationInterface::make_default();
- SceneRPCInterface::make_default();
- SceneCacheInterface::make_default();
}
void initialize_theme() {
@@ -1107,7 +1131,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));
@@ -1172,6 +1196,12 @@ void unregister_scene_types() {
ResourceLoader::remove_resource_format_loader(resource_loader_shader);
resource_loader_shader.unref();
+ ResourceSaver::remove_resource_format_saver(resource_saver_shader_include);
+ resource_saver_shader_include.unref();
+
+ ResourceLoader::remove_resource_format_loader(resource_loader_shader_include);
+ resource_loader_shader_include.unref();
+
// StandardMaterial3D is not initialised when 3D is disabled, so it shouldn't be cleaned up either
#ifndef _3D_DISABLED
BaseMaterial3D::finish_shaders();
diff --git a/scene/register_scene_types.h b/scene/register_scene_types.h
index f0a14387c1..dce8713976 100644
--- a/scene/register_scene_types.h
+++ b/scene/register_scene_types.h
@@ -36,4 +36,4 @@ void unregister_scene_types();
void initialize_theme();
-#endif
+#endif // REGISTER_SCENE_TYPES_H
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 7183accc66..69b30b72b0 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -1563,33 +1563,35 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
return -1;
}
-void Animation::track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition) {
- ERR_FAIL_INDEX(p_track, tracks.size());
+int Animation::track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition) {
+ ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
+ int ret = -1;
+
switch (t->type) {
case TYPE_POSITION_3D: {
- ERR_FAIL_COND((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I));
- int idx = position_track_insert_key(p_track, p_time, p_key);
- track_set_key_transition(p_track, idx, p_transition);
+ ERR_FAIL_COND_V((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I), -1);
+ ret = position_track_insert_key(p_track, p_time, p_key);
+ track_set_key_transition(p_track, ret, p_transition);
} break;
case TYPE_ROTATION_3D: {
- ERR_FAIL_COND((p_key.get_type() != Variant::QUATERNION) && (p_key.get_type() != Variant::BASIS));
- int idx = rotation_track_insert_key(p_track, p_time, p_key);
- track_set_key_transition(p_track, idx, p_transition);
+ ERR_FAIL_COND_V((p_key.get_type() != Variant::QUATERNION) && (p_key.get_type() != Variant::BASIS), -1);
+ ret = rotation_track_insert_key(p_track, p_time, p_key);
+ track_set_key_transition(p_track, ret, p_transition);
} break;
case TYPE_SCALE_3D: {
- ERR_FAIL_COND((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I));
- int idx = scale_track_insert_key(p_track, p_time, p_key);
- track_set_key_transition(p_track, idx, p_transition);
+ ERR_FAIL_COND_V((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I), -1);
+ ret = scale_track_insert_key(p_track, p_time, p_key);
+ track_set_key_transition(p_track, ret, p_transition);
} break;
case TYPE_BLEND_SHAPE: {
- ERR_FAIL_COND((p_key.get_type() != Variant::FLOAT) && (p_key.get_type() != Variant::INT));
- int idx = blend_shape_track_insert_key(p_track, p_time, p_key);
- track_set_key_transition(p_track, idx, p_transition);
+ ERR_FAIL_COND_V((p_key.get_type() != Variant::FLOAT) && (p_key.get_type() != Variant::INT), -1);
+ ret = blend_shape_track_insert_key(p_track, p_time, p_key);
+ track_set_key_transition(p_track, ret, p_transition);
} break;
case TYPE_VALUE: {
@@ -1599,17 +1601,17 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke
k.time = p_time;
k.transition = p_transition;
k.value = p_key;
- _insert(p_time, vt->values, k);
+ ret = _insert(p_time, vt->values, k);
} break;
case TYPE_METHOD: {
MethodTrack *mt = static_cast<MethodTrack *>(t);
- ERR_FAIL_COND(p_key.get_type() != Variant::DICTIONARY);
+ ERR_FAIL_COND_V(p_key.get_type() != Variant::DICTIONARY, -1);
Dictionary d = p_key;
- ERR_FAIL_COND(!d.has("method") || (d["method"].get_type() != Variant::STRING_NAME && d["method"].get_type() != Variant::STRING));
- ERR_FAIL_COND(!d.has("args") || !d["args"].is_array());
+ ERR_FAIL_COND_V(!d.has("method") || (d["method"].get_type() != Variant::STRING_NAME && d["method"].get_type() != Variant::STRING), -1);
+ ERR_FAIL_COND_V(!d.has("args") || !d["args"].is_array(), -1);
MethodKey k;
@@ -1618,14 +1620,14 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke
k.method = d["method"];
k.params = d["args"];
- _insert(p_time, mt->methods, k);
+ ret = _insert(p_time, mt->methods, k);
} break;
case TYPE_BEZIER: {
BezierTrack *bt = static_cast<BezierTrack *>(t);
Array arr = p_key;
- ERR_FAIL_COND(arr.size() != 6);
+ ERR_FAIL_COND_V(arr.size() != 6, -1);
TKey<BezierKey> k;
k.time = p_time;
@@ -1635,23 +1637,23 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke
k.value.out_handle.x = arr[3];
k.value.out_handle.y = arr[4];
k.value.handle_mode = static_cast<HandleMode>((int)arr[5]);
- _insert(p_time, bt->values, k);
+ ret = _insert(p_time, bt->values, k);
} break;
case TYPE_AUDIO: {
AudioTrack *at = static_cast<AudioTrack *>(t);
Dictionary k = p_key;
- ERR_FAIL_COND(!k.has("start_offset"));
- ERR_FAIL_COND(!k.has("end_offset"));
- ERR_FAIL_COND(!k.has("stream"));
+ ERR_FAIL_COND_V(!k.has("start_offset"), -1);
+ ERR_FAIL_COND_V(!k.has("end_offset"), -1);
+ ERR_FAIL_COND_V(!k.has("stream"), -1);
TKey<AudioKey> ak;
ak.time = p_time;
ak.value.start_offset = k["start_offset"];
ak.value.end_offset = k["end_offset"];
ak.value.stream = k["stream"];
- _insert(p_time, at->values, ak);
+ ret = _insert(p_time, at->values, ak);
} break;
case TYPE_ANIMATION: {
@@ -1661,12 +1663,14 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke
ak.time = p_time;
ak.value = p_key;
- _insert(p_time, at->values, ak);
+ ret = _insert(p_time, at->values, ak);
} break;
}
emit_changed();
+
+ return ret;
}
int Animation::track_get_key_count(int p_track) const {
@@ -2302,7 +2306,7 @@ Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a
}
Quaternion Animation::_cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c) const {
- return p_a.cubic_slerp(p_b, p_pre_a, p_post_b, p_c);
+ return p_a.spherical_cubic_interpolate(p_b, p_pre_a, p_post_b, p_c);
}
Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const {
@@ -2363,7 +2367,7 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a
Quaternion pa = p_pre_a;
Quaternion pb = p_post_b;
- return a.cubic_slerp(b, pa, pb, p_c);
+ return a.spherical_cubic_interpolate(b, pa, pb, p_c);
}
case Variant::AABB: {
AABB a = p_a;
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index b4528ccd3a..bf9f786a0d 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -392,7 +392,7 @@ public:
void track_set_enabled(int p_track, bool p_enabled);
bool track_is_enabled(int p_track) const;
- void track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition = 1);
+ int track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition = 1);
void track_set_key_transition(int p_track, int p_key_idx, real_t p_transition);
void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value);
void track_set_key_time(int p_track, int p_key_idx, double p_time);
@@ -488,4 +488,4 @@ VARIANT_ENUM_CAST(Animation::UpdateMode);
VARIANT_ENUM_CAST(Animation::HandleMode);
VARIANT_ENUM_CAST(Animation::LoopMode);
-#endif
+#endif // ANIMATION_H
diff --git a/scene/resources/animation_library.h b/scene/resources/animation_library.h
index 7a69cd140a..d63807b6d7 100644
--- a/scene/resources/animation_library.h
+++ b/scene/resources/animation_library.h
@@ -63,4 +63,4 @@ public:
AnimationLibrary();
};
-#endif // ANIMATIONLIBRARY_H
+#endif // ANIMATION_LIBRARY_H
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_wav.cpp
index 30c222bdff..a87c8272ea 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_wav.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* audio_stream_sample.cpp */
+/* audio_stream_wav.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "audio_stream_sample.h"
+#include "audio_stream_wav.h"
#include "core/io/file_access.h"
#include "core/io/marshalls.h"
-void AudioStreamPlaybackSample::start(float p_from_pos) {
- if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+void AudioStreamPlaybackWAV::start(float p_from_pos) {
+ if (base->format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
//no seeking in IMA_ADPCM
for (int i = 0; i < 2; i++) {
ima_adpcm[i].step_index = 0;
@@ -55,24 +55,24 @@ void AudioStreamPlaybackSample::start(float p_from_pos) {
active = true;
}
-void AudioStreamPlaybackSample::stop() {
+void AudioStreamPlaybackWAV::stop() {
active = false;
}
-bool AudioStreamPlaybackSample::is_playing() const {
+bool AudioStreamPlaybackWAV::is_playing() const {
return active;
}
-int AudioStreamPlaybackSample::get_loop_count() const {
+int AudioStreamPlaybackWAV::get_loop_count() const {
return 0;
}
-float AudioStreamPlaybackSample::get_playback_position() const {
+float AudioStreamPlaybackWAV::get_playback_position() const {
return float(offset >> MIX_FRAC_BITS) / base->mix_rate;
}
-void AudioStreamPlaybackSample::seek(float p_time) {
- if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+void AudioStreamPlaybackWAV::seek(float p_time) {
+ if (base->format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
return; //no seeking in ima-adpcm
}
@@ -87,7 +87,7 @@ void AudioStreamPlaybackSample::seek(float p_time) {
}
template <class Depth, bool is_stereo, bool is_ima_adpcm>
-void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm) {
+void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm) {
// this function will be compiled branchless by any decent compiler
int32_t final, final_r, next, next_r;
@@ -124,7 +124,7 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds
ima_adpcm[i].last_nibble++;
const uint8_t *src_ptr = (const uint8_t *)base->data;
- src_ptr += AudioStreamSample::DATA_PAD;
+ src_ptr += AudioStreamWAV::DATA_PAD;
uint8_t nbb = src_ptr[(ima_adpcm[i].last_nibble >> 1) * (is_stereo ? 2 : 1) + i];
nibble = (ima_adpcm[i].last_nibble & 1) ? (nbb >> 4) : (nbb & 0xF);
@@ -221,7 +221,7 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds
}
}
-int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
+int AudioStreamPlaybackWAV::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
if (!base->data || !active) {
for (int i = 0; i < p_frames; i++) {
p_buffer[i] = AudioFrame(0, 0);
@@ -231,13 +231,13 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
int len = base->data_bytes;
switch (base->format) {
- case AudioStreamSample::FORMAT_8_BITS:
+ case AudioStreamWAV::FORMAT_8_BITS:
len /= 1;
break;
- case AudioStreamSample::FORMAT_16_BITS:
+ case AudioStreamWAV::FORMAT_16_BITS:
len /= 2;
break;
- case AudioStreamSample::FORMAT_IMA_ADPCM:
+ case AudioStreamWAV::FORMAT_IMA_ADPCM:
len *= 2;
break;
}
@@ -251,13 +251,13 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
int64_t loop_begin_fp = ((int64_t)base->loop_begin << MIX_FRAC_BITS);
int64_t loop_end_fp = ((int64_t)base->loop_end << MIX_FRAC_BITS);
int64_t length_fp = ((int64_t)len << MIX_FRAC_BITS);
- int64_t begin_limit = (base->loop_mode != AudioStreamSample::LOOP_DISABLED) ? loop_begin_fp : 0;
- int64_t end_limit = (base->loop_mode != AudioStreamSample::LOOP_DISABLED) ? loop_end_fp : length_fp;
+ int64_t begin_limit = (base->loop_mode != AudioStreamWAV::LOOP_DISABLED) ? loop_begin_fp : 0;
+ int64_t end_limit = (base->loop_mode != AudioStreamWAV::LOOP_DISABLED) ? loop_end_fp : length_fp;
bool is_stereo = base->stereo;
int32_t todo = p_frames;
- if (base->loop_mode == AudioStreamSample::LOOP_BACKWARD) {
+ if (base->loop_mode == AudioStreamWAV::LOOP_BACKWARD) {
sign = -1;
}
@@ -271,20 +271,20 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
//looping
- AudioStreamSample::LoopMode loop_format = base->loop_mode;
- AudioStreamSample::Format format = base->format;
+ AudioStreamWAV::LoopMode loop_format = base->loop_mode;
+ AudioStreamWAV::Format format = base->format;
/* audio data */
uint8_t *dataptr = (uint8_t *)base->data;
- const void *data = dataptr + AudioStreamSample::DATA_PAD;
+ const void *data = dataptr + AudioStreamWAV::DATA_PAD;
AudioFrame *dst_buff = p_buffer;
- if (format == AudioStreamSample::FORMAT_IMA_ADPCM) {
- if (loop_format != AudioStreamSample::LOOP_DISABLED) {
+ if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
+ if (loop_format != AudioStreamWAV::LOOP_DISABLED) {
ima_adpcm[0].loop_pos = loop_begin_fp >> MIX_FRAC_BITS;
ima_adpcm[1].loop_pos = loop_begin_fp >> MIX_FRAC_BITS;
- loop_format = AudioStreamSample::LOOP_FORWARD;
+ loop_format = AudioStreamWAV::LOOP_FORWARD;
}
}
@@ -297,9 +297,9 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
if (increment < 0) {
/* going backwards */
- if (loop_format != AudioStreamSample::LOOP_DISABLED && offset < loop_begin_fp) {
+ if (loop_format != AudioStreamWAV::LOOP_DISABLED && offset < loop_begin_fp) {
/* loopstart reached */
- if (loop_format == AudioStreamSample::LOOP_PINGPONG) {
+ if (loop_format == AudioStreamWAV::LOOP_PINGPONG) {
/* bounce ping pong */
offset = loop_begin_fp + (loop_begin_fp - offset);
increment = -increment;
@@ -317,10 +317,10 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
}
} else {
/* going forward */
- if (loop_format != AudioStreamSample::LOOP_DISABLED && offset >= loop_end_fp) {
+ if (loop_format != AudioStreamWAV::LOOP_DISABLED && offset >= loop_end_fp) {
/* loopend reached */
- if (loop_format == AudioStreamSample::LOOP_PINGPONG) {
+ if (loop_format == AudioStreamWAV::LOOP_PINGPONG) {
/* bounce ping pong */
offset = loop_end_fp - (offset - loop_end_fp);
increment = -increment;
@@ -328,7 +328,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
} else {
/* go to loop-begin */
- if (format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+ if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
for (int i = 0; i < 2; i++) {
ima_adpcm[i].step_index = ima_adpcm[i].loop_step_index;
ima_adpcm[i].predictor = ima_adpcm[i].loop_predictor;
@@ -366,14 +366,14 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
todo -= target;
switch (base->format) {
- case AudioStreamSample::FORMAT_8_BITS: {
+ case AudioStreamWAV::FORMAT_8_BITS: {
if (is_stereo) {
do_resample<int8_t, true, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
} else {
do_resample<int8_t, false, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
}
} break;
- case AudioStreamSample::FORMAT_16_BITS: {
+ case AudioStreamWAV::FORMAT_16_BITS: {
if (is_stereo) {
do_resample<int16_t, true, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm);
} else {
@@ -381,7 +381,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
}
} break;
- case AudioStreamSample::FORMAT_IMA_ADPCM: {
+ case AudioStreamWAV::FORMAT_IMA_ADPCM: {
if (is_stereo) {
do_resample<int8_t, true, true>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
} else {
@@ -406,69 +406,73 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
return p_frames;
}
-AudioStreamPlaybackSample::AudioStreamPlaybackSample() {}
+void AudioStreamPlaybackWAV::tag_used_streams() {
+ base->tag_used(get_playback_position());
+}
+
+AudioStreamPlaybackWAV::AudioStreamPlaybackWAV() {}
/////////////////////
-void AudioStreamSample::set_format(Format p_format) {
+void AudioStreamWAV::set_format(Format p_format) {
format = p_format;
}
-AudioStreamSample::Format AudioStreamSample::get_format() const {
+AudioStreamWAV::Format AudioStreamWAV::get_format() const {
return format;
}
-void AudioStreamSample::set_loop_mode(LoopMode p_loop_mode) {
+void AudioStreamWAV::set_loop_mode(LoopMode p_loop_mode) {
loop_mode = p_loop_mode;
}
-AudioStreamSample::LoopMode AudioStreamSample::get_loop_mode() const {
+AudioStreamWAV::LoopMode AudioStreamWAV::get_loop_mode() const {
return loop_mode;
}
-void AudioStreamSample::set_loop_begin(int p_frame) {
+void AudioStreamWAV::set_loop_begin(int p_frame) {
loop_begin = p_frame;
}
-int AudioStreamSample::get_loop_begin() const {
+int AudioStreamWAV::get_loop_begin() const {
return loop_begin;
}
-void AudioStreamSample::set_loop_end(int p_frame) {
+void AudioStreamWAV::set_loop_end(int p_frame) {
loop_end = p_frame;
}
-int AudioStreamSample::get_loop_end() const {
+int AudioStreamWAV::get_loop_end() const {
return loop_end;
}
-void AudioStreamSample::set_mix_rate(int p_hz) {
+void AudioStreamWAV::set_mix_rate(int p_hz) {
ERR_FAIL_COND(p_hz == 0);
mix_rate = p_hz;
}
-int AudioStreamSample::get_mix_rate() const {
+int AudioStreamWAV::get_mix_rate() const {
return mix_rate;
}
-void AudioStreamSample::set_stereo(bool p_enable) {
+void AudioStreamWAV::set_stereo(bool p_enable) {
stereo = p_enable;
}
-bool AudioStreamSample::is_stereo() const {
+bool AudioStreamWAV::is_stereo() const {
return stereo;
}
-float AudioStreamSample::get_length() const {
+float AudioStreamWAV::get_length() const {
int len = data_bytes;
switch (format) {
- case AudioStreamSample::FORMAT_8_BITS:
+ case AudioStreamWAV::FORMAT_8_BITS:
len /= 1;
break;
- case AudioStreamSample::FORMAT_16_BITS:
+ case AudioStreamWAV::FORMAT_16_BITS:
len /= 2;
break;
- case AudioStreamSample::FORMAT_IMA_ADPCM:
+ case AudioStreamWAV::FORMAT_IMA_ADPCM:
len *= 2;
break;
}
@@ -480,11 +484,11 @@ float AudioStreamSample::get_length() const {
return float(len) / mix_rate;
}
-bool AudioStreamSample::is_monophonic() const {
+bool AudioStreamWAV::is_monophonic() const {
return false;
}
-void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) {
+void AudioStreamWAV::set_data(const Vector<uint8_t> &p_data) {
AudioServer::get_singleton()->lock();
if (data) {
memfree(data);
@@ -506,7 +510,7 @@ void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) {
AudioServer::get_singleton()->unlock();
}
-Vector<uint8_t> AudioStreamSample::get_data() const {
+Vector<uint8_t> AudioStreamWAV::get_data() const {
Vector<uint8_t> pv;
if (data) {
@@ -521,8 +525,8 @@ Vector<uint8_t> AudioStreamSample::get_data() const {
return pv;
}
-Error AudioStreamSample::save_to_wav(const String &p_path) {
- if (format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+Error AudioStreamWAV::save_to_wav(const String &p_path) {
+ if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
WARN_PRINT("Saving IMA_ADPC samples are not supported yet");
return ERR_UNAVAILABLE;
}
@@ -540,13 +544,13 @@ Error AudioStreamSample::save_to_wav(const String &p_path) {
int byte_pr_sample = 0;
switch (format) {
- case AudioStreamSample::FORMAT_8_BITS:
+ case AudioStreamWAV::FORMAT_8_BITS:
byte_pr_sample = 1;
break;
- case AudioStreamSample::FORMAT_16_BITS:
+ case AudioStreamWAV::FORMAT_16_BITS:
byte_pr_sample = 2;
break;
- case AudioStreamSample::FORMAT_IMA_ADPCM:
+ case AudioStreamWAV::FORMAT_IMA_ADPCM:
byte_pr_sample = 4;
break;
}
@@ -579,19 +583,19 @@ Error AudioStreamSample::save_to_wav(const String &p_path) {
Vector<uint8_t> data = get_data();
const uint8_t *read_data = data.ptr();
switch (format) {
- case AudioStreamSample::FORMAT_8_BITS:
+ case AudioStreamWAV::FORMAT_8_BITS:
for (unsigned int i = 0; i < data_bytes; i++) {
uint8_t data_point = (read_data[i] + 128);
file->store_8(data_point);
}
break;
- case AudioStreamSample::FORMAT_16_BITS:
+ case AudioStreamWAV::FORMAT_16_BITS:
for (unsigned int i = 0; i < data_bytes / 2; i++) {
uint16_t data_point = decode_uint16(&read_data[i * 2]);
file->store_16(data_point);
}
break;
- case AudioStreamSample::FORMAT_IMA_ADPCM:
+ case AudioStreamWAV::FORMAT_IMA_ADPCM:
//Unimplemented
break;
}
@@ -599,40 +603,40 @@ Error AudioStreamSample::save_to_wav(const String &p_path) {
return OK;
}
-Ref<AudioStreamPlayback> AudioStreamSample::instance_playback() {
- Ref<AudioStreamPlaybackSample> sample;
+Ref<AudioStreamPlayback> AudioStreamWAV::instantiate_playback() {
+ Ref<AudioStreamPlaybackWAV> sample;
sample.instantiate();
- sample->base = Ref<AudioStreamSample>(this);
+ sample->base = Ref<AudioStreamWAV>(this);
return sample;
}
-String AudioStreamSample::get_stream_name() const {
+String AudioStreamWAV::get_stream_name() const {
return "";
}
-void AudioStreamSample::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamSample::set_data);
- ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamSample::get_data);
+void AudioStreamWAV::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamWAV::set_data);
+ ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamWAV::get_data);
- ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioStreamSample::set_format);
- ClassDB::bind_method(D_METHOD("get_format"), &AudioStreamSample::get_format);
+ ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioStreamWAV::set_format);
+ ClassDB::bind_method(D_METHOD("get_format"), &AudioStreamWAV::get_format);
- ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &AudioStreamSample::set_loop_mode);
- ClassDB::bind_method(D_METHOD("get_loop_mode"), &AudioStreamSample::get_loop_mode);
+ ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &AudioStreamWAV::set_loop_mode);
+ ClassDB::bind_method(D_METHOD("get_loop_mode"), &AudioStreamWAV::get_loop_mode);
- ClassDB::bind_method(D_METHOD("set_loop_begin", "loop_begin"), &AudioStreamSample::set_loop_begin);
- ClassDB::bind_method(D_METHOD("get_loop_begin"), &AudioStreamSample::get_loop_begin);
+ ClassDB::bind_method(D_METHOD("set_loop_begin", "loop_begin"), &AudioStreamWAV::set_loop_begin);
+ ClassDB::bind_method(D_METHOD("get_loop_begin"), &AudioStreamWAV::get_loop_begin);
- ClassDB::bind_method(D_METHOD("set_loop_end", "loop_end"), &AudioStreamSample::set_loop_end);
- ClassDB::bind_method(D_METHOD("get_loop_end"), &AudioStreamSample::get_loop_end);
+ ClassDB::bind_method(D_METHOD("set_loop_end", "loop_end"), &AudioStreamWAV::set_loop_end);
+ ClassDB::bind_method(D_METHOD("get_loop_end"), &AudioStreamWAV::get_loop_end);
- ClassDB::bind_method(D_METHOD("set_mix_rate", "mix_rate"), &AudioStreamSample::set_mix_rate);
- ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamSample::get_mix_rate);
+ ClassDB::bind_method(D_METHOD("set_mix_rate", "mix_rate"), &AudioStreamWAV::set_mix_rate);
+ ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamWAV::get_mix_rate);
- ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamSample::set_stereo);
- ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamSample::is_stereo);
+ ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamWAV::set_stereo);
+ ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamWAV::is_stereo);
- ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamSample::save_to_wav);
+ ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamWAV::save_to_wav);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data");
ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format");
@@ -652,9 +656,9 @@ void AudioStreamSample::_bind_methods() {
BIND_ENUM_CONSTANT(LOOP_BACKWARD);
}
-AudioStreamSample::AudioStreamSample() {}
+AudioStreamWAV::AudioStreamWAV() {}
-AudioStreamSample::~AudioStreamSample() {
+AudioStreamWAV::~AudioStreamWAV() {
if (data) {
memfree(data);
data = nullptr;
diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_wav.h
index 357febc27a..d800388d96 100644
--- a/scene/resources/audio_stream_sample.h
+++ b/scene/resources/audio_stream_wav.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* audio_stream_sample.h */
+/* audio_stream_wav.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,15 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIO_STREAM_SAMPLE_H
-#define AUDIO_STREAM_SAMPLE_H
+#ifndef AUDIO_STREAM_WAV_H
+#define AUDIO_STREAM_WAV_H
#include "servers/audio/audio_stream.h"
-class AudioStreamSample;
+class AudioStreamWAV;
-class AudioStreamPlaybackSample : public AudioStreamPlayback {
- GDCLASS(AudioStreamPlaybackSample, AudioStreamPlayback);
+class AudioStreamPlaybackWAV : public AudioStreamPlayback {
+ GDCLASS(AudioStreamPlaybackWAV, AudioStreamPlayback);
enum {
MIX_FRAC_BITS = 13,
MIX_FRAC_LEN = (1 << MIX_FRAC_BITS),
@@ -57,8 +57,8 @@ class AudioStreamPlaybackSample : public AudioStreamPlayback {
int64_t offset = 0;
int sign = 1;
bool active = false;
- friend class AudioStreamSample;
- Ref<AudioStreamSample> base;
+ friend class AudioStreamWAV;
+ Ref<AudioStreamWAV> base;
template <class Depth, bool is_stereo, bool is_ima_adpcm>
void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm);
@@ -75,11 +75,13 @@ public:
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
- AudioStreamPlaybackSample();
+ virtual void tag_used_streams() override;
+
+ AudioStreamPlaybackWAV();
};
-class AudioStreamSample : public AudioStream {
- GDCLASS(AudioStreamSample, AudioStream);
+class AudioStreamWAV : public AudioStream {
+ GDCLASS(AudioStreamWAV, AudioStream);
RES_BASE_EXTENSION("sample")
public:
@@ -98,7 +100,7 @@ public:
};
private:
- friend class AudioStreamPlaybackSample;
+ friend class AudioStreamPlaybackWAV;
enum {
DATA_PAD = 16 //padding for interpolation
@@ -144,14 +146,14 @@ public:
Error save_to_wav(const String &p_path);
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
- AudioStreamSample();
- ~AudioStreamSample();
+ AudioStreamWAV();
+ ~AudioStreamWAV();
};
-VARIANT_ENUM_CAST(AudioStreamSample::Format)
-VARIANT_ENUM_CAST(AudioStreamSample::LoopMode)
+VARIANT_ENUM_CAST(AudioStreamWAV::Format)
+VARIANT_ENUM_CAST(AudioStreamWAV::LoopMode)
-#endif // AUDIO_STREAM_SAMPLE_H
+#endif // AUDIO_STREAM_WAV_H
diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp
new file mode 100644
index 0000000000..aff917b2d4
--- /dev/null
+++ b/scene/resources/bone_map.cpp
@@ -0,0 +1,181 @@
+/*************************************************************************/
+/* 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;
+}
+
+void BoneMap::_get_property_list(List<PropertyInfo> *p_list) const {
+ HashMap<StringName, StringName>::ConstIterator E = bone_map.begin();
+ while (E) {
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bone_map/" + E->key, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
+ ++E;
+ }
+}
+
+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_ARRAY("bonemap", "bonemap");
+
+ 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/scene/resources/bone_map.h b/scene/resources/bone_map.h
new file mode 100644
index 0000000000..17452dfc73
--- /dev/null
+++ b/scene/resources/bone_map.h
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* bone_map.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_H
+#define BONE_MAP_H
+
+#include "skeleton_profile.h"
+
+class BoneMap : public Resource {
+ GDCLASS(BoneMap, Resource);
+
+ Ref<SkeletonProfile> profile;
+ HashMap<StringName, StringName> bone_map;
+
+ void _update_profile();
+ void _validate_bone_map();
+
+protected:
+ 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:
+ int get_profile_type() const;
+ void set_profile_type(const int p_profile_type);
+
+ Ref<SkeletonProfile> get_profile() const;
+ void set_profile(const Ref<SkeletonProfile> &p_profile);
+
+ int get_skeleton_bone_name_count(const StringName p_skeleton_bone_name) const;
+
+ 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);
+
+ StringName find_profile_bone_name(StringName p_skeleton_bone_name) const;
+
+ BoneMap();
+ ~BoneMap();
+};
+
+#endif // BONE_MAP_H
diff --git a/scene/resources/box_shape_3d.h b/scene/resources/box_shape_3d.h
index 4e6db893af..3dd0bb6cb7 100644
--- a/scene/resources/box_shape_3d.h
+++ b/scene/resources/box_shape_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BOX_SHAPE_H
-#define BOX_SHAPE_H
+#ifndef BOX_SHAPE_3D_H
+#define BOX_SHAPE_3D_H
#include "scene/resources/shape_3d.h"
@@ -56,4 +56,4 @@ public:
BoxShape3D();
};
-#endif // BOX_SHAPE_H
+#endif // BOX_SHAPE_3D_H
diff --git a/scene/resources/capsule_shape_3d.h b/scene/resources/capsule_shape_3d.h
index 4c039ab326..ad7f2e5b74 100644
--- a/scene/resources/capsule_shape_3d.h
+++ b/scene/resources/capsule_shape_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CAPSULE_SHAPE_H
-#define CAPSULE_SHAPE_H
+#ifndef CAPSULE_SHAPE_3D_H
+#define CAPSULE_SHAPE_3D_H
#include "scene/resources/shape_3d.h"
@@ -55,4 +55,4 @@ public:
CapsuleShape3D();
};
-#endif // CAPSULE_SHAPE_H
+#endif // CAPSULE_SHAPE_3D_H
diff --git a/scene/resources/concave_polygon_shape_2d.h b/scene/resources/concave_polygon_shape_2d.h
index 0f49a0d80f..d350d753b0 100644
--- a/scene/resources/concave_polygon_shape_2d.h
+++ b/scene/resources/concave_polygon_shape_2d.h
@@ -52,4 +52,4 @@ public:
ConcavePolygonShape2D();
};
-#endif
+#endif // CONCAVE_POLYGON_SHAPE_2D_H
diff --git a/scene/resources/concave_polygon_shape_3d.h b/scene/resources/concave_polygon_shape_3d.h
index a265590edd..68feacfa25 100644
--- a/scene/resources/concave_polygon_shape_3d.h
+++ b/scene/resources/concave_polygon_shape_3d.h
@@ -77,4 +77,4 @@ public:
ConcavePolygonShape3D();
};
-#endif // CONCAVE_POLYGON_SHAPE_H
+#endif // CONCAVE_POLYGON_SHAPE_3D_H
diff --git a/scene/resources/convex_polygon_shape_3d.h b/scene/resources/convex_polygon_shape_3d.h
index 930edb015d..5ca4d2a713 100644
--- a/scene/resources/convex_polygon_shape_3d.h
+++ b/scene/resources/convex_polygon_shape_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CONVEX_POLYGON_SHAPE_H
-#define CONVEX_POLYGON_SHAPE_H
+#ifndef CONVEX_POLYGON_SHAPE_3D_H
+#define CONVEX_POLYGON_SHAPE_3D_H
#include "scene/resources/shape_3d.h"
@@ -52,4 +52,4 @@ public:
ConvexPolygonShape3D();
};
-#endif // CONVEX_POLYGON_SHAPE_H
+#endif // CONVEX_POLYGON_SHAPE_3D_H
diff --git a/scene/resources/cylinder_shape_3d.h b/scene/resources/cylinder_shape_3d.h
index 65427423c8..f554358044 100644
--- a/scene/resources/cylinder_shape_3d.h
+++ b/scene/resources/cylinder_shape_3d.h
@@ -54,4 +54,4 @@ public:
CylinderShape3D();
};
-#endif // CYLINDER_SHAPE_H
+#endif // CYLINDER_SHAPE_3D_H
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 401aeb4889..fa375795c1 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));
@@ -742,7 +741,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_selected_color", "Tree", control_font_pressed_color);
theme->set_color("font_outline_color", "Tree", Color(1, 1, 1));
theme->set_color("guide_color", "Tree", Color(0.7, 0.7, 0.7, 0.25));
- theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2));
+ theme->set_color("drop_position_color", "Tree", Color(1, 1, 1));
theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27));
theme->set_color("parent_hl_line_color", "Tree", Color(0.27, 0.27, 0.27));
theme->set_color("children_hl_line_color", "Tree", Color(0.27, 0.27, 0.27));
@@ -777,7 +776,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "ItemList", control_font_lower_color);
theme->set_color("font_selected_color", "ItemList", control_font_pressed_color);
theme->set_color("font_outline_color", "ItemList", Color(1, 1, 1));
- theme->set_color("guide_color", "ItemList", Color(0, 0, 0, 0.1));
+ theme->set_color("guide_color", "ItemList", Color(0.7, 0.7, 0.7, 0.25));
theme->set_stylebox("selected", "ItemList", make_flat_stylebox(style_selected_color));
theme->set_stylebox("selected_focus", "ItemList", make_flat_stylebox(style_selected_color));
theme->set_stylebox("cursor", "ItemList", focus);
@@ -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/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h
index f777330a07..9b070a90cc 100644
--- a/scene/resources/default_theme/default_theme.h
+++ b/scene/resources/default_theme/default_theme.h
@@ -39,4 +39,4 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, bool p_font_antialiased = true, bool p_font_msdf = false, bool p_font_generate_mipmaps = false);
void clear_default_theme();
-#endif
+#endif // DEFAULT_THEME_H
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index 854bd34d6a..d361b34da8 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -1249,8 +1249,8 @@ void Environment::_bind_methods() {
ADD_GROUP("SSR", "ssr_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssr_enabled"), "set_ssr_enabled", "is_ssr_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "ssr_max_steps", PROPERTY_HINT_RANGE, "1,512,1"), "set_ssr_max_steps", "get_ssr_max_steps");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_in", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_in", "get_ssr_fade_in");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_out", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_out", "get_ssr_fade_out");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_in", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_ssr_fade_in", "get_ssr_fade_in");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_out", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_ssr_fade_out", "get_ssr_fade_out");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_depth_tolerance", PROPERTY_HINT_RANGE, "0.01,128,0.1"), "set_ssr_depth_tolerance", "get_ssr_depth_tolerance");
// SSAO
@@ -1277,7 +1277,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssao_enabled"), "set_ssao_enabled", "is_ssao_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_radius", PROPERTY_HINT_RANGE, "0.01,16,0.01,or_greater"), "set_ssao_radius", "get_ssao_radius");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_intensity", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_ssao_intensity", "get_ssao_intensity");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_power", PROPERTY_HINT_EXP_EASING), "set_ssao_power", "get_ssao_power");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_power", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_ssao_power", "get_ssao_power");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_detail", PROPERTY_HINT_RANGE, "0,5,0.01"), "set_ssao_detail", "get_ssao_detail");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_horizon", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ssao_horizon", "get_ssao_horizon");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_sharpness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ssao_sharpness", "get_ssao_sharpness");
@@ -1337,8 +1337,10 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_bounce_feedback", PROPERTY_HINT_RANGE, "0,1.99,0.01"), "set_sdfgi_bounce_feedback", "get_sdfgi_bounce_feedback");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_cascades", PROPERTY_HINT_RANGE, "1,8,1"), "set_sdfgi_cascades", "get_sdfgi_cascades");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_min_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_sdfgi_min_cell_size", "get_sdfgi_min_cell_size");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_max_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_max_distance", "get_sdfgi_max_distance");
+ // Don't store the values of `sdfgi_cascade0_distance` and `sdfgi_max_distance`
+ // as they're derived from `sdfgi_min_cell_size`.
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater", PROPERTY_USAGE_EDITOR), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_max_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater", PROPERTY_USAGE_EDITOR), "set_sdfgi_max_distance", "get_sdfgi_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_y_scale", PROPERTY_HINT_ENUM, "50% (Compact),75% (Balanced),100% (Sparse)"), "set_sdfgi_y_scale", "get_sdfgi_y_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_energy"), "set_sdfgi_energy", "get_sdfgi_energy");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_normal_bias"), "set_sdfgi_normal_bias", "get_sdfgi_normal_bias");
@@ -1423,7 +1425,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_fog_light_energy", "get_fog_light_energy");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_sun_scatter", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_fog_sun_scatter", "get_fog_sun_scatter");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density", PROPERTY_HINT_RANGE, "0,16,0.0001"), "set_fog_density", "get_fog_density");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density", PROPERTY_HINT_RANGE, "0,1,0.0001,or_greater"), "set_fog_density", "get_fog_density");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_aerial_perspective", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_fog_aerial_perspective", "get_fog_aerial_perspective");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height", PROPERTY_HINT_RANGE, "-1024,1024,0.01,or_lesser,or_greater,suffix:m"), "set_fog_height", "get_fog_height");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_density", PROPERTY_HINT_RANGE, "-16,16,0.0001,or_lesser,or_greater"), "set_fog_height_density", "get_fog_height_density");
@@ -1462,7 +1464,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_gi_inject", PROPERTY_HINT_RANGE, "0.0,16,0.01,exp"), "set_volumetric_fog_gi_inject", "get_volumetric_fog_gi_inject");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_anisotropy", PROPERTY_HINT_RANGE, "-0.9,0.9,0.01"), "set_volumetric_fog_anisotropy", "get_volumetric_fog_anisotropy");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_length", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_length", "get_volumetric_fog_length");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_ambient_inject", PROPERTY_HINT_RANGE, "0.0,16,0.01,exp"), "set_volumetric_fog_ambient_inject", "get_volumetric_fog_ambient_inject");
ADD_SUBGROUP("Temporal Reprojection", "volumetric_fog_temporal_reprojection_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "volumetric_fog_temporal_reprojection_enabled"), "set_volumetric_fog_temporal_reprojection_enabled", "is_volumetric_fog_temporal_reprojection_enabled");
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index b71fe8904a..385d815230 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -175,10 +175,10 @@ private:
// Fog
bool fog_enabled = false;
- Color fog_light_color = Color(0.5, 0.6, 0.7);
+ Color fog_light_color = Color(0.518, 0.553, 0.608);
float fog_light_energy = 1.0;
float fog_sun_scatter = 0.0;
- float fog_density = 0.001;
+ float fog_density = 0.01;
float fog_height = 0.0;
float fog_height_density = 0.0; //can be negative to invert effect
float fog_aerial_perspective = 0.0;
@@ -194,8 +194,8 @@ private:
float volumetric_fog_anisotropy = 0.2;
float volumetric_fog_length = 64.0;
float volumetric_fog_detail_spread = 2.0;
- float volumetric_fog_gi_inject = 0.0;
- float volumetric_fog_ambient_inject = false;
+ float volumetric_fog_gi_inject = 1.0;
+ float volumetric_fog_ambient_inject = 0.0;
bool volumetric_fog_temporal_reproject = true;
float volumetric_fog_temporal_reproject_amount = 0.9;
void _update_volumetric_fog();
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 46f23424dd..619036d296 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,558 @@
#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);
+
+ // 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);
+
+ // 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("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_spacing", "spacing"), &Font::get_spacing);
+ ClassDB::bind_method(D_METHOD("get_opentype_features"), &Font::get_opentype_features);
+
+ // Drawing string.
+ ClassDB::bind_method(D_METHOD("set_cache_capacity", "single_line", "multi_line"), &Font::set_cache_capacity);
-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);
+ ClassDB::bind_method(D_METHOD("get_string_size", "text", "alignment", "width", "font_size", "jst_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", "brk_flags", "jst_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::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("set_data", "data"), &FontData::set_data);
- ClassDB::bind_method(D_METHOD("get_data"), &FontData::get_data);
+ ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "modulate", "jst_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", "brk_flags", "jst_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), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- 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("draw_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "jst_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", "brk_flags", "jst_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), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("get_face_count"), &FontData::get_face_count);
+ // Drawing char.
+ ClassDB::bind_method(D_METHOD("get_char_size", "char", "font_size"), &Font::get_char_size);
+ ClassDB::bind_method(D_METHOD("draw_char", "canvas_item", "pos", "char", "font_size", "modulate"), &Font::draw_char, DEFVAL(Color(1.0, 1.0, 1.0)));
+ ClassDB::bind_method(D_METHOD("draw_char_outline", "canvas_item", "pos", "char", "font_size", "size", "modulate"), &Font::draw_char_outline, DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)));
- ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontData::set_antialiased);
- ClassDB::bind_method(D_METHOD("is_antialiased"), &FontData::is_antialiased);
+ // 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_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("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_font_name", "name"), &FontData::set_font_name);
- ClassDB::bind_method(D_METHOD("get_font_name"), &FontData::get_font_name);
+ 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_font_style_name", "name"), &FontData::set_font_style_name);
- ClassDB::bind_method(D_METHOD("get_font_style_name"), &FontData::get_font_style_name);
+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);
+ }
+ }
+}
+
+void Font::_update_rids() const {
+ rids.clear();
+ _update_rids_fb(const_cast<Font *>(this), 0);
+ dirty_rids = false;
+}
- 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);
+void Font::_invalidate_rids() {
+ rids.clear();
+ dirty_rids = true;
- 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);
+ cache.clear();
+ cache_wrap.clear();
- 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);
+ emit_changed();
+}
- 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);
+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;
+}
+
+void Font::reset_state() {
+ _invalidate_rids();
+}
+
+// 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), CONNECT_REFERENCE_COUNTED);
+ }
+ }
+ _invalidate_rids();
+}
+
+TypedArray<Font> Font::get_fallbacks() const {
+ return fallbacks;
+}
- 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);
+// Output.
+TypedArray<RID> Font::get_rids() const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ return rids;
+}
- 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);
+// 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_hinting", "hinting"), &FontData::set_hinting);
- ClassDB::bind_method(D_METHOD("get_hinting"), &FontData::get_hinting);
+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);
+}
- 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);
+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);
+}
- ClassDB::bind_method(D_METHOD("set_embolden", "strength"), &FontData::set_embolden);
- ClassDB::bind_method(D_METHOD("get_embolden"), &FontData::get_embolden);
+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_transform", "transform"), &FontData::set_transform);
- ClassDB::bind_method(D_METHOD("get_transform"), &FontData::get_transform);
+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_oversampling", "oversampling"), &FontData::set_oversampling);
- ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling);
+String Font::get_font_name() const {
+ return TS->font_get_name(_get_rid());
+}
- ClassDB::bind_method(D_METHOD("find_cache", "variation_coordinates"), &FontData::find_cache);
+String Font::get_font_style_name() const {
+ return TS->font_get_style_name(_get_rid());
+}
- 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);
+BitField<TextServer::FontStyle> Font::get_font_style() const {
+ return TS->font_get_style(_get_rid());
+}
- 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);
+Dictionary Font::get_opentype_features() const {
+ return Dictionary();
+}
- 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.
+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("set_ascent", "cache_index", "size", "ascent"), &FontData::set_ascent);
- ClassDB::bind_method(D_METHOD("get_ascent", "cache_index", "size"), &FontData::get_ascent);
+Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, BitField<TextServer::JustificationFlag> p_jst_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_jst_flags.operator uint32_t(), hash);
+ }
+ hash = hash_djb2_one_64(p_direction, hash);
+ hash = hash_djb2_one_64(p_orientation, hash);
- 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);
+ 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);
+ if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ buffer->set_horizontal_alignment(p_alignment);
+ buffer->set_width(p_width);
+ buffer->set_flags(p_jst_flags);
+ }
+ cache.insert(hash, buffer);
+ }
+ return buffer->get_size();
+}
- 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);
+Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_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_brk_flags.operator uint32_t(), hash);
+ hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash);
+ hash = hash_djb2_one_64(p_direction, hash);
+ hash = hash_djb2_one_64(p_orientation, hash);
- 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);
+ 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_break_flags(p_brk_flags);
+ lines_buffer->set_justification_flags(p_jst_flags);
+ cache_wrap.insert(hash, lines_buffer);
+ }
- 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);
+ lines_buffer->set_alignment(p_alignment);
+ lines_buffer->set_max_lines_visible(p_max_lines);
- 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);
+ return lines_buffer->get_size();
+}
- 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);
+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, BitField<TextServer::JustificationFlag> p_jst_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_jst_flags.operator uint32_t(), 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);
+ }
- 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);
+ if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ buffer->set_flags(p_jst_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, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_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_brk_flags.operator uint32_t(), hash);
+ hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), 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_break_flags(p_brk_flags);
+ lines_buffer->set_justification_flags(p_jst_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, BitField<TextServer::JustificationFlag> p_jst_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_jst_flags.operator uint32_t(), hash);
+ }
+ hash = hash_djb2_one_64(p_direction, hash);
+ hash = hash_djb2_one_64(p_orientation, 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);
+ if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ buffer->set_flags(p_jst_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, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_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_brk_flags.operator uint32_t(), hash);
+ hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), 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_break_flags(p_brk_flags);
+ lines_buffer->set_justification_flags(p_jst_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();
+}
+
+/*************************************************************************/
+/* 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();
+ }
+ }
}
-void FontData::_convert_packed_8bit(Ref<Image> &p_source, int p_page, int p_sz) {
+_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 +636,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 +736,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 +792,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 +821,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 +864,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_FLAGS, "Bold,Italic,Fixed Size", 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;
@@ -763,7 +1351,7 @@ Error FontData::load_bitmap_font(const String &p_path) {
int height = 0;
int ascent = 0;
int outline = 0;
- uint32_t st_flags = 0;
+ BitField<TextServer::FontStyle> st_flags = 0;
String font_name;
bool packed = false;
@@ -789,10 +1377,10 @@ Error FontData::load_bitmap_font(const String &p_path) {
uint8_t flags = f->get_8();
ERR_FAIL_COND_V_MSG(flags & 0x02, ERR_CANT_CREATE, RTR("Non-unicode version of BMFont is not supported."));
if (flags & (1 << 3)) {
- st_flags |= TextServer::FONT_BOLD;
+ st_flags.set_flag(TextServer::FONT_BOLD);
}
if (flags & (1 << 2)) {
- st_flags |= TextServer::FONT_ITALIC;
+ st_flags.set_flag(TextServer::FONT_ITALIC);
}
f->get_8(); // non-unicode charset, skip
f->get_16(); // stretch_h, skip
@@ -1019,12 +1607,12 @@ Error FontData::load_bitmap_font(const String &p_path) {
}
if (keys.has("bold")) {
if (keys["bold"].to_int()) {
- st_flags |= TextServer::FONT_BOLD;
+ st_flags.set_flag(TextServer::FONT_BOLD);
}
}
if (keys.has("italic")) {
if (keys["italic"].to_int()) {
- st_flags |= TextServer::FONT_ITALIC;
+ st_flags.set_flag(TextServer::FONT_ITALIC);
}
}
if (keys.has("face")) {
@@ -1209,13 +1797,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 +1812,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 +1826,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 +1840,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 +1849,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(BitField<TextServer::FontStyle> 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 +1875,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 +1890,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 +1905,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 +1920,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 +1935,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 +1950,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 +1965,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 +1980,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 +1995,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 +2010,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 +2059,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 +2089,978 @@ 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 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::_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);
- }
-}
+ 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);
-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_embolden", "strength"), &FontVariation::set_variation_embolden);
+ ClassDB::bind_method(D_METHOD("get_variation_embolden"), &FontVariation::get_variation_embolden);
- 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_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_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_transform", "transform"), &FontVariation::set_variation_transform);
+ ClassDB::bind_method(D_METHOD("get_variation_transform"), &FontVariation::get_variation_transform);
- 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_opentype_features", "features"), &FontVariation::set_opentype_features);
- 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_spacing", "spacing", "value"), &FontVariation::set_spacing);
- 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)));
+ 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("has_char", "char"), &Font::has_char);
- ClassDB::bind_method(D_METHOD("get_supported_chars"), &Font::get_supported_chars);
+ 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("update_changes"), &Font::update_changes);
+ ADD_GROUP("OpenType Features", "opentype");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "opentype_features"), "set_opentype_features", "get_opentype_features");
- ClassDB::bind_method(D_METHOD("get_rids"), &Font::get_rids);
+ 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::_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;
+void FontVariation::_update_rids() const {
+ Ref<Font> f = _get_base_font_or_default();
+
+ rids.clear();
+ if (fallbacks.is_empty() && f.is_valid()) {
+ RID rid = _get_rid();
+ if (rid.is_valid()) {
+ rids.push_back(rid);
}
- 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;
+
+ 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);
}
- return false;
+ dirty_rids = false;
}
-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::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();
+ }
- if (idx == data.size()) {
- r_ret = Ref<FontData>();
- return true;
- } else if (idx >= 0 && idx < data.size()) {
- r_ret = get_data(idx);
- return true;
- }
+ 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 false;
-}
+ variation = Variation();
+ opentype_features = Dictionary();
-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"));
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ extra_spacing[i] = 0;
}
- p_list->push_back(PropertyInfo(Variant::OBJECT, "data/" + itos(data.size()), PROPERTY_HINT_RESOURCE_TYPE, "FontData"));
+
+ Font::reset_state();
}
-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::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), CONNECT_REFERENCE_COUNTED);
}
+ _invalidate_rids();
+ notify_property_list_changed();
}
- cache.clear();
- cache_wrap.clear();
- data.clear();
- rids.clear();
+}
- variation_coordinates.clear();
- spacing_bottom = 0;
- spacing_top = 0;
+Ref<Font> FontVariation::get_base_font() const {
+ return base_font;
}
-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];
- }
+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();
+ }
+
+ if (base_font.is_valid()) {
+ return base_font;
}
- 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());
+ // 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);
- 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 (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), CONNECT_REFERENCE_COUNTED);
+ }
+ return f;
}
}
}
- cache.clear();
- cache_wrap.clear();
-
- emit_changed();
- notify_property_list_changed();
-}
-
-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));
- }
+ // 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);
- 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;
+ 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), CONNECT_REFERENCE_COUNTED);
+ }
+ return f;
+ }
}
- }
- if (data[p_idx].is_valid()) {
- data.write[p_idx]->connect(SNAME("changed"), callable_mp(this, &Font::_data_changed), varray(), CONNECT_REFERENCE_COUNTED);
+ // 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), CONNECT_REFERENCE_COUNTED);
+ }
+ return f;
}
- cache.clear();
- cache_wrap.clear();
+ return Ref<Font>();
+}
- emit_changed();
- notify_property_list_changed();
+void FontVariation::set_variation_opentype(const Dictionary &p_coords) {
+ if (variation.opentype != p_coords) {
+ variation.opentype = p_coords;
+ _invalidate_rids();
+ }
}
-int Font::get_data_count() const {
- return data.size();
+Dictionary FontVariation::get_variation_opentype() const {
+ return variation.opentype;
}
-Ref<FontData> Font::get_data(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, data.size(), Ref<FontData>());
- return data[p_idx];
+void FontVariation::set_variation_embolden(float p_strength) {
+ if (variation.embolden != p_strength) {
+ variation.embolden = p_strength;
+ _invalidate_rids();
+ }
}
-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];
+float FontVariation::get_variation_embolden() const {
+ return variation.embolden;
}
-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);
- }
+void FontVariation::set_variation_transform(Transform2D p_transform) {
+ if (variation.transform != p_transform) {
+ variation.transform = p_transform;
+ _invalidate_rids();
}
- data.clear();
- rids.clear();
}
-void Font::remove_data(int p_idx) {
- ERR_FAIL_INDEX(p_idx, data.size());
+Transform2D FontVariation::get_variation_transform() const {
+ return variation.transform;
+}
- if (data[p_idx].is_valid()) {
- data.write[p_idx]->disconnect(SNAME("changed"), callable_mp(this, &Font::_data_changed));
+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();
}
-
- data.remove_at(p_idx);
- rids.remove_at(p_idx);
-
- cache.clear();
- cache_wrap.clear();
-
- emit_changed();
- notify_property_list_changed();
}
-void Font::set_variation_coordinates(const Dictionary &p_variation_coordinates) {
- _data_changed();
- variation_coordinates = p_variation_coordinates;
+int FontVariation::get_variation_face_index() const {
+ return variation.face_index;
}
-Dictionary Font::get_variation_coordinates() const {
- return variation_coordinates;
+void FontVariation::set_opentype_features(const Dictionary &p_features) {
+ if (opentype_features != p_features) {
+ opentype_features = p_features;
+ _invalidate_rids();
+ }
}
-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;
- }
+Dictionary FontVariation::get_opentype_features() const {
+ return opentype_features;
}
-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;
+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();
}
}
-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));
- }
- return ret + spacing_bottom + spacing_top;
+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];
}
-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));
+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 ret + spacing_top;
+ return RID();
}
-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));
+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 ret + spacing_bottom;
+ return RID();
}
-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));
+FontVariation::FontVariation() {
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ extra_spacing[i] = 0;
}
- return ret + spacing_top;
}
-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));
- }
- return ret;
+FontVariation::~FontVariation() {
+ reset_state();
}
-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());
+/*************************************************************************/
+/* SystemFont */
+/*************************************************************************/
- for (int i = 0; i < data.size(); i++) {
- _ensure_rid(i);
- }
+void SystemFont::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &SystemFont::set_antialiased);
+ ClassDB::bind_method(D_METHOD("is_antialiased"), &SystemFont::is_antialiased);
- 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);
+ ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &SystemFont::set_generate_mipmaps);
+ ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &SystemFont::get_generate_mipmaps);
- Ref<TextLine> buffer;
- if (cache.has(hash)) {
- buffer = cache.get(hash);
+ ClassDB::bind_method(D_METHOD("set_force_autohinter", "force_autohinter"), &SystemFont::set_force_autohinter);
+ ClassDB::bind_method(D_METHOD("is_force_autohinter"), &SystemFont::is_force_autohinter);
+
+ ClassDB::bind_method(D_METHOD("set_hinting", "hinting"), &SystemFont::set_hinting);
+ ClassDB::bind_method(D_METHOD("get_hinting"), &SystemFont::get_hinting);
+
+ ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &SystemFont::set_subpixel_positioning);
+ ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &SystemFont::get_subpixel_positioning);
+
+ ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &SystemFont::set_oversampling);
+ ClassDB::bind_method(D_METHOD("get_oversampling"), &SystemFont::get_oversampling);
+
+ ClassDB::bind_method(D_METHOD("get_font_names"), &SystemFont::get_font_names);
+ ClassDB::bind_method(D_METHOD("set_font_names", "names"), &SystemFont::set_font_names);
+
+ ClassDB::bind_method(D_METHOD("set_font_style", "style"), &SystemFont::set_font_style);
+
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "font_names"), "set_font_names", "get_font_names");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic"), "set_font_style", "get_font_style");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "is_antialiased");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "get_generate_mipmaps");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), "set_subpixel_positioning", "get_subpixel_positioning");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), "set_oversampling", "get_oversampling");
+ 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");
+}
+
+void SystemFont::_update_rids() const {
+ Ref<Font> f = _get_base_font_or_default();
+
+ rids.clear();
+ if (fallbacks.is_empty() && f.is_valid()) {
+ RID rid = _get_rid();
+ if (rid.is_valid()) {
+ rids.push_back(rid);
+ }
+
+ 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 {
- buffer.instantiate();
- buffer->add_string(p_text, Ref<Font>(this), p_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
- cache.insert(hash, buffer);
+ _update_rids_fb(const_cast<SystemFont *>(this), 0);
}
- return buffer->get_size();
+ dirty_rids = false;
}
-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 SystemFont::_update_base_font() {
+ if (base_font.is_valid()) {
+ base_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
+ base_font.unref();
}
- 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);
+ face_indeces.clear();
+ ftr_weight = 0;
+ ftr_italic = 0;
+ for (const String &E : names) {
+ if (E.is_empty()) {
+ continue;
+ }
- 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);
- }
+ String path = OS::get_singleton()->get_system_font_path(E, style & TextServer::FONT_BOLD, style & TextServer::FONT_ITALIC);
+ if (path.is_empty()) {
+ continue;
+ }
+ Ref<FontFile> file;
+ file.instantiate();
+ Error err = file->load_dynamic_font(path);
+ if (err != OK) {
+ continue;
+ }
- 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;
+ // If it's a font collection check all faces to match requested style.
+ for (int i = 0; i < file->get_face_count(); i++) {
+ file->set_face_index(0, i);
+ if (((file->get_font_style() & TextServer::FONT_BOLD) == (style & TextServer::FONT_BOLD)) && ((file->get_font_style() & TextServer::FONT_ITALIC) == (style & TextServer::FONT_ITALIC))) {
+ face_indeces.push_back(i);
+ }
+ }
+ if (face_indeces.is_empty()) {
+ face_indeces.push_back(0);
+ }
+ file->set_face_index(0, face_indeces[0]);
+
+ // If it's a variable font, apply weight and italic coordinates to match requested style.
+ Dictionary ftr = file->get_supported_variation_list();
+ if ((style & TextServer::FONT_BOLD) && ftr.has(TS->name_to_tag("weight"))) {
+ ftr_weight = 700;
+ }
+ if ((style & TextServer::FONT_ITALIC) && ftr.has(TS->name_to_tag("italic"))) {
+ ftr_italic = 1;
}
- }
- 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());
+ // Apply font rendering settings.
+ file->set_antialiased(antialiased);
+ file->set_generate_mipmaps(mipmaps);
+ file->set_force_autohinter(force_autohinter);
+ file->set_hinting(hinting);
+ file->set_subpixel_positioning(subpixel_positioning);
+ file->set_oversampling(oversampling);
- for (int i = 0; i < data.size(); i++) {
- _ensure_rid(i);
+ base_font = file;
}
- 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);
+ if (base_font.is_valid()) {
+ base_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
}
- 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);
+ _invalidate_rids();
+ notify_property_list_changed();
+}
+
+void SystemFont::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();
}
- Vector2 ofs = p_pos;
- if (buffer->get_orientation() == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.y -= buffer->get_line_ascent();
- } else {
- ofs.x -= buffer->get_line_ascent();
+ if (theme_font.is_valid()) {
+ theme_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
+ theme_font.unref();
}
- buffer->set_width(p_width);
- buffer->set_horizontal_alignment(p_alignment);
- buffer->set_flags(p_flags);
+ names.clear();
+ face_indeces.clear();
+ ftr_weight = 0;
+ ftr_italic = 0;
+ style = 0;
+ antialiased = true;
+ mipmaps = false;
+ force_autohinter = false;
+ hinting = TextServer::HINTING_LIGHT;
+ subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED;
+ oversampling = 0.f;
- 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);
+ Font::reset_state();
}
-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());
+Ref<Font> SystemFont::_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<SystemFont *>(this)), &Font::_invalidate_rids));
+ theme_font.unref();
+ }
- for (int i = 0; i < data.size(); i++) {
- _ensure_rid(i);
+ if (base_font.is_valid()) {
+ return base_font;
}
- 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);
+ // 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);
- 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);
+ 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<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
+ }
+ return f;
+ }
+ }
}
- lines_buffer->set_alignment(p_alignment);
+ // 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);
- 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);
+ 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<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
+ }
+ return f;
}
}
- if (p_width > 0) {
- lines_buffer->set_alignment(p_alignment);
+
+ // 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<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
}
+ return f;
+ }
+
+ return Ref<Font>();
+}
- 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);
+void SystemFont::set_antialiased(bool p_antialiased) {
+ if (antialiased != p_antialiased) {
+ antialiased = p_antialiased;
+ if (base_font.is_valid()) {
+ base_font->set_antialiased(antialiased);
}
- lines_buffer->draw_line(p_canvas_item, lofs, i, p_modulate);
+ emit_changed();
+ }
+}
- 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;
+bool SystemFont::is_antialiased() const {
+ return antialiased;
+}
+
+void SystemFont::set_generate_mipmaps(bool p_generate_mipmaps) {
+ if (mipmaps != p_generate_mipmaps) {
+ mipmaps = p_generate_mipmaps;
+ if (base_font.is_valid()) {
+ base_font->set_generate_mipmaps(mipmaps);
}
+ emit_changed();
+ }
+}
+
+bool SystemFont::get_generate_mipmaps() const {
+ return mipmaps;
+}
- if ((p_max_lines > 0) && (i >= p_max_lines)) {
- return;
+void SystemFont::set_force_autohinter(bool p_force_autohinter) {
+ if (force_autohinter != p_force_autohinter) {
+ force_autohinter = p_force_autohinter;
+ if (base_font.is_valid()) {
+ base_font->set_force_autohinter(force_autohinter);
}
+ emit_changed();
}
}
-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;
+bool SystemFont::is_force_autohinter() const {
+ return force_autohinter;
+}
+
+void SystemFont::set_hinting(TextServer::Hinting p_hinting) {
+ if (hinting != p_hinting) {
+ hinting = p_hinting;
+ if (base_font.is_valid()) {
+ base_font->set_hinting(hinting);
}
+ emit_changed();
}
- return Size2();
}
-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;
- }
+TextServer::Hinting SystemFont::get_hinting() const {
+ return hinting;
+}
- 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 SystemFont::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel) {
+ if (subpixel_positioning != p_subpixel) {
+ subpixel_positioning = p_subpixel;
+ if (base_font.is_valid()) {
+ base_font->set_subpixel_positioning(subpixel_positioning);
}
+ emit_changed();
}
- 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;
+TextServer::SubpixelPositioning SystemFont::get_subpixel_positioning() const {
+ return subpixel_positioning;
+}
+
+void SystemFont::set_oversampling(real_t p_oversampling) {
+ if (oversampling != p_oversampling) {
+ oversampling = p_oversampling;
+ if (base_font.is_valid()) {
+ base_font->set_oversampling(oversampling);
}
+ emit_changed();
}
- return false;
}
-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];
- }
+real_t SystemFont::get_oversampling() const {
+ return oversampling;
+}
+
+void SystemFont::set_font_names(const PackedStringArray &p_names) {
+ if (names != p_names) {
+ names = p_names;
+ _update_base_font();
+ }
+}
+
+PackedStringArray SystemFont::get_font_names() const {
+ return names;
+}
+
+void SystemFont::set_font_style(BitField<TextServer::FontStyle> p_style) {
+ if (style != p_style) {
+ style = p_style;
+ _update_base_font();
+ }
+}
+
+BitField<TextServer::FontStyle> SystemFont::get_font_style() const {
+ return style;
+}
+
+int SystemFont::get_spacing(TextServer::SpacingType p_spacing) const {
+ if (base_font.is_valid()) {
+ return base_font->get_spacing(p_spacing);
+ } else {
+ return 0;
+ }
+}
+
+RID SystemFont::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()) {
+ Dictionary var = p_variation_coordinates;
+ if (ftr_weight > 0 && !var.has(TS->name_to_tag("weight"))) {
+ var[TS->name_to_tag("weight")] = ftr_weight;
+ }
+ if (ftr_italic > 0 && !var.has(TS->name_to_tag("italic"))) {
+ var[TS->name_to_tag("italic")] = ftr_italic;
+ }
+
+ if (!face_indeces.is_empty()) {
+ int face_index = CLAMP(p_face_index, 0, face_indeces.size() - 1);
+ return f->find_variation(var, face_indeces[face_index], p_strength, p_transform);
+ } else {
+ return f->find_variation(var, 0, 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 SystemFont::_get_rid() const {
+ Ref<Font> f = _get_base_font_or_default();
+ if (f.is_valid()) {
+ if (!face_indeces.is_empty()) {
+ Dictionary var;
+ if (ftr_weight > 0) {
+ var[TS->name_to_tag("weight")] = ftr_weight;
+ }
+ if (ftr_italic > 0) {
+ var[TS->name_to_tag("italic")] = ftr_italic;
+ }
+ return f->find_variation(var, face_indeces[0]);
+ } else {
+ return f->_get_rid();
}
}
- return _rids;
+ return RID();
}
-void Font::update_changes() {
- emit_changed();
+int64_t SystemFont::get_face_count() const {
+ return face_indeces.size();
}
-Font::Font() {
- cache.set_capacity(128);
- cache_wrap.set_capacity(32);
+SystemFont::SystemFont() {
+ /* NOP */
}
-Font::~Font() {
- clear_data();
- cache.clear();
- cache_wrap.clear();
+SystemFont::~SystemFont() {
+ reset_state();
}
diff --git a/scene/resources/font.h b/scene/resources/font.h
index 950959e054..260b4e521f 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 BitField<TextServer::FontStyle> 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, BitField<TextServer::JustificationFlag> p_jst_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, BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_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_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), BitField<TextServer::JustificationFlag> p_jst_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), BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_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_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), BitField<TextServer::JustificationFlag> p_jst_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), BitField<TextServer::LineBreakFlag> p_brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, BitField<TextServer::JustificationFlag> p_jst_flags = 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_font_style(BitField<TextServer::FontStyle> p_style);
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_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_face_index(int p_cache_index, int64_t p_index);
+ virtual int64_t get_face_index(int p_cache_index) 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_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_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_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_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_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_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_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_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,140 @@ 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 Font : public Resource {
- GDCLASS(Font, Resource);
+class FontVariation : public Font {
+ GDCLASS(FontVariation, Font);
- // Shaped string cache.
- mutable LRUCache<uint64_t, Ref<TextLine>> cache;
- mutable LRUCache<uint64_t, Ref<TextParagraph>> cache_wrap;
+ struct Variation {
+ Dictionary opentype;
+ real_t embolden = 0.f;
+ int face_index = 0;
+ Transform2D transform;
+ };
- // 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;
+ 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;
- Dictionary get_feature_list() const;
+ virtual void set_variation_opentype(const Dictionary &p_coords);
+ virtual Dictionary get_variation_opentype() 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_embolden(float p_strength);
+ virtual float get_variation_embolden() const;
- // Font configuration.
- virtual void set_variation_coordinates(const Dictionary &p_variation_coordinates);
- virtual Dictionary get_variation_coordinates() const;
+ virtual void set_variation_transform(Transform2D p_transform);
+ virtual Transform2D get_variation_transform() const;
+
+ virtual void set_variation_face_index(int p_face_index);
+ virtual int get_variation_face_index() const;
+
+ virtual void set_opentype_features(const Dictionary &p_features);
+ virtual Dictionary get_opentype_features() const override;
virtual void set_spacing(TextServer::SpacingType p_spacing, int p_value);
- virtual int get_spacing(TextServer::SpacingType p_spacing) const;
+ virtual int get_spacing(TextServer::SpacingType p_spacing) const override;
- // 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;
+ // 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;
- // 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;
+ FontVariation();
+ ~FontVariation();
+};
- 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;
+/*************************************************************************/
+/* SystemFont */
+/*************************************************************************/
- // Helper functions.
- virtual bool has_char(char32_t p_char) const;
- virtual String get_supported_chars() const;
+class SystemFont : public Font {
+ GDCLASS(SystemFont, Font);
- // 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;
+ PackedStringArray names;
+ BitField<TextServer::FontStyle> style = 0;
- Array get_rids() const;
+ mutable Ref<Font> theme_font;
- void update_changes();
+ Ref<FontFile> base_font;
+ Vector<int> face_indeces;
+ int ftr_weight = 0;
+ int ftr_italic = 0;
- Font();
- ~Font();
+ bool antialiased = true;
+ bool mipmaps = false;
+ bool force_autohinter = false;
+ TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
+ TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
+ real_t oversampling = 0.f;
+
+protected:
+ static void _bind_methods();
+
+ virtual void _update_base_font();
+ virtual void _update_rids() const override;
+
+ virtual void reset_state() override;
+
+public:
+ virtual Ref<Font> _get_base_font_or_default() const;
+
+ virtual void set_antialiased(bool p_antialiased);
+ virtual bool is_antialiased() const;
+
+ virtual void set_generate_mipmaps(bool p_generate_mipmaps);
+ virtual bool get_generate_mipmaps() const;
+
+ virtual void set_force_autohinter(bool p_force_autohinter);
+ virtual bool is_force_autohinter() const;
+
+ virtual void set_hinting(TextServer::Hinting p_hinting);
+ virtual TextServer::Hinting get_hinting() const;
+
+ virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel);
+ virtual TextServer::SubpixelPositioning get_subpixel_positioning() const;
+
+ virtual void set_oversampling(real_t p_oversampling);
+ virtual real_t get_oversampling() const;
+
+ virtual void set_font_names(const PackedStringArray &p_names);
+ virtual PackedStringArray get_font_names() const;
+
+ virtual void set_font_style(BitField<TextServer::FontStyle> p_style);
+ virtual BitField<TextServer::FontStyle> get_font_style() const override;
+
+ virtual int get_spacing(TextServer::SpacingType p_spacing) const override;
+
+ 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;
+
+ int64_t get_face_count() const override;
+
+ SystemFont();
+ ~SystemFont();
};
-#endif /* FONT_H */
+#endif // FONT_H
diff --git a/scene/resources/gradient.h b/scene/resources/gradient.h
index 2b04ead0af..e4bac15e4b 100644
--- a/scene/resources/gradient.h
+++ b/scene/resources/gradient.h
@@ -157,10 +157,10 @@ public:
const Point &pointP3 = points[p3];
float x = (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset);
- float r = Math::cubic_interpolate(pointP0.color.r, pointFirst.color.r, pointSecond.color.r, pointP3.color.r, x);
- float g = Math::cubic_interpolate(pointP0.color.g, pointFirst.color.g, pointSecond.color.g, pointP3.color.g, x);
- float b = Math::cubic_interpolate(pointP0.color.b, pointFirst.color.b, pointSecond.color.b, pointP3.color.b, x);
- float a = Math::cubic_interpolate(pointP0.color.a, pointFirst.color.a, pointSecond.color.a, pointP3.color.a, x);
+ float r = Math::cubic_interpolate(pointFirst.color.r, pointSecond.color.r, pointP0.color.r, pointP3.color.r, x);
+ float g = Math::cubic_interpolate(pointFirst.color.g, pointSecond.color.g, pointP0.color.g, pointP3.color.g, x);
+ float b = Math::cubic_interpolate(pointFirst.color.b, pointSecond.color.b, pointP0.color.b, pointP3.color.b, x);
+ float a = Math::cubic_interpolate(pointFirst.color.a, pointSecond.color.a, pointP0.color.a, pointP3.color.a, x);
return Color(r, g, b, a);
} break;
diff --git a/scene/resources/height_map_shape_3d.h b/scene/resources/height_map_shape_3d.h
index 79d1b15674..633238030b 100644
--- a/scene/resources/height_map_shape_3d.h
+++ b/scene/resources/height_map_shape_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef HEIGHT_MAP_SHAPE_H
-#define HEIGHT_MAP_SHAPE_H
+#ifndef HEIGHT_MAP_SHAPE_3D_H
+#define HEIGHT_MAP_SHAPE_3D_H
#include "scene/resources/shape_3d.h"
@@ -60,4 +60,4 @@ public:
HeightMapShape3D();
};
-#endif /* !HEIGHT_MAP_SHAPE_H */
+#endif // HEIGHT_MAP_SHAPE_3D_H
diff --git a/scene/resources/immediate_mesh.h b/scene/resources/immediate_mesh.h
index e5f627ae8e..de10fdbfbe 100644
--- a/scene/resources/immediate_mesh.h
+++ b/scene/resources/immediate_mesh.h
@@ -115,4 +115,4 @@ public:
~ImmediateMesh();
};
-#endif // IMMEDIATEMESH_H
+#endif // IMMEDIATE_MESH_H
diff --git a/scene/resources/importer_mesh.h b/scene/resources/importer_mesh.h
index 8f77597a58..bf1d0301d1 100644
--- a/scene/resources/importer_mesh.h
+++ b/scene/resources/importer_mesh.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SCENE_IMPORTER_MESH_H
-#define SCENE_IMPORTER_MESH_H
+#ifndef IMPORTER_MESH_H
+#define IMPORTER_MESH_H
#include "core/io/resource.h"
#include "core/templates/local_vector.h"
@@ -130,4 +130,5 @@ public:
Ref<ArrayMesh> get_mesh(const Ref<ArrayMesh> &p_base = Ref<ArrayMesh>());
void clear();
};
-#endif // SCENE_IMPORTER_MESH_H
+
+#endif // IMPORTER_MESH_H
diff --git a/scene/resources/label_settings.cpp b/scene/resources/label_settings.cpp
new file mode 100644
index 0000000000..ef380a68f9
--- /dev/null
+++ b/scene/resources/label_settings.cpp
@@ -0,0 +1,187 @@
+/*************************************************************************/
+/* label_settings.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 "label_settings.h"
+
+#include "core/core_string_names.h"
+
+void LabelSettings::_font_changed() {
+ emit_changed();
+}
+
+void LabelSettings::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_line_spacing", "spacing"), &LabelSettings::set_line_spacing);
+ ClassDB::bind_method(D_METHOD("get_line_spacing"), &LabelSettings::get_line_spacing);
+
+ ClassDB::bind_method(D_METHOD("set_font", "font"), &LabelSettings::set_font);
+ ClassDB::bind_method(D_METHOD("get_font"), &LabelSettings::get_font);
+
+ ClassDB::bind_method(D_METHOD("set_font_size", "size"), &LabelSettings::set_font_size);
+ ClassDB::bind_method(D_METHOD("get_font_size"), &LabelSettings::get_font_size);
+
+ ClassDB::bind_method(D_METHOD("set_font_color", "color"), &LabelSettings::set_font_color);
+ ClassDB::bind_method(D_METHOD("get_font_color"), &LabelSettings::get_font_color);
+
+ ClassDB::bind_method(D_METHOD("set_outline_size", "size"), &LabelSettings::set_outline_size);
+ ClassDB::bind_method(D_METHOD("get_outline_size"), &LabelSettings::get_outline_size);
+
+ ClassDB::bind_method(D_METHOD("set_outline_color", "color"), &LabelSettings::set_outline_color);
+ ClassDB::bind_method(D_METHOD("get_outline_color"), &LabelSettings::get_outline_color);
+
+ ClassDB::bind_method(D_METHOD("set_shadow_size", "size"), &LabelSettings::set_shadow_size);
+ ClassDB::bind_method(D_METHOD("get_shadow_size"), &LabelSettings::get_shadow_size);
+
+ ClassDB::bind_method(D_METHOD("set_shadow_color", "color"), &LabelSettings::set_shadow_color);
+ ClassDB::bind_method(D_METHOD("get_shadow_color"), &LabelSettings::get_shadow_color);
+
+ ClassDB::bind_method(D_METHOD("set_shadow_offset", "offset"), &LabelSettings::set_shadow_offset);
+ ClassDB::bind_method(D_METHOD("get_shadow_offset"), &LabelSettings::get_shadow_offset);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing");
+
+ ADD_GROUP("Font", "font");
+ 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,1024,1,or_greater,suffix:px"), "set_font_size", "get_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "font_color"), "set_font_color", "get_font_color");
+
+ ADD_GROUP("Outline", "outline");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1,or_greater,suffix:px"), "set_outline_size", "get_outline_size");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_color"), "set_outline_color", "get_outline_color");
+
+ ADD_GROUP("Shadow", "shadow");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size", PROPERTY_HINT_RANGE, "0,127,1,or_greater,suffix:px"), "set_shadow_size", "get_shadow_size");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shadow_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_shadow_offset", "get_shadow_offset");
+}
+
+void LabelSettings::set_line_spacing(real_t p_spacing) {
+ if (line_spacing != p_spacing) {
+ line_spacing = p_spacing;
+ emit_changed();
+ }
+}
+
+real_t LabelSettings::get_line_spacing() const {
+ return line_spacing;
+}
+
+void LabelSettings::set_font(const Ref<Font> &p_font) {
+ if (font != p_font) {
+ if (font.is_valid()) {
+ font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &LabelSettings::_font_changed));
+ }
+ font = p_font;
+ if (font.is_valid()) {
+ font->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &LabelSettings::_font_changed), CONNECT_REFERENCE_COUNTED);
+ }
+ emit_changed();
+ }
+}
+
+Ref<Font> LabelSettings::get_font() const {
+ return font;
+}
+
+void LabelSettings::set_font_size(int p_size) {
+ if (font_size != p_size) {
+ font_size = p_size;
+ emit_changed();
+ }
+}
+
+int LabelSettings::get_font_size() const {
+ return font_size;
+}
+
+void LabelSettings::set_font_color(const Color &p_color) {
+ if (font_color != p_color) {
+ font_color = p_color;
+ emit_changed();
+ }
+}
+
+Color LabelSettings::get_font_color() const {
+ return font_color;
+}
+
+void LabelSettings::set_outline_size(int p_size) {
+ if (outline_size != p_size) {
+ outline_size = p_size;
+ emit_changed();
+ }
+}
+
+int LabelSettings::get_outline_size() const {
+ return outline_size;
+}
+
+void LabelSettings::set_outline_color(const Color &p_color) {
+ if (outline_color != p_color) {
+ outline_color = p_color;
+ emit_changed();
+ }
+}
+
+Color LabelSettings::get_outline_color() const {
+ return outline_color;
+}
+
+void LabelSettings::set_shadow_size(int p_size) {
+ if (shadow_size != p_size) {
+ shadow_size = p_size;
+ emit_changed();
+ }
+}
+
+int LabelSettings::get_shadow_size() const {
+ return shadow_size;
+}
+
+void LabelSettings::set_shadow_color(const Color &p_color) {
+ if (shadow_color != p_color) {
+ shadow_color = p_color;
+ emit_changed();
+ }
+}
+
+Color LabelSettings::get_shadow_color() const {
+ return shadow_color;
+}
+
+void LabelSettings::set_shadow_offset(const Vector2 &p_offset) {
+ if (shadow_offset != p_offset) {
+ shadow_offset = p_offset;
+ emit_changed();
+ }
+}
+
+Vector2 LabelSettings::get_shadow_offset() const {
+ return shadow_offset;
+}
diff --git a/editor/plugins/font_editor_plugin.h b/scene/resources/label_settings.h
index 3f0700d880..062d499d50 100644
--- a/editor/plugins/font_editor_plugin.h
+++ b/scene/resources/label_settings.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* font_editor_plugin.h */
+/* label_settings.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,50 +28,62 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef FONT_EDITOR_PLUGIN_H
-#define FONT_EDITOR_PLUGIN_H
+#ifndef LABEL_SETTINGS_H
+#define LABEL_SETTINGS_H
-#include "editor/editor_plugin.h"
-#include "scene/resources/font.h"
-#include "scene/resources/text_line.h"
+#include "core/io/resource.h"
+#include "font.h"
-class FontDataPreview : public Control {
- GDCLASS(FontDataPreview, Control);
+/*************************************************************************/
-protected:
- void _notification(int p_what);
- static void _bind_methods();
+class LabelSettings : public Resource {
+ GDCLASS(LabelSettings, Resource);
- Ref<TextLine> line;
+ real_t line_spacing = 3;
-public:
- virtual Size2 get_minimum_size() const override;
+ Ref<Font> font;
+ int font_size = Font::DEFAULT_FONT_SIZE;
+ Color font_color = Color(1, 1, 1);
- void set_data(const Ref<FontData> &p_data);
+ int outline_size = 0;
+ Color outline_color = Color(1, 1, 1);
- FontDataPreview();
-};
+ int shadow_size = 1;
+ Color shadow_color = Color(0, 0, 0, 0);
+ Vector2 shadow_offset = Vector2(1, 1);
-/*************************************************************************/
+ void _font_changed();
-class EditorInspectorPluginFont : public EditorInspectorPlugin {
- GDCLASS(EditorInspectorPluginFont, EditorInspectorPlugin);
+protected:
+ static void _bind_methods();
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;
-};
+ void set_line_spacing(real_t p_spacing);
+ real_t get_line_spacing() const;
-/*************************************************************************/
+ void set_font(const Ref<Font> &p_font);
+ Ref<Font> get_font() const;
-class FontEditorPlugin : public EditorPlugin {
- GDCLASS(FontEditorPlugin, EditorPlugin);
+ void set_font_size(int p_size);
+ int get_font_size() const;
-public:
- FontEditorPlugin();
+ void set_font_color(const Color &p_color);
+ Color get_font_color() const;
+
+ void set_outline_size(int p_size);
+ int get_outline_size() const;
+
+ void set_outline_color(const Color &p_color);
+ Color get_outline_color() const;
+
+ void set_shadow_size(int p_size);
+ int get_shadow_size() const;
+
+ void set_shadow_color(const Color &p_color);
+ Color get_shadow_color() const;
- virtual String get_name() const override { return "Font"; }
+ void set_shadow_offset(const Vector2 &p_offset);
+ Vector2 get_shadow_offset() const;
};
-#endif // FONT_EDITOR_PLUGIN_H
+#endif // LABEL_SETTINGS_H
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index b7a3b677f5..55356c2058 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -154,18 +154,18 @@ Material::~Material() {
bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) {
if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
+ StringName pr = shader->remap_uniform(p_name);
if (!pr) {
String n = p_name;
if (n.find("param/") == 0) { //backwards compatibility
pr = n.substr(6, n.length());
}
- if (n.find("shader_param/") == 0) { //backwards compatibility
- pr = n.replace_first("shader_param/", "");
+ if (n.find("shader_uniform/") == 0) { //backwards compatibility
+ pr = n.replace_first("shader_uniform/", "");
}
}
if (pr) {
- set_shader_param(pr, p_value);
+ set_shader_uniform(pr, p_value);
return true;
}
}
@@ -175,14 +175,14 @@ bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) {
bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const {
if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
+ StringName pr = shader->remap_uniform(p_name);
if (!pr) {
String n = p_name;
if (n.find("param/") == 0) { //backwards compatibility
pr = n.substr(6, n.length());
}
- if (n.find("shader_param/") == 0) { //backwards compatibility
- pr = n.replace_first("shader_param/", "");
+ if (n.find("shader_uniform/") == 0) { //backwards compatibility
+ pr = n.replace_first("shader_uniform/", "");
}
}
@@ -202,13 +202,104 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const {
void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const {
if (!shader.is_null()) {
- shader->get_param_list(p_list);
+ List<PropertyInfo> list;
+ shader->get_shader_uniform_list(&list, true);
+
+ HashMap<String, HashMap<String, List<PropertyInfo>>> groups;
+ {
+ HashMap<String, List<PropertyInfo>> none_subgroup;
+ none_subgroup.insert("<None>", List<PropertyInfo>());
+ groups.insert("<None>", none_subgroup);
+ }
+
+ String last_group = "<None>";
+ String last_subgroup = "<None>";
+
+ bool is_none_group_undefined = true;
+ bool is_none_group = true;
+
+ for (List<PropertyInfo>::Element *E = list.front(); E; E = E->next()) {
+ if (E->get().usage == PROPERTY_USAGE_GROUP) {
+ if (!E->get().name.is_empty()) {
+ Vector<String> vgroup = E->get().name.split("::");
+ last_group = vgroup[0];
+ if (vgroup.size() > 1) {
+ last_subgroup = vgroup[1];
+ } else {
+ last_subgroup = "<None>";
+ }
+ is_none_group = false;
+
+ if (!groups.has(last_group)) {
+ PropertyInfo info;
+ info.usage = PROPERTY_USAGE_GROUP;
+ info.name = last_group;
+
+ List<PropertyInfo> none_subgroup;
+ none_subgroup.push_back(info);
+
+ HashMap<String, List<PropertyInfo>> subgroup_map;
+ subgroup_map.insert("<None>", none_subgroup);
+
+ groups.insert(last_group, subgroup_map);
+ }
+
+ if (!groups[last_group].has(last_subgroup)) {
+ PropertyInfo info;
+ info.usage = PROPERTY_USAGE_SUBGROUP;
+ info.name = last_subgroup;
+
+ List<PropertyInfo> subgroup;
+ subgroup.push_back(info);
+
+ groups[last_group].insert(last_subgroup, subgroup);
+ }
+ } else {
+ last_group = "<None>";
+ last_subgroup = "<None>";
+ is_none_group = true;
+ }
+ continue; // Pass group.
+ }
+
+ if (is_none_group_undefined && is_none_group) {
+ is_none_group_undefined = false;
+
+ PropertyInfo info;
+ info.usage = PROPERTY_USAGE_GROUP;
+ info.name = "Shader Param";
+ groups["<None>"]["<None>"].push_back(info);
+ }
+
+ PropertyInfo info = E->get();
+ info.name = info.name;
+ groups[last_group][last_subgroup].push_back(info);
+ }
+
+ // Sort groups alphabetically.
+ List<UniformProp> props;
+ for (HashMap<String, HashMap<String, List<PropertyInfo>>>::Iterator group = groups.begin(); group; ++group) {
+ for (HashMap<String, List<PropertyInfo>>::Iterator subgroup = group->value.begin(); subgroup; ++subgroup) {
+ for (List<PropertyInfo>::Element *item = subgroup->value.front(); item; item = item->next()) {
+ if (subgroup->key == "<None>") {
+ props.push_back({ group->key, item->get() });
+ } else {
+ props.push_back({ group->key + "::" + subgroup->key, item->get() });
+ }
+ }
+ }
+ }
+ props.sort_custom<UniformPropComparator>();
+
+ for (List<UniformProp>::Element *E = props.front(); E; E = E->next()) {
+ p_list->push_back(E->get().info);
+ }
}
}
bool ShaderMaterial::property_can_revert(const String &p_name) {
if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
+ StringName pr = shader->remap_uniform(p_name);
if (pr) {
Variant default_value = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr);
Variant current_value;
@@ -222,7 +313,7 @@ bool ShaderMaterial::property_can_revert(const String &p_name) {
Variant ShaderMaterial::property_get_revert(const String &p_name) {
Variant r_ret;
if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
+ StringName pr = shader->remap_uniform(p_name);
if (pr) {
r_ret = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr);
}
@@ -258,7 +349,7 @@ Ref<Shader> ShaderMaterial::get_shader() const {
return shader;
}
-void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) {
+void ShaderMaterial::set_shader_uniform(const StringName &p_param, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
param_cache.erase(p_param);
RS::get_singleton()->material_set_param(_get_material(), p_param, Variant());
@@ -278,7 +369,7 @@ void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &
}
}
-Variant ShaderMaterial::get_shader_param(const StringName &p_param) const {
+Variant ShaderMaterial::get_shader_uniform(const StringName &p_param) const {
if (param_cache.has(p_param)) {
return param_cache[p_param];
} else {
@@ -293,8 +384,8 @@ void ShaderMaterial::_shader_changed() {
void ShaderMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shader", "shader"), &ShaderMaterial::set_shader);
ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader);
- ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &ShaderMaterial::set_shader_param);
- ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &ShaderMaterial::get_shader_param);
+ ClassDB::bind_method(D_METHOD("set_shader_uniform", "param", "value"), &ShaderMaterial::set_shader_uniform);
+ ClassDB::bind_method(D_METHOD("get_shader_uniform", "param"), &ShaderMaterial::get_shader_uniform);
ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ShaderMaterial::property_can_revert);
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ShaderMaterial::property_get_revert);
@@ -303,12 +394,12 @@ void ShaderMaterial::_bind_methods() {
void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
String f = p_function.operator String();
- if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) {
+ if ((f == "get_shader_uniform" || f == "set_shader_uniform") && p_idx == 0) {
if (shader.is_valid()) {
List<PropertyInfo> pl;
- shader->get_param_list(&pl);
+ shader->get_shader_uniform_list(&pl);
for (const PropertyInfo &E : pl) {
- r_options->push_back(E.name.replace_first("shader_param/", "").quote());
+ r_options->push_back(E.name.replace_first("shader_uniform/", "").quote());
}
}
}
@@ -976,7 +1067,8 @@ void BaseMaterial3D::_update_shader() {
code += " float num_layers = mix(float(heightmap_max_layers),float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n";
code += " float layer_depth = 1.0 / num_layers;\n";
code += " float current_layer_depth = 0.0;\n";
- code += " vec2 P = view_dir.xy * heightmap_scale;\n";
+ // Multiply the heightmap scale by 0.01 to improve heightmap scale usability.
+ code += " vec2 P = view_dir.xy * heightmap_scale * 0.01;\n";
code += " vec2 delta = P / num_layers;\n";
code += " vec2 ofs = base_uv;\n";
if (flags[FLAG_INVERT_HEIGHTMAP]) {
@@ -1012,7 +1104,8 @@ void BaseMaterial3D::_update_shader() {
}
// Use offset limiting to improve the appearance of non-deep parallax.
// This reduces the impression of depth, but avoids visible warping in the distance.
- code += " vec2 ofs = base_uv - view_dir.xy * depth * heightmap_scale;\n";
+ // Multiply the heightmap scale by 0.01 to improve heightmap scale usability.
+ code += " vec2 ofs = base_uv - view_dir.xy * depth * heightmap_scale * 0.01;\n";
}
code += " base_uv=ofs;\n";
@@ -1185,38 +1278,21 @@ void BaseMaterial3D::_update_shader() {
if ((distance_fade == DISTANCE_FADE_OBJECT_DITHER || distance_fade == DISTANCE_FADE_PIXEL_DITHER)) {
if (!RenderingServer::get_singleton()->is_low_end()) {
code += " {\n";
+
if (distance_fade == DISTANCE_FADE_OBJECT_DITHER) {
code += " float fade_distance = abs((VIEW_MATRIX * MODEL_MATRIX[3]).z);\n";
} else {
- code += " float fade_distance=-VERTEX.z;\n";
+ code += " float fade_distance = -VERTEX.z;\n";
}
+ // Use interleaved gradient noise, which is fast but still looks good.
+ code += " const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);";
+ code += " float fade = clamp(smoothstep(distance_fade_min, distance_fade_max, fade_distance), 0.0, 1.0);\n";
+ // Use a hard cap to prevent a few stray pixels from remaining when past the fade-out distance.
+ code += " if (fade < 0.001 || fade < fract(magic.z * fract(dot(FRAGCOORD.xy, magic.xy)))) {\n";
+ code += " discard;\n";
+ code += " }\n";
- code += " float fade=clamp(smoothstep(distance_fade_min,distance_fade_max,fade_distance),0.0,1.0);\n";
- code += " int x = int(FRAGCOORD.x) % 4;\n";
- code += " int y = int(FRAGCOORD.y) % 4;\n";
- code += " int index = x + y * 4;\n";
- code += " float limit = 0.0;\n\n";
- code += " if (x < 8) {\n";
- code += " if (index == 0) limit = 0.0625;\n";
- code += " if (index == 1) limit = 0.5625;\n";
- code += " if (index == 2) limit = 0.1875;\n";
- code += " if (index == 3) limit = 0.6875;\n";
- code += " if (index == 4) limit = 0.8125;\n";
- code += " if (index == 5) limit = 0.3125;\n";
- code += " if (index == 6) limit = 0.9375;\n";
- code += " if (index == 7) limit = 0.4375;\n";
- code += " if (index == 8) limit = 0.25;\n";
- code += " if (index == 9) limit = 0.75;\n";
- code += " if (index == 10) limit = 0.125;\n";
- code += " if (index == 11) limit = 0.625;\n";
- code += " if (index == 12) limit = 1.0;\n";
- code += " if (index == 13) limit = 0.5;\n";
- code += " if (index == 14) limit = 0.875;\n";
- code += " if (index == 15) limit = 0.375;\n";
- code += " }\n\n";
- code += " if (fade < limit)\n";
- code += " discard;\n";
code += " }\n\n";
}
@@ -1702,12 +1778,21 @@ void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) {
}
flags[p_flag] = p_enabled;
- if (p_flag == FLAG_USE_SHADOW_TO_OPACITY || p_flag == FLAG_USE_TEXTURE_REPEAT || p_flag == FLAG_SUBSURFACE_MODE_SKIN || p_flag == FLAG_USE_POINT_SIZE) {
+
+ if (
+ p_flag == FLAG_USE_SHADOW_TO_OPACITY ||
+ p_flag == FLAG_USE_TEXTURE_REPEAT ||
+ p_flag == FLAG_SUBSURFACE_MODE_SKIN ||
+ p_flag == FLAG_USE_POINT_SIZE ||
+ p_flag == FLAG_UV1_USE_TRIPLANAR ||
+ p_flag == FLAG_UV2_USE_TRIPLANAR) {
notify_property_list_changed();
}
+
if (p_flag == FLAG_PARTICLE_TRAILS_MODE) {
update_configuration_warning();
}
+
_queue_shader_change();
}
@@ -1833,6 +1918,14 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NO_EDITOR;
}
+ if ((property.name == "uv1_triplanar_sharpness" || property.name == "uv1_world_triplanar") && !flags[FLAG_UV1_USE_TRIPLANAR]) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+
+ if ((property.name == "uv2_triplanar_sharpness" || property.name == "uv2_world_triplanar") && !flags[FLAG_UV2_USE_TRIPLANAR]) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+
// you can only enable anti-aliasing (in materials) on alpha scissor and alpha hash
const bool can_select_aa = (transparency == TRANSPARENCY_ALPHA_SCISSOR || transparency == TRANSPARENCY_ALPHA_HASH);
// alpha anti aliasiasing is only enabled when you can select aa
@@ -2546,7 +2639,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_GROUP("Transparency", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth Pre-Pass"), "set_transparency", "get_transparency");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge");
@@ -2593,7 +2686,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_on_uv2"), "set_flag", "get_flag", FLAG_EMISSION_ON_UV2);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_EMISSION);
- ADD_GROUP("NormalMap", "normal_");
+ ADD_GROUP("Normal Map", "normal_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "normal_enabled"), "set_feature", "get_feature", FEATURE_NORMAL_MAPPING);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_NORMAL);
@@ -2633,7 +2726,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "heightmap_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_HEIGHTMAP);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "heightmap_flip_texture"), "set_flag", "get_flag", FLAG_INVERT_HEIGHTMAP);
- ADD_GROUP("Subsurf Scatter", "subsurf_scatter_");
+ ADD_GROUP("Subsurface Scattering", "subsurf_scatter_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURFACE_SCATTERING);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_skin_mode"), "set_flag", "get_flag", FLAG_SUBSURFACE_MODE_SKIN);
@@ -2857,7 +2950,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_clearcoat(1);
set_clearcoat_roughness(0.5);
set_anisotropy(0);
- set_heightmap_scale(0.05);
+ set_heightmap_scale(5.0);
set_subsurface_scattering_strength(0);
set_backlight(Color(0, 0, 0));
set_transmittance_color(Color(1, 1, 1, 1));
@@ -2878,7 +2971,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_transparency(TRANSPARENCY_DISABLED);
set_alpha_antialiasing(ALPHA_ANTIALIASING_OFF);
- set_alpha_scissor_threshold(0.05);
+ set_alpha_scissor_threshold(0.5);
set_alpha_hash_scale(1.0);
set_alpha_antialiasing_edge(0.3);
diff --git a/scene/resources/material.h b/scene/resources/material.h
index b845fd68c8..ca5b17dd07 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -84,6 +84,17 @@ class ShaderMaterial : public Material {
HashMap<StringName, Variant> param_cache;
+ struct UniformProp {
+ String str;
+ PropertyInfo info;
+ };
+
+ struct UniformPropComparator {
+ bool operator()(const UniformProp &p_a, const UniformProp &p_b) const {
+ return p_a.str.naturalnocasecmp_to(p_b.str) < 0;
+ }
+ };
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -104,8 +115,8 @@ public:
void set_shader(const Ref<Shader> &p_shader);
Ref<Shader> get_shader() const;
- void set_shader_param(const StringName &p_param, const Variant &p_value);
- Variant get_shader_param(const StringName &p_param) const;
+ void set_shader_uniform(const StringName &p_param, const Variant &p_value);
+ Variant get_shader_uniform(const StringName &p_param) const;
virtual Shader::Mode get_shader_mode() const override;
@@ -809,4 +820,4 @@ public:
//////////////////////
-#endif
+#endif // MATERIAL_H
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 3e7b0a2808..ec9db89794 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -260,6 +260,64 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
return triangle_mesh;
}
+Ref<TriangleMesh> Mesh::generate_surface_triangle_mesh(int p_surface) const {
+ ERR_FAIL_INDEX_V(p_surface, get_surface_count(), Ref<TriangleMesh>());
+
+ if (surface_triangle_meshes.size() != get_surface_count()) {
+ surface_triangle_meshes.resize(get_surface_count());
+ }
+
+ if (surface_triangle_meshes[p_surface].is_valid()) {
+ return surface_triangle_meshes[p_surface];
+ }
+
+ int facecount = 0;
+
+ if (surface_get_primitive_type(p_surface) != PRIMITIVE_TRIANGLES) {
+ return Ref<TriangleMesh>();
+ }
+
+ if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) {
+ facecount += surface_get_array_index_len(p_surface);
+ } else {
+ facecount += surface_get_array_len(p_surface);
+ }
+
+ Vector<Vector3> faces;
+ faces.resize(facecount);
+ Vector3 *facesw = faces.ptrw();
+
+ Array a = surface_get_arrays(p_surface);
+ ERR_FAIL_COND_V(a.is_empty(), Ref<TriangleMesh>());
+
+ int vc = surface_get_array_len(p_surface);
+ Vector<Vector3> vertices = a[ARRAY_VERTEX];
+ const Vector3 *vr = vertices.ptr();
+ int widx = 0;
+
+ if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) {
+ int ic = surface_get_array_index_len(p_surface);
+ Vector<int> indices = a[ARRAY_INDEX];
+ const int *ir = indices.ptr();
+
+ for (int j = 0; j < ic; j++) {
+ int index = ir[j];
+ facesw[widx++] = vr[index];
+ }
+
+ } else {
+ for (int j = 0; j < vc; j++) {
+ facesw[widx++] = vr[j];
+ }
+ }
+
+ Ref<TriangleMesh> triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh));
+ triangle_mesh->create(faces);
+ surface_triangle_meshes.set(p_surface, triangle_mesh);
+
+ return triangle_mesh;
+}
+
void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) {
if (debug_lines.size() > 0) {
r_lines = debug_lines;
@@ -320,6 +378,14 @@ Vector<Face3> Mesh::get_faces() const {
return Vector<Face3>();
}
+Vector<Face3> Mesh::get_surface_faces(int p_surface) const {
+ Ref<TriangleMesh> tm = generate_surface_triangle_mesh(p_surface);
+ if (tm.is_valid()) {
+ return tm->get_faces();
+ }
+ return Vector<Face3>();
+}
+
Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
if (p_simplify) {
ConvexDecompositionSettings settings;
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index b166d12ead..142373ce7f 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -42,6 +42,7 @@ class Mesh : public Resource {
GDCLASS(Mesh, Resource);
mutable Ref<TriangleMesh> triangle_mesh; //cached
+ mutable Vector<Ref<TriangleMesh>> surface_triangle_meshes; //cached
mutable Vector<Vector3> debug_lines;
Size2i lightmap_size_hint;
@@ -161,7 +162,9 @@ public:
virtual AABB get_aabb() const;
Vector<Face3> get_faces() const;
+ Vector<Face3> get_surface_faces(int p_surface) const;
Ref<TriangleMesh> generate_triangle_mesh() const;
+ Ref<TriangleMesh> generate_surface_triangle_mesh(int p_surface) const;
void generate_debug_mesh_lines(Vector<Vector3> &r_lines);
void generate_debug_mesh_indices(Vector<Vector3> &r_points);
@@ -362,4 +365,4 @@ public:
~PlaceholderMesh();
};
-#endif
+#endif // MESH_H
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index c8bfb73b2d..2d3f9d9afc 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -107,7 +107,7 @@ void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::ARRAY, name + PNAME("shapes")));
p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("navmesh"), PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"));
p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, name + PNAME("navmesh_transform"), PROPERTY_HINT_NONE, "suffix:m"));
- p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("preview"), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_HELPER));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("preview"), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT));
}
}
diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h
index 30ada5365f..0f8cc76173 100644
--- a/scene/resources/multimesh.h
+++ b/scene/resources/multimesh.h
@@ -113,4 +113,4 @@ public:
VARIANT_ENUM_CAST(MultiMesh::TransformFormat);
-#endif // MULTI_MESH_H
+#endif // MULTIMESH_H
diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp
index a808ead66b..ac5493efdc 100644
--- a/scene/resources/navigation_mesh.cpp
+++ b/scene/resources/navigation_mesh.cpp
@@ -30,6 +30,10 @@
#include "navigation_mesh.h"
+#ifdef DEBUG_ENABLED
+#include "servers/navigation_server_3d.h"
+#endif
+
void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) {
ERR_FAIL_COND(p_mesh.is_null());
@@ -337,6 +341,7 @@ void NavigationMesh::clear_polygons() {
polygons.clear();
}
+#ifndef DISABLE_DEPRECATED
Ref<Mesh> NavigationMesh::get_debug_mesh() {
if (debug_mesh.is_valid()) {
return debug_mesh;
@@ -420,6 +425,102 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() {
return debug_mesh;
}
+#endif // DISABLE_DEPRECATED
+
+#ifdef DEBUG_ENABLED
+Ref<ArrayMesh> NavigationMesh::_get_debug_mesh() {
+ if (debug_mesh.is_valid()) {
+ // Blocks further updates for now, code below is intended for dynamic updates e.g. when settings change.
+ return debug_mesh;
+ }
+
+ if (!debug_mesh.is_valid()) {
+ debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
+ } else {
+ debug_mesh->clear_surfaces();
+ }
+
+ if (vertices.size() == 0) {
+ return debug_mesh;
+ }
+
+ int polygon_count = get_polygon_count();
+
+ if (polygon_count < 1) {
+ // no face, no play
+ return debug_mesh;
+ }
+
+ // build geometry face surface
+ Vector<Vector3> face_vertex_array;
+ face_vertex_array.resize(polygon_count * 3);
+
+ for (int i = 0; i < polygon_count; i++) {
+ Vector<int> polygon = get_polygon(i);
+
+ face_vertex_array.push_back(vertices[polygon[0]]);
+ face_vertex_array.push_back(vertices[polygon[1]]);
+ face_vertex_array.push_back(vertices[polygon[2]]);
+ }
+
+ Array face_mesh_array;
+ face_mesh_array.resize(Mesh::ARRAY_MAX);
+ face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array;
+
+ // if enabled add vertex colors to colorize each face individually
+ bool enabled_geometry_face_random_color = NavigationServer3D::get_singleton()->get_debug_navigation_enable_geometry_face_random_color();
+ if (enabled_geometry_face_random_color) {
+ Color debug_navigation_geometry_face_color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color();
+ Color polygon_color = debug_navigation_geometry_face_color;
+
+ Vector<Color> face_color_array;
+ face_color_array.resize(polygon_count * 3);
+
+ for (int i = 0; i < polygon_count; i++) {
+ polygon_color = debug_navigation_geometry_face_color * (Color(Math::randf(), Math::randf(), Math::randf()));
+
+ Vector<int> polygon = get_polygon(i);
+
+ face_color_array.push_back(polygon_color);
+ face_color_array.push_back(polygon_color);
+ face_color_array.push_back(polygon_color);
+ }
+ face_mesh_array[Mesh::ARRAY_COLOR] = face_color_array;
+ }
+
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array);
+ Ref<StandardMaterial3D> debug_geometry_face_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_material();
+ debug_mesh->surface_set_material(debug_mesh->get_surface_count(), debug_geometry_face_material);
+
+ // if enabled build geometry edge line surface
+ bool enabled_edge_lines = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines();
+
+ if (enabled_edge_lines) {
+ Vector<Vector3> line_vertex_array;
+ line_vertex_array.resize(polygon_count * 6);
+
+ for (int i = 0; i < polygon_count; i++) {
+ Vector<int> polygon = get_polygon(i);
+
+ line_vertex_array.push_back(vertices[polygon[0]]);
+ line_vertex_array.push_back(vertices[polygon[1]]);
+ line_vertex_array.push_back(vertices[polygon[1]]);
+ line_vertex_array.push_back(vertices[polygon[2]]);
+ line_vertex_array.push_back(vertices[polygon[2]]);
+ line_vertex_array.push_back(vertices[polygon[0]]);
+ }
+
+ Array line_mesh_array;
+ line_mesh_array.resize(Mesh::ARRAY_MAX);
+ line_mesh_array[Mesh::ARRAY_VERTEX] = line_vertex_array;
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, line_mesh_array);
+ Ref<StandardMaterial3D> debug_geometry_edge_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_material();
+ debug_mesh->surface_set_material(debug_mesh->get_surface_count(), debug_geometry_edge_material);
+ }
+
+ return debug_mesh;
+}
+#endif
void NavigationMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationMesh::set_sample_partition_type);
diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h
index 40b275c792..79d8962d24 100644
--- a/scene/resources/navigation_mesh.h
+++ b/scene/resources/navigation_mesh.h
@@ -204,7 +204,11 @@ public:
Vector<int> get_polygon(int p_idx);
void clear_polygons();
+#ifndef DISABLE_DEPRECATED
Ref<Mesh> get_debug_mesh();
+#endif // DISABLE_DEPRECATED
+
+ Ref<ArrayMesh> _get_debug_mesh();
NavigationMesh();
};
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 2c58aa83a9..ac67e6e5e9 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -434,10 +434,10 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
for (int j = 0; j < binds.size(); j++) {
argptrs[j] = &binds[j];
}
- callable = callable.bind(argptrs, binds.size());
+ callable = callable.bindp(argptrs, binds.size());
}
- cfrom->connect(snames[c.signal], callable, varray(), CONNECT_PERSIST | c.flags);
+ cfrom->connect(snames[c.signal], callable, CONNECT_PERSIST | c.flags);
}
//Node *s = ret_nodes[0];
@@ -892,9 +892,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, HashMap<String
cd.signal = _nm_get_string(c.signal.get_name(), name_map);
cd.flags = c.flags;
cd.unbinds = unbinds;
- for (int i = 0; i < c.binds.size(); i++) { // TODO: This could be removed now.
- cd.binds.push_back(_vm_get_variant(c.binds[i], variant_map));
- }
+
for (int i = 0; i < binds.size(); i++) {
cd.binds.push_back(_vm_get_variant(binds[i], variant_map));
}
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index 5f8001c871..8e1a1d29b6 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -249,4 +249,4 @@ public:
VARIANT_ENUM_CAST(PackedScene::GenEditState)
-#endif // SCENE_PRELOADER_H
+#endif // PACKED_SCENE_H
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index 7a49b9b515..4b2e029f47 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -98,6 +98,17 @@ void ParticlesMaterial::init_shaders() {
shader_names->emission_ring_radius = "emission_ring_radius";
shader_names->emission_ring_inner_radius = "emission_ring_inner_radius";
+ shader_names->turbulence_enabled = "turbulence_enabled";
+ shader_names->turbulence_noise_strength = "turbulence_noise_strength";
+ shader_names->turbulence_noise_scale = "turbulence_noise_scale";
+ shader_names->turbulence_noise_speed = "turbulence_noise_speed";
+ shader_names->turbulence_noise_speed_random = "turbulence_noise_speed_random";
+ shader_names->turbulence_influence_over_life = "turbulence_influence_over_life";
+ shader_names->turbulence_influence_min = "turbulence_influence_min";
+ shader_names->turbulence_influence_max = "turbulence_influence_max";
+ shader_names->turbulence_initial_displacement_min = "turbulence_initial_displacement_min";
+ shader_names->turbulence_initial_displacement_max = "turbulence_initial_displacement_max";
+
shader_names->gravity = "gravity";
shader_names->lifetime_randomness = "lifetime_randomness";
@@ -141,7 +152,6 @@ void ParticlesMaterial::_update_shader() {
shader_map[mk].users++;
return;
}
-
//must create a shader!
// Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
@@ -282,6 +292,77 @@ void ParticlesMaterial::_update_shader() {
code += "uniform float collision_bounce;\n";
}
+ if (turbulence_enabled) {
+ code += "uniform float turbulence_noise_strength;\n";
+ code += "uniform float turbulence_noise_scale;\n";
+ code += "uniform float turbulence_influence_min;\n";
+ code += "uniform float turbulence_influence_max;\n";
+ code += "uniform float turbulence_initial_displacement_min;\n";
+ code += "uniform float turbulence_initial_displacement_max;\n";
+ code += "uniform float turbulence_noise_speed_random;\n";
+ code += "uniform vec3 turbulence_noise_speed = vec3(1.0, 1.0, 1.0);\n";
+ if (tex_parameters[PARAM_TURB_INFLUENCE_OVER_LIFE].is_valid()) {
+ code += "uniform sampler2D turbulence_influence_over_life;\n";
+ }
+ if (turbulence_color_ramp.is_valid()) {
+ code += "uniform sampler2D turbulence_color_ramp;\n";
+ }
+ code += "\n";
+
+ //functions for 3D noise / turbulence
+ code += "\n\n";
+ code += "// 3D Noise with friendly permission by Inigo Quilez\n";
+ code += "vec3 hash_noise( vec3 p ) {\n";
+ code += " p *= mat3(vec3(127.1, 311.7, -53.7), vec3(269.5, 183.3, 77.1), vec3(-301.7, 27.3, 215.3));\n";
+ code += " return 2.0 * fract(fract(p)*4375.55) -1.;\n";
+ code += "}\n";
+ code += "\n";
+ code += "float noise( vec3 p) {\n";
+ code += " vec3 i = floor(p);;\n";
+ code += " vec3 f = fract(p);\n ";
+ code += " vec3 u = f * f * (3.0 - 2.0 * f);\n";
+ code += "\n";
+ code += " return 2.0*mix( mix( mix( dot( hash_noise( i + vec3(0.0,0.0,0.0) ), f - vec3(0.0,0.0,0.0) ), dot( hash_noise( i + vec3(1.0,0.0,0.0) ), f - vec3(1.0,0.0,0.0) ), u.x),\n";
+ code += " mix( dot( hash_noise( i + vec3(0.0,1.0,0.0) ), f - vec3(0.0,1.0,0.0) ), dot( hash_noise( i + vec3(1.0,1.0,0.0) ), f - vec3(1.0,1.0,0.0) ), u.x), u.y),\n";
+ code += " mix( mix( dot( hash_noise( i + vec3(0.0,0.0,1.0) ), f - vec3(0.0,0.0,1.0) ), dot( hash_noise( i + vec3(1.0,0.0,1.0) ), f - vec3(1.0,0.0,1.0) ), u.x),\n";
+ code += " mix( dot( hash_noise( i + vec3(0.0,1.0,1.0) ), f - vec3(0.0,1.0,1.0) ), dot( hash_noise( i + vec3(1.0,1.0,1.0) ), f - vec3(1.0,1.0,1.0) ), u.x), u.y), u.z);\n";
+ code += "}\n\n";
+ code += "// Curl 3D and noise_3d function with friendly permission by Isaac Cohen\n";
+ code += "vec3 noise_3d(vec3 p) {\n";
+ code += " float s = noise(p);\n";
+ code += " float s1 = noise(vec3(p.y - 19.1, p.z + 33.4, p.x + 47.2));\n";
+ code += " float s2 = noise(vec3(p.z + 74.2, p.x - 124.5, p.y + 99.4));\n";
+ code += " vec3 c = vec3(s, s1, s2);\n";
+ code += " return c;\n";
+ code += "}\n\n";
+ code += "vec3 curl_3d(vec3 p, float c) {\n";
+ code += " float epsilon = 0.001 + c;\n";
+ code += " vec3 dx = vec3(epsilon, 0.0, 0.0);\n";
+ code += " vec3 dy = vec3(0.0, epsilon, 0.0);\n";
+ code += " vec3 dz = vec3(0.0, 0.0, epsilon);\n";
+ code += " vec3 x0 = noise_3d(p - dx).xyz;\n";
+ code += " vec3 x1 = noise_3d(p + dx).xyz;\n";
+ code += " vec3 y0 = noise_3d(p - dy).xyz;\n";
+ code += " vec3 y1 = noise_3d(p + dy).xyz;\n";
+ code += " vec3 z0 = noise_3d(p - dz).xyz;\n";
+ code += " vec3 z1 = noise_3d(p + dz).xyz;\n";
+ code += " float x = y1.z - y0.z - z1.y + z0.y;\n";
+ code += " float y = z1.x - z0.x - x1.z + x0.z;\n";
+ code += " float z = x1.y - x0.y - y1.x + y0.x;\n";
+ code += " float divisor = 1.0 / (2.0 * epsilon);\n";
+ code += " return vec3(normalize(vec3(x, y, z) * divisor));\n";
+ code += "}\n";
+ code += "vec3 get_noise_direction(vec3 pos, vec3 emission_pos, vec3 time_noise) {\n";
+ code += " float adj_contrast = max((turbulence_noise_strength - 1.0), 0.0) * 70.0;\n";
+ code += " vec3 noise_time = (vec3(TIME) * turbulence_noise_speed) + time_noise;\n";
+ code += " vec3 noise_pos = (pos * turbulence_noise_scale) - emission_pos;\n";
+ code += " vec3 diff = pos - emission_pos;\n";
+ code += " vec3 noise_direction = curl_3d(noise_pos + noise_time - diff, adj_contrast);\n";
+ code += " noise_direction = mix(0.9 * noise_direction, noise_direction, turbulence_noise_strength - 9.0);\n";
+ code += " return noise_direction;\n";
+ code += "}\n";
+ }
+
//need a random function
code += "\n\n";
code += "float rand_from_seed(inout uint seed) {\n";
@@ -463,8 +544,18 @@ void ParticlesMaterial::_update_shader() {
break;
}
}
-
code += " if (RESTART_VELOCITY) VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n";
+ // Apply noise/turbulence: initial displacement.
+ if (turbulence_enabled) {
+ if (get_turbulence_noise_speed_random() >= 0.0) {
+ code += " vec3 time_noise = noise_3d( vec3(TIME) * turbulence_noise_speed_random ) * -turbulence_noise_speed;\n";
+ } else {
+ code += " const vec3 time_noise = vec3(0.0);\n";
+ }
+ code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz, EMISSION_TRANSFORM[3].xyz, time_noise);\n";
+ code += " float turb_init_displacement = mix(turbulence_initial_displacement_min, turbulence_initial_displacement_max, rand_from_seed(alt_seed));";
+ code += " TRANSFORM[3].xyz += noise_direction * turb_init_displacement;\n";
+ }
code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n";
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
code += " VELOCITY.z = 0.0;\n";
@@ -483,7 +574,6 @@ void ParticlesMaterial::_update_shader() {
if (color_initial_ramp.is_valid()) {
code += " float color_initial_rand = rand_from_seed(alt_seed);\n";
}
-
code += " float pi = 3.14159;\n";
code += " float degree_to_rad = pi / 180.0;\n";
code += "\n";
@@ -570,7 +660,7 @@ void ParticlesMaterial::_update_shader() {
code += " vec3 diff = pos - org;\n";
code += " force += length(diff) > 0.0 ? normalize(diff) * tex_radial_accel * mix(radial_accel_min, radial_accel_max, rand_from_seed(alt_seed)) : vec3(0.0);\n";
code += " // apply tangential acceleration;\n";
- code += " float tangent_accel_val = tex_tangent_accel * mix(tangent_accel_min, tangent_accel_max, rand_from_seed(alt_seed))\n;";
+ code += " float tangent_accel_val = tex_tangent_accel * mix(tangent_accel_min, tangent_accel_max, rand_from_seed(alt_seed));\n";
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
code += " force += length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0, 1.0)), 0.0) * tangent_accel_val : vec3(0.0);\n";
@@ -584,6 +674,41 @@ void ParticlesMaterial::_update_shader() {
code += " // apply attractor forces\n";
code += " VELOCITY += force * DELTA;\n";
+
+ if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
+ code += " VELOCITY = normalize(VELOCITY) * tex_linear_velocity;\n";
+ }
+
+ // Apply noise/turbulence.
+ if (turbulence_enabled) {
+ code += " // apply turbulence\n";
+ if (tex_parameters[PARAM_TURB_INFLUENCE_OVER_LIFE].is_valid()) {
+ code += " float turbulence_influence = textureLod(turbulence_influence_over_life, vec2(tv, 0.0), 0.0).r;\n";
+ } else {
+ code += " const float turbulence_influence = 1.0;\n";
+ }
+ code += " \n";
+ if (get_turbulence_noise_speed_random() >= 0.0) {
+ code += " vec3 time_noise = noise_3d( vec3(TIME) * turbulence_noise_speed_random ) * -turbulence_noise_speed;\n";
+ } else {
+ code += " const vec3 time_noise = vec3(0.0);\n";
+ }
+ code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz, EMISSION_TRANSFORM[3].xyz, time_noise);\n";
+ // If collision happened, turbulence is no longer applied.
+ String extra_tab = "";
+ if (collision_enabled) {
+ code += " if (!COLLIDED) {\n";
+ extra_tab = " ";
+ }
+ code += extra_tab + " \n";
+ code += extra_tab + " float vel_mag = length(VELOCITY);\n";
+ code += extra_tab + " float vel_infl = clamp(mix(turbulence_influence_min, turbulence_influence_max, rand_from_seed(alt_seed)) * turbulence_influence, 0.0, 1.0);\n";
+ code += extra_tab + " VELOCITY = mix(VELOCITY, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n";
+ if (collision_enabled) {
+ code += " }";
+ }
+ }
+ code += " \n";
code += " // orbit velocity\n";
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
code += " float orbit_amount = tex_orbit_velocity * mix(orbit_velocity_min, orbit_velocity_max, rand_from_seed(alt_seed));\n";
@@ -595,9 +720,6 @@ void ParticlesMaterial::_update_shader() {
code += " }\n";
}
- if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
- code += " VELOCITY = normalize(VELOCITY) * tex_linear_velocity;\n";
- }
code += " float dmp = mix(damping_min, damping_max, rand_from_seed(alt_seed));\n";
code += " if (dmp * tex_damping > 0.0) {\n";
code += " float v = length(VELOCITY);\n";
@@ -701,24 +823,34 @@ void ParticlesMaterial::_update_shader() {
code += " TRANSFORM[3] = origin;\n";
}
}
- //scale by scale
- code += " float base_scale = mix(scale_min, scale_max, scale_rand);\n";
- code += " base_scale = sign(base_scale) * max(abs(base_scale), 0.001);\n";
- code += " TRANSFORM[0].xyz *= base_scale * sign(tex_scale.r) * max(abs(tex_scale.r), 0.001);\n";
- code += " TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);\n";
- code += " TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);\n";
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
- code += " VELOCITY.z = 0.0;\n";
code += " TRANSFORM[3].z = 0.0;\n";
}
+
if (collision_enabled) {
code += " if (COLLIDED) {\n";
- code += " TRANSFORM[3].xyz+=COLLISION_NORMAL * COLLISION_DEPTH;\n";
- code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n";
- code += " VELOCITY = mix(VELOCITY,vec3(0.0),collision_friction * DELTA * 100.0);\n";
+ code += " if (length(VELOCITY) > 3.0) {\n";
+ code += " TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;\n";
+ code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n";
+ code += " VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));\n";
+ code += " } else {\n";
+ code += " VELOCITY = vec3(0.0);\n";
+ // If turbulence is enabled, set the noise direction to up so the turbulence color is "neutral"
+ if (turbulence_enabled) {
+ code += " noise_direction = vec3(1.0, 0.0, 0.0);\n";
+ }
+ code += " }\n";
code += " }\n";
}
+
+ // scale by scale
+ code += " float base_scale = mix(scale_min, scale_max, scale_rand);\n";
+ code += " base_scale = sign(base_scale) * max(abs(base_scale), 0.001);\n";
+ code += " TRANSFORM[0].xyz *= base_scale * sign(tex_scale.r) * max(abs(tex_scale.r), 0.001);\n";
+ code += " TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);\n";
+ code += " TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);\n";
+
if (sub_emitter_mode != SUB_EMITTER_DISABLED) {
code += " int emit_count = 0;\n";
switch (sub_emitter_mode) {
@@ -856,6 +988,15 @@ void ParticlesMaterial::set_param_min(Parameter p_param, float p_value) {
case PARAM_ANIM_OFFSET: {
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_min, p_value);
} break;
+ case PARAM_TURB_VEL_INFLUENCE: {
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_influence_min, p_value);
+ } break;
+ case PARAM_TURB_INIT_DISPLACEMENT: {
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_initial_displacement_min, p_value);
+ } break;
+ case PARAM_TURB_INFLUENCE_OVER_LIFE: {
+ // Can't happen, but silences warning
+ } break;
case PARAM_MAX:
break; // Can't happen, but silences warning
}
@@ -912,6 +1053,15 @@ void ParticlesMaterial::set_param_max(Parameter p_param, float p_value) {
case PARAM_ANIM_OFFSET: {
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_max, p_value);
} break;
+ case PARAM_TURB_VEL_INFLUENCE: {
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_influence_max, p_value);
+ } break;
+ case PARAM_TURB_INIT_DISPLACEMENT: {
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_initial_displacement_max, p_value);
+ } break;
+ case PARAM_TURB_INFLUENCE_OVER_LIFE: {
+ // Can't happen, but silences warning
+ } break;
case PARAM_MAX:
break; // Can't happen, but silences warning
}
@@ -986,6 +1136,16 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D
case PARAM_ANIM_OFFSET: {
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, tex_rid);
} break;
+ case PARAM_TURB_INFLUENCE_OVER_LIFE: {
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_influence_over_life, tex_rid);
+ _adjust_curve_range(p_texture, 0, 1);
+ } break;
+ case PARAM_TURB_VEL_INFLUENCE: {
+ // Can't happen, but silences warning
+ } break;
+ case PARAM_TURB_INIT_DISPLACEMENT: {
+ // Can't happen, but silences warning
+ } break;
case PARAM_MAX:
break; // Can't happen, but silences warning
}
@@ -1151,6 +1311,54 @@ real_t ParticlesMaterial::get_emission_ring_inner_radius() const {
return emission_ring_inner_radius;
}
+void ParticlesMaterial::set_turbulence_enabled(const bool p_turbulence_enabled) {
+ turbulence_enabled = p_turbulence_enabled;
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_enabled, turbulence_enabled);
+ _queue_shader_change();
+ notify_property_list_changed();
+}
+
+bool ParticlesMaterial::get_turbulence_enabled() const {
+ return turbulence_enabled;
+}
+
+void ParticlesMaterial::set_turbulence_noise_strength(float p_turbulence_noise_strength) {
+ turbulence_noise_strength = p_turbulence_noise_strength;
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_strength, p_turbulence_noise_strength);
+}
+
+float ParticlesMaterial::get_turbulence_noise_strength() const {
+ return turbulence_noise_strength;
+}
+
+void ParticlesMaterial::set_turbulence_noise_scale(float p_turbulence_noise_scale) {
+ turbulence_noise_scale = p_turbulence_noise_scale;
+ float shader_turbulence_noise_scale = (pow(p_turbulence_noise_scale, 0.25) * 5.6234 / 10.0) * 4.0 - 3.0;
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_scale, shader_turbulence_noise_scale);
+}
+
+float ParticlesMaterial::get_turbulence_noise_scale() const {
+ return turbulence_noise_scale;
+}
+
+void ParticlesMaterial::set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random) {
+ turbulence_noise_speed_random = p_turbulence_noise_speed_random;
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed_random, p_turbulence_noise_speed_random);
+}
+
+float ParticlesMaterial::get_turbulence_noise_speed_random() const {
+ return turbulence_noise_speed_random;
+}
+
+void ParticlesMaterial::set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed) {
+ turbulence_noise_speed = p_turbulence_noise_speed;
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed, turbulence_noise_speed);
+}
+
+Vector3 ParticlesMaterial::get_turbulence_noise_speed() const {
+ return turbulence_noise_speed;
+}
+
void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) {
gravity = p_gravity;
Vector3 gset = gravity;
@@ -1214,6 +1422,20 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const {
if (property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
property.usage = PROPERTY_USAGE_NONE;
}
+
+ if (!turbulence_enabled) {
+ if (property.name == "turbulence_noise_strength" ||
+ property.name == "turbulence_noise_scale" ||
+ property.name == "turbulence_noise_speed" ||
+ property.name == "turbulence_noise_speed_random" ||
+ property.name == "turbulence_influence_over_life" ||
+ property.name == "turbulence_influence_min" ||
+ property.name == "turbulence_influence_max" ||
+ property.name == "turbulence_initial_displacement_min" ||
+ property.name == "turbulence_initial_displacement_max") {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ }
}
void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) {
@@ -1365,6 +1587,21 @@ void ParticlesMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &ParticlesMaterial::set_emission_ring_inner_radius);
ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &ParticlesMaterial::get_emission_ring_inner_radius);
+ ClassDB::bind_method(D_METHOD("get_turbulence_enabled"), &ParticlesMaterial::get_turbulence_enabled);
+ ClassDB::bind_method(D_METHOD("set_turbulence_enabled", "turbulence_enabled"), &ParticlesMaterial::set_turbulence_enabled);
+
+ ClassDB::bind_method(D_METHOD("get_turbulence_noise_strength"), &ParticlesMaterial::get_turbulence_noise_strength);
+ ClassDB::bind_method(D_METHOD("set_turbulence_noise_strength", "turbulence_noise_strength"), &ParticlesMaterial::set_turbulence_noise_strength);
+
+ ClassDB::bind_method(D_METHOD("get_turbulence_noise_scale"), &ParticlesMaterial::get_turbulence_noise_scale);
+ ClassDB::bind_method(D_METHOD("set_turbulence_noise_scale", "turbulence_noise_scale"), &ParticlesMaterial::set_turbulence_noise_scale);
+
+ ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed_random"), &ParticlesMaterial::get_turbulence_noise_speed_random);
+ ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed_random", "turbulence_noise_speed_random"), &ParticlesMaterial::set_turbulence_noise_speed_random);
+
+ ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed"), &ParticlesMaterial::get_turbulence_noise_speed);
+ ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed", "turbulence_noise_speed"), &ParticlesMaterial::set_turbulence_noise_speed);
+
ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity);
ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity);
@@ -1413,7 +1650,7 @@ void ParticlesMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_height"), "set_emission_ring_height", "get_emission_ring_height");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_radius"), "set_emission_ring_radius", "get_emission_ring_radius");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_inner_radius"), "set_emission_ring_inner_radius", "get_emission_ring_inner_radius");
- ADD_GROUP("ParticleFlags", "particle_flag_");
+ ADD_GROUP("Particle Flags", "particle_flag_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_align_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_rotate_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ROTATE_Y);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_disable_z"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_DISABLE_Z);
@@ -1467,6 +1704,19 @@ void ParticlesMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_min", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param_min", "get_param_min", PARAM_HUE_VARIATION);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_max", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param_max", "get_param_max", PARAM_HUE_VARIATION);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION);
+
+ ADD_GROUP("Turbulence", "turbulence_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "turbulence_enabled"), "set_turbulence_enabled", "get_turbulence_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbulence_noise_strength", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_turbulence_noise_strength", "get_turbulence_noise_strength");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbulence_noise_scale", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_turbulence_noise_scale", "get_turbulence_noise_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "turbulence_noise_speed"), "set_turbulence_noise_speed", "get_turbulence_noise_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbulence_noise_speed_random", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_turbulence_noise_speed_random", "get_turbulence_noise_speed_random");
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_influence_min", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_min", "get_param_min", PARAM_TURB_VEL_INFLUENCE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_influence_max", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_max", "get_param_max", PARAM_TURB_VEL_INFLUENCE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_initial_displacement_min", PROPERTY_HINT_RANGE, "-100,100,0.1"), "set_param_min", "get_param_min", PARAM_TURB_INIT_DISPLACEMENT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_initial_displacement_max", PROPERTY_HINT_RANGE, "-100,100,0.1"), "set_param_max", "get_param_max", PARAM_TURB_INIT_DISPLACEMENT);
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "turbulence_influence_over_life", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_TURB_INFLUENCE_OVER_LIFE);
+
ADD_GROUP("Animation", "anim_");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_min", PROPERTY_HINT_RANGE, "0,16,0.01,or_lesser,or_greater"), "set_param_min", "get_param_min", PARAM_ANIM_SPEED);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_max", PROPERTY_HINT_RANGE, "0,16,0.01,or_lesser,or_greater"), "set_param_max", "get_param_max", PARAM_ANIM_SPEED);
@@ -1517,6 +1767,10 @@ void ParticlesMaterial::_bind_methods() {
BIND_ENUM_CONSTANT(EMISSION_SHAPE_RING);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX);
+ BIND_ENUM_CONSTANT(PARAM_TURB_VEL_INFLUENCE);
+ BIND_ENUM_CONSTANT(PARAM_TURB_INIT_DISPLACEMENT);
+ BIND_ENUM_CONSTANT(PARAM_TURB_INFLUENCE_OVER_LIFE);
+
BIND_ENUM_CONSTANT(SUB_EMITTER_DISABLED);
BIND_ENUM_CONSTANT(SUB_EMITTER_CONSTANT);
BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END);
@@ -1560,6 +1814,17 @@ ParticlesMaterial::ParticlesMaterial() :
set_emission_ring_height(1);
set_emission_ring_radius(1);
set_emission_ring_inner_radius(0);
+
+ set_turbulence_enabled(false);
+ set_turbulence_noise_speed(Vector3(0.5, 0.5, 0.5));
+ set_turbulence_noise_strength(1);
+ set_turbulence_noise_scale(9);
+ set_turbulence_noise_speed_random(0);
+ set_param_min(PARAM_TURB_VEL_INFLUENCE, 0.1);
+ set_param_max(PARAM_TURB_VEL_INFLUENCE, 0.1);
+ set_param_min(PARAM_TURB_INIT_DISPLACEMENT, 0.0);
+ set_param_max(PARAM_TURB_INIT_DISPLACEMENT, 0.0);
+
set_gravity(Vector3(0, -9.8, 0));
set_lifetime_randomness(0);
diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h
index af45593f38..7fb46d6ac5 100644
--- a/scene/resources/particles_material.h
+++ b/scene/resources/particles_material.h
@@ -58,6 +58,9 @@ public:
PARAM_HUE_VARIATION,
PARAM_ANIM_SPEED,
PARAM_ANIM_OFFSET,
+ PARAM_TURB_INFLUENCE_OVER_LIFE,
+ PARAM_TURB_VEL_INFLUENCE,
+ PARAM_TURB_INIT_DISPLACEMENT,
PARAM_MAX
};
@@ -105,9 +108,10 @@ private:
uint32_t attractor_enabled : 1;
uint32_t collision_enabled : 1;
uint32_t collision_scale : 1;
+ uint32_t turbulence_enabled : 1;
};
- uint32_t key = 0;
+ uint64_t key = 0;
static uint32_t hash(const MaterialKey &p_key) {
return hash_murmur3_one_32(p_key.key);
@@ -152,6 +156,7 @@ private:
mk.collision_enabled = collision_enabled;
mk.attractor_enabled = attractor_interaction_enabled;
mk.collision_scale = collision_scale;
+ mk.turbulence_enabled = turbulence_enabled;
return mk;
}
@@ -216,6 +221,17 @@ private:
StringName emission_ring_radius;
StringName emission_ring_inner_radius;
+ StringName turbulence_enabled;
+ StringName turbulence_noise_strength;
+ StringName turbulence_noise_scale;
+ StringName turbulence_noise_speed;
+ StringName turbulence_noise_speed_random;
+ StringName turbulence_influence_over_life;
+ StringName turbulence_influence_min;
+ StringName turbulence_influence_max;
+ StringName turbulence_initial_displacement_min;
+ StringName turbulence_initial_displacement_max;
+
StringName gravity;
StringName lifetime_randomness;
@@ -243,6 +259,7 @@ private:
float params_min[PARAM_MAX];
float params_max[PARAM_MAX];
+ float params[PARAM_MAX];
Ref<Texture2D> tex_parameters[PARAM_MAX];
Color color;
@@ -265,6 +282,13 @@ private:
bool anim_loop = false;
+ bool turbulence_enabled;
+ Vector3 turbulence_noise_speed;
+ Ref<Texture2D> turbulence_color_ramp;
+ float turbulence_noise_strength = 0.0f;
+ float turbulence_noise_scale = 0.0f;
+ float turbulence_noise_speed_random = 0.0f;
+
Vector3 gravity;
double lifetime_randomness = 0.0;
@@ -340,6 +364,18 @@ public:
real_t get_emission_ring_inner_radius() const;
int get_emission_point_count() const;
+ void set_turbulence_enabled(bool p_turbulence_enabled);
+ void set_turbulence_noise_strength(float p_turbulence_noise_strength);
+ void set_turbulence_noise_scale(float p_turbulence_noise_scale);
+ void set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random);
+ void set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed);
+
+ bool get_turbulence_enabled() const;
+ float get_turbulence_noise_strength() const;
+ float get_turbulence_noise_scale() const;
+ float get_turbulence_noise_speed_random() const;
+ Vector3 get_turbulence_noise_speed() const;
+
void set_gravity(const Vector3 &p_gravity);
Vector3 get_gravity() const;
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index f4fd81b25f..f038a79b8f 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -1622,6 +1622,134 @@ bool SphereMesh::get_is_hemisphere() const {
SphereMesh::SphereMesh() {}
/**
+ TorusMesh
+*/
+
+void TorusMesh::_create_mesh_array(Array &p_arr) const {
+ // set our bounding box
+
+ Vector<Vector3> points;
+ Vector<Vector3> normals;
+ Vector<float> tangents;
+ Vector<Vector2> uvs;
+ Vector<int> indices;
+
+#define ADD_TANGENT(m_x, m_y, m_z, m_d) \
+ tangents.push_back(m_x); \
+ tangents.push_back(m_y); \
+ tangents.push_back(m_z); \
+ tangents.push_back(m_d);
+
+ ERR_FAIL_COND_MSG(inner_radius == outer_radius, "Inner radius and outer radius cannot be the same.");
+
+ float min_radius = inner_radius;
+ float max_radius = outer_radius;
+
+ if (min_radius > max_radius) {
+ SWAP(min_radius, max_radius);
+ }
+
+ float radius = (max_radius - min_radius) * 0.5;
+
+ for (int i = 0; i <= rings; i++) {
+ int prevrow = (i - 1) * (ring_segments + 1);
+ int thisrow = i * (ring_segments + 1);
+ float inci = float(i) / rings;
+ float angi = inci * Math_TAU;
+
+ Vector2 normali = Vector2(-Math::sin(angi), -Math::cos(angi));
+
+ for (int j = 0; j <= ring_segments; j++) {
+ float incj = float(j) / ring_segments;
+ float angj = incj * Math_TAU;
+
+ Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj));
+ Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0);
+
+ points.push_back(Vector3(normali.x * normalk.x, normalk.y, normali.y * normalk.x));
+ normals.push_back(Vector3(normali.x * normalj.x, normalj.y, normali.y * normalj.x));
+ ADD_TANGENT(-Math::cos(angi), 0.0, Math::sin(angi), 1.0);
+ uvs.push_back(Vector2(inci, incj));
+
+ if (i > 0 && j > 0) {
+ indices.push_back(thisrow + j - 1);
+ indices.push_back(prevrow + j);
+ indices.push_back(prevrow + j - 1);
+
+ indices.push_back(thisrow + j - 1);
+ indices.push_back(thisrow + j);
+ indices.push_back(prevrow + j);
+ }
+ }
+ }
+
+ p_arr[RS::ARRAY_VERTEX] = points;
+ p_arr[RS::ARRAY_NORMAL] = normals;
+ p_arr[RS::ARRAY_TANGENT] = tangents;
+ p_arr[RS::ARRAY_TEX_UV] = uvs;
+ p_arr[RS::ARRAY_INDEX] = indices;
+}
+
+void TorusMesh::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &TorusMesh::set_inner_radius);
+ ClassDB::bind_method(D_METHOD("get_inner_radius"), &TorusMesh::get_inner_radius);
+
+ ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &TorusMesh::set_outer_radius);
+ ClassDB::bind_method(D_METHOD("get_outer_radius"), &TorusMesh::get_outer_radius);
+
+ ClassDB::bind_method(D_METHOD("set_rings", "rings"), &TorusMesh::set_rings);
+ ClassDB::bind_method(D_METHOD("get_rings"), &TorusMesh::get_rings);
+
+ ClassDB::bind_method(D_METHOD("set_ring_segments", "rings"), &TorusMesh::set_ring_segments);
+ ClassDB::bind_method(D_METHOD("get_ring_segments"), &TorusMesh::get_ring_segments);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_inner_radius", "get_inner_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_outer_radius", "get_outer_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "3,128,1"), "set_rings", "get_rings");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "ring_segments", PROPERTY_HINT_RANGE, "3,64,1"), "set_ring_segments", "get_ring_segments");
+}
+
+void TorusMesh::set_inner_radius(const float p_inner_radius) {
+ inner_radius = p_inner_radius;
+ _request_update();
+}
+
+float TorusMesh::get_inner_radius() const {
+ return inner_radius;
+}
+
+void TorusMesh::set_outer_radius(const float p_outer_radius) {
+ outer_radius = p_outer_radius;
+ _request_update();
+}
+
+float TorusMesh::get_outer_radius() const {
+ return outer_radius;
+}
+
+void TorusMesh::set_rings(const int p_rings) {
+ ERR_FAIL_COND(p_rings < 3);
+ rings = p_rings;
+ _request_update();
+}
+
+int TorusMesh::get_rings() const {
+ return rings;
+}
+
+void TorusMesh::set_ring_segments(const int p_ring_segments) {
+ ERR_FAIL_COND(p_ring_segments < 3);
+ ring_segments = p_ring_segments;
+ _request_update();
+}
+
+int TorusMesh::get_ring_segments() const {
+ return ring_segments;
+}
+
+TorusMesh::TorusMesh() {}
+
+/**
PointMesh
*/
@@ -2190,12 +2318,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 +2504,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 +2525,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 +2571,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 +2628,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 +2813,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 +2831,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 +2841,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 +2862,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 +2925,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 +3032,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..64eefd2c07 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -351,6 +351,38 @@ public:
};
/**
+ Big donut
+*/
+class TorusMesh : public PrimitiveMesh {
+ GDCLASS(TorusMesh, PrimitiveMesh);
+
+private:
+ float inner_radius = 0.5;
+ float outer_radius = 1.0;
+ int rings = 64;
+ int ring_segments = 32;
+
+protected:
+ static void _bind_methods();
+ virtual void _create_mesh_array(Array &p_arr) const override;
+
+public:
+ void set_inner_radius(const float p_inner_radius);
+ float get_inner_radius() const;
+
+ void set_outer_radius(const float p_outer_radius);
+ float get_outer_radius() const;
+
+ void set_rings(const int p_rings);
+ int get_rings() const;
+
+ void set_ring_segments(const int p_ring_segments);
+ int get_ring_segments() const;
+
+ TorusMesh();
+};
+
+/**
A single point for use in particle systems
*/
@@ -475,6 +507,7 @@ private:
sharp = p_sharp;
};
};
+
struct ContourInfo {
real_t length = 0.0;
bool ccw = true;
@@ -484,6 +517,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 +545,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 +557,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 +570,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 +579,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 +601,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;
@@ -582,4 +627,5 @@ public:
};
VARIANT_ENUM_CAST(RibbonTrailMesh::Shape)
-#endif
+
+#endif // PRIMITIVE_MESHES_H
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index 66afb001fb..2b1d91e4ef 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -65,14 +65,18 @@ Error ResourceLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, Varia
return ERR_PARSE_ERROR;
}
- String unique_id = token.value;
+ if (p_data->no_placeholders) {
+ r_res.unref();
+ } else {
+ String unique_id = token.value;
- if (!p_data->resource_map.has(unique_id)) {
- r_err_str = "Found unique_id reference before mapping, sub-resources stored out of order in resource file";
- return ERR_PARSE_ERROR;
- }
+ if (!p_data->resource_map.has(unique_id)) {
+ r_err_str = "Found unique_id reference before mapping, sub-resources stored out of order in resource file";
+ return ERR_PARSE_ERROR;
+ }
- r_res = p_data->resource_map[unique_id];
+ r_res = p_data->resource_map[unique_id];
+ }
VariantParser::get_token(p_stream, token, line, r_err_str);
if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
@@ -91,11 +95,15 @@ Error ResourceLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, Varia
return ERR_PARSE_ERROR;
}
- String id = token.value;
+ if (p_data->no_placeholders) {
+ r_res.unref();
+ } else {
+ String id = token.value;
- ERR_FAIL_COND_V(!p_data->rev_external_resources.has(id), ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(!p_data->rev_external_resources.has(id), ERR_PARSE_ERROR);
- r_res = p_data->rev_external_resources[id];
+ r_res = p_data->rev_external_resources[id];
+ }
VariantParser::get_token(p_stream, token, line, r_err_str);
if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
@@ -1066,7 +1074,7 @@ static void bs_save_unicode_string(Ref<FileAccess> p_f, const String &p_string,
p_f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
}
-Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_path) {
+Error ResourceLoaderText::save_as_binary(const String &p_path) {
if (error) {
return error;
}
@@ -1271,7 +1279,7 @@ Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_pa
}
if (next_tag.name == "node") {
- //this is a node, must save one more!
+ // This is a node, must save one more!
if (!is_scene) {
error_text += "found the 'node' tag on a resource file!";
@@ -1346,6 +1354,126 @@ Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_pa
return OK;
}
+Error ResourceLoaderText::get_classes_used(HashSet<StringName> *r_classes) {
+ if (error) {
+ return error;
+ }
+
+ ignore_resource_parsing = true;
+
+ DummyReadData dummy_read;
+ dummy_read.no_placeholders = true;
+ VariantParser::ResourceParser rp;
+ rp.ext_func = _parse_ext_resource_dummys;
+ rp.sub_func = _parse_sub_resource_dummys;
+ rp.userdata = &dummy_read;
+
+ while (next_tag.name == "ext_resource") {
+ error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
+
+ if (error) {
+ _printerr();
+ return error;
+ }
+ }
+
+ while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
+ if (next_tag.name == "sub_resource") {
+ if (!next_tag.fields.has("type")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Missing 'type' in external resource tag";
+ _printerr();
+ return error;
+ }
+
+ r_classes->insert(next_tag.fields["type"]);
+
+ } else {
+ r_classes->insert(next_tag.fields["res_type"]);
+ }
+
+ while (true) {
+ String assign;
+ Variant value;
+
+ error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
+
+ if (error) {
+ if (error == ERR_FILE_EOF) {
+ return OK;
+ }
+
+ _printerr();
+ return error;
+ }
+
+ if (!assign.is_empty()) {
+ continue;
+ } else if (!next_tag.name.is_empty()) {
+ error = OK;
+ break;
+ } else {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Premature end of file while parsing [sub_resource]";
+ _printerr();
+ return error;
+ }
+ }
+ }
+
+ while (next_tag.name == "node") {
+ // This is a node, must save one more!
+
+ if (!is_scene) {
+ error_text += "found the 'node' tag on a resource file!";
+ _printerr();
+ error = ERR_FILE_CORRUPT;
+ return error;
+ }
+
+ if (!next_tag.fields.has("type")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Missing 'type' in external resource tag";
+ _printerr();
+ return error;
+ }
+
+ r_classes->insert(next_tag.fields["type"]);
+
+ while (true) {
+ String assign;
+ Variant value;
+
+ error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
+
+ if (error) {
+ if (error == ERR_FILE_MISSING_DEPENDENCIES) {
+ // Resource loading error, just skip it.
+ } else if (error != ERR_FILE_EOF) {
+ _printerr();
+ return error;
+ } else {
+ return OK;
+ }
+ }
+
+ if (!assign.is_empty()) {
+ continue;
+ } else if (!next_tag.name.is_empty()) {
+ error = OK;
+ break;
+ } else {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Premature end of file while parsing [sub_resource]";
+ _printerr();
+ return error;
+ }
+ }
+ }
+
+ return OK;
+}
+
String ResourceLoaderText::recognize(Ref<FileAccess> p_f) {
error = OK;
@@ -1473,6 +1601,26 @@ bool ResourceFormatLoaderText::handles_type(const String &p_type) const {
return true;
}
+void ResourceFormatLoaderText::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
+ String ext = p_path.get_extension().to_lower();
+ if (ext == "tscn") {
+ r_classes->insert("PackedScene");
+ }
+
+ // ...for anything else must test...
+
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
+ return; // Could not read.
+ }
+
+ ResourceLoaderText loader;
+ loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+ loader.res_path = loader.local_path;
+ loader.open(f);
+ loader.get_classes_used(r_classes);
+}
+
String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
String ext = p_path.get_extension().to_lower();
if (ext == "tscn") {
@@ -1561,7 +1709,7 @@ Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path,
loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
loader.res_path = loader.local_path;
loader.open(f);
- return loader.save_as_binary(f, p_dst_path);
+ return loader.save_as_binary(p_dst_path);
}
/*****************************************************************************************************/
@@ -2063,7 +2211,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso
return OK;
}
-Error ResourceFormatSaverText::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaverText::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
if (p_path.ends_with(".tscn") && !Ref<PackedScene>(p_resource).is_valid()) {
return ERR_FILE_UNRECOGNIZED;
}
diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h
index 5c6a937bf2..9154bcf795 100644
--- a/scene/resources/resource_format_text.h
+++ b/scene/resources/resource_format_text.h
@@ -90,6 +90,7 @@ class ResourceLoaderText {
};
struct DummyReadData {
+ bool no_placeholders = false;
HashMap<Ref<Resource>, int> external_resources;
HashMap<String, Ref<Resource>> rev_external_resources;
HashMap<Ref<Resource>, int> resource_index_map;
@@ -125,8 +126,9 @@ public:
ResourceUID::ID get_uid(Ref<FileAccess> p_f);
void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types);
Error rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const HashMap<String, String> &p_map);
+ Error get_classes_used(HashSet<StringName> *r_classes);
- Error save_as_binary(Ref<FileAccess> p_f, const String &p_path);
+ Error save_as_binary(const String &p_path);
ResourceLoaderText();
};
@@ -137,6 +139,8 @@ public:
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
+ virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes);
+
virtual String get_resource_type(const String &p_path) const;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
@@ -190,7 +194,7 @@ public:
class ResourceFormatSaverText : public ResourceFormatSaver {
public:
static ResourceFormatSaverText *singleton;
- virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
virtual bool recognize(const Ref<Resource> &p_resource) const;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
diff --git a/scene/resources/separation_ray_shape_2d.cpp b/scene/resources/separation_ray_shape_2d.cpp
index 0d6aee47d8..fea41061fd 100644
--- a/scene/resources/separation_ray_shape_2d.cpp
+++ b/scene/resources/separation_ray_shape_2d.cpp
@@ -57,7 +57,7 @@ void SeparationRayShape2D::draw(const RID &p_to_rid, const Color &p_color) {
Transform2D xf;
xf.rotate(target_position.angle());
- xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
+ xf.translate_local(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
Vector<Vector2> pts = {
xf.xform(Vector2(arrow_size, 0)),
diff --git a/scene/resources/separation_ray_shape_3d.h b/scene/resources/separation_ray_shape_3d.h
index 0e750a48e6..ae08ff7887 100644
--- a/scene/resources/separation_ray_shape_3d.h
+++ b/scene/resources/separation_ray_shape_3d.h
@@ -28,8 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SEPARATION_RAY_SHAPE_H
-#define SEPARATION_RAY_SHAPE_H
+#ifndef SEPARATION_RAY_SHAPE_3D_H
+#define SEPARATION_RAY_SHAPE_3D_H
+
#include "scene/resources/shape_3d.h"
class SeparationRayShape3D : public Shape3D {
@@ -53,4 +54,5 @@ public:
SeparationRayShape3D();
};
-#endif // SEPARATION_RAY_SHAPE_H
+
+#endif // SEPARATION_RAY_SHAPE_3D_H
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index d49157b1b8..db7b03f2be 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -33,6 +33,7 @@
#include "core/io/file_access.h"
#include "scene/scene_string_names.h"
#include "servers/rendering/shader_language.h"
+#include "servers/rendering/shader_preprocessor.h"
#include "servers/rendering_server.h"
#include "texture.h"
@@ -40,7 +41,23 @@ Shader::Mode Shader::get_mode() const {
return mode;
}
+void Shader::_dependency_changed() {
+ RenderingServer::get_singleton()->shader_set_code(shader, RenderingServer::get_singleton()->shader_get_code(shader));
+ params_cache_dirty = true;
+
+ emit_changed();
+}
+
+void Shader::set_path(const String &p_path, bool p_take_over) {
+ Resource::set_path(p_path, p_take_over);
+ RS::get_singleton()->shader_set_path_hint(shader, p_path);
+}
+
void Shader::set_code(const String &p_code) {
+ for (Ref<ShaderInclude> E : include_dependencies) {
+ E->disconnect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed));
+ }
+
String type = ShaderLanguage::get_shader_type(p_code);
if (type == "canvas_item") {
@@ -55,7 +72,27 @@ void Shader::set_code(const String &p_code) {
mode = MODE_SPATIAL;
}
- RenderingServer::get_singleton()->shader_set_code(shader, p_code);
+ code = p_code;
+ String pp_code = p_code;
+
+ HashSet<Ref<ShaderInclude>> new_include_dependencies;
+
+ {
+ // Preprocessor must run here and not in the server because:
+ // 1) Need to keep track of include dependencies at resource level
+ // 2) Server does not do interaction with Resource filetypes, this is a scene level feature.
+ ShaderPreprocessor preprocessor;
+ preprocessor.preprocess(p_code, pp_code, nullptr, nullptr, &new_include_dependencies);
+ }
+
+ // This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower)
+ include_dependencies = new_include_dependencies;
+
+ for (Ref<ShaderInclude> E : include_dependencies) {
+ E->connect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed));
+ }
+
+ RenderingServer::get_singleton()->shader_set_code(shader, pp_code);
params_cache_dirty = true;
emit_changed();
@@ -63,24 +100,28 @@ void Shader::set_code(const String &p_code) {
String Shader::get_code() const {
_update_shader();
- return RenderingServer::get_singleton()->shader_get_code(shader);
+ return code;
}
-void Shader::get_param_list(List<PropertyInfo> *p_params) const {
+void Shader::get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups) const {
_update_shader();
List<PropertyInfo> local;
- RenderingServer::get_singleton()->shader_get_param_list(shader, &local);
+ RenderingServer::get_singleton()->shader_get_shader_uniform_list(shader, &local);
params_cache.clear();
params_cache_dirty = false;
for (PropertyInfo &pi : local) {
- if (default_textures.has(pi.name)) { //do not show default textures
+ bool is_group = pi.usage == PROPERTY_USAGE_GROUP || pi.usage == PROPERTY_USAGE_SUBGROUP;
+ if (!p_get_groups && is_group) {
continue;
}
- String original_name = pi.name;
- pi.name = "shader_param/" + pi.name;
- params_cache[pi.name] = original_name;
+ if (!is_group) {
+ if (default_textures.has(pi.name)) { //do not show default textures
+ continue;
+ }
+ params_cache[pi.name] = pi.name;
+ }
if (p_params) {
//small little hack
if (pi.type == Variant::RID) {
@@ -135,8 +176,8 @@ bool Shader::is_text_shader() const {
return true;
}
-bool Shader::has_param(const StringName &p_param) const {
- return params_cache.has("shader_param/" + p_param);
+bool Shader::has_uniform(const StringName &p_param) const {
+ return params_cache.has("shader_uniform/" + p_param);
}
void Shader::_update_shader() const {
@@ -151,7 +192,7 @@ void Shader::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_texture_param", "param", "texture", "index"), &Shader::set_default_texture_param, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_default_texture_param", "param", "index"), &Shader::get_default_texture_param, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("has_param", "name"), &Shader::has_param);
+ ClassDB::bind_method(D_METHOD("has_uniform", "name"), &Shader::has_uniform);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code");
@@ -210,7 +251,7 @@ String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const
return "";
}
-Error ResourceFormatSaverShader::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaverShader::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Ref<Shader> shader = p_resource;
ERR_FAIL_COND_V(shader.is_null(), ERR_INVALID_PARAMETER);
diff --git a/scene/resources/shader.h b/scene/resources/shader.h
index 11c9f60ce8..abc953de5f 100644
--- a/scene/resources/shader.h
+++ b/scene/resources/shader.h
@@ -35,6 +35,7 @@
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "scene/resources/texture.h"
+#include "shader_include.h"
class Shader : public Resource {
GDCLASS(Shader, Resource);
@@ -53,6 +54,8 @@ public:
private:
RID shader;
Mode mode = MODE_SPATIAL;
+ HashSet<Ref<ShaderInclude>> include_dependencies;
+ String code;
// hack the name of performance
// shaders keep a list of ShaderMaterial -> RenderingServer name translations, to make
@@ -61,6 +64,7 @@ private:
mutable HashMap<StringName, StringName> params_cache; //map a shader param to a material param..
HashMap<StringName, HashMap<int, Ref<Texture2D>>> default_textures;
+ void _dependency_changed();
virtual void _update_shader() const; //used for visual shader
protected:
static void _bind_methods();
@@ -69,24 +73,26 @@ public:
//void set_mode(Mode p_mode);
virtual Mode get_mode() const;
+ virtual void set_path(const String &p_path, bool p_take_over = false) override;
+
void set_code(const String &p_code);
String get_code() const;
- void get_param_list(List<PropertyInfo> *p_params) const;
- bool has_param(const StringName &p_param) const;
+ void get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups = false) const;
+ bool has_uniform(const StringName &p_param) const;
- void set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture, int p_index = 0);
- Ref<Texture2D> get_default_texture_param(const StringName &p_param, int p_index = 0) const;
+ void set_default_texture_param(const StringName &p_uniform, const Ref<Texture2D> &p_texture, int p_index = 0);
+ Ref<Texture2D> get_default_texture_param(const StringName &p_uniform, int p_index = 0) const;
void get_default_texture_param_list(List<StringName> *r_textures) const;
virtual bool is_text_shader() const;
- _FORCE_INLINE_ StringName remap_param(const StringName &p_param) const {
+ _FORCE_INLINE_ StringName remap_uniform(const StringName &p_uniform) const {
if (params_cache_dirty) {
- get_param_list(nullptr);
+ get_shader_uniform_list(nullptr);
}
- const HashMap<StringName, StringName>::Iterator E = params_cache.find(p_param);
+ const HashMap<StringName, StringName>::Iterator E = params_cache.find(p_uniform);
if (E) {
return E->value;
}
@@ -111,7 +117,7 @@ public:
class ResourceFormatSaverShader : public ResourceFormatSaver {
public:
- virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
virtual bool recognize(const Ref<Resource> &p_resource) const;
};
diff --git a/scene/resources/shader_include.cpp b/scene/resources/shader_include.cpp
new file mode 100644
index 0000000000..42435fe3c7
--- /dev/null
+++ b/scene/resources/shader_include.cpp
@@ -0,0 +1,144 @@
+/*************************************************************************/
+/* shader_include.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 "shader_include.h"
+#include "servers/rendering/shader_language.h"
+#include "servers/rendering/shader_preprocessor.h"
+
+void ShaderInclude::_dependency_changed() {
+ emit_changed();
+}
+
+void ShaderInclude::set_code(const String &p_code) {
+ HashSet<Ref<ShaderInclude>> new_dependencies;
+ code = p_code;
+
+ for (Ref<ShaderInclude> E : dependencies) {
+ E->disconnect(SNAME("changed"), callable_mp(this, &ShaderInclude::_dependency_changed));
+ }
+
+ {
+ String pp_code;
+ ShaderPreprocessor preprocessor;
+ preprocessor.preprocess(p_code, pp_code, nullptr, nullptr, &new_dependencies);
+ }
+
+ // This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower)
+ dependencies = new_dependencies;
+
+ for (Ref<ShaderInclude> E : dependencies) {
+ E->connect(SNAME("changed"), callable_mp(this, &ShaderInclude::_dependency_changed));
+ }
+
+ emit_changed();
+}
+
+String ShaderInclude::get_code() const {
+ return code;
+}
+
+void ShaderInclude::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_code", "code"), &ShaderInclude::set_code);
+ ClassDB::bind_method(D_METHOD("get_code"), &ShaderInclude::get_code);
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code");
+}
+
+// ResourceFormatLoaderShaderInclude
+
+Ref<Resource> ResourceFormatLoaderShaderInclude::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+ if (r_error) {
+ *r_error = ERR_FILE_CANT_OPEN;
+ }
+
+ Ref<ShaderInclude> shader_inc;
+ shader_inc.instantiate();
+
+ Vector<uint8_t> buffer = FileAccess::get_file_as_array(p_path);
+
+ String str;
+ str.parse_utf8((const char *)buffer.ptr(), buffer.size());
+
+ shader_inc->set_code(str);
+
+ if (r_error) {
+ *r_error = OK;
+ }
+
+ return shader_inc;
+}
+
+void ResourceFormatLoaderShaderInclude::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back("gdshaderinc");
+}
+
+bool ResourceFormatLoaderShaderInclude::handles_type(const String &p_type) const {
+ return (p_type == "ShaderInclude");
+}
+
+String ResourceFormatLoaderShaderInclude::get_resource_type(const String &p_path) const {
+ String extension = p_path.get_extension().to_lower();
+ if (extension == "gdshaderinc") {
+ return "ShaderInclude";
+ }
+ return "";
+}
+
+// ResourceFormatSaverShaderInclude
+
+Error ResourceFormatSaverShaderInclude::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
+ Ref<ShaderInclude> shader_inc = p_resource;
+ ERR_FAIL_COND_V(shader_inc.is_null(), ERR_INVALID_PARAMETER);
+
+ String source = shader_inc->get_code();
+
+ Error error;
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &error);
+
+ ERR_FAIL_COND_V_MSG(error, error, "Cannot save shader include '" + p_path + "'.");
+
+ file->store_string(source);
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ return ERR_CANT_CREATE;
+ }
+
+ return OK;
+}
+
+void ResourceFormatSaverShaderInclude::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
+ const ShaderInclude *shader_inc = Object::cast_to<ShaderInclude>(*p_resource);
+ if (shader_inc != nullptr) {
+ p_extensions->push_back("gdshaderinc");
+ }
+}
+
+bool ResourceFormatSaverShaderInclude::recognize(const Ref<Resource> &p_resource) const {
+ return p_resource->get_class_name() == "ShaderInclude"; //only shader, not inherited
+}
diff --git a/scene/resources/shader_include.h b/scene/resources/shader_include.h
new file mode 100644
index 0000000000..b0865e3a61
--- /dev/null
+++ b/scene/resources/shader_include.h
@@ -0,0 +1,71 @@
+/*************************************************************************/
+/* shader_include.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 SHADER_INCLUDE_H
+#define SHADER_INCLUDE_H
+
+#include "core/io/resource.h"
+#include "core/io/resource_loader.h"
+#include "core/io/resource_saver.h"
+#include "core/templates/hash_set.h"
+
+class ShaderInclude : public Resource {
+ GDCLASS(ShaderInclude, Resource);
+ OBJ_SAVE_TYPE(ShaderInclude);
+
+private:
+ String code;
+ HashSet<Ref<ShaderInclude>> dependencies;
+ void _dependency_changed();
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_code(const String &p_text);
+ String get_code() const;
+};
+
+class ResourceFormatLoaderShaderInclude : public ResourceFormatLoader {
+public:
+ virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+class ResourceFormatSaverShaderInclude : public ResourceFormatSaver {
+public:
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
+ virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
+ virtual bool recognize(const Ref<Resource> &p_resource) const;
+};
+
+#endif // SHADER_INCLUDE_H
diff --git a/scene/resources/shape_3d.h b/scene/resources/shape_3d.h
index 77e79a269d..58fe723d89 100644
--- a/scene/resources/shape_3d.h
+++ b/scene/resources/shape_3d.h
@@ -73,4 +73,4 @@ public:
~Shape3D();
};
-#endif // SHAPE_H
+#endif // SHAPE_3D_H
diff --git a/scene/resources/skeleton_modification_2d.h b/scene/resources/skeleton_modification_2d.h
index 3b9235ffd8..4c49119df0 100644
--- a/scene/resources/skeleton_modification_2d.h
+++ b/scene/resources/skeleton_modification_2d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATION2D_H
-#define SKELETONMODIFICATION2D_H
+#ifndef SKELETON_MODIFICATION_2D_H
+#define SKELETON_MODIFICATION_2D_H
#include "scene/2d/skeleton_2d.h"
#include "scene/resources/skeleton_modification_stack_2d.h"
@@ -86,4 +86,4 @@ public:
SkeletonModification2D();
};
-#endif // SKELETONMODIFICATION2D_H
+#endif // SKELETON_MODIFICATION_2D_H
diff --git a/scene/resources/skeleton_modification_2d_ccdik.h b/scene/resources/skeleton_modification_2d_ccdik.h
index 31485fa31f..e49dfca5b5 100644
--- a/scene/resources/skeleton_modification_2d_ccdik.h
+++ b/scene/resources/skeleton_modification_2d_ccdik.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATION2DCCDIK_H
-#define SKELETONMODIFICATION2DCCDIK_H
+#ifndef SKELETON_MODIFICATION_2D_CCDIK_H
+#define SKELETON_MODIFICATION_2D_CCDIK_H
#include "scene/2d/skeleton_2d.h"
#include "scene/resources/skeleton_modification_2d.h"
@@ -113,4 +113,4 @@ public:
~SkeletonModification2DCCDIK();
};
-#endif // SKELETONMODIFICATION2DCCDIK_H
+#endif // SKELETON_MODIFICATION_2D_CCDIK_H
diff --git a/scene/resources/skeleton_modification_2d_fabrik.h b/scene/resources/skeleton_modification_2d_fabrik.h
index d5077084ef..4a875d039f 100644
--- a/scene/resources/skeleton_modification_2d_fabrik.h
+++ b/scene/resources/skeleton_modification_2d_fabrik.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATION2DFABRIK_H
-#define SKELETONMODIFICATION2DFABRIK_H
+#ifndef SKELETON_MODIFICATION_2D_FABRIK_H
+#define SKELETON_MODIFICATION_2D_FABRIK_H
#include "scene/2d/skeleton_2d.h"
#include "scene/resources/skeleton_modification_2d.h"
@@ -105,4 +105,4 @@ public:
~SkeletonModification2DFABRIK();
};
-#endif // SKELETONMODIFICATION2DFABRIK_H
+#endif // SKELETON_MODIFICATION_2D_FABRIK_H
diff --git a/scene/resources/skeleton_modification_2d_jiggle.h b/scene/resources/skeleton_modification_2d_jiggle.h
index a1abca6564..b9080eafa9 100644
--- a/scene/resources/skeleton_modification_2d_jiggle.h
+++ b/scene/resources/skeleton_modification_2d_jiggle.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATION2DJIGGLE_H
-#define SKELETONMODIFICATION2DJIGGLE_H
+#ifndef SKELETON_MODIFICATION_2D_JIGGLE_H
+#define SKELETON_MODIFICATION_2D_JIGGLE_H
#include "scene/2d/skeleton_2d.h"
#include "scene/resources/skeleton_modification_2d.h"
@@ -136,4 +136,4 @@ public:
~SkeletonModification2DJiggle();
};
-#endif // SKELETONMODIFICATION2DJIGGLE_H
+#endif // SKELETON_MODIFICATION_2D_JIGGLE_H
diff --git a/scene/resources/skeleton_modification_2d_lookat.h b/scene/resources/skeleton_modification_2d_lookat.h
index ff91b92e7d..e4d7afa605 100644
--- a/scene/resources/skeleton_modification_2d_lookat.h
+++ b/scene/resources/skeleton_modification_2d_lookat.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATION2DLOOKAT_H
-#define SKELETONMODIFICATION2DLOOKAT_H
+#ifndef SKELETON_MODIFICATION_2D_LOOKAT_H
+#define SKELETON_MODIFICATION_2D_LOOKAT_H
#include "scene/2d/skeleton_2d.h"
#include "scene/resources/skeleton_modification_2d.h"
@@ -97,4 +97,4 @@ public:
~SkeletonModification2DLookAt();
};
-#endif // SKELETONMODIFICATION2DLOOKAT_H
+#endif // SKELETON_MODIFICATION_2D_LOOKAT_H
diff --git a/scene/resources/skeleton_modification_2d_physicalbones.h b/scene/resources/skeleton_modification_2d_physicalbones.h
index 373ff666ee..55482b2cca 100644
--- a/scene/resources/skeleton_modification_2d_physicalbones.h
+++ b/scene/resources/skeleton_modification_2d_physicalbones.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATION2DPHYSICALBONES_H
-#define SKELETONMODIFICATION2DPHYSICALBONES_H
+#ifndef SKELETON_MODIFICATION_2D_PHYSICALBONES_H
+#define SKELETON_MODIFICATION_2D_PHYSICALBONES_H
#include "scene/2d/skeleton_2d.h"
#include "scene/resources/skeleton_modification_2d.h"
@@ -79,4 +79,4 @@ public:
~SkeletonModification2DPhysicalBones();
};
-#endif // SKELETONMODIFICATION2DPHYSICALBONES_H
+#endif // SKELETON_MODIFICATION_2D_PHYSICALBONES_H
diff --git a/scene/resources/skeleton_modification_2d_stackholder.h b/scene/resources/skeleton_modification_2d_stackholder.h
index 99d9f6f381..4da9fcc1f6 100644
--- a/scene/resources/skeleton_modification_2d_stackholder.h
+++ b/scene/resources/skeleton_modification_2d_stackholder.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATION2DSTACKHOLDER_H
-#define SKELETONMODIFICATION2DSTACKHOLDER_H
+#ifndef SKELETON_MODIFICATION_2D_STACKHOLDER_H
+#define SKELETON_MODIFICATION_2D_STACKHOLDER_H
#include "scene/2d/skeleton_2d.h"
#include "scene/resources/skeleton_modification_2d.h"
@@ -61,4 +61,4 @@ public:
~SkeletonModification2DStackHolder();
};
-#endif // SKELETONMODIFICATION2DSTACKHOLDER_H
+#endif // SKELETON_MODIFICATION_2D_STACKHOLDER_H
diff --git a/scene/resources/skeleton_modification_2d_twoboneik.h b/scene/resources/skeleton_modification_2d_twoboneik.h
index fc14d35f70..e1dbb6cfda 100644
--- a/scene/resources/skeleton_modification_2d_twoboneik.h
+++ b/scene/resources/skeleton_modification_2d_twoboneik.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATION2DTWOBONEIK_H
-#define SKELETONMODIFICATION2DTWOBONEIK_H
+#ifndef SKELETON_MODIFICATION_2D_TWOBONEIK_H
+#define SKELETON_MODIFICATION_2D_TWOBONEIK_H
#include "scene/2d/skeleton_2d.h"
#include "scene/resources/skeleton_modification_2d.h"
@@ -104,4 +104,4 @@ public:
~SkeletonModification2DTwoBoneIK();
};
-#endif // SKELETONMODIFICATION2DTWOBONEIK_H
+#endif // SKELETON_MODIFICATION_2D_TWOBONEIK_H
diff --git a/scene/resources/skeleton_modification_3d.h b/scene/resources/skeleton_modification_3d.h
index ab736fcbd2..6daf5efcd9 100644
--- a/scene/resources/skeleton_modification_3d.h
+++ b/scene/resources/skeleton_modification_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATION3D_H
-#define SKELETONMODIFICATION3D_H
+#ifndef SKELETON_MODIFICATION_3D_H
+#define SKELETON_MODIFICATION_3D_H
#include "scene/3d/skeleton_3d.h"
#include "scene/resources/skeleton_modification_stack_3d.h"
@@ -76,4 +76,4 @@ public:
SkeletonModification3D();
};
-#endif // SKELETONMODIFICATION3D_H
+#endif // SKELETON_MODIFICATION_3D_H
diff --git a/scene/resources/skeleton_modification_3d_ccdik.h b/scene/resources/skeleton_modification_3d_ccdik.h
index 873ab8aa5a..7098794038 100644
--- a/scene/resources/skeleton_modification_3d_ccdik.h
+++ b/scene/resources/skeleton_modification_3d_ccdik.h
@@ -32,8 +32,8 @@
#include "scene/3d/skeleton_3d.h"
#include "scene/resources/skeleton_modification_3d.h"
-#ifndef SKELETONMODIFICATION3DCCDIK_H
-#define SKELETONMODIFICATION3DCCDIK_H
+#ifndef SKELETON_MODIFICATION_3D_CCDIK_H
+#define SKELETON_MODIFICATION_3D_CCDIK_H
class SkeletonModification3DCCDIK : public SkeletonModification3D {
GDCLASS(SkeletonModification3DCCDIK, SkeletonModification3D);
@@ -111,4 +111,4 @@ public:
~SkeletonModification3DCCDIK();
};
-#endif //SKELETONMODIFICATION3DCCDIK_H
+#endif // SKELETON_MODIFICATION_3D_CCDIK_H
diff --git a/scene/resources/skeleton_modification_3d_fabrik.h b/scene/resources/skeleton_modification_3d_fabrik.h
index cc4d3a5e20..3d66bb6d99 100644
--- a/scene/resources/skeleton_modification_3d_fabrik.h
+++ b/scene/resources/skeleton_modification_3d_fabrik.h
@@ -32,8 +32,8 @@
#include "scene/3d/skeleton_3d.h"
#include "scene/resources/skeleton_modification_3d.h"
-#ifndef SKELETONMODIFICATION3DFABRIK_H
-#define SKELETONMODIFICATION3DFABRIK_H
+#ifndef SKELETON_MODIFICATION_3D_FABRIK_H
+#define SKELETON_MODIFICATION_3D_FABRIK_H
class SkeletonModification3DFABRIK : public SkeletonModification3D {
GDCLASS(SkeletonModification3DFABRIK, SkeletonModification3D);
@@ -121,4 +121,4 @@ public:
~SkeletonModification3DFABRIK();
};
-#endif //SKELETONMODIFICATION3DFABRIK_H
+#endif // SKELETON_MODIFICATION_3D_FABRIK_H
diff --git a/scene/resources/skeleton_modification_3d_jiggle.h b/scene/resources/skeleton_modification_3d_jiggle.h
index 7ec5ed4f11..f41ffcd58d 100644
--- a/scene/resources/skeleton_modification_3d_jiggle.h
+++ b/scene/resources/skeleton_modification_3d_jiggle.h
@@ -32,8 +32,8 @@
#include "scene/3d/skeleton_3d.h"
#include "scene/resources/skeleton_modification_3d.h"
-#ifndef SKELETONMODIFICATION3DJIGGLE_H
-#define SKELETONMODIFICATION3DJIGGLE_H
+#ifndef SKELETON_MODIFICATION_3D_JIGGLE_H
+#define SKELETON_MODIFICATION_3D_JIGGLE_H
class SkeletonModification3DJiggle : public SkeletonModification3D {
GDCLASS(SkeletonModification3DJiggle, SkeletonModification3D);
@@ -135,4 +135,4 @@ public:
~SkeletonModification3DJiggle();
};
-#endif //SKELETONMODIFICATION3DJIGGLE_H
+#endif // SKELETON_MODIFICATION_3D_JIGGLE_H
diff --git a/scene/resources/skeleton_modification_3d_lookat.h b/scene/resources/skeleton_modification_3d_lookat.h
index 9f5120a0fd..4e5714b5dc 100644
--- a/scene/resources/skeleton_modification_3d_lookat.h
+++ b/scene/resources/skeleton_modification_3d_lookat.h
@@ -31,8 +31,8 @@
#include "scene/3d/skeleton_3d.h"
#include "scene/resources/skeleton_modification_3d.h"
-#ifndef SKELETONMODIFICATION3DLOOKAT_H
-#define SKELETONMODIFICATION3DLOOKAT_H
+#ifndef SKELETON_MODIFICATION_3D_LOOKAT_H
+#define SKELETON_MODIFICATION_3D_LOOKAT_H
class SkeletonModification3DLookAt : public SkeletonModification3D {
GDCLASS(SkeletonModification3DLookAt, SkeletonModification3D);
@@ -86,4 +86,4 @@ public:
~SkeletonModification3DLookAt();
};
-#endif //SKELETONMODIFICATION3DLOOKAT_H
+#endif // SKELETON_MODIFICATION_3D_LOOKAT_H
diff --git a/scene/resources/skeleton_modification_3d_stackholder.h b/scene/resources/skeleton_modification_3d_stackholder.h
index 5780d7d43f..ae22099158 100644
--- a/scene/resources/skeleton_modification_3d_stackholder.h
+++ b/scene/resources/skeleton_modification_3d_stackholder.h
@@ -31,8 +31,8 @@
#include "scene/3d/skeleton_3d.h"
#include "scene/resources/skeleton_modification_3d.h"
-#ifndef SKELETONMODIFICATION3DSTACKHOLDER_H
-#define SKELETONMODIFICATION3DSTACKHOLDER_H
+#ifndef SKELETON_MODIFICATION_3D_STACKHOLDER_H
+#define SKELETON_MODIFICATION_3D_STACKHOLDER_H
class SkeletonModification3DStackHolder : public SkeletonModification3D {
GDCLASS(SkeletonModification3DStackHolder, SkeletonModification3D);
@@ -56,4 +56,4 @@ public:
~SkeletonModification3DStackHolder();
};
-#endif //SKELETONMODIFICATION3DSTACKHOLDER_H
+#endif // SKELETON_MODIFICATION_3D_STACKHOLDER_H
diff --git a/scene/resources/skeleton_modification_3d_twoboneik.h b/scene/resources/skeleton_modification_3d_twoboneik.h
index a4ddc6cee7..57e8237511 100644
--- a/scene/resources/skeleton_modification_3d_twoboneik.h
+++ b/scene/resources/skeleton_modification_3d_twoboneik.h
@@ -31,8 +31,8 @@
#include "scene/3d/skeleton_3d.h"
#include "scene/resources/skeleton_modification_3d.h"
-#ifndef SKELETONMODIFICATION3DTWOBONEIK_H
-#define SKELETONMODIFICATION3DTWOBONEIK_H
+#ifndef SKELETON_MODIFICATION_3D_TWOBONEIK_H
+#define SKELETON_MODIFICATION_3D_TWOBONEIK_H
class SkeletonModification3DTwoBoneIK : public SkeletonModification3D {
GDCLASS(SkeletonModification3DTwoBoneIK, SkeletonModification3D);
@@ -115,4 +115,4 @@ public:
~SkeletonModification3DTwoBoneIK();
};
-#endif //SKELETONMODIFICATION3DTWOBONEIK_H
+#endif // SKELETON_MODIFICATION_3D_TWOBONEIK_H
diff --git a/scene/resources/skeleton_modification_stack_2d.h b/scene/resources/skeleton_modification_stack_2d.h
index 7b5f8e0322..ceffd71368 100644
--- a/scene/resources/skeleton_modification_stack_2d.h
+++ b/scene/resources/skeleton_modification_stack_2d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATIONSTACK2D_H
-#define SKELETONMODIFICATIONSTACK2D_H
+#ifndef SKELETON_MODIFICATION_STACK_2D_H
+#define SKELETON_MODIFICATION_STACK_2D_H
#include "scene/2d/skeleton_2d.h"
#include "scene/resources/skeleton_modification_2d.h"
@@ -96,4 +96,4 @@ public:
SkeletonModificationStack2D();
};
-#endif // SKELETONMODIFICATION2D_H
+#endif // SKELETON_MODIFICATION_STACK_2D_H
diff --git a/scene/resources/skeleton_modification_stack_3d.h b/scene/resources/skeleton_modification_stack_3d.h
index 2c17fba2c5..4ff1bd1e33 100644
--- a/scene/resources/skeleton_modification_stack_3d.h
+++ b/scene/resources/skeleton_modification_stack_3d.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SKELETONMODIFICATIONSTACK3D_H
-#define SKELETONMODIFICATIONSTACK3D_H
+#ifndef SKELETON_MODIFICATION_STACK_3D_H
+#define SKELETON_MODIFICATION_STACK_3D_H
#include "core/templates/local_vector.h"
#include "scene/3d/skeleton_3d.h"
@@ -88,4 +88,4 @@ public:
SkeletonModificationStack3D();
};
-#endif // SKELETONMODIFICATIONSTACK3D_H
+#endif // SKELETON_MODIFICATION_STACK_3D_H
diff --git a/scene/resources/skeleton_profile.cpp b/scene/resources/skeleton_profile.cpp
new file mode 100644
index 0000000000..bfb4bb6e2b
--- /dev/null
+++ b/scene/resources/skeleton_profile.cpp
@@ -0,0 +1,835 @@
+/*************************************************************************/
+/* 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("groups/")) {
+ 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);
+ } else {
+ return false;
+ }
+ }
+
+ if (path.begins_with("bones/")) {
+ 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 == "bone_parent") {
+ set_bone_parent(which, p_value);
+ } else if (what == "tail_direction") {
+ set_tail_direction(which, static_cast<TailDirection>((int)p_value));
+ } else if (what == "bone_tail") {
+ set_bone_tail(which, p_value);
+ } else if (what == "reference_pose") {
+ set_reference_pose(which, p_value);
+ } else if (what == "handle_offset") {
+ set_handle_offset(which, p_value);
+ } else if (what == "group") {
+ set_group(which, p_value);
+ } else if (what == "require") {
+ set_require(which, p_value);
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool SkeletonProfile::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path.begins_with("groups/")) {
+ 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);
+ } else {
+ return false;
+ }
+ }
+
+ if (path.begins_with("bones/")) {
+ 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 == "bone_parent") {
+ r_ret = get_bone_parent(which);
+ } else if (what == "tail_direction") {
+ r_ret = get_tail_direction(which);
+ } else if (what == "bone_tail") {
+ r_ret = get_bone_tail(which);
+ } else if (what == "reference_pose") {
+ r_ret = get_reference_pose(which);
+ } else if (what == "handle_offset") {
+ r_ret = get_handle_offset(which);
+ } else if (what == "group") {
+ r_ret = get_group(which);
+ } else if (what == "require") {
+ r_ret = is_require(which);
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+void SkeletonProfile::_validate_property(PropertyInfo &property) const {
+ if (is_read_only) {
+ if (property.name == ("group_size") || property.name == ("bone_size") || property.name == ("root_bone") || property.name == ("scale_base_bone")) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ return;
+ }
+ }
+
+ if (property.name == ("root_bone") || property.name == ("scale_base_bone")) {
+ String hint = "";
+ for (int i = 0; i < bones.size(); i++) {
+ hint += i == 0 ? String(bones[i].bone_name) : "," + String(bones[i].bone_name);
+ }
+ property.hint_string = hint;
+ }
+
+ PackedStringArray split = property.name.split("/");
+ if (split.size() == 3 && split[0] == "bones") {
+ if (split[2] == "bone_tail" && get_tail_direction(split[1].to_int()) != TAIL_DIRECTION_SPECIFIC_CHILD) {
+ property.usage = PROPERTY_USAGE_NONE;
+ }
+ }
+}
+
+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 = "groups/" + 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 = "bones/" + itos(i) + "/";
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_name"));
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_parent"));
+ p_list->push_back(PropertyInfo(Variant::INT, path + "tail_direction", PROPERTY_HINT_ENUM, "AverageChildren,SpecificChild,End"));
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_tail"));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, path + "reference_pose"));
+ 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));
+ p_list->push_back(PropertyInfo(Variant::BOOL, path + "require"));
+ }
+
+ for (PropertyInfo &E : *p_list) {
+ _validate_property(E);
+ }
+}
+
+StringName SkeletonProfile::get_root_bone() {
+ return root_bone;
+}
+
+void SkeletonProfile::set_root_bone(StringName p_bone_name) {
+ if (is_read_only) {
+ return;
+ }
+ root_bone = p_bone_name;
+}
+
+StringName SkeletonProfile::get_scale_base_bone() {
+ return scale_base_bone;
+}
+
+void SkeletonProfile::set_scale_base_bone(StringName p_bone_name) {
+ if (is_read_only) {
+ return;
+ }
+ scale_base_bone = p_bone_name;
+}
+
+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();
+}
+
+int SkeletonProfile::find_bone(StringName p_bone_name) const {
+ if (p_bone_name == StringName()) {
+ return -1;
+ }
+ for (int i = 0; i < bones.size(); i++) {
+ if (bones[i].bone_name == p_bone_name) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+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");
+}
+
+StringName SkeletonProfile::get_bone_parent(int p_bone_idx) const {
+ ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), StringName());
+ return bones[p_bone_idx].bone_parent;
+}
+
+void SkeletonProfile::set_bone_parent(int p_bone_idx, const StringName p_bone_parent) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_bone_idx, bones.size());
+ bones.write[p_bone_idx].bone_parent = p_bone_parent;
+ emit_signal("profile_updated");
+}
+
+SkeletonProfile::TailDirection SkeletonProfile::get_tail_direction(int p_bone_idx) const {
+ ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), TAIL_DIRECTION_AVERAGE_CHILDREN);
+ return bones[p_bone_idx].tail_direction;
+}
+
+void SkeletonProfile::set_tail_direction(int p_bone_idx, const TailDirection p_tail_direction) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_bone_idx, bones.size());
+ bones.write[p_bone_idx].tail_direction = p_tail_direction;
+ emit_signal("profile_updated");
+ notify_property_list_changed();
+}
+
+StringName SkeletonProfile::get_bone_tail(int p_bone_idx) const {
+ ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), StringName());
+ return bones[p_bone_idx].bone_tail;
+}
+
+void SkeletonProfile::set_bone_tail(int p_bone_idx, const StringName p_bone_tail) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_bone_idx, bones.size());
+ bones.write[p_bone_idx].bone_tail = p_bone_tail;
+ emit_signal("profile_updated");
+}
+
+Transform3D SkeletonProfile::get_reference_pose(int p_bone_idx) const {
+ ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), Transform3D());
+ return bones[p_bone_idx].reference_pose;
+}
+
+void SkeletonProfile::set_reference_pose(int p_bone_idx, const Transform3D p_reference_pose) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_bone_idx, bones.size());
+ bones.write[p_bone_idx].reference_pose = p_reference_pose;
+ 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::is_require(int p_bone_idx) const {
+ ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), false);
+ return bones[p_bone_idx].require;
+}
+
+void SkeletonProfile::set_require(int p_bone_idx, const bool p_require) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_bone_idx, bones.size());
+ bones.write[p_bone_idx].require = p_require;
+ 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_root_bone", "bone_name"), &SkeletonProfile::set_root_bone);
+ ClassDB::bind_method(D_METHOD("get_root_bone"), &SkeletonProfile::get_root_bone);
+
+ ClassDB::bind_method(D_METHOD("set_scale_base_bone", "bone_name"), &SkeletonProfile::set_scale_base_bone);
+ ClassDB::bind_method(D_METHOD("get_scale_base_bone"), &SkeletonProfile::get_scale_base_bone);
+
+ 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("find_bone", "bone_name"), &SkeletonProfile::find_bone);
+
+ 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_bone_parent", "bone_idx"), &SkeletonProfile::get_bone_parent);
+ ClassDB::bind_method(D_METHOD("set_bone_parent", "bone_idx", "bone_parent"), &SkeletonProfile::set_bone_parent);
+
+ ClassDB::bind_method(D_METHOD("get_tail_direction", "bone_idx"), &SkeletonProfile::get_tail_direction);
+ ClassDB::bind_method(D_METHOD("set_tail_direction", "bone_idx", "tail_direction"), &SkeletonProfile::set_tail_direction);
+
+ ClassDB::bind_method(D_METHOD("get_bone_tail", "bone_idx"), &SkeletonProfile::get_bone_tail);
+ ClassDB::bind_method(D_METHOD("set_bone_tail", "bone_idx", "bone_tail"), &SkeletonProfile::set_bone_tail);
+
+ ClassDB::bind_method(D_METHOD("get_reference_pose", "bone_idx"), &SkeletonProfile::get_reference_pose);
+ ClassDB::bind_method(D_METHOD("set_reference_pose", "bone_idx", "bone_name"), &SkeletonProfile::set_reference_pose);
+
+ 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::STRING_NAME, "root_bone", PROPERTY_HINT_ENUM_SUGGESTION, ""), "set_root_bone", "get_root_bone");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "scale_base_bone", PROPERTY_HINT_ENUM_SUGGESTION, ""), "set_scale_base_bone", "get_scale_base_bone");
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "group_size", PROPERTY_HINT_RANGE, "0,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Groups,groups/"), "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,bones/"), "set_bone_size", "get_bone_size");
+
+ ADD_SIGNAL(MethodInfo("profile_updated"));
+
+ BIND_ENUM_CONSTANT(TAIL_DIRECTION_AVERAGE_CHILDREN);
+ BIND_ENUM_CONSTANT(TAIL_DIRECTION_SPECIFIC_CHILD);
+ BIND_ENUM_CONSTANT(TAIL_DIRECTION_END);
+}
+
+SkeletonProfile::SkeletonProfile() {
+}
+
+SkeletonProfile::~SkeletonProfile() {
+}
+
+SkeletonProfileHumanoid::SkeletonProfileHumanoid() {
+ is_read_only = true;
+
+ root_bone = "Root";
+ scale_base_bone = "Hips";
+
+ 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].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
+ bones.write[0].handle_offset = Vector2(0.5, 0.91);
+ bones.write[0].group = "Body";
+
+ bones.write[1].bone_name = "Hips";
+ bones.write[1].bone_parent = "Root";
+ bones.write[1].tail_direction = TAIL_DIRECTION_SPECIFIC_CHILD;
+ bones.write[1].bone_tail = "Spine";
+ bones.write[1].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.75, 0);
+ bones.write[1].handle_offset = Vector2(0.5, 0.5);
+ bones.write[1].group = "Body";
+ bones.write[1].require = true;
+
+ bones.write[2].bone_name = "Spine";
+ bones.write[2].bone_parent = "Hips";
+ bones.write[2].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0);
+ bones.write[2].handle_offset = Vector2(0.5, 0.43);
+ bones.write[2].group = "Body";
+ bones.write[2].require = true;
+
+ bones.write[3].bone_name = "Chest";
+ bones.write[3].bone_parent = "Spine";
+ bones.write[3].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0);
+ bones.write[3].handle_offset = Vector2(0.5, 0.36);
+ bones.write[3].group = "Body";
+
+ bones.write[4].bone_name = "UpperChest";
+ bones.write[4].bone_parent = "Chest";
+ bones.write[4].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0);
+ bones.write[4].handle_offset = Vector2(0.5, 0.29);
+ bones.write[4].group = "Body";
+
+ bones.write[5].bone_name = "Neck";
+ bones.write[5].bone_parent = "UpperChest";
+ bones.write[5].tail_direction = TAIL_DIRECTION_SPECIFIC_CHILD;
+ bones.write[5].bone_tail = "Head";
+ bones.write[5].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0);
+ bones.write[5].handle_offset = Vector2(0.5, 0.23);
+ bones.write[5].group = "Body";
+ bones.write[5].require = true;
+
+ bones.write[6].bone_name = "Head";
+ bones.write[6].bone_parent = "Neck";
+ bones.write[6].tail_direction = TAIL_DIRECTION_END;
+ bones.write[6].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0);
+ bones.write[6].handle_offset = Vector2(0.5, 0.18);
+ bones.write[6].group = "Body";
+ bones.write[6].require = true;
+
+ bones.write[7].bone_name = "LeftEye";
+ bones.write[7].bone_parent = "Head";
+ bones.write[7].reference_pose = Transform3D(1, 0, 0, 0, 0, -1, 0, 1, 0, 0.05, 0.15, 0);
+ bones.write[7].handle_offset = Vector2(0.6, 0.46);
+ bones.write[7].group = "Face";
+
+ bones.write[8].bone_name = "RightEye";
+ bones.write[8].bone_parent = "Head";
+ bones.write[8].reference_pose = Transform3D(1, 0, 0, 0, 0, -1, 0, 1, 0, -0.05, 0.15, 0);
+ bones.write[8].handle_offset = Vector2(0.37, 0.46);
+ bones.write[8].group = "Face";
+
+ bones.write[9].bone_name = "Jaw";
+ bones.write[9].bone_parent = "Head";
+ bones.write[9].reference_pose = Transform3D(-1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0.05, 0.05);
+ bones.write[9].handle_offset = Vector2(0.46, 0.75);
+ bones.write[9].group = "Face";
+
+ bones.write[10].bone_name = "LeftShoulder";
+ bones.write[10].bone_parent = "UpperChest";
+ bones.write[10].reference_pose = Transform3D(0, 1, 0, 0, 0, 1, 1, 0, 0, 0.05, 0.1, 0);
+ bones.write[10].handle_offset = Vector2(0.55, 0.235);
+ bones.write[10].group = "Body";
+ bones.write[10].require = true;
+
+ bones.write[11].bone_name = "LeftUpperArm";
+ bones.write[11].bone_parent = "LeftShoulder";
+ bones.write[11].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.05, 0);
+ bones.write[11].handle_offset = Vector2(0.6, 0.24);
+ bones.write[11].group = "Body";
+ bones.write[11].require = true;
+
+ bones.write[12].bone_name = "LeftLowerArm";
+ bones.write[12].bone_parent = "LeftUpperArm";
+ bones.write[12].reference_pose = Transform3D(0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0.25, 0);
+ bones.write[12].handle_offset = Vector2(0.7, 0.24);
+ bones.write[12].group = "Body";
+ bones.write[12].require = true;
+
+ bones.write[13].bone_name = "LeftHand";
+ bones.write[13].bone_parent = "LeftLowerArm";
+ bones.write[13].tail_direction = TAIL_DIRECTION_SPECIFIC_CHILD;
+ bones.write[13].bone_tail = "LeftMiddleProximal";
+ bones.write[13].reference_pose = Transform3D(0, 0, 1, 0, 1, 0, -1, 0, 0, 0, 0.25, 0);
+ bones.write[13].handle_offset = Vector2(0.82, 0.235);
+ bones.write[13].group = "Body";
+ bones.write[13].require = true;
+
+ bones.write[14].bone_name = "LeftThumbMetacarpal";
+ bones.write[14].bone_parent = "LeftHand";
+ bones.write[14].reference_pose = Transform3D(0, -0.577, 0.816, 0.707, 0.577, 0.408, -0.707, 0.577, 0.408, -0.025, 0, 0);
+ bones.write[14].handle_offset = Vector2(0.4, 0.8);
+ bones.write[14].group = "LeftHand";
+
+ bones.write[15].bone_name = "LeftThumbProximal";
+ bones.write[15].bone_parent = "LeftThumbMetacarpal";
+ bones.write[15].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.043, 0);
+ bones.write[15].handle_offset = Vector2(0.3, 0.69);
+ bones.write[15].group = "LeftHand";
+
+ bones.write[16].bone_name = "LeftThumbDistal";
+ bones.write[16].bone_parent = "LeftThumbProximal";
+ bones.write[16].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.043, 0);
+ bones.write[16].handle_offset = Vector2(0.23, 0.555);
+ bones.write[16].group = "LeftHand";
+
+ bones.write[17].bone_name = "LeftIndexProximal";
+ bones.write[17].bone_parent = "LeftHand";
+ bones.write[17].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.025, 0.075, 0);
+ bones.write[17].handle_offset = Vector2(0.413, 0.52);
+ bones.write[17].group = "LeftHand";
+
+ bones.write[18].bone_name = "LeftIndexIntermediate";
+ bones.write[18].bone_parent = "LeftIndexProximal";
+ bones.write[18].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0);
+ bones.write[18].handle_offset = Vector2(0.403, 0.36);
+ bones.write[18].group = "LeftHand";
+
+ bones.write[19].bone_name = "LeftIndexDistal";
+ bones.write[19].bone_parent = "LeftIndexIntermediate";
+ bones.write[19].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0);
+ bones.write[19].handle_offset = Vector2(0.403, 0.255);
+ bones.write[19].group = "LeftHand";
+
+ bones.write[20].bone_name = "LeftMiddleProximal";
+ bones.write[20].bone_parent = "LeftHand";
+ bones.write[20].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.075, 0);
+ bones.write[20].handle_offset = Vector2(0.5, 0.51);
+ bones.write[20].group = "LeftHand";
+
+ bones.write[21].bone_name = "LeftMiddleIntermediate";
+ bones.write[21].bone_parent = "LeftMiddleProximal";
+ bones.write[21].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.075, 0);
+ bones.write[21].handle_offset = Vector2(0.5, 0.345);
+ bones.write[21].group = "LeftHand";
+
+ bones.write[22].bone_name = "LeftMiddleDistal";
+ bones.write[22].bone_parent = "LeftMiddleIntermediate";
+ bones.write[22].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0);
+ bones.write[22].handle_offset = Vector2(0.5, 0.22);
+ bones.write[22].group = "LeftHand";
+
+ bones.write[23].bone_name = "LeftRingProximal";
+ bones.write[23].bone_parent = "LeftHand";
+ bones.write[23].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.025, 0.075, 0);
+ bones.write[23].handle_offset = Vector2(0.586, 0.52);
+ bones.write[23].group = "LeftHand";
+
+ bones.write[24].bone_name = "LeftRingIntermediate";
+ bones.write[24].bone_parent = "LeftRingProximal";
+ bones.write[24].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0);
+ bones.write[24].handle_offset = Vector2(0.59, 0.36);
+ bones.write[24].group = "LeftHand";
+
+ bones.write[25].bone_name = "LeftRingDistal";
+ bones.write[25].bone_parent = "LeftRingIntermediate";
+ bones.write[25].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0);
+ bones.write[25].handle_offset = Vector2(0.591, 0.25);
+ bones.write[25].group = "LeftHand";
+
+ bones.write[26].bone_name = "LeftLittleProximal";
+ bones.write[26].bone_parent = "LeftHand";
+ bones.write[26].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.05, 0.05, 0);
+ bones.write[26].handle_offset = Vector2(0.663, 0.543);
+ bones.write[26].group = "LeftHand";
+
+ bones.write[27].bone_name = "LeftLittleIntermediate";
+ bones.write[27].bone_parent = "LeftLittleProximal";
+ bones.write[27].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0);
+ bones.write[27].handle_offset = Vector2(0.672, 0.415);
+ bones.write[27].group = "LeftHand";
+
+ bones.write[28].bone_name = "LeftLittleDistal";
+ bones.write[28].bone_parent = "LeftLittleIntermediate";
+ bones.write[28].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0);
+ bones.write[28].handle_offset = Vector2(0.672, 0.32);
+ bones.write[28].group = "LeftHand";
+
+ bones.write[29].bone_name = "RightShoulder";
+ bones.write[29].bone_parent = "UpperChest";
+ bones.write[29].reference_pose = Transform3D(0, -1, 0, 0, 0, 1, -1, 0, 0, -0.05, 0.1, 0);
+ bones.write[29].handle_offset = Vector2(0.45, 0.235);
+ bones.write[29].group = "Body";
+ bones.write[29].require = true;
+
+ bones.write[30].bone_name = "RightUpperArm";
+ bones.write[30].bone_parent = "RightShoulder";
+ bones.write[30].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.05, 0);
+ bones.write[30].handle_offset = Vector2(0.4, 0.24);
+ bones.write[30].group = "Body";
+ bones.write[30].require = true;
+
+ bones.write[31].bone_name = "RightLowerArm";
+ bones.write[31].bone_parent = "RightUpperArm";
+ bones.write[31].reference_pose = Transform3D(0, 0, 1, 0, 1, 0, -1, 0, 0, 0, 0.25, 0);
+ bones.write[31].handle_offset = Vector2(0.3, 0.24);
+ bones.write[31].group = "Body";
+ bones.write[31].require = true;
+
+ bones.write[32].bone_name = "RightHand";
+ bones.write[32].bone_parent = "RightLowerArm";
+ bones.write[32].tail_direction = TAIL_DIRECTION_SPECIFIC_CHILD;
+ bones.write[32].bone_tail = "RightMiddleProximal";
+ bones.write[32].reference_pose = Transform3D(0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0.25, 0);
+ bones.write[32].handle_offset = Vector2(0.18, 0.235);
+ bones.write[32].group = "Body";
+ bones.write[32].require = true;
+
+ bones.write[33].bone_name = "RightThumbMetacarpal";
+ bones.write[33].bone_parent = "RightHand";
+ bones.write[33].reference_pose = Transform3D(0, 0.577, -0.816, -0.707, 0.577, 0.408, 0.707, 0.577, 0.408, 0.025, 0, 0);
+ bones.write[33].handle_offset = Vector2(0.6, 0.8);
+ bones.write[33].group = "RightHand";
+
+ bones.write[34].bone_name = "RightThumbProximal";
+ bones.write[34].bone_parent = "RightThumbMetacarpal";
+ bones.write[34].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.043, 0);
+ bones.write[34].handle_offset = Vector2(0.7, 0.69);
+ bones.write[34].group = "RightHand";
+
+ bones.write[35].bone_name = "RightThumbDistal";
+ bones.write[35].bone_parent = "RightThumbProximal";
+ bones.write[35].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.043, 0);
+ bones.write[35].handle_offset = Vector2(0.77, 0.555);
+ bones.write[35].group = "RightHand";
+
+ bones.write[36].bone_name = "RightIndexProximal";
+ bones.write[36].bone_parent = "RightHand";
+ bones.write[36].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.025, 0.075, 0);
+ bones.write[36].handle_offset = Vector2(0.587, 0.52);
+ bones.write[36].group = "RightHand";
+
+ bones.write[37].bone_name = "RightIndexIntermediate";
+ bones.write[37].bone_parent = "RightIndexProximal";
+ bones.write[37].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0);
+ bones.write[37].handle_offset = Vector2(0.597, 0.36);
+ bones.write[37].group = "RightHand";
+
+ bones.write[38].bone_name = "RightIndexDistal";
+ bones.write[38].bone_parent = "RightIndexIntermediate";
+ bones.write[38].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0);
+ bones.write[38].handle_offset = Vector2(0.597, 0.255);
+ bones.write[38].group = "RightHand";
+
+ bones.write[39].bone_name = "RightMiddleProximal";
+ bones.write[39].bone_parent = "RightHand";
+ bones.write[39].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.075, 0);
+ bones.write[39].handle_offset = Vector2(0.5, 0.51);
+ bones.write[39].group = "RightHand";
+
+ bones.write[40].bone_name = "RightMiddleIntermediate";
+ bones.write[40].bone_parent = "RightMiddleProximal";
+ bones.write[40].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.075, 0);
+ bones.write[40].handle_offset = Vector2(0.5, 0.345);
+ bones.write[40].group = "RightHand";
+
+ bones.write[41].bone_name = "RightMiddleDistal";
+ bones.write[41].bone_parent = "RightMiddleIntermediate";
+ bones.write[41].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0);
+ bones.write[41].handle_offset = Vector2(0.5, 0.22);
+ bones.write[41].group = "RightHand";
+
+ bones.write[42].bone_name = "RightRingProximal";
+ bones.write[42].bone_parent = "RightHand";
+ bones.write[42].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.025, 0.075, 0);
+ bones.write[42].handle_offset = Vector2(0.414, 0.52);
+ bones.write[42].group = "RightHand";
+
+ bones.write[43].bone_name = "RightRingIntermediate";
+ bones.write[43].bone_parent = "RightRingProximal";
+ bones.write[43].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0);
+ bones.write[43].handle_offset = Vector2(0.41, 0.36);
+ bones.write[43].group = "RightHand";
+
+ bones.write[44].bone_name = "RightRingDistal";
+ bones.write[44].bone_parent = "RightRingIntermediate";
+ bones.write[44].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0);
+ bones.write[44].handle_offset = Vector2(0.409, 0.25);
+ bones.write[44].group = "RightHand";
+
+ bones.write[45].bone_name = "RightLittleProximal";
+ bones.write[45].bone_parent = "RightHand";
+ bones.write[45].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.05, 0.05, 0);
+ bones.write[45].handle_offset = Vector2(0.337, 0.543);
+ bones.write[45].group = "RightHand";
+
+ bones.write[46].bone_name = "RightLittleIntermediate";
+ bones.write[46].bone_parent = "RightLittleProximal";
+ bones.write[46].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0);
+ bones.write[46].handle_offset = Vector2(0.328, 0.415);
+ bones.write[46].group = "RightHand";
+
+ bones.write[47].bone_name = "RightLittleDistal";
+ bones.write[47].bone_parent = "RightLittleIntermediate";
+ bones.write[47].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0);
+ bones.write[47].handle_offset = Vector2(0.328, 0.32);
+ bones.write[47].group = "RightHand";
+
+ bones.write[48].bone_name = "LeftUpperLeg";
+ bones.write[48].bone_parent = "Hips";
+ bones.write[48].reference_pose = Transform3D(-1, 0, 0, 0, -1, 0, 0, 0, 1, 0.1, 0, 0);
+ bones.write[48].handle_offset = Vector2(0.549, 0.49);
+ bones.write[48].group = "Body";
+ bones.write[48].require = true;
+
+ bones.write[49].bone_name = "LeftLowerLeg";
+ bones.write[49].bone_parent = "LeftUpperLeg";
+ bones.write[49].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.375, 0);
+ bones.write[49].handle_offset = Vector2(0.548, 0.683);
+ bones.write[49].group = "Body";
+ bones.write[49].require = true;
+
+ bones.write[50].bone_name = "LeftFoot";
+ bones.write[50].bone_parent = "LeftLowerLeg";
+ bones.write[50].reference_pose = Transform3D(-1, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0.375, 0);
+ bones.write[50].handle_offset = Vector2(0.545, 0.9);
+ bones.write[50].group = "Body";
+ bones.write[50].require = true;
+
+ bones.write[51].bone_name = "LeftToes";
+ bones.write[51].bone_parent = "LeftFoot";
+ bones.write[51].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.15, 0);
+ bones.write[51].handle_offset = Vector2(0.545, 0.95);
+ bones.write[51].group = "Body";
+
+ bones.write[52].bone_name = "RightUpperLeg";
+ bones.write[52].bone_parent = "Hips";
+ bones.write[52].reference_pose = Transform3D(-1, 0, 0, 0, -1, 0, 0, 0, 1, -0.1, 0, 0);
+ bones.write[52].handle_offset = Vector2(0.451, 0.49);
+ bones.write[52].group = "Body";
+ bones.write[52].require = true;
+
+ bones.write[53].bone_name = "RightLowerLeg";
+ bones.write[53].bone_parent = "RightUpperLeg";
+ bones.write[53].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.375, 0);
+ bones.write[53].handle_offset = Vector2(0.452, 0.683);
+ bones.write[53].group = "Body";
+ bones.write[53].require = true;
+
+ bones.write[54].bone_name = "RightFoot";
+ bones.write[54].bone_parent = "RightLowerLeg";
+ bones.write[54].reference_pose = Transform3D(-1, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0.375, 0);
+ bones.write[54].handle_offset = Vector2(0.455, 0.9);
+ bones.write[54].group = "Body";
+ bones.write[54].require = true;
+
+ bones.write[55].bone_name = "RightToes";
+ bones.write[55].bone_parent = "RightFoot";
+ bones.write[55].reference_pose = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0.15, 0);
+ bones.write[55].handle_offset = Vector2(0.455, 0.95);
+ bones.write[55].group = "Body";
+}
+
+SkeletonProfileHumanoid::~SkeletonProfileHumanoid() {
+}
+
+//////////////////////////////////////
diff --git a/scene/resources/skeleton_profile.h b/scene/resources/skeleton_profile.h
new file mode 100644
index 0000000000..84dfca458e
--- /dev/null
+++ b/scene/resources/skeleton_profile.h
@@ -0,0 +1,140 @@
+/*************************************************************************/
+/* skeleton_profile.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 SKELETON_PROFILE_H
+#define SKELETON_PROFILE_H
+
+#include "texture.h"
+
+class SkeletonProfile : public Resource {
+ GDCLASS(SkeletonProfile, Resource);
+
+public:
+ enum TailDirection {
+ TAIL_DIRECTION_AVERAGE_CHILDREN,
+ TAIL_DIRECTION_SPECIFIC_CHILD,
+ TAIL_DIRECTION_END
+ };
+
+protected:
+ // 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;
+ StringName bone_parent;
+ TailDirection tail_direction = TAIL_DIRECTION_AVERAGE_CHILDREN;
+ StringName bone_tail;
+ Transform3D reference_pose;
+ Vector2 handle_offset;
+ StringName group;
+ bool require = false;
+ };
+
+ StringName root_bone;
+ StringName scale_base_bone;
+
+ 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:
+ StringName get_root_bone();
+ void set_root_bone(StringName p_bone_name);
+
+ StringName get_scale_base_bone();
+ void set_scale_base_bone(StringName p_bone_name);
+
+ int get_group_size();
+ void set_group_size(int p_size);
+
+ StringName get_group_name(int p_group_idx) const;
+ void set_group_name(int p_group_idx, const StringName p_group_name);
+
+ Ref<Texture2D> get_texture(int p_group_idx) const;
+ void set_texture(int p_group_idx, const Ref<Texture2D> &p_texture);
+
+ int get_bone_size();
+ void set_bone_size(int p_size);
+
+ int find_bone(const StringName p_bone_name) const;
+
+ StringName get_bone_name(int p_bone_idx) const;
+ void set_bone_name(int p_bone_idx, const StringName p_bone_name);
+
+ StringName get_bone_parent(int p_bone_idx) const;
+ void set_bone_parent(int p_bone_idx, const StringName p_bone_parent);
+
+ TailDirection get_tail_direction(int p_bone_idx) const;
+ void set_tail_direction(int p_bone_idx, const TailDirection p_tail_direction);
+
+ StringName get_bone_tail(int p_bone_idx) const;
+ void set_bone_tail(int p_bone_idx, const StringName p_bone_tail);
+
+ Transform3D get_reference_pose(int p_bone_idx) const;
+ void set_reference_pose(int p_bone_idx, const Transform3D p_reference_pose);
+
+ 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);
+
+ bool is_require(int p_bone_idx) const;
+ void set_require(int p_bone_idx, const bool p_require);
+
+ bool has_bone(StringName p_bone_name);
+
+ SkeletonProfile();
+ ~SkeletonProfile();
+};
+
+class SkeletonProfileHumanoid : public SkeletonProfile {
+ GDCLASS(SkeletonProfileHumanoid, SkeletonProfile);
+
+public:
+ SkeletonProfileHumanoid();
+ ~SkeletonProfileHumanoid();
+};
+
+VARIANT_ENUM_CAST(SkeletonProfile::TailDirection);
+
+#endif // SKELETON_PROFILE_H
diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h
index 5be8922ba4..61999af3c4 100644
--- a/scene/resources/sky_material.h
+++ b/scene/resources/sky_material.h
@@ -219,4 +219,4 @@ public:
~PhysicalSkyMaterial();
};
-#endif /* !SKY_MATERIAL_H */
+#endif // SKY_MATERIAL_H
diff --git a/scene/resources/sphere_shape_3d.h b/scene/resources/sphere_shape_3d.h
index 8f77378ef4..91d72e01ec 100644
--- a/scene/resources/sphere_shape_3d.h
+++ b/scene/resources/sphere_shape_3d.h
@@ -52,4 +52,4 @@ public:
SphereShape3D();
};
-#endif // SPHERE_SHAPE_H
+#endif // SPHERE_SHAPE_3D_H
diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp
index ba21b9fd17..55c9d7397d 100644
--- a/scene/resources/sprite_frames.cpp
+++ b/scene/resources/sprite_frames.cpp
@@ -96,17 +96,6 @@ void SpriteFrames::rename_animation(const StringName &p_prev, const StringName &
animations[p_next] = anim;
}
-Vector<String> SpriteFrames::_get_animation_list() const {
- Vector<String> ret;
- List<StringName> al;
- get_animation_list(&al);
- for (const StringName &E : al) {
- ret.push_back(E);
- }
-
- return ret;
-}
-
void SpriteFrames::get_animation_list(List<StringName> *r_animations) const {
for (const KeyValue<StringName, Anim> &E : animations) {
r_animations->push_back(E.key);
@@ -147,31 +136,22 @@ bool SpriteFrames::get_animation_loop(const StringName &p_anim) const {
return E->value.loop;
}
-void SpriteFrames::_set_frames(const Array &p_frames) {
- clear_all();
- HashMap<StringName, Anim>::Iterator E = animations.find(SceneStringNames::get_singleton()->_default);
- ERR_FAIL_COND(!E);
-
- E->value.frames.resize(p_frames.size());
- for (int i = 0; i < E->value.frames.size(); i++) {
- E->value.frames.write[i] = p_frames[i];
- }
-}
-
-Array SpriteFrames::_get_frames() const {
- return Array();
-}
-
Array SpriteFrames::_get_animations() const {
Array anims;
- for (const KeyValue<StringName, Anim> &E : animations) {
+
+ List<StringName> sorted_names;
+ get_animation_list(&sorted_names);
+ sorted_names.sort_custom<StringName::AlphCompare>();
+
+ for (const StringName &name : sorted_names) {
+ const Anim &anim = animations[name];
Dictionary d;
- d["name"] = E.key;
- d["speed"] = E.value.speed;
- d["loop"] = E.value.loop;
+ d["name"] = name;
+ d["speed"] = anim.speed;
+ d["loop"] = anim.loop;
Array frames;
- for (int i = 0; i < E.value.frames.size(); i++) {
- frames.push_back(E.value.frames[i]);
+ for (int i = 0; i < anim.frames.size(); i++) {
+ frames.push_back(anim.frames[i]);
}
d["frames"] = frames;
anims.push_back(d);
@@ -225,15 +205,12 @@ void SpriteFrames::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear);
ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all);
- ClassDB::bind_method(D_METHOD("_set_frames"), &SpriteFrames::_set_frames);
- ClassDB::bind_method(D_METHOD("_get_frames"), &SpriteFrames::_get_frames);
-
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "frames", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_frames", "_get_frames"); //compatibility
+ // `animations` property is for serialization.
ClassDB::bind_method(D_METHOD("_set_animations"), &SpriteFrames::_set_animations);
ClassDB::bind_method(D_METHOD("_get_animations"), &SpriteFrames::_get_animations);
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations");
}
SpriteFrames::SpriteFrames() {
diff --git a/scene/resources/sprite_frames.h b/scene/resources/sprite_frames.h
index e32ccc1336..87d84b70c0 100644
--- a/scene/resources/sprite_frames.h
+++ b/scene/resources/sprite_frames.h
@@ -44,14 +44,9 @@ class SpriteFrames : public Resource {
HashMap<StringName, Anim> animations;
- Array _get_frames() const;
- void _set_frames(const Array &p_frames);
-
Array _get_animations() const;
void _set_animations(const Array &p_animations);
- Vector<String> _get_animation_list() const;
-
protected:
static void _bind_methods();
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index 3b3654775f..9f4f69d3ba 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -264,4 +264,4 @@ public:
~StyleBoxLine();
};
-#endif
+#endif // STYLE_BOX_H
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index 2d399ca3bf..6735d6623f 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -207,4 +207,4 @@ public:
VARIANT_ENUM_CAST(SurfaceTool::CustomFormat)
VARIANT_ENUM_CAST(SurfaceTool::SkinWeightCount)
-#endif
+#endif // SURFACE_TOOL_H
diff --git a/scene/resources/syntax_highlighter.h b/scene/resources/syntax_highlighter.h
index 1243a9dbf7..69131ffbee 100644
--- a/scene/resources/syntax_highlighter.h
+++ b/scene/resources/syntax_highlighter.h
@@ -142,4 +142,4 @@ public:
Color get_member_variable_color() const;
};
-#endif
+#endif // SYNTAX_HIGHLIGHTER_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_file.h b/scene/resources/text_file.h
index 0c8cf855f0..168e4f5879 100644
--- a/scene/resources/text_file.h
+++ b/scene/resources/text_file.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef TEXTFILE_H
-#define TEXTFILE_H
+#ifndef TEXT_FILE_H
+#define TEXT_FILE_H
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
@@ -51,4 +51,4 @@ public:
Error load_text(const String &p_path);
};
-#endif // TEXTFILE_H
+#endif // TEXT_FILE_H
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index d6e7ca3478..823d742d72 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));
@@ -74,7 +74,7 @@ void TextLine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flags", "flags"), &TextLine::set_flags);
ClassDB::bind_method(D_METHOD("get_flags"), &TextLine::get_flags);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justify,Word Justify,Trim Edge Spaces After Justify,Justify Only After Last Tab"), "set_flags", "get_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justification,Word Justification,Trim Edge Spaces After Justification,Justify Only After Last Tab,Constrain Ellipsis"), "set_flags", "get_flags");
ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &TextLine::set_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &TextLine::get_text_overrun_behavior);
@@ -106,24 +106,24 @@ void TextLine::_shape() {
TS->shaped_text_tab_align(rid, tab_stops);
}
- uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIM;
+ BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM;
if (overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
switch (overrun_behavior) {
case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS:
- overrun_flags |= TextServer::OVERRUN_TRIM;
- overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
- overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
+ overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
break;
case TextServer::OVERRUN_TRIM_ELLIPSIS:
- overrun_flags |= TextServer::OVERRUN_TRIM;
- overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
break;
case TextServer::OVERRUN_TRIM_WORD:
- overrun_flags |= TextServer::OVERRUN_TRIM;
- overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
break;
case TextServer::OVERRUN_TRIM_CHAR:
- overrun_flags |= TextServer::OVERRUN_TRIM;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
break;
case TextServer::OVERRUN_NO_TRIMMING:
break;
@@ -131,7 +131,7 @@ void TextLine::_shape() {
if (alignment == HORIZONTAL_ALIGNMENT_FILL) {
TS->shaped_text_fit_to_width(rid, width, flags);
- overrun_flags |= TextServer::OVERRUN_JUSTIFICATION_AWARE;
+ overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE);
TS->shaped_text_overrun_trim_to_width(rid, width, overrun_flags);
} else {
TS->shaped_text_overrun_trim_to_width(rid, width, overrun_flags);
@@ -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;
}
@@ -242,14 +241,14 @@ void TextLine::tab_align(const Vector<float> &p_tab_stops) {
dirty = true;
}
-void TextLine::set_flags(uint16_t p_flags) {
+void TextLine::set_flags(BitField<TextServer::JustificationFlag> p_flags) {
if (flags != p_flags) {
flags = p_flags;
dirty = true;
}
}
-uint16_t TextLine::get_flags() const {
+BitField<TextServer::JustificationFlag> TextLine::get_flags() const {
return flags;
}
@@ -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..e70e82cf2b 100644
--- a/scene/resources/text_line.h
+++ b/scene/resources/text_line.h
@@ -41,13 +41,11 @@ class TextLine : public RefCounted {
private:
RID rid;
- int spacing_top = 0;
- int spacing_bottom = 0;
bool dirty = true;
float width = -1.0;
- uint16_t flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA;
+ BitField<TextServer::JustificationFlag> flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA;
HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT;
TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_TRIM_ELLIPSIS;
@@ -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);
@@ -86,8 +84,8 @@ public:
void tab_align(const Vector<float> &p_tab_stops);
- void set_flags(uint16_t p_flags);
- uint16_t get_flags() const;
+ void set_flags(BitField<TextServer::JustificationFlag> p_flags);
+ BitField<TextServer::JustificationFlag> get_flags() const;
void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior);
TextServer::OverrunBehavior get_text_overrun_behavior() const;
@@ -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..43d3f329fa 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));
@@ -74,10 +74,15 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("tab_align", "tab_stops"), &TextParagraph::tab_align);
- ClassDB::bind_method(D_METHOD("set_flags", "flags"), &TextParagraph::set_flags);
- ClassDB::bind_method(D_METHOD("get_flags"), &TextParagraph::get_flags);
+ ClassDB::bind_method(D_METHOD("set_break_flags", "flags"), &TextParagraph::set_break_flags);
+ ClassDB::bind_method(D_METHOD("get_break_flags"), &TextParagraph::get_break_flags);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justify,Word Justify,Trim Edge Spaces After Justify,Justify Only After Last Tab,Break Mandatory,Break Words,Break Graphemes"), "set_flags", "get_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "break_flags", PROPERTY_HINT_FLAGS, "Mandatory,Word Bound,Grapheme Bound,Adaptive"), "set_break_flags", "get_break_flags");
+
+ ClassDB::bind_method(D_METHOD("set_justification_flags", "flags"), &TextParagraph::set_justification_flags);
+ ClassDB::bind_method(D_METHOD("get_justification_flags"), &TextParagraph::get_justification_flags);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "justification_flags", PROPERTY_HINT_FLAGS, "Kashida Justification,Word Justification,Trim Edge Spaces After Justification,Justify Only After Last Tab,Constrain Ellipsis"), "set_justification_flags", "get_justification_flags");
ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &TextParagraph::set_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &TextParagraph::get_text_overrun_behavior);
@@ -113,9 +118,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);
@@ -157,7 +159,7 @@ void TextParagraph::_shape_lines() {
if (h_offset > 0) {
// Dropcap, flow around.
- PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width - h_offset, 0, flags);
+ PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width - h_offset, 0, brk_flags);
for (int i = 0; i < line_breaks.size(); i = i + 2) {
RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
float h = (TS->shaped_text_get_orientation(line) == TextServer::ORIENTATION_HORIZONTAL) ? TS->shaped_text_get_size(line).y : TS->shaped_text_get_size(line).x;
@@ -175,7 +177,7 @@ void TextParagraph::_shape_lines() {
}
}
// Use fixed for the rest of lines.
- PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width, start, flags);
+ PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width, start, brk_flags);
for (int i = 0; i < line_breaks.size(); i = i + 2) {
RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
if (!tab_stops.is_empty()) {
@@ -184,43 +186,43 @@ void TextParagraph::_shape_lines() {
lines_rid.push_back(line);
}
- uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIM;
+ BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM;
if (overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
switch (overrun_behavior) {
case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS:
- overrun_flags |= TextServer::OVERRUN_TRIM;
- overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
- overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
+ overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
break;
case TextServer::OVERRUN_TRIM_ELLIPSIS:
- overrun_flags |= TextServer::OVERRUN_TRIM;
- overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
break;
case TextServer::OVERRUN_TRIM_WORD:
- overrun_flags |= TextServer::OVERRUN_TRIM;
- overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
break;
case TextServer::OVERRUN_TRIM_CHAR:
- overrun_flags |= TextServer::OVERRUN_TRIM;
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
break;
case TextServer::OVERRUN_NO_TRIMMING:
break;
}
}
- bool autowrap_enabled = ((flags & TextServer::BREAK_WORD_BOUND) == TextServer::BREAK_WORD_BOUND) || ((flags & TextServer::BREAK_GRAPHEME_BOUND) == TextServer::BREAK_GRAPHEME_BOUND);
+ bool autowrap_enabled = brk_flags.has_flag(TextServer::BREAK_WORD_BOUND) || brk_flags.has_flag(TextServer::BREAK_GRAPHEME_BOUND);
// Fill after min_size calculation.
if (autowrap_enabled) {
int visible_lines = (max_lines_visible >= 0) ? MIN(max_lines_visible, (int)lines_rid.size()) : (int)lines_rid.size();
bool lines_hidden = visible_lines > 0 && visible_lines < (int)lines_rid.size();
if (lines_hidden) {
- overrun_flags |= TextServer::OVERRUN_ENFORCE_ELLIPSIS;
+ overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS);
}
if (alignment == HORIZONTAL_ALIGNMENT_FILL) {
for (int i = 0; i < (int)lines_rid.size(); i++) {
if (i < visible_lines - 1 || (int)lines_rid.size() == 1) {
- TS->shaped_text_fit_to_width(lines_rid[i], width, flags);
+ TS->shaped_text_fit_to_width(lines_rid[i], width, jst_flags);
} else if (i == (visible_lines - 1)) {
TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags);
}
@@ -234,10 +236,10 @@ void TextParagraph::_shape_lines() {
// Autowrap disabled.
for (int i = 0; i < (int)lines_rid.size(); i++) {
if (alignment == HORIZONTAL_ALIGNMENT_FILL) {
- TS->shaped_text_fit_to_width(lines_rid[i], width, flags);
- overrun_flags |= TextServer::OVERRUN_JUSTIFICATION_AWARE;
+ TS->shaped_text_fit_to_width(lines_rid[i], width, jst_flags);
+ overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE);
TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
- TS->shaped_text_fit_to_width(lines_rid[i], width, flags | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
+ TS->shaped_text_fit_to_width(lines_rid[i], width, jst_flags | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
} else {
TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
}
@@ -266,8 +268,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 +347,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_
@@ -432,17 +425,30 @@ void TextParagraph::tab_align(const Vector<float> &p_tab_stops) {
lines_dirty = true;
}
-void TextParagraph::set_flags(uint16_t p_flags) {
+void TextParagraph::set_justification_flags(BitField<TextServer::JustificationFlag> p_flags) {
_THREAD_SAFE_METHOD_
- if (flags != p_flags) {
- flags = p_flags;
+ if (jst_flags != p_flags) {
+ jst_flags = p_flags;
lines_dirty = true;
}
}
-uint16_t TextParagraph::get_flags() const {
- return flags;
+BitField<TextServer::JustificationFlag> TextParagraph::get_justification_flags() const {
+ return jst_flags;
+}
+
+void TextParagraph::set_break_flags(BitField<TextServer::LineBreakFlag> p_flags) {
+ _THREAD_SAFE_METHOD_
+
+ if (brk_flags != p_flags) {
+ brk_flags = p_flags;
+ lines_dirty = true;
+ }
+}
+
+BitField<TextServer::LineBreakFlag> TextParagraph::get_break_flags() const {
+ return brk_flags;
}
void TextParagraph::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
@@ -476,9 +482,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 +498,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 +544,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 +558,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 +577,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 +585,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 +653,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 +662,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 +717,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 +755,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 +764,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 +819,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 +846,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 +914,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 +929,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..0fe82b4364 100644
--- a/scene/resources/text_paragraph.h
+++ b/scene/resources/text_paragraph.h
@@ -48,15 +48,14 @@ private:
RID rid;
LocalVector<RID> lines_rid;
- int spacing_top = 0;
- int spacing_bottom = 0;
bool lines_dirty = true;
float width = -1.0;
int max_lines_visible = -1;
- uint16_t flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA;
+ BitField<TextServer::LineBreakFlag> brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND;
+ BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA;
TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING;
HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT;
@@ -92,10 +91,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);
@@ -104,8 +103,11 @@ public:
void tab_align(const Vector<float> &p_tab_stops);
- void set_flags(uint16_t p_flags);
- uint16_t get_flags() const;
+ void set_justification_flags(BitField<TextServer::JustificationFlag> p_flags);
+ BitField<TextServer::JustificationFlag> get_justification_flags() const;
+
+ void set_break_flags(BitField<TextServer::LineBreakFlag> p_flags);
+ BitField<TextServer::LineBreakFlag> get_break_flags() const;
void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior);
TextServer::OverrunBehavior get_text_overrun_behavior() const;
@@ -151,7 +153,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..05ed9238b8 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();
@@ -291,8 +300,8 @@ bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const {
return true;
}
-void ImageTexture::set_size_override(const Size2 &p_size) {
- Size2 s = p_size;
+void ImageTexture::set_size_override(const Size2i &p_size) {
+ Size2i s = p_size;
if (s.x != 0) {
w = s.x;
}
@@ -311,9 +320,10 @@ 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("set_image", "image"), &ImageTexture::set_image);
ClassDB::bind_method(D_METHOD("update", "image"), &ImageTexture::update);
ClassDB::bind_method(D_METHOD("set_size_override", "size"), &ImageTexture::set_size_override);
}
@@ -1999,7 +2009,7 @@ void CurveXYZTexture::set_curve_x(Ref<Curve> p_curve) {
}
_curve_x = p_curve;
if (_curve_x.is_valid()) {
- _curve_x->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED);
+ _curve_x->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), CONNECT_REFERENCE_COUNTED);
}
_update();
}
@@ -2012,7 +2022,7 @@ void CurveXYZTexture::set_curve_y(Ref<Curve> p_curve) {
}
_curve_y = p_curve;
if (_curve_y.is_valid()) {
- _curve_y->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED);
+ _curve_y->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), CONNECT_REFERENCE_COUNTED);
}
_update();
}
@@ -2025,7 +2035,7 @@ void CurveXYZTexture::set_curve_z(Ref<Curve> p_curve) {
}
_curve_z = p_curve;
if (_curve_z.is_valid()) {
- _curve_z->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED);
+ _curve_z->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), CONNECT_REFERENCE_COUNTED);
}
_update();
}
@@ -2148,7 +2158,7 @@ void GradientTexture1D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &GradientTexture1D::_update);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_gradient", "get_gradient");
ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,16384,suffix:px"), "set_width", "get_width");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr");
}
@@ -3016,12 +3026,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..36b193c5d4 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;
@@ -129,7 +130,7 @@ public:
bool is_pixel_opaque(int p_x, int p_y) const override;
- void set_size_override(const Size2 &p_size);
+ void set_size_override(const Size2i &p_size);
virtual void set_path(const String &p_path, bool p_take_over = false) override;
@@ -1105,4 +1106,4 @@ public:
PlaceholderTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {}
};
-#endif
+#endif // TEXTURE_H
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 39b77568cf..3f6eec8497 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -295,7 +295,7 @@ void Theme::set_default_font(const Ref<Font> &p_default_font) {
default_font = p_default_font;
if (default_font.is_valid()) {
- default_font->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(false), CONNECT_REFERENCE_COUNTED);
+ default_font->connect("changed", callable_mp(this, &Theme::_emit_theme_changed).bind(false), CONNECT_REFERENCE_COUNTED);
}
_emit_theme_changed();
@@ -341,7 +341,7 @@ void Theme::set_icon(const StringName &p_name, const StringName &p_theme_type, c
icon_map[p_theme_type][p_name] = p_icon;
if (p_icon.is_valid()) {
- icon_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(false), CONNECT_REFERENCE_COUNTED);
+ icon_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed).bind(false), CONNECT_REFERENCE_COUNTED);
}
_emit_theme_changed(!existing);
@@ -451,7 +451,7 @@ void Theme::set_stylebox(const StringName &p_name, const StringName &p_theme_typ
style_map[p_theme_type][p_name] = p_style;
if (p_style.is_valid()) {
- style_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(false), CONNECT_REFERENCE_COUNTED);
+ style_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed).bind(false), CONNECT_REFERENCE_COUNTED);
}
_emit_theme_changed(!existing);
@@ -561,7 +561,7 @@ void Theme::set_font(const StringName &p_name, const StringName &p_theme_type, c
font_map[p_theme_type][p_name] = p_font;
if (p_font.is_valid()) {
- font_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(false), CONNECT_REFERENCE_COUNTED);
+ font_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed).bind(false), CONNECT_REFERENCE_COUNTED);
}
_emit_theme_changed(!existing);
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index 87d7d2fdea..a2aca5e61f 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -256,4 +256,4 @@ public:
VARIANT_ENUM_CAST(Theme::DataType);
-#endif
+#endif // THEME_H
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 13b671e562..b0b9f1228f 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -1048,13 +1048,13 @@ int TileSet::get_custom_data_layer_by_name(String p_value) const {
}
}
-void TileSet::set_custom_data_name(int p_layer_id, String p_value) {
+void TileSet::set_custom_data_layer_name(int p_layer_id, String p_value) {
ERR_FAIL_INDEX(p_layer_id, custom_data_layers.size());
// Exit if another property has the same name.
if (!p_value.is_empty()) {
for (int other_layer_id = 0; other_layer_id < get_custom_data_layers_count(); other_layer_id++) {
- if (other_layer_id != p_layer_id && get_custom_data_name(other_layer_id) == p_value) {
+ if (other_layer_id != p_layer_id && get_custom_data_layer_name(other_layer_id) == p_value) {
ERR_FAIL_MSG(vformat("There is already a custom property named %s", p_value));
}
}
@@ -1070,12 +1070,12 @@ void TileSet::set_custom_data_name(int p_layer_id, String p_value) {
emit_changed();
}
-String TileSet::get_custom_data_name(int p_layer_id) const {
+String TileSet::get_custom_data_layer_name(int p_layer_id) const {
ERR_FAIL_INDEX_V(p_layer_id, custom_data_layers.size(), "");
return custom_data_layers[p_layer_id].name;
}
-void TileSet::set_custom_data_type(int p_layer_id, Variant::Type p_value) {
+void TileSet::set_custom_data_layer_type(int p_layer_id, Variant::Type p_value) {
ERR_FAIL_INDEX(p_layer_id, custom_data_layers.size());
custom_data_layers.write[p_layer_id].type = p_value;
@@ -1086,7 +1086,7 @@ void TileSet::set_custom_data_type(int p_layer_id, Variant::Type p_value) {
emit_changed();
}
-Variant::Type TileSet::get_custom_data_type(int p_layer_id) const {
+Variant::Type TileSet::get_custom_data_layer_type(int p_layer_id) const {
ERR_FAIL_INDEX_V(p_layer_id, custom_data_layers.size(), Variant::NIL);
return custom_data_layers[p_layer_id].type;
}
@@ -1801,19 +1801,16 @@ Vector<Vector<Ref<Texture2D>>> TileSet::generate_terrains_icons(Size2i p_size) {
if (counts[terrain_set][terrain].count > 0) {
// Get the best tile.
Ref<Texture2D> texture = counts[terrain_set][terrain].texture;
- Rect2 region = counts[terrain_set][terrain].region;
+ Rect2i region = counts[terrain_set][terrain].region;
image->create(region.size.x, region.size.y, false, Image::FORMAT_RGBA8);
- image->blit_rect(texture->get_image(), region, Point2());
+ image->blit_rect(texture->get_image(), region, Point2i());
image->resize(p_size.x, p_size.y, Image::INTERPOLATE_NEAREST);
} else {
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;
}
}
@@ -2470,9 +2467,42 @@ Vector<Point2> TileSet::_get_half_offset_side_terrain_peering_bit_polygon(Vector
}
void TileSet::reset_state() {
+ // Rendering
occlusion_layers.clear();
+ tile_lines_mesh.instantiate();
+ tile_filled_mesh.instantiate();
+ tile_meshes_dirty = true;
+
+ // Physics
physics_layers.clear();
+
+ // Terrains
+ terrain_sets.clear();
+ terrain_meshes.clear();
+ terrain_peering_bits_meshes.clear();
+ per_terrain_pattern_tiles.clear();
+ terrains_cache_dirty = true;
+
+ // Navigation
+ navigation_layers.clear();
+
custom_data_layers.clear();
+ custom_data_layers_by_name.clear();
+
+ // Proxies
+ source_level_proxies.clear();
+ coords_level_proxies.clear();
+ alternative_level_proxies.clear();
+
+#ifndef DISABLE_DEPRECATED
+ for (const KeyValue<int, CompatibilityTileData *> &E : compatibility_data) {
+ memdelete(E.value);
+ }
+ compatibility_data.clear();
+#endif // DISABLE_DEPRECATED
+ while (!source_ids.is_empty()) {
+ remove_source(source_ids[0]);
+ }
}
const Vector2i TileSetSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1);
@@ -3006,14 +3036,14 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
while (index >= custom_data_layers.size()) {
add_custom_data_layer();
}
- set_custom_data_name(index, p_value);
+ set_custom_data_layer_name(index, p_value);
return true;
} else if (components[1] == "type") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
while (index >= custom_data_layers.size()) {
add_custom_data_layer();
}
- set_custom_data_type(index, Variant::Type(int(p_value)));
+ set_custom_data_layer_type(index, Variant::Type(int(p_value)));
return true;
}
} else if (components.size() == 2 && components[0] == "sources" && components[1].is_valid_int()) {
@@ -3135,10 +3165,10 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
return false;
}
if (components[1] == "name") {
- r_ret = get_custom_data_name(index);
+ r_ret = get_custom_data_layer_name(index);
return true;
} else if (components[1] == "type") {
- r_ret = get_custom_data_type(index);
+ r_ret = get_custom_data_layer_type(index);
return true;
}
} else if (components.size() == 2 && components[0] == "sources" && components[1].is_valid_int()) {
@@ -3361,6 +3391,11 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_custom_data_layer", "to_position"), &TileSet::add_custom_data_layer, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("move_custom_data_layer", "layer_index", "to_position"), &TileSet::move_custom_data_layer);
ClassDB::bind_method(D_METHOD("remove_custom_data_layer", "layer_index"), &TileSet::remove_custom_data_layer);
+ ClassDB::bind_method(D_METHOD("get_custom_data_layer_by_name", "layer_name"), &TileSet::get_custom_data_layer_by_name);
+ ClassDB::bind_method(D_METHOD("set_custom_data_layer_name", "layer_index", "layer_name"), &TileSet::set_custom_data_layer_name);
+ ClassDB::bind_method(D_METHOD("get_custom_data_layer_name", "layer_index"), &TileSet::get_custom_data_layer_name);
+ ClassDB::bind_method(D_METHOD("set_custom_data_layer_type", "layer_index", "layer_type"), &TileSet::set_custom_data_layer_type);
+ ClassDB::bind_method(D_METHOD("get_custom_data_layer_type", "layer_index"), &TileSet::get_custom_data_layer_type);
// Tile proxies
ClassDB::bind_method(D_METHOD("set_source_level_tile_proxy", "source_from", "source_to"), &TileSet::set_source_level_tile_proxy);
@@ -3460,6 +3495,10 @@ void TileSetSource::set_tile_set(const TileSet *p_tile_set) {
tile_set = p_tile_set;
}
+void TileSetSource::reset_state() {
+ tile_set = nullptr;
+};
+
void TileSetSource::_bind_methods() {
// Base tiles
ClassDB::bind_method(D_METHOD("get_tiles_count"), &TileSetSource::get_tiles_count);
@@ -3643,12 +3682,17 @@ void TileSetAtlasSource::remove_custom_data_layer(int p_index) {
}
void TileSetAtlasSource::reset_state() {
- // Reset all TileData.
+ tile_set = nullptr;
+
for (KeyValue<Vector2i, TileAlternativesData> &E_tile : tiles) {
- for (KeyValue<int, TileData *> &E_alternative : E_tile.value.alternatives) {
- E_alternative.value->reset_state();
+ for (const KeyValue<int, TileData *> &E_tile_data : E_tile.value.alternatives) {
+ memdelete(E_tile_data.value);
}
}
+ _coords_mapping_cache.clear();
+ tiles.clear();
+ tiles_ids.clear();
+ _queue_update_padded_texture();
}
void TileSetAtlasSource::set_texture(Ref<Texture2D> p_texture) {
@@ -3930,7 +3974,7 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const {
tile_property_list.push_back(property_info);
// animation_frames_count.
- tile_property_list.push_back(PropertyInfo(Variant::INT, "animation_frames_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NETWORK));
+ tile_property_list.push_back(PropertyInfo(Variant::INT, "animation_frames_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
// animation_frame_*.
bool store_durations = tiles[E_tile.key].animation_frames_durations.size() >= 2;
@@ -4594,7 +4638,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();
}
@@ -4808,14 +4852,14 @@ void TileData::notify_tile_data_properties_should_change() {
// Convert custom data to the new type.
custom_data.resize(tile_set->get_custom_data_layers_count());
for (int i = 0; i < custom_data.size(); i++) {
- if (custom_data[i].get_type() != tile_set->get_custom_data_type(i)) {
+ if (custom_data[i].get_type() != tile_set->get_custom_data_layer_type(i)) {
Variant new_val;
Callable::CallError error;
- if (Variant::can_convert(custom_data[i].get_type(), tile_set->get_custom_data_type(i))) {
+ if (Variant::can_convert(custom_data[i].get_type(), tile_set->get_custom_data_layer_type(i))) {
const Variant *args[] = { &custom_data[i] };
- Variant::construct(tile_set->get_custom_data_type(i), new_val, args, 1, error);
+ Variant::construct(tile_set->get_custom_data_layer_type(i), new_val, args, 1, error);
} else {
- Variant::construct(tile_set->get_custom_data_type(i), new_val, nullptr, 0, error);
+ Variant::construct(tile_set->get_custom_data_layer_type(i), new_val, nullptr, 0, error);
}
custom_data.write[i] = new_val;
}
@@ -4924,6 +4968,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;
@@ -4974,13 +5022,6 @@ void TileData::remove_custom_data_layer(int p_index) {
custom_data.remove_at(p_index);
}
-void TileData::reset_state() {
- occluders.clear();
- physics.clear();
- navigation.clear();
- custom_data.clear();
-}
-
void TileData::set_allow_transform(bool p_allow_transform) {
allow_transform = p_allow_transform;
}
@@ -5625,7 +5666,7 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
Variant default_val;
Callable::CallError error;
Variant::construct(custom_data[i].get_type(), default_val, nullptr, 0, error);
- property_info = PropertyInfo(tile_set->get_custom_data_type(i), vformat("custom_data_%d", i), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
+ property_info = PropertyInfo(tile_set->get_custom_data_layer_type(i), vformat("custom_data_%d", i), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
if (custom_data[i] == default_val) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 7368d2bd87..6ea3889fce 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -479,10 +479,10 @@ public:
void move_custom_data_layer(int p_from_index, int p_to_pos);
void remove_custom_data_layer(int p_index);
int get_custom_data_layer_by_name(String p_value) const;
- void set_custom_data_name(int p_layer_id, String p_value);
- String get_custom_data_name(int p_layer_id) const;
- void set_custom_data_type(int p_layer_id, Variant::Type p_value);
- Variant::Type get_custom_data_type(int p_layer_id) const;
+ void set_custom_data_layer_name(int p_layer_id, String p_value);
+ String get_custom_data_layer_name(int p_layer_id) const;
+ void set_custom_data_layer_type(int p_layer_id, Variant::Type p_value);
+ Variant::Type get_custom_data_layer_type(int p_layer_id) const;
// Tiles proxies.
void set_source_level_tile_proxy(int p_source_from, int p_source_to);
@@ -569,7 +569,7 @@ public:
virtual void add_custom_data_layer(int p_index){};
virtual void move_custom_data_layer(int p_from_index, int p_to_pos){};
virtual void remove_custom_data_layer(int p_index){};
- virtual void reset_state() override{};
+ virtual void reset_state() override;
// Tiles.
virtual int get_tiles_count() const = 0;
@@ -847,7 +847,6 @@ public:
void add_custom_data_layer(int p_index);
void move_custom_data_layer(int p_from_index, int p_to_pos);
void remove_custom_data_layer(int p_index);
- void reset_state();
void set_allow_transform(bool p_allow_transform);
bool is_allowing_transform() const;
diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h
index 3e154d539b..35686b293c 100644
--- a/scene/resources/video_stream.h
+++ b/scene/resources/video_stream.h
@@ -72,7 +72,7 @@ class VideoStream : public Resource {
public:
virtual void set_audio_track(int p_track) = 0;
- virtual Ref<VideoStreamPlayback> instance_playback() = 0;
+ virtual Ref<VideoStreamPlayback> instantiate_playback() = 0;
};
-#endif
+#endif // VIDEO_STREAM_H
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index b8eac6de00..a67716d52b 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -30,6 +30,7 @@
#include "visual_shader.h"
+#include "core/templates/rb_map.h"
#include "core/templates/vmap.h"
#include "servers/rendering/shader_types.h"
#include "visual_shader_nodes.h"
@@ -966,6 +967,12 @@ void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from
ERR_FAIL_COND(!g->nodes.has(p_to_node));
ERR_FAIL_INDEX(p_to_port, g->nodes[p_to_node].node->get_input_port_count());
+ for (const Connection &E : g->connections) {
+ if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) {
+ return;
+ }
+ }
+
Connection c;
c.from_node = p_from_node;
c.from_port = p_from_port;
@@ -2640,6 +2647,10 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_world", "NODE_POSITION_WORLD" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_position_world", "CAMERA_POSITION_WORLD" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" },
// Node3D, Fragment
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
@@ -2668,6 +2679,10 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_world", "NODE_POSITION_WORLD" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_position_world", "CAMERA_POSITION_WORLD" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" },
// Node3D, Light
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
@@ -3189,18 +3204,18 @@ VisualShaderNodeInput::VisualShaderNodeInput() {
////////////// UniformRef
-List<VisualShaderNodeUniformRef::Uniform> uniforms;
+RBMap<RID, List<VisualShaderNodeUniformRef::Uniform>> uniforms;
-void VisualShaderNodeUniformRef::add_uniform(const String &p_name, UniformType p_type) {
- uniforms.push_back({ p_name, p_type });
+void VisualShaderNodeUniformRef::add_uniform(RID p_shader_rid, const String &p_name, UniformType p_type) {
+ uniforms[p_shader_rid].push_back({ p_name, p_type });
}
-void VisualShaderNodeUniformRef::clear_uniforms() {
- uniforms.clear();
+void VisualShaderNodeUniformRef::clear_uniforms(RID p_shader_rid) {
+ uniforms[p_shader_rid].clear();
}
-bool VisualShaderNodeUniformRef::has_uniform(const String &p_name) {
- for (const VisualShaderNodeUniformRef::Uniform &E : uniforms) {
+bool VisualShaderNodeUniformRef::has_uniform(RID p_shader_rid, const String &p_name) {
+ for (const VisualShaderNodeUniformRef::Uniform &E : uniforms[p_shader_rid]) {
if (E.name == p_name) {
return true;
}
@@ -3313,14 +3328,24 @@ String VisualShaderNodeUniformRef::get_output_port_name(int p_port) const {
return "";
}
+void VisualShaderNodeUniformRef::set_shader_rid(const RID &p_shader_rid) {
+ shader_rid = p_shader_rid;
+}
+
void VisualShaderNodeUniformRef::set_uniform_name(const String &p_name) {
uniform_name = p_name;
+ if (shader_rid.is_valid()) {
+ update_uniform_type();
+ }
+ emit_changed();
+}
+
+void VisualShaderNodeUniformRef::update_uniform_type() {
if (uniform_name != "[None]") {
uniform_type = get_uniform_type_by_name(uniform_name);
} else {
uniform_type = UniformType::UNIFORM_TYPE_FLOAT;
}
- emit_changed();
}
String VisualShaderNodeUniformRef::get_uniform_name() const {
@@ -3328,35 +3353,45 @@ String VisualShaderNodeUniformRef::get_uniform_name() const {
}
int VisualShaderNodeUniformRef::get_uniforms_count() const {
- return uniforms.size();
+ ERR_FAIL_COND_V(!shader_rid.is_valid(), 0);
+
+ return uniforms[shader_rid].size();
}
String VisualShaderNodeUniformRef::get_uniform_name_by_index(int p_idx) const {
- if (p_idx >= 0 && p_idx < uniforms.size()) {
- return uniforms[p_idx].name;
+ ERR_FAIL_COND_V(!shader_rid.is_valid(), String());
+
+ if (p_idx >= 0 && p_idx < uniforms[shader_rid].size()) {
+ return uniforms[shader_rid][p_idx].name;
}
return "";
}
VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_name(const String &p_name) const {
- for (int i = 0; i < uniforms.size(); i++) {
- if (uniforms[i].name == p_name) {
- return uniforms[i].type;
+ ERR_FAIL_COND_V(!shader_rid.is_valid(), UNIFORM_TYPE_FLOAT);
+
+ for (int i = 0; i < uniforms[shader_rid].size(); i++) {
+ if (uniforms[shader_rid][i].name == p_name) {
+ return uniforms[shader_rid][i].type;
}
}
return UniformType::UNIFORM_TYPE_FLOAT;
}
VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_index(int p_idx) const {
- if (p_idx >= 0 && p_idx < uniforms.size()) {
- return uniforms[p_idx].type;
+ ERR_FAIL_COND_V(!shader_rid.is_valid(), UNIFORM_TYPE_FLOAT);
+
+ if (p_idx >= 0 && p_idx < uniforms[shader_rid].size()) {
+ return uniforms[shader_rid][p_idx].type;
}
return UniformType::UNIFORM_TYPE_FLOAT;
}
VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_port_type_by_index(int p_idx) const {
- if (p_idx >= 0 && p_idx < uniforms.size()) {
- switch (uniforms[p_idx].type) {
+ ERR_FAIL_COND_V(!shader_rid.is_valid(), PORT_TYPE_SCALAR);
+
+ if (p_idx >= 0 && p_idx < uniforms[shader_rid].size()) {
+ switch (uniforms[shader_rid][p_idx].type) {
case UniformType::UNIFORM_TYPE_FLOAT:
return PORT_TYPE_SCALAR;
case UniformType::UNIFORM_TYPE_INT:
@@ -3724,7 +3759,7 @@ String VisualShaderNodeUniform::get_warning(Shader::Mode p_mode, VisualShader::T
}
return vformat(RTR("This uniform type does not support the '%s' qualifier."), qualifier_str);
} else if (qualifier == Qualifier::QUAL_GLOBAL) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(uniform_name);
+ RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(uniform_name);
if (gvt == RS::GLOBAL_VAR_TYPE_MAX) {
return vformat(RTR("Global uniform '%s' does not exist.\nCreate it in the Project Settings."), uniform_name);
}
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index afd84e49cc..7ca4e5fc4a 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -561,6 +561,7 @@ public:
};
private:
+ RID shader_rid;
String uniform_name = "[None]";
UniformType uniform_type = UniformType::UNIFORM_TYPE_FLOAT;
@@ -568,9 +569,9 @@ protected:
static void _bind_methods();
public:
- static void add_uniform(const String &p_name, UniformType p_type);
- static void clear_uniforms();
- static bool has_uniform(const String &p_name);
+ static void add_uniform(RID p_shader_rid, const String &p_name, UniformType p_type);
+ static void clear_uniforms(RID p_shader_rid);
+ static bool has_uniform(RID p_shader_rid, const String &p_name);
public:
virtual String get_caption() const override;
@@ -583,9 +584,13 @@ public:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ void set_shader_rid(const RID &p_shader);
+
void set_uniform_name(const String &p_name);
String get_uniform_name() const;
+ void update_uniform_type();
+
void _set_uniform_type(int p_uniform_type);
int _get_uniform_type() const;
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index b8667f07fe..b422d298b2 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -1901,13 +1901,7 @@ String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader
code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
break;
case OP_REFLECT:
- if (op_type == OP_TYPE_VECTOR_2D) { // Not supported.
- code += "vec2(0.0);\n";
- } else if (op_type == OP_TYPE_VECTOR_4D) { // Not supported.
- code += "vec4(0.0);\n";
- } else {
- code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
- }
+ code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
break;
case OP_STEP:
code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
@@ -1967,7 +1961,7 @@ String VisualShaderNodeVectorOp::get_warning(Shader::Mode p_mode, VisualShader::
bool invalid_type = false;
if (op_type == OP_TYPE_VECTOR_2D || op_type == OP_TYPE_VECTOR_4D) {
- if (op == OP_CROSS || op == OP_REFLECT) {
+ if (op == OP_CROSS) {
invalid_type = true;
}
}
@@ -4006,14 +4000,6 @@ int VisualShaderNodeVectorRefract::get_input_port_count() const {
return 3;
}
-VisualShaderNodeVectorRefract::PortType VisualShaderNodeVectorRefract::get_input_port_type(int p_port) const {
- if (p_port == 2) {
- return PORT_TYPE_SCALAR;
- }
-
- return PORT_TYPE_VECTOR_3D;
-}
-
String VisualShaderNodeVectorRefract::get_input_port_name(int p_port) const {
switch (p_port) {
case 0:
@@ -4030,10 +4016,6 @@ int VisualShaderNodeVectorRefract::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVectorRefract::PortType VisualShaderNodeVectorRefract::get_output_port_type(int p_port) const {
- return PORT_TYPE_VECTOR_3D;
-}
-
String VisualShaderNodeVectorRefract::get_output_port_name(int p_port) const {
return "";
}
@@ -4042,6 +4024,31 @@ String VisualShaderNodeVectorRefract::generate_code(Shader::Mode p_mode, VisualS
return " " + p_output_vars[0] + " = refract(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}
+void VisualShaderNodeVectorRefract::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
+ return;
+ }
+ switch (p_op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1));
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
+ } break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1));
+ } break;
+ default:
+ break;
+ }
+ op_type = p_op_type;
+ emit_changed();
+}
+
VisualShaderNodeVectorRefract::VisualShaderNodeVectorRefract() {
set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0));
set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0));
@@ -5581,12 +5588,16 @@ String get_sampler_hint(VisualShaderNodeTextureUniform::TextureType p_texture_ty
case VisualShaderNodeTextureUniform::TYPE_DATA:
if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_BLACK) {
type_code = "hint_default_black";
+ } else if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_TRANSPARENT) {
+ type_code = "hint_default_transparent";
}
break;
case VisualShaderNodeTextureUniform::TYPE_COLOR:
type_code = "source_color";
if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_BLACK) {
type_code += ", hint_default_black";
+ } else if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_TRANSPARENT) {
+ type_code += ", hint_default_transparent";
}
break;
case VisualShaderNodeTextureUniform::TYPE_NORMAL_MAP:
@@ -5812,7 +5823,7 @@ void VisualShaderNodeTextureUniform::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_texture_repeat"), &VisualShaderNodeTextureUniform::get_texture_repeat);
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map,Anisotropic"), "set_texture_type", "get_texture_type");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White,Black"), "set_color_default", "get_color_default");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White,Black,Transparent"), "set_color_default", "get_color_default");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Default,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Default,Enabled,Disabled"), "set_texture_repeat", "get_texture_repeat");
@@ -5824,6 +5835,7 @@ void VisualShaderNodeTextureUniform::_bind_methods() {
BIND_ENUM_CONSTANT(COLOR_DEFAULT_WHITE);
BIND_ENUM_CONSTANT(COLOR_DEFAULT_BLACK);
+ BIND_ENUM_CONSTANT(COLOR_DEFAULT_TRANSPARENT);
BIND_ENUM_CONSTANT(COLOR_DEFAULT_MAX);
BIND_ENUM_CONSTANT(FILTER_DEFAULT);
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 1eb7b7240f..ffcb41072d 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -1564,21 +1564,20 @@ public:
/// REFRACT
///////////////////////////////////////
-class VisualShaderNodeVectorRefract : public VisualShaderNode {
- GDCLASS(VisualShaderNodeVectorRefract, VisualShaderNode);
+class VisualShaderNodeVectorRefract : public VisualShaderNodeVectorBase {
+ GDCLASS(VisualShaderNodeVectorRefract, VisualShaderNodeVectorBase);
public:
virtual String get_caption() const override;
virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual int get_output_port_count() const override;
- virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+ virtual void set_op_type(OpType p_op_type) override;
VisualShaderNodeVectorRefract();
};
@@ -2131,6 +2130,7 @@ public:
enum ColorDefault {
COLOR_DEFAULT_WHITE,
COLOR_DEFAULT_BLACK,
+ COLOR_DEFAULT_TRANSPARENT,
COLOR_DEFAULT_MAX,
};
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/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h
index 05a059373b..64acb6d18f 100644
--- a/scene/resources/visual_shader_particle_nodes.h
+++ b/scene/resources/visual_shader_particle_nodes.h
@@ -352,4 +352,4 @@ public:
VARIANT_ENUM_CAST(VisualShaderNodeParticleEmit::EmitFlags)
-#endif
+#endif // VISUAL_SHADER_PARTICLE_NODES_H
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/scene/resources/world_boundary_shape_3d.h b/scene/resources/world_boundary_shape_3d.h
index 5378bc52c7..5c34767106 100644
--- a/scene/resources/world_boundary_shape_3d.h
+++ b/scene/resources/world_boundary_shape_3d.h
@@ -53,4 +53,5 @@ public:
WorldBoundaryShape3D();
};
-#endif // WORLD_BOUNDARY_SHAPE_H
+
+#endif // WORLD_BOUNDARY_SHAPE_3D_H
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 232a8d5e1f..8f47e64d8b 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -85,4 +85,4 @@ public:
~AudioDriverDummy() {}
};
-#endif
+#endif // AUDIO_DRIVER_DUMMY_H
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index 3a0578679d..653d04595e 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECT_H
-#define AUDIOEFFECT_H
+#ifndef AUDIO_EFFECT_H
+#define AUDIO_EFFECT_H
#include "core/io/resource.h"
#include "core/math/audio_frame.h"
@@ -62,4 +62,4 @@ public:
AudioEffect();
};
-#endif // AUDIOEFFECT_H
+#endif // AUDIO_EFFECT_H
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 5d9a9e61dc..80485845c9 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -83,6 +83,10 @@ int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_fra
return 0;
}
+void AudioStreamPlayback::tag_used_streams() {
+ GDVIRTUAL_CALL(_tag_used_streams);
+}
+
void AudioStreamPlayback::_bind_methods() {
GDVIRTUAL_BIND(_start, "from_pos")
GDVIRTUAL_BIND(_stop)
@@ -91,6 +95,7 @@ void AudioStreamPlayback::_bind_methods() {
GDVIRTUAL_BIND(_get_playback_position)
GDVIRTUAL_BIND(_seek, "position")
GDVIRTUAL_BIND(_mix, "buffer", "rate_scale", "frames");
+ GDVIRTUAL_BIND(_tag_used_streams);
}
//////////////////////////////
@@ -187,9 +192,9 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
////////////////////////////////
-Ref<AudioStreamPlayback> AudioStream::instance_playback() {
+Ref<AudioStreamPlayback> AudioStream::instantiate_playback() {
Ref<AudioStreamPlayback> ret;
- if (GDVIRTUAL_CALL(_instance_playback, ret)) {
+ if (GDVIRTUAL_CALL(_instantiate_playback, ret)) {
return ret;
}
ERR_FAIL_V_MSG(Ref<AudioStreamPlayback>(), "Method must be implemented!");
@@ -218,19 +223,74 @@ bool AudioStream::is_monophonic() const {
return true;
}
+double AudioStream::get_bpm() const {
+ double ret = 0;
+ if (GDVIRTUAL_CALL(_get_bpm, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+bool AudioStream::has_loop() const {
+ bool ret = 0;
+ if (GDVIRTUAL_CALL(_has_loop, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int AudioStream::get_bar_beats() const {
+ int ret = 0;
+ if (GDVIRTUAL_CALL(_get_bar_beats, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int AudioStream::get_beat_count() const {
+ int ret = 0;
+ if (GDVIRTUAL_CALL(_get_beat_count, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void AudioStream::tag_used(float p_offset) {
+ if (tagged_frame != AudioServer::get_singleton()->get_mixed_frames()) {
+ offset_count = 0;
+ tagged_frame = AudioServer::get_singleton()->get_mixed_frames();
+ }
+ if (offset_count < MAX_TAGGED_OFFSETS) {
+ tagged_offsets[offset_count++] = p_offset;
+ }
+}
+
+uint64_t AudioStream::get_tagged_frame() const {
+ return tagged_frame;
+}
+uint32_t AudioStream::get_tagged_frame_count() const {
+ return offset_count;
+}
+float AudioStream::get_tagged_frame_offset(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, MAX_TAGGED_OFFSETS, 0);
+ return tagged_offsets[p_index];
+}
+
void AudioStream::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length);
ClassDB::bind_method(D_METHOD("is_monophonic"), &AudioStream::is_monophonic);
- ClassDB::bind_method(D_METHOD("instance_playback"), &AudioStream::instance_playback);
- GDVIRTUAL_BIND(_instance_playback);
+ ClassDB::bind_method(D_METHOD("instantiate_playback"), &AudioStream::instantiate_playback);
+ GDVIRTUAL_BIND(_instantiate_playback);
GDVIRTUAL_BIND(_get_stream_name);
GDVIRTUAL_BIND(_get_length);
GDVIRTUAL_BIND(_is_monophonic);
+ GDVIRTUAL_BIND(_get_bpm)
+ GDVIRTUAL_BIND(_get_beat_count)
}
////////////////////////////////
-Ref<AudioStreamPlayback> AudioStreamMicrophone::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamMicrophone::instantiate_playback() {
Ref<AudioStreamPlaybackMicrophone> playback;
playback.instantiate();
@@ -363,6 +423,10 @@ void AudioStreamPlaybackMicrophone::seek(float p_time) {
// Can't seek a microphone input
}
+void AudioStreamPlaybackMicrophone::tag_used_streams() {
+ microphone->tag_used(0);
+}
+
AudioStreamPlaybackMicrophone::~AudioStreamPlaybackMicrophone() {
microphone->playbacks.erase(this);
stop();
@@ -490,7 +554,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_random() {
for (PoolEntry &entry : local_pool) {
cumulative_weight += entry.weight;
if (cumulative_weight > chosen_cumulative_weight) {
- playback->playback = entry.stream->instance_playback();
+ playback->playback = entry.stream->instantiate_playback();
last_playback = entry.stream;
break;
}
@@ -498,7 +562,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_random() {
if (playback->playback.is_null()) {
// This indicates a floating point error. Take the last element.
last_playback = local_pool[local_pool.size() - 1].stream;
- playback->playback = local_pool.write[local_pool.size() - 1].stream->instance_playback();
+ playback->playback = local_pool.write[local_pool.size() - 1].stream->instantiate_playback();
}
return playback;
}
@@ -532,14 +596,14 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_no_repeats() {
cumulative_weight += entry.weight;
if (cumulative_weight > chosen_cumulative_weight) {
last_playback = entry.stream;
- playback->playback = entry.stream->instance_playback();
+ playback->playback = entry.stream->instantiate_playback();
break;
}
}
if (playback->playback.is_null()) {
// This indicates a floating point error. Take the last element.
last_playback = local_pool[local_pool.size() - 1].stream;
- playback->playback = local_pool.write[local_pool.size() - 1].stream->instance_playback();
+ playback->playback = local_pool.write[local_pool.size() - 1].stream->instantiate_playback();
}
return playback;
}
@@ -568,7 +632,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() {
for (Ref<AudioStream> &entry : local_pool) {
if (found_last_stream) {
last_playback = entry;
- playback->playback = entry->instance_playback();
+ playback->playback = entry->instantiate_playback();
break;
}
if (entry == last_playback) {
@@ -578,12 +642,12 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() {
if (playback->playback.is_null()) {
// Wrap around
last_playback = local_pool[0];
- playback->playback = local_pool.write[0]->instance_playback();
+ playback->playback = local_pool.write[0]->instantiate_playback();
}
return playback;
}
-Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamRandomizer::instantiate_playback() {
switch (playback_mode) {
case PLAYBACK_RANDOM:
return instance_playback_random();
@@ -696,7 +760,7 @@ void AudioStreamRandomizer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "streams_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_streams_count", "get_streams_count");
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_mode", PROPERTY_HINT_ENUM, "Random (Avoid Repeats),Random,Sequential"), "set_playback_mode", "get_playback_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_pitch", PROPERTY_HINT_RANGE, "1,16,0.01"), "set_random_pitch", "get_random_pitch");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0,suffix:dB"), "set_random_volume_offset_db", "get_random_volume_offset_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0.01,suffix:dB"), "set_random_volume_offset_db", "get_random_volume_offset_db");
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM_NO_REPEATS);
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM);
@@ -762,6 +826,14 @@ void AudioStreamPlaybackRandomizer::seek(float p_time) {
}
}
+void AudioStreamPlaybackRandomizer::tag_used_streams() {
+ Ref<AudioStreamPlayback> p = playing; // Thread safety
+ if (p.is_valid()) {
+ p->tag_used_streams();
+ }
+ randomizer->tag_used(0);
+}
+
int AudioStreamPlaybackRandomizer::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
if (playing.is_valid()) {
return playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index bf200e7ecf..7c4577977d 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -40,6 +40,8 @@
#include "core/object/script_language.h"
#include "core/variant/native_ptr.h"
+class AudioStream;
+
class AudioStreamPlayback : public RefCounted {
GDCLASS(AudioStreamPlayback, RefCounted);
@@ -52,6 +54,7 @@ protected:
GDVIRTUAL0RC(float, _get_playback_position)
GDVIRTUAL1(_seek, float)
GDVIRTUAL3R(int, _mix, GDNativePtr<AudioFrame>, float, int)
+ GDVIRTUAL0(_tag_used_streams)
public:
virtual void start(float p_from_pos = 0.0);
virtual void stop();
@@ -62,6 +65,8 @@ public:
virtual float get_playback_position() const;
virtual void seek(float p_time);
+ virtual void tag_used_streams();
+
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
};
@@ -72,7 +77,7 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback {
FP_BITS = 16, //fixed point used for resampling
FP_LEN = (1 << FP_BITS),
FP_MASK = FP_LEN - 1,
- INTERNAL_BUFFER_LEN = 256,
+ INTERNAL_BUFFER_LEN = 128, // 128 warrants 3ms positional jitter at much at 44100hz
CUBIC_INTERP_HISTORY = 4
};
@@ -101,20 +106,42 @@ class AudioStream : public Resource {
GDCLASS(AudioStream, Resource);
OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged.
+ enum {
+ MAX_TAGGED_OFFSETS = 8
+ };
+
+ uint64_t tagged_frame = 0;
+ uint64_t offset_count = 0;
+ float tagged_offsets[MAX_TAGGED_OFFSETS];
+
protected:
static void _bind_methods();
- GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instance_playback)
+ GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instantiate_playback)
GDVIRTUAL0RC(String, _get_stream_name)
GDVIRTUAL0RC(float, _get_length)
GDVIRTUAL0RC(bool, _is_monophonic)
+ GDVIRTUAL0RC(double, _get_bpm)
+ GDVIRTUAL0RC(bool, _has_loop)
+ GDVIRTUAL0RC(int, _get_bar_beats)
+ GDVIRTUAL0RC(int, _get_beat_count)
public:
- virtual Ref<AudioStreamPlayback> instance_playback();
+ virtual Ref<AudioStreamPlayback> instantiate_playback();
virtual String get_stream_name() const;
+ virtual double get_bpm() const;
+ virtual bool has_loop() const;
+ virtual int get_bar_beats() const;
+ virtual int get_beat_count() const;
+
virtual float get_length() const;
virtual bool is_monophonic() const;
+
+ void tag_used(float p_offset);
+ uint64_t get_tagged_frame() const;
+ uint32_t get_tagged_frame_count() const;
+ float get_tagged_frame_offset(int p_index) const;
};
// Microphone
@@ -131,7 +158,7 @@ protected:
static void _bind_methods();
public:
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
virtual float get_length() const override; //if supported, otherwise return 0
@@ -153,6 +180,7 @@ class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
protected:
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
virtual float get_stream_sampling_rate() override;
+ virtual float get_playback_position() const override;
public:
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
@@ -163,9 +191,10 @@ public:
virtual int get_loop_count() const override; //times it looped
- virtual float get_playback_position() const override;
virtual void seek(float p_time) override;
+ virtual void tag_used_streams() override;
+
~AudioStreamPlaybackMicrophone();
AudioStreamPlaybackMicrophone();
};
@@ -233,7 +262,7 @@ public:
void set_playback_mode(PlaybackMode p_playback_mode);
PlaybackMode get_playback_mode() const;
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
virtual float get_length() const override; //if supported, otherwise return 0
@@ -265,6 +294,8 @@ public:
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
+ virtual void tag_used_streams() override;
+
~AudioStreamPlaybackRandomizer();
};
diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h
index bd0fcaa94d..fd424cbe9a 100644
--- a/servers/audio/effects/audio_effect_amplify.h
+++ b/servers/audio/effects/audio_effect_amplify.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTAMPLIFY_H
-#define AUDIOEFFECTAMPLIFY_H
+#ifndef AUDIO_EFFECT_AMPLIFY_H
+#define AUDIO_EFFECT_AMPLIFY_H
#include "servers/audio/audio_effect.h"
@@ -63,4 +63,4 @@ public:
AudioEffectAmplify();
};
-#endif // AUDIOEFFECTAMPLIFY_H
+#endif // AUDIO_EFFECT_AMPLIFY_H
diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h
index 19035222c5..72b495f7f9 100644
--- a/servers/audio/effects/audio_effect_chorus.h
+++ b/servers/audio/effects/audio_effect_chorus.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTCHORUS_H
-#define AUDIOEFFECTCHORUS_H
+#ifndef AUDIO_EFFECT_CHORUS_H
+#define AUDIO_EFFECT_CHORUS_H
#include "servers/audio/audio_effect.h"
@@ -133,4 +133,4 @@ public:
AudioEffectChorus();
};
-#endif // AUDIOEFFECTCHORUS_H
+#endif // AUDIO_EFFECT_CHORUS_H
diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h
index 53c448e5db..998bd3c978 100644
--- a/servers/audio/effects/audio_effect_compressor.h
+++ b/servers/audio/effects/audio_effect_compressor.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTCOMPRESSOR_H
-#define AUDIOEFFECTCOMPRESSOR_H
+#ifndef AUDIO_EFFECT_COMPRESSOR_H
+#define AUDIO_EFFECT_COMPRESSOR_H
#include "servers/audio/audio_effect.h"
@@ -91,4 +91,4 @@ public:
AudioEffectCompressor();
};
-#endif // AUDIOEFFECTCOMPRESSOR_H
+#endif // AUDIO_EFFECT_COMPRESSOR_H
diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h
index 5cc6d72c99..137a4e7dbe 100644
--- a/servers/audio/effects/audio_effect_delay.h
+++ b/servers/audio/effects/audio_effect_delay.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTDELAY_H
-#define AUDIOEFFECTDELAY_H
+#ifndef AUDIO_EFFECT_DELAY_H
+#define AUDIO_EFFECT_DELAY_H
#include "servers/audio/audio_effect.h"
@@ -131,4 +131,4 @@ public:
AudioEffectDelay();
};
-#endif // AUDIOEFFECTDELAY_H
+#endif // AUDIO_EFFECT_DELAY_H
diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h
index 487babbdda..c845a0e53c 100644
--- a/servers/audio/effects/audio_effect_distortion.h
+++ b/servers/audio/effects/audio_effect_distortion.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTDISTORTION_H
-#define AUDIOEFFECTDISTORTION_H
+#ifndef AUDIO_EFFECT_DISTORTION_H
+#define AUDIO_EFFECT_DISTORTION_H
#include "servers/audio/audio_effect.h"
@@ -90,4 +90,4 @@ public:
VARIANT_ENUM_CAST(AudioEffectDistortion::Mode)
-#endif // AUDIOEFFECTDISTORTION_H
+#endif // AUDIO_EFFECT_DISTORTION_H
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
index b7c373479a..500abd3a6f 100644
--- a/servers/audio/effects/audio_effect_eq.cpp
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "audio_effect_eq.h"
+
#include "servers/audio_server.h"
void AudioEffectEQInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h
index 9b0560223f..b80fb7c73c 100644
--- a/servers/audio/effects/audio_effect_eq.h
+++ b/servers/audio/effects/audio_effect_eq.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTEQ_H
-#define AUDIOEFFECTEQ_H
+#ifndef AUDIO_EFFECT_EQ_H
+#define AUDIO_EFFECT_EQ_H
#include "servers/audio/audio_effect.h"
-#include "servers/audio/effects/eq.h"
+#include "servers/audio/effects/eq_filter.h"
class AudioEffectEQ;
@@ -98,4 +98,4 @@ public:
AudioEffectEQ(EQ::PRESET_21_BANDS) {}
};
-#endif // AUDIOEFFECTEQ_H
+#endif // AUDIO_EFFECT_EQ_H
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index d5d58ddaa3..a40af2f13c 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTFILTER_H
-#define AUDIOEFFECTFILTER_H
+#ifndef AUDIO_EFFECT_FILTER_H
+#define AUDIO_EFFECT_FILTER_H
#include "servers/audio/audio_effect.h"
#include "servers/audio/audio_filter_sw.h"
@@ -167,4 +167,4 @@ public:
AudioEffectFilter(AudioFilterSW::HIGHSHELF) {}
};
-#endif // AUDIOEFFECTFILTER_H
+#endif // AUDIO_EFFECT_FILTER_H
diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h
index d05c9902af..3eca71a926 100644
--- a/servers/audio/effects/audio_effect_panner.h
+++ b/servers/audio/effects/audio_effect_panner.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTPANNER_H
-#define AUDIOEFFECTPANNER_H
+#ifndef AUDIO_EFFECT_PANNER_H
+#define AUDIO_EFFECT_PANNER_H
#include "servers/audio/audio_effect.h"
@@ -61,4 +61,4 @@ public:
AudioEffectPanner();
};
-#endif // AUDIOEFFECTPANNER_H
+#endif // AUDIO_EFFECT_PANNER_H
diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp
index a6553e1431..fff6dbc32a 100644
--- a/servers/audio/effects/audio_effect_record.cpp
+++ b/servers/audio/effects/audio_effect_record.cpp
@@ -199,16 +199,16 @@ bool AudioEffectRecord::is_recording_active() const {
return recording_active;
}
-void AudioEffectRecord::set_format(AudioStreamSample::Format p_format) {
+void AudioEffectRecord::set_format(AudioStreamWAV::Format p_format) {
format = p_format;
}
-AudioStreamSample::Format AudioEffectRecord::get_format() const {
+AudioStreamWAV::Format AudioEffectRecord::get_format() const {
return format;
}
-Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
- AudioStreamSample::Format dst_format = format;
+Ref<AudioStreamWAV> AudioEffectRecord::get_recording() const {
+ AudioStreamWAV::Format dst_format = format;
bool stereo = true; //forcing mono is not implemented
Vector<uint8_t> dst_data;
@@ -216,7 +216,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
ERR_FAIL_COND_V(current_instance.is_null(), nullptr);
ERR_FAIL_COND_V(current_instance->recording_data.size() == 0, nullptr);
- if (dst_format == AudioStreamSample::FORMAT_8_BITS) {
+ if (dst_format == AudioStreamWAV::FORMAT_8_BITS) {
int data_size = current_instance->recording_data.size();
dst_data.resize(data_size);
uint8_t *w = dst_data.ptrw();
@@ -225,7 +225,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
int8_t v = CLAMP(current_instance->recording_data[i] * 128, -128, 127);
w[i] = v;
}
- } else if (dst_format == AudioStreamSample::FORMAT_16_BITS) {
+ } else if (dst_format == AudioStreamWAV::FORMAT_16_BITS) {
int data_size = current_instance->recording_data.size();
dst_data.resize(data_size * 2);
uint8_t *w = dst_data.ptrw();
@@ -234,7 +234,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
int16_t v = CLAMP(current_instance->recording_data[i] * 32768, -32768, 32767);
encode_uint16(v, &w[i * 2]);
}
- } else if (dst_format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+ } else if (dst_format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
//byte interleave
Vector<float> left;
Vector<float> right;
@@ -273,12 +273,12 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
ERR_PRINT("Format not implemented.");
}
- Ref<AudioStreamSample> sample;
+ Ref<AudioStreamWAV> sample;
sample.instantiate();
sample->set_data(dst_data);
sample->set_format(dst_format);
sample->set_mix_rate(AudioServer::get_singleton()->get_mix_rate());
- sample->set_loop_mode(AudioStreamSample::LOOP_DISABLED);
+ sample->set_loop_mode(AudioStreamWAV::LOOP_DISABLED);
sample->set_loop_begin(0);
sample->set_loop_end(0);
sample->set_stereo(stereo);
@@ -297,6 +297,6 @@ void AudioEffectRecord::_bind_methods() {
}
AudioEffectRecord::AudioEffectRecord() {
- format = AudioStreamSample::FORMAT_16_BITS;
+ format = AudioStreamWAV::FORMAT_16_BITS;
recording_active = false;
}
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index 8a6247e27a..e89d8adbde 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTRECORD_H
-#define AUDIOEFFECTRECORD_H
+#ifndef AUDIO_EFFECT_RECORD_H
+#define AUDIO_EFFECT_RECORD_H
#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/os/thread.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.h"
#include "servers/audio/audio_effect.h"
#include "servers/audio_server.h"
@@ -85,7 +85,7 @@ class AudioEffectRecord : public AudioEffect {
bool recording_active;
Ref<AudioEffectRecordInstance> current_instance;
- AudioStreamSample::Format format;
+ AudioStreamWAV::Format format;
void ensure_thread_stopped();
@@ -96,11 +96,11 @@ public:
Ref<AudioEffectInstance> instantiate() override;
void set_recording_active(bool p_record);
bool is_recording_active() const;
- void set_format(AudioStreamSample::Format p_format);
- AudioStreamSample::Format get_format() const;
- Ref<AudioStreamSample> get_recording() const;
+ void set_format(AudioStreamWAV::Format p_format);
+ AudioStreamWAV::Format get_format() const;
+ Ref<AudioStreamWAV> get_recording() const;
AudioEffectRecord();
};
-#endif // AUDIOEFFECTRECORD_H
+#endif // AUDIO_EFFECT_RECORD_H
diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h
index 90694c5492..a2c1fc5ea5 100644
--- a/servers/audio/effects/audio_effect_reverb.h
+++ b/servers/audio/effects/audio_effect_reverb.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTREVERB_H
-#define AUDIOEFFECTREVERB_H
+#ifndef AUDIO_EFFECT_REVERB_H
+#define AUDIO_EFFECT_REVERB_H
#include "servers/audio/audio_effect.h"
-#include "servers/audio/effects/reverb.h"
+#include "servers/audio/effects/reverb_filter.h"
class AudioEffectReverb;
@@ -94,4 +94,4 @@ public:
AudioEffectReverb();
};
-#endif // AUDIOEFFECTREVERB_H
+#endif // AUDIO_EFFECT_REVERB_H
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
index 46de1692e4..6365dacc80 100644
--- a/servers/audio/effects/audio_stream_generator.cpp
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -46,7 +46,7 @@ float AudioStreamGenerator::get_buffer_length() const {
return buffer_len;
}
-Ref<AudioStreamPlayback> AudioStreamGenerator::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamGenerator::instantiate_playback() {
Ref<AudioStreamGeneratorPlayback> playback;
playback.instantiate();
playback->generator = this;
@@ -196,6 +196,10 @@ void AudioStreamGeneratorPlayback::seek(float p_time) {
//no seek possible
}
+void AudioStreamGeneratorPlayback::tag_used_streams() {
+ generator->tag_used(0);
+}
+
void AudioStreamGeneratorPlayback::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_frame", "frame"), &AudioStreamGeneratorPlayback::push_frame);
ClassDB::bind_method(D_METHOD("can_push_buffer", "amount"), &AudioStreamGeneratorPlayback::can_push_buffer);
diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h
index 2ce4b95fcf..a0bed0fda5 100644
--- a/servers/audio/effects/audio_stream_generator.h
+++ b/servers/audio/effects/audio_stream_generator.h
@@ -50,7 +50,7 @@ public:
void set_buffer_length(float p_seconds);
float get_buffer_length() const;
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
virtual float get_length() const override;
@@ -89,8 +89,11 @@ public:
int get_frames_available() const;
int get_skips() const;
+ virtual void tag_used_streams() override;
+
void clear_buffer();
AudioStreamGeneratorPlayback();
};
+
#endif // AUDIO_STREAM_GENERATOR_H
diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq_filter.cpp
index 2123284b3b..6807e81cc4 100644
--- a/servers/audio/effects/eq.cpp
+++ b/servers/audio/effects/eq_filter.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* eq.cpp */
+/* eq_filter.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Author: reduzio@gmail.com (C) 2006
+#include "eq_filter.h"
-#include "eq.h"
#include "core/error/error_macros.h"
#include "core/math/math_funcs.h"
+
#include <math.h>
#define POW2(v) ((v) * (v))
diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq_filter.h
index d6293bf875..9dcad4dcea 100644
--- a/servers/audio/effects/eq.h
+++ b/servers/audio/effects/eq_filter.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* eq.h */
+/* eq_filter.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb_filter.cpp
index adfd648514..0363706714 100644
--- a/servers/audio/effects/reverb.cpp
+++ b/servers/audio/effects/reverb_filter.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* reverb.cpp */
+/* reverb_filter.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "reverb.h"
+#include "reverb_filter.h"
#include "core/math/math_funcs.h"
diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb_filter.h
index c9602c5b5a..fe846fe2e7 100644
--- a/servers/audio/effects/reverb.h
+++ b/servers/audio/effects/reverb_filter.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* reverb.h */
+/* reverb_filter.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef REVERB_H
-#define REVERB_H
+#ifndef REVERB_FILTER_H
+#define REVERB_FILTER_H
#include "core/math/audio_frame.h"
#include "core/os/memory.h"
@@ -119,4 +119,4 @@ public:
~Reverb();
};
-#endif // REVERB_H
+#endif // REVERB_FILTER_H
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 8ec3e469d3..9052f8e05e 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -39,7 +39,7 @@
#include "core/os/os.h"
#include "core/string/string_name.h"
#include "core/templates/pair.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.h"
#include "servers/audio/audio_driver_dummy.h"
#include "servers/audio/effects/audio_effect_compressor.h"
@@ -350,6 +350,10 @@ void AudioServer::_mix_step() {
// Mix the audio stream
unsigned int mixed_frames = playback->stream_playback->mix(&buf[LOOKAHEAD_BUFFER_SIZE], playback->pitch_scale.get(), buffer_size);
+ if (tag_used_audio_streams && playback->stream_playback->is_playing()) {
+ playback->stream_playback->tag_used_streams();
+ }
+
if (mixed_frames != buffer_size) {
// We know we have at least the size of our lookahead buffer for fade-out purposes.
@@ -1312,6 +1316,10 @@ uint64_t AudioServer::get_mix_count() const {
return mix_count;
}
+uint64_t AudioServer::get_mixed_frames() const {
+ return mix_frames;
+}
+
void AudioServer::notify_listener_changed() {
for (CallbackItem *ci : listener_changed_callback_list) {
ci->callback(ci->userdata);
@@ -1653,6 +1661,10 @@ void AudioServer::capture_set_device(const String &p_name) {
AudioDriver::get_singleton()->capture_set_device(p_name);
}
+void AudioServer::set_enable_tagging_used_audio_streams(bool p_enable) {
+ tag_used_audio_streams = p_enable;
+}
+
void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bus_count", "amount"), &AudioServer::set_bus_count);
ClassDB::bind_method(D_METHOD("get_bus_count"), &AudioServer::get_bus_count);
@@ -1719,6 +1731,8 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bus_layout", "bus_layout"), &AudioServer::set_bus_layout);
ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout);
+ ClassDB::bind_method(D_METHOD("set_enable_tagging_used_audio_streams", "enable"), &AudioServer::set_enable_tagging_used_audio_streams);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "device"), "set_device", "get_device");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "capture_device"), "capture_set_device", "capture_get_device");
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 18e173ff0b..5613267909 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -43,7 +43,7 @@
class AudioDriverDummy;
class AudioStream;
-class AudioStreamSample;
+class AudioStreamWAV;
class AudioStreamPlayback;
class AudioDriver {
@@ -187,6 +187,8 @@ private:
float playback_speed_scale = 1.0f;
+ bool tag_used_audio_streams = false;
+
struct Bus {
StringName name;
bool solo = false;
@@ -380,6 +382,7 @@ public:
bool is_playback_paused(Ref<AudioStreamPlayback> p_playback);
uint64_t get_mix_count() const;
+ uint64_t get_mixed_frames() const;
void notify_listener_changed();
@@ -424,6 +427,8 @@ public:
String capture_get_device();
void capture_set_device(const String &p_name);
+ void set_enable_tagging_used_audio_streams(bool p_enable);
+
AudioServer();
virtual ~AudioServer();
};
diff --git a/servers/debugger/servers_debugger.h b/servers/debugger/servers_debugger.h
index f949c436e7..be0e64fbc0 100644
--- a/servers/debugger/servers_debugger.h
+++ b/servers/debugger/servers_debugger.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SERVER_DEBUGGER_H
-#define SERVER_DEBUGGER_H
+#ifndef SERVERS_DEBUGGER_H
+#define SERVERS_DEBUGGER_H
#include "core/debugger/debugger_marshalls.h"
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 59f88844e9..4e7db7d0a5 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -278,7 +278,7 @@ void DisplayServer::tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id
Variant args[1];
args[0] = p_id;
const Variant *argp[] = { &args[0] };
- utterance_callback[p_event].call_deferred(argp, 1); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
+ utterance_callback[p_event].call_deferredp(argp, 1); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
}
} break;
case DisplayServer::TTS_UTTERANCE_BOUNDARY: {
@@ -287,7 +287,7 @@ void DisplayServer::tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id
args[0] = p_pos;
args[1] = p_id;
const Variant *argp[] = { &args[0], &args[1] };
- utterance_callback[p_event].call_deferred(argp, 2); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
+ utterance_callback[p_event].call_deferredp(argp, 2); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
}
} break;
default:
@@ -400,7 +400,7 @@ String DisplayServer::ime_get_text() const {
ERR_FAIL_V_MSG(String(), "IME or NOTIFICATION_WM_IME_UPDATEnot supported by this display server.");
}
-void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) {
+void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {
WARN_PRINT("Virtual keyboard not supported by this display server.");
}
@@ -494,11 +494,11 @@ int64_t DisplayServer::window_get_native_handle(HandleType p_handle_type, Window
}
void DisplayServer::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
- WARN_PRINT("Changing the VSync mode is not supported by this display server.");
+ WARN_PRINT("Changing the V-Sync mode is not supported by this display server.");
}
DisplayServer::VSyncMode DisplayServer::window_get_vsync_mode(WindowID p_window) const {
- WARN_PRINT("Changing the VSync mode is not supported by this display server.");
+ WARN_PRINT("Changing the V-Sync mode is not supported by this display server.");
return VSyncMode::VSYNC_ENABLED;
}
@@ -660,7 +660,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection);
ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text);
- ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "multiline", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2()), DEFVAL(false), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "type", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2()), DEFVAL(KEYBOARD_TYPE_DEFAULT), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide);
ClassDB::bind_method(D_METHOD("virtual_keyboard_get_height"), &DisplayServer::virtual_keyboard_get_height);
@@ -732,6 +732,15 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(SCREEN_SENSOR_PORTRAIT);
BIND_ENUM_CONSTANT(SCREEN_SENSOR);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_DEFAULT);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_MULTILINE);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER_DECIMAL);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PHONE);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_EMAIL_ADDRESS);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PASSWORD);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_URL);
+
BIND_ENUM_CONSTANT(CURSOR_ARROW);
BIND_ENUM_CONSTANT(CURSOR_IBEAM);
BIND_ENUM_CONSTANT(CURSOR_POINTING_HAND);
diff --git a/servers/display_server.h b/servers/display_server.h
index 7a15df2f92..8632b53f7b 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -382,7 +382,18 @@ public:
virtual Point2i ime_get_selection() const;
virtual String ime_get_text() const;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
+ enum VirtualKeyboardType {
+ KEYBOARD_TYPE_DEFAULT,
+ KEYBOARD_TYPE_MULTILINE,
+ KEYBOARD_TYPE_NUMBER,
+ KEYBOARD_TYPE_NUMBER_DECIMAL,
+ KEYBOARD_TYPE_PHONE,
+ KEYBOARD_TYPE_EMAIL_ADDRESS,
+ KEYBOARD_TYPE_PASSWORD,
+ KEYBOARD_TYPE_URL
+ };
+
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
virtual void virtual_keyboard_hide();
// returns height of the currently shown virtual keyboard (0 if keyboard is hidden)
@@ -467,6 +478,7 @@ VARIANT_ENUM_CAST(DisplayServer::ScreenOrientation)
VARIANT_ENUM_CAST(DisplayServer::WindowMode)
VARIANT_ENUM_CAST(DisplayServer::WindowFlags)
VARIANT_ENUM_CAST(DisplayServer::HandleType)
+VARIANT_ENUM_CAST(DisplayServer::VirtualKeyboardType);
VARIANT_ENUM_CAST(DisplayServer::CursorShape)
VARIANT_ENUM_CAST(DisplayServer::VSyncMode)
VARIANT_ENUM_CAST(DisplayServer::TTSUtteranceEvent)
diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h
index 663af1ae6c..c4b4a00eaf 100644
--- a/servers/extensions/physics_server_3d_extension.h
+++ b/servers/extensions/physics_server_3d_extension.h
@@ -545,4 +545,4 @@ public:
~PhysicsServer3DExtension();
};
-#endif // PHYSICSSERVER3DEXTENSION_H
+#endif // PHYSICS_SERVER_3D_EXTENSION_H
diff --git a/servers/movie_writer/movie_writer.cpp b/servers/movie_writer/movie_writer.cpp
index 9f96b8cfda..40b2b2539e 100644
--- a/servers/movie_writer/movie_writer.cpp
+++ b/servers/movie_writer/movie_writer.cpp
@@ -30,6 +30,9 @@
#include "movie_writer.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/os/time.h"
+#include "servers/display_server.h"
MovieWriter *MovieWriter::writers[MovieWriter::MAX_WRITERS];
uint32_t MovieWriter::writer_count = 0;
@@ -101,6 +104,7 @@ void MovieWriter::get_supported_extensions(List<String> *r_extensions) const {
}
void MovieWriter::begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) {
+ project_name = GLOBAL_GET("application/config/name");
mix_rate = get_audio_mix_rate();
AudioDriverDummy::get_dummy_singleton()->set_mix_rate(mix_rate);
AudioDriverDummy::get_dummy_singleton()->set_speaker_mode(AudioDriver::SpeakerMode(get_audio_speaker_mode()));
@@ -162,10 +166,47 @@ void MovieWriter::set_extensions_hint() {
}
void MovieWriter::add_frame(const Ref<Image> &p_image) {
+ const int movie_time_seconds = Engine::get_singleton()->get_frames_drawn() / fps;
+ const String movie_time = vformat("%s:%s:%s",
+ String::num(movie_time_seconds / 3600).pad_zeros(2),
+ String::num((movie_time_seconds % 3600) / 60).pad_zeros(2),
+ String::num(movie_time_seconds % 60).pad_zeros(2));
+
+#ifdef DEBUG_ENABLED
+ DisplayServer::get_singleton()->window_set_title(vformat("MovieWriter: Frame %d (time: %s) - %s (DEBUG)", Engine::get_singleton()->get_frames_drawn(), movie_time, project_name));
+#else
+ DisplayServer::get_singleton()->window_set_title(vformat("MovieWriter: Frame %d (time: %s) - %s", Engine::get_singleton()->get_frames_drawn(), movie_time, project_name));
+#endif
+
AudioDriverDummy::get_dummy_singleton()->mix_audio(mix_rate / fps, audio_mix_buffer.ptr());
write_frame(p_image, audio_mix_buffer.ptr());
}
void MovieWriter::end() {
write_end();
+
+ // Print a report with various statistics.
+ print_line("----------------");
+ String movie_path = Engine::get_singleton()->get_write_movie_path();
+ if (movie_path.is_relative_path()) {
+ // Print absolute path to make finding the file easier,
+ // and to make it clickable in terminal emulators that support this.
+ movie_path = ProjectSettings::get_singleton()->globalize_path("res://").plus_file(movie_path);
+ }
+ print_line(vformat("Done recording movie at path: %s", movie_path));
+
+ const int movie_time_seconds = Engine::get_singleton()->get_frames_drawn() / fps;
+ const String movie_time = vformat("%s:%s:%s",
+ String::num(movie_time_seconds / 3600).pad_zeros(2),
+ String::num((movie_time_seconds % 3600) / 60).pad_zeros(2),
+ String::num(movie_time_seconds % 60).pad_zeros(2));
+
+ const int real_time_seconds = Time::get_singleton()->get_ticks_msec() / 1000;
+ const String real_time = vformat("%s:%s:%s",
+ String::num(real_time_seconds / 3600).pad_zeros(2),
+ String::num((real_time_seconds % 3600) / 60).pad_zeros(2),
+ String::num(real_time_seconds % 60).pad_zeros(2));
+
+ print_line(vformat("%d frames at %d FPS (movie length: %s), recorded in %s (%d%% of real-time speed).", Engine::get_singleton()->get_frames_drawn(), fps, movie_time, real_time, (float(movie_time_seconds) / real_time_seconds) * 100));
+ print_line("----------------");
}
diff --git a/servers/movie_writer/movie_writer.h b/servers/movie_writer/movie_writer.h
index 1ec6e93052..7877a60715 100644
--- a/servers/movie_writer/movie_writer.h
+++ b/servers/movie_writer/movie_writer.h
@@ -42,6 +42,8 @@ class MovieWriter : public Object {
uint64_t mix_rate = 0;
uint32_t audio_channels = 0;
+ String project_name;
+
LocalVector<int32_t> audio_mix_buffer;
enum {
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 6c48c4a8de..52855c5931 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -30,6 +30,10 @@
#include "navigation_server_3d.h"
+#ifdef DEBUG_ENABLED
+#include "core/config/project_settings.h"
+#endif // DEBUG_ENABLED
+
NavigationServer3D *NavigationServer3D::singleton = nullptr;
void NavigationServer3D::_bind_methods() {
@@ -92,6 +96,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process);
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
+
+ ADD_SIGNAL(MethodInfo("navigation_debug_changed"));
}
const NavigationServer3D *NavigationServer3D::get_singleton() {
@@ -105,6 +111,19 @@ NavigationServer3D *NavigationServer3D::get_singleton_mut() {
NavigationServer3D::NavigationServer3D() {
ERR_FAIL_COND(singleton != nullptr);
singleton = this;
+
+#ifdef DEBUG_ENABLED
+ debug_navigation_edge_connection_color = GLOBAL_DEF("debug/shapes/navigation/edge_connection_color", Color(1.0, 0.0, 1.0, 1.0));
+ debug_navigation_geometry_edge_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_color", Color(0.5, 1.0, 1.0, 1.0));
+ debug_navigation_geometry_face_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_color", Color(0.5, 1.0, 1.0, 0.4));
+ debug_navigation_geometry_edge_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_disabled_color", Color(0.5, 0.5, 0.5, 1.0));
+ debug_navigation_geometry_face_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_disabled_color", Color(0.5, 0.5, 0.5, 0.4));
+ debug_navigation_enable_edge_connections = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections", true);
+ debug_navigation_enable_edge_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections_xray", true);
+ debug_navigation_enable_edge_lines = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines", true);
+ debug_navigation_enable_edge_lines_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines_xray", true);
+ debug_navigation_enable_geometry_face_random_color = GLOBAL_DEF("debug/shapes/navigation/enable_geometry_face_random_color", true);
+#endif // DEBUG_ENABLED
}
NavigationServer3D::~NavigationServer3D() {
@@ -121,3 +140,241 @@ NavigationServer3D *NavigationServer3DManager::new_default_server() {
ERR_FAIL_COND_V(create_callback == nullptr, nullptr);
return create_callback();
}
+
+#ifdef DEBUG_ENABLED
+void NavigationServer3D::_emit_navigation_debug_changed_signal() {
+ if (debug_dirty) {
+ debug_dirty = false;
+ emit_signal(SNAME("navigation_debug_changed"));
+ }
+}
+#endif // DEBUG_ENABLED
+
+#ifdef DEBUG_ENABLED
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_face_material() {
+ if (debug_navigation_geometry_face_material.is_valid()) {
+ return debug_navigation_geometry_face_material;
+ }
+
+ bool enabled_geometry_face_random_color = get_debug_navigation_enable_geometry_face_random_color();
+
+ Color debug_navigation_geometry_face_color = get_debug_navigation_geometry_face_color();
+
+ Ref<StandardMaterial3D> face_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ face_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ face_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+ face_material->set_albedo(debug_navigation_geometry_face_color);
+ if (enabled_geometry_face_random_color) {
+ face_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ face_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ }
+
+ debug_navigation_geometry_face_material = face_material;
+
+ return debug_navigation_geometry_face_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_edge_material() {
+ if (debug_navigation_geometry_edge_material.is_valid()) {
+ return debug_navigation_geometry_edge_material;
+ }
+
+ bool enabled_edge_lines_xray = get_debug_navigation_enable_edge_lines_xray();
+
+ Color debug_navigation_geometry_edge_color = get_debug_navigation_geometry_edge_color();
+
+ Ref<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ line_material->set_albedo(debug_navigation_geometry_edge_color);
+ if (enabled_edge_lines_xray) {
+ line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+
+ debug_navigation_geometry_edge_material = line_material;
+
+ return debug_navigation_geometry_edge_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_face_disabled_material() {
+ if (debug_navigation_geometry_face_disabled_material.is_valid()) {
+ return debug_navigation_geometry_face_disabled_material;
+ }
+
+ Color debug_navigation_geometry_face_disabled_color = get_debug_navigation_geometry_face_disabled_color();
+
+ Ref<StandardMaterial3D> face_disabled_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ face_disabled_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ face_disabled_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+ face_disabled_material->set_albedo(debug_navigation_geometry_face_disabled_color);
+
+ debug_navigation_geometry_face_disabled_material = face_disabled_material;
+
+ return debug_navigation_geometry_face_disabled_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_edge_disabled_material() {
+ if (debug_navigation_geometry_edge_disabled_material.is_valid()) {
+ return debug_navigation_geometry_edge_disabled_material;
+ }
+
+ bool enabled_edge_lines_xray = get_debug_navigation_enable_edge_lines_xray();
+
+ Color debug_navigation_geometry_edge_disabled_color = get_debug_navigation_geometry_edge_disabled_color();
+
+ Ref<StandardMaterial3D> line_disabled_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ line_disabled_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ line_disabled_material->set_albedo(debug_navigation_geometry_edge_disabled_color);
+ if (enabled_edge_lines_xray) {
+ line_disabled_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+
+ debug_navigation_geometry_edge_disabled_material = line_disabled_material;
+
+ return debug_navigation_geometry_edge_disabled_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_edge_connections_material() {
+ if (debug_navigation_edge_connections_material.is_valid()) {
+ return debug_navigation_edge_connections_material;
+ }
+
+ bool enabled_edge_connections_xray = get_debug_navigation_enable_edge_connections_xray();
+
+ Color debug_navigation_edge_connection_color = get_debug_navigation_edge_connection_color();
+
+ Ref<StandardMaterial3D> edge_connections_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ edge_connections_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ edge_connections_material->set_albedo(debug_navigation_edge_connection_color);
+ if (enabled_edge_connections_xray) {
+ edge_connections_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+ edge_connections_material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2);
+
+ debug_navigation_edge_connections_material = edge_connections_material;
+
+ return debug_navigation_edge_connections_material;
+}
+
+void NavigationServer3D::set_debug_navigation_edge_connection_color(const Color &p_color) {
+ debug_navigation_edge_connection_color = p_color;
+ if (debug_navigation_edge_connections_material.is_valid()) {
+ debug_navigation_edge_connections_material->set_albedo(debug_navigation_edge_connection_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_edge_connection_color() const {
+ return debug_navigation_edge_connection_color;
+}
+
+void NavigationServer3D::set_debug_navigation_geometry_edge_color(const Color &p_color) {
+ debug_navigation_geometry_edge_color = p_color;
+ if (debug_navigation_geometry_edge_material.is_valid()) {
+ debug_navigation_geometry_edge_material->set_albedo(debug_navigation_geometry_edge_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_geometry_edge_color() const {
+ return debug_navigation_geometry_edge_color;
+}
+
+void NavigationServer3D::set_debug_navigation_geometry_face_color(const Color &p_color) {
+ debug_navigation_geometry_face_color = p_color;
+ if (debug_navigation_geometry_face_material.is_valid()) {
+ debug_navigation_geometry_face_material->set_albedo(debug_navigation_geometry_face_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_geometry_face_color() const {
+ return debug_navigation_geometry_face_color;
+}
+
+void NavigationServer3D::set_debug_navigation_geometry_edge_disabled_color(const Color &p_color) {
+ debug_navigation_geometry_edge_disabled_color = p_color;
+ if (debug_navigation_geometry_edge_disabled_material.is_valid()) {
+ debug_navigation_geometry_edge_disabled_material->set_albedo(debug_navigation_geometry_edge_disabled_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_geometry_edge_disabled_color() const {
+ return debug_navigation_geometry_edge_disabled_color;
+}
+
+void NavigationServer3D::set_debug_navigation_geometry_face_disabled_color(const Color &p_color) {
+ debug_navigation_geometry_face_disabled_color = p_color;
+ if (debug_navigation_geometry_face_disabled_material.is_valid()) {
+ debug_navigation_geometry_face_disabled_material->set_albedo(debug_navigation_geometry_face_disabled_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_geometry_face_disabled_color() const {
+ return debug_navigation_geometry_face_disabled_color;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_edge_connections(const bool p_value) {
+ debug_navigation_enable_edge_connections = p_value;
+ debug_dirty = true;
+ call_deferred("_emit_navigation_debug_changed_signal");
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_edge_connections() const {
+ return debug_navigation_enable_edge_connections;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_edge_connections_xray(const bool p_value) {
+ debug_navigation_enable_edge_connections_xray = p_value;
+ if (debug_navigation_edge_connections_material.is_valid()) {
+ debug_navigation_edge_connections_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_edge_connections_xray);
+ }
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_edge_connections_xray() const {
+ return debug_navigation_enable_edge_connections_xray;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_edge_lines(const bool p_value) {
+ debug_navigation_enable_edge_lines = p_value;
+ debug_dirty = true;
+ call_deferred("_emit_navigation_debug_changed_signal");
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_edge_lines() const {
+ return debug_navigation_enable_edge_lines;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_edge_lines_xray(const bool p_value) {
+ debug_navigation_enable_edge_lines_xray = p_value;
+ if (debug_navigation_geometry_edge_material.is_valid()) {
+ debug_navigation_geometry_edge_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_edge_lines_xray);
+ }
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_edge_lines_xray() const {
+ return debug_navigation_enable_edge_lines_xray;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_geometry_face_random_color(const bool p_value) {
+ debug_navigation_enable_geometry_face_random_color = p_value;
+ debug_dirty = true;
+ call_deferred("_emit_navigation_debug_changed_signal");
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_geometry_face_random_color() const {
+ return debug_navigation_enable_geometry_face_random_color;
+}
+
+void NavigationServer3D::set_debug_enabled(bool p_enabled) {
+ if (debug_enabled != p_enabled) {
+ debug_dirty = true;
+ }
+
+ debug_enabled = p_enabled;
+
+ if (debug_dirty) {
+ call_deferred("_emit_navigation_debug_changed_signal");
+ }
+}
+
+bool NavigationServer3D::get_debug_enabled() const {
+ return debug_enabled;
+}
+#endif // DEBUG_ENABLED
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index cf91596604..f24c0117d1 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -207,6 +207,68 @@ public:
NavigationServer3D();
virtual ~NavigationServer3D();
+
+#ifdef DEBUG_ENABLED
+ bool debug_enabled = false;
+ bool debug_dirty = true;
+ void _emit_navigation_debug_changed_signal();
+
+ void set_debug_enabled(bool p_enabled);
+ bool get_debug_enabled() const;
+
+ Color debug_navigation_edge_connection_color = Color(1.0, 0.0, 1.0, 1.0);
+ Color debug_navigation_geometry_edge_color = Color(0.5, 1.0, 1.0, 1.0);
+ Color debug_navigation_geometry_face_color = Color(0.5, 1.0, 1.0, 0.4);
+ Color debug_navigation_geometry_edge_disabled_color = Color(0.5, 0.5, 0.5, 1.0);
+ Color debug_navigation_geometry_face_disabled_color = Color(0.5, 0.5, 0.5, 0.4);
+ bool debug_navigation_enable_edge_connections = true;
+ bool debug_navigation_enable_edge_connections_xray = true;
+ bool debug_navigation_enable_edge_lines = true;
+ bool debug_navigation_enable_edge_lines_xray = true;
+ bool debug_navigation_enable_geometry_face_random_color = true;
+
+ Ref<StandardMaterial3D> debug_navigation_geometry_edge_material;
+ Ref<StandardMaterial3D> debug_navigation_geometry_face_material;
+ Ref<StandardMaterial3D> debug_navigation_geometry_edge_disabled_material;
+ Ref<StandardMaterial3D> debug_navigation_geometry_face_disabled_material;
+ Ref<StandardMaterial3D> debug_navigation_edge_connections_material;
+
+ void set_debug_navigation_edge_connection_color(const Color &p_color);
+ Color get_debug_navigation_edge_connection_color() const;
+
+ void set_debug_navigation_geometry_edge_color(const Color &p_color);
+ Color get_debug_navigation_geometry_edge_color() const;
+
+ void set_debug_navigation_geometry_face_color(const Color &p_color);
+ Color get_debug_navigation_geometry_face_color() const;
+
+ void set_debug_navigation_geometry_edge_disabled_color(const Color &p_color);
+ Color get_debug_navigation_geometry_edge_disabled_color() const;
+
+ void set_debug_navigation_geometry_face_disabled_color(const Color &p_color);
+ Color get_debug_navigation_geometry_face_disabled_color() const;
+
+ void set_debug_navigation_enable_edge_connections(const bool p_value);
+ bool get_debug_navigation_enable_edge_connections() const;
+
+ void set_debug_navigation_enable_edge_connections_xray(const bool p_value);
+ bool get_debug_navigation_enable_edge_connections_xray() const;
+
+ void set_debug_navigation_enable_edge_lines(const bool p_value);
+ bool get_debug_navigation_enable_edge_lines() const;
+
+ void set_debug_navigation_enable_edge_lines_xray(const bool p_value);
+ bool get_debug_navigation_enable_edge_lines_xray() const;
+
+ void set_debug_navigation_enable_geometry_face_random_color(const bool p_value);
+ bool get_debug_navigation_enable_geometry_face_random_color() const;
+
+ Ref<StandardMaterial3D> get_debug_navigation_geometry_face_material();
+ Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_material();
+ Ref<StandardMaterial3D> get_debug_navigation_geometry_face_disabled_material();
+ Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_disabled_material();
+ Ref<StandardMaterial3D> get_debug_navigation_edge_connections_material();
+#endif // DEBUG_ENABLED
};
typedef NavigationServer3D *(*NavigationServer3DCallback)();
diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp
index 11208f2d5b..96c8dfc69e 100644
--- a/servers/physics_2d/godot_area_2d.cpp
+++ b/servers/physics_2d/godot_area_2d.cpp
@@ -247,7 +247,7 @@ void GodotArea2D::call_queries() {
Callable::CallError ce;
Variant ret;
- monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
}
} else {
monitored_bodies.clear();
@@ -285,7 +285,7 @@ void GodotArea2D::call_queries() {
Callable::CallError ce;
Variant ret;
- area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ area_monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
}
} else {
monitored_areas.clear();
diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp
index 6873504f70..268beb1a55 100644
--- a/servers/physics_2d/godot_body_2d.cpp
+++ b/servers/physics_2d/godot_body_2d.cpp
@@ -683,10 +683,10 @@ void GodotBody2D::call_queries() {
Callable::CallError ce;
Variant rv;
if (fi_callback_data->udata.get_type() != Variant::NIL) {
- fi_callback_data->callable.call(vp, 2, rv, ce);
+ fi_callback_data->callable.callp(vp, 2, rv, ce);
} else {
- fi_callback_data->callable.call(vp, 1, rv, ce);
+ fi_callback_data->callable.callp(vp, 1, rv, ce);
}
}
}
diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp
index 551fd9329f..0603458acd 100644
--- a/servers/physics_2d/godot_step_2d.cpp
+++ b/servers/physics_2d/godot_step_2d.cpp
@@ -239,7 +239,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) {
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
uint32_t total_contraint_count = all_constraints.size();
- work_pool.do_work(total_contraint_count, this, &GodotStep2D::_setup_contraint, nullptr);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics2DConstraintSetup"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -258,7 +259,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) {
// Warning: _solve_island modifies the constraint islands for optimization purpose,
// their content is not reliable after these calls and shouldn't be used anymore.
- work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr);
+ group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics2DConstraintSolveIslands"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -297,10 +299,7 @@ GodotStep2D::GodotStep2D() {
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
-
- work_pool.init();
}
GodotStep2D::~GodotStep2D() {
- work_pool.finish();
}
diff --git a/servers/physics_2d/godot_step_2d.h b/servers/physics_2d/godot_step_2d.h
index 9a6d8caf9b..9f8fdd6ce3 100644
--- a/servers/physics_2d/godot_step_2d.h
+++ b/servers/physics_2d/godot_step_2d.h
@@ -33,8 +33,8 @@
#include "godot_space_2d.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/local_vector.h"
-#include "core/templates/thread_work_pool.h"
class GodotStep2D {
uint64_t _step = 1;
@@ -42,8 +42,6 @@ class GodotStep2D {
int iterations = 0;
real_t delta = 0.0;
- ThreadWorkPool work_pool;
-
LocalVector<LocalVector<GodotBody2D *>> body_islands;
LocalVector<LocalVector<GodotConstraint2D *>> constraint_islands;
LocalVector<GodotConstraint2D *> all_constraints;
diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h
index 01a47f222e..309af76561 100644
--- a/servers/physics_3d/gjk_epa.h
+++ b/servers/physics_3d/gjk_epa.h
@@ -37,4 +37,4 @@
bool gjk_epa_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0);
bool gjk_epa_calculate_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
-#endif
+#endif // GJK_EPA_H
diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp
index e2ad765d62..fdb9f42b40 100644
--- a/servers/physics_3d/godot_area_3d.cpp
+++ b/servers/physics_3d/godot_area_3d.cpp
@@ -276,7 +276,7 @@ void GodotArea3D::call_queries() {
Callable::CallError ce;
Variant ret;
- monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
}
} else {
monitored_bodies.clear();
@@ -314,7 +314,7 @@ void GodotArea3D::call_queries() {
Callable::CallError ce;
Variant ret;
- area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ area_monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
}
} else {
monitored_areas.clear();
diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp
index ad97533f44..4c89106839 100644
--- a/servers/physics_3d/godot_body_3d.cpp
+++ b/servers/physics_3d/godot_body_3d.cpp
@@ -766,7 +766,7 @@ void GodotBody3D::call_queries() {
Callable::CallError ce;
int argc = (fi_callback_data->udata.get_type() == Variant::NIL) ? 1 : 2;
Variant rv;
- fi_callback_data->callable.call(vp, argc, rv, ce);
+ fi_callback_data->callable.callp(vp, argc, rv, ce);
}
}
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.h b/servers/physics_3d/godot_collision_solver_3d_sat.h
index 3eb7aa4c9e..46c5ec3254 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.h
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_COLLISION_SOLVER_SAT_H
-#define GODOT_COLLISION_SOLVER_SAT_H
+#ifndef GODOT_COLLISION_SOLVER_3D_SAT_H
+#define GODOT_COLLISION_SOLVER_3D_SAT_H
#include "godot_collision_solver_3d.h"
bool sat_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0);
-#endif // GODOT_COLLISION_SOLVER_SAT_H
+#endif // GODOT_COLLISION_SOLVER_3D_SAT_H
diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp
index 99656d01a0..f384c829a4 100644
--- a/servers/physics_3d/godot_step_3d.cpp
+++ b/servers/physics_3d/godot_step_3d.cpp
@@ -343,7 +343,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) {
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
uint32_t total_contraint_count = all_constraints.size();
- work_pool.do_work(total_contraint_count, this, &GodotStep3D::_setup_contraint, nullptr);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics3DConstraintSetup"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -362,7 +363,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) {
// Warning: _solve_island modifies the constraint islands for optimization purpose,
// their content is not reliable after these calls and shouldn't be used anymore.
- work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr);
+ group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics3DConstraintSolveIslands"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -409,10 +411,7 @@ GodotStep3D::GodotStep3D() {
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
-
- work_pool.init();
}
GodotStep3D::~GodotStep3D() {
- work_pool.finish();
}
diff --git a/servers/physics_3d/godot_step_3d.h b/servers/physics_3d/godot_step_3d.h
index 6d975b0dd3..189487757f 100644
--- a/servers/physics_3d/godot_step_3d.h
+++ b/servers/physics_3d/godot_step_3d.h
@@ -33,8 +33,8 @@
#include "godot_space_3d.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/local_vector.h"
-#include "core/templates/thread_work_pool.h"
class GodotStep3D {
uint64_t _step = 1;
@@ -42,8 +42,6 @@ class GodotStep3D {
int iterations = 0;
real_t delta = 0.0;
- ThreadWorkPool work_pool;
-
LocalVector<LocalVector<GodotBody3D *>> body_islands;
LocalVector<LocalVector<GodotConstraint3D *>> constraint_islands;
LocalVector<GodotConstraint3D *> all_constraints;
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 41aae36785..26768e300c 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -147,6 +147,16 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {}
///////////////////////////////////////////////////////
+Ref<PhysicsRayQueryParameters2D> PhysicsRayQueryParameters2D::create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const Vector<RID> &p_exclude) {
+ Ref<PhysicsRayQueryParameters2D> params;
+ params.instantiate();
+ params->set_from(p_from);
+ params->set_to(p_to);
+ params->set_collision_mask(p_mask);
+ params->set_exclude(p_exclude);
+ return params;
+}
+
void PhysicsRayQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
@@ -165,6 +175,8 @@ Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const {
}
void PhysicsRayQueryParameters2D::_bind_methods() {
+ ClassDB::bind_static_method("PhysicsRayQueryParameters2D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters2D::create, DEFVAL(UINT32_MAX), DEFVAL(Vector<RID>()));
+
ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters2D::set_from);
ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters2D::get_from);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 7a821c64e6..6d95c591c2 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -605,6 +605,7 @@ protected:
static void _bind_methods();
public:
+ static Ref<PhysicsRayQueryParameters2D> create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const Vector<RID> &p_exclude);
const PhysicsDirectSpaceState2D::RayParameters &get_parameters() const { return parameters; }
void set_from(const Vector2 &p_from) { parameters.from = p_from; }
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index a606d055f7..f25db22e66 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -184,6 +184,8 @@ Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const {
}
void PhysicsRayQueryParameters3D::_bind_methods() {
+ ClassDB::bind_static_method("PhysicsRayQueryParameters3D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters3D::create, DEFVAL(UINT32_MAX), DEFVAL(Vector<RID>()));
+
ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters3D::set_from);
ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters3D::get_from);
@@ -220,6 +222,16 @@ void PhysicsRayQueryParameters3D::_bind_methods() {
///////////////////////////////////////////////////////
+Ref<PhysicsRayQueryParameters3D> PhysicsRayQueryParameters3D::create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const Vector<RID> &p_exclude) {
+ Ref<PhysicsRayQueryParameters3D> params;
+ params.instantiate();
+ params->set_from(p_from);
+ params->set_to(p_to);
+ params->set_collision_mask(p_mask);
+ params->set_exclude(p_exclude);
+ return params;
+}
+
void PhysicsPointQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 86a41d96ef..837073409a 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -816,6 +816,7 @@ protected:
static void _bind_methods();
public:
+ static Ref<PhysicsRayQueryParameters3D> create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const Vector<RID> &p_exclude);
const PhysicsDirectSpaceState3D::RayParameters &get_parameters() const { return parameters; }
void set_from(const Vector3 &p_from) { parameters.from = p_from; }
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..623f94b95f
--- /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..76d34cd14e 100644
--- a/servers/rendering/dummy/environment/gi.h
+++ b/servers/rendering/dummy/environment/gi.h
@@ -74,12 +74,9 @@ 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; }
};
} // namespace RendererDummy
-#endif // !GI_DUMMY_H
+#endif // GI_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_canvas_dummy.h b/servers/rendering/dummy/rasterizer_canvas_dummy.h
index 194b5b5cfe..64c4cf5024 100644
--- a/servers/rendering/dummy/rasterizer_canvas_dummy.h
+++ b/servers/rendering/dummy/rasterizer_canvas_dummy.h
@@ -60,4 +60,4 @@ public:
~RasterizerCanvasDummy() {}
};
-#endif // !RASTERIZER_CANVAS_DUMMY_H
+#endif // RASTERIZER_CANVAS_DUMMY_H
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/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h
index e6d2b93f99..be98770b90 100644
--- a/servers/rendering/dummy/rasterizer_scene_dummy.h
+++ b/servers/rendering/dummy/rasterizer_scene_dummy.h
@@ -35,33 +35,10 @@
class RasterizerSceneDummy : public RendererSceneRender {
public:
- GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
- void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
- void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
- void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {}
- void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
- void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
- void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
- void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {}
- void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {}
- void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {}
- void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
- void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
- void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
- void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
- void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}
+ RenderGeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
+ void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override {}
uint32_t geometry_instance_get_pair_mask() override { return 0; }
- void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
- void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
- void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
- void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
- void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {}
-
- void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
/* SHADOW ATLAS API */
@@ -92,49 +69,24 @@ public:
/* ENVIRONMENT API */
- RID environment_allocate() override { return RID(); }
- void environment_initialize(RID p_rid) override {}
- void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {}
- void environment_set_sky(RID p_env, RID p_sky) override {}
- void environment_set_sky_custom_fov(RID p_env, float p_scale) override {}
- void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {}
- void environment_set_bg_color(RID p_env, const Color &p_color) override {}
- void environment_set_bg_energy(RID p_env, float p_energy) override {}
- void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
- void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {}
-
- void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {}
void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
void environment_glow_set_use_high_quality(bool p_enable) override {}
- void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {}
void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
- void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {}
+
void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
- void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {}
- void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
- void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
+ void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {}
- void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {}
-
- void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}
-
- void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {}
void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
- bool is_environment(RID p_env) const override { return false; }
- RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; }
- int environment_get_canvas_max_layer(RID p_env) const override { return 0; }
-
RID camera_effects_allocate() override { return RID(); }
void camera_effects_initialize(RID p_rid) override {}
void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {}
@@ -143,13 +95,13 @@ public:
void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {}
void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {}
- void shadows_quality_set(RS::ShadowQuality p_quality) override {}
- void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {}
+ void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {}
+ void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {}
RID light_instance_create(RID p_light) override { return RID(); }
void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {}
void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
+ void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
void light_instance_mark_visible(RID p_light_instance) override {}
RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); }
@@ -179,20 +131,20 @@ public:
RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); }
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {}
bool voxel_gi_needs_update(RID p_probe) const override { return false; }
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {}
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override {}
void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
- void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
- void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
- void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
+ void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
+ void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override {}
void set_scene_pass(uint64_t p_pass) override {}
void set_time(double p_time, double p_step) override {}
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
RID render_buffers_create() override { return RID(); }
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
void gi_set_use_half_resolution(bool p_enable) override {}
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
@@ -203,7 +155,14 @@ public:
TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
- bool free(RID p_rid) override { return false; }
+ bool free(RID p_rid) override {
+ if (is_environment(p_rid)) {
+ environment_free(p_rid);
+ return true;
+ } else {
+ return false;
+ }
+ }
void update() override {}
void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
@@ -214,4 +173,4 @@ public:
~RasterizerSceneDummy() {}
};
-#endif // !RASTERIZER_SCENE_DUMMY_H
+#endif // RASTERIZER_SCENE_DUMMY_H
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/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
index b0100a5fe7..0c0ea61df5 100644
--- a/servers/rendering/dummy/storage/light_storage.h
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -132,4 +132,4 @@ public:
} // namespace RendererDummy
-#endif // !LIGHT_STORAGE_DUMMY_H
+#endif // LIGHT_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h
index 8890be8ea9..e25a2ac3a9 100644
--- a/servers/rendering/dummy/storage/material_storage.h
+++ b/servers/rendering/dummy/storage/material_storage.h
@@ -32,28 +32,29 @@
#define MATERIAL_STORAGE_DUMMY_H
#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererDummy {
class MaterialStorage : public RendererMaterialStorage {
public:
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {}
- virtual void global_variable_remove(const StringName &p_name) override {}
- virtual Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); }
+ virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override {}
+ virtual void global_shader_uniform_remove(const StringName &p_name) override {}
+ virtual Vector<StringName> global_shader_uniform_get_list() const override { return Vector<StringName>(); }
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override {}
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {}
- virtual Variant global_variable_get(const StringName &p_name) const override { return Variant(); }
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override {}
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override {}
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const override { return Variant(); }
+ virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
- virtual void global_variables_load_settings(bool p_load_textures = true) override {}
- virtual void global_variables_clear() override {}
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override {}
+ virtual void global_shader_uniforms_clear() override {}
- virtual int32_t global_variables_instance_allocate(RID p_instance) override { return 0; }
- virtual void global_variables_instance_free(RID p_instance) override {}
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
+ virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override { return 0; }
+ virtual void global_shader_uniforms_instance_free(RID p_instance) override {}
+ virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
/* SHADER API */
@@ -62,8 +63,10 @@ public:
virtual void shader_free(RID p_rid) override{};
virtual void shader_set_code(RID p_shader, const String &p_code) override {}
+ virtual void shader_set_path_hint(RID p_shader, const String &p_code) override {}
+
virtual String shader_get_code(RID p_shader) const override { return ""; }
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
+ virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
@@ -86,10 +89,10 @@ 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_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
+ virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
};
} // namespace RendererDummy
-#endif // !MATERIAL_STORAGE_DUMMY_H
+#endif // MATERIAL_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index dfbd265bba..aab5145982 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -32,21 +32,49 @@
#define MESH_STORAGE_DUMMY_H
#include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererDummy {
class MeshStorage : public RendererMeshStorage {
+private:
+ struct DummyMesh : public RID {
+ Vector<RS::SurfaceData> surfaces;
+ int blend_shape_count;
+ RS::BlendShapeMode blend_shape_mode;
+ PackedFloat32Array blend_shape_values;
+ };
+
+ mutable RID_Owner<DummyMesh> mesh_owner;
+
public:
/* MESH API */
- virtual RID mesh_allocate() override { return RID(); }
- virtual void mesh_initialize(RID p_rid) override {}
+ virtual RID mesh_allocate() override {
+ return mesh_owner.allocate_rid();
+ }
+
+ virtual void mesh_initialize(RID p_rid) override {
+ mesh_owner.initialize_rid(p_rid, DummyMesh());
+ }
virtual void mesh_free(RID p_rid) override {}
virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
- virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!m);
+ m->surfaces.push_back(RS::SurfaceData());
+ RS::SurfaceData *s = &m->surfaces.write[m->surfaces.size() - 1];
+ s->format = p_surface.format;
+ s->primitive = p_surface.primitive;
+ s->vertex_data = p_surface.vertex_data;
+ s->attribute_data = p_surface.attribute_data;
+ s->vertex_count = p_surface.vertex_count;
+ s->index_data = p_surface.index_data;
+ s->index_count = p_surface.index_count;
+ }
virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
@@ -60,8 +88,19 @@ public:
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
- virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
- virtual int mesh_get_surface_count(RID p_mesh) const override { return 0; }
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!m, RS::SurfaceData());
+ RS::SurfaceData s = m->surfaces[p_surface];
+ return s;
+ }
+
+ virtual int mesh_get_surface_count(RID p_mesh) const override {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!m, 0);
+ print_line(m->surfaces.size());
+ return m->surfaces.size();
+ }
virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
@@ -121,9 +160,13 @@ 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
-#endif // !MESH_STORAGE_DUMMY_H
+#endif // MESH_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h
index f614b41c4c..7cee55922d 100644
--- a/servers/rendering/dummy/storage/particles_storage.h
+++ b/servers/rendering/dummy/storage/particles_storage.h
@@ -123,4 +123,4 @@ public:
} // namespace RendererDummy
-#endif // !PARTICLES_STORAGE_DUMMY_H
+#endif // PARTICLES_STORAGE_DUMMY_H
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..73b1284558 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 */
@@ -166,8 +169,11 @@ public:
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
+
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{};
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{};
};
} // namespace RendererDummy
-#endif // !TEXTURE_STORAGE_DUMMY_H
+#endif // TEXTURE_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/storage/utilities.h
index 7f637d2c42..b94f678c75 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..c55021e1a1
--- /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..70d2bb3a9c 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,10 +75,7 @@ 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;
};
-#endif // !RENDERER_GI_H
+#endif // RENDERER_GI_H
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index bc1e8eb348..86e5e4802b 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;
@@ -594,9 +605,13 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
}
if (p_antialiased) {
- float border_size = 2.0;
- if (p_width < border_size) {
- border_size = p_width;
+ // Use the same antialiasing feather size as StyleBoxFlat's default
+ // (but doubled, as it's specified for both sides here).
+ // This value is empirically determined to provide good antialiasing quality
+ // while not making lines appear too soft.
+ float border_size = 1.25f;
+ if (p_width < 1.0f) {
+ border_size *= p_width;
}
Vector2 dir2 = diff.normalized();
@@ -763,9 +778,13 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Color *colors_ptr = colors.ptrw();
if (p_antialiased) {
- float border_size = 2.0;
- if (p_width < border_size) {
- border_size = p_width;
+ // Use the same antialiasing feather size as StyleBoxFlat's default
+ // (but doubled, as it's specified for both sides here).
+ // This value is empirically determined to provide good antialiasing quality
+ // while not making lines appear too soft.
+ float border_size = 1.25f;
+ if (p_width < 1.0f) {
+ border_size *= p_width;
}
Color color2 = Color(1, 1, 1, 0);
@@ -1895,11 +1914,11 @@ void RendererCanvasCull::update_visibility_notifiers() {
if (!visibility_notifier->enter_callable.is_null()) {
if (RSG::threaded) {
- visibility_notifier->enter_callable.call_deferred(nullptr, 0);
+ visibility_notifier->enter_callable.call_deferredp(nullptr, 0);
} else {
Callable::CallError ce;
Variant ret;
- visibility_notifier->enter_callable.call(nullptr, 0, ret, ce);
+ visibility_notifier->enter_callable.callp(nullptr, 0, ret, ce);
}
}
} else {
@@ -1908,11 +1927,11 @@ void RendererCanvasCull::update_visibility_notifiers() {
if (!visibility_notifier->exit_callable.is_null()) {
if (RSG::threaded) {
- visibility_notifier->exit_callable.call_deferred(nullptr, 0);
+ visibility_notifier->exit_callable.call_deferredp(nullptr, 0);
} else {
Callable::CallError ce;
Variant ret;
- visibility_notifier->exit_callable.call(nullptr, 0, ret, ce);
+ visibility_notifier->exit_callable.callp(nullptr, 0, ret, ce);
}
}
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 963cca7630..e8c54310c9 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_CANVAS_CULL_H
-#define RENDERING_SERVER_CANVAS_CULL_H
+#ifndef RENDERER_CANVAS_CULL_H
+#define RENDERER_CANVAS_CULL_H
#include "core/templates/paged_allocator.h"
#include "renderer_compositor.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;
}
};
@@ -315,4 +317,4 @@ public:
~RendererCanvasCull();
};
-#endif // RENDERING_SERVER_CANVAS_CULL_H
+#endif // RENDERER_CANVAS_CULL_H
diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp
index 163a24247e..623f0c647b 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_instance_free(mesh_instance);
+ }
+}
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 1724a99b20..11a7d34291 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERCANVASRENDER_H
-#define RENDERINGSERVERCANVASRENDER_H
+#ifndef RENDERER_CANVAS_RENDER_H
+#define RENDERER_CANVAS_RENDER_H
-#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
class RendererCanvasRender {
public:
@@ -77,7 +77,7 @@ public:
Rect2 rect_cache;
Transform2D xform_cache;
float radius_cache; //used for shadow far plane
- //CameraMatrix shadow_matrix_cache;
+ //Projection shadow_matrix_cache;
Transform2D light_shader_xform;
//Vector2 light_shader_pos;
@@ -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 {
@@ -524,4 +520,4 @@ public:
virtual ~RendererCanvasRender() {}
};
-#endif // RENDERINGSERVERCANVASRENDER_H
+#endif // RENDERER_CANVAS_RENDER_H
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index b331ec2c1d..80e71a0df3 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include "servers/xr_server.h"
RendererCompositor *(*RendererCompositor::_create_func)() = nullptr;
bool RendererCompositor::low_end = false;
@@ -46,7 +47,11 @@ bool RendererCompositor::is_xr_enabled() const {
}
RendererCompositor::RendererCompositor() {
- xr_enabled = GLOBAL_GET("xr/shaders/enabled");
+ if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) {
+ xr_enabled = GLOBAL_GET("xr/shaders/enabled");
+ } else {
+ xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON;
+ }
}
RendererCanvasRender *RendererCanvasRender::singleton = nullptr;
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index f58bc851ef..4cfded8460 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -28,18 +28,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_COMPOSITOR_H
-#define RENDERING_SERVER_COMPOSITOR_H
+#ifndef RENDERER_COMPOSITOR_H
+#define RENDERER_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;
@@ -107,4 +109,4 @@ public:
virtual ~RendererCompositor() {}
};
-#endif // RASTERIZER_H
+#endif // RENDERER_COMPOSITOR_H
diff --git a/servers/rendering/renderer_geometry_instance.cpp b/servers/rendering/renderer_geometry_instance.cpp
new file mode 100644
index 0000000000..675659f4c8
--- /dev/null
+++ b/servers/rendering/renderer_geometry_instance.cpp
@@ -0,0 +1,138 @@
+/*************************************************************************/
+/* renderer_geometry_instance.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 "servers/rendering/renderer_geometry_instance.h"
+
+void RenderGeometryInstanceBase::set_skeleton(RID p_skeleton) {
+ data->skeleton = p_skeleton;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_material_override(RID p_override) {
+ data->material_override = p_override;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_material_overlay(RID p_overlay) {
+ data->material_overlay = p_overlay;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_surface_materials(const Vector<RID> &p_materials) {
+ data->surface_materials = p_materials;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_mesh_instance(RID p_mesh_instance) {
+ mesh_instance = p_mesh_instance;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
+ transform = p_transform;
+ mirror = p_transform.basis.determinant() < 0;
+ data->aabb = p_aabb;
+ transformed_aabb = p_transformed_aabb;
+
+ Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
+ // handle non uniform scale here
+
+ float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
+ float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
+ non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
+
+ lod_model_scale = max_scale;
+}
+
+void RenderGeometryInstanceBase::set_lod_bias(float p_lod_bias) {
+ lod_bias = p_lod_bias;
+}
+
+void RenderGeometryInstanceBase::set_layer_mask(uint32_t p_layer_mask) {
+ layer_mask = p_layer_mask;
+}
+
+void RenderGeometryInstanceBase::set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
+ fade_near = p_enable_near;
+ fade_near_begin = p_near_begin;
+ fade_near_end = p_near_end;
+ fade_far = p_enable_far;
+ fade_far_begin = p_far_begin;
+ fade_far_end = p_far_end;
+}
+
+void RenderGeometryInstanceBase::set_parent_fade_alpha(float p_alpha) {
+ parent_fade_alpha = p_alpha;
+}
+
+void RenderGeometryInstanceBase::set_transparency(float p_transparency) {
+ force_alpha = CLAMP(1.0 - p_transparency, 0, 1);
+}
+
+void RenderGeometryInstanceBase::set_use_baked_light(bool p_enable) {
+ data->use_baked_light = p_enable;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_use_dynamic_gi(bool p_enable) {
+ data->use_dynamic_gi = p_enable;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_instance_shader_uniforms_offset(int32_t p_offset) {
+ shader_uniforms_offset = p_offset;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_cast_double_sided_shadows(bool p_enable) {
+ data->cast_double_sided_shadows = p_enable;
+
+ _mark_dirty();
+}
+
+Transform3D RenderGeometryInstanceBase::get_transform() {
+ return transform;
+}
+
+AABB RenderGeometryInstanceBase::get_aabb() {
+ return data->aabb;
+}
diff --git a/servers/rendering/renderer_geometry_instance.h b/servers/rendering/renderer_geometry_instance.h
new file mode 100644
index 0000000000..fecb9878c2
--- /dev/null
+++ b/servers/rendering/renderer_geometry_instance.h
@@ -0,0 +1,150 @@
+/*************************************************************************/
+/* renderer_geometry_instance.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_GEOMETRY_INSTANCE_H
+#define RENDERER_GEOMETRY_INSTANCE_H
+
+#include "core/math/rect2.h"
+#include "core/math/transform_3d.h"
+#include "core/math/vector3.h"
+#include "core/templates/rid.h"
+#include "storage/utilities.h"
+
+// API definition for our RenderGeometryInstance class so we can expose this through GDExternal in the near future
+class RenderGeometryInstance {
+public:
+ virtual ~RenderGeometryInstance() {}
+
+ virtual void _mark_dirty() = 0;
+
+ virtual void set_skeleton(RID p_skeleton) = 0;
+ virtual void set_material_override(RID p_override) = 0;
+ virtual void set_material_overlay(RID p_overlay) = 0;
+ virtual void set_surface_materials(const Vector<RID> &p_materials) = 0;
+ virtual void set_mesh_instance(RID p_mesh_instance) = 0;
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) = 0;
+ virtual void set_lod_bias(float p_lod_bias) = 0;
+ virtual void set_layer_mask(uint32_t p_layer_mask) = 0;
+ virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0;
+ virtual void set_parent_fade_alpha(float p_alpha) = 0;
+ virtual void set_transparency(float p_transparency) = 0;
+ virtual void set_use_baked_light(bool p_enable) = 0;
+ virtual void set_use_dynamic_gi(bool p_enable) = 0;
+ virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
+ virtual void set_lightmap_capture(const Color *p_sh9) = 0;
+ virtual void set_instance_shader_uniforms_offset(int32_t p_offset) = 0;
+ virtual void set_cast_double_sided_shadows(bool p_enable) = 0;
+
+ virtual Transform3D get_transform() = 0;
+ virtual AABB get_aabb() = 0;
+
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) = 0;
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0;
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0;
+
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) = 0;
+};
+
+// Base implementation of RenderGeometryInstance shared by internal renderers.
+class RenderGeometryInstanceBase : public RenderGeometryInstance {
+public:
+ // setup
+ uint32_t base_flags = 0;
+ uint32_t flags_cache = 0;
+
+ // used during rendering
+ float depth = 0;
+
+ RID mesh_instance;
+
+ Transform3D transform;
+ bool mirror = false; // move into data?
+ AABB transformed_aabb; //needed for LOD
+ bool non_uniform_scale = false;
+ float lod_model_scale = 1.0;
+ float lod_bias = 0.0;
+
+ uint32_t layer_mask = 1;
+
+ bool fade_near = false;
+ float fade_near_begin = 0;
+ float fade_near_end = 0;
+ bool fade_far = false;
+ float fade_far_begin = 0;
+ float fade_far_end = 0;
+
+ float parent_fade_alpha = 1.0;
+ float force_alpha = 1.0;
+
+ int32_t shader_uniforms_offset = -1;
+
+ struct Data {
+ //data used less often goes into regular heap
+ RID base;
+ RS::InstanceType base_type;
+
+ RID skeleton;
+ Vector<RID> surface_materials;
+ RID material_override;
+ RID material_overlay;
+ AABB aabb;
+
+ bool use_baked_light = false;
+ bool use_dynamic_gi = false;
+ bool cast_double_sided_shadows = false;
+ bool dirty_dependencies = false;
+
+ DependencyTracker dependency_tracker;
+ };
+
+ Data *data = nullptr;
+
+ virtual void set_skeleton(RID p_skeleton) override;
+ virtual void set_material_override(RID p_override) override;
+ virtual void set_material_overlay(RID p_overlay) override;
+ virtual void set_surface_materials(const Vector<RID> &p_materials) override;
+ virtual void set_mesh_instance(RID p_mesh_instance) override;
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
+ virtual void set_lod_bias(float p_lod_bias) override;
+ virtual void set_layer_mask(uint32_t p_layer_mask) override;
+ virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
+ virtual void set_parent_fade_alpha(float p_alpha) override;
+ virtual void set_transparency(float p_transparency) override;
+ virtual void set_use_baked_light(bool p_enable) override;
+ virtual void set_use_dynamic_gi(bool p_enable) override;
+ virtual void set_instance_shader_uniforms_offset(int32_t p_offset) override;
+ virtual void set_cast_double_sided_shadows(bool p_enable) override;
+
+ virtual Transform3D get_transform() override;
+ virtual AABB get_aabb() override;
+};
+
+#endif // RENDERER_GEOMETRY_INSTANCE_H
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 0b36fe3964..1bb45cbcc1 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -374,7 +374,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
}
}
-void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y) {
+void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y) {
view_xform = p_view_transform.affine_inverse();
projection = p_cam_projection;
z_near = projection.get_z_near();
@@ -385,7 +385,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMa
adjusted_projection.adjust_perspective_znear(0.0001);
}
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(p_flip_y);
projection = correction * projection;
adjusted_projection = correction * adjusted_projection;
@@ -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..17ca1986c6 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;
@@ -168,8 +168,8 @@ private:
uint32_t render_element_max = 0;
Transform3D view_xform;
- CameraMatrix adjusted_projection;
- CameraMatrix projection;
+ Projection adjusted_projection;
+ Projection projection;
float z_far = 0;
float z_near = 0;
bool orthogonal = false;
@@ -220,7 +220,7 @@ private:
public:
void setup(Size2i p_screen_size, uint32_t p_max_elements, RID p_depth_buffer, RID p_depth_buffer_sampler, RID p_color_buffer);
- void begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y);
+ void begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y);
_FORCE_INLINE_ void add_light(LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) {
if (p_type == LIGHT_TYPE_OMNI && cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT] == max_elements_by_type) {
@@ -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++;
@@ -375,4 +375,4 @@ public:
~ClusterBuilderRD();
};
-#endif // CLUSTER_BUILDER_H
+#endif // CLUSTER_BUILDER_RD_H
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h
index d7b736119c..30b33be168 100644
--- a/servers/rendering/renderer_rd/effects/bokeh_dof.h
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h
@@ -117,4 +117,4 @@ public:
} // namespace RendererRD
-#endif // !BOKEH_DOF_RD_H
+#endif // BOKEH_DOF_RD_H
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index c30e8ed58f..5507483cee 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -100,11 +100,11 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
{
Vector<String> copy_modes;
- copy_modes.push_back("\n");
- copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n");
- copy_modes.push_back("\n#define MODE_TWO_SOURCES\n");
- copy_modes.push_back("\n#define MULTIVIEW\n");
- copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n");
+ copy_modes.push_back("\n"); // COPY_TO_FB_COPY
+ copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); // COPY_TO_FB_COPY_PANORAMA_TO_DP
+ copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2
+ copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW
+ copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH
copy_to_fb.shader.initialize(copy_modes);
@@ -249,6 +249,56 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
roughness.raster_pipeline.clear();
}
}
+
+ {
+ Vector<String> specular_modes;
+ specular_modes.push_back("\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD
+ specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR
+ specular_modes.push_back("\n"); // SPECULAR_MERGE_ADDITIVE_ADD
+ specular_modes.push_back("\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR
+
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD_MULTIVIEW
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR_MULTIVIEW
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n"); // SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW
+
+ specular_merge.shader.initialize(specular_modes);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADD_MULTIVIEW, false);
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_SSR_MULTIVIEW, false);
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW, false);
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW, false);
+ }
+
+ specular_merge.shader_version = specular_merge.shader.version_create();
+
+ //use additive
+
+ RD::PipelineColorBlendState::Attachment ba;
+ ba.enable_blend = true;
+ ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.color_blend_op = RD::BLEND_OP_ADD;
+ ba.alpha_blend_op = RD::BLEND_OP_ADD;
+
+ RD::PipelineColorBlendState blend_additive;
+ blend_additive.attachments.push_back(ba);
+
+ for (int i = 0; i < SPECULAR_MERGE_MAX; i++) {
+ if (specular_merge.shader.is_variant_enabled(i)) {
+ RD::PipelineColorBlendState blend_state;
+ if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR || i == SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW || i == SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW) {
+ blend_state = blend_additive;
+ } else {
+ blend_state = RD::PipelineColorBlendState::create_disabled();
+ }
+ specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
+ }
+ }
}
CopyEffects::~CopyEffects() {
@@ -264,6 +314,8 @@ CopyEffects::~CopyEffects() {
roughness.compute_shader.version_free(roughness.shader_version);
}
+ specular_merge.shader.version_free(specular_merge.shader_version);
+
RD::get_singleton()->free(filter.coefficient_buffer);
if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
@@ -1083,3 +1135,57 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
+
+void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::get_singleton()->draw_command_begin_label("Merge specular");
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, Vector<Color>());
+
+ int mode;
+ if (p_reflection.is_valid()) {
+ if (p_base.is_valid()) {
+ mode = SPECULAR_MERGE_SSR;
+ } else {
+ mode = SPECULAR_MERGE_ADDITIVE_SSR;
+ }
+ } else {
+ if (p_base.is_valid()) {
+ mode = SPECULAR_MERGE_ADD;
+ } else {
+ mode = SPECULAR_MERGE_ADDITIVE_ADD;
+ }
+ }
+
+ if (p_view_count > 1) {
+ mode += SPECULAR_MERGE_ADD_MULTIVIEW;
+ }
+
+ RID shader = specular_merge.shader.version_get_shader(specular_merge.shader_version, mode);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+
+ if (p_base.is_valid()) {
+ RD::Uniform u_base(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_base }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_base), 2);
+ }
+
+ RD::Uniform u_specular(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_specular }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_specular), 0);
+
+ if (p_reflection.is_valid()) {
+ RD::Uniform u_reflection(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_reflection }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_reflection), 1);
+ }
+
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ RD::get_singleton()->draw_command_end_label();
+}
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
index 882b446964..d25555eee5 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.h
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COPY_RD_H
-#define COPY_RD_H
+#ifndef COPY_EFFECTS_RD_H
+#define COPY_EFFECTS_RD_H
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h"
@@ -42,6 +42,7 @@
#include "servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
@@ -274,6 +275,33 @@ private:
PipelineCacheRD raster_pipeline;
} roughness;
+ // Merge specular
+
+ enum SpecularMergeMode {
+ SPECULAR_MERGE_ADD,
+ SPECULAR_MERGE_SSR,
+ SPECULAR_MERGE_ADDITIVE_ADD,
+ SPECULAR_MERGE_ADDITIVE_SSR,
+
+ SPECULAR_MERGE_ADD_MULTIVIEW,
+ SPECULAR_MERGE_SSR_MULTIVIEW,
+ SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW,
+ SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW,
+
+ SPECULAR_MERGE_MAX
+ };
+
+ /* Specular merge must be done using raster, rather than compute
+ * because it must continue the existing color buffer
+ */
+
+ struct SpecularMerge {
+ SpecularMergeShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[SPECULAR_MERGE_MAX];
+
+ } specular_merge;
+
static CopyEffects *singleton;
public:
@@ -309,8 +337,10 @@ public:
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
+
+ void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count);
};
} // namespace RendererRD
-#endif // !COPY_RD_H
+#endif // COPY_EFFECTS_RD_H
diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h
index d4b24a610f..2a4cd06827 100644
--- a/servers/rendering/renderer_rd/effects/resolve.h
+++ b/servers/rendering/renderer_rd/effects/resolve.h
@@ -71,4 +71,4 @@ public:
} // namespace RendererRD
-#endif // !RESOLVE_RD_H
+#endif // RESOLVE_RD_H
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
new file mode 100644
index 0000000000..0f896a8aa7
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -0,0 +1,1715 @@
+/*************************************************************************/
+/* ss_effects.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 "ss_effects.h"
+
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+SSEffects *SSEffects::singleton = nullptr;
+
+static _FORCE_INLINE_ void store_camera(const Projection &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];
+ }
+ }
+}
+
+SSEffects::SSEffects() {
+ singleton = this;
+
+ {
+ // Initialize depth buffer for screen space effects
+ Vector<String> downsampler_modes;
+ downsampler_modes.push_back("\n");
+ downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");
+ downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");
+
+ ss_effects.downsample_shader.initialize(downsampler_modes);
+
+ ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();
+
+ for (int i = 0; i < SS_EFFECTS_MAX; i++) {
+ ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
+ }
+
+ ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));
+ SSEffectsGatherConstants gather_constants;
+
+ const int sub_pass_count = 5;
+ for (int pass = 0; pass < 4; pass++) {
+ for (int subPass = 0; subPass < sub_pass_count; subPass++) {
+ int a = pass;
+ int b = subPass;
+
+ int spmap[5]{ 0, 1, 4, 3, 2 };
+ b = spmap[subPass];
+
+ float ca, sa;
+ float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f;
+
+ ca = Math::cos(angle0);
+ sa = Math::sin(angle0);
+
+ float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f;
+
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca;
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa;
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa;
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca;
+ }
+ }
+
+ RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);
+ }
+
+ // Initialize Screen Space Indirect Lighting (SSIL)
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n");
+ ssil_modes.push_back("\n#define SSIL_BASE\n");
+ ssil_modes.push_back("\n#define ADAPTIVE\n");
+
+ ssil.gather_shader.initialize(ssil_modes);
+
+ ssil.gather_shader_version = ssil.gather_shader.version_create();
+
+ for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
+ }
+ ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define GENERATE_MAP\n");
+ ssil_modes.push_back("\n#define PROCESS_MAPA\n");
+ ssil_modes.push_back("\n#define PROCESS_MAPB\n");
+
+ ssil.importance_map_shader.initialize(ssil_modes);
+
+ ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();
+
+ for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
+ }
+ ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
+ RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(ssil.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);
+ RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssil_modes.push_back("\n#define MODE_SMART\n");
+ ssil_modes.push_back("\n#define MODE_WIDE\n");
+
+ ssil.blur_shader.initialize(ssil_modes);
+
+ ssil.blur_shader_version = ssil.blur_shader.version_create();
+ for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
+ }
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssil_modes.push_back("\n#define MODE_SMART\n");
+ ssil_modes.push_back("\n#define MODE_HALF\n");
+
+ ssil.interleave_shader.initialize(ssil_modes);
+
+ ssil.interleave_shader_version = ssil.interleave_shader.version_create();
+ for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
+ }
+ }
+
+ {
+ // Initialize Screen Space Ambient Occlusion (SSAO)
+
+ RD::SamplerState sampler;
+ sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.max_lod = 4;
+
+ uint32_t pipeline = 0;
+ {
+ Vector<String> ssao_modes;
+
+ ssao_modes.push_back("\n");
+ ssao_modes.push_back("\n#define SSAO_BASE\n");
+ ssao_modes.push_back("\n#define ADAPTIVE\n");
+
+ ssao.gather_shader.initialize(ssao_modes);
+
+ ssao.gather_shader_version = ssao.gather_shader.version_create();
+
+ for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
+ pipeline++;
+ }
+ }
+
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define GENERATE_MAP\n");
+ ssao_modes.push_back("\n#define PROCESS_MAPA\n");
+ ssao_modes.push_back("\n#define PROCESS_MAPB\n");
+
+ ssao.importance_map_shader.initialize(ssao_modes);
+
+ ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
+
+ for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
+
+ pipeline++;
+ }
+
+ ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
+ RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(ssao.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
+ RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
+ }
+
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssao_modes.push_back("\n#define MODE_SMART\n");
+ ssao_modes.push_back("\n#define MODE_WIDE\n");
+
+ ssao.blur_shader.initialize(ssao_modes);
+
+ ssao.blur_shader_version = ssao.blur_shader.version_create();
+
+ for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
+
+ pipeline++;
+ }
+ }
+
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssao_modes.push_back("\n#define MODE_SMART\n");
+ ssao_modes.push_back("\n#define MODE_HALF\n");
+
+ ssao.interleave_shader.initialize(ssao_modes);
+
+ ssao.interleave_shader_version = ssao.interleave_shader.version_create();
+ for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
+ RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
+ pipeline++;
+ }
+ }
+
+ ERR_FAIL_COND(pipeline != SSAO_MAX);
+
+ ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
+ }
+
+ {
+ // Screen Space Reflections
+
+ Vector<RD::PipelineSpecializationConstant> specialization_constants;
+
+ {
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 0; // SSR_USE_FULL_PROJECTION_MATRIX
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
+ }
+
+ {
+ Vector<String> ssr_scale_modes;
+ ssr_scale_modes.push_back("\n");
+
+ ssr_scale.shader.initialize(ssr_scale_modes);
+ ssr_scale.shader_version = ssr_scale.shader.version_create();
+
+ for (int v = 0; v < SSR_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
+ ssr_scale.pipelines[v] = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), specialization_constants);
+ }
+ }
+
+ {
+ Vector<String> ssr_modes;
+ ssr_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_NORMAL
+ ssr_modes.push_back("\n#define MODE_ROUGH\n"); // SCREEN_SPACE_REFLECTION_ROUGH
+
+ ssr.shader.initialize(ssr_modes);
+ ssr.shader_version = ssr.shader.version_create();
+
+ for (int v = 0; v < SSR_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
+ for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {
+ ssr.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i), specialization_constants);
+ }
+ }
+ }
+
+ {
+ Vector<String> ssr_filter_modes;
+ ssr_filter_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL
+ ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); // SCREEN_SPACE_REFLECTION_FILTER_VERTICAL
+
+ ssr_filter.shader.initialize(ssr_filter_modes);
+ ssr_filter.shader_version = ssr_filter.shader.version_create();
+
+ for (int v = 0; v < SSR_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
+ for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
+ ssr_filter.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i), specialization_constants);
+ }
+ }
+ }
+ }
+}
+
+SSEffects::~SSEffects() {
+ {
+ // Cleanup SS Reflections
+ ssr.shader.version_free(ssr.shader_version);
+ ssr_filter.shader.version_free(ssr_filter.shader_version);
+ ssr_scale.shader.version_free(ssr_scale.shader_version);
+
+ if (ssr.ubo.is_valid()) {
+ RD::get_singleton()->free(ssr.ubo);
+ }
+ }
+
+ {
+ // Cleanup SS downsampler
+ ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
+
+ RD::get_singleton()->free(ss_effects.mirror_sampler);
+ RD::get_singleton()->free(ss_effects.gather_constants_buffer);
+ }
+
+ {
+ // Cleanup SSIL
+ ssil.blur_shader.version_free(ssil.blur_shader_version);
+ ssil.gather_shader.version_free(ssil.gather_shader_version);
+ ssil.interleave_shader.version_free(ssil.interleave_shader_version);
+ ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);
+
+ RD::get_singleton()->free(ssil.importance_map_load_counter);
+ RD::get_singleton()->free(ssil.projection_uniform_buffer);
+ }
+
+ {
+ // Cleanup SSAO
+ ssao.blur_shader.version_free(ssao.blur_shader_version);
+ ssao.gather_shader.version_free(ssao.gather_shader_version);
+ ssao.interleave_shader.version_free(ssao.interleave_shader_version);
+ ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);
+
+ RD::get_singleton()->free(ssao.importance_map_load_counter);
+ }
+
+ singleton = nullptr;
+}
+
+/* SS Downsampler */
+
+void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // Downsample and deinterleave the depth buffer for SSAO and SSIL
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ int downsample_mode = SS_EFFECTS_DOWNSAMPLE;
+ bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
+
+ if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF;
+ } else if (use_mips) {
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
+ }
+
+ bool use_half_size = false;
+ bool use_full_mips = false;
+
+ if (p_ssao_half_size && p_ssil_half_size) {
+ downsample_mode++;
+ use_half_size = true;
+ } else if (p_ssao_half_size != p_ssil_half_size) {
+ if (use_mips) {
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
+ use_full_mips = true;
+ } else {
+ // Only need the first two mipmaps, but the cost to generate the next two is trivial
+ // TODO investigate the benefit of a shader version to generate only 2 mips
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
+ use_mips = true;
+ }
+ }
+
+ int depth_index = use_half_size ? 1 : 0;
+
+ RD::get_singleton()->draw_command_begin_label("Downsample Depth");
+ if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.append_id(p_depth_mipmaps[depth_index + 1]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(p_depth_mipmaps[depth_index + 2]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.append_id(p_depth_mipmaps[depth_index + 3]);
+ uniforms.push_back(u);
+ }
+ if (use_full_mips) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.append_id(p_depth_mipmaps[4]);
+ uniforms.push_back(u);
+ }
+ ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
+ }
+
+ float depth_linearize_mul = -p_projection.matrix[3][2];
+ float depth_linearize_add = p_projection.matrix[2][2];
+ if (depth_linearize_mul * depth_linearize_add < 0) {
+ depth_linearize_add = -depth_linearize_add;
+ }
+
+ ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
+ ss_effects.downsample_push_constant.z_near = depth_linearize_mul;
+ ss_effects.downsample_push_constant.z_far = depth_linearize_add;
+ if (ss_effects.downsample_push_constant.orthogonal) {
+ ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
+ ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
+ }
+ ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x;
+ ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y;
+ ss_effects.downsample_push_constant.radius_sq = 1.0;
+
+ RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode);
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_buffer }));
+ RD::Uniform u_depth_mipmaps(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_depth_mipmaps[depth_index + 0] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmaps), 1);
+ if (use_mips) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2);
+ }
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
+
+ Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1)));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
+
+ ss_effects.used_full_mips_last_frame = use_full_mips;
+ ss_effects.used_half_size_last_frame = use_half_size;
+}
+
+/* SSIL */
+
+void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
+ if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
+
+ RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_slices[i] }));
+ RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_edges_slices[i] }));
+
+ ssil.gather_push_constant.pass_coord_offset[0] = i % 2;
+ ssil.gather_push_constant.pass_coord_offset[1] = i / 2;
+ ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
+ ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
+ ssil.gather_push_constant.pass = i;
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ssil_slice, u_edges_slice), 2);
+ RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
+
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
+ }
+ RD::get_singleton()->compute_list_add_barrier(p_compute_list);
+}
+
+void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth) {
+ if (p_ssil_buffers.half_size != p_settings.half_size) {
+ ssil_free(p_ssil_buffers);
+ }
+
+ if (p_settings.half_size) {
+ p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
+ p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
+ } else {
+ p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
+ p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
+ p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ }
+
+ if (p_ssil_buffers.ssil_final.is_null()) {
+ {
+ p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = p_settings.full_screen_size.x;
+ tf.height = p_settings.full_screen_size.y;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ p_ssil_buffers.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.ssil_final, "SSIL texture");
+ RD::get_singleton()->texture_clear(p_ssil_buffers.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ if (p_ssil_buffers.last_frame.is_null()) {
+ tf.mipmaps = 6;
+ p_ssil_buffers.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.last_frame, "Last Frame Radiance");
+ RD::get_singleton()->texture_clear(p_ssil_buffers.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1);
+ for (uint32_t i = 0; i < 6; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.last_frame, 0, i);
+ p_ssil_buffers.last_frame_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " ");
+ }
+ }
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssil_buffers.buffer_width;
+ tf.height = p_ssil_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.deinterleaved, "SSIL deinterleaved buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.deinterleaved, i, 0);
+ p_ssil_buffers.deinterleaved_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssil_buffers.buffer_width;
+ tf.height = p_ssil_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.pong, "SSIL deinterleaved pong buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.pong, i, 0);
+ p_ssil_buffers.pong_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssil_buffers.buffer_width;
+ tf.height = p_ssil_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.edges = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.edges, "SSIL edges buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.edges, i, 0);
+ p_ssil_buffers.edges_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_ssil_buffers.half_buffer_width;
+ tf.height = p_ssil_buffers.half_buffer_height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[0], "SSIL Importance Map");
+ p_ssil_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[1], "SSIL Importance Map Pong");
+ }
+ p_ssil_buffers.half_size = p_settings.half_size;
+ }
+}
+
+void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");
+ //Store projection info before starting the compute list
+ SSILProjectionUniforms projection_uniforms;
+ store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
+
+ RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);
+
+ memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
+
+ RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ {
+ RD::get_singleton()->draw_command_begin_label("Gather Samples");
+ ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
+ ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
+
+ ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
+ ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+ float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
+ float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
+ ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
+ ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
+ ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
+ ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
+ ssil.gather_push_constant.z_near = p_projection.get_z_near();
+ ssil.gather_push_constant.z_far = p_projection.get_z_far();
+ ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
+
+ ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
+ ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
+
+ ssil.gather_push_constant.radius = p_settings.radius;
+ float radius_near_limit = (p_settings.radius * 1.2f);
+ if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) {
+ radius_near_limit *= 1.50f;
+
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ ssil.gather_push_constant.radius *= 0.8f;
+ }
+ }
+ radius_near_limit /= tan_half_fov_y;
+ ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI;
+ ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
+ ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
+ ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
+ ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
+ ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
+
+ ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255);
+ ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
+
+ ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
+ ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
+
+ if (p_ssil_buffers.projection_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.append_id(default_mipmap_sampler);
+ u.append_id(p_ssil_buffers.last_frame);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 1;
+ u.append_id(ssil.projection_uniform_buffer);
+ uniforms.push_back(u);
+ }
+ p_ssil_buffers.projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
+ }
+
+ if (p_ssil_buffers.gather_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.append_id(default_sampler);
+ u.append_id(p_ssil_buffers.depth_texture_view);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(p_normal_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.append_id(ss_effects.gather_constants_buffer);
+ uniforms.push_back(u);
+ }
+ p_ssil_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
+ }
+
+ if (p_ssil_buffers.importance_map_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.append_id(p_ssil_buffers.pong);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 1;
+ u.append_id(default_sampler);
+ u.append_id(p_ssil_buffers.importance_map[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(ssil.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ p_ssil_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
+ }
+
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) {
+ RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
+ ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
+ ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+ ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI;
+ //base pass
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
+ gather_ssil(compute_list, p_ssil_buffers.pong_slices, p_ssil_buffers.edges_slices, p_settings, true, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set);
+
+ //generate importance map
+ RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong }));
+ RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[0] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // process Importance Map A
+ RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[0] }));
+ RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[1] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // process Importance Map B
+ RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[1] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->draw_command_end_label(); // Importance Map
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);
+ } else {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
+ }
+
+ gather_ssil(compute_list, p_ssil_buffers.deinterleaved_slices, p_ssil_buffers.edges_slices, p_settings, false, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set);
+ RD::get_singleton()->draw_command_end_label(); //Gather
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
+ ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
+ ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
+ ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+
+ int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
+
+ shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0);
+
+ for (int pass = 0; pass < blur_passes; pass++) {
+ int blur_pipeline = SSIL_BLUR_PASS;
+ if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ blur_pipeline = SSIL_BLUR_PASS_SMART;
+ if (pass < blur_passes - 2) {
+ blur_pipeline = SSIL_BLUR_PASS_WIDE;
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
+ if (pass % 2 == 0) {
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0);
+ } else {
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0);
+ }
+
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong_slice), 1);
+ } else {
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0);
+ } else {
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0);
+ }
+
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_slice), 1);
+ }
+
+ RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges_slice), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
+
+ int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1));
+ int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
+ if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ }
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // Blur
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
+ ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
+ ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
+ ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
+ ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
+
+ int interleave_pipeline = SSIL_INTERLEAVE_HALF;
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) {
+ interleave_pipeline = SSIL_INTERLEAVE;
+ } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
+ interleave_pipeline = SSIL_INTERLEAVE_SMART;
+ }
+
+ shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
+
+ RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.ssil_final }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0);
+
+ if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
+ RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1);
+ } else {
+ RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1);
+ }
+
+ RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label(); // Interleave
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // SSIL
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
+
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
+}
+
+void SSEffects::ssil_free(SSILRenderBuffers &p_ssil_buffers) {
+ if (p_ssil_buffers.ssil_final.is_valid()) {
+ RD::get_singleton()->free(p_ssil_buffers.ssil_final);
+ RD::get_singleton()->free(p_ssil_buffers.deinterleaved);
+ RD::get_singleton()->free(p_ssil_buffers.pong);
+ RD::get_singleton()->free(p_ssil_buffers.edges);
+ RD::get_singleton()->free(p_ssil_buffers.importance_map[0]);
+ RD::get_singleton()->free(p_ssil_buffers.importance_map[1]);
+ RD::get_singleton()->free(p_ssil_buffers.last_frame);
+
+ p_ssil_buffers.ssil_final = RID();
+ p_ssil_buffers.deinterleaved = RID();
+ p_ssil_buffers.pong = RID();
+ p_ssil_buffers.edges = RID();
+ p_ssil_buffers.deinterleaved_slices.clear();
+ p_ssil_buffers.pong_slices.clear();
+ p_ssil_buffers.edges_slices.clear();
+ p_ssil_buffers.importance_map[0] = RID();
+ p_ssil_buffers.importance_map[1] = RID();
+ p_ssil_buffers.last_frame = RID();
+ p_ssil_buffers.last_frame_slices.clear();
+
+ p_ssil_buffers.gather_uniform_set = RID();
+ p_ssil_buffers.importance_map_uniform_set = RID();
+ p_ssil_buffers.projection_uniform_set = RID();
+ }
+}
+
+/* SSAO */
+
+void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
+ if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 0);
+ }
+
+ RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); //
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::Uniform u_ao_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ao_slices[i] }));
+
+ ssao.gather_push_constant.pass_coord_offset[0] = i % 2;
+ ssao.gather_push_constant.pass_coord_offset[1] = i / 2;
+ ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
+ ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
+ ssao.gather_push_constant.pass = i;
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2);
+ RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
+
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
+ }
+ RD::get_singleton()->compute_list_add_barrier(p_compute_list);
+}
+
+void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth) {
+ if (p_ssao_buffers.half_size != p_settings.half_size) {
+ ssao_free(p_ssao_buffers);
+ }
+
+ if (p_settings.half_size) {
+ p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
+ p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
+ } else {
+ p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
+ p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
+ p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ }
+
+ if (p_ssao_buffers.ao_deinterleaved.is_null()) {
+ {
+ p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8G8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssao_buffers.buffer_width;
+ tf.height = p_ssao_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_deinterleaved, "SSAO De-interleaved Array");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_deinterleaved, i, 0);
+ p_ssao_buffers.ao_deinterleaved_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8G8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssao_buffers.buffer_width;
+ tf.height = p_ssao_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_pong, "SSAO De-interleaved Array Pong");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_pong, i, 0);
+ p_ssao_buffers.ao_pong_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_ssao_buffers.buffer_width;
+ tf.height = p_ssao_buffers.buffer_height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[0], "SSAO Importance Map");
+ p_ssao_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[1], "SSAO Importance Map Pong");
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_settings.full_screen_size.x;
+ tf.height = p_settings.full_screen_size.y;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_final, "SSAO Final");
+ }
+ p_ssao_buffers.half_size = p_settings.half_size;
+ }
+}
+
+void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
+ /* FIRST PASS */
+
+ RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0);
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");
+ /* SECOND PASS */
+ // Sample SSAO
+ {
+ RD::get_singleton()->draw_command_begin_label("Gather Samples");
+ ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
+ ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
+
+ ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
+ ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+ float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
+ float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
+ ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
+ ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
+ ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
+ ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
+ ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
+
+ ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
+ ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
+
+ ssao.gather_push_constant.radius = p_settings.radius;
+ float radius_near_limit = (p_settings.radius * 1.2f);
+ if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) {
+ radius_near_limit *= 1.50f;
+
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ ssao.gather_push_constant.radius *= 0.8f;
+ }
+ }
+ radius_near_limit /= tan_half_fov_y;
+ ssao.gather_push_constant.intensity = p_settings.intensity;
+ ssao.gather_push_constant.shadow_power = p_settings.power;
+ ssao.gather_push_constant.shadow_clamp = 0.98;
+ ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
+ ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
+ ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;
+ ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
+ ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
+
+ ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255);
+ ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
+
+ ssao.gather_push_constant.detail_intensity = p_settings.detail;
+ ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
+ ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
+
+ if (p_ssao_buffers.gather_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.append_id(default_sampler);
+ u.append_id(p_ssao_buffers.depth_texture_view);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(p_normal_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.append_id(ss_effects.gather_constants_buffer);
+ uniforms.push_back(u);
+ }
+ p_ssao_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader, 0);
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.gather_uniform_set, "SSAO Gather Uniform Set");
+ }
+
+ if (p_ssao_buffers.importance_map_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.append_id(p_ssao_buffers.ao_pong);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 1;
+ u.append_id(default_sampler);
+ u.append_id(p_ssao_buffers.importance_map[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(ssao.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ p_ssao_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map_uniform_set, "SSAO Importance Map Uniform Set");
+ }
+
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) {
+ RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
+ ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
+ ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+ ssao.importance_map_push_constant.intensity = p_settings.intensity;
+ ssao.importance_map_push_constant.power = p_settings.power;
+
+ //base pass
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
+ gather_ssao(compute_list, p_ssao_buffers.ao_pong_slices, p_settings, true, p_ssao_buffers.gather_uniform_set, RID());
+
+ //generate importance map
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
+
+ RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_with_sampler), 0);
+
+ RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //process importance map A
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
+
+ RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0);
+
+ RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //process Importance Map B
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
+
+ RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
+ RD::get_singleton()->draw_command_end_label(); // Importance Map
+ } else {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
+ }
+
+ gather_ssao(compute_list, p_ssao_buffers.ao_deinterleaved_slices, p_settings, false, p_ssao_buffers.gather_uniform_set, p_ssao_buffers.importance_map_uniform_set);
+ RD::get_singleton()->draw_command_end_label(); // Gather SSAO
+ }
+
+ // /* THIRD PASS */
+ // // Blur
+ //
+ {
+ RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
+ ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
+ ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
+ ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+
+ int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
+
+ shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0);
+
+ for (int pass = 0; pass < blur_passes; pass++) {
+ int blur_pipeline = SSAO_BLUR_PASS;
+ if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ blur_pipeline = SSAO_BLUR_PASS_SMART;
+ if (pass < blur_passes - 2) {
+ blur_pipeline = SSAO_BLUR_PASS_WIDE;
+ } else {
+ blur_pipeline = SSAO_BLUR_PASS_SMART;
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
+ if (pass % 2 == 0) {
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0);
+ } else {
+ RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0);
+ }
+
+ RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_pong_slices), 1);
+ } else {
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0);
+ } else {
+ RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0);
+ }
+
+ RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_slices), 1);
+ }
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
+
+ Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
+ }
+
+ if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ }
+ RD::get_singleton()->draw_command_end_label(); // Blur
+ }
+
+ /* FOURTH PASS */
+ // Interleave buffers
+ // back to full size
+ {
+ RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
+ ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
+ ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
+ ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
+ ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
+
+ shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0);
+
+ int interleave_pipeline = SSAO_INTERLEAVE_HALF;
+ if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) {
+ interleave_pipeline = SSAO_INTERLEAVE;
+ } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
+ interleave_pipeline = SSAO_INTERLEAVE_SMART;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);
+
+ RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_final }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_buffer), 0);
+
+ if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
+ RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1);
+ } else {
+ RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label(); // Interleave
+ }
+ RD::get_singleton()->draw_command_end_label(); //SSAO
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer
+
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
+}
+
+void SSEffects::ssao_free(SSAORenderBuffers &p_ssao_buffers) {
+ if (p_ssao_buffers.ao_final.is_valid()) {
+ RD::get_singleton()->free(p_ssao_buffers.ao_deinterleaved);
+ RD::get_singleton()->free(p_ssao_buffers.ao_pong);
+ RD::get_singleton()->free(p_ssao_buffers.ao_final);
+
+ RD::get_singleton()->free(p_ssao_buffers.importance_map[0]);
+ RD::get_singleton()->free(p_ssao_buffers.importance_map[1]);
+
+ p_ssao_buffers.ao_deinterleaved = RID();
+ p_ssao_buffers.ao_pong = RID();
+ p_ssao_buffers.ao_final = RID();
+ p_ssao_buffers.importance_map[0] = RID();
+ p_ssao_buffers.importance_map[1] = RID();
+ p_ssao_buffers.ao_deinterleaved_slices.clear();
+ p_ssao_buffers.ao_pong_slices.clear();
+
+ p_ssao_buffers.gather_uniform_set = RID();
+ p_ssao_buffers.importance_map_uniform_set = RID();
+ }
+}
+
+/* Screen Space Reflection */
+
+void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count) {
+ // As we are processing one view at a time, we can reuse buffers, only our output needs to have layers for each view.
+
+ if (p_ssr_buffers.depth_scaled.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R32_SFLOAT;
+ tf.width = p_screen_size.x;
+ tf.height = p_screen_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ p_ssr_buffers.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.depth_scaled, "SSR Depth Scaled");
+
+ tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+
+ p_ssr_buffers.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.normal_scaled, "SSR Normal Scaled");
+ }
+
+ if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_ssr_buffers.blur_radius[0].is_valid()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_screen_size.x;
+ tf.height = p_screen_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ p_ssr_buffers.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[0], "SSR Blur Radius 0");
+ p_ssr_buffers.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[1], "SSR Blur Radius 1");
+ }
+
+ if (p_ssr_buffers.intermediate.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = p_color_format;
+ tf.width = p_screen_size.x;
+ tf.height = p_screen_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ p_ssr_buffers.intermediate = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.intermediate, "SSR Intermediate");
+
+ if (p_view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.array_layers = p_view_count;
+ } else {
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ }
+
+ p_ssr_buffers.output = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.output, "SSR Output");
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ p_ssr_buffers.output_slices[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssr_buffers.output, v, 0);
+ }
+ }
+}
+
+void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ {
+ // Store some scene data in a UBO, in the near future we will use a UBO shared with other shaders
+ ScreenSpaceReflectionSceneData scene_data;
+
+ if (ssr.ubo.is_null()) {
+ ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData));
+ }
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ store_camera(p_projections[v], scene_data.projection[v]);
+ 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;
+ scene_data.eye_offset[v][3] = 0.0;
+ }
+
+ RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
+ }
+
+ uint32_t pipeline_specialization = 0;
+ if (p_view_count > 1) {
+ pipeline_specialization |= SSR_MULTIVIEW;
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ RD::get_singleton()->draw_command_begin_label(String("SSR View ") + itos(v));
+
+ { //scale color and depth to half
+ RD::get_singleton()->draw_command_begin_label("SSR Scale");
+
+ ScreenSpaceReflectionScalePushConstant push_constant;
+ push_constant.view_index = v;
+ push_constant.camera_z_far = p_projections[v].get_z_far();
+ push_constant.camera_z_near = p_projections[v].get_z_near();
+ push_constant.orthogonal = p_projections[v].is_orthogonal();
+ push_constant.filter = false; //enabling causes arctifacts
+ push_constant.screen_size[0] = p_screen_size.x;
+ push_constant.screen_size[1] = p_screen_size.y;
+
+ RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]);
+
+ RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0);
+
+ RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_slices[v] }));
+ RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1);
+
+ RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur), 2);
+
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth, u_scale_normal), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("SSR main");
+
+ ScreenSpaceReflectionPushConstant push_constant;
+ push_constant.view_index = v;
+ push_constant.camera_z_far = p_projections[v].get_z_far();
+ push_constant.camera_z_near = p_projections[v].get_z_near();
+ push_constant.orthogonal = p_projections[v].is_orthogonal();
+ push_constant.screen_size[0] = p_screen_size.x;
+ push_constant.screen_size[1] = p_screen_size.y;
+ push_constant.curve_fade_in = p_fade_in;
+ push_constant.distance_fade = p_fade_out;
+ push_constant.num_steps = p_max_steps;
+ push_constant.depth_tolerance = p_tolerance;
+ push_constant.use_half_res = true;
+ push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]);
+ push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]);
+ push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
+ push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
+ push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255);
+ push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255);
+ push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255);
+ push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255);
+
+ ScreenSpaceReflectionMode mode = (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL;
+ RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode]);
+
+ RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
+ RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_scale_depth), 0);
+
+ if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate, u_blur_radius), 1);
+ } else {
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
+ }
+
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_scale_normal), 2);
+
+ RD::Uniform u_metallic(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_metallic_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_metallic), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ RD::get_singleton()->draw_command_begin_label("SSR filter");
+ //blur
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ ScreenSpaceReflectionFilterPushConstant push_constant;
+ push_constant.view_index = v;
+ push_constant.orthogonal = p_projections[v].is_orthogonal();
+ push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0));
+ push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]);
+ push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]);
+ push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
+ push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
+ push_constant.vertical = 0;
+ if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
+ push_constant.steps = p_max_steps / 3;
+ push_constant.increment = 3;
+ } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {
+ push_constant.steps = p_max_steps / 2;
+ push_constant.increment = 2;
+ } else {
+ push_constant.steps = p_max_steps;
+ push_constant.increment = 1;
+ }
+
+ push_constant.screen_size[0] = p_screen_size.width;
+ push_constant.screen_size[1] = p_screen_size.height;
+
+ // Horizontal pass
+
+ SSRReflectionMode mode = SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL;
+
+ RID shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
+
+ RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius), 0);
+
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
+
+ RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur, u_blur_radius2), 2);
+
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // Vertical pass
+
+ mode = SCREEN_SPACE_REFLECTION_FILTER_VERTICAL;
+ shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
+
+ push_constant.vertical = 1;
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_blur_radius2), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ if (v != p_view_count - 1) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) {
+ for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
+ p_ssr_buffers.output_slices[v] = RID();
+ }
+
+ if (p_ssr_buffers.output.is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.output);
+ p_ssr_buffers.output = RID();
+ }
+
+ if (p_ssr_buffers.intermediate.is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.intermediate);
+ p_ssr_buffers.intermediate = RID();
+ }
+
+ if (p_ssr_buffers.blur_radius[0].is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.blur_radius[0]);
+ RD::get_singleton()->free(p_ssr_buffers.blur_radius[1]);
+ p_ssr_buffers.blur_radius[0] = RID();
+ p_ssr_buffers.blur_radius[1] = RID();
+ }
+
+ if (p_ssr_buffers.depth_scaled.is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.depth_scaled);
+ p_ssr_buffers.depth_scaled = RID();
+ RD::get_singleton()->free(p_ssr_buffers.normal_scaled);
+ p_ssr_buffers.normal_scaled = RID();
+ }
+}
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h
new file mode 100644
index 0000000000..c31271ffd2
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/ss_effects.h
@@ -0,0 +1,508 @@
+/*************************************************************************/
+/* ss_effects.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 SS_EFFECTS_RD_H
+#define SS_EFFECTS_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class SSEffects {
+private:
+ static SSEffects *singleton;
+
+public:
+ static SSEffects *get_singleton() { return singleton; }
+
+ SSEffects();
+ ~SSEffects();
+
+ /* SS Downsampler */
+
+ void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection);
+
+ /* SSIL */
+
+ struct SSILRenderBuffers {
+ bool half_size = false;
+ int buffer_width;
+ int buffer_height;
+ int half_buffer_width;
+ int half_buffer_height;
+
+ RID ssil_final;
+ RID deinterleaved;
+ Vector<RID> deinterleaved_slices;
+ RID pong;
+ Vector<RID> pong_slices;
+ RID edges;
+ Vector<RID> edges_slices;
+ RID importance_map[2];
+ RID depth_texture_view;
+
+ RID last_frame;
+ Vector<RID> last_frame_slices;
+
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
+ RID projection_uniform_set;
+ };
+
+ struct SSILSettings {
+ float radius = 1.0;
+ float intensity = 2.0;
+ float sharpness = 0.98;
+ float normal_rejection = 1.0;
+
+ RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM;
+ bool half_size = true;
+ float adaptive_target = 0.5;
+ int blur_passes = 4;
+ float fadeout_from = 50.0;
+ float fadeout_to = 300.0;
+
+ Size2i full_screen_size = Size2i();
+ };
+
+ void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth);
+ void screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings);
+ void ssil_free(SSILRenderBuffers &p_ssil_buffers);
+
+ /* SSAO */
+
+ struct SSAORenderBuffers {
+ bool half_size = false;
+ int buffer_width;
+ int buffer_height;
+ int half_buffer_width;
+ int half_buffer_height;
+
+ RID ao_deinterleaved;
+ Vector<RID> ao_deinterleaved_slices;
+ RID ao_pong;
+ Vector<RID> ao_pong_slices;
+ RID ao_final;
+ RID importance_map[2];
+ RID depth_texture_view;
+
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
+ };
+
+ struct SSAOSettings {
+ float radius = 1.0;
+ float intensity = 2.0;
+ float power = 1.5;
+ float detail = 0.5;
+ float horizon = 0.06;
+ float sharpness = 0.98;
+
+ RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM;
+ bool half_size = false;
+ float adaptive_target = 0.5;
+ int blur_passes = 2;
+ float fadeout_from = 50.0;
+ float fadeout_to = 300.0;
+
+ Size2i full_screen_size = Size2i();
+ };
+
+ void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth);
+ void generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings);
+ void ssao_free(SSAORenderBuffers &p_ssao_buffers);
+
+ /* Screen Space Reflection */
+
+ struct SSRRenderBuffers {
+ RID normal_scaled;
+ RID depth_scaled;
+ RID blur_radius[2];
+ RID intermediate;
+ RID output;
+ RID output_slices[RendererSceneRender::MAX_RENDER_VIEWS];
+ };
+
+ void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count);
+ void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets);
+ void ssr_free(SSRRenderBuffers &p_ssr_buffers);
+
+private:
+ /* SS Downsampler */
+
+ struct SSEffectsDownsamplePushConstant {
+ float pixel_size[2];
+ float z_far;
+ float z_near;
+ uint32_t orthogonal;
+ float radius_sq;
+ uint32_t pad[2];
+ };
+
+ enum SSEffectsMode {
+ SS_EFFECTS_DOWNSAMPLE,
+ SS_EFFECTS_DOWNSAMPLE_HALF_RES,
+ SS_EFFECTS_DOWNSAMPLE_MIPMAP,
+ SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES,
+ SS_EFFECTS_DOWNSAMPLE_HALF,
+ SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF,
+ SS_EFFECTS_DOWNSAMPLE_FULL_MIPS,
+ SS_EFFECTS_MAX
+ };
+
+ struct SSEffectsGatherConstants {
+ float rotation_matrices[80]; //5 vec4s * 4
+ };
+
+ struct SSEffectsShader {
+ SSEffectsDownsamplePushConstant downsample_push_constant;
+ SsEffectsDownsampleShaderRD downsample_shader;
+ RID downsample_shader_version;
+ RID downsample_uniform_set;
+ bool used_half_size_last_frame = false;
+ bool used_mips_last_frame = false;
+ bool used_full_mips_last_frame = false;
+
+ RID gather_constants_buffer;
+
+ RID mirror_sampler;
+
+ RID pipelines[SS_EFFECTS_MAX];
+ } ss_effects;
+
+ /* SSIL */
+
+ enum SSILMode {
+ SSIL_GATHER,
+ SSIL_GATHER_BASE,
+ SSIL_GATHER_ADAPTIVE,
+ SSIL_GENERATE_IMPORTANCE_MAP,
+ SSIL_PROCESS_IMPORTANCE_MAPA,
+ SSIL_PROCESS_IMPORTANCE_MAPB,
+ SSIL_BLUR_PASS,
+ SSIL_BLUR_PASS_SMART,
+ SSIL_BLUR_PASS_WIDE,
+ SSIL_INTERLEAVE,
+ SSIL_INTERLEAVE_SMART,
+ SSIL_INTERLEAVE_HALF,
+ SSIL_MAX
+ };
+
+ struct SSILGatherPushConstant {
+ int32_t screen_size[2];
+ int pass;
+ int quality;
+
+ float half_screen_pixel_size[2];
+ float half_screen_pixel_size_x025[2];
+
+ float NDC_to_view_mul[2];
+ float NDC_to_view_add[2];
+
+ float pad2[2];
+ float z_near;
+ float z_far;
+
+ float radius;
+ float intensity;
+ int size_multiplier;
+ int pad;
+
+ float fade_out_mul;
+ float fade_out_add;
+ float normal_rejection_amount;
+ float inv_radius_near_limit;
+
+ uint32_t is_orthogonal;
+ float neg_inv_radius;
+ float load_counter_avg_div;
+ float adaptive_sample_limit;
+
+ int32_t pass_coord_offset[2];
+ float pass_uv_offset[2];
+ };
+
+ struct SSILImportanceMapPushConstant {
+ float half_screen_pixel_size[2];
+ float intensity;
+ float pad;
+ };
+
+ struct SSILBlurPushConstant {
+ float edge_sharpness;
+ float pad;
+ float half_screen_pixel_size[2];
+ };
+
+ struct SSILInterleavePushConstant {
+ float inv_sharpness;
+ uint32_t size_modifier;
+ float pixel_size[2];
+ };
+
+ struct SSILProjectionUniforms {
+ float inv_last_frame_projection_matrix[16];
+ };
+
+ struct SSIL {
+ SSILGatherPushConstant gather_push_constant;
+ SsilShaderRD gather_shader;
+ RID gather_shader_version;
+ RID projection_uniform_buffer;
+
+ SSILImportanceMapPushConstant importance_map_push_constant;
+ SsilImportanceMapShaderRD importance_map_shader;
+ RID importance_map_shader_version;
+ RID importance_map_load_counter;
+ RID counter_uniform_set;
+
+ SSILBlurPushConstant blur_push_constant;
+ SsilBlurShaderRD blur_shader;
+ RID blur_shader_version;
+
+ SSILInterleavePushConstant interleave_push_constant;
+ SsilInterleaveShaderRD interleave_shader;
+ RID interleave_shader_version;
+
+ RID pipelines[SSIL_MAX];
+ } ssil;
+
+ void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
+
+ /* SSAO */
+
+ enum SSAOMode {
+ SSAO_GATHER,
+ SSAO_GATHER_BASE,
+ SSAO_GATHER_ADAPTIVE,
+ SSAO_GENERATE_IMPORTANCE_MAP,
+ SSAO_PROCESS_IMPORTANCE_MAPA,
+ SSAO_PROCESS_IMPORTANCE_MAPB,
+ SSAO_BLUR_PASS,
+ SSAO_BLUR_PASS_SMART,
+ SSAO_BLUR_PASS_WIDE,
+ SSAO_INTERLEAVE,
+ SSAO_INTERLEAVE_SMART,
+ SSAO_INTERLEAVE_HALF,
+ SSAO_MAX
+ };
+
+ struct SSAOGatherPushConstant {
+ int32_t screen_size[2];
+ int pass;
+ int quality;
+
+ float half_screen_pixel_size[2];
+ int size_multiplier;
+ float detail_intensity;
+
+ float NDC_to_view_mul[2];
+ float NDC_to_view_add[2];
+
+ float pad[2];
+ float half_screen_pixel_size_x025[2];
+
+ float radius;
+ float intensity;
+ float shadow_power;
+ float shadow_clamp;
+
+ float fade_out_mul;
+ float fade_out_add;
+ float horizon_angle_threshold;
+ float inv_radius_near_limit;
+
+ uint32_t is_orthogonal;
+ float neg_inv_radius;
+ float load_counter_avg_div;
+ float adaptive_sample_limit;
+
+ int32_t pass_coord_offset[2];
+ float pass_uv_offset[2];
+ };
+
+ struct SSAOImportanceMapPushConstant {
+ float half_screen_pixel_size[2];
+ float intensity;
+ float power;
+ };
+
+ struct SSAOBlurPushConstant {
+ float edge_sharpness;
+ float pad;
+ float half_screen_pixel_size[2];
+ };
+
+ struct SSAOInterleavePushConstant {
+ float inv_sharpness;
+ uint32_t size_modifier;
+ float pixel_size[2];
+ };
+
+ struct SSAO {
+ SSAOGatherPushConstant gather_push_constant;
+ SsaoShaderRD gather_shader;
+ RID gather_shader_version;
+
+ SSAOImportanceMapPushConstant importance_map_push_constant;
+ SsaoImportanceMapShaderRD importance_map_shader;
+ RID importance_map_shader_version;
+ RID importance_map_load_counter;
+ RID counter_uniform_set;
+
+ SSAOBlurPushConstant blur_push_constant;
+ SsaoBlurShaderRD blur_shader;
+ RID blur_shader_version;
+
+ SSAOInterleavePushConstant interleave_push_constant;
+ SsaoInterleaveShaderRD interleave_shader;
+ RID interleave_shader_version;
+
+ RID pipelines[SSAO_MAX];
+ } ssao;
+
+ void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
+
+ /* Screen Space Reflection */
+
+ enum SSRShaderSpecializations {
+ SSR_MULTIVIEW = 1 << 0,
+ SSR_VARIATIONS = 2,
+ };
+
+ struct ScreenSpaceReflectionSceneData {
+ float projection[2][16];
+ float inv_projection[2][16];
+ float eye_offset[2][4];
+ };
+
+ // SSR Scale
+
+ struct ScreenSpaceReflectionScalePushConstant {
+ int32_t screen_size[2];
+ float camera_z_near;
+ float camera_z_far;
+
+ uint32_t orthogonal;
+ uint32_t filter;
+ uint32_t view_index;
+ uint32_t pad1;
+ };
+
+ struct ScreenSpaceReflectionScale {
+ ScreenSpaceReflectionScaleShaderRD shader;
+ RID shader_version;
+ RID pipelines[SSR_VARIATIONS];
+ } ssr_scale;
+
+ // SSR main
+
+ enum ScreenSpaceReflectionMode {
+ SCREEN_SPACE_REFLECTION_NORMAL,
+ SCREEN_SPACE_REFLECTION_ROUGH,
+ SCREEN_SPACE_REFLECTION_MAX,
+ };
+
+ struct ScreenSpaceReflectionPushConstant {
+ float proj_info[4]; // 16 - 16
+
+ int32_t screen_size[2]; // 8 - 24
+ float camera_z_near; // 4 - 28
+ float camera_z_far; // 4 - 32
+
+ int32_t num_steps; // 4 - 36
+ float depth_tolerance; // 4 - 40
+ float distance_fade; // 4 - 44
+ float curve_fade_in; // 4 - 48
+
+ uint32_t orthogonal; // 4 - 52
+ float filter_mipmap_levels; // 4 - 56
+ uint32_t use_half_res; // 4 - 60
+ uint8_t metallic_mask[4]; // 4 - 64
+
+ uint32_t view_index; // 4 - 68
+ uint32_t pad[3]; // 12 - 80
+
+ // float projection[16]; // this is in our ScreenSpaceReflectionSceneData now
+ };
+
+ struct ScreenSpaceReflection {
+ ScreenSpaceReflectionShaderRD shader;
+ RID shader_version;
+ RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_MAX];
+
+ RID ubo;
+ } ssr;
+
+ // SSR Filter
+
+ struct ScreenSpaceReflectionFilterPushConstant {
+ float proj_info[4]; // 16 - 16
+
+ uint32_t orthogonal; // 4 - 20
+ float edge_tolerance; // 4 - 24
+ int32_t increment; // 4 - 28
+ uint32_t view_index; // 4 - 32
+
+ int32_t screen_size[2]; // 8 - 40
+ uint32_t vertical; // 4 - 44
+ uint32_t steps; // 4 - 48
+ };
+
+ enum SSRReflectionMode {
+ SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL,
+ SCREEN_SPACE_REFLECTION_FILTER_VERTICAL,
+ SCREEN_SPACE_REFLECTION_FILTER_MAX,
+ };
+
+ struct ScreenSpaceReflectionFilter {
+ ScreenSpaceReflectionFilterShaderRD shader;
+ RID shader_version;
+ RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX];
+ } ssr_filter;
+};
+
+} // namespace RendererRD
+
+#endif // SS_EFFECTS_RD_H
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h
index a90849dbeb..05db4a0cbe 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.h
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.h
@@ -149,4 +149,4 @@ public:
} // namespace RendererRD
-#endif // !TONE_MAPPER_RD_H
+#endif // TONE_MAPPER_RD_H
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
new file mode 100644
index 0000000000..68cfd43d90
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -0,0 +1,174 @@
+/*************************************************************************/
+/* vrs.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 "vrs.h"
+#include "../renderer_compositor_rd.h"
+#include "../storage_rd/texture_storage.h"
+#include "../uniform_set_cache_rd.h"
+#include "servers/xr_server.h"
+
+using namespace RendererRD;
+
+VRS::VRS() {
+ {
+ Vector<String> vrs_modes;
+ vrs_modes.push_back("\n"); // VRS_DEFAULT
+ vrs_modes.push_back("\n#define MULTIVIEW\n"); // VRS_MULTIVIEW
+
+ vrs_shader.shader.initialize(vrs_modes);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ vrs_shader.shader.set_variant_enabled(VRS_MULTIVIEW, false);
+ }
+
+ vrs_shader.shader_version = vrs_shader.shader.version_create();
+
+ //use additive
+
+ for (int i = 0; i < VRS_MAX; i++) {
+ if (vrs_shader.shader.is_variant_enabled(i)) {
+ vrs_shader.pipelines[i].setup(vrs_shader.shader.version_get_shader(vrs_shader.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ vrs_shader.pipelines[i].clear();
+ }
+ }
+ }
+}
+
+VRS::~VRS() {
+ vrs_shader.shader.version_free(vrs_shader.shader_version);
+}
+
+void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
+
+ RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>());
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ // RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) {
+ // TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm
+
+ // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
+ // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
+ // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
+ // of the VRS buffer to supply.
+ Size2i texel_size = Size2i(16, 16);
+
+ RD::TextureFormat tf;
+ if (p_view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } else {
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ }
+ tf.format = RD::DATA_FORMAT_R8_UINT;
+ tf.width = p_base_width / texel_size.x;
+ if (p_base_width % texel_size.x != 0) {
+ tf.width++;
+ }
+ tf.height = p_base_height / texel_size.y;
+ if (p_base_height % texel_size.y != 0) {
+ tf.height++;
+ }
+ tf.array_layers = p_view_count; // create a layer for every view
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.samples = RD::TEXTURE_SAMPLES_1;
+
+ p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ // by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control
+ Vector<RID> fb;
+ fb.push_back(p_vrs_texture);
+
+ RD::FramebufferPass pass;
+ pass.color_attachments.push_back(0);
+
+ Vector<RD::FramebufferPass> passes;
+ passes.push_back(pass);
+
+ p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count);
+}
+
+void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
+ RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
+
+ if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
+ RD::get_singleton()->draw_command_begin_label("VRS Setup");
+
+ // TODO figure out if image has changed since it was last copied so we can save some resources..
+
+ if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) {
+ RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target);
+ if (vrs_texture.is_valid()) {
+ RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture);
+ int layers = texture_storage->texture_get_layers(vrs_texture);
+ if (rd_texture.is_valid()) {
+ // Copy into our density buffer
+ copy_vrs(rd_texture, p_vrs_fb, layers > 1);
+ }
+ }
+ } else if (vrs_mode == RS::VIEWPORT_VRS_XR) {
+ Ref<XRInterface> interface = XRServer::get_singleton()->get_primary_interface();
+ if (interface.is_valid()) {
+ RID vrs_texture = interface->get_vrs_texture();
+ if (vrs_texture.is_valid()) {
+ RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture);
+ int layers = texture_storage->texture_get_layers(vrs_texture);
+
+ if (rd_texture.is_valid()) {
+ // Copy into our density buffer
+ copy_vrs(rd_texture, p_vrs_fb, layers > 1);
+ }
+ }
+ }
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+}
diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h
new file mode 100644
index 0000000000..dd15df615e
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/vrs.h
@@ -0,0 +1,75 @@
+/*************************************************************************/
+/* vrs.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 VRS_RD_H
+#define VRS_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/vrs.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class VRS {
+private:
+ enum VRSMode {
+ VRS_DEFAULT,
+ VRS_MULTIVIEW,
+ VRS_MAX,
+ };
+
+ /* we have no push constant here (yet)
+ struct VRSPushConstant {
+
+ };
+ */
+
+ struct VRSShader {
+ // VRSPushConstant push_constant;
+ VrsShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[VRS_MAX];
+ } vrs_shader;
+
+public:
+ VRS();
+ ~VRS();
+
+ void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false);
+
+ void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb);
+ void update_vrs_texture(RID p_vrs_fb, RID p_render_target);
+};
+
+} // namespace RendererRD
+
+#endif // VRS_RD_H
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index d45ddbc392..8d59b24f3f 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -41,14 +41,6 @@ bool EffectsRD::get_prefer_raster_effects() {
return prefer_raster_effects;
}
-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];
- }
- }
-}
-
RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
if (image_to_uniform_set_cache.has(p_image)) {
RID uniform_set = image_to_uniform_set_cache[p_image];
@@ -86,7 +78,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
u.append_id(p_texture);
uniforms.push_back(u);
// anything with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, specular_merge.shader.version_get_shader(specular_merge.shader_version, 0), 0);
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, 0), 0);
texture_to_uniform_set_cache[p_texture] = uniform_set;
@@ -116,105 +108,6 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m
return uniform_set;
}
-RID EffectsRD::_get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler) {
- TextureSamplerPair tsp;
- tsp.texture = p_texture;
- tsp.sampler = p_sampler;
-
- if (texture_sampler_to_compute_uniform_set_cache.has(tsp)) {
- RID uniform_set = texture_sampler_to_compute_uniform_set_cache[tsp];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(p_sampler);
- u.append_id(p_texture);
- uniforms.push_back(u);
- //any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0), 0);
-
- texture_sampler_to_compute_uniform_set_cache[tsp] = uniform_set;
-
- return uniform_set;
-}
-
-RID EffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) {
- TexturePair tp;
- tp.texture1 = p_texture1;
- tp.texture2 = p_texture2;
-
- if (texture_pair_to_compute_uniform_set_cache.has(tp)) {
- RID uniform_set = texture_pair_to_compute_uniform_set_cache[tp];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
- u.append_id(p_texture1);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
- u.append_id(p_texture2);
- uniforms.push_back(u);
- }
- //any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 1);
-
- texture_pair_to_compute_uniform_set_cache[tp] = uniform_set;
-
- return uniform_set;
-}
-
-RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_texture2) {
- TexturePair tp;
- tp.texture1 = p_texture1;
- tp.texture2 = p_texture2;
-
- if (image_pair_to_compute_uniform_set_cache.has(tp)) {
- RID uniform_set = image_pair_to_compute_uniform_set_cache[tp];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_texture1);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_texture2);
- uniforms.push_back(u);
- }
- //any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 3);
-
- image_pair_to_compute_uniform_set_cache[tp] = uniform_set;
-
- return uniform_set;
-}
-
void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) {
memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
@@ -281,126 +174,7 @@ void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- { //scale color and depth to half
- ssr_scale.push_constant.camera_z_far = p_camera.get_z_far();
- ssr_scale.push_constant.camera_z_near = p_camera.get_z_near();
- ssr_scale.push_constant.orthogonal = p_camera.is_orthogonal();
- ssr_scale.push_constant.filter = false; //enabling causes arctifacts
- ssr_scale.push_constant.screen_size[0] = p_screen_size.x;
- ssr_scale.push_constant.screen_size[1] = p_screen_size.y;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipeline);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal_roughness), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output_blur), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_scale_depth, p_scale_normal), 3);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_scale.push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
-
- {
- ssr.push_constant.camera_z_far = p_camera.get_z_far();
- ssr.push_constant.camera_z_near = p_camera.get_z_near();
- ssr.push_constant.orthogonal = p_camera.is_orthogonal();
- ssr.push_constant.screen_size[0] = p_screen_size.x;
- ssr.push_constant.screen_size[1] = p_screen_size.y;
- ssr.push_constant.curve_fade_in = p_fade_in;
- ssr.push_constant.distance_fade = p_fade_out;
- ssr.push_constant.num_steps = p_max_steps;
- ssr.push_constant.depth_tolerance = p_tolerance;
- ssr.push_constant.use_half_res = true;
- ssr.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]);
- ssr.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]);
- ssr.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0];
- ssr.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1];
- ssr.push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255);
- ssr.push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255);
- ssr.push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255);
- ssr.push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255);
- store_camera(p_camera, ssr.push_constant.projection);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[(p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL]);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr.push_constant, sizeof(ScreenSpaceReflectionPushConstant));
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_scale_depth), 0);
-
- if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 2);
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
- }
-
- if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
- //blur
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- ssr_filter.push_constant.orthogonal = p_camera.is_orthogonal();
- ssr_filter.push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0));
- ssr_filter.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]);
- ssr_filter.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]);
- ssr_filter.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0];
- ssr_filter.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1];
- ssr_filter.push_constant.vertical = 0;
- if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
- ssr_filter.push_constant.steps = p_max_steps / 3;
- ssr_filter.push_constant.increment = 3;
- } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {
- ssr_filter.push_constant.steps = p_max_steps / 2;
- ssr_filter.push_constant.increment = 2;
- } else {
- ssr_filter.push_constant.steps = p_max_steps;
- ssr_filter.push_constant.increment = 1;
- }
-
- ssr_filter.push_constant.screen_size[0] = p_screen_size.width;
- ssr_filter.push_constant.screen_size[1] = p_screen_size.height;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_VERTICAL]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3);
-
- ssr_filter.push_constant.vertical = 1;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
+void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
@@ -443,36 +217,6 @@ void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_dept
}
}
-void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) {
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, Vector<Color>());
-
- if (p_reflection.is_valid()) {
- if (p_base.is_valid()) {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2);
- } else {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- }
-
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_reflection), 1);
-
- } else {
- if (p_base.is_valid()) {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2);
- } else {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- }
-
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0);
- }
-
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
@@ -546,674 +290,6 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_
}
}
-void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) {
- // Downsample and deinterleave the depth buffer for SSAO and SSIL
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- int downsample_pipeline = SS_EFFECTS_DOWNSAMPLE;
- bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
-
- if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_HALF;
- } else if (use_mips) {
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
- }
-
- bool use_half_size = false;
- bool use_full_mips = false;
-
- if (p_ssao_half_size && p_ssil_half_size) {
- downsample_pipeline++;
- use_half_size = true;
- } else if (p_ssao_half_size != p_ssil_half_size) {
- if (use_mips) {
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
- use_full_mips = true;
- } else {
- // Only need the first two mipmaps, but the cost to generate the next two is trivial
- // TODO investigate the benefit of a shader version to generate only 2 mips
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
- use_mips = true;
- }
- }
-
- int depth_index = use_half_size ? 1 : 0;
-
- RD::get_singleton()->draw_command_begin_label("Downsample Depth");
- if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_depth_mipmaps[depth_index + 1]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_depth_mipmaps[depth_index + 2]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.append_id(p_depth_mipmaps[depth_index + 3]);
- uniforms.push_back(u);
- }
- if (use_full_mips) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- u.append_id(p_depth_mipmaps[4]);
- uniforms.push_back(u);
- }
- ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
- }
-
- float depth_linearize_mul = -p_projection.matrix[3][2];
- float depth_linearize_add = p_projection.matrix[2][2];
- if (depth_linearize_mul * depth_linearize_add < 0) {
- depth_linearize_add = -depth_linearize_add;
- }
-
- ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
- ss_effects.downsample_push_constant.z_near = depth_linearize_mul;
- ss_effects.downsample_push_constant.z_far = depth_linearize_add;
- if (ss_effects.downsample_push_constant.orthogonal) {
- ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
- ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
- }
- ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x;
- ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y;
- ss_effects.downsample_push_constant.radius_sq = 1.0;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_pipeline]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[depth_index + 0]), 1);
- if (use_mips) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2);
- }
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
-
- Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1)));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label();
-
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
-
- ss_effects.used_full_mips_last_frame = use_full_mips;
- ss_effects.used_half_size_last_frame = use_half_size;
-}
-
-void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
- }
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- ssao.gather_push_constant.pass_coord_offset[0] = i % 2;
- ssao.gather_push_constant.pass_coord_offset[1] = i / 2;
- ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
- ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
- ssao.gather_push_constant.pass = i;
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 2);
- RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
-
- Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
-
- RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
- }
- RD::get_singleton()->compute_list_add_barrier(p_compute_list);
-}
-
-void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
- /* FIRST PASS */
-
- RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");
- /* SECOND PASS */
- // Sample SSAO
- {
- RD::get_singleton()->draw_command_begin_label("Gather Samples");
- ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
- ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
-
- ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
- float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
- ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
- ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
- ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
- ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
- ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
-
- ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
- ssao.gather_push_constant.radius = p_settings.radius;
- float radius_near_limit = (p_settings.radius * 1.2f);
- if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) {
- radius_near_limit *= 1.50f;
-
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- ssao.gather_push_constant.radius *= 0.8f;
- }
- }
- radius_near_limit /= tan_half_fov_y;
- ssao.gather_push_constant.intensity = p_settings.intensity;
- ssao.gather_push_constant.shadow_power = p_settings.power;
- ssao.gather_push_constant.shadow_clamp = 0.98;
- ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
- ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
- ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;
- ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
- ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
-
- ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255);
- ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
-
- ssao.gather_push_constant.detail_intensity = p_settings.detail;
- ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
- ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_sampler);
- u.append_id(p_depth_mipmaps_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_normal_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(ss_effects.gather_constants_buffer);
- uniforms.push_back(u);
- }
- r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
- }
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_ao_pong);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(default_sampler);
- u.append_id(p_importance_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(ssao.importance_map_load_counter);
- uniforms.push_back(u);
- }
- r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
- }
-
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) {
- RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
- ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- ssao.importance_map_push_constant.intensity = p_settings.intensity;
- ssao.importance_map_push_constant.power = p_settings.power;
- //base pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
- gather_ssao(compute_list, p_ao_pong_slices, p_settings, true, r_gather_uniform_set, RID());
- //generate importance map
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- //process importance map A
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- //process Importance Map B
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
- RD::get_singleton()->draw_command_end_label(); // Importance Map
- } else {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
- }
-
- gather_ssao(compute_list, p_ao_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set);
- RD::get_singleton()->draw_command_end_label(); // Gather SSAO
- }
-
- // /* THIRD PASS */
- // // Blur
- //
- {
- RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
- ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
- ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
-
- int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
-
- for (int pass = 0; pass < blur_passes; pass++) {
- int blur_pipeline = SSAO_BLUR_PASS;
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
- blur_pipeline = SSAO_BLUR_PASS_SMART;
- if (pass < blur_passes - 2) {
- blur_pipeline = SSAO_BLUR_PASS_WIDE;
- } else {
- blur_pipeline = SSAO_BLUR_PASS_SMART;
- }
- }
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
- if (pass % 2 == 0) {
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_slices[i], ss_effects.mirror_sampler), 0);
- }
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_pong_slices[i]), 1);
- } else {
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_pong_slices[i], ss_effects.mirror_sampler), 0);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 1);
- }
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
-
- Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
- }
-
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- }
- RD::get_singleton()->draw_command_end_label(); // Blur
- }
-
- /* FOURTH PASS */
- // Interleave buffers
- // back to full size
- {
- RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
- ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
- ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
- ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
- ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
-
- int interleave_pipeline = SSAO_INTERLEAVE_HALF;
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) {
- interleave_pipeline = SSAO_INTERLEAVE;
- } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
- interleave_pipeline = SSAO_INTERLEAVE_SMART;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 0);
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 1);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label(); // Interleave
- }
- RD::get_singleton()->draw_command_end_label(); //SSAO
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer
-
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
-}
-
-void EffectsRD::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- ssil.gather_push_constant.pass_coord_offset[0] = i % 2;
- ssil.gather_push_constant.pass_coord_offset[1] = i / 2;
- ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
- ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
- ssil.gather_push_constant.pass = i;
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_compute_uniform_set_from_image_pair(p_ssil_slices[i], p_edges_slices[i]), 2);
- RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
-
- Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
-
- RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
- }
- RD::get_singleton()->compute_list_add_barrier(p_compute_list);
-}
-
-void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ssil, const Vector<RID> p_ssil_slices, RID p_ssil_pong, const Vector<RID> p_ssil_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set) {
- RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");
- //Store projection info before starting the compute list
- SSILProjectionUniforms projection_uniforms;
- store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
-
- RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);
-
- memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- {
- RD::get_singleton()->draw_command_begin_label("Gather Samples");
- ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
- ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
-
- ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
- float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
- ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
- ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
- ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
- ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
- ssil.gather_push_constant.z_near = p_projection.get_z_near();
- ssil.gather_push_constant.z_far = p_projection.get_z_far();
- ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
-
- ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
- ssil.gather_push_constant.radius = p_settings.radius;
- float radius_near_limit = (p_settings.radius * 1.2f);
- if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) {
- radius_near_limit *= 1.50f;
-
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- ssil.gather_push_constant.radius *= 0.8f;
- }
- }
- radius_near_limit /= tan_half_fov_y;
- ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI;
- ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
- ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
- ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
- ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
- ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
-
- ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255);
- ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
-
- ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
- ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_mipmap_sampler);
- u.append_id(p_diffuse);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 1;
- u.append_id(ssil.projection_uniform_buffer);
- uniforms.push_back(u);
- }
- r_projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
- }
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_sampler);
- u.append_id(p_depth_mipmaps_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_normal_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(ss_effects.gather_constants_buffer);
- uniforms.push_back(u);
- }
- r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
- }
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_ssil_pong);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(default_sampler);
- u.append_id(p_importance_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(ssil.importance_map_load_counter);
- uniforms.push_back(u);
- }
- r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
- }
-
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) {
- RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
- ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI;
- //base pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
- gather_ssil(compute_list, p_ssil_pong_slices, p_edges_slices, p_settings, true, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set);
- //generate importance map
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- // process Importance Map A
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- // process Importance Map B
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->draw_command_end_label(); // Importance Map
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);
- } else {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
- }
-
- gather_ssil(compute_list, p_ssil_slices, p_edges_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set);
- RD::get_singleton()->draw_command_end_label(); //Gather
- }
-
- {
- RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
- ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
- ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
-
- int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
-
- for (int pass = 0; pass < blur_passes; pass++) {
- int blur_pipeline = SSIL_BLUR_PASS;
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
- blur_pipeline = SSIL_BLUR_PASS_SMART;
- if (pass < blur_passes - 2) {
- blur_pipeline = SSIL_BLUR_PASS_WIDE;
- }
- }
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
- if (pass % 2 == 0) {
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_slices[i], ss_effects.mirror_sampler), 0);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_pong_slices[i]), 1);
- } else {
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_pong_slices[i], ss_effects.mirror_sampler), 0);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_slices[i]), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges_slices[i]), 2);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
-
- int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1));
- int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- }
- }
-
- RD::get_singleton()->draw_command_end_label(); // Blur
- }
-
- {
- RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
- ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
- ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
- ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
- ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
-
- int interleave_pipeline = SSIL_INTERLEAVE_HALF;
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) {
- interleave_pipeline = SSIL_INTERLEAVE;
- } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
- interleave_pipeline = SSIL_INTERLEAVE_SMART;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination), 0);
-
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges), 2);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label(); // Interleave
- }
-
- RD::get_singleton()->draw_command_end_label(); // SSIL
-
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
-
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
-}
-
void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) {
roughness_limiter.push_constant.screen_size[0] = p_size.x;
roughness_limiter.push_constant.screen_size[1] = p_size.y;
@@ -1304,12 +380,12 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
{
Vector<String> FSR_upscale_modes;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
// MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
#else
// Everyone else can use normal mode when available.
- if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) {
+ if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
} else {
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
@@ -1358,154 +434,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
if (!prefer_raster_effects) {
- {
- // Initialize depth buffer for screen space effects
- Vector<String> downsampler_modes;
- downsampler_modes.push_back("\n");
- downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");
- downsampler_modes.push_back("\n#define GENERATE_MIPS\n");
- downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");
- downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");
- downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");
- downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");
-
- ss_effects.downsample_shader.initialize(downsampler_modes);
-
- ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();
-
- for (int i = 0; i < SS_EFFECTS_MAX; i++) {
- ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
- }
-
- ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));
- SSEffectsGatherConstants gather_constants;
-
- const int sub_pass_count = 5;
- for (int pass = 0; pass < 4; pass++) {
- for (int subPass = 0; subPass < sub_pass_count; subPass++) {
- int a = pass;
- int b = subPass;
-
- int spmap[5]{ 0, 1, 4, 3, 2 };
- b = spmap[subPass];
-
- float ca, sa;
- float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f;
-
- ca = Math::cos(angle0);
- sa = Math::sin(angle0);
-
- float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f;
-
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca;
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa;
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa;
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca;
- }
- }
-
- RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);
- }
-
- {
- // Initialize ssao
-
- RD::SamplerState sampler;
- sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.max_lod = 4;
-
- ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
-
- uint32_t pipeline = 0;
- {
- Vector<String> ssao_modes;
-
- ssao_modes.push_back("\n");
- ssao_modes.push_back("\n#define SSAO_BASE\n");
- ssao_modes.push_back("\n#define ADAPTIVE\n");
-
- ssao.gather_shader.initialize(ssao_modes);
-
- ssao.gather_shader_version = ssao.gather_shader.version_create();
-
- for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
- pipeline++;
- }
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define GENERATE_MAP\n");
- ssao_modes.push_back("\n#define PROCESS_MAPA\n");
- ssao_modes.push_back("\n#define PROCESS_MAPB\n");
-
- ssao.importance_map_shader.initialize(ssao_modes);
-
- ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
-
- for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
-
- pipeline++;
- }
- ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
- RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(ssao.importance_map_load_counter);
- uniforms.push_back(u);
- }
- ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
- RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define MODE_NON_SMART\n");
- ssao_modes.push_back("\n#define MODE_SMART\n");
- ssao_modes.push_back("\n#define MODE_WIDE\n");
-
- ssao.blur_shader.initialize(ssao_modes);
-
- ssao.blur_shader_version = ssao.blur_shader.version_create();
-
- for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
-
- pipeline++;
- }
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define MODE_NON_SMART\n");
- ssao_modes.push_back("\n#define MODE_SMART\n");
- ssao_modes.push_back("\n#define MODE_HALF\n");
-
- ssao.interleave_shader.initialize(ssao_modes);
-
- ssao.interleave_shader_version = ssao.interleave_shader.version_create();
- for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
- RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
- pipeline++;
- }
- }
-
- ERR_FAIL_COND(pipeline != SSAO_MAX);
- }
- }
-
- if (!prefer_raster_effects) {
// Initialize roughness limiter
Vector<String> shader_modes;
shader_modes.push_back("");
@@ -1518,81 +446,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
if (!prefer_raster_effects) {
- Vector<String> specular_modes;
- specular_modes.push_back("\n#define MODE_MERGE\n");
- specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n");
- specular_modes.push_back("\n");
- specular_modes.push_back("\n#define MODE_SSR\n");
-
- specular_merge.shader.initialize(specular_modes);
-
- specular_merge.shader_version = specular_merge.shader.version_create();
-
- //use additive
-
- RD::PipelineColorBlendState::Attachment ba;
- ba.enable_blend = true;
- ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.color_blend_op = RD::BLEND_OP_ADD;
- ba.alpha_blend_op = RD::BLEND_OP_ADD;
-
- RD::PipelineColorBlendState blend_additive;
- blend_additive.attachments.push_back(ba);
-
- for (int i = 0; i < SPECULAR_MERGE_MAX; i++) {
- RD::PipelineColorBlendState blend_state;
- if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR) {
- blend_state = blend_additive;
- } else {
- blend_state = RD::PipelineColorBlendState::create_disabled();
- }
- specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
- }
- }
-
- if (!prefer_raster_effects) {
- {
- Vector<String> ssr_modes;
- ssr_modes.push_back("\n");
- ssr_modes.push_back("\n#define MODE_ROUGH\n");
-
- ssr.shader.initialize(ssr_modes);
-
- ssr.shader_version = ssr.shader.version_create();
-
- for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {
- ssr.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i));
- }
- }
-
- {
- Vector<String> ssr_filter_modes;
- ssr_filter_modes.push_back("\n");
- ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n");
-
- ssr_filter.shader.initialize(ssr_filter_modes);
-
- ssr_filter.shader_version = ssr_filter.shader.version_create();
-
- for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
- ssr_filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i));
- }
- }
-
- {
- Vector<String> ssr_scale_modes;
- ssr_scale_modes.push_back("\n");
-
- ssr_scale.shader.initialize(ssr_scale_modes);
-
- ssr_scale.shader_version = ssr_scale.shader.version_create();
-
- ssr_scale.pipeline = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0));
- }
-
{
Vector<String> sss_modes;
sss_modes.push_back("\n#define USE_11_SAMPLES\n");
@@ -1607,79 +460,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
}
}
-
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n");
- ssil_modes.push_back("\n#define SSIL_BASE\n");
- ssil_modes.push_back("\n#define ADAPTIVE\n");
-
- ssil.gather_shader.initialize(ssil_modes);
-
- ssil.gather_shader_version = ssil.gather_shader.version_create();
-
- for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
- }
- ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));
- }
-
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n#define GENERATE_MAP\n");
- ssil_modes.push_back("\n#define PROCESS_MAPA\n");
- ssil_modes.push_back("\n#define PROCESS_MAPB\n");
-
- ssil.importance_map_shader.initialize(ssil_modes);
-
- ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();
-
- for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
- }
- ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
- RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(ssil.importance_map_load_counter);
- uniforms.push_back(u);
- }
- ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);
- RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");
- }
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n#define MODE_NON_SMART\n");
- ssil_modes.push_back("\n#define MODE_SMART\n");
- ssil_modes.push_back("\n#define MODE_WIDE\n");
-
- ssil.blur_shader.initialize(ssil_modes);
-
- ssil.blur_shader_version = ssil.blur_shader.version_create();
- for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
- }
- }
-
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n#define MODE_NON_SMART\n");
- ssil_modes.push_back("\n#define MODE_SMART\n");
- ssil_modes.push_back("\n#define MODE_HALF\n");
-
- ssil.interleave_shader.initialize(ssil_modes);
-
- ssil.interleave_shader_version = ssil.interleave_shader.version_create();
- for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
- }
- }
}
{
@@ -1751,27 +531,8 @@ EffectsRD::~EffectsRD() {
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
}
if (!prefer_raster_effects) {
- specular_merge.shader.version_free(specular_merge.shader_version);
- ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
- ssao.blur_shader.version_free(ssao.blur_shader_version);
- ssao.gather_shader.version_free(ssao.gather_shader_version);
- ssao.interleave_shader.version_free(ssao.interleave_shader_version);
- ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);
- ssil.blur_shader.version_free(ssil.blur_shader_version);
- ssil.gather_shader.version_free(ssil.gather_shader_version);
- ssil.interleave_shader.version_free(ssil.interleave_shader_version);
- ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
- ssr.shader.version_free(ssr.shader_version);
- ssr_filter.shader.version_free(ssr_filter.shader_version);
- ssr_scale.shader.version_free(ssr_scale.shader_version);
sss.shader.version_free(sss.shader_version);
-
- RD::get_singleton()->free(ss_effects.mirror_sampler);
- RD::get_singleton()->free(ss_effects.gather_constants_buffer);
- RD::get_singleton()->free(ssao.importance_map_load_counter);
- RD::get_singleton()->free(ssil.importance_map_load_counter);
- RD::get_singleton()->free(ssil.projection_uniform_buffer);
}
sort.shader.version_free(sort.shader_version);
}
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 76627a8d7d..94cd26fae9 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -31,26 +31,13 @@
#ifndef EFFECTS_RD_H
#define EFFECTS_RD_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/specular_merge.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_blur.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_interleave.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil_blur.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil_interleave.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
@@ -142,231 +129,6 @@ private:
PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX];
} luminance_reduce_raster;
- struct SSEffectsDownsamplePushConstant {
- float pixel_size[2];
- float z_far;
- float z_near;
- uint32_t orthogonal;
- float radius_sq;
- uint32_t pad[2];
- };
-
- enum SSEffectsMode {
- SS_EFFECTS_DOWNSAMPLE,
- SS_EFFECTS_DOWNSAMPLE_HALF_RES,
- SS_EFFECTS_DOWNSAMPLE_MIPMAP,
- SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES,
- SS_EFFECTS_DOWNSAMPLE_HALF,
- SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF,
- SS_EFFECTS_DOWNSAMPLE_FULL_MIPS,
- SS_EFFECTS_MAX
- };
-
- struct SSEffectsGatherConstants {
- float rotation_matrices[80]; //5 vec4s * 4
- };
-
- struct SSEffects {
- SSEffectsDownsamplePushConstant downsample_push_constant;
- SsEffectsDownsampleShaderRD downsample_shader;
- RID downsample_shader_version;
- RID downsample_uniform_set;
- bool used_half_size_last_frame = false;
- bool used_mips_last_frame = false;
- bool used_full_mips_last_frame = false;
-
- RID gather_constants_buffer;
-
- RID mirror_sampler;
-
- RID pipelines[SS_EFFECTS_MAX];
- } ss_effects;
-
- enum SSAOMode {
- SSAO_GATHER,
- SSAO_GATHER_BASE,
- SSAO_GATHER_ADAPTIVE,
- SSAO_GENERATE_IMPORTANCE_MAP,
- SSAO_PROCESS_IMPORTANCE_MAPA,
- SSAO_PROCESS_IMPORTANCE_MAPB,
- SSAO_BLUR_PASS,
- SSAO_BLUR_PASS_SMART,
- SSAO_BLUR_PASS_WIDE,
- SSAO_INTERLEAVE,
- SSAO_INTERLEAVE_SMART,
- SSAO_INTERLEAVE_HALF,
- SSAO_MAX
- };
-
- struct SSAOGatherPushConstant {
- int32_t screen_size[2];
- int pass;
- int quality;
-
- float half_screen_pixel_size[2];
- int size_multiplier;
- float detail_intensity;
-
- float NDC_to_view_mul[2];
- float NDC_to_view_add[2];
-
- float pad[2];
- float half_screen_pixel_size_x025[2];
-
- float radius;
- float intensity;
- float shadow_power;
- float shadow_clamp;
-
- float fade_out_mul;
- float fade_out_add;
- float horizon_angle_threshold;
- float inv_radius_near_limit;
-
- uint32_t is_orthogonal;
- float neg_inv_radius;
- float load_counter_avg_div;
- float adaptive_sample_limit;
-
- int32_t pass_coord_offset[2];
- float pass_uv_offset[2];
- };
-
- struct SSAOImportanceMapPushConstant {
- float half_screen_pixel_size[2];
- float intensity;
- float power;
- };
-
- struct SSAOBlurPushConstant {
- float edge_sharpness;
- float pad;
- float half_screen_pixel_size[2];
- };
-
- struct SSAOInterleavePushConstant {
- float inv_sharpness;
- uint32_t size_modifier;
- float pixel_size[2];
- };
-
- struct SSAO {
- SSAOGatherPushConstant gather_push_constant;
- SsaoShaderRD gather_shader;
- RID gather_shader_version;
-
- SSAOImportanceMapPushConstant importance_map_push_constant;
- SsaoImportanceMapShaderRD importance_map_shader;
- RID importance_map_shader_version;
- RID importance_map_load_counter;
- RID counter_uniform_set;
-
- SSAOBlurPushConstant blur_push_constant;
- SsaoBlurShaderRD blur_shader;
- RID blur_shader_version;
-
- SSAOInterleavePushConstant interleave_push_constant;
- SsaoInterleaveShaderRD interleave_shader;
- RID interleave_shader_version;
-
- RID pipelines[SSAO_MAX];
- } ssao;
-
- enum SSILMode {
- SSIL_GATHER,
- SSIL_GATHER_BASE,
- SSIL_GATHER_ADAPTIVE,
- SSIL_GENERATE_IMPORTANCE_MAP,
- SSIL_PROCESS_IMPORTANCE_MAPA,
- SSIL_PROCESS_IMPORTANCE_MAPB,
- SSIL_BLUR_PASS,
- SSIL_BLUR_PASS_SMART,
- SSIL_BLUR_PASS_WIDE,
- SSIL_INTERLEAVE,
- SSIL_INTERLEAVE_SMART,
- SSIL_INTERLEAVE_HALF,
- SSIL_MAX
- };
-
- struct SSILGatherPushConstant {
- int32_t screen_size[2];
- int pass;
- int quality;
-
- float half_screen_pixel_size[2];
- float half_screen_pixel_size_x025[2];
-
- float NDC_to_view_mul[2];
- float NDC_to_view_add[2];
-
- float pad2[2];
- float z_near;
- float z_far;
-
- float radius;
- float intensity;
- int size_multiplier;
- int pad;
-
- float fade_out_mul;
- float fade_out_add;
- float normal_rejection_amount;
- float inv_radius_near_limit;
-
- uint32_t is_orthogonal;
- float neg_inv_radius;
- float load_counter_avg_div;
- float adaptive_sample_limit;
-
- int32_t pass_coord_offset[2];
- float pass_uv_offset[2];
- };
-
- struct SSILImportanceMapPushConstant {
- float half_screen_pixel_size[2];
- float intensity;
- float pad;
- };
-
- struct SSILBlurPushConstant {
- float edge_sharpness;
- float pad;
- float half_screen_pixel_size[2];
- };
-
- struct SSILInterleavePushConstant {
- float inv_sharpness;
- uint32_t size_modifier;
- float pixel_size[2];
- };
-
- struct SSILProjectionUniforms {
- float inv_last_frame_projection_matrix[16];
- };
-
- struct SSIL {
- SSILGatherPushConstant gather_push_constant;
- SsilShaderRD gather_shader;
- RID gather_shader_version;
- RID projection_uniform_buffer;
-
- SSILImportanceMapPushConstant importance_map_push_constant;
- SsilImportanceMapShaderRD importance_map_shader;
- RID importance_map_shader_version;
- RID importance_map_load_counter;
- RID counter_uniform_set;
-
- SSILBlurPushConstant blur_push_constant;
- SsilBlurShaderRD blur_shader;
- RID blur_shader_version;
-
- SSILInterleavePushConstant interleave_push_constant;
- SsilInterleaveShaderRD interleave_shader;
- RID interleave_shader_version;
-
- RID pipelines[SSIL_MAX];
- } ssil;
-
struct RoughnessLimiterPushConstant {
int32_t screen_size[2];
float curve;
@@ -381,101 +143,6 @@ private:
} roughness_limiter;
- enum SpecularMergeMode {
- SPECULAR_MERGE_ADD,
- SPECULAR_MERGE_SSR,
- SPECULAR_MERGE_ADDITIVE_ADD,
- SPECULAR_MERGE_ADDITIVE_SSR,
- SPECULAR_MERGE_MAX
- };
-
- /* Specular merge must be done using raster, rather than compute
- * because it must continue the existing color buffer
- */
-
- struct SpecularMerge {
- SpecularMergeShaderRD shader;
- RID shader_version;
- PipelineCacheRD pipelines[SPECULAR_MERGE_MAX];
-
- } specular_merge;
-
- enum ScreenSpaceReflectionMode {
- SCREEN_SPACE_REFLECTION_NORMAL,
- SCREEN_SPACE_REFLECTION_ROUGH,
- SCREEN_SPACE_REFLECTION_MAX,
- };
-
- struct ScreenSpaceReflectionPushConstant {
- float proj_info[4];
-
- int32_t screen_size[2];
- float camera_z_near;
- float camera_z_far;
-
- int32_t num_steps;
- float depth_tolerance;
- float distance_fade;
- float curve_fade_in;
-
- uint32_t orthogonal;
- float filter_mipmap_levels;
- uint32_t use_half_res;
- uint8_t metallic_mask[4];
-
- float projection[16];
- };
-
- struct ScreenSpaceReflection {
- ScreenSpaceReflectionPushConstant push_constant;
- ScreenSpaceReflectionShaderRD shader;
- RID shader_version;
- RID pipelines[SCREEN_SPACE_REFLECTION_MAX];
-
- } ssr;
-
- struct ScreenSpaceReflectionFilterPushConstant {
- float proj_info[4];
-
- uint32_t orthogonal;
- float edge_tolerance;
- int32_t increment;
- uint32_t pad;
-
- int32_t screen_size[2];
- uint32_t vertical;
- uint32_t steps;
- };
- enum {
- SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL,
- SCREEN_SPACE_REFLECTION_FILTER_VERTICAL,
- SCREEN_SPACE_REFLECTION_FILTER_MAX,
- };
-
- struct ScreenSpaceReflectionFilter {
- ScreenSpaceReflectionFilterPushConstant push_constant;
- ScreenSpaceReflectionFilterShaderRD shader;
- RID shader_version;
- RID pipelines[SCREEN_SPACE_REFLECTION_FILTER_MAX];
- } ssr_filter;
-
- struct ScreenSpaceReflectionScalePushConstant {
- int32_t screen_size[2];
- float camera_z_near;
- float camera_z_far;
-
- uint32_t orthogonal;
- uint32_t filter;
- uint32_t pad[2];
- };
-
- struct ScreenSpaceReflectionScale {
- ScreenSpaceReflectionScalePushConstant push_constant;
- ScreenSpaceReflectionScaleShaderRD shader;
- RID shader_version;
- RID pipeline;
- } ssr_scale;
-
struct SubSurfaceScatteringPushConstant {
int32_t screen_size[2];
float camera_z_far;
@@ -559,9 +226,6 @@ private:
RID _get_uniform_set_from_image(RID p_texture);
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
- RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler);
- RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
- RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
public:
bool get_prefer_raster_effects();
@@ -572,57 +236,9 @@ public:
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
- struct SSAOSettings {
- float radius = 1.0;
- float intensity = 2.0;
- float power = 1.5;
- float detail = 0.5;
- float horizon = 0.06;
- float sharpness = 0.98;
-
- RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM;
- bool half_size = false;
- float adaptive_target = 0.5;
- int blur_passes = 2;
- float fadeout_from = 50.0;
- float fadeout_to = 300.0;
-
- Size2i full_screen_size = Size2i();
- Size2i half_screen_size = Size2i();
- Size2i quarter_screen_size = Size2i();
- };
-
- struct SSILSettings {
- float radius = 1.0;
- float intensity = 2.0;
- float sharpness = 0.98;
- float normal_rejection = 1.0;
-
- RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM;
- bool half_size = true;
- float adaptive_target = 0.5;
- int blur_passes = 4;
- float fadeout_from = 50.0;
- float fadeout_to = 300.0;
-
- Size2i full_screen_size = Size2i();
- Size2i half_screen_size = Size2i();
- Size2i quarter_screen_size = Size2i();
- };
-
- void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection);
-
- void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
- void generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set);
-
- void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
- void screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set);
-
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
- void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
- void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
- void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
+ void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
void sort_buffer(RID p_uniform_set, int p_size);
@@ -630,4 +246,4 @@ public:
~EffectsRD();
};
-#endif // !RASTERIZER_EFFECTS_RD_H
+#endif // EFFECTS_RD_H
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
new file mode 100644
index 0000000000..58f4c855a4
--- /dev/null
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -0,0 +1,1205 @@
+/*************************************************************************/
+/* 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"
+
+#include "servers/rendering/renderer_rd/renderer_compositor_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"
+
+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;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Fog material
+
+bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ uniform_set_updated = true;
+
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
+}
+
+Fog::FogMaterialData::~FogMaterialData() {
+ free_parameters_uniform_set(uniform_set);
+}
+
+RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() {
+ FogShaderData *shader_data = memnew(FogShaderData);
+ return shader_data;
+}
+
+RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() {
+ return Fog::get_singleton()->_create_fog_shader_func();
+};
+
+RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) {
+ FogMaterialData *material_data = memnew(FogMaterialData);
+ material_data->shader_data = p_shader;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
+ return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// FOG VOLUMES INSTANCE
+
+RID Fog::fog_volume_instance_create(RID p_fog_volume) {
+ FogVolumeInstance fvi;
+ fvi.volume = p_fog_volume;
+ return fog_volume_instance_owner.make_rid(fvi);
+}
+
+void Fog::fog_instance_free(RID p_rid) {
+ fog_volume_instance_owner.free(p_rid);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Volumetric Fog Shader
+
+void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array) {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ {
+ // Initialize local fog shader
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("");
+ volumetric_fog.shader.initialize(volumetric_fog_modes);
+
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_material_funcs);
+ volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
+ }
+
+ {
+ ShaderCompiler::DefaultIdentifierActions actions;
+
+ actions.renames["TIME"] = "scene_params.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
+ actions.renames["WORLD_POSITION"] = "world.xyz";
+ actions.renames["OBJECT_POSITION"] = "params.position";
+ actions.renames["UVW"] = "uvw";
+ actions.renames["EXTENTS"] = "params.extents";
+ actions.renames["ALBEDO"] = "albedo";
+ actions.renames["DENSITY"] = "density";
+ actions.renames["EMISSION"] = "emission";
+ actions.renames["SDF"] = "sdf";
+
+ actions.usage_defines["SDF"] = "#define SDF_USED\n";
+ actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n";
+ actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n";
+ actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL;
+ actions.base_uniform_string = "material.";
+
+ actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+ actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
+ actions.global_buffer_array_variable = "global_variables.data";
+
+ volumetric_fog.compiler.initialize(actions);
+ }
+
+ {
+ // default material and shader for fog shader
+ volumetric_fog.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(volumetric_fog.default_shader);
+ material_storage->shader_set_code(volumetric_fog.default_shader, R"(
+// Default fog shader.
+
+shader_type fog;
+
+void fog() {
+DENSITY = 1.0;
+ALBEDO = vec3(1.0);
+}
+)");
+ volumetric_fog.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(volumetric_fog.default_material);
+ material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
+
+ FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG));
+ volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
+ volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ }
+ {
+ String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(p_max_directional_lights) + "\n";
+ defines += "\n#define MAX_SKY_LOD " + itos(p_roughness_layers - 1) + ".0\n";
+ if (p_is_using_radiance_cubemap_array) {
+ defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
+ }
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
+ volumetric_fog_modes.push_back("\n#define MODE_COPY\n");
+
+ volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines);
+ volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
+ for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
+ volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i));
+ }
+ volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
+ }
+}
+
+void Fog::free_fog_shader() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
+ RD::get_singleton()->free(volumetric_fog.volume_ubo);
+ RD::get_singleton()->free(volumetric_fog.params_ubo);
+ material_storage->shader_free(volumetric_fog.default_shader);
+ material_storage->material_free(volumetric_fog.default_material);
+}
+
+void Fog::FogShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
+void Fog::FogShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE;
+
+ uses_time = false;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+
+ actions.uniforms = &uniforms;
+
+ Fog *fog_singleton = Fog::get_singleton();
+
+ Error err = fog_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
+
+ if (version.is_null()) {
+ version = fog_singleton->volumetric_fog.shader.version_create();
+ }
+
+ fog_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
+ ERR_FAIL_COND(!fog_singleton->volumetric_fog.shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ pipeline = RD::get_singleton()->compute_pipeline_create(fog_singleton->volumetric_fog.shader.version_get_shader(version, 0));
+
+ valid = true;
+}
+
+void Fog::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = HashMap<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void Fog::FogShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
+ RBMap<int, StringName> order;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
+ } else {
+ order[E.value.order] = E.key;
+ }
+ }
+
+ String last_group;
+ for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
+ p_param_list->push_back(pi);
+ }
+}
+
+void Fog::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererMaterialStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool Fog::FogShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool Fog::FogShaderData::is_animated() const {
+ return false;
+}
+
+bool Fog::FogShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant Fog::FogShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode Fog::FogShaderData::get_native_source_code() const {
+ Fog *fog_singleton = Fog::get_singleton();
+
+ return fog_singleton->volumetric_fog.shader.version_get_native_source_code(version);
+}
+
+Fog::FogShaderData::~FogShaderData() {
+ Fog *fog_singleton = Fog::get_singleton();
+ ERR_FAIL_COND(!fog_singleton);
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ fog_singleton->volumetric_fog.shader.version_free(version);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Volumetric Fog
+
+Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) {
+ width = fog_size.x;
+ height = fog_size.y;
+ depth = fog_size.z;
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = fog_size.x;
+ tf.height = fog_size.y;
+ tf.depth = fog_size.z;
+ tf.texture_type = RD::TEXTURE_TYPE_3D;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+
+ light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(light_density_map, "Fog light-density map");
+
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+
+ prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(prev_light_density_map, "Fog previous light-density map");
+ RD::get_singleton()->texture_clear(prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(fog_map, "Fog map");
+
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ Vector<uint8_t> dm;
+ dm.resize(fog_size.x * fog_size.y * fog_size.z * 4);
+ dm.fill(0);
+
+ density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(density_map, "Fog density map");
+ light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(light_map, "Fog light map");
+ emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map");
+#else
+ tf.format = RD::DATA_FORMAT_R32_UINT;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(density_map, "Fog density map");
+ RD::get_singleton()->texture_clear(density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ light_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(light_map, "Fog light map");
+ RD::get_singleton()->texture_clear(light_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map");
+ RD::get_singleton()->texture_clear(emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+#endif
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.append_id(fog_map);
+ uniforms.push_back(u);
+ }
+
+ sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_sky_shader, RendererRD::SkyRD::SKY_SET_FOG);
+}
+
+Fog::VolumetricFog::~VolumetricFog() {
+ RD::get_singleton()->free(prev_light_density_map);
+ RD::get_singleton()->free(light_density_map);
+ RD::get_singleton()->free(fog_map);
+ RD::get_singleton()->free(density_map);
+ RD::get_singleton()->free(light_map);
+ RD::get_singleton()->free(emissive_map);
+
+ if (fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(fog_uniform_set)) {
+ RD::get_singleton()->free(fog_uniform_set);
+ }
+ if (process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set_density)) {
+ RD::get_singleton()->free(process_uniform_set_density);
+ }
+ if (process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set)) {
+ RD::get_singleton()->free(process_uniform_set);
+ }
+ if (process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set2)) {
+ RD::get_singleton()->free(process_uniform_set2);
+ }
+ if (sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_uniform_set)) {
+ RD::get_singleton()->free(sdfgi_uniform_set);
+ }
+ if (sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_uniform_set)) {
+ RD::get_singleton()->free(sky_uniform_set);
+ }
+}
+
+Vector3i Fog::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) {
+ Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point);
+ view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera
+ Vector3 fog_position = Vector3(0, 0, 0);
+
+ view_position.y = -view_position.y;
+ fog_position.z = -view_position.z / fog_end;
+ fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5;
+ fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5;
+ fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread));
+ fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5);
+
+ fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x);
+ fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y);
+ fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z);
+
+ return Vector3i(fog_position);
+}
+
+void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ RENDER_TIMESTAMP("> Volumetric Fog");
+ RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
+
+ if (p_fog_volumes.size() > 0) {
+ RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
+
+ RENDER_TIMESTAMP("Render FogVolumes");
+
+ VolumetricFogShader::VolumeUBO params;
+
+ Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
+ Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
+ float z_near = p_cam_projection.get_z_near();
+ float z_far = p_cam_projection.get_z_far();
+ float fog_end = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
+
+ Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
+ Vector2 fog_near_size;
+ if (p_cam_projection.is_orthogonal()) {
+ fog_near_size = fog_far_size;
+ } else {
+ fog_near_size = Vector2();
+ }
+
+ params.fog_frustum_size_begin[0] = fog_near_size.x;
+ params.fog_frustum_size_begin[1] = fog_near_size.y;
+
+ params.fog_frustum_size_end[0] = fog_far_size.x;
+ params.fog_frustum_size_end[1] = fog_far_size.y;
+
+ params.fog_frustum_end = fog_end;
+ params.z_near = z_near;
+ params.z_far = z_far;
+ params.time = p_settings.time;
+
+ params.fog_volume_size[0] = p_settings.vfog->width;
+ params.fog_volume_size[1] = p_settings.vfog->height;
+ params.fog_volume_size[2] = p_settings.vfog->depth;
+
+ params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env);
+ params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
+ params.detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
+ params.temporal_blend = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection_amount(p_settings.env);
+
+ Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_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);
+
+ if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 1;
+ u.append_id(p_settings.vfog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.append_id(volumetric_fog.volume_ubo);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 3;
+ u.append_id(p_settings.vfog->density_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 4;
+ u.append_id(p_settings.vfog->light_map);
+ uniforms.push_back(u);
+ }
+
+ p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ bool any_uses_time = false;
+
+ for (int i = 0; i < (int)p_fog_volumes.size(); i++) {
+ FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]);
+ ERR_FAIL_COND(!fog_volume_instance);
+ RID fog_volume = fog_volume_instance->volume;
+
+ RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume);
+
+ FogMaterialData *material = nullptr;
+
+ if (fog_material.is_valid()) {
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG));
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ fog_material = volumetric_fog.default_material;
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG));
+ }
+
+ ERR_FAIL_COND(!material);
+
+ FogShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ any_uses_time |= shader_data->uses_time;
+
+ Vector3i min = Vector3i();
+ Vector3i max = Vector3i();
+ Vector3i kernel_size = Vector3i();
+
+ Vector3 position = fog_volume_instance->transform.get_origin();
+ 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.
+ Vector3i points[8];
+ Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+ float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
+ points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+
+ min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1);
+ max = Vector3i(1, 1, 1);
+
+ for (int j = 0; j < 8; j++) {
+ min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z));
+ max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z));
+ }
+
+ kernel_size = max - min;
+ } else {
+ // Volume type global runs on all cells
+ extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+ min = Vector3i(0, 0, 0);
+ kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth));
+ }
+
+ if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
+ continue;
+ }
+
+ VolumetricFogShader::FogPushConstant push_constant;
+ push_constant.position[0] = position.x;
+ push_constant.position[1] = position.y;
+ push_constant.position[2] = position.z;
+ push_constant.extents[0] = extents.x;
+ push_constant.extents[1] = extents.y;
+ push_constant.extents[2] = extents.z;
+ push_constant.corner[0] = min.x;
+ push_constant.corner[1] = min.y;
+ push_constant.corner[2] = min.z;
+ 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(), push_constant.transform);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
+ }
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z);
+ }
+ if (any_uses_time || RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) {
+ RenderingServerDefault::redraw_request();
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end();
+ }
+
+ if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) {
+ //re create uniform set if needed
+ Vector<RD::Uniform> uniforms;
+ Vector<RD::Uniform> copy_uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+ if (p_settings.shadow_atlas_depth.is_null()) {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK));
+ } else {
+ u.append_id(p_settings.shadow_atlas_depth);
+ }
+
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+ if (p_settings.directional_shadow_depth.is_valid()) {
+ u.append_id(p_settings.directional_shadow_depth);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK));
+ }
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 3;
+ u.append_id(p_settings.omni_light_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 4;
+ u.append_id(p_settings.spot_light_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 5;
+ u.append_id(p_settings.directional_light_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 6;
+ u.append_id(p_settings.cluster_builder->get_cluster_buffer());
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 7;
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 8;
+ u.append_id(p_settings.vfog->light_density_map);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.append_id(p_settings.vfog->fog_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.append_id(p_settings.vfog->prev_light_density_map);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 10;
+ u.append_id(p_settings.shadow_sampler);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 11;
+ u.append_id(p_settings.voxel_gl_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 12;
+ for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) {
+ u.append_id(p_settings.rbgi->voxel_gi_textures[i]);
+ }
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 13;
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 14;
+ u.append_id(volumetric_fog.params_ubo);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 15;
+ u.append_id(p_settings.vfog->prev_light_density_map);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 16;
+ u.append_id(p_settings.vfog->density_map);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 17;
+ u.append_id(p_settings.vfog->light_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 18;
+ u.append_id(p_settings.vfog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 19;
+ RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ RID sky_texture = RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env).is_valid() ? p_settings.sky->sky_get_radiance_texture_rd(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env)) : RID();
+ u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture);
+ uniforms.push_back(u);
+ }
+
+ p_settings.vfog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
+
+ p_settings.vfog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
+
+ RID aux7 = uniforms.write[7].get_id(0);
+ RID aux8 = uniforms.write[8].get_id(0);
+
+ uniforms.write[7].set_id(0, aux8);
+ uniforms.write[8].set_id(0, aux7);
+
+ p_settings.vfog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
+
+ uniforms.remove_at(8);
+ uniforms.write[7].set_id(0, aux7);
+ p_settings.vfog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
+ }
+
+ bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi != nullptr);
+
+ if (using_sdfgi) {
+ if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.append_id(p_settings.gi->sdfgi_ubo);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+ u.append_id(p_settings.sdfgi->ambient_texture);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+ u.append_id(p_settings.sdfgi->occlusion_texture);
+ uniforms.push_back(u);
+ }
+
+ p_settings.vfog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
+ }
+ }
+
+ p_settings.vfog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
+ p_settings.vfog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
+
+ VolumetricFogShader::ParamsUBO params;
+
+ Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
+ Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
+ float z_near = p_cam_projection.get_z_near();
+ float z_far = p_cam_projection.get_z_far();
+ float fog_end = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
+
+ Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
+ Vector2 fog_near_size;
+ if (p_cam_projection.is_orthogonal()) {
+ fog_near_size = fog_far_size;
+ } else {
+ fog_near_size = Vector2();
+ }
+
+ params.fog_frustum_size_begin[0] = fog_near_size.x;
+ params.fog_frustum_size_begin[1] = fog_near_size.y;
+
+ params.fog_frustum_size_end[0] = fog_far_size.x;
+ params.fog_frustum_size_end[1] = fog_far_size.y;
+
+ params.ambient_inject = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_ambient_inject(p_settings.env) * RendererSceneRenderRD::get_singleton()->environment_get_ambient_light_energy(p_settings.env);
+ params.z_far = z_far;
+
+ params.fog_frustum_end = fog_end;
+
+ Color ambient_color = RendererSceneRenderRD::get_singleton()->environment_get_ambient_light(p_settings.env).srgb_to_linear();
+ params.ambient_color[0] = ambient_color.r;
+ params.ambient_color[1] = ambient_color.g;
+ params.ambient_color[2] = ambient_color.b;
+ params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env);
+
+ params.fog_volume_size[0] = p_settings.vfog->width;
+ params.fog_volume_size[1] = p_settings.vfog->height;
+ params.fog_volume_size[2] = p_settings.vfog->depth;
+
+ params.directional_light_count = p_directional_light_count;
+
+ Color emission = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission(p_settings.env).srgb_to_linear();
+ params.base_emission[0] = emission.r * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env);
+ params.base_emission[1] = emission.g * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env);
+ params.base_emission[2] = emission.b * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env);
+ params.base_density = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_density(p_settings.env);
+
+ Color base_scattering = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_scattering(p_settings.env).srgb_to_linear();
+ params.base_scattering[0] = base_scattering.r;
+ params.base_scattering[1] = base_scattering.g;
+ params.base_scattering[2] = base_scattering.b;
+ params.phase_g = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_anisotropy(p_settings.env);
+
+ params.detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
+ params.gi_inject = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env);
+
+ params.cam_rotation[0] = p_cam_transform.basis[0][0];
+ params.cam_rotation[1] = p_cam_transform.basis[1][0];
+ params.cam_rotation[2] = p_cam_transform.basis[2][0];
+ params.cam_rotation[3] = 0;
+ params.cam_rotation[4] = p_cam_transform.basis[0][1];
+ params.cam_rotation[5] = p_cam_transform.basis[1][1];
+ params.cam_rotation[6] = p_cam_transform.basis[2][1];
+ params.cam_rotation[7] = 0;
+ params.cam_rotation[8] = p_cam_transform.basis[0][2];
+ params.cam_rotation[9] = p_cam_transform.basis[1][2];
+ params.cam_rotation[10] = p_cam_transform.basis[2][2];
+ params.cam_rotation[11] = 0;
+ params.filter_axis = 0;
+ params.max_voxel_gi_instances = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.001 ? p_voxel_gi_count : 0;
+ 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;
+ RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view);
+
+ params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env);
+ params.temporal_blend = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection_amount(p_settings.env);
+
+ {
+ uint32_t cluster_size = p_settings.cluster_builder->get_cluster_size();
+ params.cluster_shift = get_shift_from_power_of_2(cluster_size);
+
+ uint32_t cluster_screen_width = (p_settings.rb_size.x - 1) / cluster_size + 1;
+ uint32_t cluster_screen_height = (p_settings.rb_size.y - 1) / cluster_size + 1;
+ params.max_cluster_element_count_div_32 = p_settings.max_cluster_elements / 32;
+ params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32);
+ params.cluster_width = cluster_screen_width;
+
+ params.screen_size[0] = p_settings.rb_size.x;
+ params.screen_size[1] = p_settings.rb_size.y;
+ }
+
+ Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_settings.env);
+ sky_transform = sky_transform.inverse() * p_cam_transform.basis;
+ RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform);
+
+ RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
+
+ RENDER_TIMESTAMP("Render Fog");
+ RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params, RD::BARRIER_MASK_COMPUTE);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set_density, 0);
+
+ if (using_sdfgi) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1);
+ }
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // Copy fog to history buffer
+ if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->copy_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ RD::get_singleton()->draw_command_end_label();
+
+ if (p_settings.volumetric_fog_filter_active) {
+ RD::get_singleton()->draw_command_begin_label("Filter Fog");
+
+ RENDER_TIMESTAMP("Filter Fog");
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+
+ RD::get_singleton()->compute_list_end();
+ //need restart for buffer update
+
+ params.filter_axis = 1;
+ RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params);
+
+ compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set2, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ RENDER_TIMESTAMP("Integrate Fog");
+ RD::get_singleton()->draw_command_begin_label("Integrate Fog");
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1);
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
+
+ RENDER_TIMESTAMP("< Volumetric Fog");
+ RD::get_singleton()->draw_command_end_label();
+ RD::get_singleton()->draw_command_end_label();
+}
diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h
new file mode 100644
index 0000000000..171f9f3b88
--- /dev/null
+++ b/servers/rendering/renderer_rd/environment/fog.h
@@ -0,0 +1,328 @@
+/*************************************************************************/
+/* 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/renderer_rd/cluster_builder_rd.h"
+#include "servers/rendering/renderer_rd/environment/gi.h"
+#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h"
+#include "servers/rendering/storage/utilities.h"
+
+namespace RendererRD {
+
+class Fog : public RendererFog {
+public:
+ /* FOG VOLUMES */
+
+ struct FogVolume {
+ RID material;
+ Vector3 extents = Vector3(1, 1, 1);
+
+ RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
+
+ Dependency dependency;
+ };
+
+ struct FogVolumeInstance {
+ RID volume;
+ Transform3D transform;
+ bool active = false;
+ };
+
+private:
+ static Fog *singleton;
+
+ mutable RID_Owner<FogVolume, true> fog_volume_owner;
+ mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
+
+ /* Volumetric Fog */
+ struct VolumetricFogShader {
+ enum FogSet {
+ FOG_SET_BASE,
+ FOG_SET_UNIFORMS,
+ FOG_SET_MATERIAL,
+ FOG_SET_MAX,
+ };
+
+ struct FogPushConstant {
+ float position[3];
+ float pad;
+
+ float extents[3];
+ float pad2;
+
+ int32_t corner[3];
+ uint32_t shape;
+
+ float transform[16];
+ };
+
+ struct VolumeUBO {
+ float fog_frustum_size_begin[2];
+ float fog_frustum_size_end[2];
+
+ float fog_frustum_end;
+ float z_near;
+ float z_far;
+ float time;
+
+ int32_t fog_volume_size[3];
+ uint32_t directional_light_count;
+
+ uint32_t use_temporal_reprojection;
+ uint32_t temporal_frame;
+ float detail_spread;
+ float temporal_blend;
+
+ float to_prev_view[16];
+ float transform[16];
+ };
+
+ ShaderCompiler compiler;
+ VolumetricFogShaderRD shader;
+ RID volume_ubo;
+
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+
+ RID base_uniform_set;
+
+ RID params_ubo;
+
+ enum {
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
+ VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
+ };
+
+ struct ParamsUBO {
+ float fog_frustum_size_begin[2];
+ float fog_frustum_size_end[2];
+
+ float fog_frustum_end;
+ float ambient_inject;
+ float z_far;
+ uint32_t filter_axis;
+
+ float ambient_color[3];
+ float sky_contribution;
+
+ int32_t fog_volume_size[3];
+ uint32_t directional_light_count;
+
+ float base_emission[3];
+ float base_density;
+
+ float base_scattering[3];
+ float phase_g;
+
+ float detail_spread;
+ float gi_inject;
+ uint32_t max_voxel_gi_instances;
+ uint32_t cluster_type_size;
+
+ float screen_size[2];
+ uint32_t cluster_shift;
+ uint32_t cluster_width;
+
+ uint32_t max_cluster_element_count_div_32;
+ uint32_t use_temporal_reprojection;
+ uint32_t temporal_frame;
+ float temporal_blend;
+
+ float cam_rotation[12];
+ float to_prev_view[16];
+ float radiance_inverse_xform[12];
+ };
+
+ VolumetricFogProcessShaderRD process_shader;
+
+ RID process_shader_version;
+ RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
+
+ } volumetric_fog;
+
+ Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
+
+ struct FogShaderData : public RendererRD::MaterialStorage::ShaderData {
+ bool valid = false;
+ RID version;
+
+ RID pipeline;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size = 0;
+
+ String path;
+ String code;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
+
+ bool uses_time = false;
+
+ virtual void set_path_hint(const String &p_hint);
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
+ FogShaderData() {}
+ virtual ~FogShaderData();
+ };
+
+ struct FogMaterialData : public RendererRD::MaterialStorage::MaterialData {
+ FogShaderData *shader_data = nullptr;
+ RID uniform_set;
+ bool uniform_set_updated;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~FogMaterialData();
+ };
+
+ RendererRD::MaterialStorage::ShaderData *_create_fog_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_fog_shader_funcs();
+
+ RendererRD::MaterialStorage::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader);
+
+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;
+
+ /* FOG VOLUMES INSTANCE */
+
+ FogVolumeInstance *get_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.get_or_null(p_rid); };
+ bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); };
+
+ RID fog_volume_instance_create(RID p_fog_volume);
+ void fog_instance_free(RID p_rid);
+
+ /* Volumetric FOG */
+ struct VolumetricFog {
+ enum {
+ MAX_TEMPORAL_FRAMES = 16
+ };
+
+ uint32_t width = 0;
+ uint32_t height = 0;
+ uint32_t depth = 0;
+
+ float length;
+ float spread;
+
+ RID light_density_map;
+ RID prev_light_density_map;
+ RID fog_map;
+ RID density_map;
+ RID light_map;
+ RID emissive_map;
+
+ RID fog_uniform_set;
+ RID copy_uniform_set;
+ RID process_uniform_set_density;
+ RID process_uniform_set;
+ RID process_uniform_set2;
+ RID sdfgi_uniform_set;
+ RID sky_uniform_set;
+
+ int last_shadow_filter = -1;
+
+ VolumetricFog(const Vector3i &fog_size, RID p_sky_shader);
+ ~VolumetricFog();
+ };
+
+ void init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array);
+ void free_fog_shader();
+
+ struct VolumetricFogSettings {
+ Vector2i rb_size;
+ double time;
+ bool is_using_radiance_cubemap_array;
+ uint32_t max_cluster_elements;
+ bool volumetric_fog_filter_active;
+ RID shadow_sampler;
+ RID voxel_gl_buffer;
+ RID shadow_atlas_depth;
+ RID omni_light_buffer;
+ RID spot_light_buffer;
+ RID directional_shadow_depth;
+ RID directional_light_buffer;
+
+ // Objects related to our render buffer
+ VolumetricFog *vfog;
+ ClusterBuilderRD *cluster_builder;
+ GI *gi;
+ GI::SDFGI *sdfgi;
+ GI::RenderBuffersGI *rbgi;
+ RID env;
+ SkyRD *sky;
+ };
+ void volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
+};
+
+} // 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..feafcc42c9 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"
@@ -110,6 +109,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo
Vector<Vector<uint8_t>> s;
s.push_back(p_distance_field);
voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s);
+ RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture");
}
#if 0
{
@@ -123,6 +123,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM);
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT);
voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture");
}
RID shared_tex;
{
@@ -184,7 +185,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 +313,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);
@@ -386,16 +374,15 @@ RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
////////////////////////////////////////////////////////////////////////////////
// SDFGI
-void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi) {
+void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi) {
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;
- uses_occlusion = p_env->sdfgi_use_occlusion;
- y_scale_mode = p_env->sdfgi_y_scale;
+ num_cascades = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_cascades(p_env);
+ min_cell_size = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_min_cell_size(p_env);
+ uses_occlusion = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_use_occlusion(p_env);
+ y_scale_mode = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_y_scale(p_env);
static const float y_scale[3] = { 2.0, 1.5, 1.0 };
y_mult = y_scale[y_scale_mode];
cascades.resize(num_cascades);
@@ -417,29 +404,38 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
RD::TextureFormat tf_render = tf_sdf;
tf_render.format = RD::DATA_FORMAT_R16_UINT;
render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_albedo, "VoxelGI Render Albedo");
tf_render.format = RD::DATA_FORMAT_R32_UINT;
render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_emission, "VoxelGI Render Emission");
render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_emission_aniso, "VoxelGI Render Emission Aniso");
tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize
for (int i = 0; i < 8; i++) {
render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_occlusion[i], String("VoxelGI Render Occlusion ") + itos(i));
}
tf_render.format = RD::DATA_FORMAT_R32_UINT;
render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_geom_facing, "VoxelGI Render Geometry Facing");
tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf[0], "VoxelGI Render SDF 0");
render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf[1], "VoxelGI Render SDF 1");
tf_render.width /= 2;
tf_render.height /= 2;
tf_render.depth /= 2;
render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf_half[0], "VoxelGI Render SDF Half 0");
render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf_half[1], "VoxelGI Render SDF Half 1");
}
RD::TextureFormat tf_occlusion = tf_sdf;
@@ -480,7 +476,9 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D;
lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
+ RD::get_singleton()->set_resource_name(lightprobe_history_scroll, "VoxelGI LightProbe History Scroll");
lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
+ RD::get_singleton()->set_resource_name(lightprobe_average_scroll, "VoxelGI LightProbe Average Scroll");
{
//octahedral lightprobes
@@ -494,6 +492,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
//lightprobe texture is an octahedral texture
lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView());
+ RD::get_singleton()->set_resource_name(lightprobe_data, "VoxelGI LightProbe Data");
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data);
@@ -507,11 +506,13 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
//lightprobe texture is an octahedral texture
ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView());
+ RD::get_singleton()->set_resource_name(ambient_texture, "VoxelGI Ambient Texture");
}
cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES);
occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView());
+ RD::get_singleton()->set_resource_name(occlusion_data, "VoxelGI Occlusion Data");
{
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16;
@@ -524,11 +525,15 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
/* 3D Textures */
cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.sdf_tex, "VoxelGI Cascade SDF Texture");
cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.light_data, "VoxelGI Cascade Light Data");
cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.light_aniso_0_tex, "VoxelGI Cascade Light Aniso 0 Texture");
cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.light_aniso_1_tex, "VoxelGI Cascade Light Aniso 1 Texture");
{
RD::TextureView tv;
@@ -555,9 +560,11 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
/* Probe History */
cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.lightprobe_history_tex, "VoxelGI Cascade LightProbe History Texture");
RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work
cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.lightprobe_average_tex, "VoxelGI Cascade LightProbe Average Texture");
RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work
/* Buffers */
@@ -727,7 +734,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
if (j < cascades.size()) {
u.append_id(cascades[j].sdf_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -803,7 +810,8 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
uniforms.push_back(u);
}
- cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, 0), 0);
+ cascade.sdf_direct_light_static_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_STATIC), 0);
+ cascade.sdf_direct_light_dynamic_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_DYNAMIC), 0);
}
//preprocess initialize uniform set
@@ -970,7 +978,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
if (j < cascades.size()) {
u.append_id(cascades[j].sdf_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -983,7 +991,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
if (j < cascades.size()) {
u.append_id(cascades[j].light_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -996,7 +1004,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
if (j < cascades.size()) {
u.append_id(cascades[j].light_aniso_0_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1009,7 +1017,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
if (j < cascades.size()) {
u.append_id(cascades[j].light_aniso_1_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1093,11 +1101,11 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
cascades[i].integrate_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.integrate.version_get_shader(gi->sdfgi_shader.integrate_shader, 0), 0);
}
- bounce_feedback = p_env->sdfgi_bounce_feedback;
- energy = p_env->sdfgi_energy;
- normal_bias = p_env->sdfgi_normal_bias;
- probe_bias = p_env->sdfgi_probe_bias;
- reads_sky = p_env->sdfgi_read_sky_light;
+ bounce_feedback = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_bounce_feedback(p_env);
+ energy = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_energy(p_env);
+ normal_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_normal_bias(p_env);
+ probe_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_probe_bias(p_env);
+ reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);
}
void GI::SDFGI::erase() {
@@ -1155,12 +1163,12 @@ void GI::SDFGI::erase() {
}
}
-void GI::SDFGI::update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position) {
- bounce_feedback = p_env->sdfgi_bounce_feedback;
- energy = p_env->sdfgi_energy;
- normal_bias = p_env->sdfgi_normal_bias;
- probe_bias = p_env->sdfgi_probe_bias;
- reads_sky = p_env->sdfgi_read_sky_light;
+void GI::SDFGI::update(RID p_env, const Vector3 &p_world_position) {
+ bounce_feedback = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_bounce_feedback(p_env);
+ energy = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_energy(p_env);
+ normal_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_normal_bias(p_env);
+ probe_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_probe_bias(p_env);
+ reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);
int32_t drag_margin = (cascade_size / SDFGI::PROBE_DIVISOR) / 2;
@@ -1252,7 +1260,7 @@ void GI::SDFGI::update_light() {
}
cascades[i].all_dynamic_lights_dirty = false;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_dynamic_uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DirectLightPushConstant));
RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0);
}
@@ -1260,7 +1268,7 @@ void GI::SDFGI::update_light() {
RD::get_singleton()->draw_command_end_label();
}
-void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky) {
+void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) {
RD::get_singleton()->draw_command_begin_label("SDFGI Update Probes");
SDFGIShader::IntegratePushConstant push_constant;
@@ -1276,29 +1284,29 @@ void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSk
push_constant.ray_bias = probe_bias;
push_constant.image_size[0] = probe_axis_count * probe_axis_count;
push_constant.image_size[1] = probe_axis_count;
- push_constant.store_ambient_texture = p_env->volumetric_fog_enabled;
+ push_constant.store_ambient_texture = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_enabled(p_env);
RID sky_uniform_set = gi->sdfgi_shader.integrate_default_sky_uniform_set;
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_DISABLED;
push_constant.y_mult = y_mult;
- if (reads_sky && p_env) {
- push_constant.sky_energy = p_env->bg_energy;
+ if (reads_sky && p_env.is_valid()) {
+ push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
- if (p_env->background == RS::ENV_BG_CLEAR_COLOR) {
+ if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == 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;
- } else if (p_env->background == RS::ENV_BG_COLOR) {
+ } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_COLOR) {
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = p_env->bg_color;
+ Color c = RendererSceneRenderRD::get_singleton()->environment_get_bg_color(p_env);
push_constant.sky_color[0] = c.r;
push_constant.sky_color[1] = c.g;
push_constant.sky_color[2] = c.b;
- } else if (p_env->background == RS::ENV_BG_SKY) {
+ } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_SKY) {
if (p_sky && p_sky->radiance.is_valid()) {
if (integrate_sky_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(integrate_sky_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -1474,7 +1482,7 @@ void GI::SDFGI::update_cascades() {
RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE);
}
-void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) {
+void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
@@ -1490,7 +1498,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
if (i < cascades.size()) {
u.append_id(cascades[i].sdf_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1503,7 +1511,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
if (i < cascades.size()) {
u.append_id(cascades[i].light_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1516,7 +1524,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
if (i < cascades.size()) {
u.append_id(cascades[i].light_aniso_0_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1529,7 +1537,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
if (i < cascades.size()) {
u.append_id(cascades[i].light_aniso_1_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -1583,34 +1591,24 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
push_constant.max_cascades = cascades.size();
push_constant.screen_size[0] = p_width;
push_constant.screen_size[1] = p_height;
- push_constant.probe_axis_size = probe_axis_count;
- push_constant.use_occlusion = uses_occlusion;
push_constant.y_mult = y_mult;
push_constant.z_near = -p_projections[v].get_z_near();
- push_constant.cam_transform[0] = p_transform.basis.rows[0][0];
- push_constant.cam_transform[1] = p_transform.basis.rows[1][0];
- push_constant.cam_transform[2] = p_transform.basis.rows[2][0];
- push_constant.cam_transform[3] = 0;
- push_constant.cam_transform[4] = p_transform.basis.rows[0][1];
- push_constant.cam_transform[5] = p_transform.basis.rows[1][1];
- push_constant.cam_transform[6] = p_transform.basis.rows[2][1];
- push_constant.cam_transform[7] = 0;
- push_constant.cam_transform[8] = p_transform.basis.rows[0][2];
- push_constant.cam_transform[9] = p_transform.basis.rows[1][2];
- push_constant.cam_transform[10] = p_transform.basis.rows[2][2];
- push_constant.cam_transform[11] = 0;
- push_constant.cam_transform[12] = p_transform.origin.x;
- push_constant.cam_transform[13] = p_transform.origin.y;
- push_constant.cam_transform[14] = p_transform.origin.z;
- push_constant.cam_transform[15] = 1;
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ push_constant.cam_basis[i][j] = p_transform.basis.rows[j][i];
+ }
+ }
+ push_constant.cam_origin[0] = p_transform.origin[0];
+ push_constant.cam_origin[1] = p_transform.origin[1];
+ push_constant.cam_origin[2] = p_transform.origin[2];
// need to properly unproject for asymmetric projection matrices in stereo..
- CameraMatrix inv_projection = p_projections[v].inverse();
+ Projection inv_projection = p_projections[v].inverse();
for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- push_constant.inv_projection[i * 4 + j] = inv_projection.matrix[i][j];
+ for (int j = 0; j < 3; j++) {
+ push_constant.inv_projection[j][i] = inv_projection.matrix[i][j];
}
}
@@ -1624,7 +1622,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true, false, false, false, RID(), p_view_count > 1);
}
-void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
+void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
// setup scene data
@@ -1636,7 +1634,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);
@@ -1939,7 +1937,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
}
}
-void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) {
+void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) {
//print_line("rendering region " + itos(p_region));
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
@@ -2406,7 +2404,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co
dl_push_constant.cascade = p_cascade_indices[i];
if (dl_push_constant.light_count > 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_static_uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDFGIShader::DirectLightPushConstant));
RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0);
}
@@ -2420,7 +2418,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co
////////////////////////////////////////////////////////////////////////////////
// VoxelGIInstance
-void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
uint32_t data_version = gi->voxel_gi_get_data_version(probe);
@@ -2459,6 +2457,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(texture, "VoxelGI Instance Texture");
RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1);
@@ -2588,6 +2587,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.texture, "VoxelGI Instance DMap Texture");
if (dynamic_maps.size() == 0) {
// Render depth for first one.
@@ -2595,6 +2595,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D16_UNORM, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.fb_depth, "VoxelGI Instance DMap FB Depth");
}
//just use depth as-is
@@ -2602,13 +2603,17 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.depth, "VoxelGI Instance DMap Depth");
if (dynamic_maps.size() == 0) {
dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.albedo, "VoxelGI Instance DMap Albedo");
dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.normal, "VoxelGI Instance DMap Normal");
dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.orm, "VoxelGI Instance DMap ORM");
Vector<RID> fb;
fb.push_back(dmap.albedo);
@@ -2936,10 +2941,10 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
//this could probably be better parallelized in compute..
for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
- RendererSceneRender::GeometryInstance *instance = p_dynamic_objects[i];
+ RenderGeometryInstance *instance = p_dynamic_objects[i];
//transform aabb to voxel_gi
- AABB aabb = (to_probe_xform * p_scene_render->geometry_instance_get_transform(instance)).xform(p_scene_render->geometry_instance_get_aabb(instance));
+ AABB aabb = (to_probe_xform * instance->get_transform()).xform(instance->get_aabb());
//this needs to wrap to grid resolution to avoid jitter
//also extend margin a bit just in case
@@ -3000,7 +3005,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(1)) < 0);
bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(2)) > 0);
- CameraMatrix cm;
+ Projection cm;
cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]);
if (p_scene_render->cull_argument.size() == 0) {
@@ -3125,14 +3130,14 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
last_probe_version = gi->voxel_gi_get_version(probe);
}
-void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
if (mipmaps.size() == 0) {
return;
}
- CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse());
+ Projection cam_transform = (p_camera_with_transform * Projection(transform)) * Projection(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse());
int level = 0;
Vector3i octree_size = gi->voxel_gi_get_octree_size(probe);
@@ -3218,12 +3223,10 @@ GI::~GI() {
singleton = nullptr;
}
-void GI::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
+void GI::init(SkyRD *p_sky) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
-
/* GI */
{
@@ -3339,7 +3342,11 @@ void GI::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 0;
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE));
+ if (p_sky->sky_use_cubemap_array) {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE));
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE));
+ }
uniforms.push_back(u);
}
{
@@ -3359,37 +3366,40 @@ void GI::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
//calculate tables
String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
Vector<String> gi_modes;
+
gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI
gi_modes.push_back("\n#define USE_SDFGI\n"); // MODE_SDFGI
gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_COMBINED
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_VOXEL_GI
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n"); // MODE_HALF_RES_SDFGI
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_COMBINED
-
- gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_VOXEL_GI_MULTIVIEW
- gi_modes.push_back("\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_SDFGI_MULTIVIEW
- gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_COMBINED_MULTIVIEW
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_VOXEL_GI_MULTIVIEW
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_SDFGI_MULTIVIEW
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_COMBINED_MULTIVIEW
shader.initialize(gi_modes, defines);
+ shader_version = shader.version_create();
+
+ Vector<RD::PipelineSpecializationConstant> specialization_constants;
- if (!RendererCompositorRD::singleton->is_xr_enabled()) {
- shader.set_variant_enabled(MODE_VOXEL_GI_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_SDFGI_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_COMBINED_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_HALF_RES_VOXEL_GI_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_HALF_RES_SDFGI_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_HALF_RES_COMBINED_MULTIVIEW, false);
+ {
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 0; // SHADER_SPECIALIZATION_HALF_RES
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
+
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 1; // SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
+
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 2; // SHADER_SPECIALIZATION_USE_VRS
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
}
- shader_version = shader.version_create();
- for (int i = 0; i < MODE_MAX; i++) {
- if (shader.is_variant_enabled(i)) {
- pipelines[i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i));
- } else {
- pipelines[i] = RID();
+ for (int v = 0; v < SHADER_SPECIALIZATION_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SHADER_SPECIALIZATION_HALF_RES) ? true : false;
+ specialization_constants.ptrw()[1].bool_value = (v & SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX) ? true : false;
+ specialization_constants.ptrw()[2].bool_value = (v & SHADER_SPECIALIZATION_USE_VRS) ? true : false;
+ for (int i = 0; i < MODE_MAX; i++) {
+ pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i), specialization_constants);
}
}
@@ -3457,7 +3467,7 @@ void GI::free() {
}
}
-GI::SDFGI *GI::create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
+GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
SDFGI *sdfgi = memnew(SDFGI);
sdfgi->create(p_env, p_world_position, p_requested_history_size, this);
@@ -3530,7 +3540,7 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra
}
if (texture == RID()) {
- texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
}
if (texture != rb->rbgi.voxel_gi_textures[i]) {
@@ -3581,25 +3591,17 @@ void GI::RenderBuffersGI::free() {
}
if (ambient_buffer.is_valid()) {
- if (view_count == 1) {
- // Only one view? then these are copies of our main buffers.
- ambient_view[0] = RID();
- reflection_view[0] = RID();
- } else {
- // Multiple views? free our slices.
- for (uint32_t v = 0; v < view_count; v++) {
- RD::get_singleton()->free(ambient_view[v]);
- RD::get_singleton()->free(reflection_view[v]);
- ambient_view[v] = RID();
- reflection_view[v] = RID();
- }
- }
-
- // Now we can free our buffers.
RD::get_singleton()->free(ambient_buffer);
RD::get_singleton()->free(reflection_buffer);
ambient_buffer = RID();
reflection_buffer = RID();
+
+ // these are automatically freed when we free the textures, so just reset..
+ for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
+ ambient_slice[v] = RID();
+ reflection_slice[v] = RID();
+ }
+
view_count = 0;
}
@@ -3609,7 +3611,7 @@ void GI::RenderBuffersGI::free() {
}
}
-void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
+void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -3623,17 +3625,14 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) {
// Free our old buffer if applicable
if (rb->rbgi.ambient_buffer.is_valid()) {
- if (rb->rbgi.view_count > 1) {
- for (uint32_t v = 0; v < rb->rbgi.view_count; v++) {
- RD::get_singleton()->free(rb->rbgi.ambient_view[v]);
- RD::get_singleton()->free(rb->rbgi.reflection_view[v]);
- }
- }
RD::get_singleton()->free(rb->rbgi.ambient_buffer);
RD::get_singleton()->free(rb->rbgi.reflection_buffer);
- }
- print_line("Allocating GI buffers"); // TESTING REMOVE BEFORE MERGING
+ for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
+ rb->rbgi.ambient_slice[v] = RID();
+ rb->rbgi.reflection_slice[v] = RID();
+ }
+ }
// Remember the view count we're using
rb->rbgi.view_count = p_view_count;
@@ -3656,18 +3655,19 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
}
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer");
rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer");
rb->rbgi.using_half_size_gi = half_resolution;
if (p_view_count == 1) {
- // Just one view? Copy our buffers
- rb->rbgi.ambient_view[0] = rb->rbgi.ambient_buffer;
- rb->rbgi.reflection_view[0] = rb->rbgi.reflection_buffer;
+ // Just copy, we don't need to create slices
+ rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer;
+ rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer;
} else {
- // More then one view? Create slices for each view
for (uint32_t v = 0; v < p_view_count; v++) {
- rb->rbgi.ambient_view[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0);
- rb->rbgi.reflection_view[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0);
+ rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0);
+ rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0);
}
}
}
@@ -3681,7 +3681,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 +3689,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;
@@ -3700,29 +3700,45 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
// Now compute the contents of our buffers.
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
- for (uint32_t v = 0; v < p_view_count; v++) {
- // Render each eye seperately.
- // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference..
+ // Render each eye separately.
+ // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference..
- // setup our push constant
+ // setup our push constant
- PushConstant push_constant;
+ PushConstant push_constant;
- push_constant.view_index = v;
- push_constant.orthogonal = p_projections[v].is_orthogonal();
- push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
- push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH;
+ push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
+ push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH;
- push_constant.z_near = p_projections[v].get_z_near();
- push_constant.z_far = p_projections[v].get_z_far();
+ // these should be the same for all views
+ push_constant.orthogonal = p_projections[0].is_orthogonal();
+ push_constant.z_near = p_projections[0].get_z_near();
+ push_constant.z_far = p_projections[0].get_z_far();
- push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[v].matrix[0][0]);
- push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[v].matrix[1][1]);
- push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
- push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
+ // these are only used if we have 1 view, else we use the projections in our scene data
+ push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]);
+ push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]);
+ push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0];
+ push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1];
- bool use_sdfgi = rb->sdfgi != nullptr;
- bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
+ bool use_sdfgi = rb->sdfgi != nullptr;
+ bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
+
+ uint32_t pipeline_specialization = 0;
+ if (rb->rbgi.using_half_size_gi) {
+ pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES;
+ }
+ if (p_view_count > 1) {
+ pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX;
+ }
+ if (p_vrs_slices[0].is_valid()) {
+ pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS;
+ }
+
+ Mode mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ push_constant.view_index = v;
// setup our uniform set
if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) {
@@ -3735,7 +3751,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
u.append_id(rb->sdfgi->cascades[j].sdf_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -3748,7 +3764,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
u.append_id(rb->sdfgi->cascades[j].light_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -3761,7 +3777,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -3774,7 +3790,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -3786,7 +3802,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
if (rb->sdfgi) {
u.append_id(rb->sdfgi->occlusion_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
uniforms.push_back(u);
}
@@ -3809,7 +3825,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
- u.append_id(rb->rbgi.ambient_view[v]);
+ u.append_id(rb->rbgi.ambient_slice[v]);
uniforms.push_back(u);
}
@@ -3817,7 +3833,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 10;
- u.append_id(rb->rbgi.reflection_view[v]);
+ u.append_id(rb->rbgi.reflection_slice[v]);
uniforms.push_back(u);
}
@@ -3828,7 +3844,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
if (rb->sdfgi) {
u.append_id(rb->sdfgi->lightprobe_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
}
uniforms.push_back(u);
}
@@ -3843,14 +3859,14 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 13;
- u.append_id(p_normal_roughness_views[v]);
+ u.append_id(p_normal_roughness_slices[v]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 14;
- RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(buffer);
uniforms.push_back(u);
}
@@ -3884,27 +3900,19 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
u.append_id(rb->rbgi.scene_data_ubo);
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 19;
+ RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS);
+ u.append_id(buffer);
+ uniforms.push_back(u);
+ }
rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
}
- Mode mode;
-
- if (p_view_count > 1) {
- if (rb->rbgi.using_half_size_gi) {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_HALF_RES_SDFGI_MULTIVIEW : MODE_HALF_RES_VOXEL_GI_MULTIVIEW);
- } else {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_SDFGI_MULTIVIEW : MODE_VOXEL_GI_MULTIVIEW);
- }
- } else {
- if (rb->rbgi.using_half_size_gi) {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_VOXEL_GI);
- } else {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
- }
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
@@ -3923,7 +3931,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;
@@ -3943,14 +3950,14 @@ bool GI::voxel_gi_needs_update(RID p_probe) const {
return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe);
}
-void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render);
}
-void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h
index b6ecfe42ea..304df1605b 100644
--- a/servers/rendering/renderer_rd/environment/gi.h
+++ b/servers/rendering/renderer_rd/environment/gi.h
@@ -35,9 +35,7 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/environment/renderer_gi.h"
#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/environment/sky.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 +45,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;
@@ -80,20 +78,17 @@ public:
float energy = 1.0;
float bias = 1.4;
float normal_bias = 0.0;
- float propagation = 0.7;
+ float propagation = 0.5;
bool interior = false;
- bool use_two_bounces = false;
-
- float anisotropy_strength = 0.5;
+ bool use_two_bounces = true;
uint32_t version = 1;
uint32_t data_version = 1;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
private:
- RendererStorageRD *storage = nullptr;
static GI *singleton;
/* VOXEL GI STORAGE */
@@ -237,16 +232,13 @@ private:
uint32_t max_cascades;
int32_t screen_size[2];
- uint32_t use_occlusion;
float y_mult;
- uint32_t probe_axis_size;
float z_near;
- float reserved1;
- float reserved2;
- float cam_transform[16];
- float inv_projection[16];
+ float inv_projection[3][4];
+ float cam_basis[3][3];
+ float cam_origin[3];
};
SdfgiDebugShaderRD debug;
@@ -418,9 +410,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 +424,6 @@ public:
struct VoxelGIInstance {
// access to our containers
- RendererStorageRD *storage = nullptr;
GI *gi = nullptr;
RID probe;
@@ -479,8 +467,8 @@ public:
Transform3D transform;
- void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
- void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
+ void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
};
mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
@@ -549,7 +537,8 @@ public:
Vector3i dirty_regions; //(0,0,0 is not dirty, negative is refresh from the end, DIRTY_ALL is refresh all.
RID sdf_store_uniform_set;
- RID sdf_direct_light_uniform_set;
+ RID sdf_direct_light_static_uniform_set;
+ RID sdf_direct_light_dynamic_uniform_set;
RID scroll_uniform_set;
RID scroll_occlusion_uniform_set;
RID integrate_uniform_set;
@@ -559,7 +548,6 @@ public:
};
// access to our containers
- RendererStorageRD *storage = nullptr;
GI *gi = nullptr;
// used for rendering (voxelization)
@@ -622,20 +610,20 @@ public:
int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically
RID integrate_sky_uniform_set;
- void create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi);
+ void create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi);
void erase();
- void update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position);
+ void update(RID p_env, const Vector3 &p_world_position);
void update_light();
- void update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky);
+ void update_probes(RID p_env, RendererRD::SkyRD::Sky *p_sky);
void store_probes();
int get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const;
void update_cascades();
- void debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views);
- void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
+ void debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views);
+ void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render);
- void render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render);
+ void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render);
void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
};
@@ -669,13 +657,13 @@ public:
/* GI buffers */
RID ambient_buffer;
+ RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS];
RID reflection_buffer;
- RID ambient_view[RendererSceneRender::MAX_RENDER_VIEWS];
- RID reflection_view[RendererSceneRender::MAX_RENDER_VIEWS];
- RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
+ RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS];
bool using_half_size_gi = false;
uint32_t view_count = 1;
+ RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
RID scene_data_ubo;
void free();
@@ -738,63 +726,60 @@ public:
};
struct PushConstant {
- uint32_t view_index;
uint32_t max_voxel_gi_instances;
uint32_t high_quality_vct;
uint32_t orthogonal;
+ uint32_t view_index;
float proj_info[4];
float z_near;
float z_far;
- float pad1;
float pad2;
+ float pad3;
};
RID sdfgi_ubo;
+
enum Mode {
MODE_VOXEL_GI,
MODE_SDFGI,
MODE_COMBINED,
- MODE_HALF_RES_VOXEL_GI,
- MODE_HALF_RES_SDFGI,
- MODE_HALF_RES_COMBINED,
-
- MODE_VOXEL_GI_MULTIVIEW,
- MODE_SDFGI_MULTIVIEW,
- MODE_COMBINED_MULTIVIEW,
- MODE_HALF_RES_VOXEL_GI_MULTIVIEW,
- MODE_HALF_RES_SDFGI_MULTIVIEW,
- MODE_HALF_RES_COMBINED_MULTIVIEW,
-
MODE_MAX
};
+ enum ShaderSpecializations {
+ SHADER_SPECIALIZATION_HALF_RES = 1 << 0,
+ SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX = 1 << 1,
+ SHADER_SPECIALIZATION_USE_VRS = 1 << 2,
+ SHADER_SPECIALIZATION_VARIATIONS = 8,
+ };
+
RID default_voxel_gi_buffer;
bool half_resolution = false;
GiShaderRD shader;
RID shader_version;
- RID pipelines[MODE_MAX];
+ RID pipelines[SHADER_SPECIALIZATION_VARIATIONS][MODE_MAX];
GI();
~GI();
- void init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky);
+ void init(RendererRD::SkyRD *p_sky);
void free();
- SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
+ SDFGI *create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
- void process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
+ void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
RID voxel_gi_instance_create(RID p_base);
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
bool voxel_gi_needs_update(RID p_probe) const;
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
- void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
+ void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
};
} // namespace RendererRD
-#endif /* !GI_RD_H */
+#endif // GI_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index b3b9b86aa8..6433a39863 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_sky_rd.cpp */
+/* sky.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,20 +28,27 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_scene_sky_rd.h"
+#include "sky.h"
#include "core/config/project_settings.h"
#include "core/math/math_defs.h"
-#include "renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.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/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"
+
+using namespace RendererRD;
////////////////////////////////////////////////////////////////////////////////
// SKY SHADER
-void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
+void SkyRD::SkyShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
+void SkyRD::SkyShaderData::set_code(const String &p_code) {
//compile
code = p_code;
@@ -140,7 +147,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void SkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -157,7 +164,7 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa
}
}
-void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SkyRD::SkyShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -171,15 +178,29 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par
order[E.value.order] = E.key;
}
}
-
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
}
}
-void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+void SkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
@@ -194,7 +215,7 @@ void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMat
}
}
-bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
+bool SkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -202,15 +223,15 @@ bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_par
return uniforms[p_param].texture_order >= 0;
}
-bool RendererSceneSkyRD::SkyShaderData::is_animated() const {
+bool SkyRD::SkyShaderData::is_animated() const {
return false;
}
-bool RendererSceneSkyRD::SkyShaderData::casts_shadows() const {
+bool SkyRD::SkyShaderData::casts_shadows() const {
return false;
}
-Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
+Variant SkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
@@ -219,13 +240,13 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam
return Variant();
}
-RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const {
+RS::ShaderNativeSourceCode SkyRD::SkyShaderData::get_native_source_code() const {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version);
}
-RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
+SkyRD::SkyShaderData::~SkyShaderData() {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
ERR_FAIL_COND(!scene_singleton);
//pipeline variants will clear themselves if shader is gone
@@ -237,7 +258,7 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
////////////////////////////////////////////////////////////////////////////////
// Sky material
-bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
uniform_set_updated = true;
@@ -245,7 +266,7 @@ bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<String
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL);
}
-RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
+SkyRD::SkyMaterialData::~SkyMaterialData() {
free_parameters_uniform_set(uniform_set);
}
@@ -267,7 +288,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
p_array[11] = 0;
}
-void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) {
+void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
@@ -318,7 +339,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
////////////////////////////////////////////////////////////////////////////////
// ReflectionData
-void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
+void SkyRD::ReflectionData::clear_reflection_data() {
layers.clear();
radiance_base_cubemap = RID();
if (downsampled_radiance_cubemap.is_valid()) {
@@ -329,13 +350,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 SkyRD::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();
@@ -398,21 +419,22 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, 1, RD::TEXTURE_SLICE_CUBEMAP);
RD::get_singleton()->set_resource_name(radiance_base_cubemap, "radiance base cubemap");
+
RD::TextureFormat tf;
tf.format = p_texture_format;
- tf.width = 64; // Always 64x64
- tf.height = 64;
+ tf.width = p_low_quality ? 64 : p_size >> 1; // Always 64x64 when using REALTIME.
+ tf.height = p_low_quality ? 64 : p_size >> 1;
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
tf.array_layers = 6;
- tf.mipmaps = 7;
+ tf.mipmaps = p_low_quality ? 7 : mipmaps - 1;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap");
{
- uint32_t mmw = 64;
- uint32_t mmh = 64;
- downsampled_layer.mipmaps.resize(7);
+ uint32_t mmw = tf.width;
+ uint32_t mmh = tf.height;
+ downsampled_layer.mipmaps.resize(tf.mipmaps);
for (int j = 0; j < downsampled_layer.mipmaps.size(); j++) {
ReflectionData::DownsampleLayer::Mipmap &mm = downsampled_layer.mipmaps.write[j];
mm.size.width = mmw;
@@ -437,7 +459,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
}
}
-void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays) {
+void SkyRD::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 +517,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 SkyRD::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 +586,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 SkyRD::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();
@@ -589,9 +611,9 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStora
}
////////////////////////////////////////////////////////////////////////////////
-// RendererSceneSkyRD::Sky
+// SkyRD::Sky
-void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) {
+void SkyRD::Sky::free() {
if (radiance.is_valid()) {
RD::get_singleton()->free(radiance);
radiance = RID();
@@ -614,12 +636,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 SkyRD::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])) {
@@ -633,7 +655,7 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) {
u.append_id(radiance);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
uniforms.push_back(u);
}
@@ -649,9 +671,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
}
} else {
if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
}
uniforms.push_back(u);
@@ -668,9 +690,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
}
} else {
if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
}
uniforms.push_back(u);
@@ -680,7 +702,7 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
return texture_uniform_sets[p_version];
}
-bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) {
+bool SkyRD::Sky::set_radiance_size(int p_radiance_size) {
ERR_FAIL_COND_V(p_radiance_size < 32 || p_radiance_size > 2048, false);
if (radiance_size == p_radiance_size) {
return false;
@@ -701,7 +723,7 @@ bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) {
return true;
}
-bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) {
+bool SkyRD::Sky::set_mode(RS::SkyMode p_mode) {
if (mode == p_mode) {
return false;
}
@@ -722,7 +744,7 @@ bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) {
return true;
}
-bool RendererSceneSkyRD::Sky::set_material(RID p_material) {
+bool SkyRD::Sky::set_material(RID p_material) {
if (material == p_material) {
return false;
}
@@ -731,7 +753,7 @@ bool RendererSceneSkyRD::Sky::set_material(RID p_material) {
return true;
}
-Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) {
+Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) {
if (radiance.is_valid()) {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
@@ -765,40 +787,39 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughnes
}
////////////////////////////////////////////////////////////////////////////////
-// RendererSceneSkyRD
+// SkyRD
-RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
+RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() {
SkyShaderData *shader_data = memnew(SkyShaderData);
return shader_data;
}
-RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
+RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_funcs() {
// !BAS! Why isn't _create_sky_shader_func not just static too?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func();
};
-RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
-RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
// !BAS! same here, we could just make _create_sky_material_func static?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
};
-RendererSceneSkyRD::RendererSceneSkyRD() {
+SkyRD::SkyRD() {
roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers");
sky_ggx_samples_quality = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples");
sky_use_cubemap_array = GLOBAL_GET("rendering/reflections/sky_reflections/texture_array_reflections");
}
-void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
+void SkyRD::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
@@ -834,8 +855,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
}
// register our shader funds
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_material_funcs);
{
ShaderCompiler::DefaultIdentifierActions actions;
@@ -891,7 +912,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
sky_shader.compiler.initialize(actions);
}
@@ -916,7 +937,7 @@ void sky() {
material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
- SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY));
+ SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND);
sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO));
@@ -949,7 +970,7 @@ void sky() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -978,7 +999,7 @@ void sky() {
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
u.append_id(vfog);
uniforms.push_back(u);
}
@@ -1012,21 +1033,21 @@ void sky() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 0;
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1;
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
uniforms.push_back(u);
}
@@ -1051,15 +1072,15 @@ void sky() {
}
}
-void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
+void SkyRD::set_texture_format(RD::DataFormat p_texture_format) {
texture_format = p_texture_format;
}
-RendererSceneSkyRD::~RendererSceneSkyRD() {
+SkyRD::~SkyRD() {
// cleanup anything created in init...
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY));
+ SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
sky_shader.shader.version_free(md->shader_data->version);
RD::get_singleton()->free(sky_scene_state.directional_light_buffer);
RD::get_singleton()->free(sky_scene_state.uniform_buffer);
@@ -1085,23 +1106,23 @@ RendererSceneSkyRD::~RendererSceneSkyRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
}
-void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
SkyMaterialData *material = nullptr;
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
RID sky_material;
SkyShaderData *shader_data = nullptr;
if (sky) {
- sky_material = sky_get_material(p_env->sky);
+ sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1109,7 +1130,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1284,32 +1305,32 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
}
sky_scene_state.ubo.z_far = p_projection.get_z_far();
- sky_scene_state.ubo.fog_enabled = p_env->fog_enabled;
- sky_scene_state.ubo.fog_density = p_env->fog_density;
- sky_scene_state.ubo.fog_aerial_perspective = p_env->fog_aerial_perspective;
- Color fog_color = p_env->fog_light_color.srgb_to_linear();
- float fog_energy = p_env->fog_light_energy;
+ sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_env);
+ sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_env);
+ sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_env);
+ Color fog_color = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_color(p_env).srgb_to_linear();
+ float fog_energy = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_energy(p_env);
sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy;
- sky_scene_state.ubo.fog_sun_scatter = p_env->fog_sun_scatter;
+ sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_env);
RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
}
-void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
ERR_FAIL_COND(!sky);
- RID sky_material = sky_get_material(p_env->sky);
+ RID sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
SkyMaterialData *material = nullptr;
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1317,7 +1338,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1326,7 +1347,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
ERR_FAIL_COND(!shader_data);
- float multiplier = p_env->bg_energy;
+ float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY;
RS::SkyMode sky_mode = sky->mode;
@@ -1371,9 +1392,9 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
Vector3(0, -1, 0)
};
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, 0.01, 10.0);
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
cm = correction * cm;
@@ -1387,7 +1408,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 +1427,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 +1442,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 +1451,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 +1476,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++;
@@ -1466,26 +1487,26 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
}
}
-void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
ERR_FAIL_COND(p_view_count == 0);
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
SkyMaterialData *material = nullptr;
RID sky_material;
- RS::EnvironmentBG background = p_env->background;
+ RS::EnvironmentBG background = RendererSceneRenderRD::get_singleton()->environment_get_background(p_env);
if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
ERR_FAIL_COND(!sky);
- sky_material = sky_get_material(p_env->sky);
+ sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1493,13 +1514,13 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
}
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
sky_material = sky_scene_state.fog_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1508,16 +1529,16 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
ERR_FAIL_COND(!shader_data);
- Basis sky_transform = p_env->sky_orientation;
+ Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
- float multiplier = p_env->bg_energy;
- float custom_fov = p_env->sky_custom_fov;
+ float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
+ float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
- CameraMatrix camera;
+ Projection camera;
uint32_t view_count = p_view_count;
- const CameraMatrix *projections = p_projections;
+ const Projection *projections = p_projections;
if (custom_fov) {
// With custom fov we don't support stereo...
@@ -1536,7 +1557,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 +1570,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 +1584,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;
}
@@ -1573,23 +1594,23 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
RD::get_singleton()->draw_list_end();
}
-void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
ERR_FAIL_COND(p_view_count == 0);
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
ERR_FAIL_COND(!sky);
SkyMaterialData *material = nullptr;
RID sky_material;
- sky_material = sky_get_material(p_env->sky);
+ sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1597,7 +1618,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1606,16 +1627,16 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
ERR_FAIL_COND(!shader_data);
- Basis sky_transform = p_env->sky_orientation;
+ Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
- float multiplier = p_env->bg_energy;
- float custom_fov = p_env->sky_custom_fov;
+ float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
+ float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
- CameraMatrix camera;
+ Projection camera;
uint32_t view_count = p_view_count;
- const CameraMatrix *projections = p_projections;
+ const Projection *projections = p_projections;
if (custom_fov) {
// With custom fov we don't support stereo...
@@ -1634,7 +1655,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 +1668,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));
@@ -1658,26 +1679,26 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
}
}
-void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
ERR_FAIL_COND(p_view_count == 0);
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
SkyMaterialData *material = nullptr;
RID sky_material;
- RS::EnvironmentBG background = p_env->background;
+ RS::EnvironmentBG background = RendererSceneRenderRD::get_singleton()->environment_get_background(p_env);
if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
ERR_FAIL_COND(!sky);
- sky_material = sky_get_material(p_env->sky);
+ sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1685,13 +1706,13 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
}
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
sky_material = sky_scene_state.fog_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1700,16 +1721,16 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
ERR_FAIL_COND(!shader_data);
- Basis sky_transform = p_env->sky_orientation;
+ Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
- float multiplier = p_env->bg_energy;
- float custom_fov = p_env->sky_custom_fov;
+ float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
+ float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
- CameraMatrix camera;
+ Projection camera;
uint32_t view_count = p_view_count;
- const CameraMatrix *projections = p_projections;
+ const Projection *projections = p_projections;
if (custom_fov) {
// With custom fov we don't support stereo...
@@ -1729,7 +1750,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;
}
@@ -1737,7 +1758,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
}
-void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
+void SkyRD::invalidate_sky(Sky *p_sky) {
if (!p_sky->dirty) {
p_sky->dirty = true;
p_sky->dirty_list = dirty_sky_list;
@@ -1745,7 +1766,7 @@ void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
}
}
-void RendererSceneSkyRD::update_dirty_skys() {
+void SkyRD::update_dirty_skys() {
Sky *sky = dirty_sky_list;
while (sky) {
@@ -1777,7 +1798,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 +1813,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;
}
@@ -1849,34 +1870,34 @@ void RendererSceneSkyRD::update_dirty_skys() {
dirty_sky_list = nullptr;
}
-RID RendererSceneSkyRD::sky_get_material(RID p_sky) const {
+RID SkyRD::sky_get_material(RID p_sky) const {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, RID());
return sky->material;
}
-RID RendererSceneSkyRD::allocate_sky_rid() {
+RID SkyRD::allocate_sky_rid() {
return sky_owner.allocate_rid();
}
-void RendererSceneSkyRD::initialize_sky_rid(RID p_rid) {
+void SkyRD::initialize_sky_rid(RID p_rid) {
sky_owner.initialize_rid(p_rid, Sky());
}
-RendererSceneSkyRD::Sky *RendererSceneSkyRD::get_sky(RID p_sky) const {
+SkyRD::Sky *SkyRD::get_sky(RID p_sky) const {
return sky_owner.get_or_null(p_sky);
}
-void RendererSceneSkyRD::free_sky(RID p_sky) {
+void SkyRD::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);
}
-void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
+void SkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1885,7 +1906,7 @@ void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
}
}
-void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
+void SkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1894,7 +1915,7 @@ void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
}
}
-void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) {
+void SkyRD::sky_set_material(RID p_sky, RID p_material) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1903,7 +1924,7 @@ void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) {
}
}
-Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
+Ref<Image> SkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, Ref<Image>());
@@ -1912,7 +1933,7 @@ Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool
return sky->bake_panorama(p_energy, p_bake_irradiance ? roughness_layers : 0, p_size);
}
-RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const {
+RID SkyRD::sky_get_radiance_texture_rd(RID p_sky) const {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, RID());
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/environment/sky.h
index 83a8fe6e77..080165c112 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/environment/sky.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_sky_rd.h */
+/* sky.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,21 +28,24 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_SKY_RD_H
-#define RENDERING_SERVER_SCENE_SKY_RD_H
+#ifndef SKY_RD_H
+#define SKY_RD_H
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.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/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/environment/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;
-class RendererSceneSkyRD {
+namespace RendererRD {
+
+class SkyRD {
public:
enum SkySet {
SKY_SET_UNIFORMS,
@@ -63,7 +66,6 @@ public:
};
private:
- RendererStorageRD *storage = nullptr;
RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RID index_buffer;
@@ -105,7 +107,7 @@ private:
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
- struct SkyShaderData : public RendererRD::ShaderData {
+ struct SkyShaderData : public RendererRD::MaterialStorage::ShaderData {
bool valid = false;
RID version;
@@ -127,8 +129,9 @@ private:
bool uses_light = false;
virtual void set_code(const String &p_Code);
+ virtual void set_path_hint(const String &p_hint);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -140,7 +143,7 @@ private:
virtual ~SkyShaderData();
};
- void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier);
+ void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier);
public:
struct SkySceneState {
@@ -211,10 +214,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 */
@@ -228,7 +231,7 @@ public:
RID default_shader_rd;
} sky_shader;
- struct SkyMaterialData : public RendererRD::MaterialData {
+ struct SkyMaterialData : public RendererRD::MaterialStorage::MaterialData {
SkyShaderData *shader_data = nullptr;
RID uniform_set;
bool uniform_set_updated;
@@ -267,9 +270,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);
@@ -282,22 +285,22 @@ public:
mutable RID_Owner<Sky, true> sky_owner;
int roughness_layers;
- RendererRD::ShaderData *_create_sky_shader_func();
- static RendererRD::ShaderData *_create_sky_shader_funcs();
+ RendererRD::MaterialStorage::ShaderData *_create_sky_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_sky_shader_funcs();
- RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
- static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader);
+ RendererRD::MaterialStorage::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader);
- RendererSceneSkyRD();
- void init(RendererStorageRD *p_storage);
+ SkyRD();
+ void init();
void set_texture_format(RD::DataFormat p_texture_format);
- ~RendererSceneSkyRD();
+ ~SkyRD();
- void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
- void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
- void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer
- void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
- void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
+ void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer
+ void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();
@@ -316,4 +319,6 @@ public:
RID sky_get_radiance_texture_rd(RID p_sky) const;
};
-#endif /* RENDERING_SERVER_SCENE_SKY_RD_H */
+} // namespace RendererRD
+
+#endif // SKY_RD_H
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..8754e90647 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"
@@ -65,6 +66,13 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
}
specular = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ if (view_count == 1) {
+ specular_views[0] = specular;
+ } else {
+ for (uint32_t v = 0; v < view_count; v++) {
+ specular_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular, v, 0);
+ }
+ }
if (msaa == RS::VIEWPORT_MSAA_DISABLED) {
{
@@ -79,6 +87,14 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
specular_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ if (view_count == 1) {
+ specular_msaa_views[0] = specular_msaa;
+ } else {
+ for (uint32_t v = 0; v < view_count; v++) {
+ specular_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular_msaa, v, 0);
+ }
+ }
+
{
Vector<RID> fb;
fb.push_back(specular_msaa);
@@ -170,29 +186,26 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi()
}
void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
+ // note, slices are freed automatically when the parent texture is freed so we just clear them.
+ for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
+ color_views[v] = RID();
+ depth_views[v] = RID();
+ specular_views[v] = RID();
+ specular_msaa_views[v] = RID();
+ color_msaa_views[v] = RID();
+ depth_msaa_views[v] = RID();
+ normal_roughness_views[v] = RID();
+ normal_roughness_msaa_views[v] = RID();
+ voxelgi_views[v] = RID();
+ voxelgi_msaa_views[v] = RID();
+ vrs_views[v] = RID();
+ }
+
if (voxelgi_buffer != RID()) {
RD::get_singleton()->free(voxelgi_buffer);
voxelgi_buffer = RID();
- if (view_count == 1) {
- voxelgi_views[0] = RID();
- } else {
- for (uint32_t v = 0; v < view_count; v++) {
- RD::get_singleton()->free(voxelgi_views[v]);
- voxelgi_views[v] = RID();
- }
- }
-
if (voxelgi_buffer_msaa.is_valid()) {
- if (view_count == 1) {
- voxelgi_msaa_views[0] = RID();
- } else {
- for (uint32_t v = 0; v < view_count; v++) {
- RD::get_singleton()->free(voxelgi_msaa_views[v]);
- voxelgi_msaa_views[v] = RID();
- }
- }
-
RD::get_singleton()->free(voxelgi_buffer_msaa);
voxelgi_buffer_msaa = RID();
}
@@ -201,35 +214,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
}
if (color_msaa.is_valid()) {
- if (view_count == 1) {
- color_views[0] = RID();
- color_msaa_views[0] = RID();
- } else {
- for (uint32_t v = 0; v < view_count; v++) {
- RD::get_singleton()->free(color_views[v]);
- RD::get_singleton()->free(color_msaa_views[v]);
- color_views[v] = RID();
- color_msaa_views[v] = RID();
- }
- }
-
RD::get_singleton()->free(color_msaa);
color_msaa = RID();
}
if (depth_msaa.is_valid()) {
- if (view_count == 1) {
- depth_views[0] = RID();
- depth_msaa_views[0] = RID();
- } else {
- for (uint32_t v = 0; v < view_count; v++) {
- RD::get_singleton()->free(depth_views[v]);
- RD::get_singleton()->free(depth_msaa_views[v]);
- depth_views[v] = RID();
- depth_msaa_views[v] = RID();
- }
- }
-
RD::get_singleton()->free(depth_msaa);
depth_msaa = RID();
}
@@ -244,33 +233,17 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
}
color = RID();
+ color_only_fb = RID();
depth = RID();
depth_fb = RID();
color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations
if (normal_roughness_buffer.is_valid()) {
- if (view_count == 1) {
- normal_roughness_views[0] = RID();
- } else {
- for (uint32_t v = 0; v < view_count; v++) {
- RD::get_singleton()->free(normal_roughness_views[v]);
- normal_roughness_views[v] = RID();
- }
- }
-
RD::get_singleton()->free(normal_roughness_buffer);
normal_roughness_buffer = RID();
if (normal_roughness_buffer_msaa.is_valid()) {
- if (view_count == 1) {
- normal_roughness_msaa_views[0] = RID();
- } else {
- for (uint32_t v = 0; v < view_count; v++) {
- RD::get_singleton()->free(normal_roughness_msaa_views[v]);
- normal_roughness_msaa_views[v] = RID();
- }
- }
RD::get_singleton()->free(normal_roughness_buffer_msaa);
normal_roughness_buffer_msaa = RID();
}
@@ -293,11 +266,12 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
}
}
-void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) {
+void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) {
clear();
msaa = p_msaa;
use_taa = p_use_taa;
+ vrs = p_vrs_texture;
width = p_width;
height = p_height;
@@ -306,11 +280,26 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
color = p_color_buffer;
depth = p_depth_buffer;
+ if (vrs.is_valid()) {
+ if (view_count == 1) {
+ // just reuse
+ vrs_views[0] = vrs;
+ } else {
+ // create slices
+ for (uint32_t v = 0; v < view_count; v++) {
+ vrs_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), vrs, v, 0);
+ }
+ }
+ }
+
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
{
Vector<RID> fb;
fb.push_back(p_color_buffer);
fb.push_back(depth);
+ if (vrs.is_valid()) {
+ fb.push_back(vrs);
+ }
color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
@@ -345,7 +334,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());
@@ -370,6 +359,9 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
Vector<RID> fb;
fb.push_back(color_msaa);
fb.push_back(depth_msaa);
+ if (vrs.is_valid()) {
+ fb.push_back(vrs);
+ }
color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
@@ -408,6 +400,10 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(
fb.push_back(use_msaa ? depth_msaa : depth);
+ if (vrs.is_valid()) {
+ fb.push_back(vrs);
+ }
+
int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1;
RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count);
color_framebuffers[p_color_pass_flags] = framebuffer;
@@ -435,7 +431,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 +444,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());
@@ -779,7 +775,7 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
void RenderForwardClustered::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
uint32_t render_total = p_params->element_count;
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t render_from = p_thread * render_total / total_threads;
uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads);
_render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to);
@@ -791,9 +787,10 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p
if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardClustered::_render_list_thread_function, p_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardClustered::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardClusteredRenderList"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
RD::get_singleton()->draw_list_end(p_params->barrier);
} else {
//single threaded
@@ -804,23 +801,23 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p
}
void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) {
- //CameraMatrix projection = p_render_data->cam_projection;
+ //Projection projection = p_render_data->cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(p_flip_y);
correction.add_jitter_offset(p_render_data->taa_jitter);
- CameraMatrix projection = correction * p_render_data->cam_projection;
+ Projection 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 +833,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;
@@ -926,7 +923,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.use_ambient_cubemap = false;
} else {
float energy = environment_get_ambient_light_energy(p_render_data->environment);
- Color color = environment_get_ambient_light_color(p_render_data->environment);
+ Color color = environment_get_ambient_light(p_render_data->environment);
color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * energy;
@@ -934,7 +931,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;
@@ -948,16 +945,16 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.use_reflection_cubemap = false;
}
- scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment);
- scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment);
+ scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_channel_affect(p_render_data->environment);
+ scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment);
uint32_t ss_flags = 0;
if (p_opaque_render_buffers) {
- ss_flags |= environment_is_ssao_enabled(p_render_data->environment) ? 1 : 0;
- ss_flags |= environment_is_ssil_enabled(p_render_data->environment) ? 2 : 0;
+ ss_flags |= environment_get_ssao_enabled(p_render_data->environment) ? 1 : 0;
+ ss_flags |= environment_get_ssil_enabled(p_render_data->environment) ? 2 : 0;
}
scene_state.ubo.ss_effects_flags = ss_flags;
- scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_render_data->environment);
+ scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment);
scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
@@ -999,21 +996,21 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
if (render_buffers->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
memcpy(&scene_state.prev_ubo, &scene_state.ubo, sizeof(SceneState::UBO));
- CameraMatrix prev_correction;
+ Projection prev_correction;
prev_correction.set_depth_correction(true);
prev_correction.add_jitter_offset(p_render_data->prev_taa_jitter);
- CameraMatrix prev_projection = prev_correction * p_render_data->prev_cam_projection;
+ Projection 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,17 +1066,17 @@ 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;
instance_data.gi_offset = inst->gi_offset_cache;
instance_data.layer_mask = inst->layer_mask;
- instance_data.instance_uniforms_ofs = uint32_t(inst->shader_parameters_offset);
+ instance_data.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset);
instance_data.lightmap_uv_scale[0] = inst->lightmap_uv_scale.position.x;
instance_data.lightmap_uv_scale[1] = inst->lightmap_uv_scale.position.y;
instance_data.lightmap_uv_scale[2] = inst->lightmap_uv_scale.size.x;
@@ -1397,7 +1394,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);
@@ -1413,7 +1410,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (p_render_data->render_buffers.is_valid()) {
render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
}
- RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 };
//first of all, make a new render pass
@@ -1438,7 +1434,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_sdfgi = false;
bool using_voxelgi = false;
bool reverse_cull = false;
- bool using_ssil = p_render_data->environment.is_valid() && environment_is_ssil_enabled(p_render_data->environment);
+ bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment);
if (render_buffer) {
screen_size.x = render_buffer->width;
@@ -1452,21 +1448,21 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
using_voxelgi = true;
}
- if (!p_render_data->environment.is_valid() && using_voxelgi) {
+ if (p_render_data->environment.is_null() && using_voxelgi) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI;
- } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) {
- if (environment_is_sdfgi_enabled(p_render_data->environment)) {
+ } else if (p_render_data->environment.is_valid() && (environment_get_ssr_enabled(p_render_data->environment) || environment_get_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) {
+ if (environment_get_sdfgi_enabled(p_render_data->environment)) {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi
using_sdfgi = true;
} else {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
- if (environment_is_ssr_enabled(p_render_data->environment)) {
+ if (environment_get_ssr_enabled(p_render_data->environment)) {
using_separate_specular = true;
using_ssr = true;
color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
}
- } else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
+ } else if (p_render_data->environment.is_valid() && (environment_get_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
@@ -1507,7 +1503,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
- env = nullptr;
}
reverse_cull = true; // for some reason our views are inverted
@@ -1559,7 +1554,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy;
clear_color.g *= bg_energy;
clear_color.b *= bg_energy;
- if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_fog_enabled(p_render_data->environment)) {
+ if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -1569,7 +1564,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy;
clear_color.g *= bg_energy;
clear_color.b *= bg_energy;
- if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_fog_enabled(p_render_data->environment)) {
+ if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -1592,18 +1587,18 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
- CameraMatrix projection = p_render_data->cam_projection;
+ Projection projection = p_render_data->cam_projection;
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
projection = correction * p_render_data->cam_projection;
}
- sky.setup(env, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
+ sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
- RID sky_rid = env->sky;
+ RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
- sky.update(env, projection, p_render_data->cam_transform, time);
+ sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time);
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@@ -1619,7 +1614,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid();
- bool using_ssao = depth_pre_pass && p_render_data->render_buffers.is_valid() && p_render_data->environment.is_valid() && environment_is_ssao_enabled(p_render_data->environment);
+ bool using_ssao = depth_pre_pass && p_render_data->render_buffers.is_valid() && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment);
bool continue_depth = false;
if (depth_pre_pass) { //depth pre pass
@@ -1672,8 +1667,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
continue_depth = !finish_depth;
}
- RID null_rids[2];
- _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : null_rids, render_buffer ? render_buffer->voxelgi_buffer : RID());
+ RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS];
+ _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : nullrids, render_buffer ? render_buffer->voxelgi_buffer : RID(), render_buffer ? render_buffer->vrs_views : nullrids);
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
@@ -1723,9 +1718,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
- CameraMatrix dc;
+ Projection dc;
dc.set_depth_correction(true);
- CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
+ Projection cm = (dc * p_render_data->cam_projection) * Projection(p_render_data->cam_transform.affine_inverse());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs");
for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) {
@@ -1740,11 +1735,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
- CameraMatrix dc;
+ Projection dc;
dc.set_depth_correction(true);
- CameraMatrix cms[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection cms[RendererSceneRender::MAX_RENDER_VIEWS];
for (uint32_t v = 0; v < p_render_data->view_count; v++) {
- cms[v] = (dc * p_render_data->view_projection[v]) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
+ cms[v] = (dc * p_render_data->view_projection[v]) * Projection(p_render_data->cam_transform.affine_inverse());
}
_debug_sdfgi_probes(p_render_data->render_buffers, color_only_framebuffer, p_render_data->view_count, cms, will_continue_color, will_continue_depth);
}
@@ -1755,12 +1750,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Draw Sky");
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ Projection projection = correction * p_render_data->cam_projection;
+ sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
} else {
- sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
}
RD::get_singleton()->draw_command_end_label();
}
@@ -1770,9 +1765,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
for (uint32_t v = 0; v < render_buffer->view_count; v++) {
RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa_views[v], render_buffer->color_views[v]);
}
- // TODO mame this do multiview
if (using_separate_specular) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular);
+ for (uint32_t v = 0; v < render_buffer->view_count; v++) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa_views[v], render_buffer->specular_views[v]);
+ }
}
}
@@ -1793,12 +1789,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (using_ssr) {
RENDER_TIMESTAMP("Screen-Space Reflections");
RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections");
- _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
+ _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_views, render_buffer->specular, render_buffer->specular_views, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->view_projection, p_render_data->view_eye_offset, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
RD::get_singleton()->draw_command_end_label();
} 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());
+ copy_effects->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID(), p_render_data->view_count);
}
}
@@ -1875,7 +1871,7 @@ void RenderForwardClustered::_render_shadow_begin() {
scene_state.instance_data[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
+void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -1965,7 +1961,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
+void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
@@ -2004,7 +2000,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
@@ -2053,7 +2049,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
RD::get_singleton()->draw_command_begin_label("Render UV2");
@@ -2123,7 +2119,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
RENDER_TIMESTAMP("Render SDFGI");
RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel");
@@ -2189,7 +2185,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());
@@ -2269,15 +2265,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
case RS::DECAL_FILTER_NEAREST: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
- case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- } break;
case RS::DECAL_FILTER_LINEAR: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -2296,15 +2295,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
- case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -2385,7 +2387,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2437,7 +2439,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (p_radiance_texture.is_valid()) {
radiance_texture = p_radiance_texture;
} else {
- radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
}
RD::Uniform u;
u.binding = 2;
@@ -2454,7 +2456,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (ref_texture.is_valid()) {
u.append_id(ref_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
}
uniforms.push_back(u);
}
@@ -2468,7 +2470,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
}
if (!texture.is_valid()) {
- texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
}
u.append_id(texture);
uniforms.push_back(u);
@@ -2480,7 +2482,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
u.append_id(directional_shadow_get_texture());
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH));
}
uniforms.push_back(u);
}
@@ -2489,7 +2491,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
if (p_render_data && i < p_render_data->lightmaps->size()) {
RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
@@ -2507,7 +2509,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) {
RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]);
@@ -2537,7 +2539,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
- RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2546,7 +2548,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
- RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2556,7 +2558,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL);
+ RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_NORMAL);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2566,7 +2568,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID();
- RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2576,7 +2578,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID();
- RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2586,7 +2588,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 14;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID();
- RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2598,7 +2600,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers);
} else {
- t = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ t = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
}
u.append_id(t);
uniforms.push_back(u);
@@ -2610,7 +2612,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers));
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
uniforms.push_back(u);
}
@@ -2629,10 +2631,10 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) {
vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers);
if (vfog.is_null()) {
- vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
}
} else {
- vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
}
u.append_id(vfog);
uniforms.push_back(u);
@@ -2642,7 +2644,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 19;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID();
- RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2666,12 +2668,16 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 1;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(scene_state.instance_buffer[RENDER_LIST_SECONDARY]);
+ RID instance_buffer = scene_state.instance_buffer[RENDER_LIST_SECONDARY];
+ if (instance_buffer == RID()) {
+ instance_buffer = scene_shader.default_vec4_xform_buffer; // any buffer will do since its not used
+ }
+ u.append_id(instance_buffer);
uniforms.push_back(u);
}
{
// No radiance texture.
- RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
RD::Uniform u;
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
@@ -2681,7 +2687,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
{
// No reflection atlas.
- RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+ RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
RD::Uniform u;
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
@@ -2694,7 +2700,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2704,7 +2710,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2715,7 +2721,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
u.append_id(default_tex);
}
@@ -2729,7 +2735,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
u.append_id(default_tex);
}
@@ -2794,24 +2800,23 @@ RID RenderForwardClustered::_render_buffers_get_velocity_texture(RID p_render_bu
RenderForwardClustered *RenderForwardClustered::singleton = nullptr;
-void RenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- if (ginstance->dirty_list_element.in_list()) {
+void RenderForwardClustered::GeometryInstanceForwardClustered::_mark_dirty() {
+ if (dirty_list_element.in_list()) {
return;
}
//clear surface caches
- GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
+ GeometryInstanceSurfaceDataCache *surf = surface_caches;
while (surf) {
GeometryInstanceSurfaceDataCache *next = surf->next;
- geometry_instance_surface_alloc.free(surf);
+ RenderForwardClustered::get_singleton()->geometry_instance_surface_alloc.free(surf);
surf = next;
}
- ginstance->surface_caches = nullptr;
+ surface_caches = nullptr;
- geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
+ RenderForwardClustered::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element);
}
void RenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
@@ -2865,7 +2870,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
void *surface_shadow = nullptr;
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
+ material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
@@ -2888,7 +2893,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
@@ -2926,7 +2931,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
break;
}
@@ -2946,7 +2951,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
SceneShaderForwardClustered::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2957,7 +2962,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
m_src = scene_shader.default_material;
}
@@ -2968,7 +2973,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
@@ -2979,7 +2984,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
}
}
-void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
@@ -3131,16 +3136,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: {
- static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ 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<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
} 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 +3156,12 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora
} break;
}
}
-void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
- static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
}
-RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) {
- RS::InstanceType type = storage->get_base_type(p_base);
+RenderGeometryInstance *RenderForwardClustered::geometry_instance_create(RID 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();
@@ -3168,155 +3173,47 @@ RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance
ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed;
ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted;
- _geometry_instance_mark_dirty(ginstance);
+ ginstance->_mark_dirty();
return ginstance;
}
-void RenderForwardClustered::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->skeleton = p_skeleton;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_override = p_override;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_overlay = p_overlay;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->surface_materials = p_materials;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->mesh_instance = p_mesh_instance;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) {
uint64_t frame = RSG::rasterizer->get_frame_number();
- if (frame != ginstance->prev_transform_change_frame) {
- ginstance->prev_transform = ginstance->transform;
- ginstance->prev_transform_change_frame = frame;
- ginstance->prev_transform_dirty = true;
+ if (frame != prev_transform_change_frame) {
+ prev_transform = transform;
+ prev_transform_change_frame = frame;
+ prev_transform_dirty = true;
}
- ginstance->transform = p_transform;
- ginstance->mirror = p_transform.basis.determinant() < 0;
- ginstance->data->aabb = p_aabb;
- ginstance->transformed_aabb = p_transformed_aabb;
-
- Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
- // handle non uniform scale here
- float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
- float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
-
- ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
-
- ginstance->lod_model_scale = max_scale;
-}
-void RenderForwardClustered::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lod_bias = p_lod_bias;
-}
-void RenderForwardClustered::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->fade_near = p_enable_near;
- ginstance->fade_near_begin = p_near_begin;
- ginstance->fade_near_end = p_near_end;
- ginstance->fade_far = p_enable_far;
- ginstance->fade_far_begin = p_far_begin;
- ginstance->fade_far_end = p_far_end;
+ RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabbb);
}
-void RenderForwardClustered::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->parent_fade_alpha = p_alpha;
-}
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+ lightmap_instance = p_lightmap_instance;
+ lightmap_uv_scale = p_lightmap_uv_scale;
+ lightmap_slice_index = p_lightmap_slice_index;
-void RenderForwardClustered::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1);
+ _mark_dirty();
}
-void RenderForwardClustered::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_baked_light = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_dynamic_gi = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lightmap_instance = p_lightmap_instance;
- ginstance->lightmap_uv_scale = p_lightmap_uv_scale;
- ginstance->lightmap_slice_index = p_lightmap_slice_index;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_lightmap_capture(const Color *p_sh9) {
if (p_sh9) {
- if (ginstance->lightmap_sh == nullptr) {
- ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc();
+ if (lightmap_sh == nullptr) {
+ lightmap_sh = RenderForwardClustered::get_singleton()->geometry_instance_lightmap_sh.alloc();
}
- memcpy(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
+ memcpy(lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
} else {
- if (ginstance->lightmap_sh != nullptr) {
- geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
- ginstance->lightmap_sh = nullptr;
+ if (lightmap_sh != nullptr) {
+ RenderForwardClustered::get_singleton()->geometry_instance_lightmap_sh.free(lightmap_sh);
+ lightmap_sh = nullptr;
}
}
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->shader_parameters_offset = p_offset;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->data->cast_double_sided_shadows = p_enable;
- _geometry_instance_mark_dirty(ginstance);
+ _mark_dirty();
}
-void RenderForwardClustered::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->layer_mask = p_layer_mask;
-}
-
-void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+void RenderForwardClustered::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
if (ginstance->lightmap_sh != nullptr) {
@@ -3335,47 +3232,25 @@ void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry
uint32_t RenderForwardClustered::geometry_instance_get_pair_mask() {
return (1 << RS::INSTANCE_VOXEL_GI);
}
-void RenderForwardClustered::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
-}
-void RenderForwardClustered::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
-}
-void RenderForwardClustered::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
-}
-
-Transform3D RenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, Transform3D());
- return ginstance->transform;
-}
-
-AABB RenderForwardClustered::geometry_instance_get_aabb(GeometryInstance *p_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, AABB());
- return ginstance->data->aabb;
-}
-void RenderForwardClustered::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
if (p_voxel_gi_instance_count > 0) {
- ginstance->voxel_gi_instances[0] = p_voxel_gi_instances[0];
+ voxel_gi_instances[0] = p_voxel_gi_instances[0];
} else {
- ginstance->voxel_gi_instances[0] = RID();
+ voxel_gi_instances[0] = RID();
}
if (p_voxel_gi_instance_count > 1) {
- ginstance->voxel_gi_instances[1] = p_voxel_gi_instances[1];
+ voxel_gi_instances[1] = p_voxel_gi_instances[1];
} else {
- ginstance->voxel_gi_instances[1] = RID();
+ voxel_gi_instances[1] = RID();
}
}
-void RenderForwardClustered::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->using_projectors = p_projector;
- ginstance->using_softshadows = p_softshadow;
- _geometry_instance_mark_dirty(ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) {
+ using_projectors = p_projector;
+ using_softshadows = p_softshadow;
+ _mark_dirty();
}
void RenderForwardClustered::_update_shader_quality_settings() {
@@ -3406,12 +3281,18 @@ void RenderForwardClustered::_update_shader_quality_settings() {
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
sc.constant_id = SPEC_CONSTANT_DECAL_FILTER;
- sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER;
- sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
@@ -3420,8 +3301,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 +3333,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..7e71406af8 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -28,16 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
-#define RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
+#ifndef RENDER_FORWARD_CLUSTERED_H
+#define RENDER_FORWARD_CLUSTERED_H
#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_rd/effects/resolve.h"
#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 {
@@ -107,26 +107,32 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID depth_normal_roughness_voxelgi_fb;
RID color_only_fb;
RID specular_only_fb;
+
+ RID vrs;
+
int width, height;
HashMap<uint32_t, RID> color_framebuffers;
// for multiview
- uint32_t view_count;
+ uint32_t view_count = 1;
RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
+ RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS];
+ RID specular_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID depth_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
+ RID vrs_views[RendererSceneRender::MAX_RENDER_VIEWS];
RID render_sdfgi_uniform_set;
void ensure_specular();
void ensure_voxelgi();
void ensure_velocity();
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
RID get_color_pass_fb(uint32_t p_color_pass_flags);
~RenderBufferDataForwardClustered();
@@ -421,7 +427,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
HashMap<Size2i, RID> sdfgi_framebuffer_size_cache;
struct GeometryInstanceData;
- struct GeometryInstanceForwardClustered;
+ class GeometryInstanceForwardClustered;
struct GeometryInstanceLightmapSH {
Color sh[9];
@@ -481,77 +487,52 @@ class RenderForwardClustered : public RendererSceneRenderRD {
GeometryInstanceForwardClustered *owner = nullptr;
};
- struct GeometryInstanceForwardClustered : public GeometryInstance {
+ class GeometryInstanceForwardClustered : public RenderGeometryInstanceBase {
+ public:
+ // lightmap
+ RID lightmap_instance;
+ Rect2 lightmap_uv_scale;
+ uint32_t lightmap_slice_index;
+ GeometryInstanceLightmapSH *lightmap_sh = nullptr;
+
//used during rendering
- bool mirror = false;
- bool non_uniform_scale = false;
- float lod_bias = 0.0;
- float lod_model_scale = 1.0;
- AABB transformed_aabb; //needed for LOD
- float depth = 0;
+
uint32_t gi_offset_cache = 0;
- uint32_t flags_cache = 0;
bool store_transform_cache = true;
- int32_t shader_parameters_offset = -1;
- uint32_t lightmap_slice_index;
- Rect2 lightmap_uv_scale;
- uint32_t layer_mask = 1;
RID transforms_uniform_set;
uint32_t instance_count = 0;
uint32_t trail_steps = 1;
- RID mesh_instance;
bool can_sdfgi = false;
bool using_projectors = false;
bool using_softshadows = false;
- bool fade_near = false;
- float fade_near_begin = 0;
- float fade_near_end = 0;
- bool fade_far = false;
- float fade_far_begin = 0;
- float fade_far_end = 0;
- float force_alpha = 1.0;
- float parent_fade_alpha = 1.0;
//used during setup
- uint32_t base_flags = 0;
uint64_t prev_transform_change_frame = 0xFFFFFFFF;
bool prev_transform_dirty = true;
- Transform3D transform;
Transform3D prev_transform;
RID voxel_gi_instances[MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE];
- RID lightmap_instance;
- GeometryInstanceLightmapSH *lightmap_sh = nullptr;
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
SelfList<GeometryInstanceForwardClustered> dirty_list_element;
- struct Data {
- //data used less often goes into regular heap
- RID base;
- RS::InstanceType base_type;
-
- RID skeleton;
- Vector<RID> surface_materials;
- RID material_override;
- RID material_overlay;
- AABB aabb;
+ GeometryInstanceForwardClustered() :
+ dirty_list_element(this) {}
- bool use_dynamic_gi = false;
- bool use_baked_light = true;
- bool cast_double_sided_shadows = false;
- bool mirror = false;
- bool dirty_dependencies = false;
+ virtual void _mark_dirty() override;
- RendererStorage::DependencyTracker dependency_tracker;
- };
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override;
+ virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
+ virtual void set_lightmap_capture(const Color *p_sh9) override;
- Data *data = nullptr;
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override {}
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
- GeometryInstanceForwardClustered() :
- dirty_list_element(this) {}
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) 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<GeometryInstanceForwardClustered>::List geometry_instance_dirty_list;
@@ -562,8 +543,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
- void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
- void _geometry_instance_update(GeometryInstance *p_geometry_instance);
+ void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
/* Render List */
@@ -634,57 +614,33 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
virtual void _render_shadow_begin() override;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
public:
+ static RenderForwardClustered *get_singleton() { return singleton; }
+
_FORCE_INLINE_ virtual void update_uniform_sets() override {
base_uniform_set_updated = true;
_update_render_base_uniform_set();
}
- virtual GeometryInstance *geometry_instance_create(RID p_base) override;
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
- virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override;
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
- virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
- virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
- virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+ virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
virtual uint32_t geometry_instance_get_pair_mask() override;
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
-
- virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
virtual bool free(RID p_rid) override;
- RenderForwardClustered(RendererStorageRD *p_storage);
+ RenderForwardClustered();
~RenderForwardClustered();
};
} // namespace RendererSceneRenderImplementation
-#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
+
+#endif // RENDER_FORWARD_CLUSTERED_H
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..556db086b2 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
@@ -37,6 +37,10 @@
using namespace RendererSceneRenderImplementation;
+void SceneShaderForwardClustered::ShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
//compile
@@ -388,7 +392,7 @@ void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const St
}
}
-void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SceneShaderForwardClustered::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -403,7 +407,22 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo>
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -469,7 +488,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() {
}
}
-RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
+RendererRD::MaterialStorage::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -493,7 +512,7 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -520,9 +539,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;
@@ -592,8 +610,8 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
@@ -664,7 +682,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["OUTPUT_IS_SRGB"] = "true";
- actions.renames["FOG"] = "custom_fog";
+ actions.renames["FOG"] = "fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
actions.renames["BONE_INDICES"] = "bone_attrib";
@@ -675,6 +693,11 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz";
+ actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
+ actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz";
+ actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz";
+
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
@@ -770,7 +793,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs";
compiler.initialize(actions);
@@ -799,7 +822,7 @@ void fragment() {
material_storage->material_initialize(default_material);
material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D));
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF);
@@ -827,7 +850,7 @@ void fragment() {
material_storage->material_initialize(overdraw_material);
material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D));
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
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..fa9ebde1b2 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
@@ -28,11 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RSSR_SCENE_SHADER_FC_H
-#define RSSR_SCENE_SHADER_FC_H
+#ifndef SCENE_SHADER_FORWARD_CLUSTERED_H
+#define SCENE_SHADER_FORWARD_CLUSTERED_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,
@@ -96,7 +93,7 @@ public:
SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3,
};
- struct ShaderData : public RendererRD::ShaderData {
+ struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -183,8 +180,9 @@ public:
uint32_t index = 0;
virtual void set_code(const String &p_Code);
+ virtual void set_path_hint(const String &p_path);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -200,12 +198,12 @@ public:
SelfList<ShaderData>::List shader_list;
- RendererRD::ShaderData *_create_shader_func();
- static RendererRD::ShaderData *_create_shader_funcs() {
+ RendererRD::MaterialStorage::ShaderData *_create_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererRD::MaterialData {
+ struct MaterialData : public RendererRD::MaterialStorage::MaterialData {
ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
@@ -218,8 +216,8 @@ public:
virtual ~MaterialData();
};
- RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+ RendererRD::MaterialStorage::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
@@ -249,9 +247,10 @@ 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);
};
} // namespace RendererSceneRenderImplementation
-#endif // !RSSR_SCENE_SHADER_FM_H
+
+#endif // SCENE_SHADER_FORWARD_CLUSTERED_H
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..ffd47cc163 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -87,10 +87,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
}
}
-void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) {
+void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) {
clear();
msaa = p_msaa;
+ vrs = p_vrs_texture;
Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer);
@@ -108,6 +109,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
Vector<RID> fb;
fb.push_back(p_color_buffer); // 0 - color buffer
fb.push_back(depth); // 1 - depth buffer
+ if (vrs.is_valid()) {
+ fb.push_back(vrs); // 2 - vrs texture
+ }
// Now define our subpasses
Vector<RD::FramebufferPass> passes;
@@ -116,6 +120,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
// re-using the same attachments
pass.color_attachments.push_back(0);
pass.depth_attachment = 1;
+ if (vrs.is_valid()) {
+ pass.vrs_attachment = 2;
+ }
// - opaque pass
passes.push_back(pass);
@@ -131,12 +138,13 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
if (!is_scaled) {
// - add blit to 2D pass
- fb.push_back(p_target_buffer); // 2 - target buffer
+ int target_buffer_id = fb.size();
+ fb.push_back(p_target_buffer); // 2/3 - target buffer
RD::FramebufferPass blit_pass;
- blit_pass.color_attachments.push_back(2);
+ blit_pass.color_attachments.push_back(target_buffer_id);
blit_pass.input_attachments.push_back(0);
- passes.push_back(blit_pass);
+ passes.push_back(blit_pass); // this doesn't need VRS
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
} else {
@@ -179,6 +187,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
Vector<RID> fb;
fb.push_back(color_msaa); // 0 - msaa color buffer
fb.push_back(depth_msaa); // 1 - msaa depth buffer
+ if (vrs.is_valid()) {
+ fb.push_back(vrs); // 2 - vrs texture
+ }
// Now define our subpasses
Vector<RD::FramebufferPass> passes;
@@ -187,18 +198,22 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
// re-using the same attachments
pass.color_attachments.push_back(0);
pass.depth_attachment = 1;
+ if (vrs.is_valid()) {
+ pass.vrs_attachment = 2;
+ }
// - opaque pass
passes.push_back(pass);
// - add sky pass
- fb.push_back(color); // 2 - color buffer
+ int color_buffer_id = fb.size();
+ fb.push_back(color); // color buffer
passes.push_back(pass); // without resolve for our 3 + 4 subpass config
{
// but with resolve for our 2 subpass config
Vector<RD::FramebufferPass> two_passes;
two_passes.push_back(pass); // opaque subpass without resolve
- pass.resolve_attachments.push_back(2);
+ pass.resolve_attachments.push_back(color_buffer_id);
two_passes.push_back(pass); // sky subpass with resolve
color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count);
@@ -217,10 +232,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
if (!is_scaled) {
// - add blit to 2D pass
- fb.push_back(p_target_buffer); // 3 - target buffer
+ int target_buffer_id = fb.size();
+ fb.push_back(p_target_buffer); // target buffer
RD::FramebufferPass blit_pass;
- blit_pass.color_attachments.push_back(3);
- blit_pass.input_attachments.push_back(2);
+ blit_pass.color_attachments.push_back(target_buffer_id);
+ blit_pass.input_attachments.push_back(color_buffer_id);
passes.push_back(blit_pass);
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
@@ -321,7 +337,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
if (p_radiance_texture.is_valid()) {
radiance_texture = p_radiance_texture;
} else {
- radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
}
RD::Uniform u;
u.binding = 2;
@@ -338,7 +354,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
if (ref_texture.is_valid()) {
u.append_id(ref_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
}
uniforms.push_back(u);
}
@@ -352,7 +368,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
}
if (!texture.is_valid()) {
- texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
}
u.append_id(texture);
uniforms.push_back(u);
@@ -364,7 +380,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
u.append_id(directional_shadow_get_texture());
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH));
}
uniforms.push_back(u);
}
@@ -375,7 +391,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
if (p_render_data && i < p_render_data->lightmaps->size()) {
RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
@@ -396,7 +412,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
if (i < (int)p_voxel_gi_instances.size()) {
RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]);
@@ -427,7 +443,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
- RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -436,7 +452,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
- RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -465,7 +481,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);
@@ -481,7 +497,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (p_render_data->render_buffers.is_valid()) {
render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
}
- RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
RENDER_TIMESTAMP("Setup 3D Scene");
@@ -524,7 +539,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) {
// can't do blit subpass
using_subpass_post_process = false;
- } else if (env && (env->glow_enabled || env->auto_exposure || camera_effects_uses_dof(p_render_data->camera_effects))) {
+ } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || environment_get_auto_exposure(p_render_data->environment) || camera_effects_uses_dof(p_render_data->camera_effects))) {
// can't do blit subpass
using_subpass_post_process = false;
}
@@ -554,7 +569,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
- env = nullptr;
}
reverse_cull = true;
@@ -596,7 +610,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color.g *= bg_energy;
clear_color.b *= bg_energy;
/*
- if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
+ if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -608,7 +622,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color.g *= bg_energy;
clear_color.b *= bg_energy;
/*
- if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
+ if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -632,18 +646,18 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
- CameraMatrix projection = p_render_data->cam_projection;
+ Projection projection = p_render_data->cam_projection;
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
projection = correction * p_render_data->cam_projection;
}
- sky.setup(env, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
+ sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
- RID sky_rid = env->sky;
+ RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
- sky.update(env, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
+ sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@@ -664,19 +678,19 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers");
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.update_res_buffers(env, 1, &projection, p_render_data->cam_transform, time);
+ Projection projection = correction * p_render_data->cam_projection;
+ sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->cam_transform, time);
} else {
- sky.update_res_buffers(env, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.update_res_buffers(p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
}
RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
}
- RID null_rids[2];
- _pre_opaque_render(p_render_data, false, false, false, null_rids, RID());
+ RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS];
+ _pre_opaque_render(p_render_data, false, false, false, nullrids, RID(), nullrids);
uint32_t spec_constant_base_flags = 0;
@@ -691,7 +705,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS;
}
- if (!is_environment(p_render_data->environment) || environment_is_fog_enabled(p_render_data->environment)) {
+ if (!is_environment(p_render_data->environment) || environment_get_fog_enabled(p_render_data->environment)) {
spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG;
}
}
@@ -742,9 +756,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderList"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
} else {
//single threaded
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
@@ -760,12 +777,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
+ Projection projection = correction * p_render_data->cam_projection;
+ sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
} else {
- sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
+ sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
}
RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass
@@ -806,10 +823,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_switch_to_next_pass_split(thread_draw_lists.size(), thread_draw_lists.ptr());
render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass();
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
} else {
//single threaded
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
@@ -843,9 +862,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
} else {
//single threaded
@@ -884,7 +905,7 @@ void RenderForwardMobile::_render_shadow_begin() {
render_list[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
+void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -978,7 +999,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
/* */
-void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
@@ -1024,7 +1045,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
RD::get_singleton()->draw_command_begin_label("Render UV2");
@@ -1091,11 +1112,11 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
// we don't do GI in low end..
}
-void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
+void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
@@ -1193,15 +1214,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
case RS::DECAL_FILTER_NEAREST: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
- case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- } break;
case RS::DECAL_FILTER_LINEAR: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -1220,15 +1244,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
- case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -1309,7 +1336,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1527,22 +1554,22 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
// This populates our UBO with main scene data that is pushed into set 1
- //CameraMatrix projection = p_render_data->cam_projection;
+ //Projection projection = p_render_data->cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(p_flip_y);
- CameraMatrix projection = correction * p_render_data->cam_projection;
+ Projection 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 +1582,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;
@@ -1640,7 +1667,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.use_ambient_cubemap = false;
} else {
float energy = environment_get_ambient_light_energy(p_render_data->environment);
- Color color = environment_get_ambient_light_color(p_render_data->environment);
+ Color color = environment_get_ambient_light(p_render_data->environment);
color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * energy;
@@ -1648,7 +1675,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;
@@ -1662,11 +1689,11 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.use_reflection_cubemap = false;
}
- scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_is_ssao_enabled(p_render_data->environment);
- scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment);
- scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment);
+ scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_get_ssao_enabled(p_render_data->environment);
+ scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_channel_affect(p_render_data->environment);
+ scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment);
- scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_render_data->environment);
+ scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment);
scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
@@ -1755,7 +1782,7 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list,
void RenderForwardMobile::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
uint32_t render_total = p_params->element_count;
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t render_from = p_thread * render_total / total_threads;
uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads);
_render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to);
@@ -1767,9 +1794,11 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para
if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, p_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
RD::get_singleton()->draw_list_end(p_params->barrier);
} else {
//single threaded
@@ -1866,15 +1895,15 @@ 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;
push_constant.gi_offset = inst->gi_offset_cache;
push_constant.layer_mask = inst->layer_mask;
- push_constant.instance_uniforms_ofs = uint32_t(inst->shader_parameters_offset);
+ push_constant.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset);
if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
// abuse lightmap_uv_scale[0] here, should not be needed here
@@ -2031,8 +2060,8 @@ 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);
+RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID 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();
@@ -2041,165 +2070,36 @@ RendererSceneRender::GeometryInstance *RenderForwardMobile::geometry_instance_cr
ginstance->data->base = p_base;
ginstance->data->base_type = type;
- _geometry_instance_mark_dirty(ginstance);
+ ginstance->_mark_dirty();
return ginstance;
}
-void RenderForwardMobile::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->skeleton = p_skeleton;
+void RenderForwardMobile::GeometryInstanceForwardMobile::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+ lightmap_instance = p_lightmap_instance;
+ lightmap_uv_scale = p_lightmap_uv_scale;
+ lightmap_slice_index = p_lightmap_slice_index;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
+ _mark_dirty();
}
-void RenderForwardMobile::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_override = p_override;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_overlay = p_overlay;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->surface_materials = p_materials;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->mesh_instance = p_mesh_instance;
-
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->transform = p_transform;
- ginstance->mirror = p_transform.basis.determinant() < 0;
- ginstance->data->aabb = p_aabb;
- ginstance->transformed_aabb = p_transformed_aabb;
-
- Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
- // handle non uniform scale here
-
- float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
- float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
- ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
-
- ginstance->lod_model_scale = max_scale;
-}
-
-void RenderForwardMobile::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->layer_mask = p_layer_mask;
-}
-
-void RenderForwardMobile::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lod_bias = p_lod_bias;
-}
-
-void RenderForwardMobile::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
-}
-
-void RenderForwardMobile::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
-}
-
-void RenderForwardMobile::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
-}
-
-void RenderForwardMobile::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_baked_light = p_enable;
-
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
- // !BAS! do we support this in mobile?
- // GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- // ERR_FAIL_COND(!ginstance);
- // ginstance->data->use_dynamic_gi = p_enable;
- // _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lightmap_instance = p_lightmap_instance;
- ginstance->lightmap_uv_scale = p_lightmap_uv_scale;
- ginstance->lightmap_slice_index = p_lightmap_slice_index;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardMobile::GeometryInstanceForwardMobile::set_lightmap_capture(const Color *p_sh9) {
if (p_sh9) {
- if (ginstance->lightmap_sh == nullptr) {
- ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc();
+ if (lightmap_sh == nullptr) {
+ lightmap_sh = RenderForwardMobile::get_singleton()->geometry_instance_lightmap_sh.alloc();
}
- memcpy(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
+ memcpy(lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
} else {
- if (ginstance->lightmap_sh != nullptr) {
- geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
- ginstance->lightmap_sh = nullptr;
+ if (lightmap_sh != nullptr) {
+ RenderForwardMobile::get_singleton()->geometry_instance_lightmap_sh.free(lightmap_sh);
+ lightmap_sh = nullptr;
}
}
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->shader_parameters_offset = p_offset;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->data->cast_double_sided_shadows = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-Transform3D RenderForwardMobile::geometry_instance_get_transform(GeometryInstance *p_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, Transform3D());
- return ginstance->transform;
-}
-
-AABB RenderForwardMobile::geometry_instance_get_aabb(GeometryInstance *p_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, AABB());
- return ginstance->data->aabb;
+ _mark_dirty();
}
-void RenderForwardMobile::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+void RenderForwardMobile::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
if (ginstance->lightmap_sh != nullptr) {
@@ -2219,26 +2119,23 @@ uint32_t RenderForwardMobile::geometry_instance_get_pair_mask() {
return ((1 << RS::INSTANCE_LIGHT) + (1 << RS::INSTANCE_REFLECTION_PROBE) + (1 << RS::INSTANCE_DECAL));
}
-void RenderForwardMobile::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->omni_light_count = 0;
- ginstance->spot_light_count = 0;
+void RenderForwardMobile::GeometryInstanceForwardMobile::pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) {
+ omni_light_count = 0;
+ spot_light_count = 0;
for (uint32_t i = 0; i < p_light_instance_count; i++) {
- RS::LightType type = light_instance_get_type(p_light_instances[i]);
+ RS::LightType type = RenderForwardMobile::get_singleton()->light_instance_get_type(p_light_instances[i]);
switch (type) {
case RS::LIGHT_OMNI: {
- if (ginstance->omni_light_count < (uint32_t)MAX_RDL_CULL) {
- ginstance->omni_lights[ginstance->omni_light_count] = light_instance_get_forward_id(p_light_instances[i]);
- ginstance->omni_light_count++;
+ if (omni_light_count < (uint32_t)MAX_RDL_CULL) {
+ omni_lights[omni_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]);
+ omni_light_count++;
}
} break;
case RS::LIGHT_SPOT: {
- if (ginstance->spot_light_count < (uint32_t)MAX_RDL_CULL) {
- ginstance->spot_lights[ginstance->spot_light_count] = light_instance_get_forward_id(p_light_instances[i]);
- ginstance->spot_light_count++;
+ if (spot_light_count < (uint32_t)MAX_RDL_CULL) {
+ spot_lights[spot_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]);
+ spot_light_count++;
}
} break;
default:
@@ -2247,56 +2144,42 @@ void RenderForwardMobile::geometry_instance_pair_light_instances(GeometryInstanc
}
}
-void RenderForwardMobile::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL;
- for (uint32_t i = 0; i < ginstance->reflection_probe_count; i++) {
- ginstance->reflection_probes[i] = reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]);
+void RenderForwardMobile::GeometryInstanceForwardMobile::pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
+ reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL;
+ for (uint32_t i = 0; i < reflection_probe_count; i++) {
+ reflection_probes[i] = RenderForwardMobile::get_singleton()->reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]);
}
}
-void RenderForwardMobile::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL;
- for (uint32_t i = 0; i < ginstance->decals_count; i++) {
- ginstance->decals[i] = decal_instance_get_forward_id(p_decal_instances[i]);
+void RenderForwardMobile::GeometryInstanceForwardMobile::pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) {
+ decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL;
+ for (uint32_t i = 0; i < decals_count; i++) {
+ decals[i] = RenderForwardMobile::get_singleton()->decal_instance_get_forward_id(p_decal_instances[i]);
}
}
-void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
- // We do not have this here!
+void RenderForwardMobile::GeometryInstanceForwardMobile::set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) {
+ use_projector = p_projector;
+ use_soft_shadow = p_softshadow;
}
-void RenderForwardMobile::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->use_projector = p_projector;
- ginstance->use_soft_shadow = p_softshadow;
-}
-
-void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- if (ginstance->dirty_list_element.in_list()) {
+void RenderForwardMobile::GeometryInstanceForwardMobile::_mark_dirty() {
+ if (dirty_list_element.in_list()) {
return;
}
//clear surface caches
- GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
+ GeometryInstanceSurfaceDataCache *surf = surface_caches;
while (surf) {
GeometryInstanceSurfaceDataCache *next = surf->next;
- geometry_instance_surface_alloc.free(surf);
+ RenderForwardMobile::get_singleton()->geometry_instance_surface_alloc.free(surf);
surf = next;
}
- ginstance->surface_caches = nullptr;
+ surface_caches = nullptr;
- geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
+ RenderForwardMobile::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element);
}
void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
@@ -2350,7 +2233,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
void *surface_shadow = nullptr;
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
+ material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
@@ -2373,7 +2256,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
@@ -2409,7 +2292,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(Geo
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
break;
}
@@ -2429,7 +2312,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
SceneShaderForwardMobile::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2440,7 +2323,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
m_src = scene_shader.default_material;
}
@@ -2451,7 +2334,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
@@ -2462,7 +2345,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
}
}
-void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
@@ -2609,16 +2492,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: {
- static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ 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<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
} 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,8 +2512,8 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage:
} break;
}
}
-void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
- static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
}
/* misc */
@@ -2681,12 +2564,18 @@ void RenderForwardMobile::_update_shader_quality_settings() {
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
sc.constant_id = SPEC_CONSTANT_DECAL_USE_MIPMAPS;
- sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
sc.constant_id = SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS;
- sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
@@ -2695,8 +2584,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 +2616,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..4a7112eb81 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
-#define RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
+#ifndef RENDER_FORWARD_MOBILE_H
+#define RENDER_FORWARD_MOBILE_H
#include "core/templates/paged_allocator.h"
#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 {
@@ -131,12 +131,14 @@ protected:
RID depth_msaa;
// RID normal_roughness_buffer_msaa;
+ RID vrs;
+
RID color_fbs[FB_CONFIG_MAX];
int width, height;
uint32_t view_count;
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
~RenderBufferDataForwardMobile();
};
@@ -158,7 +160,7 @@ protected:
// PASS_MODE_SDF,
};
- struct GeometryInstanceForwardMobile;
+ class GeometryInstanceForwardMobile;
struct GeometryInstanceSurfaceDataCache;
struct RenderElementInfo;
@@ -210,14 +212,14 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
virtual void _render_shadow_begin() override;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
@@ -516,14 +518,8 @@ protected:
GeometryInstanceForwardMobile *owner = nullptr;
};
- // !BAS! GeometryInstanceForwardClustered and GeometryInstanceForwardMobile will likely have a lot of overlap
- // may need to think about making this its own class like GeometryInstanceRD?
-
- struct GeometryInstanceForwardMobile : public GeometryInstance {
- // setup
- uint32_t base_flags = 0;
- uint32_t flags_cache = 0;
-
+ class GeometryInstanceForwardMobile : public RenderGeometryInstanceBase {
+ public:
// this structure maps to our push constant in our shader and is populated right before our draw call
struct PushConstant {
float transform[16];
@@ -541,28 +537,18 @@ protected:
// PushConstant push_constant; // we populate this from our instance data
//used during rendering
- uint32_t layer_mask = 1;
RID transforms_uniform_set;
- float depth = 0;
- bool mirror = false;
bool use_projector = false;
bool use_soft_shadow = false;
- Transform3D transform;
bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform
- bool non_uniform_scale = false;
- AABB transformed_aabb; //needed for LOD
- float lod_bias = 0.0;
- float lod_model_scale = 1.0;
- int32_t shader_parameters_offset = -1;
uint32_t instance_count = 0;
uint32_t trail_steps = 1;
- RID mesh_instance;
// lightmap
uint32_t gi_offset_cache = 0; // !BAS! Should rename this to lightmap_offset_cache, in forward clustered this was shared between gi and lightmap
- uint32_t lightmap_slice_index;
- Rect2 lightmap_uv_scale;
RID lightmap_instance;
+ Rect2 lightmap_uv_scale;
+ uint32_t lightmap_slice_index;
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
// culled light info
@@ -580,30 +566,20 @@ protected:
// do we use this?
SelfList<GeometryInstanceForwardMobile> dirty_list_element;
- struct Data {
- //data used less often goes into regular heap
- RID base;
- RS::InstanceType base_type;
-
- RID skeleton;
- Vector<RID> surface_materials;
- RID material_override;
- RID material_overlay;
- AABB aabb;
-
- bool use_baked_light = true;
- bool cast_double_sided_shadows = false;
- // bool mirror = false; // !BAS! Does not seem used, we already have this in the main struct
+ GeometryInstanceForwardMobile() :
+ dirty_list_element(this) {}
- bool dirty_dependencies = false;
+ virtual void _mark_dirty() override;
- RendererStorage::DependencyTracker dependency_tracker;
- };
+ virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
+ virtual void set_lightmap_capture(const Color *p_sh9) override;
- Data *data = nullptr;
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override;
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
- GeometryInstanceForwardMobile() :
- dirty_list_element(this) {}
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override;
};
_FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance);
@@ -611,10 +587,12 @@ protected:
void _update_shader_quality_settings() override;
public:
+ static RenderForwardMobile *get_singleton() { return singleton; }
+
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;
@@ -625,41 +603,13 @@ public:
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
- void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
- void _geometry_instance_update(GeometryInstance *p_geometry_instance);
+ void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
- virtual GeometryInstance *geometry_instance_create(RID p_base) override;
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
- virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override;
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
- virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
- virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
- virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+ virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
virtual uint32_t geometry_instance_get_pair_mask() override;
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
-
- virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
virtual bool free(RID p_rid) override;
@@ -668,8 +618,9 @@ public:
virtual bool is_volumetric_supported() const override;
virtual uint32_t get_max_elements() const override;
- RenderForwardMobile(RendererStorageRD *p_storage);
+ RenderForwardMobile();
~RenderForwardMobile();
};
} // namespace RendererSceneRenderImplementation
-#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
+
+#endif // RENDER_FORWARD_MOBILE_H
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..01b54607bc 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
@@ -39,6 +39,10 @@ using namespace RendererSceneRenderImplementation;
/* ShaderData */
+void SceneShaderForwardMobile::ShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
//compile
@@ -345,7 +349,7 @@ void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const Strin
}
}
-void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SceneShaderForwardMobile::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -360,7 +364,22 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -426,7 +445,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() {
}
}
-RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
+RendererRD::MaterialStorage::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -450,7 +469,7 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -466,8 +485,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 */
@@ -494,8 +512,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
}
}
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
@@ -566,7 +584,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["OUTPUT_IS_SRGB"] = "true";
- actions.renames["FOG"] = "custom_fog";
+ actions.renames["FOG"] = "fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
actions.renames["BONE_INDICES"] = "bone_attrib";
@@ -577,6 +595,11 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz";
+ actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
+ actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz";
+ actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz";
+
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
@@ -667,7 +690,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
@@ -698,7 +721,7 @@ void fragment() {
material_storage->material_initialize(default_material);
material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D));
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_material_shader_ptr = md->shader_data;
@@ -725,7 +748,7 @@ void fragment() {
material_storage->material_initialize(overdraw_material);
material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D));
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
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..e208334547 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
@@ -28,11 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RSSR_SCENE_SHADER_FM_H
-#define RSSR_SCENE_SHADER_FM_H
+#ifndef SCENE_SHADER_FORWARD_MOBILE_H
+#define SCENE_SHADER_FORWARD_MOBILE_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 {
@@ -57,7 +55,7 @@ public:
SHADER_VERSION_MAX
};
- struct ShaderData : public RendererRD::ShaderData {
+ struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -141,8 +139,10 @@ public:
uint32_t index = 0;
virtual void set_code(const String &p_Code);
+ virtual void set_path_hint(const String &p_path);
+
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -157,12 +157,12 @@ public:
virtual ~ShaderData();
};
- RendererRD::ShaderData *_create_shader_func();
- static RendererRD::ShaderData *_create_shader_funcs() {
+ RendererRD::MaterialStorage::ShaderData *_create_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererRD::MaterialData {
+ struct MaterialData : public RendererRD::MaterialStorage::MaterialData {
ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
@@ -177,8 +177,8 @@ public:
SelfList<ShaderData>::List shader_list;
- RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+ RendererRD::MaterialStorage::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
@@ -207,9 +207,10 @@ 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);
};
} // namespace RendererSceneRenderImplementation
-#endif // !RSSR_SCENE_SHADER_FM_H
+
+#endif // SCENE_SHADER_FORWARD_MOBILE_H
diff --git a/servers/rendering/renderer_thread_pool.cpp b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp
index ddf1d1bd00..9baa86a32d 100644
--- a/servers/rendering/renderer_thread_pool.cpp
+++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_thread_pool.cpp */
+/* framebuffer_cache_rd.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,15 +28,37 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_thread_pool.h"
+#include "framebuffer_cache_rd.h"
-RendererThreadPool *RendererThreadPool::singleton = nullptr;
+FramebufferCacheRD *FramebufferCacheRD::singleton = nullptr;
-RendererThreadPool::RendererThreadPool() {
+void FramebufferCacheRD::_invalidate(Cache *p_cache) {
+ if (p_cache->prev) {
+ p_cache->prev->next = p_cache->next;
+ } else {
+ // At beginning of table
+ uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE;
+ hash_table[table_idx] = p_cache->next;
+ }
+
+ if (p_cache->next) {
+ p_cache->next->prev = p_cache->prev;
+ }
+
+ cache_allocator.free(p_cache);
+ cache_instances_used--;
+}
+void FramebufferCacheRD::_framebuffer_invalidation_callback(void *p_userdata) {
+ singleton->_invalidate(reinterpret_cast<Cache *>(p_userdata));
+}
+
+FramebufferCacheRD::FramebufferCacheRD() {
+ ERR_FAIL_COND(singleton != nullptr);
singleton = this;
- thread_work_pool.init();
}
-RendererThreadPool::~RendererThreadPool() {
- thread_work_pool.finish();
+FramebufferCacheRD::~FramebufferCacheRD() {
+ if (cache_instances_used > 0) {
+ ERR_PRINT("At exit: " + itos(cache_instances_used) + " framebuffer cache instance(s) still in use.");
+ }
}
diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.h b/servers/rendering/renderer_rd/framebuffer_cache_rd.h
new file mode 100644
index 0000000000..f360e0fc6b
--- /dev/null
+++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.h
@@ -0,0 +1,310 @@
+/*************************************************************************/
+/* framebuffer_cache_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 FRAMEBUFFER_CACHE_RD_H
+#define FRAMEBUFFER_CACHE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/paged_allocator.h"
+#include "servers/rendering/rendering_device.h"
+
+class FramebufferCacheRD : public Object {
+ GDCLASS(FramebufferCacheRD, Object)
+
+ struct Cache {
+ Cache *prev = nullptr;
+ Cache *next = nullptr;
+ uint32_t hash = 0;
+ RID cache;
+ LocalVector<RID> textures;
+ LocalVector<RD::FramebufferPass> passes;
+ uint32_t views = 0;
+ };
+
+ PagedAllocator<Cache> cache_allocator;
+
+ enum {
+ HASH_TABLE_SIZE = 16381 // Prime
+ };
+
+ Cache *hash_table[HASH_TABLE_SIZE] = {};
+
+ static _FORCE_INLINE_ uint32_t _hash_pass(const RD::FramebufferPass &p, uint32_t h) {
+ h = hash_murmur3_one_32(p.depth_attachment, h);
+ h = hash_murmur3_one_32(p.vrs_attachment, h);
+
+ h = hash_murmur3_one_32(p.color_attachments.size(), h);
+ for (int i = 0; i < p.color_attachments.size(); i++) {
+ h = hash_murmur3_one_32(p.color_attachments[i], h);
+ }
+
+ h = hash_murmur3_one_32(p.resolve_attachments.size(), h);
+ for (int i = 0; i < p.resolve_attachments.size(); i++) {
+ h = hash_murmur3_one_32(p.resolve_attachments[i], h);
+ }
+
+ h = hash_murmur3_one_32(p.preserve_attachments.size(), h);
+ for (int i = 0; i < p.preserve_attachments.size(); i++) {
+ h = hash_murmur3_one_32(p.preserve_attachments[i], h);
+ }
+
+ return h;
+ }
+
+ static _FORCE_INLINE_ bool _compare_pass(const RD::FramebufferPass &a, const RD::FramebufferPass &b) {
+ if (a.depth_attachment != b.depth_attachment) {
+ return false;
+ }
+
+ if (a.vrs_attachment != b.vrs_attachment) {
+ return false;
+ }
+
+ if (a.color_attachments.size() != b.color_attachments.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < a.color_attachments.size(); i++) {
+ if (a.color_attachments[i] != b.color_attachments[i]) {
+ return false;
+ }
+ }
+
+ if (a.resolve_attachments.size() != b.resolve_attachments.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < a.resolve_attachments.size(); i++) {
+ if (a.resolve_attachments[i] != b.resolve_attachments[i]) {
+ return false;
+ }
+ }
+
+ if (a.preserve_attachments.size() != b.preserve_attachments.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < a.preserve_attachments.size(); i++) {
+ if (a.preserve_attachments[i] != b.preserve_attachments[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ _FORCE_INLINE_ uint32_t _hash_rids(uint32_t h, const RID &arg) {
+ return hash_murmur3_one_64(arg.get_id(), h);
+ }
+
+ template <typename... Args>
+ uint32_t _hash_rids(uint32_t h, const RID &arg, Args... args) {
+ h = hash_murmur3_one_64(arg.get_id(), h);
+ return _hash_rids(h, args...);
+ }
+
+ _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RID> &textures, const RID &arg) {
+ return textures[idx] == arg;
+ }
+
+ template <typename... Args>
+ _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RID> &textures, const RID &arg, Args... args) {
+ if (textures[idx] != arg) {
+ return false;
+ }
+ return _compare_args(idx + 1, textures, args...);
+ }
+
+ _FORCE_INLINE_ void _create_args(Vector<RID> &textures, const RID &arg) {
+ textures.push_back(arg);
+ }
+
+ template <typename... Args>
+ _FORCE_INLINE_ void _create_args(Vector<RID> &textures, const RID &arg, Args... args) {
+ textures.push_back(arg);
+ _create_args(textures, args...);
+ }
+
+ static FramebufferCacheRD *singleton;
+
+ uint32_t cache_instances_used = 0;
+
+ void _invalidate(Cache *p_cache);
+ static void _framebuffer_invalidation_callback(void *p_userdata);
+
+ RID _allocate_from_data(uint32_t p_views, uint32_t p_hash, uint32_t p_table_idx, const Vector<RID> &p_textures, const Vector<RD::FramebufferPass> &p_passes) {
+ RID rid;
+ if (p_passes.size()) {
+ rid = RD::get_singleton()->framebuffer_create_multipass(p_textures, p_passes, RD::INVALID_ID, p_views);
+ } else {
+ rid = RD::get_singleton()->framebuffer_create(p_textures, RD::INVALID_ID, p_views);
+ }
+
+ ERR_FAIL_COND_V(rid.is_null(), rid);
+
+ Cache *c = cache_allocator.alloc();
+ c->views = p_views;
+ c->cache = rid;
+ c->hash = p_hash;
+ c->textures.resize(p_textures.size());
+ for (uint32_t i = 0; i < c->textures.size(); i++) {
+ c->textures[i] = p_textures[i];
+ }
+ c->passes.resize(p_passes.size());
+ for (uint32_t i = 0; i < c->passes.size(); i++) {
+ c->passes[i] = p_passes[i];
+ }
+ c->prev = nullptr;
+ c->next = hash_table[p_table_idx];
+ if (hash_table[p_table_idx]) {
+ hash_table[p_table_idx]->prev = c;
+ }
+ hash_table[p_table_idx] = c;
+
+ RD::get_singleton()->framebuffer_set_invalidation_callback(rid, _framebuffer_invalidation_callback, c);
+
+ cache_instances_used++;
+
+ return rid;
+ }
+
+public:
+ template <typename... Args>
+ RID get_cache(Args... args) {
+ uint32_t h = hash_murmur3_one_32(1); //1 view
+ h = hash_murmur3_one_32(sizeof...(Args), h);
+ h = _hash_args(h, args...);
+ h = hash_murmur3_one_32(0, h); // 0 passes
+ h = hash_fmix32(h);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->passes.size() == 0 && c->textures.size() == sizeof...(Args) && c->views == 1 && _compare_args(0, c->textures, args...)) {
+ return c->cache;
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+
+ Vector<RID> textures;
+ _create_args(textures, args...);
+
+ return _allocate_from_data(1, h, table_idx, textures, Vector<RD::FramebufferPass>());
+ }
+
+ template <typename... Args>
+ RID get_cache_multiview(uint32_t p_views, Args... args) {
+ uint32_t h = hash_murmur3_one_32(p_views);
+ h = hash_murmur3_one_32(sizeof...(Args), h);
+ h = _hash_args(h, args...);
+ h = hash_murmur3_one_32(0, h); // 0 passes
+ h = hash_fmix32(h);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->passes.size() == 0 && c->textures.size() == sizeof...(Args) && c->views == p_views && _compare_args(0, c->textures, args...)) {
+ return c->cache;
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+
+ Vector<RID> textures;
+ _create_args(textures, args...);
+
+ return _allocate_from_data(p_views, h, table_idx, textures, Vector<RD::FramebufferPass>());
+ }
+
+ RID get_cache_multipass(const Vector<RID> &p_textures, const Vector<RD::FramebufferPass> &p_passes, uint32_t p_views = 1) {
+ uint32_t h = hash_murmur3_one_32(p_views);
+ h = hash_murmur3_one_32(p_textures.size());
+ for (int i = 0; i < p_textures.size(); i++) {
+ h = hash_murmur3_one_64(p_textures[i].get_id(), h);
+ }
+ h = hash_murmur3_one_32(p_passes.size());
+ for (int i = 0; i < p_passes.size(); i++) {
+ h = _hash_pass(p_passes[i], h);
+ }
+
+ h = hash_fmix32(h);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->views == p_views && c->textures.size() == (uint32_t)p_textures.size() && c->passes.size() == (uint32_t)p_passes.size()) {
+ bool all_ok = true;
+
+ for (int i = 0; i < p_textures.size(); i++) {
+ if (p_textures[i] != c->textures[i]) {
+ all_ok = false;
+ break;
+ }
+ }
+
+ if (all_ok) {
+ for (int i = 0; i < p_passes.size(); i++) {
+ if (!_compare_pass(p_passes[i], c->passes[i])) {
+ all_ok = false;
+ break;
+ }
+ }
+ }
+
+ if (all_ok) {
+ return c->cache;
+ }
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+ return _allocate_from_data(p_views, h, table_idx, p_textures, p_passes);
+ }
+
+ static FramebufferCacheRD *get_singleton() { return singleton; }
+
+ FramebufferCacheRD();
+ ~FramebufferCacheRD();
+};
+
+#endif // FRAMEBUFFER_CACHE_RD_H
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index ad83fc76b7..882e459bcd 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -97,4 +97,4 @@ public:
~PipelineCacheRD();
};
-#endif // RENDER_PIPELINE_CACHE_RD_H
+#endif // PIPELINE_CACHE_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 3c2f3f8a42..c1b08ee4c9 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -192,7 +192,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[1] = vd;
- buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_COLOR);
+ buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_COLOR);
}
//uvs
@@ -220,7 +220,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[2] = vd;
- buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_TEX_UV);
+ buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_TEX_UV);
}
//bones
@@ -253,7 +253,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[3] = vd;
- buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_BONES);
+ buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_BONES);
}
//weights
@@ -286,7 +286,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[4] = vd;
- buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_WEIGHTS);
+ buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_WEIGHTS);
}
//check that everything is as it should be
@@ -528,7 +528,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
if (rect->flags & CANVAS_RECT_TRANSPOSE) {
- dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform
+ push_constant.flags |= FLAGS_TRANSPOSE_RECT;
}
if (rect->flags & CANVAS_RECT_CLIP_UV) {
@@ -988,7 +988,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
} else {
screen = texture_storage->render_target_get_rd_backbuffer(p_to_render_target);
if (screen.is_null()) { //unallocated backbuffer
- screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
}
u.append_id(screen);
@@ -1031,7 +1031,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 9;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1115,7 +1115,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
if (material != prev_material) {
CanvasMaterialData *material_data = nullptr;
if (material.is_valid()) {
- material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D));
+ material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D));
}
if (material_data) {
@@ -1304,7 +1304,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
Transform3D screen_transform;
- screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
+ screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f));
_update_transform_to_mat4(screen_transform, state_buffer.screen_transform);
_update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
@@ -1383,7 +1383,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
if (material.is_valid()) {
- CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D));
+ CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D));
if (md && md->shader_data->valid) {
if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
if (!material_screen_texture_found) {
@@ -1581,9 +1581,10 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
//light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2);
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
+ RD::InitialAction initial_action = i == 0 ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE;
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, initial_action, i != 3 ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, initial_action, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
- CameraMatrix projection;
+ Projection projection;
{
real_t fov = 90;
real_t nearp = p_near;
@@ -1599,7 +1600,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
}
Vector3 cam_target = Basis(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
- projection = projection * CameraMatrix(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
+ projection = projection * Projection(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
@@ -1670,11 +1671,11 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
cc.push_back(Color(1, 1, 1, 1));
Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2);
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
- CameraMatrix projection;
+ Projection projection;
projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance);
- projection = projection * CameraMatrix(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse());
+ projection = projection * Projection(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse());
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
@@ -1742,7 +1743,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc);
- CameraMatrix projection;
+ Projection projection;
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
@@ -1967,6 +1968,10 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::
oc->cull_mode = p_mode;
}
+void RendererCanvasRenderRD::CanvasShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
//compile
@@ -2166,7 +2171,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const S
}
}
-void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -2180,7 +2185,22 @@ void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo>
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -2241,7 +2261,7 @@ RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() {
}
}
-RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
+RendererRD::MaterialStorage::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
CanvasShaderData *shader_data = memnew(CanvasShaderData);
return shader_data;
}
@@ -2256,7 +2276,7 @@ RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
CanvasMaterialData *material_data = memnew(CanvasMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -2270,10 +2290,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
@@ -2432,6 +2451,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n";
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n";
+ actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n";
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
@@ -2449,7 +2469,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
actions.base_varying_index = 4;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
shader.compiler.initialize(actions);
}
@@ -2609,8 +2629,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
//create functions for shader and material
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_2D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_2D, _create_material_funcs);
state.time = 0;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 04881ce7e6..5eb4cee4c6 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -28,21 +28,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_CANVAS_RENDER_RD_H
-#define RENDERING_SERVER_CANVAS_RENDER_RD_H
+#ifndef RENDERER_CANVAS_RENDER_RD_H
+#define RENDERER_CANVAS_RENDER_RD_H
#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,
@@ -151,7 +149,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
ShaderCompiler compiler;
} shader;
- struct CanvasShaderData : public RendererRD::ShaderData {
+ struct CanvasShaderData : public RendererRD::MaterialStorage::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -180,8 +178,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
bool uses_time = false;
virtual void set_code(const String &p_Code);
+ virtual void set_path_hint(const String &p_path);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -194,12 +193,12 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual ~CanvasShaderData();
};
- RendererRD::ShaderData *_create_shader_func();
- static RendererRD::ShaderData *_create_shader_funcs() {
+ RendererRD::MaterialStorage::ShaderData *_create_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() {
return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func();
}
- struct CanvasMaterialData : public RendererRD::MaterialData {
+ struct CanvasMaterialData : public RendererRD::MaterialStorage::MaterialData {
CanvasShaderData *shader_data = nullptr;
RID uniform_set;
@@ -209,8 +208,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual ~CanvasMaterialData();
};
- RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader);
- static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+ RendererRD::MaterialStorage::MaterialData *_create_material_func(CanvasShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader));
}
@@ -462,8 +461,8 @@ public:
void set_time(double p_time);
void update();
bool free(RID p_rid);
- RendererCanvasRenderRD(RendererStorageRD *p_storage);
+ RendererCanvasRenderRD();
~RendererCanvasRenderRD();
};
-#endif // RASTERIZER_CANVAS_RD_H
+#endif // RENDERER_CANVAS_RENDER_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 759b8690eb..967b725b9e 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);
@@ -247,6 +249,7 @@ RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
uniform_set_cache = memnew(UniformSetCacheRD);
+ framebuffer_cache = memnew(FramebufferCacheRD);
{
String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path();
@@ -287,31 +290,33 @@ 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() {
memdelete(uniform_set_cache);
+ memdelete(framebuffer_cache);
ShaderRD::set_shader_cache_dir(String());
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 12bcfc4684..a28335f800 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -28,34 +28,39 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_COMPOSITOR_RD_H
-#define RENDERING_SERVER_COMPOSITOR_RD_H
+#ifndef RENDERER_COMPOSITOR_RD_H
+#define RENDERER_COMPOSITOR_RD_H
#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/framebuffer_cache_rd.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;
+ FramebufferCacheRD *framebuffer_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 +103,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 +113,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; }
@@ -142,4 +149,5 @@ public:
RendererCompositorRD();
~RendererCompositorRD();
};
-#endif // RASTERIZER_RD_H
+
+#endif // RENDERER_COMPOSITOR_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
deleted file mode 100644
index 0d9477d850..0000000000
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*************************************************************************/
-/* renderer_scene_environment_rd.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 "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
-
-uint64_t RendererSceneEnvironmentRD::auto_exposure_counter = 2;
-
-void RendererSceneEnvironmentRD::set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
- ambient_light = p_color;
- ambient_source = p_ambient;
- ambient_light_energy = p_energy;
- ambient_sky_contribution = p_sky_contribution;
- reflection_source = p_reflection_source;
-}
-
-void RendererSceneEnvironmentRD::set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
- exposure = p_exposure;
- tone_mapper = p_tone_mapper;
- if (!auto_exposure && p_auto_exposure) {
- auto_exposure_version = ++auto_exposure_counter;
- }
- auto_exposure = p_auto_exposure;
- white = p_white;
- min_luminance = p_min_luminance;
- max_luminance = p_max_luminance;
- auto_exp_speed = p_auto_exp_speed;
- auto_exp_scale = p_auto_exp_scale;
-}
-
-void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
- ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
- glow_enabled = p_enable;
- glow_levels = p_levels;
- glow_intensity = p_intensity;
- glow_strength = p_strength;
- glow_mix = p_mix;
- glow_bloom = p_bloom_threshold;
- glow_blend_mode = p_blend_mode;
- glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
- glow_hdr_bleed_scale = p_hdr_bleed_scale;
- glow_hdr_luminance_cap = p_hdr_luminance_cap;
- glow_map_strength = p_glow_map_strength;
- glow_map = p_glow_map;
-}
-
-void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
- sdfgi_enabled = p_enable;
- sdfgi_cascades = p_cascades;
- sdfgi_min_cell_size = p_min_cell_size;
- sdfgi_use_occlusion = p_use_occlusion;
- sdfgi_bounce_feedback = p_bounce_feedback;
- sdfgi_read_sky_light = p_read_sky;
- sdfgi_energy = p_energy;
- sdfgi_normal_bias = p_normal_bias;
- sdfgi_probe_bias = p_probe_bias;
- sdfgi_y_scale = p_y_scale;
-}
-
-void RendererSceneEnvironmentRD::set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
- fog_enabled = p_enable;
- fog_light_color = p_light_color;
- fog_light_energy = p_light_energy;
- fog_sun_scatter = p_sun_scatter;
- fog_density = p_density;
- fog_height = p_height;
- fog_height_density = p_height_density;
- fog_aerial_perspective = p_fog_aerial_perspective;
-}
-
-void RendererSceneEnvironmentRD::set_volumetric_fog(bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
- volumetric_fog_enabled = p_enable;
- volumetric_fog_density = p_density;
- volumetric_fog_scattering = p_albedo;
- volumetric_fog_emission = p_emission;
- volumetric_fog_emission_energy = p_emission_energy;
- volumetric_fog_anisotropy = p_anisotropy,
- volumetric_fog_length = p_length;
- volumetric_fog_detail_spread = p_detail_spread;
- volumetric_fog_gi_inject = p_gi_inject;
- volumetric_fog_temporal_reprojection = p_temporal_reprojection;
- volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount;
- volumetric_fog_ambient_inject = p_ambient_inject;
-}
-
-void RendererSceneEnvironmentRD::set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
- ssr_enabled = p_enable;
- ssr_max_steps = p_max_steps;
- ssr_fade_in = p_fade_int;
- ssr_fade_out = p_fade_out;
- ssr_depth_tolerance = p_depth_tolerance;
-}
-
-void RendererSceneEnvironmentRD::set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
- ssao_enabled = p_enable;
- ssao_radius = p_radius;
- ssao_intensity = p_intensity;
- ssao_power = p_power;
- ssao_detail = p_detail;
- ssao_horizon = p_horizon;
- ssao_sharpness = p_sharpness;
- ssao_direct_light_affect = p_light_affect;
- ssao_ao_channel_affect = p_ao_channel_affect;
-}
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
deleted file mode 100644
index 4e170b8cfb..0000000000
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*************************************************************************/
-/* renderer_scene_environment_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_SCENE_ENVIRONMENT_RD_H
-#define RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H
-
-#include "servers/rendering/renderer_scene_render.h"
-#include "servers/rendering/rendering_device.h"
-
-class RendererSceneEnvironmentRD {
-private:
- static uint64_t auto_exposure_counter;
-
-public:
- // BG
- RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR;
- RID sky;
- float sky_custom_fov = 0.0;
- Basis sky_orientation;
- Color bg_color;
- float bg_energy = 1.0;
- int canvas_max_layer = 0;
- RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG;
- Color ambient_light;
- float ambient_light_energy = 1.0;
- float ambient_sky_contribution = 1.0;
- RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
-
- /// Tonemap
-
- RS::EnvironmentToneMapper tone_mapper;
- float exposure = 1.0;
- float white = 1.0;
- bool auto_exposure = false;
- float min_luminance = 0.2;
- float max_luminance = 8.0;
- float auto_exp_speed = 0.2;
- float auto_exp_scale = 0.5;
- uint64_t auto_exposure_version = 0;
-
- // Fog
- bool fog_enabled = false;
- Color fog_light_color = Color(0.5, 0.6, 0.7);
- float fog_light_energy = 1.0;
- float fog_sun_scatter = 0.0;
- float fog_density = 0.001;
- float fog_height = 0.0;
- float fog_height_density = 0.0; //can be negative to invert effect
- float fog_aerial_perspective = 0.0;
-
- /// Volumetric Fog
- ///
- bool volumetric_fog_enabled = false;
- float volumetric_fog_density = 0.01;
- Color volumetric_fog_scattering = Color(1, 1, 1);
- Color volumetric_fog_emission = Color(0, 0, 0);
- float volumetric_fog_emission_energy = 0.0;
- float volumetric_fog_anisotropy = 0.2;
- float volumetric_fog_length = 64.0;
- float volumetric_fog_detail_spread = 2.0;
- float volumetric_fog_gi_inject = 0.0;
- bool volumetric_fog_temporal_reprojection = true;
- float volumetric_fog_temporal_reprojection_amount = 0.9;
- float volumetric_fog_ambient_inject = 0.0;
-
- /// Glow
-
- bool glow_enabled = false;
- Vector<float> glow_levels;
- float glow_intensity = 0.8;
- float glow_strength = 1.0;
- float glow_bloom = 0.0;
- float glow_mix = 0.01;
- RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT;
- float glow_hdr_bleed_threshold = 1.0;
- float glow_hdr_luminance_cap = 12.0;
- float glow_hdr_bleed_scale = 2.0;
- float glow_map_strength = 0.0f;
- RID glow_map = RID();
-
- /// SSAO
-
- bool ssao_enabled = false;
- float ssao_radius = 1.0;
- float ssao_intensity = 2.0;
- float ssao_power = 1.5;
- float ssao_detail = 0.5;
- float ssao_horizon = 0.06;
- float ssao_sharpness = 0.98;
- float ssao_direct_light_affect = 0.0;
- float ssao_ao_channel_affect = 0.0;
-
- /// SSR
- ///
- bool ssr_enabled = false;
- int ssr_max_steps = 64;
- float ssr_fade_in = 0.15;
- float ssr_fade_out = 2.0;
- float ssr_depth_tolerance = 0.2;
-
- /// SSIL
- ///
- bool ssil_enabled = false;
- float ssil_radius = 5.0;
- float ssil_intensity = 1.0;
- float ssil_sharpness = 0.98;
- float ssil_normal_rejection = 1.0;
-
- /// SDFGI
- bool sdfgi_enabled = false;
- int sdfgi_cascades = 4;
- float sdfgi_min_cell_size = 0.2;
- bool sdfgi_use_occlusion = false;
- float sdfgi_bounce_feedback = 0.5;
- bool sdfgi_read_sky_light = true;
- float sdfgi_energy = 1.0;
- float sdfgi_normal_bias = 1.1;
- float sdfgi_probe_bias = 1.1;
- RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_75_PERCENT;
-
- /// Adjustments
-
- bool adjustments_enabled = false;
- float adjustments_brightness = 1.0f;
- float adjustments_contrast = 1.0f;
- float adjustments_saturation = 1.0f;
- bool use_1d_color_correction = false;
- RID color_correction = RID();
-
- void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source);
- void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
- void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map);
- void set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
- void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective);
- void set_volumetric_fog(bool p_enable, float p_density, const Color &p_scatterin, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject);
- void set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
- void set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
-};
-
-#endif /* !RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H */
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index eb4bc3d535..8b3b7050d2 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"
@@ -50,9 +51,8 @@ void get_vogel_disk(float *r_kernel, int p_sample_count) {
}
void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- bool needs_sdfgi = env && env->sdfgi_enabled;
+ bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment);
if (!needs_sdfgi) {
if (rb->sdfgi != nullptr) {
@@ -67,7 +67,7 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 };
uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge];
- if (rb->sdfgi && (rb->sdfgi->num_cascades != env->sdfgi_cascades || rb->sdfgi->min_cell_size != env->sdfgi_min_cell_size || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != env->sdfgi_use_occlusion || rb->sdfgi->y_scale_mode != env->sdfgi_y_scale)) {
+ if (rb->sdfgi && (rb->sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || rb->sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || rb->sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) {
//configuration changed, erase
rb->sdfgi->erase();
memdelete(rb->sdfgi);
@@ -77,10 +77,10 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
RendererRD::GI::SDFGI *sdfgi = rb->sdfgi;
if (sdfgi == nullptr) {
// re-create
- rb->sdfgi = gi.create_sdfgi(env, p_world_position, requested_history_size);
+ rb->sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size);
} else {
//check for updates
- rb->sdfgi->update(env, p_world_position);
+ rb->sdfgi->update(p_environment, p_world_position);
}
}
@@ -158,145 +158,6 @@ Ref<Image> RendererSceneRenderRD::sky_bake_panorama(RID p_sky, float p_energy, b
return sky.sky_bake_panorama(p_sky, p_energy, p_bake_irradiance, p_size);
}
-RID RendererSceneRenderRD::environment_allocate() {
- return environment_owner.allocate_rid();
-}
-void RendererSceneRenderRD::environment_initialize(RID p_rid) {
- environment_owner.initialize_rid(p_rid, RendererSceneEnvironmentRD());
-}
-
-void RendererSceneRenderRD::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->background = p_bg;
-}
-
-void RendererSceneRenderRD::environment_set_sky(RID p_env, RID p_sky) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->sky = p_sky;
-}
-
-void RendererSceneRenderRD::environment_set_sky_custom_fov(RID p_env, float p_scale) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->sky_custom_fov = p_scale;
-}
-
-void RendererSceneRenderRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->sky_orientation = p_orientation;
-}
-
-void RendererSceneRenderRD::environment_set_bg_color(RID p_env, const Color &p_color) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->bg_color = p_color;
-}
-
-void RendererSceneRenderRD::environment_set_bg_energy(RID p_env, float p_energy) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->bg_energy = p_energy;
-}
-
-void RendererSceneRenderRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->canvas_max_layer = p_max_layer;
-}
-
-void RendererSceneRenderRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->set_ambient_light(p_color, p_ambient, p_energy, p_sky_contribution, p_reflection_source);
-}
-
-RS::EnvironmentBG RendererSceneRenderRD::environment_get_background(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX);
- return env->background;
-}
-
-RID RendererSceneRenderRD::environment_get_sky(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, RID());
- return env->sky;
-}
-
-float RendererSceneRenderRD::environment_get_sky_custom_fov(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->sky_custom_fov;
-}
-
-Basis RendererSceneRenderRD::environment_get_sky_orientation(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Basis());
- return env->sky_orientation;
-}
-
-Color RendererSceneRenderRD::environment_get_bg_color(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Color());
- return env->bg_color;
-}
-
-float RendererSceneRenderRD::environment_get_bg_energy(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->bg_energy;
-}
-
-int RendererSceneRenderRD::environment_get_canvas_max_layer(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->canvas_max_layer;
-}
-
-Color RendererSceneRenderRD::environment_get_ambient_light_color(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Color());
- return env->ambient_light;
-}
-
-RS::EnvironmentAmbientSource RendererSceneRenderRD::environment_get_ambient_source(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG);
- return env->ambient_source;
-}
-
-float RendererSceneRenderRD::environment_get_ambient_light_energy(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->ambient_light_energy;
-}
-
-float RendererSceneRenderRD::environment_get_ambient_sky_contribution(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->ambient_sky_contribution;
-}
-
-RS::EnvironmentReflectionSource RendererSceneRenderRD::environment_get_reflection_source(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_DISABLED);
- return env->reflection_source;
-}
-
-void RendererSceneRenderRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->set_tonemap(p_tone_mapper, p_exposure, p_white, p_auto_exposure, p_min_luminance, p_max_luminance, p_auto_exp_speed, p_auto_exp_scale);
-}
-
-void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->set_glow(p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap, p_glow_map_strength, p_glow_map);
-}
-
void RendererSceneRenderRD::environment_glow_set_use_bicubic_upscale(bool p_enable) {
glow_bicubic_upscale = p_enable;
}
@@ -305,79 +166,6 @@ void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable)
glow_high_quality = p_enable;
}
-void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- if (!is_dynamic_gi_supported()) {
- return;
- }
-
- env->set_sdfgi(p_enable, p_cascades, p_min_cell_size, p_y_scale, p_use_occlusion, p_bounce_feedback, p_read_sky, p_energy, p_normal_bias, p_probe_bias);
-}
-
-void RendererSceneRenderRD::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->set_fog(p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_fog_aerial_perspective);
-}
-
-bool RendererSceneRenderRD::environment_is_fog_enabled(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
-
- return env->fog_enabled;
-}
-Color RendererSceneRenderRD::environment_get_fog_light_color(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Color());
- return env->fog_light_color;
-}
-float RendererSceneRenderRD::environment_get_fog_light_energy(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_light_energy;
-}
-float RendererSceneRenderRD::environment_get_fog_sun_scatter(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_sun_scatter;
-}
-float RendererSceneRenderRD::environment_get_fog_density(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_density;
-}
-float RendererSceneRenderRD::environment_get_fog_height(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
-
- return env->fog_height;
-}
-float RendererSceneRenderRD::environment_get_fog_height_density(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_height_density;
-}
-
-float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_aerial_perspective;
-}
-
-void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- if (!is_volumetric_supported()) {
- return;
- }
-
- env->set_volumetric_fog(p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject);
-}
-
void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) {
volumetric_fog_size = p_size;
volumetric_fog_depth = p_depth;
@@ -398,13 +186,6 @@ void RendererSceneRenderRD::environment_set_sdfgi_frames_to_update_light(RS::Env
gi.sdfgi_frames_to_update_light = p_update;
}
-void RendererSceneRenderRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->set_ssr(p_enable, p_max_steps, p_fade_int, p_fade_out, p_depth_tolerance);
-}
-
void RendererSceneRenderRD::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
ssr_roughness_quality = p_quality;
}
@@ -413,13 +194,6 @@ RS::EnvironmentSSRRoughnessQuality RendererSceneRenderRD::environment_get_ssr_ro
return ssr_roughness_quality;
}
-void RendererSceneRenderRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->set_ssao(p_enable, p_radius, p_intensity, p_power, p_detail, p_horizon, p_sharpness, p_light_affect, p_ao_channel_affect);
-}
-
void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
ssao_quality = p_quality;
ssao_half_size = p_half_size;
@@ -429,17 +203,6 @@ void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQual
ssao_fadeout_to = p_fadeout_to;
}
-void RendererSceneRenderRD::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->ssil_enabled = p_enable;
- env->ssil_radius = p_radius;
- env->ssil_intensity = p_intensity;
- env->ssil_sharpness = p_sharpness;
- env->ssil_normal_rejection = p_normal_rejection;
-}
-
void RendererSceneRenderRD::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
ssil_quality = p_quality;
ssil_half_size = p_half_size;
@@ -449,56 +212,16 @@ void RendererSceneRenderRD::environment_set_ssil_quality(RS::EnvironmentSSILQual
ssil_fadeout_to = p_fadeout_to;
}
-bool RendererSceneRenderRD::environment_is_ssao_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
- return env->ssao_enabled;
-}
-
-float RendererSceneRenderRD::environment_get_ssao_ao_affect(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0.0);
- return env->ssao_ao_channel_affect;
-}
-
-float RendererSceneRenderRD::environment_get_ssao_light_affect(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0.0);
- return env->ssao_direct_light_affect;
-}
-
-bool RendererSceneRenderRD::environment_is_ssil_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
- return env->ssil_enabled;
-}
-
-bool RendererSceneRenderRD::environment_is_ssr_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
- return env->ssr_enabled;
-}
-bool RendererSceneRenderRD::environment_is_sdfgi_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
- return env->sdfgi_enabled;
-}
-
-bool RendererSceneRenderRD::is_environment(RID p_env) const {
- return environment_owner.owns(p_env);
-}
-
Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Ref<Image>());
+ ERR_FAIL_COND_V(p_env.is_null(), Ref<Image>());
- RS::EnvironmentBG environment_background = env->background;
+ RS::EnvironmentBG environment_background = environment_get_background(p_env);
if (environment_background == RS::ENV_BG_CAMERA_FEED || environment_background == RS::ENV_BG_CANVAS || environment_background == RS::ENV_BG_KEEP) {
return Ref<Image>(); //nothing to bake
}
- RS::EnvironmentAmbientSource ambient_source = env->ambient_source;
+ RS::EnvironmentAmbientSource ambient_source = environment_get_ambient_source(p_env);
bool use_ambient_light = false;
bool use_cube_map = false;
@@ -508,14 +231,14 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
use_cube_map = (ambient_source == RS::ENV_AMBIENT_SOURCE_BG && environment_background == RS::ENV_BG_SKY) || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY;
use_ambient_light = use_cube_map || ambient_source == RS::ENV_AMBIENT_SOURCE_COLOR;
}
- use_cube_map = use_cube_map || (environment_background == RS::ENV_BG_SKY && env->sky.is_valid());
+ use_cube_map = use_cube_map || (environment_background == RS::ENV_BG_SKY && environment_get_sky(p_env).is_valid());
Color ambient_color;
- float ambient_color_sky_mix;
+ float ambient_color_sky_mix = 0.0;
if (use_ambient_light) {
- ambient_color_sky_mix = env->ambient_sky_contribution;
- const float ambient_energy = env->ambient_light_energy;
- ambient_color = env->ambient_light;
+ ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_env);
+ const float ambient_energy = environment_get_ambient_light_energy(p_env);
+ ambient_color = environment_get_ambient_light(p_env);
ambient_color = ambient_color.srgb_to_linear();
ambient_color.r *= ambient_energy;
ambient_color.g *= ambient_energy;
@@ -523,7 +246,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
}
if (use_cube_map) {
- Ref<Image> panorama = sky_bake_panorama(env->sky, env->bg_energy, p_bake_irradiance, p_size);
+ Ref<Image> panorama = sky_bake_panorama(environment_get_sky(p_env), environment_get_bg_energy(p_env), p_bake_irradiance, p_size);
if (use_ambient_light) {
for (int x = 0; x < p_size.width; x++) {
for (int y = 0; y < p_size.height; y++) {
@@ -533,8 +256,8 @@ 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);
+ const float bg_energy = environment_get_bg_energy(p_env);
+ Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? RSG::texture_storage->get_default_clear_color() : environment_get_bg_color(p_env));
panorama_color = panorama_color.srgb_to_linear();
panorama_color.r *= bg_energy;
panorama_color.g *= bg_energy;
@@ -557,29 +280,28 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
////////////////////////////////////////////////////////////
RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) {
- FogVolumeInstance fvi;
- fvi.volume = p_fog_volume;
- return fog_volume_instance_owner.make_rid(fvi);
+ return RendererRD::Fog::get_singleton()->fog_volume_instance_create(p_fog_volume);
}
+
void RendererSceneRenderRD::fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance);
ERR_FAIL_COND(!fvi);
fvi->transform = p_transform;
}
void RendererSceneRenderRD::fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance);
ERR_FAIL_COND(!fvi);
fvi->active = p_active;
}
RID RendererSceneRenderRD::fog_volume_instance_get_volume(RID p_fog_volume_instance) const {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance);
ERR_FAIL_COND_V(!fvi, RID());
return fvi->volume;
}
Vector3 RendererSceneRenderRD::fog_volume_instance_get_position(RID p_fog_volume_instance) const {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance);
ERR_FAIL_COND_V(!fvi, Vector3());
return fvi->transform.get_origin();
@@ -759,7 +481,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 +551,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 +559,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 +570,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++;
@@ -1429,7 +1151,7 @@ void RendererSceneRenderRD::light_instance_set_aabb(RID p_light_instance, const
light_instance->aabb = p_aabb;
}
-void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
+void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
ERR_FAIL_COND(!light_instance);
@@ -1525,7 +1247,7 @@ bool RendererSceneRenderRD::voxel_gi_needs_update(RID p_probe) const {
return gi.voxel_gi_needs_update(p_probe);
}
-void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {
+void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) {
if (!is_dynamic_gi_supported()) {
return;
}
@@ -1533,7 +1255,7 @@ void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_ins
gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this);
}
-void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
+void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -1826,6 +1548,16 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->sss_texture = RID();
}
+ if (rb->vrs_fb.is_valid()) {
+ RD::get_singleton()->free(rb->vrs_fb);
+ rb->vrs_fb = RID();
+ }
+
+ if (rb->vrs_texture.is_valid()) {
+ RD::get_singleton()->free(rb->vrs_texture);
+ rb->vrs_texture = RID();
+ }
+
for (int i = 0; i < 2; i++) {
for (int l = 0; l < rb->blur[i].layers.size(); l++) {
for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) {
@@ -1880,60 +1612,9 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->ss_effects.linear_depth_slices.clear();
}
- if (rb->ss_effects.ssao.ao_final.is_valid()) {
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_final);
-
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]);
-
- rb->ss_effects.ssao.ao_deinterleaved = RID();
- rb->ss_effects.ssao.ao_pong = RID();
- rb->ss_effects.ssao.ao_final = RID();
- rb->ss_effects.ssao.importance_map[0] = RID();
- rb->ss_effects.ssao.importance_map[1] = RID();
-
- rb->ss_effects.ssao.ao_deinterleaved_slices.clear();
- rb->ss_effects.ssao.ao_pong_slices.clear();
- }
-
- if (rb->ss_effects.ssil.ssil_final.is_valid()) {
- RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final);
- RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssil.pong);
- RD::get_singleton()->free(rb->ss_effects.ssil.edges);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]);
-
- rb->ss_effects.ssil.ssil_final = RID();
- rb->ss_effects.ssil.deinterleaved = RID();
- rb->ss_effects.ssil.pong = RID();
- rb->ss_effects.ssil.edges = RID();
- rb->ss_effects.ssil.deinterleaved_slices.clear();
- rb->ss_effects.ssil.pong_slices.clear();
- rb->ss_effects.ssil.edges_slices.clear();
- rb->ss_effects.ssil.importance_map[0] = RID();
- rb->ss_effects.ssil.importance_map[1] = RID();
-
- RD::get_singleton()->free(rb->ss_effects.last_frame);
- rb->ss_effects.last_frame = RID();
- rb->ss_effects.last_frame_slices.clear();
- }
-
- if (rb->ssr.blur_radius[0].is_valid()) {
- RD::get_singleton()->free(rb->ssr.blur_radius[0]);
- RD::get_singleton()->free(rb->ssr.blur_radius[1]);
- rb->ssr.blur_radius[0] = RID();
- rb->ssr.blur_radius[1] = RID();
- }
-
- if (rb->ssr.depth_scaled.is_valid()) {
- RD::get_singleton()->free(rb->ssr.depth_scaled);
- rb->ssr.depth_scaled = RID();
- RD::get_singleton()->free(rb->ssr.normal_scaled);
- rb->ssr.normal_scaled = RID();
- }
+ ss_effects->ssao_free(rb->ss_effects.ssao);
+ ss_effects->ssil_free(rb->ss_effects.ssil);
+ ss_effects->ssr_free(rb->ssr);
if (rb->taa.history.is_valid()) {
RD::get_singleton()->free(rb->taa.history);
@@ -1953,7 +1634,7 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->rbgi.free();
}
-void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) {
+void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const Projection &p_camera) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -1968,10 +1649,12 @@ 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) {
+void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) {
+ ERR_FAIL_NULL(ss_effects);
+
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -1979,161 +1662,45 @@ 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());
+ copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID(), rb->view_count);
return;
}
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
- ERR_FAIL_COND(!env);
+ ERR_FAIL_COND(p_environment.is_null());
- ERR_FAIL_COND(!env->ssr_enabled);
+ ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment));
- if (rb->ssr.depth_scaled.is_null()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = rb->internal_width / 2;
- tf.height = rb->internal_height / 2;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
-
- rb->ssr.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
-
- rb->ssr.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-
- if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->internal_width / 2;
- tf.height = rb->internal_height / 2;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- rb->ssr.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->ssr.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ Size2i half_size = Size2i(rb->internal_width / 2, rb->internal_height / 2);
+ if (rb->ssr.output.is_null()) {
+ ss_effects->ssr_allocate_buffers(rb->ssr, _render_buffers_get_color_format(), ssr_roughness_quality, half_size, rb->view_count);
}
-
- if (rb->blur[0].texture.is_null()) {
- _allocate_blur_textures(rb);
+ RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS];
+ RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS];
+ for (uint32_t v = 0; v < rb->view_count; v++) {
+ texture_slices[v] = rb->views[v].view_texture;
+ depth_slices[v] = rb->views[v].view_depth;
}
-
- 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);
+ ss_effects->screen_space_reflection(rb->ssr, texture_slices, p_normal_slices, ssr_roughness_quality, p_metallic_slices, p_metallic_mask, depth_slices, half_size, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), rb->view_count, p_projections, p_eye_offsets);
+ copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->ssr.output, rb->view_count);
}
-void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
+void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) {
+ ERR_FAIL_NULL(ss_effects);
+
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
- ERR_FAIL_COND(!env);
+ ERR_FAIL_COND(p_environment.is_null());
RENDER_TIMESTAMP("Process SSAO");
- if (rb->ss_effects.ssao.ao_final.is_valid() && ssao_using_half_size != ssao_half_size) {
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_final);
-
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]);
-
- rb->ss_effects.ssao.ao_deinterleaved = RID();
- rb->ss_effects.ssao.ao_pong = RID();
- rb->ss_effects.ssao.ao_final = RID();
- rb->ss_effects.ssao.importance_map[0] = RID();
- rb->ss_effects.ssao.importance_map[1] = RID();
- rb->ss_effects.ssao.ao_deinterleaved_slices.clear();
- rb->ss_effects.ssao.ao_pong_slices.clear();
- }
-
- int buffer_width;
- int buffer_height;
- int half_width;
- int half_height;
- if (ssao_half_size) {
- buffer_width = (rb->internal_width + 3) / 4;
- buffer_height = (rb->internal_height + 3) / 4;
- half_width = (rb->internal_width + 7) / 8;
- half_height = (rb->internal_height + 7) / 8;
- } else {
- buffer_width = (rb->internal_width + 1) / 2;
- buffer_height = (rb->internal_height + 1) / 2;
- half_width = (rb->internal_width + 3) / 4;
- half_height = (rb->internal_height + 3) / 4;
- }
- bool uniform_sets_are_invalid = false;
- if (rb->ss_effects.ssao.ao_deinterleaved.is_null()) {
- {
- rb->ss_effects.ssao.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_deinterleaved, "SSAO De-interleaved Array");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_deinterleaved, i, 0);
- rb->ss_effects.ssao.ao_deinterleaved_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_pong, "SSAO De-interleaved Array Pong");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_pong, i, 0);
- rb->ss_effects.ssao.ao_pong_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = half_width;
- tf.height = half_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[0], "SSAO Importance Map");
- rb->ss_effects.ssao.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[1], "SSAO Importance Map Pong");
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->internal_width;
- tf.height = rb->internal_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_final, "SSAO Final");
- }
- ssao_using_half_size = ssao_half_size;
- uniform_sets_are_invalid = true;
- }
-
- EffectsRD::SSAOSettings settings;
- settings.radius = env->ssao_radius;
- settings.intensity = env->ssao_intensity;
- settings.power = env->ssao_power;
- settings.detail = env->ssao_detail;
- settings.horizon = env->ssao_horizon;
- settings.sharpness = env->ssao_sharpness;
+ RendererRD::SSEffects::SSAOSettings settings;
+ settings.radius = environment_get_ssao_radius(p_environment);
+ settings.intensity = environment_get_ssao_intensity(p_environment);
+ settings.power = environment_get_ssao_power(p_environment);
+ settings.detail = environment_get_ssao_detail(p_environment);
+ settings.horizon = environment_get_ssao_horizon(p_environment);
+ settings.sharpness = environment_get_ssao_sharpness(p_environment);
settings.quality = ssao_quality;
settings.half_size = ssao_half_size;
@@ -2142,152 +1709,26 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
settings.fadeout_from = ssao_fadeout_from;
settings.fadeout_to = ssao_fadeout_to;
settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height);
- 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);
+ ss_effects->ssao_allocate_buffers(rb->ss_effects.ssao, settings, rb->ss_effects.linear_depth);
+ ss_effects->generate_ssao(rb->ss_effects.ssao, p_normal_buffer, p_projection, settings);
}
-void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform) {
+void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) {
+ ERR_FAIL_NULL(ss_effects);
+
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
- ERR_FAIL_COND(!env);
+ ERR_FAIL_COND(p_environment.is_null());
RENDER_TIMESTAMP("Process SSIL");
- if (rb->ss_effects.ssil.ssil_final.is_valid() && ssil_using_half_size != ssil_half_size) {
- RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final);
- RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssil.pong);
- RD::get_singleton()->free(rb->ss_effects.ssil.edges);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]);
-
- rb->ss_effects.ssil.ssil_final = RID();
- rb->ss_effects.ssil.deinterleaved = RID();
- rb->ss_effects.ssil.pong = RID();
- rb->ss_effects.ssil.edges = RID();
- rb->ss_effects.ssil.deinterleaved_slices.clear();
- rb->ss_effects.ssil.pong_slices.clear();
- rb->ss_effects.ssil.edges_slices.clear();
- rb->ss_effects.ssil.importance_map[0] = RID();
- rb->ss_effects.ssil.importance_map[1] = RID();
- }
-
- int buffer_width;
- int buffer_height;
- int half_width;
- int half_height;
- if (ssil_half_size) {
- buffer_width = (rb->width + 3) / 4;
- buffer_height = (rb->height + 3) / 4;
- half_width = (rb->width + 7) / 8;
- half_height = (rb->height + 7) / 8;
- } else {
- buffer_width = (rb->width + 1) / 2;
- buffer_height = (rb->height + 1) / 2;
- half_width = (rb->width + 3) / 4;
- half_height = (rb->height + 3) / 4;
- }
- bool uniform_sets_are_invalid = false;
- if (rb->ss_effects.ssil.ssil_final.is_null()) {
- {
- rb->ss_effects.ssil.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- rb->ss_effects.ssil.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.ssil_final, "SSIL texture");
- RD::get_singleton()->texture_clear(rb->ss_effects.ssil.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1);
- if (rb->ss_effects.last_frame.is_null()) {
- tf.mipmaps = 6;
- rb->ss_effects.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.last_frame, "Last Frame Radiance");
- RD::get_singleton()->texture_clear(rb->ss_effects.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1);
- for (uint32_t i = 0; i < 6; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.last_frame, 0, i);
- rb->ss_effects.last_frame_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " ");
- }
- }
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.deinterleaved, "SSIL deinterleaved buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.deinterleaved, i, 0);
- rb->ss_effects.ssil.deinterleaved_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.pong, "SSIL deinterleaved pong buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.pong, i, 0);
- rb->ss_effects.ssil.pong_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.edges = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.edges, "SSIL edges buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.edges, i, 0);
- rb->ss_effects.ssil.edges_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = half_width;
- tf.height = half_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[0], "SSIL Importance Map");
- rb->ss_effects.ssil.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[1], "SSIL Importance Map Pong");
- }
- uniform_sets_are_invalid = true;
- ssil_using_half_size = ssil_half_size;
- }
-
- EffectsRD::SSILSettings settings;
- settings.radius = env->ssil_radius;
- settings.intensity = env->ssil_intensity;
- settings.sharpness = env->ssil_sharpness;
- settings.normal_rejection = env->ssil_normal_rejection;
+ RendererRD::SSEffects::SSILSettings settings;
+ settings.radius = environment_get_ssil_radius(p_environment);
+ settings.intensity = environment_get_ssil_intensity(p_environment);
+ settings.sharpness = environment_get_ssil_sharpness(p_environment);
+ settings.normal_rejection = environment_get_ssil_normal_rejection(p_environment);
settings.quality = ssil_quality;
settings.half_size = ssil_half_size;
@@ -2296,17 +1737,16 @@ void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environmen
settings.fadeout_from = ssil_fadeout_from;
settings.fadeout_to = ssil_fadeout_to;
settings.full_screen_size = Size2i(rb->width, rb->height);
- settings.half_screen_size = Size2i(buffer_width, buffer_height);
- settings.quarter_screen_size = Size2i(half_width, half_height);
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_projection;
+ Projection projection = correction * p_projection;
Transform3D transform = p_transform;
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();
+ Projection last_frame_projection = rb->ss_effects.last_frame_projection * Projection(rb->ss_effects.last_frame_transform.affine_inverse()) * Projection(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);
+ ss_effects->ssil_allocate_buffers(rb->ss_effects.ssil, settings, rb->ss_effects.linear_depth);
+ ss_effects->screen_space_indirect_lighting(rb->ss_effects.ssil, p_normal_buffer, p_projection, last_frame_projection, settings);
rb->ss_effects.last_frame_projection = projection;
rb->ss_effects.last_frame_transform = transform;
}
@@ -2315,15 +1755,15 @@ void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- if (rb->ss_effects.last_frame.is_valid()) {
- copy_effects->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height));
+ if (rb->ss_effects.ssil.last_frame.is_valid()) {
+ copy_effects->copy_to_rect(rb->texture, rb->ss_effects.ssil.last_frame, Rect2i(0, 0, rb->width, rb->height));
int width = rb->width;
int height = rb->height;
- for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) {
+ for (int i = 0; i < rb->ss_effects.ssil.last_frame_slices.size() - 1; i++) {
width = MAX(1, width >> 1);
height = MAX(1, height >> 1);
- copy_effects->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height));
+ copy_effects->make_mipmap(rb->ss_effects.ssil.last_frame_slices[i], rb->ss_effects.ssil.last_frame_slices[i + 1], Size2i(width, height));
}
}
}
@@ -2354,7 +1794,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));
}
@@ -2420,7 +1860,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
// Glow and override exposure (if enabled).
CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
@@ -2480,21 +1919,21 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RD::get_singleton()->draw_command_end_label();
}
- if (can_use_effects && env && env->auto_exposure) {
+ if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment)) {
RENDER_TIMESTAMP("Auto exposure");
RD::get_singleton()->draw_command_begin_label("Auto exposure");
if (rb->luminance.current.is_null()) {
_allocate_luminance_textures(rb);
}
- bool set_immediate = env->auto_exposure_version != rb->auto_exposure_version;
- rb->auto_exposure_version = env->auto_exposure_version;
+ bool set_immediate = environment_get_auto_exposure_version(p_render_data->environment) != rb->auto_exposure_version;
+ rb->auto_exposure_version = environment_get_auto_exposure_version(p_render_data->environment);
- double step = env->auto_exp_speed * time_step;
+ double step = environment_get_auto_exp_speed(p_render_data->environment) * 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, environment_get_min_luminance(p_render_data->environment), environment_get_max_luminance(p_render_data->environment), 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, environment_get_min_luminance(p_render_data->environment), environment_get_max_luminance(p_render_data->environment), step, set_immediate);
}
// Swap final reduce with prev luminance.
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
@@ -2508,7 +1947,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
int max_glow_level = -1;
- if (can_use_effects && env && env->glow_enabled) {
+ if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
RENDER_TIMESTAMP("Glow");
RD::get_singleton()->draw_command_begin_label("Gaussian Glow");
@@ -2519,7 +1958,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
- if (env->glow_levels[i] > 0.0) {
+ if (environment_get_glow_levels(p_render_data->environment)[i] > 0.0) {
if (i >= rb->blur[1].layers[0].mipmaps.size()) {
max_glow_level = rb->blur[1].layers[0].mipmaps.size() - 1;
} else {
@@ -2536,19 +1975,19 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
if (i == 0) {
RID luminance_texture;
- if (env->auto_exposure && rb->luminance.current.is_valid()) {
+ if (environment_get_auto_exposure(p_render_data->environment) && rb->luminance.current.is_valid()) {
luminance_texture = rb->luminance.current;
}
if (can_use_storage) {
- copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, environment_get_auto_exp_scale(p_render_data->environment));
} else {
- copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, environment_get_auto_exp_scale(p_render_data->environment));
}
} else {
if (can_use_storage) {
- copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality);
} else {
- copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality);
}
}
}
@@ -2563,36 +2002,36 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RendererRD::ToneMapper::TonemapSettings tonemap;
- if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) {
+ if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment) && rb->luminance.current.is_valid()) {
tonemap.use_auto_exposure = true;
tonemap.exposure_texture = rb->luminance.current;
- tonemap.auto_exposure_grey = env->auto_exp_scale;
+ tonemap.auto_exposure_grey = environment_get_auto_exp_scale(p_render_data->environment);
} else {
- tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
- if (can_use_effects && env && env->glow_enabled) {
+ if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
tonemap.use_glow = true;
- tonemap.glow_mode = RendererRD::ToneMapper::TonemapSettings::GlowMode(env->glow_blend_mode);
- tonemap.glow_intensity = env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity;
+ tonemap.glow_mode = RendererRD::ToneMapper::TonemapSettings::GlowMode(environment_get_glow_blend_mode(p_render_data->environment));
+ tonemap.glow_intensity = environment_get_glow_blend_mode(p_render_data->environment) == RS::ENV_GLOW_BLEND_MODE_MIX ? environment_get_glow_mix(p_render_data->environment) : environment_get_glow_intensity(p_render_data->environment);
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
- tonemap.glow_levels[i] = env->glow_levels[i];
+ tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i];
}
tonemap.glow_texture_size.x = rb->blur[1].layers[0].mipmaps[0].width;
tonemap.glow_texture_size.y = rb->blur[1].layers[0].mipmaps[0].height;
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;
tonemap.glow_texture = rb->blur[1].texture;
- if (env->glow_map.is_valid()) {
- tonemap.glow_map_strength = env->glow_map_strength;
- tonemap.glow_map = texture_storage->texture_get_rd_texture(env->glow_map);
+ if (environment_get_glow_map(p_render_data->environment).is_valid()) {
+ tonemap.glow_map_strength = environment_get_glow_map_strength(p_render_data->environment);
+ tonemap.glow_map = texture_storage->texture_get_rd_texture(environment_get_glow_map(p_render_data->environment));
} else {
tonemap.glow_map_strength = 0.0f;
- tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
} else {
- tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
@@ -2602,10 +2041,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.use_debanding = rb->use_debanding;
tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height);
- if (env) {
- tonemap.tonemap_mode = env->tone_mapper;
- tonemap.white = env->white;
- tonemap.exposure = env->exposure;
+ if (p_render_data->environment.is_valid()) {
+ tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment);
+ tonemap.white = environment_get_white(p_render_data->environment);
+ tonemap.exposure = environment_get_exposure(p_render_data->environment);
}
if (camfx && camfx->override_exposure_enabled) {
@@ -2614,17 +2053,17 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
- tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
-
- if (can_use_effects && env) {
- tonemap.use_bcs = env->adjustments_enabled;
- tonemap.brightness = env->adjustments_brightness;
- tonemap.contrast = env->adjustments_contrast;
- tonemap.saturation = env->adjustments_saturation;
- if (env->adjustments_enabled && env->color_correction.is_valid()) {
+ tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
+
+ if (can_use_effects && p_render_data->environment.is_valid()) {
+ tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment);
+ tonemap.brightness = environment_get_adjustments_brightness(p_render_data->environment);
+ tonemap.contrast = environment_get_adjustments_contrast(p_render_data->environment);
+ tonemap.saturation = environment_get_adjustments_saturation(p_render_data->environment);
+ if (environment_get_adjustments_enabled(p_render_data->environment) && environment_get_color_correction(p_render_data->environment).is_valid()) {
tonemap.use_color_correction = true;
- tonemap.use_1d_color_correction = env->use_1d_color_correction;
- tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction);
+ tonemap.use_1d_color_correction = environment_get_use_1d_color_correction(p_render_data->environment);
+ tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(environment_get_color_correction(p_render_data->environment));
}
}
@@ -2639,7 +2078,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();
}
@@ -2654,7 +2093,6 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
// Override exposure (if enabled).
CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
@@ -2664,10 +2102,10 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
RendererRD::ToneMapper::TonemapSettings tonemap;
- if (env) {
- tonemap.tonemap_mode = env->tone_mapper;
- tonemap.exposure = env->exposure;
- tonemap.white = env->white;
+ if (p_render_data->environment.is_valid()) {
+ tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment);
+ tonemap.exposure = environment_get_exposure(p_render_data->environment);
+ tonemap.white = environment_get_white(p_render_data->environment);
}
if (camfx && camfx->override_exposure_enabled) {
@@ -2677,32 +2115,32 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
// We don't support glow or auto exposure here, if they are needed, don't use subpasses!
// The problem is that we need to use the result so far and process them before we can
// apply this to our results.
- if (can_use_effects && env && env->glow_enabled) {
+ if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
ERR_FAIL_MSG("Glow is not supported when using subpasses.");
}
- if (can_use_effects && env && env->auto_exposure) {
+ if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment)) {
ERR_FAIL_MSG("Glow is not supported when using subpasses.");
}
tonemap.use_glow = false;
- tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
tonemap.use_auto_exposure = false;
- tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
- tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
-
- if (can_use_effects && env) {
- tonemap.use_bcs = env->adjustments_enabled;
- tonemap.brightness = env->adjustments_brightness;
- tonemap.contrast = env->adjustments_contrast;
- tonemap.saturation = env->adjustments_saturation;
- if (env->adjustments_enabled && env->color_correction.is_valid()) {
+ tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
+
+ if (can_use_effects && p_render_data->environment.is_valid()) {
+ tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment);
+ tonemap.brightness = environment_get_adjustments_brightness(p_render_data->environment);
+ tonemap.contrast = environment_get_adjustments_contrast(p_render_data->environment);
+ tonemap.saturation = environment_get_adjustments_saturation(p_render_data->environment);
+ if (environment_get_adjustments_enabled(p_render_data->environment) && environment_get_color_correction(p_render_data->environment).is_valid()) {
tonemap.use_color_correction = true;
- tonemap.use_1d_color_correction = env->use_1d_color_correction;
- tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction);
+ tonemap.use_1d_color_correction = environment_get_use_1d_color_correction(p_render_data->environment);
+ tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(environment_get_color_correction(p_render_data->environment));
}
}
@@ -2736,7 +2174,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
if (shadow_atlas_texture.is_null()) {
- shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
}
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
@@ -2806,18 +2244,6 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
}
}
-void RendererSceneRenderRD::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->adjustments_enabled = p_enable;
- env->adjustments_brightness = p_brightness;
- env->adjustments_contrast = p_contrast;
- env->adjustments_saturation = p_saturation;
- env->use_1d_color_correction = p_use_1d_color_correction;
- env->color_correction = p_color_correction;
-}
-
RID RendererSceneRenderRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
@@ -3022,7 +2448,7 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
return true;
}
-void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -3033,11 +2459,9 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
p_internal_width = p_width;
}
- if (p_width != p_internal_width) {
- float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
- material_storage->sampler_rd_configure_custom(fsr_mipmap_bias);
- update_uniform_sets();
- }
+ const float texture_mipmap_bias = -log2f(p_width / p_internal_width) + p_texture_mipmap_bias;
+ material_storage->sampler_rd_configure_custom(texture_mipmap_bias);
+ update_uniform_sets();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
@@ -3097,7 +2521,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;
}
@@ -3150,8 +2574,13 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
}
}
+ RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(rb->render_target);
+ if (is_vrs_supported() && vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
+ vrs->create_vrs_texture(p_internal_width, p_internal_height, p_view_count, rb->vrs_texture, rb->vrs_fb);
+ }
+
RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target);
- rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count);
+ rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count, rb->vrs_texture);
if (is_clustered_enabled()) {
rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
@@ -3175,7 +2604,7 @@ void RendererSceneRenderRD::sub_surface_scattering_set_scale(float p_scale, floa
sss_depth_scale = p_depth_scale;
}
-void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) {
+void RendererSceneRenderRD::positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) {
ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum");
if (shadows_quality != p_quality) {
@@ -3222,7 +2651,7 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) {
_update_shader_quality_settings();
}
-void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) {
+void RendererSceneRenderRD::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) {
ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum");
if (directional_shadow_quality != p_quality) {
@@ -3364,7 +2793,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);
@@ -3440,7 +2869,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
}
- light_data.shadow_enabled = p_using_shadows && light_storage->light_has_shadow(base);
+ light_data.shadow_opacity = p_using_shadows && light_storage->light_has_shadow(base) ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) : 0.0;
float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
if (angular_diameter > 0.0) {
@@ -3457,24 +2886,24 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
angular_diameter = 0.0;
}
- if (light_data.shadow_enabled) {
+ if (light_data.shadow_opacity > 0.001) {
RS::LightDirectionalShadowMode smode = light_storage->light_directional_get_shadow_mode(base);
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light_storage->light_directional_get_blend_splits(base);
for (int j = 0; j < 4; j++) {
Rect2 atlas_rect = li->shadow_transform[j].atlas_rect;
- CameraMatrix matrix = li->shadow_transform[j].camera;
+ Projection matrix = li->shadow_transform[j].camera;
float split = li->shadow_transform[MIN(limit, j)].split;
- CameraMatrix bias;
+ Projection bias;
bias.set_light_bias();
- CameraMatrix rectm;
+ Projection rectm;
rectm.set_light_atlas_rect(atlas_rect);
Transform3D modelview = (inverse_transform * li->shadow_transform[j].transform).inverse();
- CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
+ Projection shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
float bias_scale = li->shadow_transform[j].bias_scale;
light_data.shadow_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
@@ -3482,7 +2911,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
@@ -3611,19 +3040,26 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
// Reuse fade begin, fade length and distance for shadow LOD determination later.
float fade_begin = 0.0;
+ float fade_shadow = 0.0;
float fade_length = 0.0;
real_t distance = 0.0;
float fade = 1.0;
+ float shadow_opacity_fade = 1.0;
if (light_storage->light_is_distance_fade_enabled(li->light)) {
fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+ fade_shadow = light_storage->light_get_distance_fade_shadow(li->light);
fade_length = light_storage->light_get_distance_fade_length(li->light);
distance = camera_plane.distance_to(li->transform.origin);
+ // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
if (distance > fade_begin) {
- // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
}
+
+ if (distance > fade_shadow) {
+ shadow_opacity_fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_shadow) / fade_length);
+ }
}
float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
@@ -3691,7 +3127,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
bool in_shadow_range = true;
if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) {
- if (distance > light_storage->light_get_distance_fade_shadow(li->light)) {
+ if (distance > light_storage->light_get_distance_fade_shadow(li->light) + light_storage->light_get_distance_fade_length(li->light)) {
// Out of range, don't draw shadows to improve performance.
in_shadow_range = false;
}
@@ -3700,7 +3136,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
if (needs_shadow && in_shadow_range) {
// fill in the shadow information
- light_data.shadow_enabled = true;
+ light_data.shadow_opacity = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) * shadow_opacity_fade;
float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
@@ -3727,7 +3163,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.
@@ -3742,16 +3178,16 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.direction[1] = omni_offset.y * float(rect.size.height);
} else if (type == RS::LIGHT_SPOT) {
Transform3D modelview = (inverse_transform * light_transform).inverse();
- CameraMatrix bias;
+ Projection bias;
bias.set_light_bias();
- CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview;
- RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix);
+ Projection shadow_mtx = bias * li->shadow_transform[0].camera * modelview;
+ 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.
// Otherwise, performance would decrease with no visual difference.
- CameraMatrix cm = li->shadow_transform[0].camera;
+ Projection cm = li->shadow_transform[0].camera;
float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
} else {
@@ -3760,7 +3196,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
}
} else {
- light_data.shadow_enabled = false;
+ light_data.shadow_opacity = 0.0;
}
li->cull_mask = light_storage->light_get_cull_mask(base);
@@ -3865,7 +3301,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 +3339,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;
@@ -3962,242 +3398,10 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
////////////////////////////////////////////////////////////////////////////////
// FOG SHADER
-void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) {
- //compile
-
- code = p_code;
- valid = false;
- ubo_size = 0;
- uniforms.clear();
-
- if (code.is_empty()) {
- return; //just invalid, but no error
- }
-
- ShaderCompiler::GeneratedCode gen_code;
- ShaderCompiler::IdentifierActions actions;
- actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE;
-
- uses_time = false;
-
- actions.usage_flag_pointers["TIME"] = &uses_time;
-
- actions.uniforms = &uniforms;
-
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
-
- Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
- ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
-
- if (version.is_null()) {
- version = scene_singleton->volumetric_fog.shader.version_create();
- }
-
- scene_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
- ERR_FAIL_COND(!scene_singleton->volumetric_fog.shader.version_is_valid(version));
-
- ubo_size = gen_code.uniform_total_size;
- ubo_offsets = gen_code.uniform_offsets;
- texture_uniforms = gen_code.texture_uniforms;
-
- pipeline = RD::get_singleton()->compute_pipeline_create(scene_singleton->volumetric_fog.shader.version_get_shader(version, 0));
-
- valid = true;
-}
-
-void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
- if (!p_texture.is_valid()) {
- if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
- default_texture_params[p_name].erase(p_index);
-
- if (default_texture_params[p_name].is_empty()) {
- default_texture_params.erase(p_name);
- }
- }
- } else {
- if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = HashMap<int, RID>();
- }
- default_texture_params[p_name][p_index] = p_texture;
- }
-}
-
-void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- RBMap<int, StringName> order;
-
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- if (E.value.texture_order >= 0) {
- order[E.value.texture_order + 100000] = E.key;
- } else {
- order[E.value.order] = E.key;
- }
- }
-
- for (const KeyValue<int, StringName> &E : order) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
- pi.name = E.value;
- p_param_list->push_back(pi);
- }
-}
-
-void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- RendererMaterialStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E.value);
- p.info.name = E.key; //supply name
- p.index = E.value.instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
- p_param_list->push_back(p);
- }
-}
-
-bool RendererSceneRenderRD::FogShaderData::is_param_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
-bool RendererSceneRenderRD::FogShaderData::is_animated() const {
- return false;
-}
-
-bool RendererSceneRenderRD::FogShaderData::casts_shadows() const {
- return false;
-}
-
-Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const StringName &p_parameter) const {
- if (uniforms.has(p_parameter)) {
- ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
- Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
- }
- return Variant();
-}
-
-RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const {
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
-
- return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version);
-}
-
-RendererSceneRenderRD::FogShaderData::~FogShaderData() {
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
- ERR_FAIL_COND(!scene_singleton);
- //pipeline variants will clear themselves if shader is gone
- if (version.is_valid()) {
- scene_singleton->volumetric_fog.shader.version_free(version);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Fog material
-
-bool RendererSceneRenderRD::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
-
- uniform_set_updated = true;
-
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
-}
-
-RendererSceneRenderRD::FogMaterialData::~FogMaterialData() {
- free_parameters_uniform_set(uniform_set);
-}
-
-RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
- FogShaderData *shader_data = memnew(FogShaderData);
- return shader_data;
-}
-
-RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
- return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func();
-};
-
-RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
- FogMaterialData *material_data = memnew(FogMaterialData);
- material_data->shader_data = p_shader;
- //update will happen later anyway so do nothing.
- return material_data;
-}
-
-RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) {
- return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Volumetric Fog
-
-void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
- ERR_FAIL_COND(!rb->volumetric_fog);
-
- RD::get_singleton()->free(rb->volumetric_fog->prev_light_density_map);
- RD::get_singleton()->free(rb->volumetric_fog->light_density_map);
- RD::get_singleton()->free(rb->volumetric_fog->fog_map);
- RD::get_singleton()->free(rb->volumetric_fog->density_map);
- RD::get_singleton()->free(rb->volumetric_fog->light_map);
- RD::get_singleton()->free(rb->volumetric_fog->emissive_map);
-
- if (rb->volumetric_fog->fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
- }
- if (rb->volumetric_fog->process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) {
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set_density);
- }
- if (rb->volumetric_fog->process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
- }
- if (rb->volumetric_fog->process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set2)) {
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
- }
- if (rb->volumetric_fog->sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->sdfgi_uniform_set);
- }
- if (rb->volumetric_fog->sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sky_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->sky_uniform_set);
- }
-
- memdelete(rb->volumetric_fog);
-
- rb->volumetric_fog = nullptr;
-}
-
-Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) {
- Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point);
- view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera
- Vector3 fog_position = Vector3(0, 0, 0);
-
- view_position.y = -view_position.y;
- fog_position.z = -view_position.z / fog_end;
- fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5;
- fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5;
- fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread));
- fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5);
-
- fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x);
- fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y);
- fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z);
-
- return Vector3i(fog_position);
-}
-
-void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
+void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
float ratio = float(rb->width) / float((rb->width + rb->height) / 2);
uint32_t target_width = uint32_t(float(volumetric_fog_size) * ratio);
@@ -4205,694 +3409,49 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
if (rb->volumetric_fog) {
//validate
- if (!env || !env->volumetric_fog_enabled || rb->volumetric_fog->width != target_width || rb->volumetric_fog->height != target_height || rb->volumetric_fog->depth != volumetric_fog_depth) {
- _volumetric_fog_erase(rb);
+ if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment) || rb->volumetric_fog->width != target_width || rb->volumetric_fog->height != target_height || rb->volumetric_fog->depth != volumetric_fog_depth) {
+ memdelete(rb->volumetric_fog);
+ rb->volumetric_fog = nullptr;
}
}
- if (!env || !env->volumetric_fog_enabled) {
+ if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment)) {
//no reason to enable or update, bye
return;
}
- RENDER_TIMESTAMP("> Volumetric Fog");
- RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
-
- if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) {
+ if (p_environment.is_valid() && environment_get_volumetric_fog_enabled(p_environment) && !rb->volumetric_fog) {
//required volumetric fog but not existing, create
- rb->volumetric_fog = memnew(VolumetricFog);
- rb->volumetric_fog->width = target_width;
- rb->volumetric_fog->height = target_height;
- rb->volumetric_fog->depth = volumetric_fog_depth;
-
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = target_width;
- tf.height = target_height;
- tf.depth = volumetric_fog_depth;
- tf.texture_type = RD::TEXTURE_TYPE_3D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
-
- rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_density_map, "Fog light-density map");
-
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
-
- rb->volumetric_fog->prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->prev_light_density_map, "Fog previous light-density map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
-
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map");
-
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- Vector<uint8_t> dm;
- dm.resize(target_width * target_height * volumetric_fog_depth * 4);
- dm.fill(0);
-
- rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
- rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
- rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
-#else
- tf.format = RD::DATA_FORMAT_R32_UINT;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
- rb->volumetric_fog->light_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->light_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
- rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
-#endif
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.append_id(rb->volumetric_fog->fog_map);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky.sky_shader.default_shader_rd, RendererSceneSkyRD::SKY_SET_FOG);
- }
-
- if (p_fog_volumes.size() > 0) {
- RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
-
- RENDER_TIMESTAMP("Render FogVolumes");
-
- VolumetricFogShader::VolumeUBO params;
-
- Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
- Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
- float z_near = p_cam_projection.get_z_near();
- float z_far = p_cam_projection.get_z_far();
- float fog_end = env->volumetric_fog_length;
-
- Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
- Vector2 fog_near_size;
- if (p_cam_projection.is_orthogonal()) {
- fog_near_size = fog_far_size;
- } else {
- fog_near_size = Vector2();
- }
-
- params.fog_frustum_size_begin[0] = fog_near_size.x;
- params.fog_frustum_size_begin[1] = fog_near_size.y;
-
- params.fog_frustum_size_end[0] = fog_far_size.x;
- params.fog_frustum_size_end[1] = fog_far_size.y;
-
- params.fog_frustum_end = fog_end;
- params.z_near = z_near;
- params.z_far = z_far;
- params.time = time;
-
- params.fog_volume_size[0] = rb->volumetric_fog->width;
- params.fog_volume_size[1] = rb->volumetric_fog->height;
- params.fog_volume_size[2] = rb->volumetric_fog->depth;
-
- params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
- params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
- params.detail_spread = env->volumetric_fog_detail_spread;
- 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);
-
- RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
-
- if (rb->volumetric_fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 1;
- u.append_id(rb->volumetric_fog->emissive_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(volumetric_fog.volume_ubo);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 3;
- u.append_id(rb->volumetric_fog->density_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 4;
- u.append_id(rb->volumetric_fog->light_map);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
- }
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- bool any_uses_time = false;
-
- for (int i = 0; i < (int)p_fog_volumes.size(); i++) {
- FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]);
- ERR_FAIL_COND(!fog_volume_instance);
- RID fog_volume = fog_volume_instance->volume;
-
- RID fog_material = storage->fog_volume_get_material(fog_volume);
-
- FogMaterialData *material = nullptr;
-
- if (fog_material.is_valid()) {
- material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
-
- if (!material) {
- fog_material = volumetric_fog.default_material;
- material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
- }
-
- ERR_FAIL_COND(!material);
-
- FogShaderData *shader_data = material->shader_data;
-
- ERR_FAIL_COND(!shader_data);
-
- any_uses_time |= shader_data->uses_time;
-
- Vector3i min = Vector3i();
- Vector3i max = Vector3i();
- 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);
-
- if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
- // Local fog volume.
- Vector3i points[8];
- points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
-
- min = Vector3i(int32_t(rb->volumetric_fog->width) - 1, int32_t(rb->volumetric_fog->height) - 1, int32_t(rb->volumetric_fog->depth) - 1);
- max = Vector3i(1, 1, 1);
-
- for (int j = 0; j < 8; j++) {
- min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z));
- max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z));
- }
-
- kernel_size = max - min;
- } else {
- // Volume type global runs on all cells
- extents = Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
- min = Vector3i(0, 0, 0);
- kernel_size = Vector3i(int32_t(rb->volumetric_fog->width), int32_t(rb->volumetric_fog->height), int32_t(rb->volumetric_fog->depth));
- }
-
- if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
- continue;
- }
-
- volumetric_fog.push_constant.position[0] = position.x;
- volumetric_fog.push_constant.position[1] = position.y;
- volumetric_fog.push_constant.position[2] = position.z;
- volumetric_fog.push_constant.extents[0] = extents.x;
- volumetric_fog.push_constant.extents[1] = extents.y;
- volumetric_fog.push_constant.extents[2] = extents.z;
- 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);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &volumetric_fog.push_constant, sizeof(VolumetricFogShader::FogPushConstant));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
- if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
- }
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z);
- }
- if (any_uses_time || env->volumetric_fog_temporal_reprojection) {
- RenderingServerDefault::redraw_request();
- }
-
- RD::get_singleton()->draw_command_end_label();
-
- RD::get_singleton()->compute_list_end();
- }
-
- if (rb->volumetric_fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) {
- //re create uniform set if needed
- Vector<RD::Uniform> uniforms;
- Vector<RD::Uniform> copy_uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
- if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
- } else {
- u.append_id(shadow_atlas->depth);
- }
-
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
- if (directional_shadow.depth.is_valid()) {
- u.append_id(directional_shadow.depth);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
- }
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 3;
- u.append_id(get_omni_light_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 4;
- u.append_id(get_spot_light_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 5;
- u.append_id(get_directional_light_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 6;
- u.append_id(rb->cluster_builder->get_cluster_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 7;
- u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 8;
- u.append_id(rb->volumetric_fog->light_density_map);
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
- u.append_id(rb->volumetric_fog->fog_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
- u.append_id(rb->volumetric_fog->prev_light_density_map);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 10;
- u.append_id(shadow_sampler);
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 11;
- u.append_id(render_buffers_get_voxel_gi_buffer(p_render_buffers));
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 12;
- for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) {
- u.append_id(rb->rbgi.voxel_gi_textures[i]);
- }
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 13;
- u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 14;
- u.append_id(volumetric_fog.params_ubo);
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 15;
- u.append_id(rb->volumetric_fog->prev_light_density_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 16;
- u.append_id(rb->volumetric_fog->density_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 17;
- u.append_id(rb->volumetric_fog->light_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 18;
- u.append_id(rb->volumetric_fog->emissive_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 19;
- RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
- RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID();
- u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
-
- rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
-
- RID aux7 = uniforms.write[7].get_id(0);
- RID aux8 = uniforms.write[8].get_id(0);
-
- uniforms.write[7].set_id(0, aux8);
- uniforms.write[8].set_id(0, aux7);
-
- rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
-
- uniforms.remove_at(8);
- uniforms.write[7].set_id(0, aux7);
- rb->volumetric_fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
- }
-
- bool using_sdfgi = env->volumetric_fog_gi_inject > 0.0001 && env->sdfgi_enabled && (rb->sdfgi != nullptr);
-
- if (using_sdfgi) {
- if (rb->volumetric_fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.append_id(gi.sdfgi_ubo);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
- u.append_id(rb->sdfgi->ambient_texture);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
- u.append_id(rb->sdfgi->occlusion_texture);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
- }
- }
-
- rb->volumetric_fog->length = env->volumetric_fog_length;
- rb->volumetric_fog->spread = env->volumetric_fog_detail_spread;
-
- VolumetricFogShader::ParamsUBO params;
-
- Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
- Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
- float z_near = p_cam_projection.get_z_near();
- float z_far = p_cam_projection.get_z_far();
- float fog_end = env->volumetric_fog_length;
-
- Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
- Vector2 fog_near_size;
- if (p_cam_projection.is_orthogonal()) {
- fog_near_size = fog_far_size;
- } else {
- fog_near_size = Vector2();
- }
-
- params.fog_frustum_size_begin[0] = fog_near_size.x;
- params.fog_frustum_size_begin[1] = fog_near_size.y;
-
- params.fog_frustum_size_end[0] = fog_far_size.x;
- params.fog_frustum_size_end[1] = fog_far_size.y;
-
- params.ambient_inject = env->volumetric_fog_ambient_inject * env->ambient_light_energy;
- params.z_far = z_far;
-
- params.fog_frustum_end = fog_end;
-
- Color ambient_color = env->ambient_light.srgb_to_linear();
- params.ambient_color[0] = ambient_color.r;
- params.ambient_color[1] = ambient_color.g;
- params.ambient_color[2] = ambient_color.b;
- params.sky_contribution = env->ambient_sky_contribution;
-
- params.fog_volume_size[0] = rb->volumetric_fog->width;
- params.fog_volume_size[1] = rb->volumetric_fog->height;
- params.fog_volume_size[2] = rb->volumetric_fog->depth;
-
- params.directional_light_count = p_directional_light_count;
-
- Color emission = env->volumetric_fog_emission.srgb_to_linear();
- params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy;
- params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy;
- params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy;
- params.base_density = env->volumetric_fog_density;
-
- Color base_scattering = env->volumetric_fog_scattering.srgb_to_linear();
- params.base_scattering[0] = base_scattering.r;
- params.base_scattering[1] = base_scattering.g;
- params.base_scattering[2] = base_scattering.b;
- params.phase_g = env->volumetric_fog_anisotropy;
-
- params.detail_spread = env->volumetric_fog_detail_spread;
- params.gi_inject = env->volumetric_fog_gi_inject;
-
- params.cam_rotation[0] = p_cam_transform.basis[0][0];
- params.cam_rotation[1] = p_cam_transform.basis[1][0];
- params.cam_rotation[2] = p_cam_transform.basis[2][0];
- params.cam_rotation[3] = 0;
- params.cam_rotation[4] = p_cam_transform.basis[0][1];
- params.cam_rotation[5] = p_cam_transform.basis[1][1];
- params.cam_rotation[6] = p_cam_transform.basis[2][1];
- params.cam_rotation[7] = 0;
- params.cam_rotation[8] = p_cam_transform.basis[0][2];
- params.cam_rotation[9] = p_cam_transform.basis[1][2];
- params.cam_rotation[10] = p_cam_transform.basis[2][2];
- params.cam_rotation[11] = 0;
- params.filter_axis = 0;
- params.max_voxel_gi_instances = env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0;
- 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);
-
- params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
- params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
-
- {
- uint32_t cluster_size = rb->cluster_builder->get_cluster_size();
- params.cluster_shift = get_shift_from_power_of_2(cluster_size);
-
- uint32_t cluster_screen_width = (rb->width - 1) / cluster_size + 1;
- uint32_t cluster_screen_height = (rb->height - 1) / cluster_size + 1;
- params.max_cluster_element_count_div_32 = max_cluster_elements / 32;
- params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32);
- params.cluster_width = cluster_screen_width;
-
- params.screen_size[0] = rb->width;
- params.screen_size[1] = rb->height;
+ rb->volumetric_fog = memnew(RendererRD::Fog::VolumetricFog(Vector3i(target_width, target_height, volumetric_fog_depth), sky.sky_shader.default_shader_rd));
}
- 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);
-
- RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
-
- RENDER_TIMESTAMP("Render Fog");
- RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params, RD::BARRIER_MASK_COMPUTE);
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set_density, 0);
-
- if (using_sdfgi) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
- }
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- // Copy fog to history buffer
- if (env->volumetric_fog_temporal_reprojection) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->copy_uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- RD::get_singleton()->draw_command_end_label();
-
- if (volumetric_fog_filter_active) {
- RD::get_singleton()->draw_command_begin_label("Filter Fog");
-
- RENDER_TIMESTAMP("Filter Fog");
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
-
- RD::get_singleton()->compute_list_end();
- //need restart for buffer update
-
- params.filter_axis = 1;
- RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params);
+ if (rb->volumetric_fog) {
+ RendererRD::Fog::VolumetricFogSettings settings;
+ settings.rb_size = Vector2i(rb->width, rb->height);
+ settings.time = time;
+ settings.is_using_radiance_cubemap_array = is_using_radiance_cubemap_array();
+ settings.max_cluster_elements = max_cluster_elements;
+ settings.volumetric_fog_filter_active = volumetric_fog_filter_active;
+
+ settings.shadow_sampler = shadow_sampler;
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
+ settings.shadow_atlas_depth = shadow_atlas ? shadow_atlas->depth : RID();
+ settings.voxel_gl_buffer = render_buffers_get_voxel_gi_buffer(p_render_buffers);
+ settings.omni_light_buffer = get_omni_light_buffer();
+ settings.spot_light_buffer = get_spot_light_buffer();
+ settings.directional_shadow_depth = directional_shadow.depth;
+ settings.directional_light_buffer = get_directional_light_buffer();
- compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set2, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
+ settings.vfog = rb->volumetric_fog;
+ settings.cluster_builder = rb->cluster_builder;
+ settings.rbgi = &rb->rbgi;
+ settings.sdfgi = rb->sdfgi;
+ settings.env = p_environment;
+ settings.sky = &sky;
+ settings.gi = &gi;
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label();
+ RendererRD::Fog::get_singleton()->volumetric_fog_update(settings, p_cam_projection, p_cam_transform, p_prev_cam_inv_transform, p_shadow_atlas, p_directional_light_count, p_use_directional_shadows, p_positional_light_count, p_voxel_gi_count, p_fog_volumes);
}
-
- RENDER_TIMESTAMP("Integrate Fog");
- RD::get_singleton()->draw_command_begin_label("Integrate Fog");
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1);
-
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
-
- RENDER_TIMESTAMP("< Volumetric Fog");
- RD::get_singleton()->draw_command_end_label();
- RD::get_singleton()->draw_command_end_label();
}
bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) {
@@ -4914,8 +3473,7 @@ void RendererSceneRenderRD::_post_prepass_render(RenderDataRD *p_render_data, bo
return;
}
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
- rb->sdfgi->update_probes(env, sky.sky_owner.get_or_null(env->sky));
+ rb->sdfgi->update_probes(p_render_data->environment, sky.sky_owner.get_or_null(environment_get_sky(p_render_data->environment)));
}
}
}
@@ -4928,7 +3486,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo
}
}
-void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID *p_normal_roughness_views, RID p_voxel_gi_buffer) {
+void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices) {
// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
@@ -5003,7 +3561,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
//start GI
if (render_gi) {
- gi.process_gi(p_render_data->render_buffers, p_normal_roughness_views, p_voxel_gi_buffer, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this);
+ gi.process_gi(p_render_data->render_buffers, p_normal_roughness_slices, p_voxel_gi_buffer, p_vrs_slices, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this);
}
//Do shadow rendering (in parallel with GI)
@@ -5015,7 +3573,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier
}
- if (p_render_data->render_buffers.is_valid()) {
+ if (p_render_data->render_buffers.is_valid() && ss_effects) {
if (p_use_ssao || p_use_ssil) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
@@ -5040,17 +3598,17 @@ 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);
+ ss_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) {
- // TODO make these proper stereo and thus use p_normal_roughness_views correctly
- _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_views[0], p_render_data->cam_projection);
+ // TODO make these proper stereo
+ _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection);
}
if (p_use_ssil) {
- // TODO make these proper stereo and thus use p_normal_roughness_views correctly
- _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_views[0], p_render_data->cam_projection, p_render_data->cam_transform);
+ // TODO make these proper stereo
+ _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection, p_render_data->cam_transform);
}
}
@@ -5086,7 +3644,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
if (p_render_data->render_buffers.is_valid()) {
bool directional_shadows = false;
for (uint32_t i = 0; i < directional_light_count; i++) {
- if (cluster.directional_lights[i].shadow_enabled) {
+ if (cluster.directional_lights[i].shadow_opacity > 0.001) {
directional_shadows = true;
break;
}
@@ -5097,7 +3655,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
// getting this here now so we can direct call a bunch of things more easily
@@ -5189,7 +3747,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
@@ -5239,6 +3797,11 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements();
}
+ if (rb != nullptr && rb->vrs_fb.is_valid()) {
+ // vrs_fb will only be valid if vrs is enabled
+ vrs->update_vrs_texture(rb->vrs_fb, rb->render_target);
+ }
+
_render_scene(&render_data, clear_color);
if (p_render_buffers.is_valid()) {
@@ -5287,7 +3850,7 @@ void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) {
}
}
-void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) {
+void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) {
LightInstance *light_instance = light_instance_owner.get_or_null(p_light);
ERR_FAIL_COND(!light_instance);
@@ -5308,7 +3871,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
bool flip_y = false;
- CameraMatrix light_projection;
+ Projection light_projection;
Transform3D light_transform;
if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
@@ -5450,7 +4013,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true);
//restore transform so it can be properly used
- light_instance_set_shadow_transform(p_light, CameraMatrix(), light_instance->transform, zfar, 0, 0, 0);
+ light_instance_set_shadow_transform(p_light, Projection(), light_instance->transform, zfar, 0, 0, 0);
}
} else {
@@ -5459,16 +4022,16 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
}
}
-void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
_render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region);
}
-void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
+void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) {
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider));
Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
- CameraMatrix cm;
+ Projection cm;
cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0);
Vector3 cam_pos = p_transform.origin;
@@ -5493,15 +4056,15 @@ bool RendererSceneRenderRD::free(RID p_rid) {
rb->sdfgi = nullptr;
}
if (rb->volumetric_fog) {
- _volumetric_fog_erase(rb);
+ memdelete(rb->volumetric_fog);
+ rb->volumetric_fog = nullptr;
}
if (rb->cluster_builder) {
memdelete(rb->cluster_builder);
}
render_buffers_owner.free(p_rid);
- } else if (environment_owner.owns(p_rid)) {
- //not much to delete, just free it
- environment_owner.free(p_rid);
+ } else if (is_environment(p_rid)) {
+ environment_free(p_rid);
} else if (camera_effects_owner.owns(p_rid)) {
//not much to delete, just free it
camera_effects_owner.free(p_rid);
@@ -5568,8 +4131,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
} else if (shadow_atlas_owner.owns(p_rid)) {
shadow_atlas_set_size(p_rid, 0);
shadow_atlas_owner.free(p_rid);
- } else if (fog_volume_instance_owner.owns(p_rid)) {
- fog_volume_instance_owner.free(p_rid);
+ } else if (RendererRD::Fog::get_singleton()->owns_fog_volume_instance(p_rid)) {
+ RendererRD::Fog::get_singleton()->fog_instance_free(p_rid);
} else {
return false;
}
@@ -5641,7 +4204,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
//RID sampled_light;
- GeometryInstance *gi = geometry_instance_create(p_base);
+ RenderGeometryInstance *gi = geometry_instance_create(p_base);
uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base);
Vector<RID> materials;
@@ -5653,7 +4216,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
}
}
- geometry_instance_set_surface_materials(gi, materials);
+ gi->set_surface_materials(materials);
if (cull_argument.size() == 0) {
cull_argument.push_back(nullptr);
@@ -5735,6 +4298,10 @@ int RendererSceneRenderRD::get_max_directional_lights() const {
return cluster.max_directional_lights;
}
+bool RendererSceneRenderRD::is_vrs_supported() const {
+ return RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS);
+}
+
bool RendererSceneRenderRD::is_dynamic_gi_supported() const {
// usable by default (unless low end = true)
return true;
@@ -5754,14 +4321,11 @@ 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;
}
void RendererSceneRenderRD::init() {
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
max_cluster_elements = get_max_elements();
directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
@@ -5769,12 +4333,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
@@ -5812,124 +4376,7 @@ void RendererSceneRenderRD::init() {
}
if (is_volumetric_supported()) {
- {
- // Initialize local fog shader
- Vector<String> volumetric_fog_modes;
- volumetric_fog_modes.push_back("");
- volumetric_fog.shader.initialize(volumetric_fog_modes);
-
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
- volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
- }
-
- {
- ShaderCompiler::DefaultIdentifierActions actions;
-
- actions.renames["TIME"] = "scene_params.time";
- actions.renames["PI"] = _MKSTR(Math_PI);
- actions.renames["TAU"] = _MKSTR(Math_TAU);
- actions.renames["E"] = _MKSTR(Math_E);
- actions.renames["WORLD_POSITION"] = "world.xyz";
- actions.renames["OBJECT_POSITION"] = "params.position";
- actions.renames["UVW"] = "uvw";
- actions.renames["EXTENTS"] = "params.extents";
- actions.renames["ALBEDO"] = "albedo";
- actions.renames["DENSITY"] = "density";
- actions.renames["EMISSION"] = "emission";
- actions.renames["SDF"] = "sdf";
-
- actions.usage_defines["SDF"] = "#define SDF_USED\n";
- actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n";
- actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n";
- actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n";
-
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL;
- actions.base_uniform_string = "material.";
-
- actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
- actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
- actions.global_buffer_array_variable = "global_variables.data";
-
- volumetric_fog.compiler.initialize(actions);
- }
-
- {
- // default material and shader for fog shader
- volumetric_fog.default_shader = material_storage->shader_allocate();
- material_storage->shader_initialize(volumetric_fog.default_shader);
- material_storage->shader_set_code(volumetric_fog.default_shader, R"(
-// Default fog shader.
-
-shader_type fog;
-
-void fog() {
- DENSITY = 1.0;
- ALBEDO = vec3(1.0);
-}
-)");
- volumetric_fog.default_material = material_storage->material_allocate();
- material_storage->material_initialize(volumetric_fog.default_material);
- material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
-
- FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG));
- volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
-
- Vector<RD::Uniform> uniforms;
-
- {
- Vector<RID> ids;
- ids.resize(12);
- RID *ids_ptr = ids.ptrw();
- ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-
- RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
- uniforms.push_back(u);
- }
-
- volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE);
- }
- {
- String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n";
- defines += "\n#define MAX_SKY_LOD " + itos(get_roughness_layers() - 1) + ".0\n";
- if (is_using_radiance_cubemap_array()) {
- defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
- }
- Vector<String> volumetric_fog_modes;
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
- volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
- volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
- volumetric_fog_modes.push_back("\n#define MODE_COPY\n");
-
- volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines);
- volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
- for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
- volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i));
- }
- volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
- }
+ RendererRD::Fog::get_singleton()->init_fog_shader(cluster.max_directional_lights, get_roughness_layers(), is_using_radiance_cubemap_array());
}
{
@@ -5960,8 +4407,8 @@ void fog() {
directional_soft_shadow_kernel = memnew_arr(float, 128);
penumbra_shadow_kernel = memnew_arr(float, 128);
soft_shadow_kernel = memnew_arr(float, 128);
- shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/shadows/soft_shadow_quality"))));
- directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_quality"))));
+ positional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality"))));
+ directional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality"))));
environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"));
@@ -5975,11 +4422,13 @@ void fog() {
bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage));
copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage));
tone_mapper = memnew(RendererRD::ToneMapper);
+ vrs = memnew(RendererRD::VRS);
+ if (can_use_storage) {
+ ss_effects = memnew(RendererRD::SSEffects);
+ }
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
if (bokeh_dof) {
memdelete(bokeh_dof);
}
@@ -5989,6 +4438,12 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
if (tone_mapper) {
memdelete(tone_mapper);
}
+ if (vrs) {
+ memdelete(vrs);
+ }
+ if (ss_effects) {
+ memdelete(ss_effects);
+ }
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
RD::get_singleton()->free(E.value.cubemap);
@@ -6003,11 +4458,7 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
}
if (is_volumetric_supported()) {
- volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
- RD::get_singleton()->free(volumetric_fog.volume_ubo);
- RD::get_singleton()->free(volumetric_fog.params_ubo);
- material_storage->shader_free(volumetric_fog.default_shader);
- material_storage->material_free(volumetric_fog.default_material);
+ RendererRD::Fog::get_singleton()->free_fog_shader();
}
memdelete_arr(directional_penumbra_shadow_kernel);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 3f03f857f7..22e9ead243 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_RD_H
-#define RENDERING_SERVER_SCENE_RENDER_RD_H
+#ifndef RENDERER_SCENE_RENDER_RD_H
+#define RENDERER_SCENE_RENDER_RD_H
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
@@ -37,13 +37,12 @@
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
+#include "servers/rendering/renderer_rd/effects/ss_effects.h"
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
+#include "servers/rendering/renderer_rd/effects/vrs.h"
+#include "servers/rendering/renderer_rd/environment/fog.h"
#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_rd/environment/sky.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -52,24 +51,24 @@ struct RenderDataRD {
RID render_buffers;
Transform3D cam_transform;
- CameraMatrix cam_projection;
+ Projection cam_projection;
Vector2 taa_jitter;
bool cam_orthogonal = false;
// For stereo rendering
uint32_t view_count = 1;
Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS];
- CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
Transform3D prev_cam_transform;
- CameraMatrix prev_cam_projection;
+ Projection prev_cam_projection;
Vector2 prev_taa_jitter;
- CameraMatrix prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
float z_near = 0.0;
float z_far = 0.0;
- const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr;
+ const PagedArray<RenderGeometryInstance *> *instances = nullptr;
const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr;
const PagedArray<RID> *voxel_gi_instances = nullptr;
@@ -98,19 +97,19 @@ struct RenderDataRD {
};
class RendererSceneRenderRD : public RendererSceneRender {
- friend RendererSceneSkyRD;
+ friend RendererRD::SkyRD;
friend RendererRD::GI;
protected:
- RendererStorageRD *storage = nullptr;
RendererRD::BokehDOF *bokeh_dof = nullptr;
RendererRD::CopyEffects *copy_effects = nullptr;
RendererRD::ToneMapper *tone_mapper = nullptr;
+ RendererRD::VRS *vrs = nullptr;
double time = 0.0;
double time_step = 0.0;
struct RenderBufferData {
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) = 0;
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) = 0;
virtual ~RenderBufferData() {}
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
@@ -122,16 +121,16 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0;
virtual void _render_shadow_begin() = 0;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0;
virtual void _render_shadow_process() = 0;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
- void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
+ void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
void _debug_draw_cluster(RID p_render_buffers);
RenderBufferData *render_buffers_get_data(RID p_render_buffers);
@@ -140,10 +139,11 @@ protected:
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0;
- void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
- void _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);
- void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera);
- void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform);
+ void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
+ void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
+ void _process_sss(RID p_render_buffers, const Projection &p_camera);
+ void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
+
void _copy_framebuffer_to_ssil(RID p_render_buffers);
void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far);
@@ -151,7 +151,7 @@ protected:
void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi);
- void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID *p_normal_roughness_views, RID p_voxel_gi_buffer);
+ void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices);
void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
@@ -160,19 +160,12 @@ protected:
void _disable_clear_request(const RenderDataRD *p_render_data);
// needed for a single argument calls (material and uv2)
- PagedArrayPool<GeometryInstance *> cull_argument_pool;
- PagedArray<GeometryInstance *> cull_argument; //need this to exist
+ PagedArrayPool<RenderGeometryInstance *> cull_argument_pool;
+ PagedArray<RenderGeometryInstance *> cull_argument; //need this to exist
+ RendererRD::SSEffects *ss_effects = nullptr;
RendererRD::GI gi;
- RendererSceneSkyRD sky;
-
- RendererSceneEnvironmentRD *get_environment(RID p_environment) {
- if (p_environment.is_valid()) {
- return environment_owner.get_or_null(p_environment);
- } else {
- return nullptr;
- }
- };
+ RendererRD::SkyRD sky;
//used for mobile renderer mostly
@@ -209,7 +202,7 @@ private:
struct Reflection {
RID owner;
- RendererSceneSkyRD::ReflectionData data;
+ RendererRD::SkyRD::ReflectionData data;
RID fbs[6];
};
@@ -362,7 +355,7 @@ private:
struct LightInstance {
struct ShadowTransform {
- CameraMatrix camera;
+ Projection camera;
Transform3D transform;
float farplane;
float split;
@@ -404,21 +397,10 @@ private:
mutable RID_Owner<LightInstance> light_instance_owner;
- /* FOG VOLUMES */
-
- struct FogVolumeInstance {
- RID volume;
- Transform3D transform;
- bool active = false;
- };
-
- mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
-
/* ENVIRONMENT */
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
bool ssao_half_size = false;
- bool ssao_using_half_size = false;
float ssao_adaptive_target = 0.5;
int ssao_blur_passes = 2;
float ssao_fadeout_from = 50.0;
@@ -436,8 +418,6 @@ private:
bool glow_high_quality = false;
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
- mutable RID_Owner<RendererSceneEnvironmentRD, true> environment_owner;
-
/* CAMERA EFFECTS */
struct CameraEffects {
@@ -469,8 +449,6 @@ private:
ClusterBuilderSharedDataRD cluster_builder_shared;
ClusterBuilderRD *current_cluster_builder = nullptr;
- struct VolumetricFog;
-
struct RenderBuffers {
RenderBufferData *data = nullptr;
int internal_width = 0;
@@ -494,6 +472,8 @@ private:
RID depth_texture; //main depth texture
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
+ RID vrs_texture; // texture for vrs.
+ RID vrs_fb; // framebuffer to write to our vrs texture
// Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images)
struct View {
@@ -504,8 +484,8 @@ private:
Vector<View> views;
RendererRD::GI::SDFGI *sdfgi = nullptr;
- VolumetricFog *volumetric_fog = nullptr;
RendererRD::GI::RenderBuffersGI rbgi;
+ RendererRD::Fog::VolumetricFog *volumetric_fog = nullptr;
ClusterBuilderRD *cluster_builder = nullptr;
@@ -559,47 +539,14 @@ private:
RID downsample_uniform_set;
- RID last_frame;
- Vector<RID> last_frame_slices;
-
- CameraMatrix last_frame_projection;
+ Projection last_frame_projection;
Transform3D last_frame_transform;
- struct SSAO {
- RID ao_deinterleaved;
- Vector<RID> ao_deinterleaved_slices;
- RID ao_pong;
- Vector<RID> ao_pong_slices;
- RID ao_final;
- RID importance_map[2];
- RID depth_texture_view;
-
- RID gather_uniform_set;
- RID importance_map_uniform_set;
- } ssao;
-
- struct SSIL {
- RID ssil_final;
- RID deinterleaved;
- Vector<RID> deinterleaved_slices;
- RID pong;
- Vector<RID> pong_slices;
- RID edges;
- Vector<RID> edges_slices;
- RID importance_map[2];
- RID depth_texture_view;
-
- RID gather_uniform_set;
- RID importance_map_uniform_set;
- RID projection_uniform_set;
- } ssil;
+ RendererRD::SSEffects::SSAORenderBuffers ssao;
+ RendererRD::SSEffects::SSILRenderBuffers ssil;
} ss_effects;
- struct SSR {
- RID normal_scaled;
- RID depth_scaled;
- RID blur_radius[2];
- } ssr;
+ RendererRD::SSEffects::SSRRenderBuffers ssr;
struct TAA {
RID history;
@@ -661,7 +608,7 @@ private:
float inv_spot_attenuation;
float cos_spot_angle;
float specular_amount;
- uint32_t shadow_enabled;
+ float shadow_opacity;
float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
float shadow_matrix[16];
@@ -686,7 +633,7 @@ private:
float softshadow_angle;
float soft_shadow_scale;
uint32_t blend_splits;
- uint32_t shadow_enabled;
+ float shadow_opacity;
float fade_from;
float fade_to;
uint32_t pad[2];
@@ -778,203 +725,6 @@ private:
bool depth_prepass_used; // this does not seem used anywhere...
} render_state;
- struct VolumetricFog {
- enum {
- MAX_TEMPORAL_FRAMES = 16
- };
-
- uint32_t width = 0;
- uint32_t height = 0;
- uint32_t depth = 0;
-
- float length;
- float spread;
-
- RID light_density_map;
- RID prev_light_density_map;
- RID fog_map;
- RID density_map;
- RID light_map;
- RID emissive_map;
-
- RID fog_uniform_set;
- RID copy_uniform_set;
- RID process_uniform_set_density;
- RID process_uniform_set;
- RID process_uniform_set2;
- RID sdfgi_uniform_set;
- RID sky_uniform_set;
-
- int last_shadow_filter = -1;
- };
-
- struct VolumetricFogShader {
- enum FogSet {
- FOG_SET_BASE,
- FOG_SET_UNIFORMS,
- FOG_SET_MATERIAL,
- FOG_SET_MAX,
- };
-
- struct FogPushConstant {
- float position[3];
- float pad;
-
- float extents[3];
- float pad2;
-
- int32_t corner[3];
- uint32_t shape;
-
- float transform[16];
- };
-
- struct VolumeUBO {
- float fog_frustum_size_begin[2];
- float fog_frustum_size_end[2];
-
- float fog_frustum_end;
- float z_near;
- float z_far;
- float time;
-
- int32_t fog_volume_size[3];
- uint32_t directional_light_count;
-
- uint32_t use_temporal_reprojection;
- uint32_t temporal_frame;
- float detail_spread;
- float temporal_blend;
-
- float to_prev_view[16];
- float transform[16];
- };
-
- ShaderCompiler compiler;
- VolumetricFogShaderRD shader;
- FogPushConstant push_constant;
- RID volume_ubo;
-
- RID default_shader;
- RID default_material;
- RID default_shader_rd;
-
- RID base_uniform_set;
-
- RID params_ubo;
-
- enum {
- VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
- VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
- VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
- VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
- VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
- VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
- };
-
- struct ParamsUBO {
- float fog_frustum_size_begin[2];
- float fog_frustum_size_end[2];
-
- float fog_frustum_end;
- float ambient_inject;
- float z_far;
- uint32_t filter_axis;
-
- float ambient_color[3];
- float sky_contribution;
-
- int32_t fog_volume_size[3];
- uint32_t directional_light_count;
-
- float base_emission[3];
- float base_density;
-
- float base_scattering[3];
- float phase_g;
-
- float detail_spread;
- float gi_inject;
- uint32_t max_voxel_gi_instances;
- uint32_t cluster_type_size;
-
- float screen_size[2];
- uint32_t cluster_shift;
- uint32_t cluster_width;
-
- uint32_t max_cluster_element_count_div_32;
- uint32_t use_temporal_reprojection;
- uint32_t temporal_frame;
- float temporal_blend;
-
- float cam_rotation[12];
- float to_prev_view[16];
- float radiance_inverse_xform[12];
- };
-
- VolumetricFogProcessShaderRD process_shader;
-
- RID process_shader_version;
- RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
-
- } volumetric_fog;
-
- uint32_t volumetric_fog_depth = 128;
- uint32_t volumetric_fog_size = 128;
- bool volumetric_fog_filter_active = true;
-
- Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
- void _volumetric_fog_erase(RenderBuffers *rb);
- void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
-
- struct FogShaderData : public RendererRD::ShaderData {
- bool valid = false;
- RID version;
-
- RID pipeline;
- HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
-
- Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size = 0;
-
- String path;
- String code;
- HashMap<StringName, HashMap<int, RID>> default_texture_params;
-
- bool uses_time = false;
-
- virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
- virtual bool is_animated() const;
- virtual bool casts_shadows() const;
- virtual Variant get_default_parameter(const StringName &p_parameter) const;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const;
-
- FogShaderData() {}
- virtual ~FogShaderData();
- };
-
- struct FogMaterialData : public RendererRD::MaterialData {
- FogShaderData *shader_data = nullptr;
- RID uniform_set;
- bool uniform_set_updated;
-
- virtual void set_render_priority(int p_priority) {}
- virtual void set_next_pass(RID p_pass) {}
- virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~FogMaterialData();
- };
-
- RendererRD::ShaderData *_create_fog_shader_func();
- static RendererRD::ShaderData *_create_fog_shader_funcs();
-
- RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
- static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader);
-
RID shadow_sampler;
uint64_t scene_pass = 0;
@@ -989,11 +739,18 @@ private:
uint32_t max_cluster_elements = 512;
- void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr);
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr);
+
+ /* Volumetric Fog */
+
+ uint32_t volumetric_fog_size = 128;
+ uint32_t volumetric_fog_depth = 128;
+ bool volumetric_fog_filter_active = true;
+
+ void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
public:
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0;
+ static RendererSceneRenderRD *get_singleton() { return singleton; }
/* GI */
@@ -1055,65 +812,16 @@ public:
/* ENVIRONMENT API */
- virtual RID environment_allocate() override;
- virtual void environment_initialize(RID p_rid) override;
-
- virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override;
- virtual void environment_set_sky(RID p_env, RID p_sky) override;
- virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) override;
- virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override;
- virtual void environment_set_bg_color(RID p_env, const Color &p_color) override;
- virtual void environment_set_bg_energy(RID p_env, float p_energy) override;
- virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override;
- virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override;
-
- virtual RS::EnvironmentBG environment_get_background(RID p_env) const override;
- RID environment_get_sky(RID p_env) const;
- float environment_get_sky_custom_fov(RID p_env) const;
- Basis environment_get_sky_orientation(RID p_env) const;
- Color environment_get_bg_color(RID p_env) const;
- float environment_get_bg_energy(RID p_env) const;
- virtual int environment_get_canvas_max_layer(RID p_env) const override;
- Color environment_get_ambient_light_color(RID p_env) const;
- RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
- float environment_get_ambient_light_energy(RID p_env) const;
- float environment_get_ambient_sky_contribution(RID p_env) const;
- RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
-
- virtual bool is_environment(RID p_env) const override;
-
- virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override;
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) override;
virtual void environment_glow_set_use_high_quality(bool p_enable) override;
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override;
- bool environment_is_fog_enabled(RID p_env) const;
- Color environment_get_fog_light_color(RID p_env) const;
- float environment_get_fog_light_energy(RID p_env) const;
- float environment_get_fog_sun_scatter(RID p_env) const;
- float environment_get_fog_density(RID p_env) const;
- float environment_get_fog_height(RID p_env) const;
- float environment_get_fog_height_density(RID p_env) const;
- float environment_get_fog_aerial_perspective(RID p_env) const;
-
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override;
-
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override;
- virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override;
- virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override;
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
- virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override;
+
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
- bool environment_is_ssao_enabled(RID p_env) const;
- float environment_get_ssao_ao_affect(RID p_env) const;
- float environment_get_ssao_light_affect(RID p_env) const;
- bool environment_is_ssil_enabled(RID p_env) const;
- bool environment_is_ssr_enabled(RID p_env) const;
- bool environment_is_sdfgi_enabled(RID p_env) const;
-
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override;
+
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override;
virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override;
@@ -1121,9 +829,6 @@ public:
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override;
RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const;
- virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override;
- virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override;
-
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
/* CAMERA EFFECTS */
@@ -1148,7 +853,7 @@ public:
virtual RID light_instance_create(RID p_light) override;
virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
- virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
virtual void light_instance_mark_visible(RID p_light_instance) override;
_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
@@ -1197,7 +902,7 @@ public:
return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size));
}
- _FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
+ _FORCE_INLINE_ Projection light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->shadow_transform[p_index].camera;
}
@@ -1391,7 +1096,7 @@ public:
virtual RID voxel_gi_instance_create(RID p_base) override;
virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override;
virtual bool voxel_gi_needs_update(RID p_probe) const override;
- virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override;
+ virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override;
virtual void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) override { gi.voxel_gi_quality = p_quality; }
/* render buffers */
@@ -1400,7 +1105,7 @@ public:
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
virtual RID render_buffers_create() override;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
virtual void gi_set_use_half_resolution(bool p_enable) override;
RID render_buffers_get_depth_texture(RID p_render_buffers);
@@ -1434,11 +1139,11 @@ public:
virtual void update_uniform_sets(){};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
- virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override;
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override;
virtual void set_scene_pass(uint64_t p_pass) override {
scene_pass = p_pass;
@@ -1456,8 +1161,8 @@ public:
RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override;
- virtual void shadows_quality_set(RS::ShadowQuality p_quality) override;
- virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) override;
+ virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
+ virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
virtual void decals_set_filter(RS::DecalFilter p_filter) override;
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
@@ -1505,6 +1210,7 @@ public:
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override;
+ virtual bool is_vrs_supported() const;
virtual bool is_dynamic_gi_supported() const;
virtual bool is_clustered_enabled() const;
virtual bool is_volumetric_supported() const;
@@ -1512,8 +1218,8 @@ public:
void init();
- RendererSceneRenderRD(RendererStorageRD *p_storage);
+ RendererSceneRenderRD();
~RendererSceneRenderRD();
};
-#endif // RASTERIZER_SCENE_RD_H
+#endif // RENDERER_SCENE_RENDER_RD_H
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/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 04e05380f1..c9b6d09d4c 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -177,7 +177,7 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
builder.append(String("#define ") + String(E.key) + "_CODE_USED\n");
}
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
builder.append("#define MOLTENVK_USED\n");
#endif
} break;
@@ -476,7 +476,9 @@ void ShaderRD::_compile_version(Version *p_version) {
#if 1
- RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, p_version, variant_defines.size(), -1, true, SNAME("ShaderCompilation"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
#else
for (int i = 0; i < variant_defines.size(); i++) {
_compile_variant(i, p_version);
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/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index 12f57b0178..2ea6965c09 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -138,10 +138,10 @@ layout(set = 0, binding = 7) uniform texture2D sdf_texture;
layout(set = 0, binding = 8) uniform sampler material_samplers[12];
-layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
/* SET1: Is reserved for the material */
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/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
index 9787c9879d..1c17eabb56 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
@@ -88,7 +88,7 @@ layout(set = 0, binding = 0) uniform sampler2DArray source_color;
layout(set = 1, binding = 0) uniform sampler2DArray source_depth;
layout(location = 1) out float depth;
#endif /* MODE_TWO_SOURCES */
-#else
+#else /* MULTIVIEW */
layout(set = 0, binding = 0) uniform sampler2D source_color;
#ifdef MODE_TWO_SOURCES
layout(set = 1, binding = 0) uniform sampler2D source_color2;
@@ -139,7 +139,7 @@ void main() {
//uv.y = 1.0 - uv.y;
uv = 1.0 - uv;
}
-#endif
+#endif /* MODE_PANORAMA_TO_DP */
#ifdef MULTIVIEW
vec4 color = textureLod(source_color, uv, 0.0);
@@ -148,12 +148,13 @@ void main() {
depth = textureLod(source_depth, uv, 0.0).r;
#endif /* MODE_TWO_SOURCES */
-#else
+#else /* MULTIVIEW */
vec4 color = textureLod(source_color, uv, 0.0);
#ifdef MODE_TWO_SOURCES
color += textureLod(source_color2, uv, 0.0);
#endif /* MODE_TWO_SOURCES */
#endif /* MULTIVIEW */
+
if (params.force_luminance) {
color.rgb = vec3(max(max(color.r, color.g), color.b));
}
@@ -163,5 +164,6 @@ void main() {
if (params.srgb) {
color.rgb = linear_to_srgb(color.rgb);
}
+
frag_color = color;
}
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
index a416891ff2..246ef81cb2 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
@@ -32,12 +32,17 @@ layout(push_constant, std430) uniform Params {
bool use_half_res;
uint metallic_mask;
- mat4 projection;
+ uint view_index;
+ uint pad1;
+ uint pad2;
+ uint pad3;
}
params;
+#include "screen_space_reflection_inc.glsl"
+
vec2 view_to_screen(vec3 view_pos, out float w) {
- vec4 projected = params.projection * vec4(view_pos, 1.0);
+ vec4 projected = scene_data.projection[params.view_index] * vec4(view_pos, 1.0);
projected.xyz /= projected.w;
projected.xy = projected.xy * 0.5 + 0.5;
w = projected.w;
@@ -46,24 +51,16 @@ vec2 view_to_screen(vec3 view_pos, out float w) {
#define M_PI 3.14159265359
-vec3 reconstructCSPosition(vec2 S, float z) {
- if (params.orthogonal) {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z);
- } else {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
- }
-}
-
void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
vec2 pixel_size = 1.0 / vec2(params.screen_size);
- vec2 uv = vec2(ssC) * pixel_size;
+ vec2 uv = vec2(ssC.xy) * pixel_size;
uv += pixel_size * 0.5;
@@ -77,7 +74,12 @@ void main() {
normal = normalize(normal);
normal.y = -normal.y; //because this code reads flipped
- vec3 view_dir = normalize(vertex);
+ vec3 view_dir;
+ if (sc_multiview) {
+ view_dir = normalize(vertex + scene_data.eye_offset[params.view_index].xyz);
+ } else {
+ view_dir = normalize(vertex);
+ }
vec3 ray_dir = normalize(reflect(view_dir, normal));
if (dot(ray_dir, normal) < 0.001) {
@@ -154,6 +156,11 @@ void main() {
// convert to linear depth
depth = imageLoad(source_depth, ivec2(pos - 0.5)).r;
+ if (sc_multiview) {
+ depth = depth * 2.0 - 1.0;
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ depth = -depth;
+ }
z_from = z_to;
z_to = z / w;
@@ -175,17 +182,18 @@ void main() {
if (found) {
float margin_blend = 1.0;
- vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.5 * 0.05); // make a uniform margin
- if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, params.screen_size + margin)))) {
- // clip outside screen + margin
+ vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.05); // make a uniform margin
+ if (any(bvec4(lessThan(pos, vec2(0.0, 0.0)), greaterThan(pos, params.screen_size)))) {
+ // clip at the screen edges
imageStore(ssr_image, ssC, vec4(0.0));
return;
}
{
- //blend fading out towards external margin
- vec2 margin_grad = mix(pos - params.screen_size, -pos, lessThan(pos, vec2(0.0)));
- margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y));
+ //blend fading out towards inner margin
+ // 0.5 = midpoint of reflection
+ vec2 margin_grad = mix(params.screen_size - pos, pos, lessThan(pos, params.screen_size * 0.5));
+ margin_blend = smoothstep(0.0, margin.x * margin.y, margin_grad.x * margin_grad.y);
//margin_blend = 1.0;
}
@@ -222,13 +230,16 @@ void main() {
blur_radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
}
}
+
+ // Isn't this going to be overwritten after our endif?
final_color = imageLoad(source_diffuse, ivec2((final_pos - 0.5) * pixel_size));
imageStore(blur_radius_image, ssC, vec4(blur_radius / 255.0)); //stored in r8
-#endif
+#endif // MODE_ROUGH
final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend);
+
//change blend by metallic
vec4 metallic_mask = unpackUnorm4x8(params.metallic_mask);
final_color.a *= dot(metallic_mask, texelFetch(source_metallic, ssC << 1, 0));
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl
index 20e1712496..a63d60e0b2 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl
@@ -22,7 +22,7 @@ layout(push_constant, std430) uniform Params {
bool orthogonal;
float edge_tolerance;
int increment;
- uint pad;
+ uint view_index;
ivec2 screen_size;
bool vertical;
@@ -30,6 +30,8 @@ layout(push_constant, std430) uniform Params {
}
params;
+#include "screen_space_reflection_inc.glsl"
+
#define GAUSS_TABLE_SIZE 15
const float gauss_table[GAUSS_TABLE_SIZE + 1] = float[](
@@ -64,14 +66,6 @@ float gauss_weight(float p_val) {
#define M_PI 3.14159265359
-vec3 reconstructCSPosition(vec2 S, float z) {
- if (params.orthogonal) {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z);
- } else {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
- }
-}
-
void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor, ivec2 texcoord, ivec2 increment, vec3 p_pos, vec3 normal, float p_limit_radius) {
for (int i = 1; i < params.steps; i++) {
float d = float(i * params.increment);
@@ -110,7 +104,7 @@ void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
@@ -130,13 +124,13 @@ void main() {
ivec2 direction = ivec2(params.increment, 0);
#endif
float depth = imageLoad(source_depth, ssC).r;
- vec3 pos = reconstructCSPosition(vec2(ssC) + 0.5, depth);
+ vec3 pos = reconstructCSPosition(vec2(ssC.xy) + 0.5, depth);
vec3 normal = imageLoad(source_normal, ssC).xyz * 2.0 - 1.0;
normal = normalize(normal);
normal.y = -normal.y;
- do_filter(accum, accum_radius, divisor, ssC, direction, pos, normal, radius);
- do_filter(accum, accum_radius, divisor, ssC, -direction, pos, normal, radius);
+ do_filter(accum, accum_radius, divisor, ssC.xy, direction, pos, normal, radius);
+ do_filter(accum, accum_radius, divisor, ssC.xy, -direction, pos, normal, radius);
if (divisor > 0.0) {
accum /= divisor;
diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl
new file mode 100644
index 0000000000..26405ab040
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl
@@ -0,0 +1,28 @@
+layout(constant_id = 0) const bool sc_multiview = false;
+
+layout(set = 4, binding = 0, std140) uniform SceneData {
+ mat4x4 projection[2];
+ mat4x4 inv_projection[2];
+ vec4 eye_offset[2];
+}
+scene_data;
+
+vec3 reconstructCSPosition(vec2 screen_pos, float z) {
+ if (sc_multiview) {
+ vec4 pos;
+ pos.xy = (2.0 * vec2(screen_pos) / vec2(params.screen_size)) - 1.0;
+ pos.z = z * 2.0 - 1.0;
+ pos.w = 1.0;
+
+ pos = scene_data.inv_projection[params.view_index] * pos;
+ pos.xyz /= pos.w;
+
+ return pos.xyz;
+ } else {
+ if (params.orthogonal) {
+ return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw), z);
+ } else {
+ return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
+ }
+ }
+}
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
index 3f537e273a..a7da0812df 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
@@ -6,6 +6,11 @@
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+/* Specialization Constants (Toggles) */
+
+layout(constant_id = 0) const bool sc_multiview = false;
+
+/* inputs */
layout(set = 0, binding = 0) uniform sampler2D source_ssr;
layout(set = 1, binding = 0) uniform sampler2D source_depth;
layout(set = 1, binding = 1) uniform sampler2D source_normal;
@@ -28,7 +33,7 @@ void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
//do not filter, SSR will generate arctifacts if this is done
@@ -57,13 +62,19 @@ void main() {
normal.xyz += nr.xyz * 2.0 - 1.0;
normal.w += nr.w;
- d = d * 2.0 - 1.0;
- if (params.orthogonal) {
- d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ if (sc_multiview) {
+ // we're doing a full unproject so we need the value as is.
+ depth += d;
} else {
- d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near));
+ // unproject our Z value so we can use it directly.
+ d = d * 2.0 - 1.0;
+ if (params.orthogonal) {
+ d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ } else {
+ d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near));
+ }
+ depth += -d;
}
- depth += -d;
}
color /= 4.0;
@@ -71,17 +82,22 @@ void main() {
normal.xyz = normalize(normal.xyz / 4.0) * 0.5 + 0.5;
normal.w /= 4.0;
} else {
- color = texelFetch(source_ssr, ssC << 1, 0);
- depth = texelFetch(source_depth, ssC << 1, 0).r;
- normal = texelFetch(source_normal, ssC << 1, 0);
-
- depth = depth * 2.0 - 1.0;
- if (params.orthogonal) {
- depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
- } else {
- depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ ivec2 ofs = ssC << 1;
+
+ color = texelFetch(source_ssr, ofs, 0);
+ depth = texelFetch(source_depth, ofs, 0).r;
+ normal = texelFetch(source_normal, ofs, 0);
+
+ if (!sc_multiview) {
+ // unproject our Z value so we can use it directly.
+ depth = depth * 2.0 - 1.0;
+ if (params.orthogonal) {
+ depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ } else {
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ }
+ depth = -depth;
}
- depth = -depth;
}
imageStore(dest_ssr, ssC, color);
diff --git a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
new file mode 100644
index 0000000000..c62144fdaf
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
@@ -0,0 +1,112 @@
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
+#ifdef USE_MULTIVIEW
+layout(location = 0) out vec3 uv_interp;
+#else // USE_MULTIVIEW
+layout(location = 0) out vec2 uv_interp;
+#endif //USE_MULTIVIEW
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+
+#ifdef USE_MULTIVIEW
+ uv_interp = vec3(base_arr[gl_VertexIndex], ViewIndex);
+
+ gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0);
+#else
+ uv_interp = base_arr[gl_VertexIndex];
+
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+#endif
+}
+
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
+#ifdef USE_MULTIVIEW
+layout(location = 0) in vec3 uv_interp;
+#else // USE_MULTIVIEW
+layout(location = 0) in vec2 uv_interp;
+#endif //USE_MULTIVIEW
+
+#ifdef USE_MULTIVIEW
+layout(set = 0, binding = 0) uniform sampler2DArray specular;
+#else // USE_MULTIVIEW
+layout(set = 0, binding = 0) uniform sampler2D specular;
+#endif //USE_MULTIVIEW
+
+#ifdef MODE_SSR
+
+#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 0) uniform sampler2DArray ssr;
+#else // USE_MULTIVIEW
+layout(set = 1, binding = 0) uniform sampler2D ssr;
+#endif //USE_MULTIVIEW
+
+#endif
+
+#ifdef MODE_MERGE
+
+#ifdef USE_MULTIVIEW
+layout(set = 2, binding = 0) uniform sampler2DArray diffuse;
+#else // USE_MULTIVIEW
+layout(set = 2, binding = 0) uniform sampler2D diffuse;
+#endif //USE_MULTIVIEW
+
+#endif
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+ frag_color.rgb = texture(specular, uv_interp).rgb;
+ frag_color.a = 0.0;
+#ifdef MODE_SSR
+
+ vec4 ssr_color = texture(ssr, uv_interp);
+ frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a);
+#endif
+
+#ifdef MODE_MERGE
+ frag_color += texture(diffuse, uv_interp);
+#endif
+ //added using additive blend
+}
diff --git a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
index 134aae5ce7..134aae5ce7 100644
--- a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
index 2a87e273bc..2a87e273bc 100644
--- a/servers/rendering/renderer_rd/shaders/ssao.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl
index f42734c46d..f42734c46d 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
index 04f98964e8..04f98964e8 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
index f6a9a92fac..f6a9a92fac 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
index 513791dfbf..513791dfbf 100644
--- a/servers/rendering/renderer_rd/shaders/ssil.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
index 47c56571f6..47c56571f6 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
index 6b6b02739d..6b6b02739d 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
index 9e86ac0cf0..9e86ac0cf0 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
new file mode 100644
index 0000000000..5ef83c0b44
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -0,0 +1,72 @@
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#ifdef MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#endif //MULTIVIEW
+
+#ifdef MULTIVIEW
+layout(location = 0) out vec3 uv_interp;
+#else
+layout(location = 0) out vec2 uv_interp;
+#endif
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp.xy = base_arr[gl_VertexIndex];
+#ifdef MULTIVIEW
+ uv_interp.z = ViewIndex;
+#endif
+
+ gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0);
+}
+
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#ifdef MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#endif //MULTIVIEW
+
+#ifdef MULTIVIEW
+layout(location = 0) in vec3 uv_interp;
+layout(set = 0, binding = 0) uniform sampler2DArray source_color;
+#else /* MULTIVIEW */
+layout(location = 0) in vec2 uv_interp;
+layout(set = 0, binding = 0) uniform sampler2D source_color;
+#endif /* MULTIVIEW */
+
+layout(location = 0) out uint frag_color;
+
+void main() {
+#ifdef MULTIVIEW
+ vec3 uv = uv_interp;
+#else
+ vec2 uv = uv_interp;
+#endif
+
+#ifdef MULTIVIEW
+ vec4 color = textureLod(source_color, uv, 0.0);
+#else /* MULTIVIEW */
+ vec4 color = textureLod(source_color, uv, 0.0);
+#endif /* MULTIVIEW */
+
+ // See if we can change the sampler to one that returns int...
+ frag_color = uint(color.r * 256.0);
+}
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/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
index f687d50a2d..6ea8cb1377 100644
--- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
@@ -8,6 +8,12 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#define M_PI 3.141592
+/* Specialization Constants (Toggles) */
+
+layout(constant_id = 0) const bool sc_half_res = false;
+layout(constant_id = 1) const bool sc_use_full_projection_matrix = false;
+layout(constant_id = 2) const bool sc_use_vrs = false;
+
#define SDFGI_MAX_CASCADES 8
//set 0 for SDFGI and render buffers
@@ -97,18 +103,20 @@ layout(set = 0, binding = 18, std140) uniform SceneData {
}
scene_data;
+layout(r8ui, set = 0, binding = 19) uniform restrict readonly uimage2D vrs_buffer;
+
layout(push_constant, std430) uniform Params {
- uint view_index;
uint max_voxel_gi_instances;
bool high_quality_vct;
bool orthogonal;
+ uint view_index;
vec4 proj_info;
float z_near;
float z_far;
- float pad1;
float pad2;
+ float pad3;
}
params;
@@ -140,34 +148,34 @@ vec4 blend_color(vec4 src, vec4 dst) {
}
vec3 reconstruct_position(ivec2 screen_pos) {
-#ifdef USE_MULTIVIEW
- vec4 pos;
- pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0;
- pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0;
- pos.w = 1.0;
+ if (sc_use_full_projection_matrix) {
+ vec4 pos;
+ pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0;
+ pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0;
+ pos.w = 1.0;
- pos = scene_data.inv_projection[params.view_index] * pos;
+ pos = scene_data.inv_projection[params.view_index] * pos;
- return pos.xyz / pos.w;
-#else
- vec3 pos;
- pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r;
-
- pos.z = pos.z * 2.0 - 1.0;
- if (params.orthogonal) {
- pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
+ return pos.xyz / pos.w;
} else {
- pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near));
- }
- pos.z = -pos.z;
+ vec3 pos;
+ pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r;
+
+ pos.z = pos.z * 2.0 - 1.0;
+ if (params.orthogonal) {
+ pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
+ } else {
+ pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near));
+ }
+ pos.z = -pos.z;
- pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw;
- if (!params.orthogonal) {
- pos.xy *= pos.z;
- }
+ pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw;
+ if (!params.orthogonal) {
+ pos.xy *= pos.z;
+ }
- return pos;
-#endif
+ return pos;
+ }
}
void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) {
@@ -587,7 +595,6 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
vec4 fetch_normal_and_roughness(ivec2 pos) {
vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0);
-
normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0);
return normal_roughness;
}
@@ -600,7 +607,7 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref
if (normal.length() > 0.5) {
//valid normal, can do GI
float roughness = normal_roughness.w;
- vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[params.view_index].xyz));
+ vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[gl_GlobalInvocationID.z].xyz));
vertex = mat3(scene_data.cam_transform) * vertex;
normal = normalize(mat3(scene_data.cam_transform) * normal);
vec3 reflection = normalize(reflect(-view, normal));
@@ -648,9 +655,35 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref
void main() {
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
-#ifdef MODE_HALF_RES
- pos <<= 1;
-#endif
+ uint vrs_x, vrs_y;
+ if (sc_use_vrs) {
+ ivec2 vrs_pos;
+
+ // Currently we use a 16x16 texel, possibly some day make this configurable.
+ if (sc_half_res) {
+ vrs_pos = pos >> 3;
+ } else {
+ vrs_pos = pos >> 4;
+ }
+
+ uint vrs_texel = imageLoad(vrs_buffer, vrs_pos).r;
+ // note, valid values for vrs_x and vrs_y are 1, 2 and 4.
+ vrs_x = 1 << ((vrs_texel >> 2) & 3);
+ vrs_y = 1 << (vrs_texel & 3);
+
+ if (mod(pos.x, vrs_x) != 0) {
+ return;
+ }
+
+ if (mod(pos.y, vrs_y) != 0) {
+ return;
+ }
+ }
+
+ if (sc_half_res) {
+ pos <<= 1;
+ }
+
if (any(greaterThanEqual(pos, scene_data.screen_size))) { //too large, do nothing
return;
}
@@ -663,10 +696,69 @@ void main() {
process_gi(pos, vertex, ambient_light, reflection_light);
-#ifdef MODE_HALF_RES
- pos >>= 1;
-#endif
+ if (sc_half_res) {
+ pos >>= 1;
+ }
imageStore(ambient_buffer, pos, ambient_light);
imageStore(reflection_buffer, pos, reflection_light);
+
+ if (sc_use_vrs) {
+ if (vrs_x > 1) {
+ imageStore(ambient_buffer, pos + ivec2(1, 0), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(1, 0), reflection_light);
+ }
+
+ if (vrs_x > 2) {
+ imageStore(ambient_buffer, pos + ivec2(2, 0), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(2, 0), reflection_light);
+
+ imageStore(ambient_buffer, pos + ivec2(3, 0), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(3, 0), reflection_light);
+ }
+
+ if (vrs_y > 1) {
+ imageStore(ambient_buffer, pos + ivec2(0, 1), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(0, 1), reflection_light);
+ }
+
+ if (vrs_y > 1 && vrs_x > 1) {
+ imageStore(ambient_buffer, pos + ivec2(1, 1), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(1, 1), reflection_light);
+ }
+
+ if (vrs_y > 1 && vrs_x > 2) {
+ imageStore(ambient_buffer, pos + ivec2(2, 1), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(2, 1), reflection_light);
+
+ imageStore(ambient_buffer, pos + ivec2(3, 1), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(3, 1), reflection_light);
+ }
+
+ if (vrs_y > 2) {
+ imageStore(ambient_buffer, pos + ivec2(0, 2), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(0, 2), reflection_light);
+ imageStore(ambient_buffer, pos + ivec2(0, 3), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(0, 3), reflection_light);
+ }
+
+ if (vrs_y > 2 && vrs_x > 1) {
+ imageStore(ambient_buffer, pos + ivec2(1, 2), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(1, 2), reflection_light);
+ imageStore(ambient_buffer, pos + ivec2(1, 3), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(1, 3), reflection_light);
+ }
+
+ if (vrs_y > 2 && vrs_x > 2) {
+ imageStore(ambient_buffer, pos + ivec2(2, 2), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(2, 2), reflection_light);
+ imageStore(ambient_buffer, pos + ivec2(2, 3), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(2, 3), reflection_light);
+
+ imageStore(ambient_buffer, pos + ivec2(3, 2), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(3, 2), reflection_light);
+ imageStore(ambient_buffer, pos + ivec2(3, 3), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(3, 3), reflection_light);
+ }
+ }
}
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
index af5f7d0a58..9640d30e78 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
@@ -37,16 +37,14 @@ layout(push_constant, std430) uniform Params {
uint max_cascades;
ivec2 screen_size;
- bool use_occlusion;
float y_mult;
- int probe_axis_size;
float z_near;
- float reserved1;
- float reserved2;
- mat4 cam_transform;
- mat4 inv_projection;
+ mat3x4 inv_projection;
+ // We pack these more tightly than mat3 and vec3, which will require some reconstruction trickery.
+ float cam_basis[3][3];
+ float cam_origin[3];
}
params;
@@ -82,13 +80,21 @@ void main() {
vec3 ray_pos;
vec3 ray_dir;
{
- ray_pos = params.cam_transform[3].xyz;
+ ray_pos = vec3(params.cam_origin[0], params.cam_origin[1], params.cam_origin[2]);
ray_dir.xy = ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0);
ray_dir.z = params.z_near;
- ray_dir = (params.inv_projection * vec4(ray_dir, 1.0)).xyz;
- ray_dir = normalize(mat3(params.cam_transform) * ray_dir);
+ ray_dir = (vec4(ray_dir, 1.0) * mat4(params.inv_projection)).xyz;
+
+ mat3 cam_basis;
+ {
+ vec3 c0 = vec3(params.cam_basis[0][0], params.cam_basis[0][1], params.cam_basis[0][2]);
+ vec3 c1 = vec3(params.cam_basis[1][0], params.cam_basis[1][1], params.cam_basis[1][2]);
+ vec3 c2 = vec3(params.cam_basis[2][0], params.cam_basis[2][1], params.cam_basis[2][2]);
+ cam_basis = mat3(c0, c1, c2);
+ }
+ ray_dir = normalize(cam_basis * ray_dir);
}
ray_pos.y *= params.y_mult;
diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
index 5b4594da99..e825020a4e 100644
--- a/servers/rendering/renderer_rd/shaders/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
@@ -77,10 +77,10 @@ params;
layout(set = 0, binding = 0) uniform sampler material_samplers[12];
-layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
layout(set = 0, binding = 2, std140) uniform SceneData {
bool volumetric_fog_enabled;
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
index eee609fb48..4658afd02d 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
@@ -21,17 +21,17 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
#define DENSITY_SCALE 1024.0
-#include "cluster_data_inc.glsl"
-#include "light_data_inc.glsl"
+#include "../cluster_data_inc.glsl"
+#include "../light_data_inc.glsl"
#define M_PI 3.14159265359
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
layout(push_constant, std430) uniform Params {
vec3 position;
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
index fdbd7d3e35..6f79b9e771 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
@@ -19,8 +19,8 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#endif
-#include "cluster_data_inc.glsl"
-#include "light_data_inc.glsl"
+#include "../cluster_data_inc.glsl"
+#include "../light_data_inc.glsl"
#define M_PI 3.14159265359
@@ -377,7 +377,7 @@ void main() {
for (uint i = 0; i < params.directional_light_count; i++) {
vec3 shadow_attenuation = vec3(1.0);
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -view_pos.z;
vec4 pssm_coord;
@@ -486,7 +486,7 @@ void main() {
vec3 light = omni_lights.data[light_index].color;
- if (omni_lights.data[light_index].shadow_enabled) {
+ if (omni_lights.data[light_index].shadow_opacity > 0.001) {
//has shadow
vec4 uv_rect = omni_lights.data[light_index].atlas_rect;
vec2 flip_offset = omni_lights.data[light_index].direction.xy;
@@ -572,7 +572,7 @@ void main() {
vec3 light = spot_lights.data[light_index].color;
- if (spot_lights.data[light_index].shadow_enabled) {
+ if (spot_lights.data[light_index].shadow_opacity > 0.001) {
//has shadow
vec4 uv_rect = spot_lights.data[light_index].atlas_rect;
vec2 flip_offset = spot_lights.data[light_index].direction.xy;
diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
index 61c8488a05..799f7087b6 100644
--- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
@@ -15,7 +15,7 @@ struct LightData { //this structure needs to be as packed as possible
mediump float cone_attenuation;
mediump float cone_angle;
mediump float specular_amount;
- bool shadow_enabled;
+ mediump float shadow_opacity;
highp vec4 atlas_rect; // rect in the shadow atlas
highp mat4 shadow_matrix;
@@ -60,7 +60,7 @@ struct DirectionalLightData {
highp float softshadow_angle;
highp float soft_shadow_scale;
bool blend_splits;
- bool shadow_enabled;
+ mediump float shadow_opacity;
highp float fade_from;
highp float fade_to;
uvec2 pad;
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index acb62b812e..fb5759bc17 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -25,10 +25,10 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
/* Set 1: FRAME AND PARTICLE DATA */
@@ -458,11 +458,11 @@ void main() {
} break;
case ATTRACTOR_TYPE_VECTOR_FIELD: {
- vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents) * 2.0 - 1.0;
+ vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents + 1.0) * 0.5;
if (any(lessThan(uvw_pos, vec3(0.0))) || any(greaterThan(uvw_pos, vec3(1.0)))) {
continue;
}
- vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz;
+ vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * 2.0 - 1.0;
dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction
amount = length(s);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 3b8aaa15f9..e9515c7670 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -947,9 +947,9 @@ void fragment_shader(in SceneData scene_data) {
if (decals.data[decal_index].emission_rect != vec4(0.0)) {
//emission is additive, so its independent from albedo
if (sc_decal_use_mipmaps) {
- emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade;
} else {
- emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
+ emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade;
}
}
}
@@ -1389,7 +1389,7 @@ void fragment_shader(in SceneData scene_data) {
float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
- specular_light *= env.x * f0 + env.y;
+ specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0);
#endif
}
@@ -1425,7 +1425,7 @@ void fragment_shader(in SceneData scene_data) {
float shadow = 1.0;
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
vec3 light_dir = directional_lights.data[i].direction;
vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
@@ -1634,7 +1634,7 @@ void fragment_shader(in SceneData scene_data) {
#ifdef LIGHT_TRANSMITTANCE_USED
float transmittance_z = transmittance_depth;
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
@@ -1689,6 +1689,8 @@ void fragment_shader(in SceneData scene_data) {
} else {
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
}
+
+ shadow = shadow * directional_lights.data[i].shadow_opacity + 1.0 - directional_lights.data[i].shadow_opacity;
#endif
blur_shadow(shadow);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index 0c23de96c3..f0717294ef 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -129,10 +129,10 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
}
decals;
-layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
struct SDFVoxelGICascadeData {
vec3 position;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 4f2e9793a5..7299bb0576 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -199,7 +199,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif // LIGHT_ANISOTROPY_USED
// F
float cLdotH5 = SchlickFresnel(cLdotH);
- vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0);
+ // Calculate Fresnel using specular occlusion term from Filament:
+ // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion
+ float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), 0.0, 1.0);
+ vec3 F = f0 + (f90 - f0) * cLdotH5;
vec3 specular_brdf_NL = cNdotL * D * F * G;
@@ -392,7 +395,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
#ifndef SHADOWS_DISABLED
- if (omni_lights.data[idx].shadow_enabled) {
+ if (omni_lights.data[idx].shadow_opacity > 0.001) {
// there is a shadowmap
vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
@@ -495,6 +498,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
}
shadow /= float(sc_penumbra_shadow_samples);
+ shadow = mix(1.0, shadow, omni_lights.data[idx].shadow_opacity);
} else {
//no blockers found, so no shadow
@@ -513,7 +517,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
vec2 pos = shadow_sample.xy / shadow_sample.z;
float depth = shadow_len - omni_lights.data[idx].shadow_bias;
depth *= omni_lights.data[idx].inv_radius;
- shadow = sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth);
+ shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth), omni_lights.data[idx].shadow_opacity);
}
return shadow;
@@ -671,7 +675,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
#ifndef SHADOWS_DISABLED
- if (spot_lights.data[idx].shadow_enabled) {
+ if (spot_lights.data[idx].shadow_opacity > 0.001) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
vec3 spot_dir = spot_lights.data[idx].direction;
@@ -732,6 +736,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
}
shadow /= float(sc_penumbra_shadow_samples);
+ shadow = mix(1.0, shadow, spot_lights.data[idx].shadow_opacity);
} else {
//no blockers found, so no shadow
@@ -740,7 +745,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
} else {
//hard shadow
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
- shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv);
+ shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv), spot_lights.data[idx].shadow_opacity);
}
return shadow;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 042de7b590..6548793bee 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -1142,7 +1142,7 @@ void main() {
#ifdef USE_SOFT_SHADOWS
//version with soft shadows, more expensive
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
vec4 pssm_coord;
@@ -1294,7 +1294,7 @@ void main() {
#else
// Soft shadow disabled version
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
vec4 pssm_coord;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index 7413d8730a..98ad674ce0 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -118,10 +118,10 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
}
decals;
-layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData {
highp vec4 data[];
}
-global_variables;
+global_shader_uniforms;
/* Set 1: Render Pass (changes per render pass) */
diff --git a/servers/rendering/renderer_rd/shaders/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/specular_merge.glsl
deleted file mode 100644
index 3579c35cce..0000000000
--- a/servers/rendering/renderer_rd/shaders/specular_merge.glsl
+++ /dev/null
@@ -1,53 +0,0 @@
-#[vertex]
-
-#version 450
-
-#VERSION_DEFINES
-
-layout(location = 0) out vec2 uv_interp;
-
-void main() {
- vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
- uv_interp = base_arr[gl_VertexIndex];
-
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-}
-
-#[fragment]
-
-#version 450
-
-#VERSION_DEFINES
-
-layout(location = 0) in vec2 uv_interp;
-
-layout(set = 0, binding = 0) uniform sampler2D specular;
-
-#ifdef MODE_SSR
-
-layout(set = 1, binding = 0) uniform sampler2D ssr;
-
-#endif
-
-#ifdef MODE_MERGE
-
-layout(set = 2, binding = 0) uniform sampler2D diffuse;
-
-#endif
-
-layout(location = 0) out vec4 frag_color;
-
-void main() {
- frag_color.rgb = texture(specular, uv_interp).rgb;
- frag_color.a = 0.0;
-#ifdef MODE_SSR
-
- vec4 ssr_color = texture(ssr, uv_interp);
- frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a);
-#endif
-
-#ifdef MODE_MERGE
- frag_color += texture(diffuse, uv_interp);
-#endif
- //added using additive blend
-}
diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
index a1a77b95aa..b0a0839836 100644
--- a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
+++ b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
@@ -29,7 +29,8 @@
#VERSION_DEFINES
-// Based on Spartan Engine's TAA implementation https://github.com/PanosK92/SpartanEngine/blob/master/Data/shaders/temporal_antialiasing.hlsl
+// Based on Spartan Engine's TAA implementation (without TAA upscale).
+// <https://github.com/PanosK92/SpartanEngine/blob/a8338d0609b85dc32f3732a5c27fb4463816a3b9/Data/shaders/temporal_antialiasing.hlsl>
#define USE_SUBGROUPS
@@ -188,7 +189,7 @@ vec3 sample_catmull_rom_9(sampler2D stex, vec2 uv, vec2 resolution) {
// Source: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1
// License: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae
- // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding
+ // We're going to sample a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding
// down the sample location to get the exact center of our "starting" texel. The starting texel will be at
// location [1, 1] in the grid, where [0, 0] is the top left corner.
vec2 sample_pos = uv * resolution;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 56a4525b8e..882afdfa54 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -56,7 +56,7 @@ LightStorage::LightStorage() {
}
for (int i = 0; i < lightmap_textures.size(); i++) {
- lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
}
}
@@ -88,6 +88,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
+ light.param[RS::LIGHT_PARAM_SHADOW_OPACITY] = 1.0;
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
@@ -156,12 +157,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 +178,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 +200,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 +218,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 +238,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 +248,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 +258,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 +268,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 +284,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 +293,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 {
@@ -366,6 +367,13 @@ AABB LightStorage::light_get_aabb(RID p_light) const {
ERR_FAIL_V(AABB());
}
+Dependency *LightStorage::light_get_dependency(RID p_light) const {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_NULL_V(light, nullptr);
+
+ return &light->dependency;
+}
+
/* REFLECTION PROBE */
RID LightStorage::reflection_probe_allocate() {
@@ -387,7 +395,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 +432,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 +443,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 +451,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 +459,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 +474,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 +482,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 +499,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 {
@@ -601,6 +609,13 @@ float LightStorage::reflection_probe_get_ambient_color_energy(RID p_probe) const
return reflection_probe->ambient_color_energy;
}
+Dependency *LightStorage::reflection_probe_get_dependency(RID p_probe) const {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_NULL_V(reflection_probe, nullptr);
+
+ return &reflection_probe->dependency;
+}
+
/* LIGHTMAP API */
RID LightStorage::lightmap_allocate() {
@@ -628,17 +643,17 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use
//erase lightmap users
if (lm->light_texture.is_valid()) {
- RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture);
+ RendererRD::TextureStorage::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture);
if (t) {
t->lightmap_users.erase(p_lightmap);
}
}
- RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light);
+ RendererRD::TextureStorage::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light);
lm->light_texture = p_light;
lm->uses_spherical_harmonics = p_uses_spherical_haromics;
- RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
if (!t) {
if (using_lightmap_array) {
if (lm->array_index >= 0) {
@@ -725,6 +740,13 @@ void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) {
lightmap_probe_capture_update_speed = p_speed;
}
+Dependency *LightStorage::lightmap_get_dependency(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_NULL_V(lm, nullptr);
+
+ return &lm->dependency;
+}
+
void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND(!lm);
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index 3cc455692d..3e3246e8e9 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -35,90 +35,85 @@
#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 {
-/* LIGHT */
-
-struct Light {
- RS::LightType type;
- float param[RS::LIGHT_PARAM_MAX];
- Color color = Color(1, 1, 1, 1);
- RID projector;
- bool shadow = false;
- bool negative = false;
- bool reverse_cull = false;
- RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
- uint32_t max_sdfgi_cascade = 2;
- uint32_t cull_mask = 0xFFFFFFFF;
- bool distance_fade = false;
- real_t distance_fade_begin = 40.0;
- real_t distance_fade_shadow = 50.0;
- real_t distance_fade_length = 10.0;
- RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
- RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
- bool directional_blend_splits = false;
- RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
- uint64_t version = 0;
-
- RendererStorage::Dependency dependency;
-};
-
-/* REFLECTION PROBE */
-
-struct ReflectionProbe {
- RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
- int resolution = 256;
- float intensity = 1.0;
- RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
- Color ambient_color;
- float ambient_color_energy = 1.0;
- float max_distance = 0;
- Vector3 extents = Vector3(1, 1, 1);
- Vector3 origin_offset;
- bool interior = false;
- bool box_projection = false;
- bool enable_shadows = false;
- uint32_t cull_mask = (1 << 20) - 1;
- float mesh_lod_threshold = 0.01;
-
- RendererStorage::Dependency dependency;
-};
-
-/* LIGHTMAP */
-
-struct Lightmap {
- RID light_texture;
- bool uses_spherical_harmonics = false;
- bool interior = false;
- AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
- int32_t array_index = -1; //unassigned
- PackedVector3Array points;
- PackedColorArray point_sh;
- PackedInt32Array tetrahedra;
- PackedInt32Array bsp_tree;
-
- struct BSP {
- static const int32_t EMPTY_LEAF = INT32_MIN;
- float plane[4];
- int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
- };
-
- RendererStorage::Dependency dependency;
-};
-
class LightStorage : public RendererLightStorage {
private:
static LightStorage *singleton;
/* LIGHT */
+ struct Light {
+ RS::LightType type;
+ float param[RS::LIGHT_PARAM_MAX];
+ Color color = Color(1, 1, 1, 1);
+ RID projector;
+ bool shadow = false;
+ bool negative = false;
+ bool reverse_cull = false;
+ RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
+ uint32_t max_sdfgi_cascade = 2;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ bool distance_fade = false;
+ real_t distance_fade_begin = 40.0;
+ real_t distance_fade_shadow = 50.0;
+ real_t distance_fade_length = 10.0;
+ RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
+ RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+ bool directional_blend_splits = false;
+ RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
+ uint64_t version = 0;
+
+ Dependency dependency;
+ };
+
mutable RID_Owner<Light, true> light_owner;
/* REFLECTION PROBE */
+
+ struct ReflectionProbe {
+ RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
+ int resolution = 256;
+ float intensity = 1.0;
+ RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
+ Color ambient_color;
+ float ambient_color_energy = 1.0;
+ float max_distance = 0;
+ Vector3 extents = Vector3(1, 1, 1);
+ Vector3 origin_offset;
+ bool interior = false;
+ bool box_projection = false;
+ bool enable_shadows = false;
+ uint32_t cull_mask = (1 << 20) - 1;
+ float mesh_lod_threshold = 0.01;
+
+ Dependency dependency;
+ };
mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
/* LIGHTMAP */
+ struct Lightmap {
+ RID light_texture;
+ bool uses_spherical_harmonics = false;
+ bool interior = false;
+ AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
+ int32_t array_index = -1; //unassigned
+ PackedVector3Array points;
+ PackedColorArray point_sh;
+ PackedInt32Array tetrahedra;
+ PackedInt32Array bsp_tree;
+
+ struct BSP {
+ static const int32_t EMPTY_LEAF = INT32_MIN;
+ float plane[4];
+ int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
+ };
+
+ Dependency dependency;
+ };
+
bool using_lightmap_array;
Vector<RID> lightmap_textures;
uint64_t lightmap_array_version = 0;
@@ -134,7 +129,6 @@ public:
/* LIGHT */
- Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); };
bool owns_light(RID p_rid) { return light_owner.owns(p_rid); };
void _light_initialize(RID p_rid, RS::LightType p_type);
@@ -267,9 +261,10 @@ public:
virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
virtual uint64_t light_get_version(RID p_light) const override;
+ Dependency *light_get_dependency(RID p_light) const;
+
/* REFLECTION PROBE */
- ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); };
bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); };
virtual RID reflection_probe_allocate() override;
@@ -309,9 +304,10 @@ public:
Color reflection_probe_get_ambient_color(RID p_probe) const;
float reflection_probe_get_ambient_color_energy(RID p_probe) const;
+ Dependency *reflection_probe_get_dependency(RID p_probe) const;
+
/* LIGHTMAP */
- Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); };
virtual RID lightmap_allocate() override;
@@ -331,6 +327,8 @@ public:
virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override;
virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
+ Dependency *lightmap_get_dependency(RID p_lightmap) const;
+
virtual float lightmap_get_probe_capture_update_speed() const override {
return lightmap_probe_capture_update_speed;
}
@@ -367,4 +365,4 @@ public:
} // namespace RendererRD
-#endif // !LIGHT_STORAGE_RD_H
+#endif // LIGHT_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 096d371b8d..41dd1ccc40 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -172,75 +172,84 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} break;
case ShaderLanguage::TYPE_IVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 2 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector2i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
}
} break;
case ShaderLanguage::TYPE_IVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 3 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
}
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector3i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
}
} break;
case ShaderLanguage::TYPE_IVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 4 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
}
+ } else {
+ Vector4i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
} break;
case ShaderLanguage::TYPE_UINT: {
@@ -267,75 +276,84 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} break;
case ShaderLanguage::TYPE_UVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 2 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector2i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
}
} break;
case ShaderLanguage::TYPE_UVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 3 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
}
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector3i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
}
} break;
case ShaderLanguage::TYPE_UVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 4 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i++) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i++) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
}
+ } else {
+ Vector4i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
} break;
case ShaderLanguage::TYPE_FLOAT: {
@@ -514,13 +532,20 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[1] = v.y;
gui[2] = v.z;
gui[3] = v.w;
- } else {
+ } else if (value.get_type() == Variant::PLANE) {
Plane v = value;
gui[0] = v.normal.x;
gui[1] = v.normal.y;
gui[2] = v.normal.z;
gui[3] = v.d;
+ } else {
+ Vector4 v = value;
+
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
}
} break;
@@ -670,7 +695,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[i + 15] = 1;
}
}
- } else {
+ } else if (value.get_type() == Variant::TRANSFORM3D) {
Transform3D v = value;
gui[0] = v.basis.rows[0][0];
gui[1] = v.basis.rows[1][0];
@@ -691,6 +716,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[13] = v.origin.y;
gui[14] = v.origin.z;
gui[15] = 1;
+ } else {
+ Projection v = value;
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ gui[i * 4 + j] = v.matrix[i][j];
+ }
+ }
}
} break;
default: {
@@ -894,9 +926,9 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
}
///////////////////////////////////////////////////////////////////////////
-// MaterialData
+// MaterialStorage::MaterialData
-void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
+void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
bool uses_global_buffer = false;
@@ -911,7 +943,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
//this is a global variable, get the index to it
- GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key);
uint32_t index = 0;
if (gv) {
index = gv->buffer_index;
@@ -967,33 +999,33 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
if (uses_global_buffer != (global_buffer_E != nullptr)) {
if (uses_global_buffer) {
- global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self);
+ global_buffer_E = material_storage->global_shader_uniforms.materials_using_buffer.push_back(self);
} else {
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
global_buffer_E = nullptr;
}
}
}
-MaterialData::~MaterialData() {
+MaterialStorage::MaterialData::~MaterialData() {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
if (global_buffer_E) {
//unregister global buffers
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
}
if (global_texture_E) {
//unregister global textures
for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
}
//unregister material from those using global textures
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
}
if (uniform_buffer.is_valid()) {
@@ -1001,14 +1033,14 @@ MaterialData::~MaterialData() {
}
}
-void MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
TextureStorage *texture_storage = TextureStorage::get_singleton();
MaterialStorage *material_storage = MaterialStorage::get_singleton();
#ifdef TOOLS_ENABLED
- Texture *roughness_detect_texture = nullptr;
+ TextureStorage::Texture *roughness_detect_texture = nullptr;
RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
- Texture *normal_detect_texture = nullptr;
+ TextureStorage::Texture *normal_detect_texture = nullptr;
#endif
bool uses_global_textures = false;
@@ -1023,7 +1055,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
if (p_texture_uniforms[i].global) {
uses_global_textures = true;
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name);
if (v) {
if (v->buffer_index >= 0) {
WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
@@ -1091,19 +1123,22 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
case ShaderLanguage::TYPE_SAMPLER2D: {
switch (p_texture_uniforms[i].hint) {
case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: {
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_TRANSPARENT);
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_ANISO);
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL);
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL);
} break;
default: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
} break;
}
} break;
@@ -1111,27 +1146,27 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
case ShaderLanguage::TYPE_SAMPLERCUBE: {
switch (p_texture_uniforms[i].hint) {
case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
} break;
default: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
} break;
}
} break;
case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
} break;
case ShaderLanguage::TYPE_ISAMPLER3D:
case ShaderLanguage::TYPE_USAMPLER3D:
case ShaderLanguage::TYPE_SAMPLER3D: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
} break;
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY:
case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
} break;
default: {
@@ -1153,7 +1188,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
bool srgb = p_use_linear_color && p_texture_uniforms[i].use_color;
for (int j = 0; j < textures.size(); j++) {
- Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]);
+ TextureStorage::Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]);
if (tex) {
rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
@@ -1175,7 +1210,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
#endif
}
if (rd_texture.is_null()) {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
#ifdef TOOLS_ENABLED
if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
@@ -1193,7 +1228,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
if (E.value != global_textures_pass) {
to_delete.push_back(E.key);
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
@@ -1207,23 +1242,23 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
//handle registering/unregistering global textures
if (uses_global_textures != (global_texture_E != nullptr)) {
if (uses_global_textures) {
- global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self);
+ global_texture_E = material_storage->global_shader_uniforms.materials_using_texture.push_back(self);
} else {
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
global_texture_E = nullptr;
}
}
}
}
-void MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
+void MaterialStorage::MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
RD::get_singleton()->free(p_uniform_set);
}
}
-bool MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
if ((uint32_t)ubo_data.size() != p_ubo_size) {
p_uniform_dirty = true;
if (uniform_buffer.is_valid()) {
@@ -1441,22 +1476,22 @@ MaterialStorage::MaterialStorage() {
shader_data_request_func[i] = nullptr;
}
- static_assert(sizeof(GlobalVariables::Value) == 16);
+ static_assert(sizeof(GlobalShaderUniforms::Value) == 16);
- global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
- global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
- memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
- global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
- global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+ global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+ global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size);
+ memset(global_shader_uniforms.buffer_values, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_usage = memnew_arr(GlobalShaderUniforms::ValueUsage, global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_dirty_regions = memnew_arr(bool, global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ global_shader_uniforms.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
}
MaterialStorage::~MaterialStorage() {
- memdelete_arr(global_variables.buffer_values);
- memdelete_arr(global_variables.buffer_usage);
- memdelete_arr(global_variables.buffer_dirty_regions);
- RD::get_singleton()->free(global_variables.buffer);
+ memdelete_arr(global_shader_uniforms.buffer_values);
+ memdelete_arr(global_shader_uniforms.buffer_usage);
+ memdelete_arr(global_shader_uniforms.buffer_dirty_regions);
+ RD::get_singleton()->free(global_shader_uniforms.buffer);
// buffers
@@ -1577,17 +1612,17 @@ void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) {
}
}
-/* GLOBAL VARIABLE API */
+/* GLOBAL SHADER UNIFORM API */
-int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
+int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) {
int32_t idx = 0;
- while (idx + p_elements <= global_variables.buffer_size) {
- if (global_variables.buffer_usage[idx].elements == 0) {
+ while (idx + p_elements <= global_shader_uniforms.buffer_size) {
+ if (global_shader_uniforms.buffer_usage[idx].elements == 0) {
bool valid = true;
for (uint32_t i = 1; i < p_elements; i++) {
- if (global_variables.buffer_usage[idx + i].elements > 0) {
+ if (global_shader_uniforms.buffer_usage[idx + i].elements > 0) {
valid = false;
- idx += i + global_variables.buffer_usage[idx + i].elements;
+ idx += i + global_shader_uniforms.buffer_usage[idx + i].elements;
break;
}
}
@@ -1598,17 +1633,17 @@ int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
return idx;
} else {
- idx += global_variables.buffer_usage[idx].elements;
+ idx += global_shader_uniforms.buffer_usage[idx].elements;
}
}
return -1;
}
-void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
+void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
bool b = p_value;
bv.x = b ? 1.0 : 0.0;
bv.y = 0.0;
@@ -1617,7 +1652,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_BVEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1625,7 +1660,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1633,7 +1668,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1641,7 +1676,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = (bvec & 8) ? 1.0 : 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_INT: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
int32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1649,7 +1684,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC2: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1657,7 +1692,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC3: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1665,7 +1700,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC4: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1673,7 +1708,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2I: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Rect2i v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1681,7 +1716,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_UINT: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
uint32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1689,7 +1724,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC2: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1697,7 +1732,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC3: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1705,7 +1740,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC4: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1713,7 +1748,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_FLOAT: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
float v = p_value;
bv.x = v;
bv.y = 0;
@@ -1721,7 +1756,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector2 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1729,7 +1764,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector3 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1737,7 +1772,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Plane v = p_value;
bv.x = v.normal.x;
bv.y = v.normal.y;
@@ -1745,14 +1780,14 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.d;
} break;
case RS::GLOBAL_VAR_TYPE_COLOR: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Color v = p_value;
bv.x = v.r;
bv.y = v.g;
bv.z = v.b;
bv.w = v.a;
- GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+ GlobalShaderUniforms::Value &bv_linear = global_shader_uniforms.buffer_values[p_index + 1];
v = v.srgb_to_linear();
bv_linear.x = v.r;
bv_linear.y = v.g;
@@ -1761,7 +1796,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Rect2 v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1769,7 +1804,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_MAT2: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 4) {
m2.resize(4);
@@ -1786,7 +1821,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT3: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Basis v = p_value;
bv[0].x = v.rows[0][0];
bv[0].y = v.rows[1][0];
@@ -1805,7 +1840,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT4: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 16) {
@@ -1834,7 +1869,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform2D v = p_value;
bv[0].x = v.columns[0][0];
bv[0].y = v.columns[0][1];
@@ -1853,7 +1888,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform3D v = p_value;
bv[0].x = v.basis.rows[0][0];
bv[0].y = v.basis.rows[1][0];
@@ -1882,15 +1917,15 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
}
}
-void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
+void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
int32_t prev_chunk = -1;
for (int32_t i = 0; i < p_elements; i++) {
- int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ int32_t chunk = (p_index + i) / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
if (chunk != prev_chunk) {
- if (!global_variables.buffer_dirty_regions[chunk]) {
- global_variables.buffer_dirty_regions[chunk] = true;
- global_variables.buffer_dirty_region_count++;
+ if (!global_shader_uniforms.buffer_dirty_regions[chunk]) {
+ global_shader_uniforms.buffer_dirty_regions[chunk] = true;
+ global_shader_uniforms.buffer_dirty_region_count++;
}
}
@@ -1898,16 +1933,16 @@ void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_
}
}
-void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
- ERR_FAIL_COND(global_variables.variables.has(p_name));
- GlobalVariables::Variable gv;
+void MaterialStorage::global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) {
+ ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable gv;
gv.type = p_type;
gv.value = p_value;
gv.buffer_index = -1;
if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
//is texture
- global_variables.must_update_texture_materials = true; //normally there are none
+ global_shader_uniforms.must_update_texture_materials = true; //normally there are none
} else {
gv.buffer_elements = 1;
if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
@@ -1924,56 +1959,56 @@ void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVa
}
//is vector, allocate in buffer and update index
- gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+ gv.buffer_index = _global_shader_uniform_allocate(gv.buffer_elements);
ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
- global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- global_variables.must_update_buffer_materials = true; //normally there are none
+ global_shader_uniforms.must_update_buffer_materials = true; //normally there are none
}
- global_variables.variables[p_name] = gv;
+ global_shader_uniforms.variables[p_name] = gv;
}
-void MaterialStorage::global_variable_remove(const StringName &p_name) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_uniform_remove(const StringName &p_name) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return;
}
- const GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ const GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
if (gv.buffer_index >= 0) {
- global_variables.buffer_usage[gv.buffer_index].elements = 0;
- global_variables.must_update_buffer_materials = true;
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = 0;
+ global_shader_uniforms.must_update_buffer_materials = true;
} else {
- global_variables.must_update_texture_materials = true;
+ global_shader_uniforms.must_update_texture_materials = true;
}
- global_variables.variables.erase(p_name);
+ global_shader_uniforms.variables.erase(p_name);
}
-Vector<StringName> MaterialStorage::global_variable_get_list() const {
+Vector<StringName> MaterialStorage::global_shader_uniform_get_list() const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
}
Vector<StringName> names;
- for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+ for (const KeyValue<StringName, GlobalShaderUniforms::Variable> &E : global_shader_uniforms.variables) {
names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
return names;
}
-void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
- ERR_FAIL_COND(!global_variables.variables.has(p_name));
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+void MaterialStorage::global_shader_uniform_set(const StringName &p_name, const Variant &p_value) {
+ ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.value = p_value;
if (gv.override.get_type() == Variant::NIL) {
if (gv.buffer_index >= 0) {
//buffer
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -1986,26 +2021,26 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian
}
}
-void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return; //variable may not exist
}
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.override = p_value;
if (gv.buffer_index >= 0) {
//buffer
if (gv.override.get_type() == Variant::NIL) {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
} else {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.override);
}
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -2017,35 +2052,35 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con
}
}
-Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+Variant MaterialStorage::global_shader_uniform_get(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
}
- if (!global_variables.variables.has(p_name)) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return Variant();
}
- return global_variables.variables[p_name].value;
+ return global_shader_uniforms.variables[p_name].value;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const {
- if (!global_variables.variables.has(p_name)) {
+RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type_internal(const StringName &p_name) const {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return RS::GLOBAL_VAR_TYPE_MAX;
}
- return global_variables.variables[p_name].type;
+ return global_shader_uniforms.variables[p_name].type;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
}
- return global_variable_get_type_internal(p_name);
+ return global_shader_uniform_get_type_internal(p_name);
}
-void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) {
List<PropertyInfo> settings;
ProjectSettings::get_singleton()->get_property_list(&settings);
@@ -2090,11 +2125,11 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
"samplerCube",
};
- RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+ RS::GlobalShaderUniformType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
if (global_var_type_names[i] == type) {
- gvtype = RS::GlobalVariableType(i);
+ gvtype = RS::GlobalShaderUniformType(i);
break;
}
}
@@ -2116,47 +2151,47 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
value = resource;
}
- if (global_variables.variables.has(name)) {
+ if (global_shader_uniforms.variables.has(name)) {
//has it, update it
- global_variable_set(name, value);
+ global_shader_uniform_set(name, value);
} else {
- global_variable_add(name, gvtype, value);
+ global_shader_uniform_add(name, gvtype, value);
}
}
}
}
-void MaterialStorage::global_variables_clear() {
- global_variables.variables.clear(); //not right but for now enough
+void MaterialStorage::global_shader_uniforms_clear() {
+ global_shader_uniforms.variables.clear(); //not right but for now enough
}
-RID MaterialStorage::global_variables_get_storage_buffer() const {
- return global_variables.buffer;
+RID MaterialStorage::global_shader_uniforms_get_storage_buffer() const {
+ return global_shader_uniforms.buffer;
}
-int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
- ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
- int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
+int32_t MaterialStorage::global_shader_uniforms_instance_allocate(RID p_instance) {
+ ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1);
+ int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway
ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
- global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+ global_shader_uniforms.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
return pos;
}
-void MaterialStorage::global_variables_instance_free(RID p_instance) {
- ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+void MaterialStorage::global_shader_uniforms_instance_free(RID p_instance) {
+ ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance));
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos >= 0) {
- global_variables.buffer_usage[pos].elements = 0;
+ global_shader_uniforms.buffer_usage[pos].elements = 0;
}
- global_variables.instance_buffer_pos.erase(p_instance);
+ global_shader_uniforms.instance_buffer_pos.erase(p_instance);
}
-void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
- if (!global_variables.instance_buffer_pos.has(p_instance)) {
+void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+ if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) {
return; //just not allocated, ignore
}
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos < 0) {
return; //again, not allocated, ignore
@@ -2177,11 +2212,14 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
ShaderLanguage::TYPE_VEC3, // vec3
ShaderLanguage::TYPE_IVEC3, //vec3i
ShaderLanguage::TYPE_MAX, //xform2d not supported here
+ ShaderLanguage::TYPE_VEC4, //vec4
+ ShaderLanguage::TYPE_IVEC4, //vec4i
ShaderLanguage::TYPE_VEC4, //plane
ShaderLanguage::TYPE_VEC4, //quat
ShaderLanguage::TYPE_MAX, //aabb not supported here
ShaderLanguage::TYPE_MAX, //basis not supported here
ShaderLanguage::TYPE_MAX, //xform not supported here
+ ShaderLanguage::TYPE_MAX, //projection not supported here
ShaderLanguage::TYPE_VEC4 //color
};
@@ -2191,57 +2229,57 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
pos += p_index;
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
- _global_variable_mark_buffer_dirty(pos, 1);
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[pos], true); //instances always use linear color in this renderer
+ _global_shader_uniform_mark_buffer_dirty(pos, 1);
}
-void MaterialStorage::_update_global_variables() {
+void MaterialStorage::_update_global_shader_uniforms() {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
- if (global_variables.buffer_dirty_region_count > 0) {
- uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
+ if (global_shader_uniforms.buffer_dirty_region_count > 0) {
+ uint32_t total_regions = global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
+ if (total_regions / global_shader_uniforms.buffer_dirty_region_count <= 4) {
// 25% of regions dirty, just update all buffer
- RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
+ RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, global_shader_uniforms.buffer_values);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
} else {
- uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ uint32_t region_byte_size = sizeof(GlobalShaderUniforms::Value) * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
for (uint32_t i = 0; i < total_regions; i++) {
- if (global_variables.buffer_dirty_regions[i]) {
- RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
+ if (global_shader_uniforms.buffer_dirty_regions[i]) {
+ RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, i * region_byte_size, region_byte_size, &global_shader_uniforms.buffer_values[i * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE]);
- global_variables.buffer_dirty_regions[i] = false;
+ global_shader_uniforms.buffer_dirty_regions[i] = false;
}
}
}
- global_variables.buffer_dirty_region_count = 0;
+ global_shader_uniforms.buffer_dirty_region_count = 0;
}
- if (global_variables.must_update_buffer_materials) {
+ if (global_shader_uniforms.must_update_buffer_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_buffer) {
+ for (const RID &E : global_shader_uniforms.materials_using_buffer) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, true, false);
}
- global_variables.must_update_buffer_materials = false;
+ global_shader_uniforms.must_update_buffer_materials = false;
}
- if (global_variables.must_update_texture_materials) {
+ if (global_shader_uniforms.must_update_texture_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_texture) {
+ for (const RID &E : global_shader_uniforms.materials_using_texture) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, false, true);
}
- global_variables.must_update_texture_materials = false;
+ global_shader_uniforms.must_update_texture_materials = false;
}
}
@@ -2341,27 +2379,38 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
}
if (shader->data) {
+ shader->data->set_path_hint(shader->path_hint);
shader->data->set_code(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);
}
}
+void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ shader->path_hint = p_path;
+ if (shader->data) {
+ shader->data->set_path_hint(p_path);
+ }
+}
+
String MaterialStorage::shader_get_code(RID p_shader) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, String());
return shader->code;
}
-void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+void MaterialStorage::shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (shader->data) {
- return shader->data->get_param_list(p_param_list);
+ return shader->data->get_shader_uniform_list(p_param_list);
}
}
@@ -2436,7 +2485,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 +2515,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 +2556,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,10 +2579,19 @@ 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);
}
+MaterialStorage::ShaderData *MaterialStorage::material_get_shader_data(RID p_material) {
+ const MaterialStorage::Material *material = MaterialStorage::get_singleton()->get_material(p_material);
+ if (material && material->shader && material->shader->data) {
+ return material->shader->data;
+ }
+
+ return nullptr;
+}
+
void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
@@ -2576,7 +2634,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) {
@@ -2614,19 +2672,19 @@ bool MaterialStorage::material_casts_shadows(RID p_material) {
return true; //by default everything casts shadows
}
-void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
+void MaterialStorage::material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) {
Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
if (material->shader && material->shader->data) {
material->shader->data->get_instance_param_list(r_parameters);
if (material->next_pass.is_valid()) {
- material_get_instance_shader_parameters(material->next_pass, r_parameters);
+ material_get_instance_shader_uniforms(material->next_pass, r_parameters);
}
}
}
-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);
@@ -2635,12 +2693,12 @@ void MaterialStorage::material_update_dependency(RID p_material, RendererStorage
}
}
-void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) {
+void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialStorage::MaterialDataRequestFunction p_function) {
ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
material_data_request_func[p_shader_type] = p_function;
}
-MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) {
+MaterialStorage::MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) {
ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr);
return material_data_request_func[p_shader_type];
}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index f83df05355..dbf7a92e23 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -31,168 +31,73 @@
#ifndef MATERIAL_STORAGE_RD_H
#define MATERIAL_STORAGE_RD_H
+#include "core/math/projection.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 {
-class MaterialStorage;
-
-/* SHADER Structs */
-
-enum ShaderType {
- SHADER_TYPE_2D,
- SHADER_TYPE_3D,
- SHADER_TYPE_PARTICLES,
- SHADER_TYPE_SKY,
- SHADER_TYPE_FOG,
- SHADER_TYPE_MAX
-};
-
-struct ShaderData {
- virtual void set_code(const String &p_Code) = 0;
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
-
- virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
- virtual bool is_param_texture(const StringName &p_param) const = 0;
- virtual bool is_animated() const = 0;
- virtual bool casts_shadows() const = 0;
- virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
-
- virtual ~ShaderData() {}
-};
-
-typedef ShaderData *(*ShaderDataRequestFunction)();
-
-struct Material;
-
-struct Shader {
- ShaderData *data = nullptr;
- String code;
- ShaderType type;
- HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
- HashSet<Material *> owners;
-};
-
-/* Material structs */
-
-struct MaterialData {
- void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
-
- virtual void set_render_priority(int p_priority) = 0;
- virtual void set_next_pass(RID p_pass) = 0;
- virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
- virtual ~MaterialData();
-
- //to be used internally by update_parameters, in the most common configuration of material parameters
- bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- void free_parameters_uniform_set(RID p_uniform_set);
-
-private:
- friend class MaterialStorage;
- RID self;
- List<RID>::Element *global_buffer_E = nullptr;
- List<RID>::Element *global_texture_E = nullptr;
- uint64_t global_textures_pass = 0;
- HashMap<StringName, uint64_t> used_global_textures;
-
- //internally by update_parameters_uniform_set
- Vector<uint8_t> ubo_data;
- RID uniform_buffer;
- Vector<RID> texture_cache;
-};
-
-typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
-
-struct Material {
- RID self;
- MaterialData *data = nullptr;
- Shader *shader = nullptr;
- //shortcut to shader data and type
- ShaderType shader_type = SHADER_TYPE_MAX;
- uint32_t shader_id = 0;
- bool uniform_dirty = false;
- bool texture_dirty = false;
- HashMap<StringName, Variant> params;
- int32_t priority = 0;
- RID next_pass;
- SelfList<Material> update_element;
-
- RendererStorage::Dependency dependency;
-
- Material() :
- update_element(this) {}
-};
-
-/* Global variable structs */
-struct GlobalVariables {
- enum {
- BUFFER_DIRTY_REGION_SIZE = 1024
- };
- struct Variable {
- HashSet<RID> texture_materials; // materials using this
-
- RS::GlobalVariableType type;
- Variant value;
- Variant override;
- int32_t buffer_index; //for vectors
- int32_t buffer_elements; //for vectors
+class MaterialStorage : public RendererMaterialStorage {
+public:
+ enum ShaderType {
+ SHADER_TYPE_2D,
+ SHADER_TYPE_3D,
+ SHADER_TYPE_PARTICLES,
+ SHADER_TYPE_SKY,
+ SHADER_TYPE_FOG,
+ SHADER_TYPE_MAX
};
- HashMap<StringName, Variable> variables;
+ struct ShaderData {
+ virtual void set_code(const String &p_Code) = 0;
+ virtual void set_path_hint(const String &p_hint) = 0;
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0;
- struct Value {
- float x;
- float y;
- float z;
- float w;
- };
-
- struct ValueInt {
- int32_t x;
- int32_t y;
- int32_t z;
- int32_t w;
- };
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
+ virtual bool is_param_texture(const StringName &p_param) const = 0;
+ virtual bool is_animated() const = 0;
+ virtual bool casts_shadows() const = 0;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
- struct ValueUInt {
- uint32_t x;
- uint32_t y;
- uint32_t z;
- uint32_t w;
+ virtual ~ShaderData() {}
};
- struct ValueUsage {
- uint32_t elements = 0;
- };
+ struct MaterialData {
+ void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
+ void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
- List<RID> materials_using_buffer;
- List<RID> materials_using_texture;
+ virtual void set_render_priority(int p_priority) = 0;
+ virtual void set_next_pass(RID p_pass) = 0;
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
+ virtual ~MaterialData();
- RID buffer;
- Value *buffer_values = nullptr;
- ValueUsage *buffer_usage = nullptr;
- bool *buffer_dirty_regions = nullptr;
- uint32_t buffer_dirty_region_count = 0;
+ //to be used internally by update_parameters, in the most common configuration of material parameters
+ bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void free_parameters_uniform_set(RID p_uniform_set);
- uint32_t buffer_size;
+ private:
+ friend class MaterialStorage;
- bool must_update_texture_materials = false;
- bool must_update_buffer_materials = false;
+ RID self;
+ List<RID>::Element *global_buffer_E = nullptr;
+ List<RID>::Element *global_texture_E = nullptr;
+ uint64_t global_textures_pass = 0;
+ HashMap<StringName, uint64_t> used_global_textures;
- HashMap<RID, int32_t> instance_buffer_pos;
-};
+ //internally by update_parameters_uniform_set
+ Vector<uint8_t> ubo_data;
+ RID uniform_buffer;
+ Vector<RID> texture_cache;
+ };
-class MaterialStorage : public RendererMaterialStorage {
private:
- friend struct MaterialData;
static MaterialStorage *singleton;
/* Samplers */
@@ -205,22 +110,116 @@ private:
RID quad_index_buffer;
RID quad_index_array;
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
+
+ struct GlobalShaderUniforms {
+ enum {
+ BUFFER_DIRTY_REGION_SIZE = 1024
+ };
+ struct Variable {
+ HashSet<RID> texture_materials; // materials using this
+
+ RS::GlobalShaderUniformType type;
+ Variant value;
+ Variant override;
+ int32_t buffer_index; //for vectors
+ int32_t buffer_elements; //for vectors
+ };
+
+ HashMap<StringName, Variable> variables;
+
+ struct Value {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ struct ValueInt {
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int32_t w;
+ };
+
+ struct ValueUInt {
+ uint32_t x;
+ uint32_t y;
+ uint32_t z;
+ uint32_t w;
+ };
+
+ struct ValueUsage {
+ uint32_t elements = 0;
+ };
+
+ List<RID> materials_using_buffer;
+ List<RID> materials_using_texture;
+
+ RID buffer;
+ Value *buffer_values = nullptr;
+ ValueUsage *buffer_usage = nullptr;
+ bool *buffer_dirty_regions = nullptr;
+ uint32_t buffer_dirty_region_count = 0;
+
+ uint32_t buffer_size;
+
+ bool must_update_texture_materials = false;
+ bool must_update_buffer_materials = false;
+
+ HashMap<RID, int32_t> instance_buffer_pos;
+ } global_shader_uniforms;
+
+ int32_t _global_shader_uniform_allocate(uint32_t p_elements);
+ void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value);
+ void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
- GlobalVariables global_variables;
+ /* SHADER API */
- int32_t _global_variable_allocate(uint32_t p_elements);
- void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
- void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+ struct Material;
- /* SHADER API */
+ struct Shader {
+ ShaderData *data = nullptr;
+ String code;
+ String path_hint;
+ ShaderType type;
+ HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
+ HashSet<Material *> owners;
+ };
+ typedef ShaderData *(*ShaderDataRequestFunction)();
ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
+
mutable RID_Owner<Shader, true> shader_owner;
+ Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }
/* MATERIAL API */
+
+ typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
+
+ struct Material {
+ RID self;
+ MaterialData *data = nullptr;
+ Shader *shader = nullptr;
+ //shortcut to shader data and type
+ ShaderType shader_type = SHADER_TYPE_MAX;
+ uint32_t shader_id = 0;
+ bool uniform_dirty = false;
+ bool texture_dirty = false;
+ HashMap<StringName, Variant> params;
+ int32_t priority = 0;
+ RID next_pass;
+ SelfList<Material> update_element;
+
+ Dependency dependency;
+
+ Material() :
+ update_element(this) {}
+ };
+
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
mutable RID_Owner<Material, true> material_owner;
+ Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
SelfList<Material>::List material_update_list;
@@ -232,6 +231,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 Projection &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) {
@@ -249,32 +328,31 @@ public:
RID get_quad_index_array() { return quad_index_array; }
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- void _update_global_variables();
+ void _update_global_shader_uniforms();
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
- virtual void global_variable_remove(const StringName &p_name) override;
- virtual Vector<StringName> global_variable_get_list() const override;
+ virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override;
+ virtual void global_shader_uniform_remove(const StringName &p_name) override;
+ virtual Vector<StringName> global_shader_uniform_get_list() const override;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
- virtual Variant global_variable_get(const StringName &p_name) const override;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
- RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override;
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override;
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const override;
+ virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override;
+ RS::GlobalShaderUniformType global_shader_uniform_get_type_internal(const StringName &p_name) const;
- virtual void global_variables_load_settings(bool p_load_textures = true) override;
- virtual void global_variables_clear() override;
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override;
+ virtual void global_shader_uniforms_clear() override;
- virtual int32_t global_variables_instance_allocate(RID p_instance) override;
- virtual void global_variables_instance_free(RID p_instance) override;
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+ virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override;
+ virtual void global_shader_uniforms_instance_free(RID p_instance) override;
+ virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
- RID global_variables_get_storage_buffer() const;
+ RID global_shader_uniforms_get_storage_buffer() const;
/* SHADER API */
- Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); };
bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
virtual RID shader_allocate() override;
@@ -282,8 +360,9 @@ public:
virtual void shader_free(RID p_rid) override;
virtual void shader_set_code(RID p_shader, const String &p_code) override;
+ virtual void shader_set_path_hint(RID p_shader, const String &p_path) override;
virtual String shader_get_code(RID p_shader) const override;
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
+ virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
@@ -294,7 +373,6 @@ public:
/* MATERIAL API */
- Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
@@ -305,6 +383,7 @@ public:
virtual void material_free(RID p_rid) override;
virtual void material_set_shader(RID p_material, RID p_shader) override;
+ ShaderData *material_get_shader_data(RID p_material);
virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;
@@ -315,9 +394,9 @@ public:
virtual bool material_is_animated(RID p_material) override;
virtual bool material_casts_shadows(RID p_material) override;
- virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
+ virtual void material_get_instance_shader_uniforms(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);
@@ -339,4 +418,4 @@ public:
} // namespace RendererRD
-#endif // !MATERIAL_STORAGE_RD_H
+#endif // MATERIAL_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 1e0d67f269..dc3f35f942 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);
}
}
@@ -756,6 +758,13 @@ bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton);
}
+Dependency *MeshStorage::mesh_get_dependency(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, nullptr);
+
+ return &mesh->dependency;
+}
+
/* MESH INSTANCE */
RID MeshStorage::mesh_instance_create(RID p_base) {
@@ -1209,7 +1218,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 +1252,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
@@ -1471,6 +1480,13 @@ RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const {
return multimesh->mesh;
}
+Dependency *MeshStorage::multimesh_get_dependency(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, nullptr);
+
+ return &multimesh->dependency;
+}
+
Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Transform3D());
@@ -1602,7 +1618,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 +1660,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 +1719,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 +1797,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 +1918,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 +1929,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..5c0d019c15 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -35,245 +35,156 @@
#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 {
-/* Mesh */
-
-enum DefaultRDBuffer {
- DEFAULT_RD_BUFFER_VERTEX,
- DEFAULT_RD_BUFFER_NORMAL,
- DEFAULT_RD_BUFFER_TANGENT,
- DEFAULT_RD_BUFFER_COLOR,
- DEFAULT_RD_BUFFER_TEX_UV,
- DEFAULT_RD_BUFFER_TEX_UV2,
- DEFAULT_RD_BUFFER_CUSTOM0,
- DEFAULT_RD_BUFFER_CUSTOM1,
- DEFAULT_RD_BUFFER_CUSTOM2,
- DEFAULT_RD_BUFFER_CUSTOM3,
- DEFAULT_RD_BUFFER_BONES,
- DEFAULT_RD_BUFFER_WEIGHTS,
- DEFAULT_RD_BUFFER_MAX,
-};
+class MeshStorage : public RendererMeshStorage {
+public:
+ enum DefaultRDBuffer {
+ DEFAULT_RD_BUFFER_VERTEX,
+ DEFAULT_RD_BUFFER_NORMAL,
+ DEFAULT_RD_BUFFER_TANGENT,
+ DEFAULT_RD_BUFFER_COLOR,
+ DEFAULT_RD_BUFFER_TEX_UV,
+ DEFAULT_RD_BUFFER_TEX_UV2,
+ DEFAULT_RD_BUFFER_CUSTOM0,
+ DEFAULT_RD_BUFFER_CUSTOM1,
+ DEFAULT_RD_BUFFER_CUSTOM2,
+ DEFAULT_RD_BUFFER_CUSTOM3,
+ DEFAULT_RD_BUFFER_BONES,
+ DEFAULT_RD_BUFFER_WEIGHTS,
+ DEFAULT_RD_BUFFER_MAX,
+ };
-struct MeshInstance;
-
-struct Mesh {
- struct Surface {
- RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
- uint32_t format = 0;
-
- RID vertex_buffer;
- RID attribute_buffer;
- RID skin_buffer;
- uint32_t vertex_count = 0;
- uint32_t vertex_buffer_size = 0;
- uint32_t skin_buffer_size = 0;
-
- // A different pipeline needs to be allocated
- // depending on the inputs available in the
- // material.
- // There are never that many geometry/material
- // combinations, so a simple array is the most
- // cache-efficient structure.
-
- struct Version {
- uint32_t input_mask = 0;
- RD::VertexFormatID vertex_format = 0;
- RID vertex_array;
- };
+private:
+ static MeshStorage *singleton;
- SpinLock version_lock; //needed to access versions
- Version *versions = nullptr; //allocated on demand
- uint32_t version_count = 0;
+ RID default_rd_storage_buffer;
- RID index_buffer;
- RID index_array;
- uint32_t index_count = 0;
+ /* Mesh */
- struct LOD {
- float edge_length = 0.0;
- uint32_t index_count = 0;
- RID index_buffer;
- RID index_array;
- };
+ RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
- LOD *lods = nullptr;
- uint32_t lod_count = 0;
+ struct MeshInstance;
+
+ struct Mesh {
+ struct Surface {
+ RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
+ uint32_t format = 0;
+
+ RID vertex_buffer;
+ RID attribute_buffer;
+ RID skin_buffer;
+ uint32_t vertex_count = 0;
+ uint32_t vertex_buffer_size = 0;
+ uint32_t skin_buffer_size = 0;
+
+ // A different pipeline needs to be allocated
+ // depending on the inputs available in the
+ // material.
+ // There are never that many geometry/material
+ // combinations, so a simple array is the most
+ // cache-efficient structure.
+
+ struct Version {
+ uint32_t input_mask = 0;
+ RD::VertexFormatID vertex_format = 0;
+ RID vertex_array;
+ };
+
+ SpinLock version_lock; //needed to access versions
+ Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
- AABB aabb;
+ RID index_buffer;
+ RID index_array;
+ uint32_t index_count = 0;
- Vector<AABB> bone_aabbs;
+ struct LOD {
+ float edge_length = 0.0;
+ uint32_t index_count = 0;
+ RID index_buffer;
+ RID index_array;
+ };
- RID blend_shape_buffer;
+ LOD *lods = nullptr;
+ uint32_t lod_count = 0;
- RID material;
+ AABB aabb;
- uint32_t render_index = 0;
- uint64_t render_pass = 0;
+ Vector<AABB> bone_aabbs;
- uint32_t multimesh_render_index = 0;
- uint64_t multimesh_render_pass = 0;
+ RID blend_shape_buffer;
- uint32_t particles_render_index = 0;
- uint64_t particles_render_pass = 0;
+ RID material;
- RID uniform_set;
- };
+ uint32_t render_index = 0;
+ uint64_t render_pass = 0;
- uint32_t blend_shape_count = 0;
- RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
+ uint32_t multimesh_render_index = 0;
+ uint64_t multimesh_render_pass = 0;
- Surface **surfaces = nullptr;
- uint32_t surface_count = 0;
+ uint32_t particles_render_index = 0;
+ uint64_t particles_render_pass = 0;
- Vector<AABB> bone_aabbs;
+ RID uniform_set;
+ };
- bool has_bone_weights = false;
+ uint32_t blend_shape_count = 0;
+ RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
- AABB aabb;
- AABB custom_aabb;
+ Surface **surfaces = nullptr;
+ uint32_t surface_count = 0;
- Vector<RID> material_cache;
+ Vector<AABB> bone_aabbs;
- List<MeshInstance *> instances;
+ bool has_bone_weights = false;
- RID shadow_mesh;
- HashSet<Mesh *> shadow_owners;
+ AABB aabb;
+ AABB custom_aabb;
- RendererStorage::Dependency dependency;
-};
+ Vector<RID> material_cache;
-/* Mesh Instance */
+ List<MeshInstance *> instances;
-struct MeshInstance {
- Mesh *mesh = nullptr;
- RID skeleton;
- struct Surface {
- RID vertex_buffer;
- RID uniform_set;
+ RID shadow_mesh;
+ HashSet<Mesh *> shadow_owners;
- Mesh::Surface::Version *versions = nullptr; //allocated on demand
- uint32_t version_count = 0;
+ Dependency dependency;
};
- LocalVector<Surface> surfaces;
- LocalVector<float> blend_weights;
-
- RID blend_weights_buffer;
- List<MeshInstance *>::Element *I = nullptr; //used to erase itself
- uint64_t skeleton_version = 0;
- bool dirty = false;
- bool weights_dirty = false;
- SelfList<MeshInstance> weight_update_list;
- SelfList<MeshInstance> array_update_list;
- MeshInstance() :
- weight_update_list(this), array_update_list(this) {}
-};
-
-/* MultiMesh */
-
-struct MultiMesh {
- RID mesh;
- int instances = 0;
- RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
- bool uses_colors = false;
- bool uses_custom_data = false;
- int visible_instances = -1;
- AABB aabb;
- bool aabb_dirty = false;
- bool buffer_set = false;
- uint32_t stride_cache = 0;
- uint32_t color_offset_cache = 0;
- uint32_t custom_data_offset_cache = 0;
-
- Vector<float> data_cache; //used if individual setting is used
- bool *data_cache_dirty_regions = nullptr;
- uint32_t data_cache_used_dirty_regions = 0;
-
- RID buffer; //storage buffer
- RID uniform_set_3d;
- RID uniform_set_2d;
-
- bool dirty = false;
- MultiMesh *dirty_list = nullptr;
-
- RendererStorage::Dependency dependency;
-};
-/* Skeleton */
-
-struct SkeletonShader {
- struct PushConstant {
- uint32_t has_normal;
- uint32_t has_tangent;
- uint32_t has_skeleton;
- uint32_t has_blend_shape;
+ mutable RID_Owner<Mesh, true> mesh_owner;
- uint32_t vertex_count;
- uint32_t vertex_stride;
- uint32_t skin_stride;
- uint32_t skin_weight_offset;
+ /* Mesh Instance API */
- uint32_t blend_shape_count;
- uint32_t normalized_blend_shapes;
- uint32_t pad0;
- uint32_t pad1;
- };
+ struct MeshInstance {
+ Mesh *mesh = nullptr;
+ RID skeleton;
+ struct Surface {
+ RID vertex_buffer;
+ RID uniform_set;
- enum {
- UNIFORM_SET_INSTANCE = 0,
- UNIFORM_SET_SURFACE = 1,
- UNIFORM_SET_SKELETON = 2,
- };
- enum {
- SHADER_MODE_2D,
- SHADER_MODE_3D,
- SHADER_MODE_MAX
+ Mesh::Surface::Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
+ };
+ LocalVector<Surface> surfaces;
+ LocalVector<float> blend_weights;
+
+ RID blend_weights_buffer;
+ List<MeshInstance *>::Element *I = nullptr; //used to erase itself
+ uint64_t skeleton_version = 0;
+ bool dirty = false;
+ bool weights_dirty = false;
+ SelfList<MeshInstance> weight_update_list;
+ SelfList<MeshInstance> array_update_list;
+ MeshInstance() :
+ weight_update_list(this), array_update_list(this) {}
};
- SkeletonShaderRD shader;
- RID version;
- RID version_shader[SHADER_MODE_MAX];
- RID pipeline[SHADER_MODE_MAX];
-
- RID default_skeleton_uniform_set;
-};
-
-struct Skeleton {
- bool use_2d = false;
- int size = 0;
- Vector<float> data;
- RID buffer;
-
- bool dirty = false;
- Skeleton *dirty_list = nullptr;
- Transform2D base_transform_2d;
-
- RID uniform_set_3d;
- RID uniform_set_mi;
-
- uint64_t version = 1;
-
- RendererStorage::Dependency dependency;
-};
-
-class MeshStorage : public RendererMeshStorage {
-private:
- static MeshStorage *singleton;
-
- RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
- RID default_rd_storage_buffer;
-
- /* Mesh */
-
- mutable RID_Owner<Mesh, true> mesh_owner;
-
void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr);
- /* Mesh Instance API */
-
void _mesh_instance_clear(MeshInstance *mi);
void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
@@ -284,6 +195,34 @@ private:
/* MultiMesh */
+ struct MultiMesh {
+ RID mesh;
+ int instances = 0;
+ RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
+ bool uses_colors = false;
+ bool uses_custom_data = false;
+ int visible_instances = -1;
+ AABB aabb;
+ bool aabb_dirty = false;
+ bool buffer_set = false;
+ uint32_t stride_cache = 0;
+ uint32_t color_offset_cache = 0;
+ uint32_t custom_data_offset_cache = 0;
+
+ Vector<float> data_cache; //used if individual setting is used
+ bool *data_cache_dirty_regions = nullptr;
+ uint32_t data_cache_used_dirty_regions = 0;
+
+ RID buffer; //storage buffer
+ RID uniform_set_3d;
+ RID uniform_set_2d;
+
+ bool dirty = false;
+ MultiMesh *dirty_list = nullptr;
+
+ Dependency dependency;
+ };
+
mutable RID_Owner<MultiMesh, true> multimesh_owner;
MultiMesh *multimesh_dirty_list = nullptr;
@@ -295,7 +234,60 @@ private:
/* Skeleton */
- SkeletonShader skeleton_shader;
+ struct SkeletonShader {
+ struct PushConstant {
+ uint32_t has_normal;
+ uint32_t has_tangent;
+ uint32_t has_skeleton;
+ uint32_t has_blend_shape;
+
+ uint32_t vertex_count;
+ uint32_t vertex_stride;
+ uint32_t skin_stride;
+ uint32_t skin_weight_offset;
+
+ uint32_t blend_shape_count;
+ uint32_t normalized_blend_shapes;
+ uint32_t pad0;
+ uint32_t pad1;
+ };
+
+ enum {
+ UNIFORM_SET_INSTANCE = 0,
+ UNIFORM_SET_SURFACE = 1,
+ UNIFORM_SET_SKELETON = 2,
+ };
+ enum {
+ SHADER_MODE_2D,
+ SHADER_MODE_3D,
+ SHADER_MODE_MAX
+ };
+
+ SkeletonShaderRD shader;
+ RID version;
+ RID version_shader[SHADER_MODE_MAX];
+ RID pipeline[SHADER_MODE_MAX];
+
+ RID default_skeleton_uniform_set;
+ } skeleton_shader;
+
+ struct Skeleton {
+ bool use_2d = false;
+ int size = 0;
+ Vector<float> data;
+ RID buffer;
+
+ bool dirty = false;
+ Skeleton *dirty_list = nullptr;
+ Transform2D base_transform_2d;
+
+ RID uniform_set_3d;
+ RID uniform_set_mi;
+
+ uint64_t version = 1;
+
+ Dependency dependency;
+ };
mutable RID_Owner<Skeleton, true> skeleton_owner;
@@ -309,11 +301,10 @@ public:
MeshStorage();
virtual ~MeshStorage();
- RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; }
+ RID get_default_rd_storage_buffer() const { return default_rd_storage_buffer; }
/* MESH API */
- Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); };
bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
virtual RID mesh_allocate() override;
@@ -542,10 +533,11 @@ public:
return s->particles_render_index;
}
+ Dependency *mesh_get_dependency(RID p_mesh) const;
+
/* MESH INSTANCE API */
- MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); };
- bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); };
+ bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); };
virtual RID mesh_instance_create(RID p_base) override;
virtual void mesh_instance_free(RID p_rid) override;
@@ -556,7 +548,6 @@ public:
/* MULTIMESH API */
- MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); };
bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
virtual RID multimesh_allocate() override;
@@ -654,10 +645,11 @@ public:
return multimesh->uniform_set_2d;
}
+ Dependency *multimesh_get_dependency(RID p_multimesh) const;
+
/* SKELETON API */
- Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
- bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); };
+ bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); };
virtual RID skeleton_allocate() override;
virtual void skeleton_initialize(RID p_skeleton) override;
@@ -672,7 +664,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();
@@ -703,4 +695,4 @@ public:
} // namespace RendererRD
-#endif // !MESH_STORAGE_RD_H
+#endif // MESH_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 58a96ed1f9..ba644e7eb9 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"
@@ -55,8 +54,8 @@ ParticlesStorage::ParticlesStorage() {
particles_modes.push_back("");
particles_shader.shader.initialize(particles_modes, String());
}
- MaterialStorage::get_singleton()->shader_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
- MaterialStorage::get_singleton()->material_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
+ MaterialStorage::get_singleton()->shader_set_data_request_function(MaterialStorage::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
+ MaterialStorage::get_singleton()->material_set_data_request_function(MaterialStorage::SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
{
ShaderCompiler::DefaultIdentifierActions actions;
@@ -113,7 +112,7 @@ ParticlesStorage::ParticlesStorage() {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
particles_shader.compiler.initialize(actions);
}
@@ -135,7 +134,7 @@ void process() {
material_storage->material_initialize(particles_shader.default_material);
material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
- ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+ ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
Vector<RD::Uniform> uniforms;
@@ -165,7 +164,7 @@ void process() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.append_id(material_storage->global_variables_get_storage_buffer());
+ u.append_id(material_storage->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -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;
@@ -988,14 +987,13 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
RID rd_tex;
if (i < collision_3d_textures_used) {
- Texture *t = TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]);
- if (t && t->type == Texture::TYPE_3D) {
- rd_tex = t->rd_texture;
+ if (TextureStorage::get_singleton()->texture_get_type(collision_3d_textures[i]) == TextureStorage::TYPE_3D) {
+ rd_tex = TextureStorage::get_singleton()->texture_get_rd_texture(collision_3d_textures[i]);
}
}
if (rd_tex == RID()) {
- rd_tex = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ rd_tex = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
}
u.append_id(rd_tex);
}
@@ -1008,7 +1006,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
if (collision_heightmap_texture.is_valid()) {
u.append_id(collision_heightmap_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK));
}
uniforms.push_back(u);
}
@@ -1074,9 +1072,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
- ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES));
+ ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES));
if (!m) {
- m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+ m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
}
ERR_FAIL_COND(!m);
@@ -1203,7 +1201,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;
@@ -1229,10 +1227,10 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
void ParticlesStorage::_particles_update_buffers(Particles *particles) {
uint32_t userdata_count = 0;
- const Material *material = MaterialStorage::get_singleton()->get_material(particles->process_material);
- if (material && material->shader && material->shader->data) {
- const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data);
- userdata_count = shader_data->userdata_count;
+ MaterialStorage::ShaderData *shader_data = MaterialStorage::get_singleton()->material_get_shader_data(particles->process_material);
+ if (shader_data) {
+ const ParticlesShaderData *particle_shader_data = static_cast<const ParticlesShaderData *>(shader_data);
+ userdata_count = particle_shader_data->userdata_count;
}
if (userdata_count != particles->userdata_count) {
@@ -1383,7 +1381,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 +1455,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,10 +1498,17 @@ 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);
}
}
+Dependency *ParticlesStorage::particles_get_dependency(RID p_particles) const {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_NULL_V(particles, nullptr);
+
+ return &particles->dependency;
+}
+
bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
const Particles *particles = particles_owner.get_or_null(p_particles);
@@ -1513,6 +1518,9 @@ bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
/* Particles SHADER */
+void ParticlesStorage::ParticlesShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
ParticlesStorage *particles_storage = ParticlesStorage::get_singleton();
//compile
@@ -1595,7 +1603,7 @@ void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const Stri
}
}
-void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void ParticlesStorage::ParticlesShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -1610,7 +1618,22 @@ void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -1668,7 +1691,7 @@ ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() {
}
}
-ShaderData *ParticlesStorage::_create_particles_shader_func() {
+MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() {
ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
return shader_data;
}
@@ -1681,7 +1704,7 @@ ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) {
+MaterialStorage::MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) {
ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -1756,7 +1779,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 +1793,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 +1801,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 +1835,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) {
@@ -1867,6 +1890,15 @@ bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collis
return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
}
+Dependency *ParticlesStorage::particles_collision_get_dependency(RID p_particles_collision) const {
+ ParticlesCollision *pc = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_NULL_V(pc, nullptr);
+
+ return &pc->dependency;
+}
+
+/* Particles collision instance */
+
RID ParticlesStorage::particles_collision_instance_create(RID p_collision) {
ParticlesCollisionInstance pci;
pci.collision = p_collision;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index 115633d17a..97d100e2da 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -37,237 +37,209 @@
#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 {
-/* PARTICLES */
-
-struct ParticleData {
- float xform[16];
- float velocity[3];
- uint32_t active;
- float color[4];
- float custom[3];
- float lifetime;
-};
+class ParticlesStorage : public RendererParticlesStorage {
+private:
+ static ParticlesStorage *singleton;
-struct ParticlesFrameParams {
- enum {
- MAX_ATTRACTORS = 32,
- MAX_COLLIDERS = 32,
- MAX_3D_TEXTURES = 7
- };
+ /* PARTICLES */
- enum AttractorType {
- ATTRACTOR_TYPE_SPHERE,
- ATTRACTOR_TYPE_BOX,
- ATTRACTOR_TYPE_VECTOR_FIELD,
+ struct ParticleData {
+ float xform[16];
+ float velocity[3];
+ uint32_t active;
+ float color[4];
+ float custom[3];
+ float lifetime;
};
- struct Attractor {
- float transform[16];
- float extents[3]; //exents or radius
- uint32_t type;
+ struct ParticlesFrameParams {
+ enum {
+ MAX_ATTRACTORS = 32,
+ MAX_COLLIDERS = 32,
+ MAX_3D_TEXTURES = 7
+ };
- uint32_t texture_index; //texture index for vector field
- float strength;
- float attenuation;
- float directionality;
- };
+ enum AttractorType {
+ ATTRACTOR_TYPE_SPHERE,
+ ATTRACTOR_TYPE_BOX,
+ ATTRACTOR_TYPE_VECTOR_FIELD,
+ };
- enum CollisionType {
- COLLISION_TYPE_SPHERE,
- COLLISION_TYPE_BOX,
- COLLISION_TYPE_SDF,
- COLLISION_TYPE_HEIGHT_FIELD,
- COLLISION_TYPE_2D_SDF,
+ struct Attractor {
+ float transform[16];
+ float extents[3]; //exents or radius
+ uint32_t type;
- };
+ uint32_t texture_index; //texture index for vector field
+ float strength;
+ float attenuation;
+ float directionality;
+ };
- struct Collider {
- float transform[16];
- float extents[3]; //exents or radius
- uint32_t type;
+ enum CollisionType {
+ COLLISION_TYPE_SPHERE,
+ COLLISION_TYPE_BOX,
+ COLLISION_TYPE_SDF,
+ COLLISION_TYPE_HEIGHT_FIELD,
+ COLLISION_TYPE_2D_SDF,
- uint32_t texture_index; //texture index for vector field
- real_t scale;
- uint32_t pad[2];
- };
+ };
- uint32_t emitting;
- float system_phase;
- float prev_system_phase;
- uint32_t cycle;
+ struct Collider {
+ float transform[16];
+ float extents[3]; //exents or radius
+ uint32_t type;
- real_t explosiveness;
- real_t randomness;
- float time;
- float delta;
+ uint32_t texture_index; //texture index for vector field
+ real_t scale;
+ uint32_t pad[2];
+ };
- uint32_t frame;
- uint32_t pad0;
- uint32_t pad1;
- uint32_t pad2;
+ uint32_t emitting;
+ float system_phase;
+ float prev_system_phase;
+ uint32_t cycle;
- uint32_t random_seed;
- uint32_t attractor_count;
- uint32_t collider_count;
- float particle_size;
+ real_t explosiveness;
+ real_t randomness;
+ float time;
+ float delta;
- float emission_transform[16];
+ uint32_t frame;
+ uint32_t pad0;
+ uint32_t pad1;
+ uint32_t pad2;
- Attractor attractors[MAX_ATTRACTORS];
- Collider colliders[MAX_COLLIDERS];
-};
+ uint32_t random_seed;
+ uint32_t attractor_count;
+ uint32_t collider_count;
+ float particle_size;
-struct ParticleEmissionBufferData {
-};
+ float emission_transform[16];
-struct ParticleEmissionBuffer {
- struct Data {
- float xform[16];
- float velocity[3];
- uint32_t flags;
- float color[4];
- float custom[4];
+ Attractor attractors[MAX_ATTRACTORS];
+ Collider colliders[MAX_COLLIDERS];
};
- int32_t particle_count;
- int32_t particle_max;
- uint32_t pad1;
- uint32_t pad2;
- Data data[1]; //its 2020 and empty arrays are still non standard in C++
-};
-
-struct Particles {
- RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
- bool inactive = true;
- double inactive_time = 0.0;
- bool emitting = false;
- bool one_shot = false;
- int amount = 0;
- double lifetime = 1.0;
- double pre_process_time = 0.0;
- real_t explosiveness = 0.0;
- real_t randomness = 0.0;
- bool restart_request = false;
- AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
- bool use_local_coords = true;
- bool has_collision_cache = false;
-
- bool has_sdf_collision = false;
- Transform2D sdf_collision_transform;
- Rect2 sdf_collision_to_screen;
- RID sdf_collision_texture;
-
- RID process_material;
- uint32_t frame_counter = 0;
- RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
-
- RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
-
- Vector<RID> draw_passes;
- Vector<Transform3D> trail_bind_poses;
- bool trail_bind_poses_dirty = false;
- RID trail_bind_pose_buffer;
- RID trail_bind_pose_uniform_set;
-
- RID particle_buffer;
- RID particle_instance_buffer;
- RID frame_params_buffer;
-
- uint32_t userdata_count = 0;
-
- RID particles_material_uniform_set;
- RID particles_copy_uniform_set;
- RID particles_transforms_buffer_uniform_set;
- RID collision_textures_uniform_set;
-
- RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
- uint32_t collision_3d_textures_used = 0;
- RID collision_heightmap_texture;
+ struct ParticleEmissionBufferData {
+ };
- RID particles_sort_buffer;
- RID particles_sort_uniform_set;
+ struct ParticleEmissionBuffer {
+ struct Data {
+ float xform[16];
+ float velocity[3];
+ uint32_t flags;
+ float color[4];
+ float custom[4];
+ };
- bool dirty = false;
- Particles *update_list = nullptr;
+ int32_t particle_count;
+ int32_t particle_max;
+ uint32_t pad1;
+ uint32_t pad2;
+ Data data[1]; //its 2020 and empty arrays are still non standard in C++
+ };
- RID sub_emitter;
+ struct Particles {
+ RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
+ bool inactive = true;
+ double inactive_time = 0.0;
+ bool emitting = false;
+ bool one_shot = false;
+ int amount = 0;
+ double lifetime = 1.0;
+ double pre_process_time = 0.0;
+ real_t explosiveness = 0.0;
+ real_t randomness = 0.0;
+ bool restart_request = false;
+ AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
+ bool use_local_coords = false;
+ bool has_collision_cache = false;
+
+ bool has_sdf_collision = false;
+ Transform2D sdf_collision_transform;
+ Rect2 sdf_collision_to_screen;
+ RID sdf_collision_texture;
+
+ RID process_material;
+ uint32_t frame_counter = 0;
+ RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
+
+ RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
+
+ Vector<RID> draw_passes;
+ Vector<Transform3D> trail_bind_poses;
+ bool trail_bind_poses_dirty = false;
+ RID trail_bind_pose_buffer;
+ RID trail_bind_pose_uniform_set;
+
+ RID particle_buffer;
+ RID particle_instance_buffer;
+ RID frame_params_buffer;
- double phase = 0.0;
- double prev_phase = 0.0;
- uint64_t prev_ticks = 0;
- uint32_t random_seed = 0;
+ uint32_t userdata_count = 0;
- uint32_t cycle_number = 0;
+ RID particles_material_uniform_set;
+ RID particles_copy_uniform_set;
+ RID particles_transforms_buffer_uniform_set;
+ RID collision_textures_uniform_set;
- double speed_scale = 1.0;
+ RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
+ uint32_t collision_3d_textures_used = 0;
+ RID collision_heightmap_texture;
- int fixed_fps = 30;
- bool interpolate = true;
- bool fractional_delta = false;
- double frame_remainder = 0;
- real_t collision_base_size = 0.01;
+ RID particles_sort_buffer;
+ RID particles_sort_uniform_set;
- bool clear = true;
+ bool dirty = false;
+ Particles *update_list = nullptr;
- bool force_sub_emit = false;
+ RID sub_emitter;
- Transform3D emission_transform;
+ double phase = 0.0;
+ double prev_phase = 0.0;
+ uint64_t prev_ticks = 0;
+ uint32_t random_seed = 0;
- Vector<uint8_t> emission_buffer_data;
+ uint32_t cycle_number = 0;
- ParticleEmissionBuffer *emission_buffer = nullptr;
- RID emission_storage_buffer;
+ double speed_scale = 1.0;
- HashSet<RID> collisions;
+ int fixed_fps = 30;
+ bool interpolate = true;
+ bool fractional_delta = false;
+ double frame_remainder = 0;
+ real_t collision_base_size = 0.01;
- RendererStorage::Dependency dependency;
+ bool clear = true;
- double trail_length = 1.0;
- bool trails_enabled = false;
- LocalVector<ParticlesFrameParams> frame_history;
- LocalVector<ParticlesFrameParams> trail_params;
+ bool force_sub_emit = false;
- Particles() {
- }
-};
+ Transform3D emission_transform;
-/* Particles Collision */
+ Vector<uint8_t> emission_buffer_data;
-struct ParticlesCollision {
- RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
- uint32_t cull_mask = 0xFFFFFFFF;
- float radius = 1.0;
- Vector3 extents = Vector3(1, 1, 1);
- float attractor_strength = 1.0;
- float attractor_attenuation = 1.0;
- float attractor_directionality = 0.0;
- RID field_texture;
- RID heightfield_texture;
- RID heightfield_fb;
- Size2i heightfield_fb_size;
+ ParticleEmissionBuffer *emission_buffer = nullptr;
+ RID emission_storage_buffer;
- RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
+ HashSet<RID> collisions;
- RendererStorage::Dependency dependency;
-};
+ Dependency dependency;
-struct ParticlesCollisionInstance {
- RID collision;
- Transform3D transform;
- bool active = false;
-};
+ double trail_length = 1.0;
+ bool trails_enabled = false;
+ LocalVector<ParticlesFrameParams> frame_history;
+ LocalVector<ParticlesFrameParams> trail_params;
-class ParticlesStorage : public RendererParticlesStorage {
-private:
- static ParticlesStorage *singleton;
-
- /* PARTICLES */
+ Particles() {
+ }
+ };
void _particles_process(Particles *p_particles, double p_delta);
void _particles_allocate_emission_buffer(Particles *particles);
@@ -340,7 +312,7 @@ private:
/* Particle Shader */
- struct ParticlesShaderData : public ShaderData {
+ struct ParticlesShaderData : public MaterialStorage::ShaderData {
bool valid = false;
RID version;
bool uses_collision = false;
@@ -363,8 +335,9 @@ private:
uint32_t userdata_count = 0;
virtual void set_code(const String &p_Code);
+ virtual void set_path_hint(const String &p_hint);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -376,12 +349,12 @@ private:
virtual ~ParticlesShaderData();
};
- ShaderData *_create_particles_shader_func();
- static ShaderData *_create_particles_shader_funcs() {
+ MaterialStorage::ShaderData *_create_particles_shader_func();
+ static MaterialStorage::ShaderData *_create_particles_shader_funcs() {
return ParticlesStorage::get_singleton()->_create_particles_shader_func();
}
- struct ParticlesMaterialData : public MaterialData {
+ struct ParticlesMaterialData : public MaterialStorage::MaterialData {
ParticlesShaderData *shader_data = nullptr;
RID uniform_set;
@@ -391,13 +364,37 @@ private:
virtual ~ParticlesMaterialData();
};
- MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
- static MaterialData *_create_particles_material_funcs(ShaderData *p_shader) {
+ MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
+ static MaterialStorage::MaterialData *_create_particles_material_funcs(MaterialStorage::ShaderData *p_shader) {
return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
}
/* Particles Collision */
+ struct ParticlesCollision {
+ RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ float radius = 1.0;
+ Vector3 extents = Vector3(1, 1, 1);
+ float attractor_strength = 1.0;
+ float attractor_attenuation = 1.0;
+ float attractor_directionality = 0.0;
+ RID field_texture;
+ RID heightfield_texture;
+ RID heightfield_fb;
+ Size2i heightfield_fb_size;
+
+ RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
+
+ Dependency dependency;
+ };
+
+ struct ParticlesCollisionInstance {
+ RID collision;
+ Transform3D transform;
+ bool active = false;
+ };
+
mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
@@ -410,7 +407,6 @@ public:
/* PARTICLES */
- Particles *get_particles(RID p_rid) { return particles_owner.get_or_null(p_rid); }
bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
virtual RID particles_allocate() override;
@@ -525,9 +521,10 @@ public:
virtual void update_particles() override;
+ Dependency *particles_get_dependency(RID p_particles) const;
+
/* Particles Collision */
- ParticlesCollision *get_particles_collision(RID p_rid) { return particles_collision_owner.get_or_null(p_rid); }
bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); }
virtual RID particles_collision_allocate() override;
@@ -549,8 +546,9 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
+ Dependency *particles_collision_get_dependency(RID p_particles) const;
+
//used from 2D and 3D
- ParticlesCollisionInstance *get_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.get_or_null(p_rid); }
bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); }
virtual RID particles_collision_instance_create(RID p_collision) override;
@@ -561,4 +559,4 @@ public:
} // namespace RendererRD
-#endif // !PARTICLES_STORAGE_RD_H
+#endif // PARTICLES_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 329c23bad0..e20a04ff2a 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -35,9 +35,9 @@
using namespace RendererRD;
///////////////////////////////////////////////////////////////////////////
-// CanvasTexture
+// TextureStorage::CanvasTexture
-void CanvasTexture::clear_sets() {
+void TextureStorage::CanvasTexture::clear_sets() {
if (cleared_cache) {
return;
}
@@ -52,14 +52,14 @@ void CanvasTexture::clear_sets() {
cleared_cache = true;
}
-CanvasTexture::~CanvasTexture() {
+TextureStorage::CanvasTexture::~CanvasTexture() {
clear_sets();
}
///////////////////////////////////////////////////////////////////////////
-// Texture
+// TextureStorage::Texture
-void Texture::cleanup() {
+void TextureStorage::Texture::cleanup() {
if (RD::get_singleton()->texture_is_valid(rd_texture_srgb)) {
//erase this first, as it's a dependency of the one below
RD::get_singleton()->free(rd_texture_srgb);
@@ -96,6 +96,7 @@ TextureStorage::TextureStorage() {
Vector<uint8_t> pv;
pv.resize(16 * 4);
for (int i = 0; i < 16; i++) {
+ // Opaque white.
pv.set(i * 4 + 0, 255);
pv.set(i * 4 + 1, 255);
pv.set(i * 4 + 2, 255);
@@ -109,6 +110,7 @@ TextureStorage::TextureStorage() {
}
for (int i = 0; i < 16; i++) {
+ // Opaque black.
pv.set(i * 4 + 0, 0);
pv.set(i * 4 + 1, 0);
pv.set(i * 4 + 2, 0);
@@ -122,6 +124,21 @@ TextureStorage::TextureStorage() {
}
for (int i = 0; i < 16; i++) {
+ // Transparent black.
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 0);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_TRANSPARENT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ // Opaque normal map "flat" color.
pv.set(i * 4 + 0, 128);
pv.set(i * 4 + 1, 128);
pv.set(i * 4 + 2, 255);
@@ -135,6 +152,7 @@ TextureStorage::TextureStorage() {
}
for (int i = 0; i < 16; i++) {
+ // Opaque flowmap "flat" color.
pv.set(i * 4 + 0, 255);
pv.set(i * 4 + 1, 128);
pv.set(i * 4 + 2, 255);
@@ -191,7 +209,7 @@ TextureStorage::TextureStorage() {
}
}
- { //create default cubemap
+ { //create default black cubemap array
RD::TextureFormat tformat;
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
@@ -219,7 +237,35 @@ TextureStorage::TextureStorage() {
}
}
- { //create default cubemap array
+ { //create default white cubemap array
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.array_layers = 6;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 255);
+ pv.set(i * 4 + 1, 255);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ for (int i = 0; i < 6; i++) {
+ vpv.push_back(pv);
+ }
+ default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
+ { //create default black cubemap
RD::TextureFormat tformat;
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
@@ -247,7 +293,7 @@ TextureStorage::TextureStorage() {
}
}
- { //create default cubemap white array
+ { //create default white cubemap
RD::TextureFormat tformat;
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
@@ -349,7 +395,6 @@ TextureStorage::TextureStorage() {
Vector<uint8_t> pv;
pv.resize(16 * 4);
-
for (int i = 0; i < 16; i++) {
pv.set(i * 4 + 0, 0);
pv.set(i * 4 + 1, 0);
@@ -358,7 +403,6 @@ TextureStorage::TextureStorage() {
}
{
- //take the chance and initialize decal atlas to something
Vector<Vector<uint8_t>> vpv;
vpv.push_back(pv);
decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
@@ -366,6 +410,28 @@ TextureStorage::TextureStorage() {
}
}
+ { //create default VRS
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8_UINT;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> pv;
+ pv.resize(4 * 4);
+ for (int i = 0; i < 4 * 4; i++) {
+ pv.set(i, 0);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_VRS] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
{
Vector<String> sdf_modes;
sdf_modes.push_back("\n#define MODE_LOAD\n");
@@ -486,7 +552,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
ct = t->canvas_texture;
} else {
- ct = get_canvas_texture(p_texture);
+ ct = canvas_texture_owner.get_or_null(p_texture);
}
if (!ct) {
@@ -609,7 +675,7 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
Texture texture;
- texture.type = Texture::TYPE_2D;
+ texture.type = TextureStorage::TYPE_2D;
texture.width = p_image->get_width();
texture.height = p_image->get_height();
@@ -705,7 +771,7 @@ void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<R
Texture texture;
- texture.type = Texture::TYPE_LAYERED;
+ texture.type = TextureStorage::TYPE_LAYERED;
texture.layered_type = p_layered_type;
texture.width = p_layers[0]->get_width();
@@ -835,7 +901,7 @@ void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format
Texture texture;
- texture.type = Texture::TYPE_3D;
+ texture.type = TextureStorage::TYPE_3D;
texture.width = p_width;
texture.height = p_height;
texture.depth = p_depth;
@@ -927,7 +993,7 @@ void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image
ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height);
ERR_FAIL_COND(p_image->get_format() != tex->format);
- if (tex->type == Texture::TYPE_LAYERED) {
+ if (tex->type == TextureStorage::TYPE_LAYERED) {
ERR_FAIL_INDEX(p_layer, tex->layers);
}
@@ -947,7 +1013,7 @@ void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image,
void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) {
Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
- ERR_FAIL_COND(tex->type != Texture::TYPE_3D);
+ ERR_FAIL_COND(tex->type != TextureStorage::TYPE_3D);
Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data);
if (verr != Image::VALIDATE_3D_OK) {
@@ -1119,7 +1185,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons
Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const {
Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>());
- ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>());
+ ERR_FAIL_COND_V(tex->type != TextureStorage::TYPE_3D, Vector<Ref<Image>>());
Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
@@ -1195,7 +1261,7 @@ void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) {
Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
- ERR_FAIL_COND(tex->type != Texture::TYPE_2D);
+ ERR_FAIL_COND(tex->type != TextureStorage::TYPE_2D);
tex->width_2d = p_width;
tex->height_2d = p_height;
@@ -1712,7 +1778,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 +1802,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 +1827,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) {
@@ -1807,6 +1873,13 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const {
return AABB(-decal->extents, decal->extents * 2.0);
}
+Dependency *TextureStorage::decal_get_dependency(RID p_decal) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND_V(!decal, nullptr);
+
+ return &decal->dependency;
+}
+
void TextureStorage::update_decal_atlas() {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
ERR_FAIL_NULL(copy_effects);
@@ -2751,3 +2824,31 @@ void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_targe
ERR_FAIL_COND(!rt);
rt->backbuffer_uniform_set = p_uniform_set;
}
+
+void TextureStorage::render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->vrs_mode = p_mode;
+}
+
+void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->vrs_texture = p_texture;
+}
+
+RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RS::VIEWPORT_VRS_DISABLED);
+
+ return rt->vrs_mode;
+}
+
+RID TextureStorage::render_target_get_vrs_texture(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->vrs_texture;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 901f764085..682c951f63 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -33,247 +33,138 @@
#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 {
-enum DefaultRDTexture {
- DEFAULT_RD_TEXTURE_WHITE,
- DEFAULT_RD_TEXTURE_BLACK,
- DEFAULT_RD_TEXTURE_NORMAL,
- DEFAULT_RD_TEXTURE_ANISO,
- DEFAULT_RD_TEXTURE_DEPTH,
- DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
- DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
- DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
- DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
- DEFAULT_RD_TEXTURE_3D_WHITE,
- DEFAULT_RD_TEXTURE_3D_BLACK,
- DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
- DEFAULT_RD_TEXTURE_2D_UINT,
- DEFAULT_RD_TEXTURE_MAX
-};
+class LightStorage;
+class MaterialStorage;
-class CanvasTexture {
+class TextureStorage : public RendererTextureStorage {
public:
- RID diffuse;
- RID normal_map;
- RID specular;
- Color specular_color = Color(1, 1, 1, 1);
- float shininess = 1.0;
-
- RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
- RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
- RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
-
- Size2i size_cache = Size2i(1, 1);
- bool use_normal_cache = false;
- bool use_specular_cache = false;
- bool cleared_cache = true;
-
- void clear_sets();
- ~CanvasTexture();
-};
+ enum DefaultRDTexture {
+ DEFAULT_RD_TEXTURE_WHITE,
+ DEFAULT_RD_TEXTURE_BLACK,
+ DEFAULT_RD_TEXTURE_TRANSPARENT,
+ DEFAULT_RD_TEXTURE_NORMAL,
+ DEFAULT_RD_TEXTURE_ANISO,
+ DEFAULT_RD_TEXTURE_DEPTH,
+ DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
+ DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
+ DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
+ DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
+ DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE,
+ DEFAULT_RD_TEXTURE_3D_WHITE,
+ DEFAULT_RD_TEXTURE_3D_BLACK,
+ DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
+ DEFAULT_RD_TEXTURE_2D_UINT,
+ DEFAULT_RD_TEXTURE_VRS,
+ DEFAULT_RD_TEXTURE_MAX
+ };
-class Texture {
-public:
- enum Type {
+ enum TextureType {
TYPE_2D,
TYPE_LAYERED,
TYPE_3D
};
- Type type;
- RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
-
- RenderingDevice::TextureType rd_type;
- RID rd_texture;
- RID rd_texture_srgb;
- RenderingDevice::DataFormat rd_format;
- RenderingDevice::DataFormat rd_format_srgb;
-
- RD::TextureView rd_view;
+private:
+ friend class LightStorage;
+ friend class MaterialStorage;
- Image::Format format;
- Image::Format validated_format;
+ static TextureStorage *singleton;
- int width;
- int height;
- int depth;
- int layers;
- int mipmaps;
+ RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
- int height_2d;
- int width_2d;
+ /* Canvas Texture API */
- struct BufferSlice3D {
- Size2i size;
- uint32_t offset = 0;
- uint32_t buffer_size = 0;
+ class CanvasTexture {
+ public:
+ RID diffuse;
+ RID normal_map;
+ RID specular;
+ Color specular_color = Color(1, 1, 1, 1);
+ float shininess = 1.0;
+
+ RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
+ RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
+ RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+
+ Size2i size_cache = Size2i(1, 1);
+ bool use_normal_cache = false;
+ bool use_specular_cache = false;
+ bool cleared_cache = true;
+
+ void clear_sets();
+ ~CanvasTexture();
};
- Vector<BufferSlice3D> buffer_slices_3d;
- uint32_t buffer_size_3d = 0;
-
- bool is_render_target;
- bool is_proxy;
-
- Ref<Image> image_cache_2d;
- String path;
-
- RID proxy_to;
- Vector<RID> proxies;
-
- HashSet<RID> lightmap_users;
- RS::TextureDetectCallback detect_3d_callback = nullptr;
- void *detect_3d_callback_ud = nullptr;
-
- RS::TextureDetectCallback detect_normal_callback = nullptr;
- void *detect_normal_callback_ud = nullptr;
-
- RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
- void *detect_roughness_callback_ud = nullptr;
-
- CanvasTexture *canvas_texture = nullptr;
-
- void cleanup();
-};
+ RID_Owner<CanvasTexture, true> canvas_texture_owner;
-struct DecalAtlas {
- struct Texture {
- int panorama_to_dp_users;
- int users;
- Rect2 uv_rect;
- };
-
- struct SortItem {
- RID texture;
- Size2i pixel_size;
- Size2i size;
- Point2i pos;
-
- bool operator<(const SortItem &p_item) const {
- //sort larger to smaller
- if (size.height == p_item.size.height) {
- return size.width > p_item.size.width;
- } else {
- return size.height > p_item.size.height;
- }
- }
- };
+ /* Texture API */
- HashMap<RID, Texture> textures;
- bool dirty = true;
- int mipmaps = 5;
+ class Texture {
+ public:
+ TextureType type;
+ RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
- RID texture;
- RID texture_srgb;
- struct MipMap {
- RID fb;
- RID texture;
- Size2i size;
- };
- Vector<MipMap> texture_mipmaps;
+ RenderingDevice::TextureType rd_type;
+ RID rd_texture;
+ RID rd_texture_srgb;
+ RenderingDevice::DataFormat rd_format;
+ RenderingDevice::DataFormat rd_format_srgb;
- Size2i size;
-};
+ RD::TextureView rd_view;
-struct Decal {
- Vector3 extents = Vector3(1, 1, 1);
- RID textures[RS::DECAL_TEXTURE_MAX];
- float emission_energy = 1.0;
- float albedo_mix = 1.0;
- Color modulate = Color(1, 1, 1, 1);
- uint32_t cull_mask = (1 << 20) - 1;
- float upper_fade = 0.3;
- float lower_fade = 0.3;
- bool distance_fade = false;
- float distance_fade_begin = 10;
- float distance_fade_length = 1;
- float normal_fade = 0.0;
-
- RendererStorage::Dependency dependency;
-};
+ Image::Format format;
+ Image::Format validated_format;
-struct RenderTarget {
- Size2i size;
- uint32_t view_count;
- RID framebuffer;
- RID color;
+ int width;
+ int height;
+ int depth;
+ int layers;
+ int mipmaps;
- //used for retrieving from CPU
- RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
- RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
- Image::Format image_format = Image::FORMAT_L8;
+ int height_2d;
+ int width_2d;
- bool is_transparent = false;
+ struct BufferSlice3D {
+ Size2i size;
+ uint32_t offset = 0;
+ uint32_t buffer_size = 0;
+ };
+ Vector<BufferSlice3D> buffer_slices_3d;
+ uint32_t buffer_size_3d = 0;
- bool sdf_enabled = false;
+ bool is_render_target;
+ bool is_proxy;
- RID backbuffer; //used for effects
- RID backbuffer_fb;
- RID backbuffer_mipmap0;
+ Ref<Image> image_cache_2d;
+ String path;
- Vector<RID> backbuffer_mipmaps;
+ RID proxy_to;
+ Vector<RID> proxies;
- RID framebuffer_uniform_set;
- RID backbuffer_uniform_set;
+ HashSet<RID> lightmap_users;
- RID sdf_buffer_write;
- RID sdf_buffer_write_fb;
- RID sdf_buffer_process[2];
- RID sdf_buffer_read;
- RID sdf_buffer_process_uniform_sets[2];
- RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
- RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
- Size2i process_size;
+ RS::TextureDetectCallback detect_3d_callback = nullptr;
+ void *detect_3d_callback_ud = nullptr;
- //texture generated for this owner (nor RD).
- RID texture;
- bool was_used;
+ RS::TextureDetectCallback detect_normal_callback = nullptr;
+ void *detect_normal_callback_ud = nullptr;
- //clear request
- bool clear_requested;
- Color clear_color;
-};
+ RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
+ void *detect_roughness_callback_ud = nullptr;
-struct RenderTargetSDF {
- enum {
- SHADER_LOAD,
- SHADER_LOAD_SHRINK,
- SHADER_PROCESS,
- SHADER_PROCESS_OPTIMIZED,
- SHADER_STORE,
- SHADER_STORE_SHRINK,
- SHADER_MAX
- };
+ CanvasTexture *canvas_texture = nullptr;
- struct PushConstant {
- int32_t size[2];
- int32_t stride;
- int32_t shift;
- int32_t base_size[2];
- int32_t pad[2];
+ void cleanup();
};
- CanvasSdfShaderRD shader;
- RID shader_version;
- RID pipelines[SHADER_MAX];
-};
-
-class TextureStorage : public RendererTextureStorage {
-private:
- static TextureStorage *singleton;
-
- /* Canvas Texture API */
-
- RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner;
-
- /* Texture API */
-
//textures can be created from threads, so this RID_Owner is thread safe
mutable RID_Owner<Texture, true> texture_owner;
+ Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
struct TextureToRDFormat {
RD::DataFormat format;
@@ -297,13 +188,115 @@ private:
/* DECAL API */
- DecalAtlas decal_atlas;
+ struct DecalAtlas {
+ struct Texture {
+ int panorama_to_dp_users;
+ int users;
+ Rect2 uv_rect;
+ };
+
+ struct SortItem {
+ RID texture;
+ Size2i pixel_size;
+ Size2i size;
+ Point2i pos;
+
+ bool operator<(const SortItem &p_item) const {
+ //sort larger to smaller
+ if (size.height == p_item.size.height) {
+ return size.width > p_item.size.width;
+ } else {
+ return size.height > p_item.size.height;
+ }
+ }
+ };
+
+ HashMap<RID, Texture> textures;
+ bool dirty = true;
+ int mipmaps = 5;
+
+ RID texture;
+ RID texture_srgb;
+ struct MipMap {
+ RID fb;
+ RID texture;
+ Size2i size;
+ };
+ Vector<MipMap> texture_mipmaps;
+
+ Size2i size;
+ } decal_atlas;
+
+ struct Decal {
+ Vector3 extents = Vector3(1, 1, 1);
+ RID textures[RS::DECAL_TEXTURE_MAX];
+ float emission_energy = 1.0;
+ float albedo_mix = 1.0;
+ Color modulate = Color(1, 1, 1, 1);
+ uint32_t cull_mask = (1 << 20) - 1;
+ float upper_fade = 0.3;
+ float lower_fade = 0.3;
+ bool distance_fade = false;
+ float distance_fade_begin = 40.0;
+ float distance_fade_length = 10.0;
+ float normal_fade = 0.0;
+
+ Dependency dependency;
+ };
mutable RID_Owner<Decal, true> decal_owner;
+ Decal *get_decal(RID p_rid) const { return decal_owner.get_or_null(p_rid); };
/* RENDER TARGET API */
+ struct RenderTarget {
+ Size2i size;
+ uint32_t view_count;
+ RID framebuffer;
+ RID color;
+
+ //used for retrieving from CPU
+ RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ Image::Format image_format = Image::FORMAT_L8;
+
+ bool is_transparent = false;
+
+ bool sdf_enabled = false;
+
+ RID backbuffer; //used for effects
+ RID backbuffer_fb;
+ RID backbuffer_mipmap0;
+
+ Vector<RID> backbuffer_mipmaps;
+
+ RID framebuffer_uniform_set;
+ RID backbuffer_uniform_set;
+
+ RID sdf_buffer_write;
+ RID sdf_buffer_write_fb;
+ RID sdf_buffer_process[2];
+ RID sdf_buffer_read;
+ RID sdf_buffer_process_uniform_sets[2];
+ RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
+ RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
+ Size2i process_size;
+
+ // VRS
+ RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
+ RID vrs_texture;
+
+ //texture generated for this owner (nor RD).
+ RID texture;
+ bool was_used;
+
+ //clear request
+ bool clear_requested;
+ Color clear_color;
+ };
+
mutable RID_Owner<RenderTarget> render_target_owner;
+ RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); };
void _clear_render_target(RenderTarget *rt);
void _update_render_target(RenderTarget *rt);
@@ -312,13 +305,33 @@ private:
void _render_target_clear_sdf(RenderTarget *rt);
Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
- RenderTargetSDF rt_sdf;
+ struct RenderTargetSDF {
+ enum {
+ SHADER_LOAD,
+ SHADER_LOAD_SHRINK,
+ SHADER_PROCESS,
+ SHADER_PROCESS_OPTIMIZED,
+ SHADER_STORE,
+ SHADER_STORE_SHRINK,
+ SHADER_MAX
+ };
+
+ struct PushConstant {
+ int32_t size[2];
+ int32_t stride;
+ int32_t shift;
+ int32_t base_size[2];
+ int32_t pad[2];
+ };
+
+ CanvasSdfShaderRD shader;
+ RID shader_version;
+ RID pipelines[SHADER_MAX];
+ } rt_sdf;
public:
static TextureStorage *get_singleton();
- RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
-
_FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
return default_rd_textures[p_texture];
}
@@ -328,7 +341,6 @@ public:
/* Canvas Texture API */
- CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
virtual RID canvas_texture_allocate() override;
@@ -345,8 +357,7 @@ public:
/* Texture API */
- Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
- bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
+ bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); };
virtual bool can_create_resources_async() const override;
@@ -388,12 +399,29 @@ public:
virtual Size2 texture_size_with_proxy(RID p_proxy) override;
//internal usage
+ _FORCE_INLINE_ TextureType texture_get_type(RID p_texture) {
+ RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
+ if (tex == nullptr) {
+ return TYPE_2D;
+ }
+
+ return tex->type;
+ }
+
+ _FORCE_INLINE_ int texture_get_layers(RID p_texture) {
+ RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
+ if (tex == nullptr) {
+ return 1;
+ }
+
+ return tex->layers;
+ }
_FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
if (p_texture.is_null()) {
return RID();
}
- RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+ RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
if (!tex) {
return RID();
@@ -405,7 +433,7 @@ public:
if (p_texture.is_null()) {
return Size2i();
}
- RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+ RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
if (!tex) {
return Size2i();
@@ -417,8 +445,7 @@ public:
void update_decal_atlas();
- Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); };
- bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); };
+ bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); };
RID decal_atlas_get_texture() const;
RID decal_atlas_get_texture_srgb() const;
@@ -512,11 +539,11 @@ public:
}
virtual AABB decal_get_aabb(RID p_decal) const override;
+ Dependency *decal_get_dependency(RID p_decal);
/* RENDER TARGET API */
- RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); };
- bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); };
+ bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); };
virtual RID render_target_create() override;
virtual void render_target_free(RID p_rid) override;
@@ -549,6 +576,12 @@ public:
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
bool render_target_is_sdf_enabled(RID p_render_target) const;
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override;
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override;
+
+ RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const;
+ RID render_target_get_vrs_texture(RID p_render_target) const;
+
Size2 render_target_get_size(RID p_render_target);
RID render_target_get_rd_framebuffer(RID p_render_target);
RID render_target_get_rd_texture(RID p_render_target);
@@ -564,4 +597,4 @@ public:
} // namespace RendererRD
-#endif // !_TEXTURE_STORAGE_RD_H
+#endif // TEXTURE_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
index 8c55ff1d0a..ae1f22be3b 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);
-}
-
-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);
-
- fog_volume->extents = p_extents;
- 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_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;
-}
+using namespace RendererRD;
-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());
+Utilities *Utilities::singleton = nullptr;
- return fog_volume->material;
+Utilities::Utilities() {
+ singleton = this;
}
-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;
-}
-
-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;
+Utilities::~Utilities() {
+ singleton = nullptr;
}
-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);
+/* INSTANCES */
- 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,189 @@ 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)) {
+ Dependency *dependency = MeshStorage::get_singleton()->mesh_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) {
+ Dependency *dependency = MeshStorage::get_singleton()->multimesh_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+
+ RID mesh = MeshStorage::get_singleton()->multimesh_get_mesh(p_base);
+ if (mesh.is_valid()) {
+ base_update_dependency(mesh, p_instance);
+ }
+ } else if (LightStorage::get_singleton()->owns_reflection_probe(p_base)) {
+ Dependency *dependency = LightStorage::get_singleton()->reflection_probe_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (TextureStorage::get_singleton()->owns_decal(p_base)) {
+ Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base);
+ p_instance->update_dependency(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)) {
+ Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (LightStorage::get_singleton()->owns_light(p_base)) {
+ Dependency *dependency = LightStorage::get_singleton()->light_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (ParticlesStorage::get_singleton()->owns_particles(p_base)) {
+ Dependency *dependency = ParticlesStorage::get_singleton()->particles_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {
+ Dependency *dependency = ParticlesStorage::get_singleton()->particles_collision_get_dependency(p_base);
+ p_instance->update_dependency(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);
+ }
}
-EffectsRD *RendererStorageRD::get_effects() {
- ERR_FAIL_NULL_V_MSG(effects, nullptr, "Effects haven't been initialised yet.");
- return effects;
+/* 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;
+}
+
+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_deferredp(nullptr, 0);
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->enter_callback.callp(nullptr, 0, r, ce);
+ }
+ }
+ } else {
+ if (!vn->exit_callback.is_null()) {
+ if (p_deferred) {
+ vn->exit_callback.call_deferredp(nullptr, 0);
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->exit_callback.callp(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_shader_uniforms(); //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 !defined(ANDROID_ENABLED) && !defined(IPHONE_ENABLED)
+ // Some Android devices report support for S3TC but we don't expect that and don't export the textures.
+ // This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs).
+ // For good measure we do the same hack for iOS, just in case.
+ 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;
+ }
+#endif
+
+ 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 +327,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..a80eb8510e
--- /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_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
index af22a48716..bca8b02178 100644
--- a/servers/rendering/renderer_rd/uniform_set_cache_rd.h
+++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef UNIFORM_SET_CACHE_H
-#define UNIFORM_SET_CACHE_H
+#ifndef UNIFORM_SET_CACHE_RD_H
+#define UNIFORM_SET_CACHE_RD_H
#include "core/templates/local_vector.h"
#include "core/templates/paged_allocator.h"
@@ -163,7 +163,7 @@ public:
const Cache *c = hash_table[table_idx];
while (c) {
- if (c->hash == h && c->set == p_set && c->shader == p_shader && _compare_args(0, c->uniforms, args...)) {
+ if (c->hash == h && c->set == p_set && c->shader == p_shader && sizeof...(Args) == c->uniforms.size() && _compare_args(0, c->uniforms, args...)) {
return c->cache;
}
c = c->next;
@@ -193,7 +193,7 @@ public:
const Cache *c = hash_table[table_idx];
while (c) {
- if (c->hash == h && c->set == p_set && c->shader == p_shader) {
+ if (c->hash == h && c->set == p_set && c->shader == p_shader && (uint32_t)p_uniforms.size() == c->uniforms.size()) {
bool all_ok = true;
for (int i = 0; i < p_uniforms.size(); i++) {
if (!_compare_uniform(p_uniforms[i], c->uniforms[i])) {
@@ -220,4 +220,4 @@ public:
~UniformSetCacheRD();
};
-#endif // UNIFORMSETCACHE_H
+#endif // UNIFORM_SET_CACHE_RD_H
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index b773ed61f4..ba6fb71e67 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERSCENE_H
-#define RENDERINGSERVERSCENE_H
+#ifndef RENDERER_SCENE_H
+#define RENDERER_SCENE_H
#include "servers/rendering_server.h"
#include "servers/xr/xr_interface.h"
@@ -100,10 +100,10 @@ public:
virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) = 0;
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0;
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
- virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0;
- virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
- virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0;
- virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const = 0;
+ virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0;
+ virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
+ virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const = 0;
+ virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const = 0;
virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0;
@@ -122,6 +122,7 @@ public:
virtual RID environment_allocate() = 0;
virtual void environment_initialize(RID p_rid) = 0;
+ // Background
virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0;
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
@@ -131,41 +132,152 @@ public:
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0;
- virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0;
- virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
- virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
+ virtual RS::EnvironmentBG environment_get_background(RID p_Env) const = 0;
+ virtual RID environment_get_sky(RID p_env) const = 0;
+ virtual float environment_get_sky_custom_fov(RID p_env) const = 0;
+ virtual Basis environment_get_sky_orientation(RID p_env) const = 0;
+ virtual Color environment_get_bg_color(RID p_env) const = 0;
+ virtual float environment_get_bg_energy(RID p_env) const = 0;
+ virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
+ virtual RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const = 0;
+ virtual Color environment_get_ambient_light(RID p_env) const = 0;
+ virtual float environment_get_ambient_light_energy(RID p_env) const = 0;
+ virtual float environment_get_ambient_sky_contribution(RID p_env) const = 0;
+ virtual RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const = 0;
+
+ // Tonemap
+ virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
+
+ virtual RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const = 0;
+ virtual float environment_get_exposure(RID p_env) const = 0;
+ virtual float environment_get_white(RID p_env) const = 0;
+ virtual bool environment_get_auto_exposure(RID p_env) const = 0;
+ virtual float environment_get_min_luminance(RID p_env) const = 0;
+ virtual float environment_get_max_luminance(RID p_env) const = 0;
+ virtual float environment_get_auto_exp_speed(RID p_env) const = 0;
+ virtual float environment_get_auto_exp_scale(RID p_env) const = 0;
+ virtual uint64_t environment_get_auto_exposure_version(RID p_env) const = 0;
+
+ // Fog
+ virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
+ virtual bool environment_get_fog_enabled(RID p_env) const = 0;
+ virtual Color environment_get_fog_light_color(RID p_env) const = 0;
+ virtual float environment_get_fog_light_energy(RID p_env) const = 0;
+ virtual float environment_get_fog_sun_scatter(RID p_env) const = 0;
+ virtual float environment_get_fog_density(RID p_env) const = 0;
+ virtual float environment_get_fog_height(RID p_env) const = 0;
+ virtual float environment_get_fog_height_density(RID p_env) const = 0;
+ virtual float environment_get_fog_aerial_perspective(RID p_env) const = 0;
+
+ // Volumetric Fog
virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
+ virtual bool environment_get_volumetric_fog_enabled(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_density(RID p_env) const = 0;
+ virtual Color environment_get_volumetric_fog_scattering(RID p_env) const = 0;
+ virtual Color environment_get_volumetric_fog_emission(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_emission_energy(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_anisotropy(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_length(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_detail_spread(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_gi_inject(RID p_env) const = 0;
+ virtual bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_ambient_inject(RID p_env) const = 0;
+
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
+ // Glow
+
+ virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0;
+
+ virtual bool environment_get_glow_enabled(RID p_env) const = 0;
+ virtual Vector<float> environment_get_glow_levels(RID p_env) const = 0;
+ virtual float environment_get_glow_intensity(RID p_env) const = 0;
+ virtual float environment_get_glow_strength(RID p_env) const = 0;
+ virtual float environment_get_glow_bloom(RID p_env) const = 0;
+ virtual float environment_get_glow_mix(RID p_env) const = 0;
+ virtual RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const = 0;
+ virtual float environment_get_glow_hdr_bleed_threshold(RID p_env) const = 0;
+ virtual float environment_get_glow_hdr_luminance_cap(RID p_env) const = 0;
+ virtual float environment_get_glow_hdr_bleed_scale(RID p_env) const = 0;
+ virtual float environment_get_glow_map_strength(RID p_env) const = 0;
+ virtual RID environment_get_glow_map(RID p_env) const = 0;
+
+ virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
+ virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
+
+ // SSR
+
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0;
+
+ virtual bool environment_get_ssr_enabled(RID p_env) const = 0;
+ virtual int environment_get_ssr_max_steps(RID p_env) const = 0;
+ virtual float environment_get_ssr_fade_in(RID p_env) const = 0;
+ virtual float environment_get_ssr_fade_out(RID p_env) const = 0;
+ virtual float environment_get_ssr_depth_tolerance(RID p_env) const = 0;
+
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
+ // SSAO
virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0;
+
+ virtual bool environment_get_ssao_enabled(RID p_env) const = 0;
+ virtual float environment_get_ssao_radius(RID p_env) const = 0;
+ virtual float environment_get_ssao_intensity(RID p_env) const = 0;
+ virtual float environment_get_ssao_power(RID p_env) const = 0;
+ virtual float environment_get_ssao_detail(RID p_env) const = 0;
+ virtual float environment_get_ssao_horizon(RID p_env) const = 0;
+ virtual float environment_get_ssao_sharpness(RID p_env) const = 0;
+ virtual float environment_get_ssao_direct_light_affect(RID p_env) const = 0;
+ virtual float environment_get_ssao_ao_channel_affect(RID p_env) const = 0;
+
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
+ // SSIL
+
virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0;
+
+ virtual bool environment_get_ssil_enabled(RID p_env) const = 0;
+ virtual float environment_get_ssil_radius(RID p_env) const = 0;
+ virtual float environment_get_ssil_intensity(RID p_env) const = 0;
+ virtual float environment_get_ssil_sharpness(RID p_env) const = 0;
+ virtual float environment_get_ssil_normal_rejection(RID p_env) const = 0;
+
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
+ // SDFGI
virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ virtual bool environment_get_sdfgi_enabled(RID p_env) const = 0;
+ virtual int environment_get_sdfgi_cascades(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_min_cell_size(RID p_env) const = 0;
+ virtual bool environment_get_sdfgi_use_occlusion(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_bounce_feedback(RID p_env) const = 0;
+ virtual bool environment_get_sdfgi_read_sky_light(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_energy(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_normal_bias(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_probe_bias(RID p_env) const = 0;
+ virtual RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const = 0;
+
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) = 0;
- virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
-
+ // Adjustment
virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0;
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
+ virtual bool environment_get_adjustments_enabled(RID p_env) const = 0;
+ virtual float environment_get_adjustments_brightness(RID p_env) const = 0;
+ virtual float environment_get_adjustments_contrast(RID p_env) const = 0;
+ virtual float environment_get_adjustments_saturation(RID p_env) const = 0;
+ virtual bool environment_get_use_1d_color_correction(RID p_env) const = 0;
+ virtual RID environment_get_color_correction(RID p_env) const = 0;
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0;
- virtual RS::EnvironmentBG environment_get_background(RID p_Env) const = 0;
- virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
-
virtual bool is_environment(RID p_environment) const = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
@@ -183,8 +295,8 @@ public:
virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
- virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
- virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
+ virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0;
+ virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0;
virtual RID shadow_atlas_create() = 0;
virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_use_16_bits = true) = 0;
@@ -194,7 +306,7 @@ public:
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
@@ -226,4 +338,4 @@ public:
virtual ~RendererScene();
};
-#endif // RENDERINGSERVERSCENE_H
+#endif // RENDERER_SCENE_H
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 325907ee85..0b20bb372a 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -470,12 +470,12 @@ 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_instance_free(p_instance->mesh_instance);
p_instance->mesh_instance = RID();
}
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
- scene_render->geometry_instance_set_mesh_instance(geom->geometry_instance, p_instance->mesh_instance);
+ geom->geometry_instance->set_mesh_instance(p_instance->mesh_instance);
if (p_instance->scenario && p_instance->array_index >= 0) {
InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
@@ -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)) {
@@ -637,20 +637,20 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base_data = geom;
geom->geometry_instance = scene_render->geometry_instance_create(p_base);
- scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton);
- scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override);
- scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, instance->material_overlay);
- scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials);
- scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb);
- scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask);
- scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, instance->lod_bias);
- scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, instance->baked_light);
- scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi);
- scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
- scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
- scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency);
+ geom->geometry_instance->set_skeleton(instance->skeleton);
+ geom->geometry_instance->set_material_override(instance->material_override);
+ geom->geometry_instance->set_material_overlay(instance->material_overlay);
+ geom->geometry_instance->set_surface_materials(instance->materials);
+ geom->geometry_instance->set_transform(instance->transform, instance->aabb, instance->transformed_aabb);
+ geom->geometry_instance->set_layer_mask(instance->layer_mask);
+ geom->geometry_instance->set_lod_bias(instance->lod_bias);
+ geom->geometry_instance->set_transparency(instance->transparency);
+ geom->geometry_instance->set_use_baked_light(instance->baked_light);
+ geom->geometry_instance->set_use_dynamic_gi(instance->dynamic_gi);
+ geom->geometry_instance->set_use_lightmap(RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
+ geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
if (instance->lightmap_sh.size() == 9) {
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr());
+ geom->geometry_instance->set_lightmap_capture(instance->lightmap_sh.ptr());
}
for (Instance *E : instance->visibility_dependencies) {
@@ -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);
@@ -836,7 +836,7 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, p_mask);
+ geom->geometry_instance->set_layer_mask(p_mask);
}
}
@@ -848,7 +848,7 @@ void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency);
+ geom->geometry_instance->set_transparency(p_transparency);
}
}
@@ -1009,7 +1009,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
_instance_update_mesh_instance(instance);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_skeleton(geom->geometry_instance, p_skeleton);
+ geom->geometry_instance->set_skeleton(p_skeleton);
}
}
@@ -1129,7 +1129,7 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, p_enabled);
+ geom->geometry_instance->set_use_baked_light(p_enabled);
}
} break;
@@ -1149,7 +1149,7 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, p_enabled);
+ geom->geometry_instance->set_use_dynamic_gi(p_enabled);
}
} break;
@@ -1207,7 +1207,7 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
+ geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
}
_instance_queue_update(instance, false, true);
@@ -1222,7 +1222,7 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_material_override(geom->geometry_instance, p_material);
+ geom->geometry_instance->set_material_override(p_material);
}
}
@@ -1235,7 +1235,7 @@ void RendererSceneCull::instance_geometry_set_material_overlay(RID p_instance, R
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, p_material);
+ geom->geometry_instance->set_material_overlay(p_material);
}
}
@@ -1358,9 +1358,9 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
bool end_enabled = p_instance->visibility_range_end > 0.0f;
float end_min = p_instance->visibility_range_end - p_instance->visibility_range_end_margin;
float end_max = p_instance->visibility_range_end + p_instance->visibility_range_end_margin;
- scene_render->geometry_instance_set_fade_range(idata.instance_geometry, begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);
+ idata.instance_geometry->set_fade_range(begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);
} else {
- scene_render->geometry_instance_set_fade_range(idata.instance_geometry, false, 0.0f, 0.0f, false, 0.0f, 0.0f);
+ idata.instance_geometry->set_fade_range(false, 0.0f, 0.0f, false, 0.0f, 0.0f);
}
}
@@ -1375,7 +1375,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
} else {
idata.parent_array_index = -1;
if (is_geometry_instance) {
- scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, 1.0f);
+ idata.instance_geometry->set_parent_fade_alpha(1.0f);
}
}
}
@@ -1407,7 +1407,7 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);
+ geom->geometry_instance->set_use_lightmap(lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);
}
}
@@ -1419,66 +1419,66 @@ void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_l
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, p_lod_bias);
+ geom->geometry_instance->set_lod_bias(p_lod_bias);
}
}
-void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
+void RendererSceneCull::instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
- HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_parameters.find(p_parameter);
+ HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_uniforms.find(p_parameter);
if (!E) {
Instance::InstanceShaderParameter isp;
isp.index = -1;
isp.info = PropertyInfo();
isp.value = p_value;
- instance->instance_shader_parameters[p_parameter] = isp;
+ instance->instance_shader_uniforms[p_parameter] = isp;
} else {
E->value.value = p_value;
- if (E->value.index >= 0 && instance->instance_allocated_shader_parameters) {
+ if (E->value.index >= 0 && instance->instance_allocated_shader_uniforms) {
//update directly
- RSG::material_storage->global_variables_instance_update(p_instance, E->value.index, p_value);
+ RSG::material_storage->global_shader_uniforms_instance_update(p_instance, E->value.index, p_value);
}
}
}
-Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const {
+Variant RendererSceneCull::instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const {
const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!instance, Variant());
- if (instance->instance_shader_parameters.has(p_parameter)) {
- return instance->instance_shader_parameters[p_parameter].value;
+ if (instance->instance_shader_uniforms.has(p_parameter)) {
+ return instance->instance_shader_uniforms[p_parameter].value;
}
return Variant();
}
-Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const {
+Variant RendererSceneCull::instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const {
const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!instance, Variant());
- if (instance->instance_shader_parameters.has(p_parameter)) {
- return instance->instance_shader_parameters[p_parameter].default_value;
+ if (instance->instance_shader_uniforms.has(p_parameter)) {
+ return instance->instance_shader_uniforms[p_parameter].default_value;
}
return Variant();
}
-void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const {
+void RendererSceneCull::instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const {
const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
const_cast<RendererSceneCull *>(this)->update_dirty_instances();
Vector<StringName> names;
- for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : instance->instance_shader_parameters) {
+ for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : instance->instance_shader_uniforms) {
names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
for (int i = 0; i < names.size(); i++) {
- PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info;
+ PropertyInfo pinfo = instance->instance_shader_uniforms[names[i]].info;
p_parameters->push_back(pinfo);
}
}
@@ -1587,11 +1587,11 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
if (!p_instance->lightmap_sh.is_empty()) {
p_instance->lightmap_sh.clear(); //don't need SH
p_instance->lightmap_target_sh.clear(); //don't need SH
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, nullptr);
+ geom->geometry_instance->set_lightmap_capture(nullptr);
}
}
- scene_render->geometry_instance_set_transform(geom->geometry_instance, p_instance->transform, p_instance->aabb, p_instance->transformed_aabb);
+ geom->geometry_instance->set_transform(p_instance->transform, p_instance->aabb, p_instance->transformed_aabb);
}
// note: we had to remove is equal approx check here, it meant that det == 0.000004 won't work, which is the case for some of our scenes.
@@ -1818,10 +1818,10 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
// Clear these now because the InstanceData containing the dirty flags is gone
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
- scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0);
+ geom->geometry_instance->pair_light_instances(nullptr, 0);
+ geom->geometry_instance->pair_reflection_probe_instances(nullptr, 0);
+ geom->geometry_instance->pair_decal_instances(nullptr, 0);
+ geom->geometry_instance->pair_voxel_gi_instances(nullptr, 0);
}
for (Instance *E : p_instance->visibility_dependencies) {
@@ -1829,7 +1829,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
if (dep_instance->array_index != -1) {
dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
if ((1 << dep_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
- scene_render->geometry_instance_set_parent_fade_alpha(dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry, 1.0f);
+ dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry->set_parent_fade_alpha(1.0f);
}
}
}
@@ -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);
@@ -1990,10 +1990,10 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
}
}
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, p_instance->lightmap_sh.ptr());
+ geom->geometry_instance->set_lightmap_capture(p_instance->lightmap_sh.ptr());
}
-void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
+void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform3D light_transform = p_instance->transform;
@@ -2045,7 +2045,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));
// setup a camera matrix for that range!
- CameraMatrix camera_matrix;
+ Projection camera_matrix;
real_t aspect = p_cam_projection.get_aspect();
@@ -2185,7 +2185,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
z_max = z_vec.dot(center) + radius + pancake_size;
{
- CameraMatrix ortho_camera;
+ Projection ortho_camera;
real_t half_x = (x_max_cam - x_min_cam) * 0.5;
real_t half_y = (y_max_cam - y_min_cam) * 0.5;
@@ -2210,7 +2210,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
}
}
-bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) {
+bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform3D light_transform = p_instance->transform;
@@ -2283,7 +2283,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::mesh_storage->update_mesh_instances();
- scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
+ scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, i, 0);
shadow_data.light = light->instance;
shadow_data.pass = i;
}
@@ -2294,7 +2294,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, radius * 0.005f, radius);
for (int i = 0; i < 6; i++) {
@@ -2366,7 +2366,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
//restore the regular DP matrix
- //scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0);
+ //scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, 0, 0);
}
} break;
@@ -2380,7 +2380,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
real_t angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(angle * 2.0, 1.0, 0.005f * radius, radius);
Vector<Plane> planes = cm.get_projection_planes(light_transform);
@@ -2450,7 +2450,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
if (p_xr_interface.is_null()) {
// Normal camera
Transform3D transform = camera->transform;
- CameraMatrix projection;
+ Projection projection;
bool vaspect = camera->vaspect;
bool is_orthogonal = false;
@@ -2489,7 +2489,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
// Setup our camera for our XR interface.
// We can support multiple views here each with their own camera
Transform3D transforms[RendererSceneRender::MAX_RENDER_VIEWS];
- CameraMatrix projections[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection projections[RendererSceneRender::MAX_RENDER_VIEWS];
uint32_t view_count = p_xr_interface->get_view_count();
ERR_FAIL_COND_MSG(view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported");
@@ -2518,14 +2518,14 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
RENDER_TIMESTAMP("Update Occlusion Buffer")
// For now just cull on the first camera
- RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal, RendererThreadPool::singleton->thread_work_pool);
+ RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal);
_render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info);
#endif
}
void RendererSceneCull::_visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data) {
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t bin_from = p_thread * cull_data->cull_count / total_threads;
uint32_t bin_to = (p_thread + 1 == total_threads) ? cull_data->cull_count : ((p_thread + 1) * cull_data->cull_count / total_threads);
@@ -2622,7 +2622,7 @@ bool RendererSceneCull::_visibility_parent_check(const CullData &p_cull_data, co
void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) {
uint32_t cull_total = cull_data->scenario->instance_data.size();
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t cull_from = p_thread * cull_total / total_threads;
uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads);
@@ -2742,7 +2742,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
const int32_t &parent_idx = cull_data.scenario->instance_data[idata.parent_array_index].visibility_index;
fade = cull_data.scenario->instance_visibility[parent_idx].children_fade_alpha;
}
- scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, fade);
+ idata.instance_geometry->set_parent_fade_alpha(fade);
}
if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
@@ -2757,14 +2757,14 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
- scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ geom->geometry_instance->pair_light_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
}
if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- scene_render->geometry_instance_set_softshadow_projector_pairing(geom->geometry_instance, geom->softshadow_count > 0, geom->projector_count > 0);
+ geom->geometry_instance->set_softshadow_projector_pairing(geom->softshadow_count > 0, geom->projector_count > 0);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY);
}
@@ -2781,7 +2781,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
- scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ geom->geometry_instance->pair_reflection_probe_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
}
@@ -2797,7 +2797,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
break;
}
}
- scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ geom->geometry_instance->pair_decal_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
}
@@ -2813,7 +2813,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
}
@@ -2824,7 +2824,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
for (uint32_t j = 0; j < 9; j++) {
sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
}
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh);
+ geom->geometry_instance->set_lightmap_capture(sh);
idata.instance->last_frame_pass = frame_number;
}
@@ -2919,7 +2919,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
if (visibility_cull_data.cull_count > thread_cull_threshold) {
- RendererThreadPool::singleton->thread_work_pool.do_work(RendererThreadPool::singleton->thread_work_pool.get_thread_count(), this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data, WorkerThreadPool::get_singleton()->get_thread_count(), -1, true, SNAME("VisibilityCullInstances"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
} else {
_visibility_cull(visibility_cull_data, visibility_cull_data.cull_offset, visibility_cull_data.cull_offset + visibility_cull_data.cull_count);
}
@@ -3024,7 +3025,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
scene_cull_result_threads[i].clear();
}
- RendererThreadPool::singleton->thread_work_pool.do_work(scene_cull_result_threads.size(), this, &RendererSceneCull::_scene_cull_threaded, &cull_data);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_scene_cull_threaded, &cull_data, scene_cull_result_threads.size(), -1, true, SNAME("RenderCullInstances"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
scene_cull_result.append_from(scene_cull_result_threads[i]);
@@ -3243,7 +3245,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
render_sdfgi_data[i].instances.clear();
}
- // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
+ // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
}
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
@@ -3280,9 +3282,9 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
RENDER_TIMESTAMP("Render Empty 3D Scene");
RendererSceneRender::CameraData camera_data;
- camera_data.set_camera(Transform3D(), CameraMatrix(), true, false);
+ camera_data.set_camera(Transform3D(), Projection(), true, false);
- scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+ scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -3329,7 +3331,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
max_distance = MAX(max_distance, distance);
//render cubemap side
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, 0.01, max_distance);
Transform3D local_view;
@@ -3586,7 +3588,7 @@ void RendererSceneCull::render_probes() {
}
}
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);
ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
}
@@ -3640,9 +3642,9 @@ void RendererSceneCull::render_particle_colliders() {
}
}
-void RendererSceneCull::_update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
+void RendererSceneCull::_update_instance_shader_uniforms_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
List<RendererMaterialStorage::InstanceShaderParam> plist;
- RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist);
+ RSG::material_storage->material_get_instance_shader_uniforms(p_material, &plist);
for (const RendererMaterialStorage::InstanceShaderParam &E : plist) {
StringName name = E.info.name;
if (isparams.has(name)) {
@@ -3677,7 +3679,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()) {
@@ -3722,7 +3724,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
can_cast_shadows = false;
}
is_animated = RSG::material_storage->material_is_animated(p_instance->material_override);
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, p_instance->material_override);
} else {
if (p_instance->base_type == RS::INSTANCE_MESH) {
RID mesh = p_instance->base;
@@ -3744,7 +3746,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat);
RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
@@ -3775,7 +3777,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat);
RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
@@ -3785,7 +3787,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;
@@ -3813,7 +3815,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat);
RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
@@ -3829,7 +3831,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if (p_instance->material_overlay.is_valid()) {
can_cast_shadows = can_cast_shadows || RSG::material_storage->material_casts_shadows(p_instance->material_overlay);
is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay);
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, p_instance->material_overlay);
}
if (can_cast_shadows != geom->can_cast_shadows) {
@@ -3843,23 +3845,23 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
geom->material_is_animated = is_animated;
- p_instance->instance_shader_parameters = isparams;
+ p_instance->instance_shader_uniforms = isparams;
- if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) {
- p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
- if (p_instance->instance_allocated_shader_parameters) {
- p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_variables_instance_allocate(p_instance->self);
- scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset);
+ if (p_instance->instance_allocated_shader_uniforms != (p_instance->instance_shader_uniforms.size() > 0)) {
+ p_instance->instance_allocated_shader_uniforms = (p_instance->instance_shader_uniforms.size() > 0);
+ if (p_instance->instance_allocated_shader_uniforms) {
+ p_instance->instance_allocated_shader_uniforms_offset = RSG::material_storage->global_shader_uniforms_instance_allocate(p_instance->self);
+ geom->geometry_instance->set_instance_shader_uniforms_offset(p_instance->instance_allocated_shader_uniforms_offset);
- for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) {
+ for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_uniforms) {
if (E.value.value.get_type() != Variant::NIL) {
- RSG::material_storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
+ RSG::material_storage->global_shader_uniforms_instance_update(p_instance->self, E.value.index, E.value.value);
}
}
} else {
- RSG::material_storage->global_variables_instance_free(p_instance->self);
- p_instance->instance_allocated_shader_parameters_offset = -1;
- scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1);
+ RSG::material_storage->global_shader_uniforms_instance_free(p_instance->self);
+ p_instance->instance_allocated_shader_uniforms_offset = -1;
+ geom->geometry_instance->set_instance_shader_uniforms_offset(-1);
}
}
}
@@ -3872,7 +3874,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
- scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, p_instance->materials);
+ geom->geometry_instance->set_surface_materials(p_instance->materials);
}
}
@@ -3885,7 +3887,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());
@@ -3951,9 +3953,9 @@ bool RendererSceneCull::free(RID p_rid) {
instance_geometry_set_material_overlay(p_rid, RID());
instance_attach_skeleton(p_rid, RID());
- if (instance->instance_allocated_shader_parameters) {
+ if (instance->instance_allocated_shader_uniforms) {
//free the used shader parameters
- RSG::material_storage->global_variables_instance_free(instance->self);
+ RSG::material_storage->global_shader_uniforms_instance_free(instance->self);
}
update_dirty_instances(); //in case something changed this
@@ -3978,12 +3980,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);
}
}
@@ -4030,14 +4032,14 @@ RendererSceneCull::RendererSceneCull() {
}
scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
- scene_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ scene_cull_result_threads.resize(WorkerThreadPool::get_singleton()->get_thread_count());
for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
scene_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
}
indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");
thread_cull_threshold = GLOBAL_GET("rendering/limits/spatial_indexer/threaded_cull_minimum_instances");
- thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)RendererThreadPool::singleton->thread_work_pool.get_thread_count()); //make sure there is at least one thread per CPU
+ thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)WorkerThreadPool::get_singleton()->get_thread_count()); //make sure there is at least one thread per CPU
taa_jitter_array.resize(TAA_JITTER_COUNT);
for (int i = 0; i < TAA_JITTER_COUNT; i++) {
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 4880221586..540fb0e27a 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_CULL_H
-#define RENDERING_SERVER_SCENE_CULL_H
+#ifndef RENDERER_SCENE_CULL_H
+#define RENDERER_SCENE_CULL_H
#include "core/math/dynamic_bvh.h"
#include "core/templates/bin_sorted_array.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 {
@@ -272,7 +272,7 @@ public:
RID base_rid;
union {
uint64_t instance_data_rid;
- RendererSceneRender::GeometryInstance *instance_geometry;
+ RenderGeometryInstance *instance_geometry;
InstanceVisibilityNotifierData *visibility_notifier = nullptr;
};
Instance *instance = nullptr;
@@ -426,9 +426,9 @@ public:
PropertyInfo info;
};
- HashMap<StringName, InstanceShaderParameter> instance_shader_parameters;
- bool instance_allocated_shader_parameters = false;
- int32_t instance_allocated_shader_parameters_offset = -1;
+ HashMap<StringName, InstanceShaderParameter> instance_shader_uniforms;
+ bool instance_allocated_shader_uniforms = false;
+ int32_t instance_allocated_shader_uniforms_offset = -1;
//
@@ -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) {
@@ -578,7 +578,7 @@ public:
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
struct InstanceGeometryData : public InstanceBaseData {
- RendererSceneRender::GeometryInstance *geometry_instance = nullptr;
+ RenderGeometryInstance *geometry_instance = nullptr;
HashSet<Instance *> lights;
bool can_cast_shadows;
bool material_is_animated;
@@ -782,14 +782,14 @@ public:
HashSet<Instance *> heightfield_particle_colliders_update_list;
PagedArrayPool<Instance *> instance_cull_page_pool;
- PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool;
+ PagedArrayPool<RenderGeometryInstance *> geometry_instance_cull_page_pool;
PagedArrayPool<RID> rid_cull_page_pool;
PagedArray<Instance *> instance_cull_result;
PagedArray<Instance *> instance_shadow_cull_result;
struct InstanceCullResult {
- PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances;
+ PagedArray<RenderGeometryInstance *> geometry_instances;
PagedArray<Instance *> lights;
PagedArray<RID> light_instances;
PagedArray<RID> lightmaps;
@@ -800,10 +800,10 @@ public:
PagedArray<RID> fog_volumes;
struct DirectionalShadow {
- PagedArray<RendererSceneRender::GeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES];
+ PagedArray<RenderGeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES];
} directional_shadows[RendererSceneRender::MAX_DIRECTIONAL_LIGHTS];
- PagedArray<RendererSceneRender::GeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
+ PagedArray<RenderGeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
PagedArray<RID> sdfgi_cascade_lights[SDFGI_MAX_CASCADES];
void clear() {
@@ -882,7 +882,7 @@ public:
}
}
- void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RendererSceneRender::GeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) {
+ void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RenderGeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) {
geometry_instances.set_page_pool(p_geometry_instance_pool);
light_instances.set_page_pool(p_rid_pool);
lights.set_page_pool(p_instance_pool);
@@ -967,12 +967,12 @@ public:
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
- void _update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material);
+ void _update_instance_shader_uniforms_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material);
- virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value);
- virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
- virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const;
- virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const;
+ virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value);
+ virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
+ virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const;
+ virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const;
_FORCE_INLINE_ void _update_instance(Instance *p_instance);
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
@@ -980,9 +980,9 @@ public:
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
void _unpair_instance(Instance *p_instance);
- void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
+ void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
- _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold);
+ _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold);
RID _render_get_environment(RID p_camera, RID p_scenario);
@@ -992,7 +992,7 @@ public:
struct Cascade {
Frustum frustum;
- CameraMatrix projection;
+ Projection projection;
Transform3D transform;
real_t zfar;
real_t split;
@@ -1045,7 +1045,7 @@ public:
uint32_t visible_layers;
Instance *render_reflection_probe = nullptr;
const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer;
- const CameraMatrix *camera_matrix;
+ const Projection *camera_matrix;
uint64_t visibility_viewport_mask;
};
@@ -1093,6 +1093,7 @@ public:
PASS1RC(bool, is_environment, RID)
+ // Background
PASS2(environment_set_background, RID, RS::EnvironmentBG)
PASS2(environment_set_sky, RID, RID)
PASS2(environment_set_sky_custom_fov, RID, float)
@@ -1102,36 +1103,146 @@ public:
PASS2(environment_set_canvas_max_layer, RID, int)
PASS6(environment_set_ambient_light, RID, const Color &, RS::EnvironmentAmbientSource, float, float, RS::EnvironmentReflectionSource)
+ PASS1RC(RS::EnvironmentBG, environment_get_background, RID)
+ PASS1RC(RID, environment_get_sky, RID)
+ PASS1RC(float, environment_get_sky_custom_fov, RID)
+ PASS1RC(Basis, environment_get_sky_orientation, RID)
+ PASS1RC(Color, environment_get_bg_color, RID)
+ PASS1RC(float, environment_get_bg_energy, RID)
+ PASS1RC(int, environment_get_canvas_max_layer, RID)
+ PASS1RC(RS::EnvironmentAmbientSource, environment_get_ambient_source, RID)
+ PASS1RC(Color, environment_get_ambient_light, RID)
+ PASS1RC(float, environment_get_ambient_light_energy, RID)
+ PASS1RC(float, environment_get_ambient_sky_contribution, RID)
+ PASS1RC(RS::EnvironmentReflectionSource, environment_get_reflection_source, RID)
+
+ // Tonemap
+ PASS9(environment_set_tonemap, RID, RS::EnvironmentToneMapper, float, float, bool, float, float, float, float)
+ PASS1RC(RS::EnvironmentToneMapper, environment_get_tone_mapper, RID)
+ PASS1RC(float, environment_get_exposure, RID)
+ PASS1RC(float, environment_get_white, RID)
+ PASS1RC(bool, environment_get_auto_exposure, RID)
+ PASS1RC(float, environment_get_min_luminance, RID)
+ PASS1RC(float, environment_get_max_luminance, RID)
+ PASS1RC(float, environment_get_auto_exp_speed, RID)
+ PASS1RC(float, environment_get_auto_exp_scale, RID)
+ PASS1RC(uint64_t, environment_get_auto_exposure_version, RID)
+
+ // Fog
+ PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
+
+ PASS1RC(bool, environment_get_fog_enabled, RID)
+ PASS1RC(Color, environment_get_fog_light_color, RID)
+ PASS1RC(float, environment_get_fog_light_energy, RID)
+ PASS1RC(float, environment_get_fog_sun_scatter, RID)
+ PASS1RC(float, environment_get_fog_density, RID)
+ PASS1RC(float, environment_get_fog_height, RID)
+ PASS1RC(float, environment_get_fog_height_density, RID)
+ PASS1RC(float, environment_get_fog_aerial_perspective, RID)
+
+ PASS2(environment_set_volumetric_fog_volume_size, int, int)
+ PASS1(environment_set_volumetric_fog_filter_active, bool)
+
+ // Volumentric Fog
+ PASS13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float)
+
+ PASS1RC(bool, environment_get_volumetric_fog_enabled, RID)
+ PASS1RC(float, environment_get_volumetric_fog_density, RID)
+ PASS1RC(Color, environment_get_volumetric_fog_scattering, RID)
+ PASS1RC(Color, environment_get_volumetric_fog_emission, RID)
+ PASS1RC(float, environment_get_volumetric_fog_emission_energy, RID)
+ PASS1RC(float, environment_get_volumetric_fog_anisotropy, RID)
+ PASS1RC(float, environment_get_volumetric_fog_length, RID)
+ PASS1RC(float, environment_get_volumetric_fog_detail_spread, RID)
+ PASS1RC(float, environment_get_volumetric_fog_gi_inject, RID)
+ PASS1RC(bool, environment_get_volumetric_fog_temporal_reprojection, RID)
+ PASS1RC(float, environment_get_volumetric_fog_temporal_reprojection_amount, RID)
+ PASS1RC(float, environment_get_volumetric_fog_ambient_inject, RID)
+
+ // Glow
+ PASS13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float, float, RID)
+
+ PASS1RC(bool, environment_get_glow_enabled, RID)
+ PASS1RC(Vector<float>, environment_get_glow_levels, RID)
+ PASS1RC(float, environment_get_glow_intensity, RID)
+ PASS1RC(float, environment_get_glow_strength, RID)
+ PASS1RC(float, environment_get_glow_bloom, RID)
+ PASS1RC(float, environment_get_glow_mix, RID)
+ PASS1RC(RS::EnvironmentGlowBlendMode, environment_get_glow_blend_mode, RID)
+ PASS1RC(float, environment_get_glow_hdr_bleed_threshold, RID)
+ PASS1RC(float, environment_get_glow_hdr_luminance_cap, RID)
+ PASS1RC(float, environment_get_glow_hdr_bleed_scale, RID)
+ PASS1RC(float, environment_get_glow_map_strength, RID)
+ PASS1RC(RID, environment_get_glow_map, RID)
+
+ PASS1(environment_glow_set_use_bicubic_upscale, bool)
+ PASS1(environment_glow_set_use_high_quality, bool)
+
+ // SSR
PASS6(environment_set_ssr, RID, bool, int, float, float, float)
+
+ PASS1RC(bool, environment_get_ssr_enabled, RID)
+ PASS1RC(int, environment_get_ssr_max_steps, RID)
+ PASS1RC(float, environment_get_ssr_fade_in, RID)
+ PASS1RC(float, environment_get_ssr_fade_out, RID)
+ PASS1RC(float, environment_get_ssr_depth_tolerance, RID)
+
PASS1(environment_set_ssr_roughness_quality, RS::EnvironmentSSRRoughnessQuality)
+ // SSAO
PASS10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
+
+ PASS1RC(bool, environment_get_ssao_enabled, RID)
+ PASS1RC(float, environment_get_ssao_radius, RID)
+ PASS1RC(float, environment_get_ssao_intensity, RID)
+ PASS1RC(float, environment_get_ssao_power, RID)
+ PASS1RC(float, environment_get_ssao_detail, RID)
+ PASS1RC(float, environment_get_ssao_horizon, RID)
+ PASS1RC(float, environment_get_ssao_sharpness, RID)
+ PASS1RC(float, environment_get_ssao_direct_light_affect, RID)
+ PASS1RC(float, environment_get_ssao_ao_channel_affect, RID)
+
PASS6(environment_set_ssao_quality, RS::EnvironmentSSAOQuality, bool, float, int, float, float)
+ // SSIL
PASS6(environment_set_ssil, RID, bool, float, float, float, float)
- PASS6(environment_set_ssil_quality, RS::EnvironmentSSILQuality, bool, float, int, float, float)
- PASS13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float, float, RID)
- PASS1(environment_glow_set_use_bicubic_upscale, bool)
- PASS1(environment_glow_set_use_high_quality, bool)
+ PASS1RC(bool, environment_get_ssil_enabled, RID)
+ PASS1RC(float, environment_get_ssil_radius, RID)
+ PASS1RC(float, environment_get_ssil_intensity, RID)
+ PASS1RC(float, environment_get_ssil_sharpness, RID)
+ PASS1RC(float, environment_get_ssil_normal_rejection, RID)
- PASS9(environment_set_tonemap, RID, RS::EnvironmentToneMapper, float, float, bool, float, float, float, float)
+ PASS6(environment_set_ssil_quality, RS::EnvironmentSSILQuality, bool, float, int, float, float)
- PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
+ // SDFGI
- PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
- PASS13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float)
+ PASS11(environment_set_sdfgi, RID, bool, int, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
- PASS2(environment_set_volumetric_fog_volume_size, int, int)
- PASS1(environment_set_volumetric_fog_filter_active, bool)
+ PASS1RC(bool, environment_get_sdfgi_enabled, RID)
+ PASS1RC(int, environment_get_sdfgi_cascades, RID)
+ PASS1RC(float, environment_get_sdfgi_min_cell_size, RID)
+ PASS1RC(bool, environment_get_sdfgi_use_occlusion, RID)
+ PASS1RC(float, environment_get_sdfgi_bounce_feedback, RID)
+ PASS1RC(bool, environment_get_sdfgi_read_sky_light, RID)
+ PASS1RC(float, environment_get_sdfgi_energy, RID)
+ PASS1RC(float, environment_get_sdfgi_normal_bias, RID)
+ PASS1RC(float, environment_get_sdfgi_probe_bias, RID)
+ PASS1RC(RS::EnvironmentSDFGIYScale, environment_get_sdfgi_y_scale, RID)
- PASS11(environment_set_sdfgi, RID, bool, int, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount)
PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge)
PASS1(environment_set_sdfgi_frames_to_update_light, RS::EnvironmentSDFGIFramesToUpdateLight)
- PASS1RC(RS::EnvironmentBG, environment_get_background, RID)
- PASS1RC(int, environment_get_canvas_max_layer, RID)
+ // Adjustment
+ PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
+
+ PASS1RC(bool, environment_get_adjustments_enabled, RID)
+ PASS1RC(float, environment_get_adjustments_brightness, RID)
+ PASS1RC(float, environment_get_adjustments_contrast, RID)
+ PASS1RC(float, environment_get_adjustments_saturation, RID)
+ PASS1RC(bool, environment_get_use_1d_color_correction, RID)
+ PASS1RC(RID, environment_get_color_correction, RID)
PASS3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
@@ -1150,8 +1261,8 @@ public:
PASS8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
PASS3(camera_effects_set_custom_exposure, RID, bool, float)
- PASS1(shadows_quality_set, RS::ShadowQuality)
- PASS1(directional_shadow_quality_set, RS::ShadowQuality)
+ PASS1(positional_soft_shadow_filter_set_quality, RS::ShadowQuality)
+ PASS1(directional_soft_shadow_filter_set_quality, RS::ShadowQuality)
PASS2(sdfgi_set_debug_probe_select, const Vector3 &, const Vector3 &)
@@ -1183,4 +1294,4 @@ public:
virtual ~RendererSceneCull();
};
-#endif // RENDERING_SERVER_SCENE_CULL_H
+#endif // RENDERER_SCENE_CULL_H
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 7198379ade..0d466e8a32 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -31,7 +31,7 @@
#ifndef RENDERER_SCENE_OCCLUSION_CULL_H
#define RENDERER_SCENE_OCCLUSION_CULL_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/templates/local_vector.h"
#include "servers/rendering_server.h"
@@ -60,7 +60,7 @@ public:
void update_mips();
- _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const CameraMatrix &p_cam_projection, real_t p_near) const {
+ _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near) const {
if (is_empty()) {
return false;
}
@@ -183,7 +183,8 @@ public:
}
virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) { _print_warning(); }
virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) { _print_warning(); }
- virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {}
+ virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) {}
+
virtual RID buffer_get_debug_texture(RID p_buffer) {
_print_warning();
return RID();
@@ -200,4 +201,4 @@ public:
};
};
-#endif //RENDERER_SCENE_OCCLUSION_CULL_H
+#endif // RENDERER_SCENE_OCCLUSION_CULL_H
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index 600908cf16..e024e59ec3 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -30,7 +30,10 @@
#include "renderer_scene_render.h"
-void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) {
+/////////////////////////////////////////////////////////////////////////////
+// CameraData
+
+void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) {
view_count = 1;
is_orthogonal = p_is_orthogonal;
vaspect = p_vaspect;
@@ -43,7 +46,7 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform,
taa_jitter = p_taa_jitter;
}
-void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect) {
+void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect) {
ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view");
view_count = p_view_count;
@@ -60,8 +63,8 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
}
// 2. average and normalize plane normals to obtain z vector, cross them to obtain y vector, and from there the x vector for combined camera basis.
- Vector3 n0 = planes[0][CameraMatrix::PLANE_LEFT].normal;
- Vector3 n1 = planes[1][CameraMatrix::PLANE_RIGHT].normal;
+ Vector3 n0 = planes[0][Projection::PLANE_LEFT].normal;
+ Vector3 n1 = planes[1][Projection::PLANE_RIGHT].normal;
Vector3 z = (n0 + n1).normalized();
Vector3 y = n0.cross(n1).normalized();
Vector3 x = y.cross(z).normalized();
@@ -73,13 +76,13 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 4. Intersect horizon, left and right to obtain the combined camera origin.
ERR_FAIL_COND_MSG(
- !horizon.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin");
+ !horizon.intersect_3(planes[0][Projection::PLANE_LEFT], planes[1][Projection::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin");
// handy to have the inverse of the transform we just build
Transform3D main_transform_inv = main_transform.inverse();
// 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters
- Vector3 far_center = (planes[0][CameraMatrix::PLANE_FAR].center() + planes[1][CameraMatrix::PLANE_FAR].center()) * 0.5;
+ Vector3 far_center = (planes[0][Projection::PLANE_FAR].center() + planes[1][Projection::PLANE_FAR].center()) * 0.5;
Plane far(-z, far_center);
/////////////////////////////////////////////////////////////////////////////
@@ -88,9 +91,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 6. Intersect far and left planes with top planes from both eyes, save the point with highest y as top_left.
Vector3 top_left, other;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector");
+ !far.intersect_3(planes[0][Projection::PLANE_LEFT], planes[0][Projection::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/left/top vector");
+ !far.intersect_3(planes[1][Projection::PLANE_LEFT], planes[1][Projection::PLANE_TOP], &other), "Can't determine right camera far/left/top vector");
if (y.dot(top_left) < y.dot(other)) {
top_left = other;
}
@@ -98,9 +101,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 7. Intersect far and left planes with bottom planes from both eyes, save the point with lowest y as bottom_left.
Vector3 bottom_left;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector");
+ !far.intersect_3(planes[0][Projection::PLANE_LEFT], planes[0][Projection::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector");
+ !far.intersect_3(planes[1][Projection::PLANE_LEFT], planes[1][Projection::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector");
if (y.dot(other) < y.dot(bottom_left)) {
bottom_left = other;
}
@@ -108,9 +111,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 8. Intersect far and right planes with top planes from both eyes, save the point with highest y as top_right.
Vector3 top_right;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector");
+ !far.intersect_3(planes[0][Projection::PLANE_RIGHT], planes[0][Projection::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/right/top vector");
+ !far.intersect_3(planes[1][Projection::PLANE_RIGHT], planes[1][Projection::PLANE_TOP], &other), "Can't determine right camera far/right/top vector");
if (y.dot(top_right) < y.dot(other)) {
top_right = other;
}
@@ -118,9 +121,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 9. Intersect far and right planes with bottom planes from both eyes, save the point with lowest y as bottom_right.
Vector3 bottom_right;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector");
+ !far.intersect_3(planes[0][Projection::PLANE_RIGHT], planes[0][Projection::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector");
+ !far.intersect_3(planes[1][Projection::PLANE_RIGHT], planes[1][Projection::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector");
if (y.dot(other) < y.dot(bottom_right)) {
bottom_right = other;
}
@@ -146,18 +149,18 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 13. Intersect near plane with bottm/left planes, to obtain min_vec then top/right to obtain max_vec
Vector3 min_vec;
ERR_FAIL_COND_MSG(
- !near.intersect_3(bottom, planes[0][CameraMatrix::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector");
+ !near.intersect_3(bottom, planes[0][Projection::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector");
ERR_FAIL_COND_MSG(
- !near.intersect_3(bottom, planes[1][CameraMatrix::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector");
+ !near.intersect_3(bottom, planes[1][Projection::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector");
if (x.dot(other) < x.dot(min_vec)) {
min_vec = other;
}
Vector3 max_vec;
ERR_FAIL_COND_MSG(
- !near.intersect_3(top, planes[0][CameraMatrix::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector");
+ !near.intersect_3(top, planes[0][Projection::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector");
ERR_FAIL_COND_MSG(
- !near.intersect_3(top, planes[1][CameraMatrix::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector");
+ !near.intersect_3(top, planes[1][Projection::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector");
if (x.dot(max_vec) < x.dot(other)) {
max_vec = other;
}
@@ -177,6 +180,464 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 3. Copy our view data
for (uint32_t v = 0; v < view_count; v++) {
view_offset[v] = main_transform_inv * p_transforms[v];
- view_projection[v] = p_projections[v] * CameraMatrix(view_offset[v].inverse());
+ view_projection[v] = p_projections[v] * Projection(view_offset[v].inverse());
}
}
+
+/* Environment API */
+
+RID RendererSceneRender::environment_allocate() {
+ return environment_storage.environment_allocate();
+}
+
+void RendererSceneRender::environment_initialize(RID p_rid) {
+ environment_storage.environment_initialize(p_rid);
+}
+
+void RendererSceneRender::environment_free(RID p_rid) {
+ environment_storage.environment_free(p_rid);
+}
+
+bool RendererSceneRender::is_environment(RID p_rid) const {
+ return environment_storage.is_environment(p_rid);
+}
+
+// background
+
+void RendererSceneRender::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
+ environment_storage.environment_set_background(p_env, p_bg);
+}
+
+void RendererSceneRender::environment_set_sky(RID p_env, RID p_sky) {
+ environment_storage.environment_set_sky(p_env, p_sky);
+}
+
+void RendererSceneRender::environment_set_sky_custom_fov(RID p_env, float p_scale) {
+ environment_storage.environment_set_sky_custom_fov(p_env, p_scale);
+}
+
+void RendererSceneRender::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
+ environment_storage.environment_set_sky_orientation(p_env, p_orientation);
+}
+
+void RendererSceneRender::environment_set_bg_color(RID p_env, const Color &p_color) {
+ environment_storage.environment_set_bg_color(p_env, p_color);
+}
+
+void RendererSceneRender::environment_set_bg_energy(RID p_env, float p_energy) {
+ environment_storage.environment_set_bg_energy(p_env, p_energy);
+}
+
+void RendererSceneRender::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
+ environment_storage.environment_set_canvas_max_layer(p_env, p_max_layer);
+}
+
+void RendererSceneRender::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
+ environment_storage.environment_set_ambient_light(p_env, p_color, p_ambient, p_energy, p_sky_contribution, p_reflection_source);
+}
+
+RS::EnvironmentBG RendererSceneRender::environment_get_background(RID p_env) const {
+ return environment_storage.environment_get_background(p_env);
+}
+
+RID RendererSceneRender::environment_get_sky(RID p_env) const {
+ return environment_storage.environment_get_sky(p_env);
+}
+
+float RendererSceneRender::environment_get_sky_custom_fov(RID p_env) const {
+ return environment_storage.environment_get_sky_custom_fov(p_env);
+}
+
+Basis RendererSceneRender::environment_get_sky_orientation(RID p_env) const {
+ return environment_storage.environment_get_sky_orientation(p_env);
+}
+
+Color RendererSceneRender::environment_get_bg_color(RID p_env) const {
+ return environment_storage.environment_get_bg_color(p_env);
+}
+
+float RendererSceneRender::environment_get_bg_energy(RID p_env) const {
+ return environment_storage.environment_get_bg_energy(p_env);
+}
+
+int RendererSceneRender::environment_get_canvas_max_layer(RID p_env) const {
+ return environment_storage.environment_get_canvas_max_layer(p_env);
+}
+
+RS::EnvironmentAmbientSource RendererSceneRender::environment_get_ambient_source(RID p_env) const {
+ return environment_storage.environment_get_ambient_source(p_env);
+}
+
+Color RendererSceneRender::environment_get_ambient_light(RID p_env) const {
+ return environment_storage.environment_get_ambient_light(p_env);
+}
+
+float RendererSceneRender::environment_get_ambient_light_energy(RID p_env) const {
+ return environment_storage.environment_get_ambient_light_energy(p_env);
+}
+
+float RendererSceneRender::environment_get_ambient_sky_contribution(RID p_env) const {
+ return environment_storage.environment_get_ambient_sky_contribution(p_env);
+}
+
+RS::EnvironmentReflectionSource RendererSceneRender::environment_get_reflection_source(RID p_env) const {
+ return environment_storage.environment_get_reflection_source(p_env);
+}
+
+// Tonemap
+
+void RendererSceneRender::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
+ environment_storage.environment_set_tonemap(p_env, p_tone_mapper, p_exposure, p_white, p_auto_exposure, p_min_luminance, p_max_luminance, p_auto_exp_speed, p_auto_exp_scale);
+}
+
+RS::EnvironmentToneMapper RendererSceneRender::environment_get_tone_mapper(RID p_env) const {
+ return environment_storage.environment_get_tone_mapper(p_env);
+}
+
+float RendererSceneRender::environment_get_exposure(RID p_env) const {
+ return environment_storage.environment_get_exposure(p_env);
+}
+
+float RendererSceneRender::environment_get_white(RID p_env) const {
+ return environment_storage.environment_get_white(p_env);
+}
+
+bool RendererSceneRender::environment_get_auto_exposure(RID p_env) const {
+ return environment_storage.environment_get_auto_exposure(p_env);
+}
+
+float RendererSceneRender::environment_get_min_luminance(RID p_env) const {
+ return environment_storage.environment_get_min_luminance(p_env);
+}
+
+float RendererSceneRender::environment_get_max_luminance(RID p_env) const {
+ return environment_storage.environment_get_max_luminance(p_env);
+}
+
+float RendererSceneRender::environment_get_auto_exp_speed(RID p_env) const {
+ return environment_storage.environment_get_auto_exp_speed(p_env);
+}
+
+float RendererSceneRender::environment_get_auto_exp_scale(RID p_env) const {
+ return environment_storage.environment_get_auto_exp_scale(p_env);
+}
+
+uint64_t RendererSceneRender::environment_get_auto_exposure_version(RID p_env) const {
+ return environment_storage.environment_get_auto_exposure_version(p_env);
+}
+
+// Fog
+
+void RendererSceneRender::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) {
+ environment_storage.environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective);
+}
+
+bool RendererSceneRender::environment_get_fog_enabled(RID p_env) const {
+ return environment_storage.environment_get_fog_enabled(p_env);
+}
+
+Color RendererSceneRender::environment_get_fog_light_color(RID p_env) const {
+ return environment_storage.environment_get_fog_light_color(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_light_energy(RID p_env) const {
+ return environment_storage.environment_get_fog_light_energy(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_sun_scatter(RID p_env) const {
+ return environment_storage.environment_get_fog_sun_scatter(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_density(RID p_env) const {
+ return environment_storage.environment_get_fog_density(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_height(RID p_env) const {
+ return environment_storage.environment_get_fog_height(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_height_density(RID p_env) const {
+ return environment_storage.environment_get_fog_height_density(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_aerial_perspective(RID p_env) const {
+ return environment_storage.environment_get_fog_aerial_perspective(p_env);
+}
+
+// Volumetric Fog
+
+void RendererSceneRender::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
+ environment_storage.environment_set_volumetric_fog(p_env, p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject);
+}
+
+bool RendererSceneRender::environment_get_volumetric_fog_enabled(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_enabled(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_density(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_density(p_env);
+}
+
+Color RendererSceneRender::environment_get_volumetric_fog_scattering(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_scattering(p_env);
+}
+
+Color RendererSceneRender::environment_get_volumetric_fog_emission(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_emission(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_emission_energy(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_emission_energy(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_anisotropy(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_anisotropy(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_length(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_length(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_detail_spread(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_detail_spread(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_gi_inject(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_gi_inject(p_env);
+}
+
+bool RendererSceneRender::environment_get_volumetric_fog_temporal_reprojection(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_temporal_reprojection(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_temporal_reprojection_amount(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_ambient_inject(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_ambient_inject(p_env);
+}
+
+// GLOW
+
+void RendererSceneRender::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
+ environment_storage.environment_set_glow(p_env, p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap, p_glow_map_strength, p_glow_map);
+}
+
+bool RendererSceneRender::environment_get_glow_enabled(RID p_env) const {
+ return environment_storage.environment_get_glow_enabled(p_env);
+}
+
+Vector<float> RendererSceneRender::environment_get_glow_levels(RID p_env) const {
+ return environment_storage.environment_get_glow_levels(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_intensity(RID p_env) const {
+ return environment_storage.environment_get_glow_intensity(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_strength(RID p_env) const {
+ return environment_storage.environment_get_glow_strength(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_bloom(RID p_env) const {
+ return environment_storage.environment_get_glow_bloom(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_mix(RID p_env) const {
+ return environment_storage.environment_get_glow_mix(p_env);
+}
+
+RS::EnvironmentGlowBlendMode RendererSceneRender::environment_get_glow_blend_mode(RID p_env) const {
+ return environment_storage.environment_get_glow_blend_mode(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_hdr_bleed_threshold(RID p_env) const {
+ return environment_storage.environment_get_glow_hdr_bleed_threshold(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_hdr_luminance_cap(RID p_env) const {
+ return environment_storage.environment_get_glow_hdr_luminance_cap(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_hdr_bleed_scale(RID p_env) const {
+ return environment_storage.environment_get_glow_hdr_bleed_scale(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_map_strength(RID p_env) const {
+ return environment_storage.environment_get_glow_map_strength(p_env);
+}
+
+RID RendererSceneRender::environment_get_glow_map(RID p_env) const {
+ return environment_storage.environment_get_glow_map(p_env);
+}
+
+// SSR
+
+void RendererSceneRender::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
+ environment_storage.environment_set_ssr(p_env, p_enable, p_max_steps, p_fade_int, p_fade_out, p_depth_tolerance);
+}
+
+bool RendererSceneRender::environment_get_ssr_enabled(RID p_env) const {
+ return environment_storage.environment_get_ssr_enabled(p_env);
+}
+
+int RendererSceneRender::environment_get_ssr_max_steps(RID p_env) const {
+ return environment_storage.environment_get_ssr_max_steps(p_env);
+}
+
+float RendererSceneRender::environment_get_ssr_fade_in(RID p_env) const {
+ return environment_storage.environment_get_ssr_fade_in(p_env);
+}
+
+float RendererSceneRender::environment_get_ssr_fade_out(RID p_env) const {
+ return environment_storage.environment_get_ssr_fade_out(p_env);
+}
+
+float RendererSceneRender::environment_get_ssr_depth_tolerance(RID p_env) const {
+ return environment_storage.environment_get_ssr_depth_tolerance(p_env);
+}
+
+// SSAO
+
+void RendererSceneRender::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
+ environment_storage.environment_set_ssao(p_env, p_enable, p_radius, p_intensity, p_power, p_detail, p_horizon, p_sharpness, p_light_affect, p_ao_channel_affect);
+}
+
+bool RendererSceneRender::environment_get_ssao_enabled(RID p_env) const {
+ return environment_storage.environment_get_ssao_enabled(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_radius(RID p_env) const {
+ return environment_storage.environment_get_ssao_radius(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_intensity(RID p_env) const {
+ return environment_storage.environment_get_ssao_intensity(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_power(RID p_env) const {
+ return environment_storage.environment_get_ssao_power(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_detail(RID p_env) const {
+ return environment_storage.environment_get_ssao_detail(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_horizon(RID p_env) const {
+ return environment_storage.environment_get_ssao_horizon(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_sharpness(RID p_env) const {
+ return environment_storage.environment_get_ssao_sharpness(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_direct_light_affect(RID p_env) const {
+ return environment_storage.environment_get_ssao_direct_light_affect(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_ao_channel_affect(RID p_env) const {
+ return environment_storage.environment_get_ssao_ao_channel_affect(p_env);
+}
+
+// SSIL
+
+void RendererSceneRender::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) {
+ environment_storage.environment_set_ssil(p_env, p_enable, p_radius, p_intensity, p_sharpness, p_normal_rejection);
+}
+
+bool RendererSceneRender::environment_get_ssil_enabled(RID p_env) const {
+ return environment_storage.environment_get_ssil_enabled(p_env);
+}
+
+float RendererSceneRender::environment_get_ssil_radius(RID p_env) const {
+ return environment_storage.environment_get_ssil_radius(p_env);
+}
+
+float RendererSceneRender::environment_get_ssil_intensity(RID p_env) const {
+ return environment_storage.environment_get_ssil_intensity(p_env);
+}
+
+float RendererSceneRender::environment_get_ssil_sharpness(RID p_env) const {
+ return environment_storage.environment_get_ssil_sharpness(p_env);
+}
+
+float RendererSceneRender::environment_get_ssil_normal_rejection(RID p_env) const {
+ return environment_storage.environment_get_ssil_normal_rejection(p_env);
+}
+
+// SDFGI
+
+void RendererSceneRender::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
+ environment_storage.environment_set_sdfgi(p_env, p_enable, p_cascades, p_min_cell_size, p_y_scale, p_use_occlusion, p_bounce_feedback, p_read_sky, p_energy, p_normal_bias, p_probe_bias);
+}
+
+bool RendererSceneRender::environment_get_sdfgi_enabled(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_enabled(p_env);
+}
+
+int RendererSceneRender::environment_get_sdfgi_cascades(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_cascades(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_min_cell_size(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_min_cell_size(p_env);
+}
+
+bool RendererSceneRender::environment_get_sdfgi_use_occlusion(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_use_occlusion(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_bounce_feedback(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_bounce_feedback(p_env);
+}
+
+bool RendererSceneRender::environment_get_sdfgi_read_sky_light(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_read_sky_light(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_energy(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_energy(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_normal_bias(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_normal_bias(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_probe_bias(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_probe_bias(p_env);
+}
+
+RS::EnvironmentSDFGIYScale RendererSceneRender::environment_get_sdfgi_y_scale(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_y_scale(p_env);
+}
+
+// Adjustments
+
+void RendererSceneRender::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
+ environment_storage.environment_set_adjustment(p_env, p_enable, p_brightness, p_contrast, p_saturation, p_use_1d_color_correction, p_color_correction);
+}
+
+bool RendererSceneRender::environment_get_adjustments_enabled(RID p_env) const {
+ return environment_storage.environment_get_adjustments_enabled(p_env);
+}
+
+float RendererSceneRender::environment_get_adjustments_brightness(RID p_env) const {
+ return environment_storage.environment_get_adjustments_brightness(p_env);
+}
+
+float RendererSceneRender::environment_get_adjustments_contrast(RID p_env) const {
+ return environment_storage.environment_get_adjustments_contrast(p_env);
+}
+
+float RendererSceneRender::environment_get_adjustments_saturation(RID p_env) const {
+ return environment_storage.environment_get_adjustments_saturation(p_env);
+}
+
+bool RendererSceneRender::environment_get_use_1d_color_correction(RID p_env) const {
+ return environment_storage.environment_get_use_1d_color_correction(p_env);
+}
+
+RID RendererSceneRender::environment_get_color_correction(RID p_env) const {
+ return environment_storage.environment_get_color_correction(p_env);
+}
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 280277c6d8..7f70f4b939 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -28,14 +28,20 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERSCENERENDER_H
-#define RENDERINGSERVERSCENERENDER_H
+#ifndef RENDERER_SCENE_RENDER_H
+#define RENDERER_SCENE_RENDER_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/templates/paged_array.h"
+#include "servers/rendering/renderer_geometry_instance.h"
#include "servers/rendering/renderer_scene.h"
+#include "servers/rendering/storage/environment_storage.h"
+#include "storage/utilities.h"
class RendererSceneRender {
+private:
+ RendererEnvironmentStorage environment_storage;
+
public:
enum {
MAX_DIRECTIONAL_LIGHTS = 8,
@@ -43,38 +49,11 @@ public:
MAX_RENDER_VIEWS = 2
};
- struct GeometryInstance {
- virtual ~GeometryInstance() {}
- };
-
- virtual GeometryInstance *geometry_instance_create(RID p_base) = 0;
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) = 0;
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0;
- virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) = 0;
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0;
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0;
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0;
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0;
- virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) = 0;
- virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0;
- virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) = 0;
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) = 0;
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) = 0;
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
+ /* Geometry Instance */
+ virtual RenderGeometryInstance *geometry_instance_create(RID p_base) = 0;
+ virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) = 0;
virtual uint32_t geometry_instance_get_pair_mask() = 0;
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) = 0;
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0;
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0;
-
- virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) = 0;
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0;
/* SHADOW ATLAS API */
@@ -106,57 +85,160 @@ public:
/* ENVIRONMENT API */
- virtual RID environment_allocate() = 0;
- virtual void environment_initialize(RID p_rid) = 0;
-
- virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0;
- virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
- virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
- virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0;
- virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
- virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
- virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
- virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0;
+ RID environment_allocate();
+ void environment_initialize(RID p_rid);
+ void environment_free(RID p_rid);
+
+ bool is_environment(RID p_env) const;
+
+ // Background
+ void environment_set_background(RID p_env, RS::EnvironmentBG p_bg);
+ void environment_set_sky(RID p_env, RID p_sky);
+ void environment_set_sky_custom_fov(RID p_env, float p_scale);
+ void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
+ void environment_set_bg_color(RID p_env, const Color &p_color);
+ void environment_set_bg_energy(RID p_env, float p_energy);
+ void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
+ void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG);
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
- virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0;
+ void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id);
#endif
- virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0;
- virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
- virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
+ RS::EnvironmentBG environment_get_background(RID p_env) const;
+ RID environment_get_sky(RID p_env) const;
+ float environment_get_sky_custom_fov(RID p_env) const;
+ Basis environment_get_sky_orientation(RID p_env) const;
+ Color environment_get_bg_color(RID p_env) const;
+ float environment_get_bg_energy(RID p_env) const;
+ int environment_get_canvas_max_layer(RID p_env) const;
+ RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
+ Color environment_get_ambient_light(RID p_env) const;
+ float environment_get_ambient_light_energy(RID p_env) const;
+ float environment_get_ambient_sky_contribution(RID p_env) const;
+ RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
+
+ // Tonemap
+ void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
+ RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const;
+ float environment_get_exposure(RID p_env) const;
+ float environment_get_white(RID p_env) const;
+ bool environment_get_auto_exposure(RID p_env) const;
+ float environment_get_min_luminance(RID p_env) const;
+ float environment_get_max_luminance(RID p_env) const;
+ float environment_get_auto_exp_speed(RID p_env) const;
+ float environment_get_auto_exp_scale(RID p_env) const;
+ uint64_t environment_get_auto_exposure_version(RID p_env) const;
+
+ // Fog
+ void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective);
+ bool environment_get_fog_enabled(RID p_env) const;
+ Color environment_get_fog_light_color(RID p_env) const;
+ float environment_get_fog_light_energy(RID p_env) const;
+ float environment_get_fog_sun_scatter(RID p_env) const;
+ float environment_get_fog_density(RID p_env) const;
+ float environment_get_fog_height(RID p_env) const;
+ float environment_get_fog_height_density(RID p_env) const;
+ float environment_get_fog_aerial_perspective(RID p_env) const;
+
+ // Volumetric Fog
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject);
+ bool environment_get_volumetric_fog_enabled(RID p_env) const;
+ float environment_get_volumetric_fog_density(RID p_env) const;
+ Color environment_get_volumetric_fog_scattering(RID p_env) const;
+ Color environment_get_volumetric_fog_emission(RID p_env) const;
+ float environment_get_volumetric_fog_emission_energy(RID p_env) const;
+ float environment_get_volumetric_fog_anisotropy(RID p_env) const;
+ float environment_get_volumetric_fog_length(RID p_env) const;
+ float environment_get_volumetric_fog_detail_spread(RID p_env) const;
+ float environment_get_volumetric_fog_gi_inject(RID p_env) const;
+ bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const;
+ float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const;
+ float environment_get_volumetric_fog_ambient_inject(RID p_env) const;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
- virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0;
+ // GLOW
+ void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map);
+ bool environment_get_glow_enabled(RID p_env) const;
+ Vector<float> environment_get_glow_levels(RID p_env) const;
+ float environment_get_glow_intensity(RID p_env) const;
+ float environment_get_glow_strength(RID p_env) const;
+ float environment_get_glow_bloom(RID p_env) const;
+ float environment_get_glow_mix(RID p_env) const;
+ RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const;
+ float environment_get_glow_hdr_bleed_threshold(RID p_env) const;
+ float environment_get_glow_hdr_luminance_cap(RID p_env) const;
+ float environment_get_glow_hdr_bleed_scale(RID p_env) const;
+ float environment_get_glow_map_strength(RID p_env) const;
+ RID environment_get_glow_map(RID p_env) const;
+
+ virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
+ virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
+
+ // SSR
+ void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
+ bool environment_get_ssr_enabled(RID p_env) const;
+ int environment_get_ssr_max_steps(RID p_env) const;
+ float environment_get_ssr_fade_in(RID p_env) const;
+ float environment_get_ssr_fade_out(RID p_env) const;
+ float environment_get_ssr_depth_tolerance(RID p_env) const;
+
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
- virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0;
+ // SSAO
+ void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
+ bool environment_get_ssao_enabled(RID p_env) const;
+ float environment_get_ssao_radius(RID p_env) const;
+ float environment_get_ssao_intensity(RID p_env) const;
+ float environment_get_ssao_power(RID p_env) const;
+ float environment_get_ssao_detail(RID p_env) const;
+ float environment_get_ssao_horizon(RID p_env) const;
+ float environment_get_ssao_sharpness(RID p_env) const;
+ float environment_get_ssao_direct_light_affect(RID p_env) const;
+ float environment_get_ssao_ao_channel_affect(RID p_env) const;
+
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
- virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0;
+ // SSIL
+ void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection);
+ bool environment_get_ssil_enabled(RID p_env) const;
+ float environment_get_ssil_radius(RID p_env) const;
+ float environment_get_ssil_intensity(RID p_env) const;
+ float environment_get_ssil_sharpness(RID p_env) const;
+ float environment_get_ssil_normal_rejection(RID p_env) const;
+
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ // SDFGI
+ void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
+ bool environment_get_sdfgi_enabled(RID p_env) const;
+ int environment_get_sdfgi_cascades(RID p_env) const;
+ float environment_get_sdfgi_min_cell_size(RID p_env) const;
+ bool environment_get_sdfgi_use_occlusion(RID p_env) const;
+ float environment_get_sdfgi_bounce_feedback(RID p_env) const;
+ bool environment_get_sdfgi_read_sky_light(RID p_env) const;
+ float environment_get_sdfgi_energy(RID p_env) const;
+ float environment_get_sdfgi_normal_bias(RID p_env) const;
+ float environment_get_sdfgi_probe_bias(RID p_env) const;
+ RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) = 0;
- virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
-
- virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0;
-
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
+ // Adjustment
+ void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction);
+ bool environment_get_adjustments_enabled(RID p_env) const;
+ float environment_get_adjustments_brightness(RID p_env) const;
+ float environment_get_adjustments_contrast(RID p_env) const;
+ float environment_get_adjustments_saturation(RID p_env) const;
+ bool environment_get_use_1d_color_correction(RID p_env) const;
+ RID environment_get_color_correction(RID p_env) const;
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0;
- virtual bool is_environment(RID p_env) const = 0;
- virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0;
- virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
-
virtual RID camera_effects_allocate() = 0;
virtual void camera_effects_initialize(RID p_rid) = 0;
@@ -166,13 +248,13 @@ public:
virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
- virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
- virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
+ virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0;
+ virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0;
virtual RID light_instance_create(RID p_light) = 0;
virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) = 0;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
- virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
virtual bool light_instances_can_render_shadow_cube() const {
return true;
@@ -205,19 +287,19 @@ public:
virtual RID voxel_gi_instance_create(RID p_voxel_gi) = 0;
virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) = 0;
virtual bool voxel_gi_needs_update(RID p_probe) const = 0;
- virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) = 0;
+ virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) = 0;
virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0;
struct RenderShadowData {
RID light;
int pass = 0;
- PagedArray<GeometryInstance *> instances;
+ PagedArray<RenderGeometryInstance *> instances;
};
struct RenderSDFGIData {
int region = 0;
- PagedArray<GeometryInstance *> instances;
+ PagedArray<RenderGeometryInstance *> instances;
};
struct RenderSDFGIUpdateData {
@@ -239,27 +321,27 @@ public:
// Main/center projection
Transform3D main_transform;
- CameraMatrix main_projection;
+ Projection main_projection;
Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS];
- CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
Vector2 taa_jitter;
- void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2());
- void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect);
+ void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2());
+ void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect);
};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
- virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
+ virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
virtual void set_time(double p_time, double p_step) = 0;
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
@@ -281,4 +363,4 @@ public:
virtual ~RendererSceneRender() {}
};
-#endif // RENDERINGSERVERSCENERENDER_H
+#endif // RENDERER_SCENE_RENDER_H
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index ab9ee2067f..118bf532b3 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -138,7 +138,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
p_viewport->internal_size = Size2(render_width, render_height);
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->texture_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
}
}
}
@@ -154,7 +154,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
if (p_viewport->use_occlusion_culling) {
if (p_viewport->occlusion_buffer_dirty) {
float aspect = p_viewport->size.aspect();
- int max_size = occlusion_rays_per_thread * RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ int max_size = occlusion_rays_per_thread * WorkerThreadPool::get_singleton()->get_thread_count();
int viewport_size = p_viewport->size.width * p_viewport->size.height;
max_size = CLAMP(max_size, viewport_size / (32 * 32), viewport_size / (2 * 2)); // At least one depth pixel for every 16x16 region. At most one depth pixel for every 2x2 region.
@@ -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;
}
}
@@ -746,11 +746,11 @@ void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpn
_configure_3d_render_buffers(viewport);
}
-void RendererViewport::viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
+void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->fsr_mipmap_bias = p_mipmap_bias;
+ viewport->texture_mipmap_bias = p_mipmap_bias;
_configure_3d_render_buffers(viewport);
}
@@ -1016,7 +1016,7 @@ void RendererViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas
viewport->canvas_map[p_canvas].sublayer = p_sublayer;
}
-void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits) {
+void RendererViewport::viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -1026,7 +1026,7 @@ void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size
RSG::scene->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size, viewport->shadow_atlas_16_bits);
}
-void RendererViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
+void RendererViewport::viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -1207,6 +1207,22 @@ RID RendererViewport::viewport_find_from_screen_attachment(DisplayServer::Window
return RID();
}
+void RendererViewport::viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ RSG::texture_storage->render_target_set_vrs_mode(viewport->render_target, p_mode);
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_vrs_texture(RID p_viewport, RID p_texture) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ RSG::texture_storage->render_target_set_vrs_texture(viewport->render_target, p_texture);
+ _configure_3d_render_buffers(viewport);
+}
+
bool RendererViewport::free(RID p_rid) {
if (viewport_owner.owns(p_rid)) {
Viewport *viewport = viewport_owner.get_or_null(p_rid);
@@ -1259,7 +1275,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/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index acab8063d1..5e37c96336 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -48,33 +48,34 @@ public:
RID self;
RID parent;
- bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */
+ // use xr interface to override camera positioning and projection matrices and control output
+ bool use_xr = false;
Size2i internal_size;
Size2i size;
RID camera;
RID scenario;
- RS::ViewportScaling3DMode scaling_3d_mode;
+ RS::ViewportScaling3DMode scaling_3d_mode = RenderingServer::VIEWPORT_SCALING_3D_MODE_BILINEAR;
float scaling_3d_scale = 1.0;
float fsr_sharpness = 0.2f;
- float fsr_mipmap_bias = 0.0f;
- bool fsr_enabled;
- RS::ViewportUpdateMode update_mode;
+ float texture_mipmap_bias = 0.0f;
+ bool fsr_enabled = false;
+ RS::ViewportUpdateMode update_mode = RenderingServer::VIEWPORT_UPDATE_WHEN_VISIBLE;
RID render_target;
RID render_target_texture;
RID render_buffers;
- RS::ViewportMSAA msaa;
- RS::ViewportScreenSpaceAA screen_space_aa;
- bool use_taa;
- bool use_debanding;
+ RS::ViewportMSAA msaa = RenderingServer::VIEWPORT_MSAA_DISABLED;
+ RS::ViewportScreenSpaceAA screen_space_aa = RenderingServer::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+ bool use_taa = false;
+ bool use_debanding = false;
RendererSceneRender::CameraData prev_camera_data;
uint64_t prev_camera_data_frame = 0;
- bool use_occlusion_culling;
- bool occlusion_buffer_dirty;
+ bool use_occlusion_culling = false;
+ bool occlusion_buffer_dirty = false;
DisplayServer::WindowID viewport_to_screen;
Rect2 viewport_to_screen_rect;
@@ -83,10 +84,10 @@ public:
bool disable_2d = false;
bool disable_environment = false;
bool disable_3d = false;
- bool measure_render_time;
+ bool measure_render_time = false;
- bool snap_2d_transforms_to_pixel;
- bool snap_2d_vertices_to_pixel;
+ bool snap_2d_transforms_to_pixel = false;
+ bool snap_2d_vertices_to_pixel = false;
uint64_t time_cpu_begin;
uint64_t time_cpu_end;
@@ -95,23 +96,23 @@ public:
uint64_t time_gpu_end;
RID shadow_atlas;
- int shadow_atlas_size;
+ int shadow_atlas_size = 2048;
bool shadow_atlas_16_bits = true;
- bool sdf_active;
+ bool sdf_active = false;
float mesh_lod_threshold = 1.0;
uint64_t last_pass = 0;
- RS::ViewportDebugDraw debug_draw;
+ RS::ViewportDebugDraw debug_draw = RenderingServer::VIEWPORT_DEBUG_DRAW_DISABLED;
- RS::ViewportClearMode clear_mode;
+ RS::ViewportClearMode clear_mode = RenderingServer::VIEWPORT_CLEAR_ALWAYS;
RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
- bool transparent_bg;
+ bool transparent_bg = false;
struct CanvasKey {
int64_t stacking;
@@ -228,7 +229,7 @@ public:
void viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode);
void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale);
void viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness);
- void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias);
+ void viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias);
void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode);
void viewport_set_vflip(RID p_viewport, bool p_enable);
@@ -255,8 +256,8 @@ public:
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
- void viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true);
- void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
+ void viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true);
+ void viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode);
@@ -284,6 +285,9 @@ public:
virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const;
+ void viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode);
+ void viewport_set_vrs_texture(RID p_viewport, RID p_texture);
+
void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
void set_default_clear_color(const Color &p_color);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 6fc5d0b3e8..c07a783302 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -64,12 +64,12 @@ Vector<uint8_t> RenderingDevice::shader_compile_spirv_from_source(ShaderStage p_
ERR_FAIL_COND_V(!compile_to_spirv_function, Vector<uint8_t>());
- return compile_to_spirv_function(p_stage, p_source_code, p_language, r_error, &device_capabilities);
+ return compile_to_spirv_function(p_stage, p_source_code, p_language, r_error, this);
}
String RenderingDevice::shader_get_spirv_cache_key() const {
if (get_spirv_cache_key_function) {
- return get_spirv_cache_key_function(&device_capabilities);
+ return get_spirv_cache_key_function(this);
}
return String();
}
@@ -279,6 +279,7 @@ static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constan
}
return ret;
}
+
RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) {
PipelineRasterizationState rasterization_state;
if (p_rasterization_state.is_valid()) {
@@ -386,6 +387,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("framebuffer_create_multipass", "textures", "passes", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create_multipass, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1));
ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "samples", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(TEXTURE_SAMPLES_1), DEFVAL(INVALID_FORMAT_ID));
ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format);
+ ClassDB::bind_method(D_METHOD("framebuffer_is_valid", "framebuffer"), &RenderingDevice::framebuffer_is_valid);
ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 0973e29974..a864cfa74c 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -123,21 +123,14 @@ public:
DeviceFamily device_family = DEVICE_UNKNOWN;
uint32_t version_major = 1.0;
uint32_t version_minor = 0.0;
-
- // subgroup capabilities
- uint32_t subgroup_size = 0;
- uint32_t subgroup_in_shaders = 0; // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
- uint32_t subgroup_operations = 0; // Set flags, using SubgroupOperations
-
- // features
- bool supports_multiview = false; // If true this device supports multiview options
- bool supports_fsr_half_float = false; // If true this device supports FSR scaling 3D in half float mode, otherwise use the fallback mode
};
- typedef String (*ShaderSPIRVGetCacheKeyFunction)(const Capabilities *p_capabilities);
- typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);
+ typedef String (*ShaderSPIRVGetCacheKeyFunction)(const RenderingDevice *p_render_device);
+ typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device);
typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language);
+ typedef void (*InvalidationCallback)(void *);
+
private:
static ShaderCompileToSPIRVFunction compile_to_spirv_function;
static ShaderCacheFunction cache_function;
@@ -444,6 +437,7 @@ public:
TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7),
TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8),
TEXTURE_USAGE_INPUT_ATTACHMENT_BIT = (1 << 9),
+ TEXTURE_USAGE_VRS_ATTACHMENT_BIT = (1 << 10),
};
enum TextureSwizzle {
@@ -552,15 +546,18 @@ public:
Vector<int32_t> resolve_attachments;
Vector<int32_t> preserve_attachments;
int32_t depth_attachment = ATTACHMENT_UNUSED;
+ int32_t vrs_attachment = ATTACHMENT_UNUSED; // density map for VRS, only used if supported
};
- virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
+ virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1) = 0;
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0) = 0;
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
- virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
+ virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID) = 0;
+ virtual bool framebuffer_is_valid(RID p_framebuffer) const = 0;
+ virtual void framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata) = 0;
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0;
@@ -675,6 +672,13 @@ public:
const Capabilities *get_device_capabilities() const { return &device_capabilities; };
+ enum Features {
+ SUPPORTS_MULTIVIEW,
+ SUPPORTS_FSR_HALF_FLOAT,
+ SUPPORTS_ATTACHMENT_VRS,
+ };
+ virtual bool has_feature(const Features p_feature) const = 0;
+
virtual Vector<uint8_t> shader_compile_spirv_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = nullptr, bool p_allow_cache = true);
virtual String shader_get_spirv_cache_key() const;
@@ -793,8 +797,7 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0;
virtual bool uniform_set_is_valid(RID p_uniform_set) = 0;
- typedef void (*UniformSetInvalidatedCallback)(void *);
- virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) = 0;
+ virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata) = 0;
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
@@ -1221,9 +1224,12 @@ public:
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X,
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y,
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z,
+ LIMIT_SUBGROUP_SIZE,
+ LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
+ LIMIT_SUBGROUP_OPERATIONS,
};
- virtual uint64_t limit_get(Limit p_limit) = 0;
+ virtual uint64_t limit_get(Limit p_limit) const = 0;
//methods below not exposed, used by RenderingDeviceRD
virtual void prepare_screen_for_drawing() = 0;
@@ -1324,6 +1330,7 @@ VARIANT_ENUM_CAST(RenderingDevice::InitialAction)
VARIANT_ENUM_CAST(RenderingDevice::FinalAction)
VARIANT_ENUM_CAST(RenderingDevice::Limit)
VARIANT_ENUM_CAST(RenderingDevice::MemoryType)
+VARIANT_ENUM_CAST(RenderingDevice::Features)
typedef RenderingDevice RD;
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 7e035bae80..8071b7e416 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)) {
@@ -106,7 +106,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
Callable c = frame_drawn_callbacks.front()->get();
Variant result;
Callable::CallError ce;
- c.call(nullptr, 0, result, ce);
+ c.callp(nullptr, 0, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
String err = Variant::get_callable_error_text(c, nullptr, 0, ce);
ERR_PRINT("Error calling frame drawn function: " + err);
@@ -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..cc79d09503 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"
@@ -225,9 +224,10 @@ public:
FUNCRIDSPLIT(shader)
FUNC2(shader_set_code, RID, const String &)
+ FUNC2(shader_set_path_hint, RID, const String &)
FUNC1RC(String, shader_get_code, RID)
- FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
+ FUNC2SC(shader_get_shader_uniform_list, RID, List<PropertyInfo> *)
FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int)
FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int)
@@ -524,8 +524,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 +535,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 &)
@@ -585,7 +591,7 @@ public:
FUNC2(viewport_set_scaling_3d_mode, RID, ViewportScaling3DMode)
FUNC2(viewport_set_scaling_3d_scale, RID, float)
FUNC2(viewport_set_fsr_sharpness, RID, float)
- FUNC2(viewport_set_fsr_mipmap_bias, RID, float)
+ FUNC2(viewport_set_texture_mipmap_bias, RID, float)
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
@@ -610,9 +616,9 @@ public:
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
- FUNC3(viewport_set_shadow_atlas_size, RID, int, bool)
+ FUNC3(viewport_set_positional_shadow_atlas_size, RID, int, bool)
FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
- FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
+ FUNC3(viewport_set_positional_shadow_atlas_quadrant_subdivision, RID, int, int)
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
FUNC2(viewport_set_use_taa, RID, bool)
@@ -632,6 +638,9 @@ public:
FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
+ FUNC2(viewport_set_vrs_mode, RID, ViewportVRSMode)
+ FUNC2(viewport_set_vrs_texture, RID, RID)
+
/* ENVIRONMENT API */
#undef server_name
@@ -710,8 +719,8 @@ public:
FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
- FUNC1(shadows_quality_set, ShadowQuality);
- FUNC1(directional_shadow_quality_set, ShadowQuality);
+ FUNC1(positional_soft_shadow_filter_set_quality, ShadowQuality);
+ FUNC1(directional_soft_shadow_filter_set_quality, ShadowQuality);
FUNC1(decals_set_filter, RS::DecalFilter);
FUNC1(light_projectors_set_filter, RS::LightProjectorFilter);
@@ -764,10 +773,10 @@ public:
FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
FUNC2(instance_geometry_set_lod_bias, RID, float)
FUNC2(instance_geometry_set_transparency, RID, float)
- FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
- FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
- FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
- FUNC2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
+ FUNC3(instance_geometry_set_shader_uniform, RID, const StringName &, const Variant &)
+ FUNC2RC(Variant, instance_geometry_get_shader_uniform, RID, const StringName &)
+ FUNC2RC(Variant, instance_geometry_get_shader_uniform_default_value, RID, const StringName &)
+ FUNC2C(instance_geometry_get_shader_uniform_list, RID, List<PropertyInfo> *)
FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
@@ -891,7 +900,7 @@ public:
FUNC1(canvas_set_shadow_texture_size, int)
- /* GLOBAL VARIABLES */
+ /* GLOBAL SHADER UNIFORMS */
#undef server_name
#undef ServerName
@@ -899,16 +908,16 @@ public:
#define ServerName RendererMaterialStorage
#define server_name RSG::material_storage
- FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
- FUNC1(global_variable_remove, const StringName &)
- FUNC0RC(Vector<StringName>, global_variable_get_list)
- FUNC2(global_variable_set, const StringName &, const Variant &)
- FUNC2(global_variable_set_override, const StringName &, const Variant &)
- FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &)
- FUNC1RC(Variant, global_variable_get, const StringName &)
+ FUNC3(global_shader_uniform_add, const StringName &, GlobalShaderUniformType, const Variant &)
+ FUNC1(global_shader_uniform_remove, const StringName &)
+ FUNC0RC(Vector<StringName>, global_shader_uniform_get_list)
+ FUNC2(global_shader_uniform_set, const StringName &, const Variant &)
+ FUNC2(global_shader_uniform_set_override, const StringName &, const Variant &)
+ FUNC1RC(GlobalShaderUniformType, global_shader_uniform_get_type, const StringName &)
+ FUNC1RC(Variant, global_shader_uniform_get, const StringName &)
- FUNC1(global_variables_load_settings, bool)
- FUNC0(global_variables_clear)
+ FUNC1(global_shader_uniforms_load_settings, bool)
+ FUNC0(global_shader_uniforms_clear)
#undef server_name
#undef ServerName
@@ -972,4 +981,4 @@ public:
~RenderingServerDefault();
};
-#endif
+#endif // RENDERING_SERVER_DEFAULT_H
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/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 463b67033d..7637eae4a6 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -370,7 +370,7 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str
}
}
-static String _get_global_variable_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
+static String _get_global_shader_uniform_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
switch (p_type) {
case ShaderLanguage::TYPE_BOOL: {
return "(" + p_buffer + "[" + p_index + "].x != 0.0)";
@@ -903,11 +903,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
code = actions.base_uniform_string + _mkid(vnode->name); //texture, use as is
//global variable, this means the code points to an index to the global table
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
code = actions.base_uniform_string + _mkid(vnode->name);
@@ -1003,11 +1003,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
code = actions.base_uniform_string + _mkid(anode->name); //texture, use as is
//global variable, this means the code points to an index to the global table
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
code = actions.base_uniform_string + _mkid(anode->name);
@@ -1309,8 +1309,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
ShaderLanguage::DataType ShaderCompiler::_get_variable_type(const StringName &p_type) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_type);
- return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt);
+ RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_type);
+ return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
}
Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
@@ -1318,23 +1318,81 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
info.shader_types = ShaderTypes::get_singleton()->get_types();
- info.global_variable_type_func = _get_variable_type;
+ info.global_shader_uniform_type_func = _get_variable_type;
Error err = parser.compile(p_code, info);
if (err != OK) {
+ Vector<ShaderLanguage::FilePosition> include_positions = parser.get_include_positions();
+
+ String current;
+ HashMap<String, Vector<String>> includes;
+ includes[""] = Vector<String>();
+ Vector<String> include_stack;
Vector<String> shader = p_code.split("\n");
+
+ // Reconstruct the files.
for (int i = 0; i < shader.size(); i++) {
- if (i + 1 == parser.get_error_line()) {
- // Mark the error line to be visible without having to look at
- // the trace at the end.
- print_line(vformat("E%4d-> %s", i + 1, shader[i]));
+ String l = shader[i];
+ if (l.begins_with("@@>")) {
+ String inc_path = l.replace_first("@@>", "");
+
+ l = "#include \"" + inc_path + "\"";
+ includes[current].append("#include \"" + inc_path + "\""); // Restore the include directive
+ include_stack.push_back(current);
+ current = inc_path;
+ includes[inc_path] = Vector<String>();
+
+ } else if (l.begins_with("@@<")) {
+ if (include_stack.size()) {
+ current = include_stack[include_stack.size() - 1];
+ include_stack.resize(include_stack.size() - 1);
+ }
+ } else {
+ includes[current].push_back(l);
+ }
+ }
+
+ // Print the files.
+ for (const KeyValue<String, Vector<String>> &E : includes) {
+ if (E.key.is_empty()) {
+ if (p_path == "") {
+ print_line("--Main Shader--");
+ } else {
+ print_line("--" + p_path + "--");
+ }
} else {
- print_line(vformat("%5d | %s", i + 1, shader[i]));
+ print_line("--" + E.key + "--");
}
+ int err_line = -1;
+ for (int i = 0; i < include_positions.size(); i++) {
+ if (include_positions[i].file == E.key) {
+ err_line = include_positions[i].line;
+ }
+ }
+ const Vector<String> &V = E.value;
+ for (int i = 0; i < V.size(); i++) {
+ if (i == err_line - 1) {
+ // Mark the error line to be visible without having to look at
+ // the trace at the end.
+ print_line(vformat("E%4d-> %s", i + 1, V[i]));
+ } else {
+ print_line(vformat("%5d | %s", i + 1, V[i]));
+ }
+ }
+ }
+
+ String file;
+ int line;
+ if (include_positions.size() > 1) {
+ file = include_positions[include_positions.size() - 1].file;
+ line = include_positions[include_positions.size() - 1].line;
+ } else {
+ file = p_path;
+ line = parser.get_error_line();
}
- _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
+ _err_print_error(nullptr, file.utf8().get_data(), line, parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
return err;
}
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index ad9b51ac0c..839f5b8eea 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -32,7 +32,9 @@
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include "core/templates/local_vector.h"
#include "servers/rendering_server.h"
+#include "shader_types.h"
#define HAS_WARNING(flag) (warning_flags & flag)
@@ -193,6 +195,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"SOURCE_COLOR",
"HINT_DEFAULT_WHITE_TEXTURE",
"HINT_DEFAULT_BLACK_TEXTURE",
+ "HINT_DEFAULT_TRANSPARENT_TEXTURE",
"HINT_NORMAL_TEXTURE",
"HINT_ANISOTROPY_TEXTURE",
"HINT_RANGE",
@@ -308,6 +311,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
// global space keywords
{ TK_UNIFORM, "uniform", CF_GLOBAL_SPACE | CF_UNIFORM_KEYWORD, {}, {} },
+ { TK_UNIFORM_GROUP, "group_uniforms", CF_GLOBAL_SPACE, {}, {} },
{ TK_VARYING, "varying", CF_GLOBAL_SPACE, { "particles", "sky", "fog" }, {} },
{ TK_CONST, "const", CF_BLOCK | CF_GLOBAL_SPACE | CF_CONST_KEYWORD, {}, {} },
{ TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} },
@@ -351,6 +355,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_NORMAL_TEXTURE, "hint_normal", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_DEFAULT_WHITE_TEXTURE, "hint_default_white", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_DEFAULT_BLACK_TEXTURE, "hint_default_black", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_DEFAULT_TRANSPARENT_TEXTURE, "hint_default_transparent", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_R, "hint_roughness_r", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_G, "hint_roughness_g", CF_UNSPECIFIED, {}, {} },
@@ -574,6 +579,37 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_OP_MOD);
} break;
+ case '@': {
+ if (GETCHAR(0) == '@' && GETCHAR(1) == '>') {
+ char_idx += 2;
+
+ LocalVector<char32_t> incp;
+ while (GETCHAR(0) != '\n') {
+ incp.push_back(GETCHAR(0));
+ char_idx++;
+ }
+ incp.push_back(0); // Zero end it.
+ String include_path(incp.ptr());
+ include_positions.write[include_positions.size() - 1].line = tk_line;
+ FilePosition fp;
+ fp.file = include_path;
+ fp.line = 0;
+ tk_line = 0;
+ include_positions.push_back(fp);
+
+ } else if (GETCHAR(0) == '@' && GETCHAR(1) == '<') {
+ if (include_positions.size() == 1) {
+ return _make_token(TK_ERROR, "Invalid include exit hint @@< without matching enter hint.");
+ }
+ char_idx += 2;
+
+ include_positions.resize(include_positions.size() - 1); // Pop back.
+ tk_line = include_positions[include_positions.size() - 1].line; // Restore line.
+
+ } else {
+ return _make_token(TK_ERROR, "Invalid include enter/exit hint token (@@> and @@<)");
+ }
+ } break;
default: {
char_idx--; //go back one, since we have no idea what this is
@@ -1054,6 +1090,9 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
case ShaderNode::Uniform::HINT_DEFAULT_WHITE: {
result = "hint_default_white";
} break;
+ case ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: {
+ result = "hint_default_transparent";
+ } break;
case ShaderNode::Uniform::HINT_ANISOTROPY: {
result = "hint_anisotropy";
} break;
@@ -1113,6 +1152,8 @@ void ShaderLanguage::clear() {
current_function = StringName();
last_name = StringName();
last_type = IDENTIFIER_MAX;
+ current_uniform_group_name = "";
+ current_uniform_subgroup_name = "";
completion_type = COMPLETION_NONE;
completion_block = nullptr;
@@ -1122,6 +1163,9 @@ void ShaderLanguage::clear() {
completion_base = TYPE_VOID;
completion_base_array = false;
+ include_positions.clear();
+ include_positions.push_back(FilePosition());
+
#ifdef DEBUG_ENABLED
keyword_completion_context = CF_GLOBAL_SPACE;
used_constants.clear();
@@ -1183,17 +1227,36 @@ void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, Iden
#endif // DEBUG_ENABLED
bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name, ConstantNode::Value *r_constant_value) {
- if (p_function_info.built_ins.has(p_identifier)) {
- if (r_data_type) {
- *r_data_type = p_function_info.built_ins[p_identifier].type;
- }
- if (r_is_const) {
- *r_is_const = p_function_info.built_ins[p_identifier].constant;
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ for (const KeyValue<StringName, FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i))) {
+ if ((current_function == E.key || E.key == "global") && E.value.built_ins.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type = E.value.built_ins[p_identifier].type;
+ }
+ if (r_is_const) {
+ *r_is_const = E.value.built_ins[p_identifier].constant;
+ }
+ if (r_type) {
+ *r_type = IDENTIFIER_BUILTIN_VAR;
+ }
+ return true;
+ }
+ }
}
- if (r_type) {
- *r_type = IDENTIFIER_BUILTIN_VAR;
+ } else {
+ if (p_function_info.built_ins.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type = p_function_info.built_ins[p_identifier].type;
+ }
+ if (r_is_const) {
+ *r_is_const = p_function_info.built_ins[p_identifier].constant;
+ }
+ if (r_type) {
+ *r_type = IDENTIFIER_BUILTIN_VAR;
+ }
+ return true;
}
- return true;
}
if (p_function_info.stage_functions.has(p_identifier)) {
@@ -2400,11 +2463,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// reflect
+ { "reflect", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
{ "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
+ { "reflect", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
// refract
+ { "refract", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
{ "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
+ { "refract", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
// faceforward
@@ -3798,18 +3865,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
}
value = Variant(array);
} else {
- Basis p;
- p[0][0] = p_value[0].real;
- p[0][1] = p_value[1].real;
- p[0][2] = p_value[2].real;
- p[1][0] = p_value[4].real;
- p[1][1] = p_value[5].real;
- p[1][2] = p_value[6].real;
- p[2][0] = p_value[8].real;
- p[2][1] = p_value[9].real;
- p[2][2] = p_value[10].real;
- Transform3D t = Transform3D(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
- value = Variant(t);
+ Projection p = Projection(Vector4(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real),
+ Vector4(p_value[4].real, p_value[5].real, p_value[6].real, p_value[7].real),
+ Vector4(p_value[8].real, p_value[9].real, p_value[10].real, p_value[11].real),
+ Vector4(p_value[12].real, p_value[13].real, p_value[14].real, p_value[15].real));
+ value = Variant(p);
}
break;
}
@@ -3891,13 +3951,29 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
}
}
} break;
- case ShaderLanguage::TYPE_IVEC2:
- case ShaderLanguage::TYPE_IVEC3:
- case ShaderLanguage::TYPE_IVEC4:
case ShaderLanguage::TYPE_UVEC2:
+ case ShaderLanguage::TYPE_IVEC2: {
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR2I;
+ }
+ } break;
case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_UVEC4: {
- pi.type = Variant::PACKED_INT32_ARRAY;
+ case ShaderLanguage::TYPE_IVEC3: {
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR3I;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC4:
+ case ShaderLanguage::TYPE_IVEC4: {
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR4I;
+ }
} break;
case ShaderLanguage::TYPE_FLOAT: {
if (p_uniform.array_size > 0) {
@@ -3945,7 +4021,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
pi.type = Variant::COLOR;
} else {
- pi.type = Variant::QUATERNION;
+ pi.type = Variant::VECTOR4;
}
}
} break;
@@ -3967,7 +4043,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_FLOAT32_ARRAY;
} else {
- pi.type = Variant::TRANSFORM3D;
+ pi.type = Variant::PROJECTION;
}
break;
case ShaderLanguage::TYPE_SAMPLER2D:
@@ -7086,9 +7162,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!n) {
return ERR_PARSE_ERROR;
}
- if (n->get_datatype() != TYPE_INT) {
- _set_error(RTR("Expected an integer expression."));
- return ERR_PARSE_ERROR;
+ {
+ const ShaderLanguage::DataType switch_type = n->get_datatype();
+ if (switch_type != TYPE_INT && switch_type != TYPE_UINT) {
+ _set_error(RTR("Expected an integer expression."));
+ return ERR_PARSE_ERROR;
+ }
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
@@ -7678,34 +7757,38 @@ Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_preci
}
Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types) {
- Token tk = _get_token();
+ Token tk;
TkPos prev_pos;
Token next;
- if (tk.type != TK_SHADER_TYPE) {
- _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
- return ERR_PARSE_ERROR;
- }
+ if (!is_shader_inc) {
+ tk = _get_token();
+
+ if (tk.type != TK_SHADER_TYPE) {
+ _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
+ return ERR_PARSE_ERROR;
+ }
#ifdef DEBUG_ENABLED
- keyword_completion_context = CF_UNSPECIFIED;
+ keyword_completion_context = CF_UNSPECIFIED;
#endif // DEBUG_ENABLED
- _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier);
- if (shader_type_identifier == StringName()) {
- _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
- return ERR_PARSE_ERROR;
- }
- if (!p_shader_types.has(shader_type_identifier)) {
- _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types)));
- return ERR_PARSE_ERROR;
- }
- prev_pos = _get_tkpos();
- tk = _get_token();
+ _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier);
+ if (shader_type_identifier == StringName()) {
+ _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
+ return ERR_PARSE_ERROR;
+ }
+ if (!p_shader_types.has(shader_type_identifier)) {
+ _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types)));
+ return ERR_PARSE_ERROR;
+ }
+ prev_pos = _get_tkpos();
+ tk = _get_token();
- if (tk.type != TK_SEMICOLON) {
- _set_tkpos(prev_pos);
- _set_expected_after_error(";", "shader_type " + String(shader_type_identifier));
- return ERR_PARSE_ERROR;
+ if (tk.type != TK_SEMICOLON) {
+ _set_tkpos(prev_pos);
+ _set_expected_after_error(";", "shader_type " + String(shader_type_identifier));
+ return ERR_PARSE_ERROR;
+ }
}
#ifdef DEBUG_ENABLED
@@ -7760,25 +7843,54 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
bool found = false;
- for (int i = 0; i < p_render_modes.size(); i++) {
- const ModeInfo &info = p_render_modes[i];
- const String name = String(info.name);
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
- if (smode.begins_with(name)) {
- if (!info.options.is_empty()) {
- if (info.options.has(smode.substr(name.length() + 1))) {
- found = true;
+ for (int j = 0; j < modes.size(); j++) {
+ const ModeInfo &info = modes[j];
+ const String name = String(info.name);
- if (defined_modes.has(name)) {
- _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
- return ERR_PARSE_ERROR;
+ if (smode.begins_with(name)) {
+ if (!info.options.is_empty()) {
+ if (info.options.has(smode.substr(name.length() + 1))) {
+ found = true;
+
+ if (defined_modes.has(name)) {
+ _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
+ return ERR_PARSE_ERROR;
+ }
+ defined_modes.insert(name, smode);
+ break;
+ }
+ } else {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < p_render_modes.size(); i++) {
+ const ModeInfo &info = p_render_modes[i];
+ const String name = String(info.name);
+
+ if (smode.begins_with(name)) {
+ if (!info.options.is_empty()) {
+ if (info.options.has(smode.substr(name.length() + 1))) {
+ found = true;
+
+ if (defined_modes.has(name)) {
+ _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
+ return ERR_PARSE_ERROR;
+ }
+ defined_modes.insert(name, smode);
+ break;
}
- defined_modes.insert(name, smode);
+ } else {
+ found = true;
break;
}
- } else {
- found = true;
- break;
}
}
}
@@ -8177,7 +8289,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (is_uniform) {
if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL && Engine::get_singleton()->is_editor_hint()) { // Type checking for global uniforms is not allowed outside the editor.
//validate global uniform
- DataType gvtype = global_var_get_type_func(name);
+ DataType gvtype = global_shader_uniform_get_type_func(name);
if (gvtype == TYPE_MAX) {
_set_error(vformat(RTR("Global uniform '%s' does not exist. Create it in Project Settings."), String(name)));
return ERR_PARSE_ERROR;
@@ -8194,6 +8306,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
uniform.scope = uniform_scope;
uniform.precision = precision;
uniform.array_size = array_size;
+ uniform.group = current_uniform_group_name;
+ uniform.subgroup = current_uniform_subgroup_name;
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
@@ -8308,6 +8422,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
case TK_HINT_DEFAULT_WHITE_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_DEFAULT_WHITE;
} break;
+ case TK_HINT_DEFAULT_TRANSPARENT_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT;
+ } break;
case TK_HINT_NORMAL_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_NORMAL;
} break;
@@ -8620,6 +8737,45 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
}
} break;
+ case TK_UNIFORM_GROUP: {
+ tk = _get_token();
+ if (tk.type == TK_IDENTIFIER) {
+ current_uniform_group_name = tk.text;
+ tk = _get_token();
+ if (tk.type == TK_PERIOD) {
+ tk = _get_token();
+ if (tk.type == TK_IDENTIFIER) {
+ current_uniform_subgroup_name = tk.text;
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ _set_expected_error(";");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error(RTR("Expected an uniform subgroup identifier."));
+ return ERR_PARSE_ERROR;
+ }
+ } else if (tk.type != TK_SEMICOLON) {
+ _set_expected_error(";", ".");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ if (tk.type != TK_SEMICOLON) {
+ if (current_uniform_group_name.is_empty()) {
+ _set_error(RTR("Expected an uniform group identifier."));
+ } else {
+ _set_error(RTR("Expected an uniform group identifier or `;`."));
+ }
+ return ERR_PARSE_ERROR;
+ } else if (tk.type == TK_SEMICOLON && current_uniform_group_name.is_empty()) {
+ _set_error(RTR("Group needs to be opened before."));
+ return ERR_PARSE_ERROR;
+ } else {
+ current_uniform_group_name = "";
+ current_uniform_subgroup_name = "";
+ }
+ }
+ } break;
case TK_SHADER_TYPE: {
_set_error(RTR("Shader type is already defined."));
return ERR_PARSE_ERROR;
@@ -9508,9 +9664,11 @@ uint32_t ShaderLanguage::get_warning_flags() const {
Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_info) {
clear();
+ is_shader_inc = p_info.is_include;
code = p_code;
- global_var_get_type_func = p_info.global_variable_type_func;
+ global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func;
+
varying_function_names = p_info.varying_function_names;
nodes = nullptr;
@@ -9532,12 +9690,13 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i
Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint) {
clear();
+ is_shader_inc = p_info.is_include;
code = p_code;
varying_function_names = p_info.varying_function_names;
nodes = nullptr;
- global_var_get_type_func = p_info.global_variable_type_func;
+ global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func;
shader = alloc_node<ShaderNode>();
_parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
@@ -9577,30 +9736,64 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
return OK;
} break;
case COMPLETION_RENDER_MODE: {
- for (int i = 0; i < p_info.render_modes.size(); i++) {
- const ModeInfo &info = p_info.render_modes[i];
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
- if (!info.options.is_empty()) {
- bool found = false;
+ for (int j = 0; j < modes.size(); j++) {
+ const ModeInfo &info = modes[j];
- for (int j = 0; j < info.options.size(); j++) {
- if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
- found = true;
+ if (!info.options.is_empty()) {
+ bool found = false;
+
+ for (int k = 0; k < info.options.size(); k++) {
+ if (shader->render_modes.has(String(info.name) + "_" + String(info.options[k]))) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ for (int k = 0; k < info.options.size(); k++) {
+ ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[k]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ } else {
+ const String name = String(info.name);
+
+ if (!shader->render_modes.has(name)) {
+ ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
}
}
+ }
+ } else {
+ for (int i = 0; i < p_info.render_modes.size(); i++) {
+ const ModeInfo &info = p_info.render_modes[i];
+
+ if (!info.options.is_empty()) {
+ bool found = false;
- if (!found) {
for (int j = 0; j < info.options.size(); j++) {
- ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
- r_options->push_back(option);
+ if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
+ found = true;
+ }
}
- }
- } else {
- const String name = String(info.name);
- if (!shader->render_modes.has(name)) {
- ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
- r_options->push_back(option);
+ if (!found) {
+ for (int j = 0; j < info.options.size(); j++) {
+ ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ } else {
+ const String name = String(info.name);
+
+ if (!shader->render_modes.has(name)) {
+ ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
}
}
}
@@ -9668,33 +9861,69 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
}
if (comp_ident) {
- if (p_info.functions.has("global")) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
- ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
- if (E.value.constant) {
- kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ const HashMap<StringName, ShaderLanguage::FunctionInfo> info = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i));
+
+ if (info.has("global")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : info["global"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
+ if (info.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : info["constants"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
+ if (skip_function != StringName() && info.has(skip_function)) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : info[skip_function].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+ }
+ } else {
+ if (p_info.functions.has("global")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
}
- matches.insert(E.key, kind);
}
- }
- if (p_info.functions.has("constants")) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
- ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
- if (E.value.constant) {
- kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ if (p_info.functions.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
}
- matches.insert(E.key, kind);
}
- }
- if (skip_function != StringName() && p_info.functions.has(skip_function)) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
- ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
- if (E.value.constant) {
- kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ if (skip_function != StringName() && p_info.functions.has(skip_function)) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
}
- matches.insert(E.key, kind);
}
}
@@ -10034,6 +10263,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
options.push_back("hint_anisotropy");
options.push_back("hint_default_black");
options.push_back("hint_default_white");
+ options.push_back("hint_default_transparent");
options.push_back("hint_normal");
options.push_back("hint_roughness_a");
options.push_back("hint_roughness_b");
@@ -10066,6 +10296,10 @@ String ShaderLanguage::get_error_text() {
return error_str;
}
+Vector<ShaderLanguage::FilePosition> ShaderLanguage::get_include_positions() {
+ return include_positions;
+}
+
int ShaderLanguage::get_error_line() {
return error_line;
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 2b147fbeb1..bfec6e1df6 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -38,6 +38,7 @@
#include "core/templates/rb_map.h"
#include "core/typedefs.h"
#include "core/variant/variant.h"
+#include "scene/resources/shader_include.h"
#ifdef DEBUG_ENABLED
#include "shader_warnings.h"
@@ -153,6 +154,7 @@ public:
TK_SEMICOLON,
TK_PERIOD,
TK_UNIFORM,
+ TK_UNIFORM_GROUP,
TK_INSTANCE,
TK_GLOBAL,
TK_VARYING,
@@ -162,6 +164,7 @@ public:
TK_RENDER_MODE,
TK_HINT_DEFAULT_WHITE_TEXTURE,
TK_HINT_DEFAULT_BLACK_TEXTURE,
+ TK_HINT_DEFAULT_TRANSPARENT_TEXTURE,
TK_HINT_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_R,
@@ -662,6 +665,7 @@ public:
HINT_ROUGHNESS_GRAY,
HINT_DEFAULT_BLACK,
HINT_DEFAULT_WHITE,
+ HINT_DEFAULT_TRANSPARENT,
HINT_ANISOTROPY,
HINT_MAX
};
@@ -686,6 +690,8 @@ public:
TextureRepeat repeat = REPEAT_DEFAULT;
float hint_range[3];
int instance_index = 0;
+ String group;
+ String subgroup;
Uniform() {
hint_range[0] = 0.0f;
@@ -865,7 +871,12 @@ public:
};
static bool has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name);
- typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name);
+ typedef DataType (*GlobalShaderUniformGetTypeFunc)(const StringName &p_name);
+
+ struct FilePosition {
+ String file;
+ int line = 0;
+ };
private:
struct KeyWord {
@@ -878,12 +889,14 @@ private:
static const KeyWord keyword_list[];
- GlobalVariableGetTypeFunc global_var_get_type_func = nullptr;
+ GlobalShaderUniformGetTypeFunc global_shader_uniform_get_type_func = nullptr;
bool error_set = false;
String error_str;
int error_line = 0;
+ Vector<FilePosition> include_positions;
+
#ifdef DEBUG_ENABLED
struct Usage {
int decl_line;
@@ -928,6 +941,10 @@ private:
StringName current_function;
bool last_const = false;
StringName last_name;
+ bool is_shader_inc = false;
+
+ String current_uniform_group_name;
+ String current_uniform_subgroup_name;
VaryingFunctionNames varying_function_names;
@@ -951,6 +968,7 @@ private:
error_line = tk_line;
error_set = true;
error_str = p_str;
+ include_positions.write[include_positions.size() - 1].line = tk_line;
}
void _set_expected_error(const String &p_what) {
@@ -1097,13 +1115,15 @@ public:
Vector<ModeInfo> render_modes;
VaryingFunctionNames varying_function_names = VaryingFunctionNames();
HashSet<String> shader_types;
- GlobalVariableGetTypeFunc global_variable_type_func = nullptr;
+ GlobalShaderUniformGetTypeFunc global_shader_uniform_type_func = nullptr;
+ bool is_include = false;
};
Error compile(const String &p_code, const ShaderCompileInfo &p_info);
Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint);
String get_error_text();
+ Vector<FilePosition> get_include_positions();
int get_error_line();
ShaderNode *get_shader();
diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp
new file mode 100644
index 0000000000..a7b274b3e2
--- /dev/null
+++ b/servers/rendering/shader_preprocessor.cpp
@@ -0,0 +1,1048 @@
+/*************************************************************************/
+/* shader_preprocessor.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 "shader_preprocessor.h"
+#include "core/math/expression.h"
+
+const char32_t CURSOR = 0xFFFF;
+
+// Tokenizer
+
+void ShaderPreprocessor::Tokenizer::add_generated(const ShaderPreprocessor::Token &p_t) {
+ generated.push_back(p_t);
+}
+
+char32_t ShaderPreprocessor::Tokenizer::next() {
+ if (index < size) {
+ return code[index++];
+ }
+ return 0;
+}
+
+int ShaderPreprocessor::Tokenizer::get_line() const {
+ return line;
+}
+
+int ShaderPreprocessor::Tokenizer::get_index() const {
+ return index;
+}
+
+void ShaderPreprocessor::Tokenizer::get_and_clear_generated(Vector<ShaderPreprocessor::Token> *r_out) {
+ for (int i = 0; i < generated.size(); i++) {
+ r_out->push_back(generated[i]);
+ }
+ generated.clear();
+}
+
+void ShaderPreprocessor::Tokenizer::backtrack(char32_t p_what) {
+ while (index >= 0) {
+ char32_t c = code[index];
+ if (c == p_what) {
+ break;
+ }
+ index--;
+ }
+}
+
+char32_t ShaderPreprocessor::Tokenizer::peek() {
+ if (index < size) {
+ return code[index];
+ }
+ return 0;
+}
+
+LocalVector<ShaderPreprocessor::Token> ShaderPreprocessor::Tokenizer::advance(char32_t p_what) {
+ LocalVector<ShaderPreprocessor::Token> tokens;
+
+ while (index < size) {
+ char32_t c = code[index++];
+
+ tokens.push_back(ShaderPreprocessor::Token(c, line));
+
+ if (c == '\n') {
+ add_generated(ShaderPreprocessor::Token('\n', line));
+ line++;
+ }
+
+ if (c == p_what || c == 0) {
+ return tokens;
+ }
+ }
+ return LocalVector<ShaderPreprocessor::Token>();
+}
+
+void ShaderPreprocessor::Tokenizer::skip_whitespace() {
+ while (is_char_space(peek())) {
+ next();
+ }
+}
+
+String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_started) {
+ if (r_is_cursor != nullptr) {
+ *r_is_cursor = false;
+ }
+
+ LocalVector<char32_t> text;
+
+ while (true) {
+ char32_t c = peek();
+ if (is_char_end(c) || c == '(' || c == ')' || c == ',' || c == ';') {
+ break;
+ }
+
+ if (is_whitespace(c) && p_started) {
+ break;
+ }
+ if (!is_whitespace(c)) {
+ p_started = true;
+ }
+
+ char32_t n = next();
+ if (n == CURSOR) {
+ if (r_is_cursor != nullptr) {
+ *r_is_cursor = true;
+ }
+ } else {
+ if (p_started) {
+ text.push_back(n);
+ }
+ }
+ }
+
+ String id = vector_to_string(text);
+ if (!id.is_valid_identifier()) {
+ return "";
+ }
+
+ return id;
+}
+
+String ShaderPreprocessor::Tokenizer::peek_identifier() {
+ const int original = index;
+ String id = get_identifier();
+ index = original;
+ return id;
+}
+
+ShaderPreprocessor::Token ShaderPreprocessor::Tokenizer::get_token() {
+ while (index < size) {
+ const char32_t c = code[index++];
+ const Token t = ShaderPreprocessor::Token(c, line);
+
+ switch (c) {
+ case ' ':
+ case '\t':
+ skip_whitespace();
+ return ShaderPreprocessor::Token(' ', line);
+ case '\n':
+ line++;
+ return t;
+ default:
+ return t;
+ }
+ }
+ return ShaderPreprocessor::Token(char32_t(0), line);
+}
+
+ShaderPreprocessor::Tokenizer::Tokenizer(const String &p_code) {
+ code = p_code;
+ line = 0;
+ index = 0;
+ size = code.size();
+}
+
+// ShaderPreprocessor::CommentRemover
+
+String ShaderPreprocessor::CommentRemover::get_error() const {
+ if (comments_open != 0) {
+ return "Block comment mismatch";
+ }
+ return "";
+}
+
+int ShaderPreprocessor::CommentRemover::get_error_line() const {
+ if (comments_open != 0) {
+ return comment_line_open;
+ }
+ return -1;
+}
+
+char32_t ShaderPreprocessor::CommentRemover::peek() const {
+ if (index < code.size()) {
+ return code[index];
+ }
+ return 0;
+}
+
+bool ShaderPreprocessor::CommentRemover::advance(char32_t p_what) {
+ while (index < code.size()) {
+ char32_t c = code[index++];
+
+ if (c == '\n') {
+ line++;
+ stripped.push_back('\n');
+ }
+
+ if (c == p_what) {
+ return true;
+ }
+ }
+ return false;
+}
+
+String ShaderPreprocessor::CommentRemover::strip() {
+ stripped.clear();
+ index = 0;
+ line = 0;
+ comment_line_open = 0;
+ comments_open = 0;
+ strings_open = 0;
+
+ while (index < code.size()) {
+ char32_t c = code[index++];
+
+ if (c == CURSOR) {
+ // Cursor. Maintain.
+ stripped.push_back(c);
+ } else if (c == '"') {
+ if (strings_open <= 0) {
+ strings_open++;
+ } else {
+ strings_open--;
+ }
+ stripped.push_back(c);
+ } else if (c == '/' && strings_open == 0) {
+ char32_t p = peek();
+ if (p == '/') { // Single line comment.
+ advance('\n');
+ } else if (p == '*') { // Start of a block comment.
+ index++;
+ comment_line_open = line;
+ comments_open++;
+ while (advance('*')) {
+ if (peek() == '/') { // End of a block comment.
+ comments_open--;
+ index++;
+ break;
+ }
+ }
+ } else {
+ stripped.push_back(c);
+ }
+ } else if (c == '*' && strings_open == 0) {
+ if (peek() == '/') { // Unmatched end of a block comment.
+ comment_line_open = line;
+ comments_open--;
+ } else {
+ stripped.push_back(c);
+ }
+ } else if (c == '\n') {
+ line++;
+ stripped.push_back(c);
+ } else {
+ stripped.push_back(c);
+ }
+ }
+ return vector_to_string(stripped);
+}
+
+ShaderPreprocessor::CommentRemover::CommentRemover(const String &p_code) {
+ code = p_code;
+ index = 0;
+ line = 0;
+ comment_line_open = 0;
+ comments_open = 0;
+ strings_open = 0;
+}
+
+// ShaderPreprocessor::Token
+
+ShaderPreprocessor::Token::Token() {
+ text = 0;
+ line = -1;
+}
+
+ShaderPreprocessor::Token::Token(char32_t p_text, int p_line) {
+ text = p_text;
+ line = p_line;
+}
+
+// ShaderPreprocessor
+
+bool ShaderPreprocessor::is_char_word(char32_t p_char) {
+ if ((p_char >= '0' && p_char <= '9') ||
+ (p_char >= 'a' && p_char <= 'z') ||
+ (p_char >= 'A' && p_char <= 'Z') ||
+ p_char == '_') {
+ return true;
+ }
+
+ return false;
+}
+
+bool ShaderPreprocessor::is_char_space(char32_t p_char) {
+ return p_char == ' ' || p_char == '\t';
+}
+
+bool ShaderPreprocessor::is_char_end(char32_t p_char) {
+ return p_char == '\n' || p_char == 0;
+}
+
+String ShaderPreprocessor::vector_to_string(const LocalVector<char32_t> &p_v, int p_start, int p_end) {
+ const int stop = (p_end == -1) ? p_v.size() : p_end;
+ const int count = stop - p_start;
+
+ String result;
+ result.resize(count + 1);
+ for (int i = 0; i < count; i++) {
+ result[i] = p_v[p_start + i];
+ }
+ result[count] = 0; // Ensure string is null terminated for length() to work.
+ return result;
+}
+
+String ShaderPreprocessor::tokens_to_string(const LocalVector<Token> &p_tokens) {
+ LocalVector<char32_t> result;
+ for (uint32_t i = 0; i < p_tokens.size(); i++) {
+ result.push_back(p_tokens[i].text);
+ }
+ return vector_to_string(result);
+}
+
+void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) {
+ bool is_cursor;
+ String directive = p_tokenizer->get_identifier(&is_cursor, true);
+ if (is_cursor) {
+ state->completion_type = COMPLETION_TYPE_DIRECTIVE;
+ }
+
+ if (directive == "if") {
+ process_if(p_tokenizer);
+ } else if (directive == "ifdef") {
+ process_ifdef(p_tokenizer);
+ } else if (directive == "ifndef") {
+ process_ifndef(p_tokenizer);
+ } else if (directive == "else") {
+ process_else(p_tokenizer);
+ } else if (directive == "endif") {
+ process_endif(p_tokenizer);
+ } else if (directive == "define") {
+ process_define(p_tokenizer);
+ } else if (directive == "undef") {
+ process_undef(p_tokenizer);
+ } else if (directive == "include") {
+ process_include(p_tokenizer);
+ } else if (directive == "pragma") {
+ process_pragma(p_tokenizer);
+ } else {
+ set_error(RTR("Unknown directive."), p_tokenizer->get_line());
+ }
+}
+
+void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String label = p_tokenizer->get_identifier();
+ if (label.is_empty()) {
+ set_error(RTR("Invalid macro name."), line);
+ return;
+ }
+
+ if (state->defines.has(label)) {
+ set_error(RTR("Macro redefinition."), line);
+ return;
+ }
+
+ if (p_tokenizer->peek() == '(') {
+ // Macro has arguments.
+ p_tokenizer->get_token();
+
+ Vector<String> args;
+ while (true) {
+ String name = p_tokenizer->get_identifier();
+ if (name.is_empty()) {
+ set_error(RTR("Invalid argument name."), line);
+ return;
+ }
+ args.push_back(name);
+
+ p_tokenizer->skip_whitespace();
+ char32_t next = p_tokenizer->get_token().text;
+ if (next == ')') {
+ break;
+ } else if (next != ',') {
+ set_error(RTR("Expected a comma in the macro argument list."), line);
+ return;
+ }
+ }
+
+ Define *define = memnew(Define);
+ define->arguments = args;
+ define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ state->defines[label] = define;
+ } else {
+ // Simple substitution macro.
+ Define *define = memnew(Define);
+ define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ state->defines[label] = define;
+ }
+}
+
+void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
+ if (state->skip_stack_else.is_empty()) {
+ set_error(RTR("Unmatched else."), p_tokenizer->get_line());
+ return;
+ }
+ p_tokenizer->advance('\n');
+
+ bool skip = state->skip_stack_else[state->skip_stack_else.size() - 1];
+ state->skip_stack_else.remove_at(state->skip_stack_else.size() - 1);
+
+ Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_include];
+ int index = vec.size() - 1;
+ if (index >= 0) {
+ SkippedCondition *cond = vec[index];
+ if (cond->end_line == -1) {
+ cond->end_line = p_tokenizer->get_line();
+ }
+ }
+
+ if (skip) {
+ Vector<String> ends;
+ ends.push_back("endif");
+ next_directive(p_tokenizer, ends);
+ }
+}
+
+void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) {
+ state->condition_depth--;
+ if (state->condition_depth < 0) {
+ set_error(RTR("Unmatched endif."), p_tokenizer->get_line());
+ return;
+ }
+
+ Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_include];
+ int index = vec.size() - 1;
+ if (index >= 0) {
+ SkippedCondition *cond = vec[index];
+ if (cond->end_line == -1) {
+ cond->end_line = p_tokenizer->get_line();
+ }
+ }
+
+ p_tokenizer->advance('\n');
+}
+
+void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
+ int line = p_tokenizer->get_line();
+
+ String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ if (body.is_empty()) {
+ set_error(RTR("Missing condition."), line);
+ return;
+ }
+
+ Error error = expand_macros(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ Expression expression;
+ Vector<String> names;
+ error = expression.parse(body, names);
+ if (error != OK) {
+ set_error(expression.get_error_text(), line);
+ return;
+ }
+
+ Variant v = expression.execute(Array(), nullptr, false);
+ if (v.get_type() == Variant::NIL) {
+ set_error(RTR("Condition evaluation error."), line);
+ return;
+ }
+
+ bool success = v.booleanize();
+ start_branch_condition(p_tokenizer, success);
+}
+
+void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String label = p_tokenizer->get_identifier();
+ if (label.is_empty()) {
+ set_error(RTR("Invalid macro name."), line);
+ return;
+ }
+
+ p_tokenizer->skip_whitespace();
+ if (!is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid ifdef."), line);
+ return;
+ }
+ p_tokenizer->advance('\n');
+
+ bool success = state->defines.has(label);
+ start_branch_condition(p_tokenizer, success);
+}
+
+void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String label = p_tokenizer->get_identifier();
+ if (label.is_empty()) {
+ set_error(RTR("Invalid macro name."), line);
+ return;
+ }
+
+ p_tokenizer->skip_whitespace();
+ if (!is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid ifndef."), line);
+ return;
+ }
+ p_tokenizer->advance('\n');
+
+ bool success = !state->defines.has(label);
+ start_branch_condition(p_tokenizer, success);
+}
+
+void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ p_tokenizer->advance('"');
+ String path = tokens_to_string(p_tokenizer->advance('"'));
+ for (int i = 0; i < path.length(); i++) {
+ if (path[i] == '\n') {
+ break; //stop parsing
+ }
+ if (path[i] == CURSOR) {
+ state->completion_type = COMPLETION_TYPE_INCLUDE_PATH;
+ break;
+ }
+ }
+ path = path.substr(0, path.length() - 1);
+ p_tokenizer->skip_whitespace();
+
+ if (path.is_empty() || !is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid path."), line);
+ return;
+ }
+
+ Ref<Resource> res = ResourceLoader::load(path);
+ if (res.is_null()) {
+ set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line);
+ return;
+ }
+
+ Ref<ShaderInclude> shader_inc = res;
+ if (shader_inc.is_null()) {
+ set_error(RTR("Shader include resource type is wrong."), line);
+ return;
+ }
+
+ String included = shader_inc->get_code();
+ if (!included.is_empty()) {
+ uint64_t code_hash = included.hash64();
+ if (state->cyclic_include_hashes.find(code_hash)) {
+ set_error(RTR("Cyclic include found."), line);
+ return;
+ }
+ }
+
+ state->shader_includes.insert(shader_inc);
+
+ const String real_path = shader_inc->get_path();
+ if (state->includes.has(real_path)) {
+ // Already included, skip.
+ // This is a valid check because 2 separate include paths could use some
+ // of the same shared functions from a common shader include.
+ return;
+ }
+
+ // Mark as included.
+ state->includes.insert(real_path);
+
+ state->include_depth++;
+ if (state->include_depth > 25) {
+ set_error(RTR("Shader max include depth exceeded."), line);
+ return;
+ }
+
+ String old_include = state->current_include;
+ state->current_include = real_path;
+ ShaderPreprocessor processor;
+
+ int prev_condition_depth = state->condition_depth;
+ state->condition_depth = 0;
+
+ FilePosition fp;
+ fp.file = state->current_include;
+ fp.line = line;
+ state->include_positions.push_back(fp);
+
+ String result;
+ processor.preprocess(state, included, result);
+ add_to_output("@@>" + real_path + "\n"); // Add token for enter include path
+ add_to_output(result);
+ add_to_output("\n@@<\n"); // Add token for exit include path
+
+ // Reset to last include if there are no errors. We want to use this as context.
+ if (state->error.is_empty()) {
+ state->current_include = old_include;
+ state->include_positions.pop_back();
+ } else {
+ return;
+ }
+
+ state->include_depth--;
+ state->condition_depth = prev_condition_depth;
+}
+
+void ShaderPreprocessor::process_pragma(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ bool is_cursor;
+ const String label = p_tokenizer->get_identifier(&is_cursor);
+ if (is_cursor) {
+ state->completion_type = COMPLETION_TYPE_PRAGMA;
+ }
+
+ if (label.is_empty()) {
+ set_error(RTR("Invalid pragma directive."), line);
+ return;
+ }
+
+ // Rxplicitly handle pragma values here.
+ // If more pragma options are created, then refactor into a more defined structure.
+ if (label == "disable_preprocessor") {
+ state->disabled = true;
+ } else {
+ set_error(RTR("Invalid pragma directive."), line);
+ return;
+ }
+
+ p_tokenizer->advance('\n');
+}
+
+void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+ const String label = p_tokenizer->get_identifier();
+ if (label.is_empty() || !state->defines.has(label)) {
+ set_error(RTR("Invalid name."), line);
+ return;
+ }
+
+ p_tokenizer->skip_whitespace();
+ if (!is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid undef."), line);
+ return;
+ }
+
+ memdelete(state->defines[label]);
+ state->defines.erase(label);
+}
+
+void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success) {
+ state->condition_depth++;
+
+ if (p_success) {
+ state->skip_stack_else.push_back(true);
+ } else {
+ SkippedCondition *cond = memnew(SkippedCondition());
+ cond->start_line = p_tokenizer->get_line();
+ state->skipped_conditions[state->current_include].push_back(cond);
+
+ Vector<String> ends;
+ ends.push_back("else");
+ ends.push_back("endif");
+ if (next_directive(p_tokenizer, ends) == "else") {
+ state->skip_stack_else.push_back(false);
+ } else {
+ state->skip_stack_else.push_back(true);
+ }
+ }
+}
+
+void ShaderPreprocessor::expand_output_macros(int p_start, int p_line_number) {
+ String line = vector_to_string(output, p_start, output.size());
+
+ Error error = expand_macros(line, p_line_number - 1, line); // We are already on next line, so -1.
+ if (error != OK) {
+ return;
+ }
+
+ output.resize(p_start);
+
+ add_to_output(line);
+}
+
+Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) {
+ Vector<Pair<String, Define *>> active_defines;
+ active_defines.resize(state->defines.size());
+ int index = 0;
+ for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
+ active_defines.set(index++, Pair<String, Define *>(E->key(), E->get()));
+ }
+
+ return expand_macros(p_string, p_line, active_defines, r_expanded);
+}
+
+Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_expanded) {
+ r_expanded = p_string;
+ // When expanding macros we must only evaluate them once.
+ // Later we continue expanding but with the already
+ // evaluated macros removed.
+ for (int i = 0; i < p_defines.size(); i++) {
+ Pair<String, Define *> define_pair = p_defines[i];
+
+ Error error = expand_macros_once(r_expanded, p_line, define_pair, r_expanded);
+ if (error != OK) {
+ return error;
+ }
+
+ // Remove expanded macro and recursively replace remaining.
+ p_defines.remove_at(i);
+ return expand_macros(r_expanded, p_line, p_defines, r_expanded);
+ }
+
+ return OK;
+}
+
+Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded) {
+ String result = p_line;
+
+ const String &key = p_define_pair.first;
+ const Define *define = p_define_pair.second;
+
+ int index_start = 0;
+ int index = 0;
+ while (find_match(result, key, index, index_start)) {
+ String body = define->body;
+ if (define->arguments.size() > 0) {
+ // Complex macro with arguments.
+ int args_start = index + key.length();
+ int args_end = p_line.find(")", args_start);
+ if (args_start == -1 || args_end == -1) {
+ set_error(RTR("Missing macro argument parenthesis."), p_line_number);
+ return FAILED;
+ }
+
+ String values = result.substr(args_start + 1, args_end - (args_start + 1));
+ Vector<String> args = values.split(",");
+ if (args.size() != define->arguments.size()) {
+ set_error(RTR("Invalid macro argument count."), p_line_number);
+ return FAILED;
+ }
+
+ // Insert macro arguments into the body.
+ for (int i = 0; i < args.size(); i++) {
+ String arg_name = define->arguments[i];
+ int arg_index_start = 0;
+ int arg_index = 0;
+ while (find_match(body, arg_name, arg_index, arg_index_start)) {
+ body = body.substr(0, arg_index) + args[i] + body.substr(arg_index + arg_name.length(), body.length() - (arg_index + arg_name.length()));
+ // Manually reset arg_index_start to where the arg value of the define finishes.
+ // This ensures we don't skip the other args of this macro in the string.
+ arg_index_start = arg_index + args[i].length() + 1;
+ }
+ }
+
+ result = result.substr(0, index) + " " + body + " " + result.substr(args_end + 1, result.length());
+ } else {
+ result = result.substr(0, index) + body + result.substr(index + key.length(), result.length() - (index + key.length()));
+ // Manually reset index_start to where the body value of the define finishes.
+ // This ensures we don't skip another instance of this macro in the string.
+ index_start = index + body.length() + 1;
+ break;
+ }
+ }
+ r_expanded = result;
+ return OK;
+}
+
+bool ShaderPreprocessor::find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start) {
+ // Looks for value in string and then determines if the boundaries
+ // are non-word characters. This method semi-emulates \b in regex.
+ r_index = p_string.find(p_value, r_index_start);
+ while (r_index > -1) {
+ if (r_index > 0) {
+ if (is_char_word(p_string[r_index - 1])) {
+ r_index_start = r_index + 1;
+ r_index = p_string.find(p_value, r_index_start);
+ continue;
+ }
+ }
+
+ if (r_index + p_value.length() < p_string.length()) {
+ if (is_char_word(p_string[r_index + p_value.length()])) {
+ r_index_start = r_index + p_value.length() + 1;
+ r_index = p_string.find(p_value, r_index_start);
+ continue;
+ }
+ }
+
+ // Return and shift index start automatically for next call.
+ r_index_start = r_index + p_value.length() + 1;
+ return true;
+ }
+
+ return false;
+}
+
+String ShaderPreprocessor::next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives) {
+ const int line = p_tokenizer->get_line();
+ int nesting = 0;
+
+ while (true) {
+ p_tokenizer->advance('#');
+
+ String id = p_tokenizer->peek_identifier();
+ if (id.is_empty()) {
+ break;
+ }
+
+ if (nesting == 0) {
+ for (int i = 0; i < p_directives.size(); i++) {
+ if (p_directives[i] == id) {
+ p_tokenizer->backtrack('#');
+ return id;
+ }
+ }
+ }
+
+ if (id == "ifdef" || id == "ifndef" || id == "if") {
+ nesting++;
+ } else if (id == "endif") {
+ nesting--;
+ }
+ }
+
+ set_error(RTR("Can't find matching branch directive."), line);
+ return "";
+}
+
+void ShaderPreprocessor::add_to_output(const String &p_str) {
+ for (int i = 0; i < p_str.length(); i++) {
+ output.push_back(p_str[i]);
+ }
+}
+
+void ShaderPreprocessor::set_error(const String &p_error, int p_line) {
+ if (state->error.is_empty()) {
+ state->error = p_error;
+ FilePosition fp;
+ fp.line = p_line + 1;
+ state->include_positions.push_back(fp);
+ }
+}
+
+ShaderPreprocessor::Define *ShaderPreprocessor::create_define(const String &p_body) {
+ ShaderPreprocessor::Define *define = memnew(Define);
+ define->body = p_body;
+ return define;
+}
+
+void ShaderPreprocessor::clear() {
+ if (state_owner && state != nullptr) {
+ for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
+ memdelete(E->get());
+ }
+
+ for (const RBMap<String, Vector<SkippedCondition *>>::Element *E = state->skipped_conditions.front(); E; E = E->next()) {
+ for (SkippedCondition *condition : E->get()) {
+ memdelete(condition);
+ }
+ }
+
+ memdelete(state);
+ }
+ state_owner = false;
+ state = nullptr;
+}
+
+Error ShaderPreprocessor::preprocess(State *p_state, const String &p_code, String &r_result) {
+ clear();
+
+ output.clear();
+
+ state = p_state;
+
+ CommentRemover remover(p_code);
+ String stripped = remover.strip();
+ String error = remover.get_error();
+ if (!error.is_empty()) {
+ set_error(error, remover.get_error_line());
+ return FAILED;
+ }
+
+ // Track code hashes to prevent cyclic include.
+ uint64_t code_hash = p_code.hash64();
+ state->cyclic_include_hashes.push_back(code_hash);
+
+ Tokenizer p_tokenizer(stripped);
+ int last_size = 0;
+ bool has_symbols_before_directive = false;
+
+ while (true) {
+ const Token &t = p_tokenizer.get_token();
+
+ if (t.text == 0) {
+ break;
+ }
+
+ if (state->disabled) {
+ // Preprocessor was disabled.
+ // Read the rest of the file into the output.
+ output.push_back(t.text);
+ continue;
+ } else {
+ // Add autogenerated tokens.
+ Vector<Token> generated;
+ p_tokenizer.get_and_clear_generated(&generated);
+ for (int i = 0; i < generated.size(); i++) {
+ output.push_back(generated[i].text);
+ }
+ }
+
+ if (t.text == '#') {
+ if (has_symbols_before_directive) {
+ set_error(RTR("Invalid symbols placed before directive."), p_tokenizer.get_line());
+ state->cyclic_include_hashes.erase(code_hash); // Remove this hash.
+ return FAILED;
+ }
+ process_directive(&p_tokenizer);
+ } else {
+ if (is_char_end(t.text)) {
+ expand_output_macros(last_size, p_tokenizer.get_line());
+ last_size = output.size();
+ has_symbols_before_directive = false;
+ } else if (!is_char_space(t.text)) {
+ has_symbols_before_directive = true;
+ }
+ output.push_back(t.text);
+ }
+
+ if (!state->error.is_empty()) {
+ state->cyclic_include_hashes.erase(code_hash); // Remove this hash.
+ return FAILED;
+ }
+ }
+ state->cyclic_include_hashes.erase(code_hash); // Remove this hash.
+
+ if (!state->disabled) {
+ if (state->condition_depth != 0) {
+ set_error(RTR("Unmatched conditional statement."), p_tokenizer.line);
+ return FAILED;
+ }
+
+ expand_output_macros(last_size, p_tokenizer.get_line());
+ }
+
+ r_result = vector_to_string(output);
+
+ return OK;
+}
+
+Error ShaderPreprocessor::preprocess(const String &p_code, String &r_result, String *r_error_text, List<FilePosition> *r_error_position, HashSet<Ref<ShaderInclude>> *r_includes, List<ScriptLanguage::CodeCompletionOption> *r_completion_options, IncludeCompletionFunction p_include_completion_func) {
+ State pp_state;
+ Error err = preprocess(&pp_state, p_code, r_result);
+ if (err != OK) {
+ if (r_error_text) {
+ *r_error_text = pp_state.error;
+ }
+ if (r_error_position) {
+ *r_error_position = pp_state.include_positions;
+ }
+ }
+ if (r_includes) {
+ *r_includes = pp_state.shader_includes;
+ }
+
+ if (r_completion_options) {
+ switch (pp_state.completion_type) {
+ case COMPLETION_TYPE_DIRECTIVE: {
+ List<String> options;
+ get_keyword_list(&options, true);
+
+ for (const String &E : options) {
+ ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_completion_options->push_back(option);
+ }
+
+ } break;
+ case COMPLETION_TYPE_PRAGMA: {
+ List<String> options;
+
+ ShaderPreprocessor::get_pragma_list(&options);
+
+ for (const String &E : options) {
+ ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_completion_options->push_back(option);
+ }
+
+ } break;
+ case COMPLETION_TYPE_INCLUDE_PATH: {
+ if (p_include_completion_func && r_completion_options) {
+ p_include_completion_func(r_completion_options);
+ }
+
+ } break;
+ default: {
+ }
+ }
+ }
+ return err;
+}
+
+void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords) {
+ r_keywords->push_back("define");
+ if (p_include_shader_keywords) {
+ r_keywords->push_back("else");
+ }
+ r_keywords->push_back("endif");
+ if (p_include_shader_keywords) {
+ r_keywords->push_back("if");
+ }
+ r_keywords->push_back("ifdef");
+ r_keywords->push_back("ifndef");
+ r_keywords->push_back("include");
+ r_keywords->push_back("pragma");
+ r_keywords->push_back("undef");
+}
+
+void ShaderPreprocessor::get_pragma_list(List<String> *r_pragmas) {
+ r_pragmas->push_back("disable_preprocessor");
+}
+
+ShaderPreprocessor::ShaderPreprocessor() {
+}
+
+ShaderPreprocessor::~ShaderPreprocessor() {
+ clear();
+}
diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h
new file mode 100644
index 0000000000..a93fb680dd
--- /dev/null
+++ b/servers/rendering/shader_preprocessor.h
@@ -0,0 +1,200 @@
+/*************************************************************************/
+/* shader_preprocessor.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 SHADER_PREPROCESSOR_H
+#define SHADER_PREPROCESSOR_H
+
+#include "core/string/ustring.h"
+#include "core/templates/list.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/rb_map.h"
+#include "core/templates/rb_set.h"
+#include "core/typedefs.h"
+
+#include "core/io/resource_loader.h"
+#include "core/os/os.h"
+#include "scene/resources/shader.h"
+#include "scene/resources/shader_include.h"
+
+class ShaderPreprocessor {
+public:
+ enum CompletionType {
+ COMPLETION_TYPE_NONE,
+ COMPLETION_TYPE_DIRECTIVE,
+ COMPLETION_TYPE_PRAGMA_DIRECTIVE,
+ COMPLETION_TYPE_PRAGMA,
+ COMPLETION_TYPE_INCLUDE_PATH,
+ };
+
+ struct FilePosition {
+ String file;
+ int line = 0;
+ };
+
+private:
+ struct Token {
+ char32_t text;
+ int line;
+
+ Token();
+ Token(char32_t p_text, int p_line);
+ };
+
+ // The real preprocessor that understands basic shader and preprocessor language syntax.
+ class Tokenizer {
+ public:
+ String code;
+ int line;
+ int index;
+ int size;
+ Vector<Token> generated;
+
+ private:
+ void add_generated(const Token &p_t);
+ char32_t next();
+
+ public:
+ int get_line() const;
+ int get_index() const;
+ char32_t peek();
+
+ void get_and_clear_generated(Vector<Token> *r_out);
+ void backtrack(char32_t p_what);
+ LocalVector<Token> advance(char32_t p_what);
+ void skip_whitespace();
+ String get_identifier(bool *r_is_cursor = nullptr, bool p_started = false);
+ String peek_identifier();
+ Token get_token();
+
+ Tokenizer(const String &p_code);
+ };
+
+ class CommentRemover {
+ private:
+ LocalVector<char32_t> stripped;
+ String code;
+ int index;
+ int line;
+ int comment_line_open;
+ int comments_open;
+ int strings_open;
+
+ public:
+ String get_error() const;
+ int get_error_line() const;
+ char32_t peek() const;
+
+ bool advance(char32_t p_what);
+ String strip();
+
+ CommentRemover(const String &p_code);
+ };
+
+ struct Define {
+ Vector<String> arguments;
+ String body;
+ };
+
+ struct SkippedCondition {
+ int start_line = -1;
+ int end_line = -1;
+ };
+
+ struct State {
+ RBMap<String, Define *> defines;
+ Vector<bool> skip_stack_else;
+ int condition_depth = 0;
+ RBSet<String> includes;
+ List<uint64_t> cyclic_include_hashes; // Holds code hash of includes.
+ int include_depth = 0;
+ String current_include;
+ String current_shader_type;
+ String error;
+ List<FilePosition> include_positions;
+ RBMap<String, Vector<SkippedCondition *>> skipped_conditions;
+ bool disabled = false;
+ CompletionType completion_type = COMPLETION_TYPE_NONE;
+ HashSet<Ref<ShaderInclude>> shader_includes;
+ };
+
+private:
+ LocalVector<char32_t> output;
+ State *state = nullptr;
+ bool state_owner = false;
+
+private:
+ static bool is_char_word(char32_t p_char);
+ static bool is_char_space(char32_t p_char);
+ static bool is_char_end(char32_t p_char);
+ static String vector_to_string(const LocalVector<char32_t> &p_v, int p_start = 0, int p_end = -1);
+ static String tokens_to_string(const LocalVector<Token> &p_tokens);
+
+ void process_directive(Tokenizer *p_tokenizer);
+ void process_define(Tokenizer *p_tokenizer);
+ void process_else(Tokenizer *p_tokenizer);
+ void process_endif(Tokenizer *p_tokenizer);
+ void process_if(Tokenizer *p_tokenizer);
+ void process_ifdef(Tokenizer *p_tokenizer);
+ void process_ifndef(Tokenizer *p_tokenizer);
+ void process_include(Tokenizer *p_tokenizer);
+ void process_pragma(Tokenizer *p_tokenizer);
+ void process_undef(Tokenizer *p_tokenizer);
+
+ void start_branch_condition(Tokenizer *p_tokenizer, bool p_success);
+
+ void expand_output_macros(int p_start, int p_line);
+ Error expand_macros(const String &p_string, int p_line, String &r_result);
+ Error expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_result);
+ Error expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded);
+ bool find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start);
+
+ String next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives);
+ void add_to_output(const String &p_str);
+ void set_error(const String &p_error, int p_line);
+
+ static Define *create_define(const String &p_body);
+
+ void clear();
+
+ Error preprocess(State *p_state, const String &p_code, String &r_result);
+
+public:
+ typedef void (*IncludeCompletionFunction)(List<ScriptLanguage::CodeCompletionOption> *);
+
+ Error preprocess(const String &p_code, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr);
+
+ static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords);
+ static void get_pragma_list(List<String> *r_pragmas);
+
+ ShaderPreprocessor();
+ ~ShaderPreprocessor();
+};
+
+#endif // SHADER_PREPROCESSOR_H
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 5772179d68..43c483a00d 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -97,6 +97,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3;
+
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
@@ -139,6 +144,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3;
+
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 107525cd15..dfec3a7111 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHADERTYPES_H
-#define SHADERTYPES_H
+#ifndef SHADER_TYPES_H
+#define SHADER_TYPES_H
#include "core/templates/rb_map.h"
#include "servers/rendering_server.h"
@@ -59,4 +59,4 @@ public:
ShaderTypes();
};
-#endif // SHADERTYPES_H
+#endif // SHADER_TYPES_H
diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h
index 8edf85842f..d5c6a4b1a6 100644
--- a/servers/rendering/shader_warnings.h
+++ b/servers/rendering/shader_warnings.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHADER_WARNINGS
-#define SHADER_WARNINGS
+#ifndef SHADER_WARNINGS_H
+#define SHADER_WARNINGS_H
#ifdef DEBUG_ENABLED
@@ -90,4 +90,4 @@ public:
#endif // DEBUG_ENABLED
-#endif // SHADER_WARNINGS
+#endif // SHADER_WARNINGS_H
diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp
new file mode 100644
index 0000000000..1d4dc55e98
--- /dev/null
+++ b/servers/rendering/storage/environment_storage.cpp
@@ -0,0 +1,769 @@
+/*************************************************************************/
+/* environment_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 "environment_storage.h"
+
+uint64_t RendererEnvironmentStorage::auto_exposure_counter = 2;
+
+RID RendererEnvironmentStorage::environment_allocate() {
+ return environment_owner.allocate_rid();
+}
+
+void RendererEnvironmentStorage::environment_initialize(RID p_rid) {
+ environment_owner.initialize_rid(p_rid, Environment());
+}
+
+void RendererEnvironmentStorage::environment_free(RID p_rid) {
+ environment_owner.free(p_rid);
+}
+
+// Background
+
+void RendererEnvironmentStorage::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->background = p_bg;
+}
+
+void RendererEnvironmentStorage::environment_set_sky(RID p_env, RID p_sky) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->sky = p_sky;
+}
+
+void RendererEnvironmentStorage::environment_set_sky_custom_fov(RID p_env, float p_scale) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->sky_custom_fov = p_scale;
+}
+
+void RendererEnvironmentStorage::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->sky_orientation = p_orientation;
+}
+
+void RendererEnvironmentStorage::environment_set_bg_color(RID p_env, const Color &p_color) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->bg_color = p_color;
+}
+
+void RendererEnvironmentStorage::environment_set_bg_energy(RID p_env, float p_energy) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->bg_energy = p_energy;
+}
+
+void RendererEnvironmentStorage::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->canvas_max_layer = p_max_layer;
+}
+
+void RendererEnvironmentStorage::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->ambient_light = p_color;
+ env->ambient_source = p_ambient;
+ env->ambient_light_energy = p_energy;
+ env->ambient_sky_contribution = p_sky_contribution;
+ env->reflection_source = p_reflection_source;
+}
+
+RS::EnvironmentBG RendererEnvironmentStorage::environment_get_background(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_BG_CLEAR_COLOR);
+ return env->background;
+}
+
+RID RendererEnvironmentStorage::environment_get_sky(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RID());
+ return env->sky;
+}
+
+float RendererEnvironmentStorage::environment_get_sky_custom_fov(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->sky_custom_fov;
+}
+
+Basis RendererEnvironmentStorage::environment_get_sky_orientation(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Basis());
+ return env->sky_orientation;
+}
+
+Color RendererEnvironmentStorage::environment_get_bg_color(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color());
+ return env->bg_color;
+}
+
+float RendererEnvironmentStorage::environment_get_bg_energy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->bg_energy;
+}
+
+int RendererEnvironmentStorage::environment_get_canvas_max_layer(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0);
+ return env->canvas_max_layer;
+}
+
+RS::EnvironmentAmbientSource RendererEnvironmentStorage::environment_get_ambient_source(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG);
+ return env->ambient_source;
+}
+
+Color RendererEnvironmentStorage::environment_get_ambient_light(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color());
+ return env->ambient_light;
+}
+
+float RendererEnvironmentStorage::environment_get_ambient_light_energy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ambient_light_energy;
+}
+
+float RendererEnvironmentStorage::environment_get_ambient_sky_contribution(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ambient_sky_contribution;
+}
+
+RS::EnvironmentReflectionSource RendererEnvironmentStorage::environment_get_reflection_source(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_BG);
+ return env->reflection_source;
+}
+
+// Tonemap
+
+void RendererEnvironmentStorage::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->exposure = p_exposure;
+ env->tone_mapper = p_tone_mapper;
+ if (!env->auto_exposure && p_auto_exposure) {
+ env->auto_exposure_version = ++auto_exposure_counter;
+ }
+ env->auto_exposure = p_auto_exposure;
+ env->white = p_white;
+ env->min_luminance = p_min_luminance;
+ env->max_luminance = p_max_luminance;
+ env->auto_exp_speed = p_auto_exp_speed;
+ env->auto_exp_scale = p_auto_exp_scale;
+}
+
+RS::EnvironmentToneMapper RendererEnvironmentStorage::environment_get_tone_mapper(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_TONE_MAPPER_LINEAR);
+ return env->tone_mapper;
+}
+
+float RendererEnvironmentStorage::environment_get_exposure(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->exposure;
+}
+
+float RendererEnvironmentStorage::environment_get_white(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->white;
+}
+
+bool RendererEnvironmentStorage::environment_get_auto_exposure(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->auto_exposure;
+}
+
+float RendererEnvironmentStorage::environment_get_min_luminance(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.2);
+ return env->min_luminance;
+}
+
+float RendererEnvironmentStorage::environment_get_max_luminance(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 8.0);
+ return env->max_luminance;
+}
+
+float RendererEnvironmentStorage::environment_get_auto_exp_speed(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.2);
+ return env->auto_exp_speed;
+}
+
+float RendererEnvironmentStorage::environment_get_auto_exp_scale(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.5);
+ return env->auto_exp_scale;
+}
+
+uint64_t RendererEnvironmentStorage::environment_get_auto_exposure_version(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0);
+ return env->auto_exposure_version;
+}
+
+// Fog
+
+void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->fog_enabled = p_enable;
+ env->fog_light_color = p_light_color;
+ env->fog_light_energy = p_light_energy;
+ env->fog_sun_scatter = p_sun_scatter;
+ env->fog_density = p_density;
+ env->fog_height = p_height;
+ env->fog_height_density = p_height_density;
+ env->fog_aerial_perspective = p_fog_aerial_perspective;
+}
+
+bool RendererEnvironmentStorage::environment_get_fog_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->fog_enabled;
+}
+
+Color RendererEnvironmentStorage::environment_get_fog_light_color(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color(0.5, 0.6, 0.7));
+ return env->fog_light_color;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_light_energy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->fog_light_energy;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_sun_scatter(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->fog_sun_scatter;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_density(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.001);
+ return env->fog_density;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_height(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->fog_height;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_height_density(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->fog_height_density;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_aerial_perspective(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->fog_aerial_perspective;
+}
+
+// Volumetric Fog
+
+void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->volumetric_fog_enabled = p_enable;
+ env->volumetric_fog_density = p_density;
+ env->volumetric_fog_scattering = p_albedo;
+ env->volumetric_fog_emission = p_emission;
+ env->volumetric_fog_emission_energy = p_emission_energy;
+ env->volumetric_fog_anisotropy = p_anisotropy,
+ env->volumetric_fog_length = p_length;
+ env->volumetric_fog_detail_spread = p_detail_spread;
+ env->volumetric_fog_gi_inject = p_gi_inject;
+ env->volumetric_fog_temporal_reprojection = p_temporal_reprojection;
+ env->volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount;
+ env->volumetric_fog_ambient_inject = p_ambient_inject;
+}
+
+bool RendererEnvironmentStorage::environment_get_volumetric_fog_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->volumetric_fog_enabled;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_density(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.01);
+ return env->volumetric_fog_density;
+}
+
+Color RendererEnvironmentStorage::environment_get_volumetric_fog_scattering(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color(1, 1, 1));
+ return env->volumetric_fog_scattering;
+}
+
+Color RendererEnvironmentStorage::environment_get_volumetric_fog_emission(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color(0, 0, 0));
+ return env->volumetric_fog_emission;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_emission_energy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->volumetric_fog_emission_energy;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_anisotropy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.2);
+ return env->volumetric_fog_anisotropy;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_length(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 64.0);
+ return env->volumetric_fog_length;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_detail_spread(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 2.0);
+ return env->volumetric_fog_detail_spread;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_gi_inject(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->volumetric_fog_gi_inject;
+}
+
+bool RendererEnvironmentStorage::environment_get_volumetric_fog_temporal_reprojection(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, true);
+ return env->volumetric_fog_temporal_reprojection;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.9);
+ return env->volumetric_fog_temporal_reprojection_amount;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_ambient_inject(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->volumetric_fog_ambient_inject;
+}
+
+// GLOW
+
+void RendererEnvironmentStorage::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
+ env->glow_enabled = p_enable;
+ env->glow_levels = p_levels;
+ env->glow_intensity = p_intensity;
+ env->glow_strength = p_strength;
+ env->glow_mix = p_mix;
+ env->glow_bloom = p_bloom_threshold;
+ env->glow_blend_mode = p_blend_mode;
+ env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
+ env->glow_hdr_bleed_scale = p_hdr_bleed_scale;
+ env->glow_hdr_luminance_cap = p_hdr_luminance_cap;
+ env->glow_map_strength = p_glow_map_strength;
+ env->glow_map = p_glow_map;
+}
+
+bool RendererEnvironmentStorage::environment_get_glow_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->glow_enabled;
+}
+
+Vector<float> RendererEnvironmentStorage::environment_get_glow_levels(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Vector<float>());
+ return env->glow_levels;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_intensity(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.8);
+ return env->glow_intensity;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_strength(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->glow_strength;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_bloom(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->glow_bloom;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_mix(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.01);
+ return env->glow_mix;
+}
+
+RS::EnvironmentGlowBlendMode RendererEnvironmentStorage::environment_get_glow_blend_mode(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT);
+ return env->glow_blend_mode;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_hdr_bleed_threshold(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->glow_hdr_bleed_threshold;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_hdr_luminance_cap(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 12.0);
+ return env->glow_hdr_luminance_cap;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_hdr_bleed_scale(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 2.0);
+ return env->glow_hdr_bleed_scale;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_map_strength(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->glow_map_strength;
+}
+
+RID RendererEnvironmentStorage::environment_get_glow_map(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RID());
+ return env->glow_map;
+}
+
+// SSR
+
+void RendererEnvironmentStorage::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->ssr_enabled = p_enable;
+ env->ssr_max_steps = p_max_steps;
+ env->ssr_fade_in = p_fade_int;
+ env->ssr_fade_out = p_fade_out;
+ env->ssr_depth_tolerance = p_depth_tolerance;
+}
+
+bool RendererEnvironmentStorage::environment_get_ssr_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->ssr_enabled;
+}
+
+int RendererEnvironmentStorage::environment_get_ssr_max_steps(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 64);
+ return env->ssr_max_steps;
+}
+
+float RendererEnvironmentStorage::environment_get_ssr_fade_in(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.15);
+ return env->ssr_fade_in;
+}
+
+float RendererEnvironmentStorage::environment_get_ssr_fade_out(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 2.0);
+ return env->ssr_fade_out;
+}
+
+float RendererEnvironmentStorage::environment_get_ssr_depth_tolerance(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.2);
+ return env->ssr_depth_tolerance;
+}
+
+// SSAO
+
+void RendererEnvironmentStorage::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->ssao_enabled = p_enable;
+ env->ssao_radius = p_radius;
+ env->ssao_intensity = p_intensity;
+ env->ssao_power = p_power;
+ env->ssao_detail = p_detail;
+ env->ssao_horizon = p_horizon;
+ env->ssao_sharpness = p_sharpness;
+ env->ssao_direct_light_affect = p_light_affect;
+ env->ssao_ao_channel_affect = p_ao_channel_affect;
+}
+
+bool RendererEnvironmentStorage::environment_get_ssao_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->ssao_enabled;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_radius(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ssao_radius;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_intensity(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 2.0);
+ return env->ssao_intensity;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_power(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.5);
+ return env->ssao_power;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_detail(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.5);
+ return env->ssao_detail;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_horizon(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.06);
+ return env->ssao_horizon;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_sharpness(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.98);
+ return env->ssao_sharpness;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_direct_light_affect(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->ssao_direct_light_affect;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_ao_channel_affect(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->ssao_ao_channel_affect;
+}
+
+// SSIL
+
+void RendererEnvironmentStorage::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->ssil_enabled = p_enable;
+ env->ssil_radius = p_radius;
+ env->ssil_intensity = p_intensity;
+ env->ssil_sharpness = p_sharpness;
+ env->ssil_normal_rejection = p_normal_rejection;
+}
+
+bool RendererEnvironmentStorage::environment_get_ssil_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->ssil_enabled;
+}
+
+float RendererEnvironmentStorage::environment_get_ssil_radius(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 5.0);
+ return env->ssil_radius;
+}
+
+float RendererEnvironmentStorage::environment_get_ssil_intensity(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ssil_intensity;
+}
+
+float RendererEnvironmentStorage::environment_get_ssil_sharpness(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.98);
+ return env->ssil_sharpness;
+}
+
+float RendererEnvironmentStorage::environment_get_ssil_normal_rejection(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ssil_normal_rejection;
+}
+
+// SDFGI
+
+void RendererEnvironmentStorage::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->sdfgi_enabled = p_enable;
+ env->sdfgi_cascades = p_cascades;
+ env->sdfgi_min_cell_size = p_min_cell_size;
+ env->sdfgi_use_occlusion = p_use_occlusion;
+ env->sdfgi_bounce_feedback = p_bounce_feedback;
+ env->sdfgi_read_sky_light = p_read_sky;
+ env->sdfgi_energy = p_energy;
+ env->sdfgi_normal_bias = p_normal_bias;
+ env->sdfgi_probe_bias = p_probe_bias;
+ env->sdfgi_y_scale = p_y_scale;
+}
+
+bool RendererEnvironmentStorage::environment_get_sdfgi_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->sdfgi_enabled;
+}
+
+int RendererEnvironmentStorage::environment_get_sdfgi_cascades(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 4);
+ return env->sdfgi_cascades;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_min_cell_size(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.2);
+ return env->sdfgi_min_cell_size;
+}
+
+bool RendererEnvironmentStorage::environment_get_sdfgi_use_occlusion(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->sdfgi_use_occlusion;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_bounce_feedback(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.5);
+ return env->sdfgi_bounce_feedback;
+}
+
+bool RendererEnvironmentStorage::environment_get_sdfgi_read_sky_light(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, true);
+ return env->sdfgi_read_sky_light;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_energy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->sdfgi_energy;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_normal_bias(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.1);
+ return env->sdfgi_normal_bias;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_probe_bias(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.1);
+ return env->sdfgi_probe_bias;
+}
+
+RS::EnvironmentSDFGIYScale RendererEnvironmentStorage::environment_get_sdfgi_y_scale(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_SDFGI_Y_SCALE_75_PERCENT);
+ return env->sdfgi_y_scale;
+}
+
+// Adjustments
+
+void RendererEnvironmentStorage::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->adjustments_enabled = p_enable;
+ env->adjustments_brightness = p_brightness;
+ env->adjustments_contrast = p_contrast;
+ env->adjustments_saturation = p_saturation;
+ env->use_1d_color_correction = p_use_1d_color_correction;
+ env->color_correction = p_color_correction;
+}
+
+bool RendererEnvironmentStorage::environment_get_adjustments_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->adjustments_enabled;
+}
+
+float RendererEnvironmentStorage::environment_get_adjustments_brightness(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->adjustments_brightness;
+}
+
+float RendererEnvironmentStorage::environment_get_adjustments_contrast(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->adjustments_contrast;
+}
+
+float RendererEnvironmentStorage::environment_get_adjustments_saturation(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->adjustments_saturation;
+}
+
+bool RendererEnvironmentStorage::environment_get_use_1d_color_correction(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->use_1d_color_correction;
+}
+
+RID RendererEnvironmentStorage::environment_get_color_correction(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RID());
+ return env->color_correction;
+}
diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h
new file mode 100644
index 0000000000..29bba86930
--- /dev/null
+++ b/servers/rendering/storage/environment_storage.h
@@ -0,0 +1,296 @@
+/*************************************************************************/
+/* environment_storage.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 ENVIRONMENT_STORAGE_H
+#define ENVIRONMENT_STORAGE_H
+
+#include "core/templates/rid_owner.h"
+#include "servers/rendering_server.h"
+
+class RendererEnvironmentStorage {
+private:
+ struct Environment {
+ // Note, we capture and store all environment parameters received from Godot here.
+ // Not all renderers support all effects and should just ignore the bits they don't support.
+
+ // Background
+ RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR;
+ RID sky;
+ float sky_custom_fov = 0.0;
+ Basis sky_orientation;
+ Color bg_color;
+ float bg_energy = 1.0;
+ int canvas_max_layer = 0;
+ RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG;
+ Color ambient_light;
+ float ambient_light_energy = 1.0;
+ float ambient_sky_contribution = 1.0;
+ RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
+
+ // Tonemap
+ RS::EnvironmentToneMapper tone_mapper;
+ float exposure = 1.0;
+ float white = 1.0;
+ bool auto_exposure = false;
+ float min_luminance = 0.2;
+ float max_luminance = 8.0;
+ float auto_exp_speed = 0.2;
+ float auto_exp_scale = 0.5;
+ uint64_t auto_exposure_version = 0;
+
+ // Fog
+ bool fog_enabled = false;
+ Color fog_light_color = Color(0.518, 0.553, 0.608);
+ float fog_light_energy = 1.0;
+ float fog_sun_scatter = 0.0;
+ float fog_density = 0.01;
+ float fog_height = 0.0;
+ float fog_height_density = 0.0; //can be negative to invert effect
+ float fog_aerial_perspective = 0.0;
+
+ // Volumetric Fog
+ bool volumetric_fog_enabled = false;
+ float volumetric_fog_density = 0.01;
+ Color volumetric_fog_scattering = Color(1, 1, 1);
+ Color volumetric_fog_emission = Color(0, 0, 0);
+ float volumetric_fog_emission_energy = 0.0;
+ float volumetric_fog_anisotropy = 0.2;
+ float volumetric_fog_length = 64.0;
+ float volumetric_fog_detail_spread = 2.0;
+ float volumetric_fog_gi_inject = 1.0;
+ float volumetric_fog_ambient_inject = 0.0;
+ bool volumetric_fog_temporal_reprojection = true;
+ float volumetric_fog_temporal_reprojection_amount = 0.9;
+
+ // Glow
+ bool glow_enabled = false;
+ Vector<float> glow_levels;
+ float glow_intensity = 0.8;
+ float glow_strength = 1.0;
+ float glow_bloom = 0.0;
+ float glow_mix = 0.01;
+ RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT;
+ float glow_hdr_bleed_threshold = 1.0;
+ float glow_hdr_luminance_cap = 12.0;
+ float glow_hdr_bleed_scale = 2.0;
+ float glow_map_strength = 0.0f; // 1.0f in GLES3 ??
+ RID glow_map = RID();
+
+ // SSR
+ bool ssr_enabled = false;
+ int ssr_max_steps = 64;
+ float ssr_fade_in = 0.15;
+ float ssr_fade_out = 2.0;
+ float ssr_depth_tolerance = 0.2;
+
+ // SSAO
+ bool ssao_enabled = false;
+ float ssao_radius = 1.0;
+ float ssao_intensity = 2.0;
+ float ssao_power = 1.5;
+ float ssao_detail = 0.5;
+ float ssao_horizon = 0.06;
+ float ssao_sharpness = 0.98;
+ float ssao_direct_light_affect = 0.0;
+ float ssao_ao_channel_affect = 0.0;
+
+ // SSIL
+ bool ssil_enabled = false;
+ float ssil_radius = 5.0;
+ float ssil_intensity = 1.0;
+ float ssil_sharpness = 0.98;
+ float ssil_normal_rejection = 1.0;
+
+ // SDFGI
+ bool sdfgi_enabled = false;
+ int sdfgi_cascades = 4;
+ float sdfgi_min_cell_size = 0.2;
+ bool sdfgi_use_occlusion = false;
+ float sdfgi_bounce_feedback = 0.5;
+ bool sdfgi_read_sky_light = true;
+ float sdfgi_energy = 1.0;
+ float sdfgi_normal_bias = 1.1;
+ float sdfgi_probe_bias = 1.1;
+ RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_75_PERCENT;
+
+ // Adjustments
+ bool adjustments_enabled = false;
+ float adjustments_brightness = 1.0f;
+ float adjustments_contrast = 1.0f;
+ float adjustments_saturation = 1.0f;
+ bool use_1d_color_correction = false;
+ RID color_correction = RID();
+ };
+
+ static uint64_t auto_exposure_counter;
+
+ mutable RID_Owner<Environment, true> environment_owner;
+
+public:
+ RID environment_allocate();
+ void environment_initialize(RID p_rid);
+ void environment_free(RID p_rid);
+
+ bool is_environment(RID p_environment) const {
+ return environment_owner.owns(p_environment);
+ }
+
+ // Background
+ void environment_set_background(RID p_env, RS::EnvironmentBG p_bg);
+ void environment_set_sky(RID p_env, RID p_sky);
+ void environment_set_sky_custom_fov(RID p_env, float p_scale);
+ void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
+ void environment_set_bg_color(RID p_env, const Color &p_color);
+ void environment_set_bg_energy(RID p_env, float p_energy);
+ void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
+ void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG);
+// FIXME: Disabled during Vulkan refactoring, should be ported.
+#if 0
+ void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id);
+#endif
+
+ RS::EnvironmentBG environment_get_background(RID p_env) const;
+ RID environment_get_sky(RID p_env) const;
+ float environment_get_sky_custom_fov(RID p_env) const;
+ Basis environment_get_sky_orientation(RID p_env) const;
+ Color environment_get_bg_color(RID p_env) const;
+ float environment_get_bg_energy(RID p_env) const;
+ int environment_get_canvas_max_layer(RID p_env) const;
+ RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
+ Color environment_get_ambient_light(RID p_env) const;
+ float environment_get_ambient_light_energy(RID p_env) const;
+ float environment_get_ambient_sky_contribution(RID p_env) const;
+ RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
+
+ // Tonemap
+ void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
+ RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const;
+ float environment_get_exposure(RID p_env) const;
+ float environment_get_white(RID p_env) const;
+ bool environment_get_auto_exposure(RID p_env) const;
+ float environment_get_min_luminance(RID p_env) const;
+ float environment_get_max_luminance(RID p_env) const;
+ float environment_get_auto_exp_speed(RID p_env) const;
+ float environment_get_auto_exp_scale(RID p_env) const;
+ uint64_t environment_get_auto_exposure_version(RID p_env) const;
+
+ // Fog
+ void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective);
+ bool environment_get_fog_enabled(RID p_env) const;
+ Color environment_get_fog_light_color(RID p_env) const;
+ float environment_get_fog_light_energy(RID p_env) const;
+ float environment_get_fog_sun_scatter(RID p_env) const;
+ float environment_get_fog_density(RID p_env) const;
+ float environment_get_fog_height(RID p_env) const;
+ float environment_get_fog_height_density(RID p_env) const;
+ float environment_get_fog_aerial_perspective(RID p_env) const;
+
+ // Volumetric Fog
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject);
+ bool environment_get_volumetric_fog_enabled(RID p_env) const;
+ float environment_get_volumetric_fog_density(RID p_env) const;
+ Color environment_get_volumetric_fog_scattering(RID p_env) const;
+ Color environment_get_volumetric_fog_emission(RID p_env) const;
+ float environment_get_volumetric_fog_emission_energy(RID p_env) const;
+ float environment_get_volumetric_fog_anisotropy(RID p_env) const;
+ float environment_get_volumetric_fog_length(RID p_env) const;
+ float environment_get_volumetric_fog_detail_spread(RID p_env) const;
+ float environment_get_volumetric_fog_gi_inject(RID p_env) const;
+ bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const;
+ float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const;
+ float environment_get_volumetric_fog_ambient_inject(RID p_env) const;
+
+ // GLOW
+ void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map);
+ bool environment_get_glow_enabled(RID p_env) const;
+ Vector<float> environment_get_glow_levels(RID p_env) const;
+ float environment_get_glow_intensity(RID p_env) const;
+ float environment_get_glow_strength(RID p_env) const;
+ float environment_get_glow_bloom(RID p_env) const;
+ float environment_get_glow_mix(RID p_env) const;
+ RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const;
+ float environment_get_glow_hdr_bleed_threshold(RID p_env) const;
+ float environment_get_glow_hdr_luminance_cap(RID p_env) const;
+ float environment_get_glow_hdr_bleed_scale(RID p_env) const;
+ float environment_get_glow_map_strength(RID p_env) const;
+ RID environment_get_glow_map(RID p_env) const;
+
+ // SSR
+ void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
+ bool environment_get_ssr_enabled(RID p_env) const;
+ int environment_get_ssr_max_steps(RID p_env) const;
+ float environment_get_ssr_fade_in(RID p_env) const;
+ float environment_get_ssr_fade_out(RID p_env) const;
+ float environment_get_ssr_depth_tolerance(RID p_env) const;
+
+ // SSAO
+ void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
+ bool environment_get_ssao_enabled(RID p_env) const;
+ float environment_get_ssao_radius(RID p_env) const;
+ float environment_get_ssao_intensity(RID p_env) const;
+ float environment_get_ssao_power(RID p_env) const;
+ float environment_get_ssao_detail(RID p_env) const;
+ float environment_get_ssao_horizon(RID p_env) const;
+ float environment_get_ssao_sharpness(RID p_env) const;
+ float environment_get_ssao_direct_light_affect(RID p_env) const;
+ float environment_get_ssao_ao_channel_affect(RID p_env) const;
+
+ // SSIL
+ void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection);
+ bool environment_get_ssil_enabled(RID p_env) const;
+ float environment_get_ssil_radius(RID p_env) const;
+ float environment_get_ssil_intensity(RID p_env) const;
+ float environment_get_ssil_sharpness(RID p_env) const;
+ float environment_get_ssil_normal_rejection(RID p_env) const;
+
+ // SDFGI
+ void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
+ bool environment_get_sdfgi_enabled(RID p_env) const;
+ int environment_get_sdfgi_cascades(RID p_env) const;
+ float environment_get_sdfgi_min_cell_size(RID p_env) const;
+ bool environment_get_sdfgi_use_occlusion(RID p_env) const;
+ float environment_get_sdfgi_bounce_feedback(RID p_env) const;
+ bool environment_get_sdfgi_read_sky_light(RID p_env) const;
+ float environment_get_sdfgi_energy(RID p_env) const;
+ float environment_get_sdfgi_normal_bias(RID p_env) const;
+ float environment_get_sdfgi_probe_bias(RID p_env) const;
+ RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const;
+
+ // Adjustment
+ void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction);
+ bool environment_get_adjustments_enabled(RID p_env) const;
+ float environment_get_adjustments_brightness(RID p_env) const;
+ float environment_get_adjustments_contrast(RID p_env) const;
+ float environment_get_adjustments_saturation(RID p_env) const;
+ bool environment_get_use_1d_color_correction(RID p_env) const;
+ RID environment_get_color_correction(RID p_env) const;
+};
+
+#endif // ENVIRONMENT_STORAGE_H
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index 0cb0f35570..087ea1a025 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 {
@@ -136,4 +135,4 @@ public:
virtual float lightmap_get_probe_capture_update_speed() const = 0;
};
-#endif // !LIGHT_STORAGE_H
+#endif // LIGHT_STORAGE_H
diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h
index f0363f129a..ad8e3e79bf 100644
--- a/servers/rendering/storage/material_storage.h
+++ b/servers/rendering/storage/material_storage.h
@@ -31,29 +31,29 @@
#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:
virtual ~RendererMaterialStorage(){};
- /* GLOBAL VARIABLE API */
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
- virtual void global_variable_remove(const StringName &p_name) = 0;
- virtual Vector<StringName> global_variable_get_list() const = 0;
+ /* GLOBAL SHADER UNIFORM API */
+ virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_remove(const StringName &p_name) = 0;
+ virtual Vector<StringName> global_shader_uniform_get_list() const = 0;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
- virtual Variant global_variable_get(const StringName &p_name) const = 0;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) = 0;
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const = 0;
+ virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const = 0;
- virtual void global_variables_load_settings(bool p_load_textures = true) = 0;
- virtual void global_variables_clear() = 0;
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) = 0;
+ virtual void global_shader_uniforms_clear() = 0;
- virtual int32_t global_variables_instance_allocate(RID p_instance) = 0;
- virtual void global_variables_instance_free(RID p_instance) = 0;
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
+ virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) = 0;
+ virtual void global_shader_uniforms_instance_free(RID p_instance) = 0;
+ virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
/* SHADER API */
virtual RID shader_allocate() = 0;
@@ -61,8 +61,9 @@ public:
virtual void shader_free(RID p_rid) = 0;
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
+ virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 0;
virtual String shader_get_code(RID p_shader) const = 0;
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
+ virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0;
@@ -93,9 +94,9 @@ public:
Variant default_value;
};
- virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
+ virtual void material_get_instance_shader_uniforms(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
+#endif // MATERIAL_STORAGE_H
diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h
index 1dac51319c..5b3738dfd7 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
+#endif // MESH_STORAGE_H
diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h
index 268b5473e2..ee4b8679b3 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 {
@@ -126,4 +125,4 @@ public:
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
};
-#endif // !PARTICLES_STORAGE_H
+#endif // PARTICLES_STORAGE_H
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index e3a969d032..982ab4a958 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;
@@ -132,6 +143,9 @@ public:
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
+
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0;
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0;
};
-#endif // !TEXTURE_STORAGE_H
+#endif // TEXTURE_STORAGE_H
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..d240d58917 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/rendering_server.cpp b/servers/rendering_server.cpp
index 9b407043fc..a54d4f0384 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -772,19 +772,11 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
elem_size = 3;
}
- {
- elem_size *= sizeof(float);
- }
-
- if (elem_size == 6) {
- elem_size = 8;
- }
-
+ elem_size *= sizeof(float);
} break;
case RS::ARRAY_NORMAL: {
elem_size = 4;
} break;
-
case RS::ARRAY_TANGENT: {
elem_size = 4;
} break;
@@ -793,12 +785,9 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
} break;
case RS::ARRAY_TEX_UV: {
elem_size = 8;
-
} break;
-
case RS::ARRAY_TEX_UV2: {
elem_size = 8;
-
} break;
case RS::ARRAY_CUSTOM0:
case RS::ARRAY_CUSTOM1:
@@ -1410,7 +1399,7 @@ Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_su
}
#endif
-int RenderingServer::global_variable_type_get_shader_datatype(GlobalVariableType p_type) {
+int RenderingServer::global_shader_uniform_type_get_shader_datatype(GlobalShaderUniformType p_type) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL:
return ShaderLanguage::TYPE_BOOL;
@@ -1511,9 +1500,9 @@ TypedArray<Image> RenderingServer::_texture_3d_get(RID p_texture) const {
return ret;
}
-TypedArray<Dictionary> RenderingServer::_shader_get_param_list(RID p_shader) const {
+TypedArray<Dictionary> RenderingServer::_shader_get_shader_uniform_list(RID p_shader) const {
List<PropertyInfo> l;
- shader_get_param_list(p_shader, &l);
+ shader_get_shader_uniform_list(p_shader, &l);
return convert_property_list(&l);
}
@@ -1636,9 +1625,9 @@ Dictionary RenderingServer::_mesh_get_surface(RID p_mesh, int p_idx) {
return d;
}
-Array RenderingServer::_instance_geometry_get_shader_parameter_list(RID p_instance) const {
+Array RenderingServer::_instance_geometry_get_shader_uniform_list(RID p_instance) const {
List<PropertyInfo> params;
- instance_geometry_get_shader_parameter_list(p_instance, &params);
+ instance_geometry_get_shader_uniform_list(p_instance, &params);
return convert_property_list(&params);
}
@@ -1709,8 +1698,10 @@ void RenderingServer::_bind_methods() {
/* SHADER */
ClassDB::bind_method(D_METHOD("shader_create"), &RenderingServer::shader_create);
+ ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &RenderingServer::shader_set_code);
+ ClassDB::bind_method(D_METHOD("shader_set_path_hint", "shader", "path"), &RenderingServer::shader_set_path_hint);
ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &RenderingServer::shader_get_code);
- ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list);
+ ClassDB::bind_method(D_METHOD("shader_get_shader_uniform_list", "shader"), &RenderingServer::_shader_get_shader_uniform_list);
ClassDB::bind_method(D_METHOD("shader_get_param_default", "shader", "param"), &RenderingServer::shader_get_param_default);
ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture", "index"), &RenderingServer::shader_set_default_texture_param, DEFVAL(0));
@@ -1894,9 +1885,10 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST);
- BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL);
@@ -1919,6 +1911,7 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_OPACITY);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BLUR);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_TRANSMITTANCE_BIAS);
@@ -1939,8 +1932,8 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY);
- ClassDB::bind_method(D_METHOD("shadows_quality_set", "quality"), &RenderingServer::shadows_quality_set);
- ClassDB::bind_method(D_METHOD("directional_shadow_quality_set", "quality"), &RenderingServer::directional_shadow_quality_set);
+ ClassDB::bind_method(D_METHOD("positional_soft_shadow_filter_set_quality", "quality"), &RenderingServer::positional_soft_shadow_filter_set_quality);
+ ClassDB::bind_method(D_METHOD("directional_soft_shadow_filter_set_quality", "quality"), &RenderingServer::directional_soft_shadow_filter_set_quality);
ClassDB::bind_method(D_METHOD("directional_shadow_atlas_set_size", "size", "is_16bits"), &RenderingServer::directional_shadow_atlas_set_size);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_HARD);
@@ -1998,9 +1991,10 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(DECAL_TEXTURE_MAX);
BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST);
- BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
/* GI API (affects VoxelGI and SDFGI) */
@@ -2182,7 +2176,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_mode", "viewport", "scaling_3d_mode"), &RenderingServer::viewport_set_scaling_3d_mode);
ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_scale", "viewport", "scale"), &RenderingServer::viewport_set_scaling_3d_scale);
ClassDB::bind_method(D_METHOD("viewport_set_fsr_sharpness", "viewport", "sharpness"), &RenderingServer::viewport_set_fsr_sharpness);
- ClassDB::bind_method(D_METHOD("viewport_set_fsr_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_fsr_mipmap_bias);
+ ClassDB::bind_method(D_METHOD("viewport_set_texture_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_texture_mipmap_bias);
ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &RenderingServer::viewport_set_update_mode);
ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &RenderingServer::viewport_set_clear_mode);
ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture);
@@ -2207,8 +2201,8 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_sdf_oversize_and_scale", "viewport", "oversize", "scale"), &RenderingServer::viewport_set_sdf_oversize_and_scale);
- ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size", "use_16_bits"), &RenderingServer::viewport_set_shadow_atlas_size, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_shadow_atlas_quadrant_subdivision);
+ ClassDB::bind_method(D_METHOD("viewport_set_positional_shadow_atlas_size", "viewport", "size", "use_16_bits"), &RenderingServer::viewport_set_positional_shadow_atlas_size, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("viewport_set_positional_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_positional_shadow_atlas_quadrant_subdivision);
ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &RenderingServer::viewport_set_msaa);
ClassDB::bind_method(D_METHOD("viewport_set_screen_space_aa", "viewport", "mode"), &RenderingServer::viewport_set_screen_space_aa);
ClassDB::bind_method(D_METHOD("viewport_set_use_taa", "viewport", "enable"), &RenderingServer::viewport_set_use_taa);
@@ -2225,6 +2219,9 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu);
+ ClassDB::bind_method(D_METHOD("viewport_set_vrs_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_mode);
+ ClassDB::bind_method(D_METHOD("viewport_set_vrs_texture", "viewport", "texture"), &RenderingServer::viewport_set_vrs_texture);
+
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR);
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_FSR);
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX);
@@ -2300,6 +2297,11 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_MOTION_VECTORS);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_DISABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_TEXTURE);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_XR);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_MAX);
+
/* SKY API */
ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create);
@@ -2483,10 +2485,10 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("instance_geometry_set_lightmap", "instance", "lightmap", "lightmap_uv_scale", "lightmap_slice"), &RenderingServer::instance_geometry_set_lightmap);
ClassDB::bind_method(D_METHOD("instance_geometry_set_lod_bias", "instance", "lod_bias"), &RenderingServer::instance_geometry_set_lod_bias);
- ClassDB::bind_method(D_METHOD("instance_geometry_set_shader_parameter", "instance", "parameter", "value"), &RenderingServer::instance_geometry_set_shader_parameter);
- ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter);
- ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_default_value", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter_default_value);
- ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_list", "instance"), &RenderingServer::_instance_geometry_get_shader_parameter_list);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_shader_uniform", "instance", "parameter", "value"), &RenderingServer::instance_geometry_set_shader_uniform);
+ ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_uniform);
+ ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform_default_value", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_uniform_default_value);
+ ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform_list", "instance"), &RenderingServer::_instance_geometry_get_shader_uniform_list);
ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &RenderingServer::_instances_cull_aabb_bind, DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &RenderingServer::_instances_cull_ray_bind, DEFVAL(RID()));
@@ -2680,15 +2682,15 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE);
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE);
- /* GLOBAL VARIABLES */
+ /* GLOBAL SHADER UNIFORMS */
- ClassDB::bind_method(D_METHOD("global_variable_add", "name", "type", "default_value"), &RenderingServer::global_variable_add);
- ClassDB::bind_method(D_METHOD("global_variable_remove", "name"), &RenderingServer::global_variable_remove);
- ClassDB::bind_method(D_METHOD("global_variable_get_list"), &RenderingServer::global_variable_get_list);
- ClassDB::bind_method(D_METHOD("global_variable_set", "name", "value"), &RenderingServer::global_variable_set);
- ClassDB::bind_method(D_METHOD("global_variable_set_override", "name", "value"), &RenderingServer::global_variable_set_override);
- ClassDB::bind_method(D_METHOD("global_variable_get", "name"), &RenderingServer::global_variable_get);
- ClassDB::bind_method(D_METHOD("global_variable_get_type", "name"), &RenderingServer::global_variable_get_type);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_add", "name", "type", "default_value"), &RenderingServer::global_shader_uniform_add);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_remove", "name"), &RenderingServer::global_shader_uniform_remove);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_get_list"), &RenderingServer::global_shader_uniform_get_list);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_set", "name", "value"), &RenderingServer::global_shader_uniform_set);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_set_override", "name", "value"), &RenderingServer::global_shader_uniform_set_override);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_get", "name"), &RenderingServer::global_shader_uniform_get);
+ ClassDB::bind_method(D_METHOD("global_shader_uniform_get_type", "name"), &RenderingServer::global_shader_uniform_get_type);
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BOOL);
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC2);
@@ -2821,7 +2823,6 @@ void RenderingServer::set_render_loop_enabled(bool p_enabled) {
RenderingServer::RenderingServer() {
//ERR_FAIL_COND(singleton);
- thread_pool = memnew(RendererThreadPool);
singleton = this;
}
@@ -2841,14 +2842,14 @@ void RenderingServer::init() {
GLOBAL_DEF("rendering/shadows/directional_shadow/size", 4096);
GLOBAL_DEF("rendering/shadows/directional_shadow/size.mobile", 2048);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
- GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality", 2);
- GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+ GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_filter_quality", 2);
+ GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_filter_quality.mobile", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_filter_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_filter_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
GLOBAL_DEF("rendering/shadows/directional_shadow/16_bits", true);
- GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality", 2);
- GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+ GLOBAL_DEF("rendering/shadows/positional_shadow/soft_shadow_filter_quality", 2);
+ GLOBAL_DEF("rendering/shadows/positional_shadow/soft_shadow_filter_quality.mobile", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/soft_shadow_filter_quality", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/soft_shadow_filter_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048);
@@ -2937,7 +2938,7 @@ void RenderingServer::init() {
GLOBAL_DEF("rendering/scaling_3d/mode", 0);
GLOBAL_DEF("rendering/scaling_3d/scale", 1.0);
GLOBAL_DEF("rendering/scaling_3d/fsr_sharpness", 0.2f);
- GLOBAL_DEF("rendering/scaling_3d/fsr_mipmap_bias", 0.0f);
+ GLOBAL_DEF("rendering/textures/default_filters/texture_mipmap_bias", 0.0f);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/mode",
PropertyInfo(Variant::INT,
"rendering/scaling_3d/mode",
@@ -2952,15 +2953,15 @@ void RenderingServer::init() {
PropertyInfo(Variant::FLOAT,
"rendering/scaling_3d/fsr_sharpness",
PROPERTY_HINT_RANGE, "0,2,0.1"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/fsr_mipmap_bias",
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/default_filters/texture_mipmap_bias",
PropertyInfo(Variant::FLOAT,
- "rendering/scaling_3d/fsr_mipmap_bias",
- PROPERTY_HINT_RANGE, "-2,2,0.1"));
+ "rendering/textures/default_filters/texture_mipmap_bias",
+ PROPERTY_HINT_RANGE, "-2,2,0.001"));
GLOBAL_DEF("rendering/textures/decals/filter", DECAL_FILTER_LINEAR_MIPMAPS);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"));
GLOBAL_DEF("rendering/textures/light_projectors/filter", LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"));
GLOBAL_DEF_RST("rendering/occlusion_culling/occlusion_rays_per_thread", 512);
GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2);
@@ -3022,6 +3023,5 @@ void RenderingServer::init() {
}
RenderingServer::~RenderingServer() {
- memdelete(thread_pool);
singleton = nullptr;
}
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index ccef95f5f2..a2fe9caf19 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -35,11 +35,11 @@
#include "core/math/geometry_3d.h"
#include "core/math/transform_2d.h"
#include "core/object/class_db.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/rid.h"
#include "core/variant/typed_array.h"
#include "core/variant/variant.h"
#include "servers/display_server.h"
-#include "servers/rendering/renderer_thread_pool.h"
#include "servers/rendering/rendering_device.h"
class RenderingServer : public Object {
@@ -52,8 +52,6 @@ class RenderingServer : public Object {
Array _get_array_from_surface(uint32_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len) const;
- RendererThreadPool *thread_pool = nullptr;
-
const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON);
const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON);
@@ -170,8 +168,9 @@ public:
virtual RID shader_create() = 0;
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
+ virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 0;
virtual String shader_get_code(RID p_shader) const = 0;
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
+ virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0;
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0;
@@ -426,6 +425,7 @@ public:
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
LIGHT_PARAM_SHADOW_BIAS,
LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
+ LIGHT_PARAM_SHADOW_OPACITY,
LIGHT_PARAM_SHADOW_BLUR,
LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
LIGHT_PARAM_TRANSMITTANCE_BIAS,
@@ -491,14 +491,15 @@ public:
SHADOW_QUALITY_MAX
};
- virtual void shadows_quality_set(ShadowQuality p_quality) = 0;
- virtual void directional_shadow_quality_set(ShadowQuality p_quality) = 0;
+ virtual void positional_soft_shadow_filter_set_quality(ShadowQuality p_quality) = 0;
+ virtual void directional_soft_shadow_filter_set_quality(ShadowQuality p_quality) = 0;
enum LightProjectorFilter {
LIGHT_PROJECTOR_FILTER_NEAREST,
- LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS,
LIGHT_PROJECTOR_FILTER_LINEAR,
+ LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS,
LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS,
+ LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC,
LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
};
@@ -558,9 +559,10 @@ public:
enum DecalFilter {
DECAL_FILTER_NEAREST,
- DECAL_FILTER_NEAREST_MIPMAPS,
DECAL_FILTER_LINEAR,
+ DECAL_FILTER_NEAREST_MIPMAPS,
DECAL_FILTER_LINEAR_MIPMAPS,
+ DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC,
DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
};
@@ -798,7 +800,7 @@ public:
virtual void viewport_set_scaling_3d_mode(RID p_viewport, ViewportScaling3DMode p_scaling_3d_mode) = 0;
virtual void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) = 0;
virtual void viewport_set_fsr_sharpness(RID p_viewport, float p_fsr_sharpness) = 0;
- virtual void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_fsr_mipmap_bias) = 0;
+ virtual void viewport_set_texture_mipmap_bias(RID p_viewport, float p_texture_mipmap_bias) = 0;
enum ViewportUpdateMode {
VIEWPORT_UPDATE_DISABLED,
@@ -856,8 +858,8 @@ public:
virtual void viewport_set_sdf_oversize_and_scale(RID p_viewport, ViewportSDFOversize p_oversize, ViewportSDFScale p_scale) = 0;
- virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true) = 0;
- virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;
+ virtual void viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true) = 0;
+ virtual void viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;
enum ViewportMSAA {
VIEWPORT_MSAA_DISABLED,
@@ -946,6 +948,16 @@ public:
virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const = 0;
+ enum ViewportVRSMode {
+ VIEWPORT_VRS_DISABLED,
+ VIEWPORT_VRS_TEXTURE,
+ VIEWPORT_VRS_XR,
+ VIEWPORT_VRS_MAX,
+ };
+
+ virtual void viewport_set_vrs_mode(RID p_viewport, ViewportVRSMode p_mode) = 0;
+ virtual void viewport_set_vrs_texture(RID p_viewport, RID p_texture) = 0;
+
/* SKY API */
enum SkyMode {
@@ -1233,10 +1245,10 @@ public:
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency) = 0;
- virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &, const Variant &p_value) = 0;
- virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &) const = 0;
- virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &) const = 0;
- virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
+ virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &, const Variant &p_value) = 0;
+ virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &) const = 0;
+ virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &) const = 0;
+ virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
/* Bake 3D objects */
@@ -1416,9 +1428,9 @@ public:
virtual void canvas_set_shadow_texture_size(int p_size) = 0;
- /* GLOBAL VARIABLES */
+ /* GLOBAL SHADER UNIFORMS */
- enum GlobalVariableType {
+ enum GlobalShaderUniformType {
GLOBAL_VAR_TYPE_BOOL,
GLOBAL_VAR_TYPE_BVEC2,
GLOBAL_VAR_TYPE_BVEC3,
@@ -1450,20 +1462,20 @@ public:
GLOBAL_VAR_TYPE_MAX
};
- virtual void global_variable_add(const StringName &p_name, GlobalVariableType p_type, const Variant &p_value) = 0;
- virtual void global_variable_remove(const StringName &p_name) = 0;
- virtual Vector<StringName> global_variable_get_list() const = 0;
+ virtual void global_shader_uniform_add(const StringName &p_name, GlobalShaderUniformType p_type, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_remove(const StringName &p_name) = 0;
+ virtual Vector<StringName> global_shader_uniform_get_list() const = 0;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) = 0;
- virtual Variant global_variable_get(const StringName &p_name) const = 0;
- virtual GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
+ virtual Variant global_shader_uniform_get(const StringName &p_name) const = 0;
+ virtual GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const = 0;
- virtual void global_variables_load_settings(bool p_load_textures) = 0;
- virtual void global_variables_clear() = 0;
+ virtual void global_shader_uniforms_load_settings(bool p_load_textures) = 0;
+ virtual void global_shader_uniforms_clear() = 0;
- static int global_variable_type_get_shader_datatype(GlobalVariableType p_type);
+ static int global_shader_uniform_type_get_shader_datatype(GlobalShaderUniformType p_type);
/* FREE */
@@ -1560,11 +1572,11 @@ private:
RID _texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data);
void _texture_3d_update(RID p_texture, const TypedArray<Image> &p_data);
TypedArray<Image> _texture_3d_get(RID p_texture) const;
- TypedArray<Dictionary> _shader_get_param_list(RID p_shader) const;
+ TypedArray<Dictionary> _shader_get_shader_uniform_list(RID p_shader) const;
RID _mesh_create_from_surfaces(const TypedArray<Dictionary> &p_surfaces, int p_blend_shape_count);
void _mesh_add_surface(RID p_mesh, const Dictionary &p_surface);
Dictionary _mesh_get_surface(RID p_mesh, int p_idx);
- Array _instance_geometry_get_shader_parameter_list(RID p_instance) const;
+ Array _instance_geometry_get_shader_uniform_list(RID p_instance) const;
TypedArray<Image> _bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size);
void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses);
};
@@ -1609,6 +1621,7 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw);
VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale);
+VARIANT_ENUM_CAST(RenderingServer::ViewportVRSMode);
VARIANT_ENUM_CAST(RenderingServer::SkyMode);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource);
@@ -1638,7 +1651,7 @@ VARIANT_ENUM_CAST(RenderingServer::CanvasLightMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasLightBlendMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter);
VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode);
-VARIANT_ENUM_CAST(RenderingServer::GlobalVariableType);
+VARIANT_ENUM_CAST(RenderingServer::GlobalShaderUniformType);
VARIANT_ENUM_CAST(RenderingServer::RenderingInfo);
VARIANT_ENUM_CAST(RenderingServer::Features);
VARIANT_ENUM_CAST(RenderingServer::CanvasTextureChannel);
diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h
index 2c4aab0784..318c844a2f 100644
--- a/servers/server_wrap_mt_common.h
+++ b/servers/server_wrap_mt_common.h
@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef SERVER_WRAP_MT_COMMON_H
+#define SERVER_WRAP_MT_COMMON_H
+
#define FUNC0R(m_r, m_type) \
virtual m_r m_type() override { \
if (Thread::get_caller_id() != server_thread) { \
@@ -762,3 +765,5 @@
server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); \
} \
}
+
+#endif // SERVER_WRAP_MT_COMMON_H
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index e9a558ac5f..59310ab69b 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");
@@ -297,9 +297,13 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(percent_sign, "language");
GDVIRTUAL_BIND(strip_diacritics, "string");
+ GDVIRTUAL_BIND(is_valid_identifier, "string");
GDVIRTUAL_BIND(string_get_word_breaks, "string", "language");
+ GDVIRTUAL_BIND(is_confusable, "string", "dict");
+ GDVIRTUAL_BIND(spoof_check, "string");
+
GDVIRTUAL_BIND(string_to_upper, "string", "language");
GDVIRTUAL_BIND(string_to_lower, "string", "language");
@@ -438,12 +442,12 @@ int64_t TextServerExtension::font_get_face_count(const RID &p_font_rid) const {
return 0;
}
-void TextServerExtension::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) {
+void TextServerExtension::font_set_style(const RID &p_font_rid, BitField<TextServer::FontStyle> p_style) {
GDVIRTUAL_CALL(font_set_style, p_font_rid, p_style);
}
-int64_t /*FontStyle*/ TextServerExtension::font_get_style(const RID &p_font_rid) const {
- int64_t ret;
+BitField<TextServer::FontStyle> TextServerExtension::font_get_style(const RID &p_font_rid) const {
+ BitField<TextServer::FontStyle> ret = 0;
if (GDVIRTUAL_CALL(font_get_style, p_font_rid, ret)) {
return ret;
}
@@ -706,18 +710,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 +1124,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)) {
@@ -1192,7 +1196,7 @@ RID TextServerExtension::shaped_text_get_parent(const RID &p_shaped) const {
return RID();
}
-double TextServerExtension::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t p_jst_flags) {
+double TextServerExtension::shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags) {
double ret;
if (GDVIRTUAL_CALL(shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret)) {
return ret;
@@ -1272,7 +1276,7 @@ Vector2i TextServerExtension::shaped_text_get_range(const RID &p_shaped) const {
return Vector2i();
}
-PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t p_break_flags) const {
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array ret;
if (GDVIRTUAL_CALL(shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) {
return ret;
@@ -1280,7 +1284,7 @@ PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID
return TextServer::shaped_text_get_line_breaks_adv(p_shaped, p_width, p_start, p_once, p_break_flags);
}
-PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t p_break_flags) const {
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array ret;
if (GDVIRTUAL_CALL(shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) {
return ret;
@@ -1288,7 +1292,7 @@ PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_s
return TextServer::shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags);
}
-PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const {
+PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags) const {
PackedInt32Array ret;
if (GDVIRTUAL_CALL(shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) {
return ret;
@@ -1328,7 +1332,7 @@ int64_t TextServerExtension::shaped_text_get_ellipsis_glyph_count(const RID &p_s
return -1;
}
-void TextServerExtension::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) {
+void TextServerExtension::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) {
GDVIRTUAL_CALL(shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags);
}
@@ -1498,6 +1502,14 @@ String TextServerExtension::percent_sign(const String &p_language) const {
return "%";
}
+bool TextServerExtension::is_valid_identifier(const String &p_string) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(is_valid_identifier, p_string, ret)) {
+ return ret;
+ }
+ return TextServer::is_valid_identifier(p_string);
+}
+
String TextServerExtension::strip_diacritics(const String &p_string) const {
String ret;
if (GDVIRTUAL_CALL(strip_diacritics, p_string, ret)) {
@@ -1538,6 +1550,22 @@ PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_str
return PackedInt32Array();
}
+int TextServerExtension::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
+ int ret;
+ if (GDVIRTUAL_CALL(is_confusable, p_string, p_dict, ret)) {
+ return ret;
+ }
+ return TextServer::is_confusable(p_string, p_dict);
+}
+
+bool TextServerExtension::spoof_check(const String &p_string) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(spoof_check, p_string, ret)) {
+ return ret;
+ }
+ return TextServer::spoof_check(p_string);
+}
+
TextServerExtension::TextServerExtension() {
//NOP
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index 9ca0939247..81af1b60e5 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -92,10 +92,10 @@ public:
virtual int64_t font_get_face_count(const RID &p_font_rid) const override;
GDVIRTUAL1RC(int64_t, font_get_face_count, RID);
- virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override;
- virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_style, RID, int64_t);
- GDVIRTUAL1RC(int64_t, font_get_style, RID);
+ virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) override;
+ virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_style, RID, BitField<FontStyle>);
+ GDVIRTUAL1RC(BitField<FontStyle>, font_get_style, RID);
virtual void font_set_name(const RID &p_font_rid, const String &p_name) override;
virtual String font_get_name(const RID &p_font_rid) const override;
@@ -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;
@@ -396,9 +396,9 @@ public:
GDVIRTUAL3RC(RID, shaped_text_substr, RID, int64_t, int64_t);
GDVIRTUAL1RC(RID, shaped_text_get_parent, RID);
- virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
+ virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override;
- GDVIRTUAL3R(double, shaped_text_fit_to_width, RID, double, int64_t);
+ GDVIRTUAL3R(double, shaped_text_fit_to_width, RID, double, BitField<TextServer::JustificationFlag>);
GDVIRTUAL2R(double, shaped_text_tab_align, RID, const PackedFloat32Array &);
virtual bool shaped_text_shape(const RID &p_shaped) override;
@@ -421,12 +421,12 @@ public:
virtual Vector2i shaped_text_get_range(const RID &p_shaped) const override;
GDVIRTUAL1RC(Vector2i, shaped_text_get_range, RID);
- virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
- virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
- virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
- GDVIRTUAL5RC(PackedInt32Array, shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int64_t, bool, int64_t);
- GDVIRTUAL4RC(PackedInt32Array, shaped_text_get_line_breaks, RID, double, int64_t, int64_t);
- GDVIRTUAL2RC(PackedInt32Array, shaped_text_get_word_breaks, RID, int64_t);
+ virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
+ virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
+ virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
+ GDVIRTUAL5RC(PackedInt32Array, shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int64_t, bool, BitField<TextServer::LineBreakFlag>);
+ GDVIRTUAL4RC(PackedInt32Array, shaped_text_get_line_breaks, RID, double, int64_t, BitField<TextServer::LineBreakFlag>);
+ GDVIRTUAL2RC(PackedInt32Array, shaped_text_get_word_breaks, RID, BitField<TextServer::GraphemeFlag>);
virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const override;
virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const override;
@@ -437,8 +437,8 @@ public:
GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, shaped_text_get_ellipsis_glyphs, RID);
GDVIRTUAL1RC(int64_t, shaped_text_get_ellipsis_glyph_count, RID);
- virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override;
- GDVIRTUAL3(shaped_text_overrun_trim_to_width, RID, double, int64_t);
+ virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) override;
+ GDVIRTUAL3(shaped_text_overrun_trim_to_width, RID, double, BitField<TextServer::TextOverrunFlag>);
virtual Array shaped_text_get_objects(const RID &p_shaped) const override;
virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const override;
@@ -496,6 +496,9 @@ public:
virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const override;
GDVIRTUAL2RC(PackedInt32Array, string_get_word_breaks, const String &, const String &);
+ virtual bool is_valid_identifier(const String &p_string) const override;
+ GDVIRTUAL1RC(bool, is_valid_identifier, const String &);
+
virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
GDVIRTUAL2RC(String, string_to_upper, const String &, const String &);
@@ -504,6 +507,11 @@ public:
Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
GDVIRTUAL3RC(Array, parse_structured_text, StructuredTextParser, const Array &, const String &);
+ virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
+ virtual bool spoof_check(const String &p_string) const override;
+ GDVIRTUAL2RC(int, is_confusable, const String &, const PackedStringArray &);
+ GDVIRTUAL1RC(bool, spoof_check, const String &);
+
TextServerExtension();
~TextServerExtension();
};
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index fe5ade88a1..2bf0837d88 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));
@@ -446,7 +446,11 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language"), &TextServer::string_get_word_breaks, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("is_confusable", "string", "dict"), &TextServer::is_confusable);
+ ClassDB::bind_method(D_METHOD("spoof_check", "string"), &TextServer::spoof_check);
+
ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics);
+ ClassDB::bind_method(D_METHOD("is_valid_identifier", "string"), &TextServer::is_valid_identifier);
ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL(""));
ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL(""));
@@ -463,12 +467,12 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(ORIENTATION_VERTICAL);
/* JustificationFlag */
- BIND_ENUM_CONSTANT(JUSTIFICATION_NONE);
- BIND_ENUM_CONSTANT(JUSTIFICATION_KASHIDA);
- BIND_ENUM_CONSTANT(JUSTIFICATION_WORD_BOUND);
- BIND_ENUM_CONSTANT(JUSTIFICATION_TRIM_EDGE_SPACES);
- BIND_ENUM_CONSTANT(JUSTIFICATION_AFTER_LAST_TAB);
- BIND_ENUM_CONSTANT(JUSTIFICATION_CONSTRAIN_ELLIPSIS);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_NONE);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_KASHIDA);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_WORD_BOUND);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_TRIM_EDGE_SPACES);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_AFTER_LAST_TAB);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_CONSTRAIN_ELLIPSIS);
/* AutowrapMode */
BIND_ENUM_CONSTANT(AUTOWRAP_OFF);
@@ -477,11 +481,11 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART);
/* LineBreakFlag */
- BIND_ENUM_CONSTANT(BREAK_NONE);
- BIND_ENUM_CONSTANT(BREAK_MANDATORY);
- BIND_ENUM_CONSTANT(BREAK_WORD_BOUND);
- BIND_ENUM_CONSTANT(BREAK_GRAPHEME_BOUND);
- BIND_ENUM_CONSTANT(BREAK_WORD_BOUND_ADAPTIVE);
+ BIND_BITFIELD_FLAG(BREAK_NONE);
+ BIND_BITFIELD_FLAG(BREAK_MANDATORY);
+ BIND_BITFIELD_FLAG(BREAK_WORD_BOUND);
+ BIND_BITFIELD_FLAG(BREAK_GRAPHEME_BOUND);
+ BIND_BITFIELD_FLAG(BREAK_ADAPTIVE);
/* VisibleCharactersBehavior */
BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING);
@@ -498,25 +502,26 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ELLIPSIS);
/* TextOverrunFlag */
- BIND_ENUM_CONSTANT(OVERRUN_NO_TRIM);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ONLY);
- BIND_ENUM_CONSTANT(OVERRUN_ADD_ELLIPSIS);
- BIND_ENUM_CONSTANT(OVERRUN_ENFORCE_ELLIPSIS);
- BIND_ENUM_CONSTANT(OVERRUN_JUSTIFICATION_AWARE);
+ BIND_BITFIELD_FLAG(OVERRUN_NO_TRIM);
+ BIND_BITFIELD_FLAG(OVERRUN_TRIM);
+ BIND_BITFIELD_FLAG(OVERRUN_TRIM_WORD_ONLY);
+ BIND_BITFIELD_FLAG(OVERRUN_ADD_ELLIPSIS);
+ BIND_BITFIELD_FLAG(OVERRUN_ENFORCE_ELLIPSIS);
+ BIND_BITFIELD_FLAG(OVERRUN_JUSTIFICATION_AWARE);
/* GraphemeFlag */
- BIND_ENUM_CONSTANT(GRAPHEME_IS_VALID);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_RTL);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_VIRTUAL);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_SPACE);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_BREAK_HARD);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_BREAK_SOFT);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_TAB);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_ELONGATION);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_PUNCTUATION);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_UNDERSCORE);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_CONNECTED);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_VALID);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_RTL);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_VIRTUAL);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_SPACE);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_BREAK_HARD);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_BREAK_SOFT);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_TAB);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_ELONGATION);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_PUNCTUATION);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_UNDERSCORE);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_CONNECTED);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL);
/* Hinting */
BIND_ENUM_CONSTANT(HINTING_NONE);
@@ -545,6 +550,8 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE);
BIND_ENUM_CONSTANT(FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION);
BIND_ENUM_CONSTANT(FEATURE_USE_SUPPORT_DATA);
+ BIND_ENUM_CONSTANT(FEATURE_UNICODE_IDENTIFIERS);
+ BIND_ENUM_CONSTANT(FEATURE_UNICODE_SECURITY);
/* FT Contour Point Types */
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON);
@@ -556,11 +563,12 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(SPACING_SPACE);
BIND_ENUM_CONSTANT(SPACING_TOP);
BIND_ENUM_CONSTANT(SPACING_BOTTOM);
+ BIND_ENUM_CONSTANT(SPACING_MAX);
/* Font Style */
- BIND_ENUM_CONSTANT(FONT_BOLD);
- BIND_ENUM_CONSTANT(FONT_ITALIC);
- BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH);
+ BIND_BITFIELD_FLAG(FONT_BOLD);
+ BIND_BITFIELD_FLAG(FONT_ITALIC);
+ BIND_BITFIELD_FLAG(FONT_FIXED_WIDTH);
/* Structured text parser */
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT);
@@ -650,7 +658,7 @@ void TextServer::draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Ve
}
}
-PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t /*TextBreakFlag*/ p_break_flags) const {
+PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array lines;
ERR_FAIL_COND_V(p_width.is_empty(), lines);
@@ -687,7 +695,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
}
continue;
}
- if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
+ if (p_break_flags.has_flag(BREAK_MANDATORY)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
lines.push_back(line_start);
lines.push_back(l_gl[i].end);
@@ -701,12 +709,12 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
continue;
}
}
- if ((p_break_flags & BREAK_WORD_BOUND) == BREAK_WORD_BOUND) {
+ if (p_break_flags.has_flag(BREAK_WORD_BOUND)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_safe_break = i;
}
}
- if ((p_break_flags & BREAK_GRAPHEME_BOUND) == BREAK_GRAPHEME_BOUND) {
+ if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND)) {
last_safe_break = i;
}
}
@@ -726,7 +734,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
return lines;
}
-PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t /*TextBreakFlag*/ p_break_flags) const {
+PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array lines;
const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped);
@@ -755,7 +763,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
word_count = 0;
continue;
}
- if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
+ if (p_break_flags.has_flag(BREAK_MANDATORY)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
lines.push_back(line_start);
lines.push_back(l_gl[i].end);
@@ -765,16 +773,16 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
continue;
}
}
- if ((p_break_flags & BREAK_WORD_BOUND) == BREAK_WORD_BOUND) {
+ if (p_break_flags.has_flag(BREAK_WORD_BOUND)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_safe_break = i;
word_count++;
}
+ if (p_break_flags.has_flag(BREAK_ADAPTIVE) && word_count == 0) {
+ last_safe_break = i;
+ }
}
- if (((p_break_flags & BREAK_WORD_BOUND_ADAPTIVE) == BREAK_WORD_BOUND_ADAPTIVE) && word_count == 0) {
- last_safe_break = i;
- }
- if ((p_break_flags & BREAK_GRAPHEME_BOUND) == BREAK_GRAPHEME_BOUND) {
+ if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND)) {
last_safe_break = i;
}
}
@@ -794,7 +802,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
return lines;
}
-PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const {
+PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags) const {
PackedInt32Array words;
const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped);
@@ -1729,6 +1737,26 @@ Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped)
return ret;
}
+bool TextServer::is_valid_identifier(const String &p_string) const {
+ const char32_t *str = p_string.ptr();
+ int len = p_string.length();
+
+ if (len == 0) {
+ return false; // Empty string.
+ }
+
+ if (!is_unicode_identifier_start(str[0])) {
+ return false;
+ }
+
+ for (int i = 1; i < len; i++) {
+ if (!is_unicode_identifier_continue(str[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
TextServer::TextServer() {
_init_diacritics_map();
}
diff --git a/servers/text_server.h b/servers/text_server.h
index 6339dde0ea..d45bea3271 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -79,12 +79,12 @@ public:
AUTOWRAP_WORD_SMART
};
- enum LineBreakFlag { // LineBreakFlag can be passed in the same value as the JustificationFlag, do not use the same values.
+ enum LineBreakFlag {
BREAK_NONE = 0,
- BREAK_MANDATORY = 1 << 5,
- BREAK_WORD_BOUND = 1 << 6,
- BREAK_GRAPHEME_BOUND = 1 << 7,
- BREAK_WORD_BOUND_ADAPTIVE = 1 << 6 | 1 << 8,
+ BREAK_MANDATORY = 1 << 0,
+ BREAK_WORD_BOUND = 1 << 1,
+ BREAK_GRAPHEME_BOUND = 1 << 2,
+ BREAK_ADAPTIVE = 1 << 3,
};
enum OverrunBehavior {
@@ -116,6 +116,7 @@ public:
GRAPHEME_IS_PUNCTUATION = 1 << 8, // Punctuation, except underscore (can be used as word break, but not line break or justifiction).
GRAPHEME_IS_UNDERSCORE = 1 << 9, // Underscore (can be used as word break).
GRAPHEME_IS_CONNECTED = 1 << 10, // Connected to previous grapheme.
+ GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL = 1 << 11, // It is safe to insert a U+0640 before this grapheme for elongation.
};
enum Hinting {
@@ -148,6 +149,8 @@ public:
FEATURE_FONT_VARIABLE = 1 << 10,
FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 11,
FEATURE_USE_SUPPORT_DATA = 1 << 12,
+ FEATURE_UNICODE_IDENTIFIERS = 1 << 13,
+ FEATURE_UNICODE_SECURITY = 1 << 14,
};
enum ContourPointTag {
@@ -161,6 +164,7 @@ public:
SPACING_SPACE,
SPACING_TOP,
SPACING_BOTTOM,
+ SPACING_MAX,
};
enum FontStyle {
@@ -217,8 +221,8 @@ public:
virtual int64_t font_get_face_count(const RID &p_font_rid) const = 0;
- virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) = 0;
- virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const = 0;
+ virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) = 0;
+ virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const = 0;
virtual void font_set_name(const RID &p_font_rid, const String &p_name) = 0;
virtual String font_get_name(const RID &p_font_rid) const = 0;
@@ -284,9 +288,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 +387,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;
@@ -397,7 +401,7 @@ public:
virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range.
virtual RID shaped_text_get_parent(const RID &p_shaped) const = 0;
- virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0;
+ virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0;
virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) = 0;
virtual bool shaped_text_shape(const RID &p_shaped) = 0;
@@ -414,9 +418,9 @@ public:
virtual Vector2i shaped_text_get_range(const RID &p_shaped) const = 0;
- virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
- virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
- virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
+ virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
+ virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
+ virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const = 0;
virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const = 0;
@@ -424,7 +428,7 @@ public:
Array _shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const;
virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const = 0;
- virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) = 0;
+ virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) = 0;
virtual Array shaped_text_get_objects(const RID &p_shaped) const = 0;
virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const = 0;
@@ -462,7 +466,11 @@ public:
// String functions.
virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const = 0;
+ virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const { return -1; };
+ virtual bool spoof_check(const String &p_string) const { return false; };
+
virtual String strip_diacritics(const String &p_string) const;
+ virtual bool is_valid_identifier(const String &p_string) const;
// Other string operations.
virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0;
@@ -550,16 +558,16 @@ VARIANT_ENUM_CAST(TextServer::AutowrapMode);
VARIANT_ENUM_CAST(TextServer::OverrunBehavior);
VARIANT_ENUM_CAST(TextServer::Direction);
VARIANT_ENUM_CAST(TextServer::Orientation);
-VARIANT_ENUM_CAST(TextServer::JustificationFlag);
-VARIANT_ENUM_CAST(TextServer::LineBreakFlag);
-VARIANT_ENUM_CAST(TextServer::TextOverrunFlag);
-VARIANT_ENUM_CAST(TextServer::GraphemeFlag);
+VARIANT_BITFIELD_CAST(TextServer::JustificationFlag);
+VARIANT_BITFIELD_CAST(TextServer::LineBreakFlag);
+VARIANT_BITFIELD_CAST(TextServer::TextOverrunFlag);
+VARIANT_BITFIELD_CAST(TextServer::GraphemeFlag);
VARIANT_ENUM_CAST(TextServer::Hinting);
VARIANT_ENUM_CAST(TextServer::SubpixelPositioning);
VARIANT_ENUM_CAST(TextServer::Feature);
VARIANT_ENUM_CAST(TextServer::ContourPointTag);
VARIANT_ENUM_CAST(TextServer::SpacingType);
-VARIANT_ENUM_CAST(TextServer::FontStyle);
+VARIANT_BITFIELD_CAST(TextServer::FontStyle);
VARIANT_ENUM_CAST(TextServer::StructuredTextParser);
GDVIRTUAL_NATIVE_PTR(Glyph);
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 7ae111b5e7..4b9ea40223 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "xr_interface.h"
-// #include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_compositor.h"
void XRInterface::_bind_methods() {
ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode")));
@@ -114,7 +114,12 @@ void XRInterface::set_primary(bool p_primary) {
XRInterface::XRInterface() {}
-XRInterface::~XRInterface() {}
+XRInterface::~XRInterface() {
+ if (vrs.vrs_texture.is_valid()) {
+ RS::get_singleton()->free(vrs.vrs_texture);
+ vrs.vrs_texture = RID();
+ }
+}
// query if this interface supports this play area mode
bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
@@ -151,6 +156,85 @@ int XRInterface::get_camera_feed_id() {
return 0;
}
+RID XRInterface::get_vrs_texture() {
+ // Default logic will return a standard VRS image based on our target size and default projections.
+ // Note that this only gets called if VRS is supported on the hardware.
+
+ Size2 texel_size = Size2(16.0, 16.0); // For now we assume we always use 16x16 texels, seems to be the standard.
+ int view_count = get_view_count();
+ Size2 target_size = get_render_target_size();
+ real_t aspect = target_size.x / target_size.y; // is this y/x ?
+ Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_size.x), round(0.5 + target_size.y / texel_size.y));
+ real_t radius = vrs_size.length() * 0.5;
+ Size2 vrs_sizei = vrs_size;
+
+ if (vrs.size != vrs_sizei) {
+ const uint8_t densities[] = {
+ 0, // 1x1
+ 1, // 1x2
+ // 4, // 2x1
+ 5, // 2x2
+ 6, // 2x4
+ // 9, // 4x2
+ 10, // 4x4
+ };
+
+ // out with the old
+ if (vrs.vrs_texture.is_valid()) {
+ RS::get_singleton()->free(vrs.vrs_texture);
+ vrs.vrs_texture = RID();
+ }
+
+ // in with the new
+ Vector<Ref<Image>> images;
+ vrs.size = vrs_sizei;
+
+ for (int i = 0; i < view_count && i < 2; i++) {
+ PackedByteArray data;
+ data.resize(vrs_sizei.x * vrs_sizei.y);
+ uint8_t *data_ptr = data.ptrw();
+
+ // Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result...
+ Projection cm = get_projection_for_view(i, aspect, 0.1, 1000.0);
+ Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0));
+
+ Vector2i view_center;
+ view_center.x = int(vrs_size.x * (center.x + 1.0) * 0.5);
+ view_center.y = int(vrs_size.y * (center.y + 1.0) * 0.5);
+
+ int d = 0;
+ for (int y = 0; y < vrs_sizei.y; y++) {
+ for (int x = 0; x < vrs_sizei.x; x++) {
+ Vector2 offset = Vector2(x - view_center.x, y - view_center.y);
+ offset.y *= aspect;
+ real_t distance = offset.length();
+ int idx = round(5.0 * distance / radius);
+ if (idx > 4) {
+ idx = 4;
+ }
+ uint8_t density = densities[idx];
+
+ data_ptr[d++] = density;
+ }
+ }
+
+ Ref<Image> image;
+ image.instantiate();
+ image->create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data);
+
+ images.push_back(image);
+ }
+
+ if (images.size() == 1) {
+ vrs.vrs_texture = RS::get_singleton()->texture_2d_create(images[0]);
+ } else {
+ vrs.vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY);
+ }
+ }
+
+ return vrs.vrs_texture;
+}
+
/** these are optional, so we want dummies **/
PackedStringArray XRInterface::get_suggested_tracker_names() const {
PackedStringArray arr;
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 62eba2f00b..f11458f1cc 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -31,7 +31,7 @@
#ifndef XR_INTERFACE_H
#define XR_INTERFACE_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/os/thread_safe.h"
#include "servers/xr_server.h"
@@ -119,7 +119,8 @@ public:
virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */
virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
- virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
+ virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
+ virtual RID get_vrs_texture(); /* obtain VRS texture */
// note, external color/depth/vrs texture support will be added here soon.
@@ -133,6 +134,12 @@ public:
XRInterface();
~XRInterface();
+
+private:
+ struct VRSData {
+ RID vrs_texture;
+ Size2i size;
+ } vrs;
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index a0bec0f95b..7395cd5ad4 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() {
@@ -52,6 +50,7 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_camera_transform);
GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform");
GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far");
+ GDVIRTUAL_BIND(_get_vrs_texture);
GDVIRTUAL_BIND(_process);
GDVIRTUAL_BIND(_pre_render);
@@ -259,12 +258,12 @@ Transform3D XRInterfaceExtension::get_transform_for_view(uint32_t p_view, const
return Transform3D();
}
-CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
- CameraMatrix cm;
+Projection XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
+ Projection cm;
PackedFloat64Array arr;
if (GDVIRTUAL_CALL(_get_projection_for_view, p_view, p_aspect, p_z_near, p_z_far, arr)) {
- ERR_FAIL_COND_V_MSG(arr.size() != 16, CameraMatrix(), "Projection matrix must contain 16 floats");
+ ERR_FAIL_COND_V_MSG(arr.size() != 16, Projection(), "Projection matrix must contain 16 floats");
real_t *m = (real_t *)cm.matrix;
for (int i = 0; i < 16; i++) {
m[i] = arr[i];
@@ -272,7 +271,16 @@ CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, doub
return cm;
}
- return CameraMatrix();
+ return Projection();
+}
+
+RID XRInterfaceExtension::get_vrs_texture() {
+ RID vrs_texture;
+ if (GDVIRTUAL_CALL(_get_vrs_texture, vrs_texture)) {
+ return vrs_texture;
+ } else {
+ return XRInterface::get_vrs_texture();
+ }
}
void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) {
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
index 5a436b9fd0..65b474425e 100644
--- a/servers/xr/xr_interface_extension.h
+++ b/servers/xr/xr_interface_extension.h
@@ -100,13 +100,15 @@ public:
virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
- virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
+ virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
+ virtual RID get_vrs_texture() override;
GDVIRTUAL0R(Size2, _get_render_target_size);
GDVIRTUAL0R(uint32_t, _get_view_count);
GDVIRTUAL0R(Transform3D, _get_camera_transform);
GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
+ GDVIRTUAL0R(RID, _get_vrs_texture);
void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0);
@@ -130,4 +132,4 @@ public:
// RID get_render_target_depth(RID p_render_target);
};
-#endif // !XR_INTERFACE_EXTENSION_H
+#endif // XR_INTERFACE_EXTENSION_H
diff --git a/servers/xr/xr_pose.h b/servers/xr/xr_pose.h
index f306c22390..e7d363764b 100644
--- a/servers/xr/xr_pose.h
+++ b/servers/xr/xr_pose.h
@@ -78,4 +78,4 @@ public:
VARIANT_ENUM_CAST(XRPose::TrackingConfidence);
-#endif
+#endif // XR_POSE_H
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index ad61aa94bc..990281d96d 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -33,6 +33,16 @@
#include "xr/xr_interface.h"
#include "xr/xr_positional_tracker.h"
+XRServer::XRMode XRServer::xr_mode = XRMODE_DEFAULT;
+
+XRServer::XRMode XRServer::get_xr_mode() {
+ return xr_mode;
+}
+
+void XRServer::set_xr_mode(XRServer::XRMode p_mode) {
+ xr_mode = p_mode;
+}
+
XRServer *XRServer::singleton = nullptr;
XRServer *XRServer::get_singleton() {
diff --git a/servers/xr_server.h b/servers/xr_server.h
index d9188d2de1..74128bfb54 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -57,6 +57,12 @@ class XRServer : public Object {
_THREAD_SAFE_CLASS_
public:
+ enum XRMode {
+ XRMODE_DEFAULT, /* Default behaviour, means we check project settings */
+ XRMODE_OFF, /* Ignore project settings, disable OpenXR, disable shaders */
+ XRMODE_ON, /* Ignore project settings, enable OpenXR, enable shaders, run editor in VR (if applicable) */
+ };
+
enum TrackerType {
TRACKER_HEAD = 0x01, /* tracks the position of the players head (or in case of handheld AR, location of the phone) */
TRACKER_CONTROLLER = 0x02, /* tracks a controller */
@@ -75,6 +81,8 @@ public:
};
private:
+ static XRMode xr_mode;
+
Vector<Ref<XRInterface>> interfaces;
Dictionary trackers;
@@ -90,6 +98,9 @@ protected:
static void _bind_methods();
public:
+ static XRMode get_xr_mode();
+ static void set_xr_mode(XRMode p_mode);
+
static XRServer *get_singleton();
/*
diff --git a/tests/core/input/test_input_event_key.h b/tests/core/input/test_input_event_key.h
new file mode 100644
index 0000000000..5d4ca55a35
--- /dev/null
+++ b/tests/core/input/test_input_event_key.h
@@ -0,0 +1,294 @@
+/*************************************************************************/
+/* test_input_event_key.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_INPUT_EVENT_KEY_H
+#define TEST_INPUT_EVENT_KEY_H
+
+#include "core/input/input_event.h"
+#include "core/os/keyboard.h"
+
+#include "tests/test_macros.h"
+
+namespace TestInputEventKey {
+
+TEST_CASE("[InputEventKey] Key correctly registers being pressed") {
+ InputEventKey key;
+ key.set_pressed(true);
+ CHECK(key.is_pressed() == true);
+
+ key.set_pressed(false);
+ CHECK(key.is_pressed() == false);
+}
+
+TEST_CASE("[InputEventKey] Key correctly stores and retrieves keycode") {
+ InputEventKey key;
+
+ key.set_keycode(Key::ENTER);
+ CHECK(key.get_keycode() == Key::ENTER);
+ CHECK(key.get_keycode() != Key::PAUSE);
+
+ key.set_physical_keycode(Key::BACKSPACE);
+ CHECK(key.get_physical_keycode() == Key::BACKSPACE);
+ CHECK(key.get_physical_keycode() != Key::PAUSE);
+}
+
+TEST_CASE("[InputEventKey] Key correctly stores and retrieves keycode with modifiers") {
+ InputEventKey key;
+
+ key.set_keycode(Key::ENTER);
+ key.set_ctrl_pressed(true);
+
+ CHECK(key.get_keycode_with_modifiers() == (Key::ENTER | KeyModifierMask::CTRL));
+ CHECK(key.get_keycode_with_modifiers() != (Key::ENTER | KeyModifierMask::SHIFT));
+ CHECK(key.get_keycode_with_modifiers() != Key::ENTER);
+
+ key.set_physical_keycode(Key::SPACE);
+ key.set_ctrl_pressed(true);
+
+ CHECK(key.get_physical_keycode_with_modifiers() == (Key::SPACE | KeyModifierMask::CTRL));
+ CHECK(key.get_physical_keycode_with_modifiers() != (Key::SPACE | KeyModifierMask::SHIFT));
+ CHECK(key.get_physical_keycode_with_modifiers() != Key::SPACE);
+}
+
+TEST_CASE("[InputEventKey] Key correctly stores and retrieves unicode") {
+ InputEventKey key;
+
+ key.set_unicode('x');
+ CHECK(key.get_unicode() == 'x');
+ CHECK(key.get_unicode() != 'y');
+}
+
+TEST_CASE("[InputEventKey] Key correctly stores and checks echo") {
+ InputEventKey key;
+
+ key.set_echo(true);
+ CHECK(key.is_echo() == true);
+
+ key.set_echo(false);
+ CHECK(key.is_echo() == false);
+}
+
+TEST_CASE("[InputEventKey] Key correctly converts itself to text") {
+ InputEventKey none_key;
+
+ // These next three tests test the functionality of getting a key that is set to None
+ // as text. These cases are a bit weird, since None has no textual representation
+ // (find_keycode_name(Key::NONE) results in a nullptr). Thus, these tests look weird
+ // with only (Physical) or a lonely modifier with (Physical) but (as far as I
+ // understand the code, that is intended behaviour.
+
+ // Key is None without a physical key.
+ none_key.set_keycode(Key::NONE);
+ CHECK(none_key.as_text() == " (Physical)");
+
+ // Key is none and has modifiers.
+ none_key.set_ctrl_pressed(true);
+ CHECK(none_key.as_text() == "Ctrl+ (Physical)");
+
+ // Key is None WITH a physical key AND modifiers.
+ none_key.set_physical_keycode(Key::ENTER);
+ CHECK(none_key.as_text() == "Ctrl+Enter (Physical)");
+
+ InputEventKey none_key2;
+
+ // Key is None without modifers with a physical key.
+ none_key2.set_keycode(Key::NONE);
+ none_key2.set_physical_keycode(Key::ENTER);
+
+ CHECK(none_key2.as_text() == "Enter (Physical)");
+
+ InputEventKey key;
+
+ // Key has keycode.
+ key.set_keycode(Key::SPACE);
+ CHECK(key.as_text() != "");
+ CHECK(key.as_text() == "Space");
+
+ // Key has keycode and modifiers.
+ key.set_ctrl_pressed(true);
+ CHECK(key.as_text() != "Space");
+ CHECK(key.as_text() == "Ctrl+Space");
+
+ // Since the keycode is set to Key::NONE upon initialization of the
+ // InputEventKey and you can only update it with another Key, the keycode
+ // cannot be empty, so the kc.is_empty() case cannot be tested.
+}
+
+TEST_CASE("[InputEventKey] Key correctly converts its state to a string representation") {
+ InputEventKey none_key;
+
+ // Set physical to true.
+ CHECK(none_key.to_string() == "InputEventKey: keycode=0 (), mods=none, physical=true, pressed=false, echo=false");
+ // Set physical key to Escape.
+ none_key.set_physical_keycode(Key::ESCAPE);
+ CHECK(none_key.to_string() == "InputEventKey: keycode=16777217 (Escape), mods=none, physical=true, pressed=false, echo=false");
+
+ InputEventKey key;
+
+ // Set physical to None, set keycode to Space.
+ key.set_keycode(Key::SPACE);
+ CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=none, physical=false, pressed=false, echo=false");
+
+ // Set pressed to true.
+ key.set_pressed(true);
+ CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=none, physical=false, pressed=true, echo=false");
+
+ // set echo to true.
+ key.set_echo(true);
+ CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=none, physical=false, pressed=true, echo=true");
+
+ // Press Ctrl and Alt.
+ key.set_ctrl_pressed(true);
+ key.set_alt_pressed(true);
+ CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=Ctrl+Alt, physical=false, pressed=true, echo=true");
+}
+
+TEST_CASE("[InputEventKey] Key is correctly converted to reference") {
+ InputEventKey base_key;
+ Ref<InputEventKey> key_ref = base_key.create_reference(Key::ENTER);
+
+ CHECK(key_ref->get_keycode() == Key::ENTER);
+}
+
+TEST_CASE("[InputEventKey] Keys are correctly matched based on action") {
+ bool pressed = false;
+ float strength, raw_strength = 0.0;
+
+ InputEventKey key;
+
+ // Nullptr.
+ CHECK_MESSAGE(key.action_match(nullptr, false, 0.0f, &pressed, &strength, &raw_strength) == false, "nullptr as key reference should result in false");
+
+ // Match on keycode.
+ key.set_keycode(Key::SPACE);
+ Ref<InputEventKey> match = key.create_reference(Key::SPACE);
+ Ref<InputEventKey> no_match = key.create_reference(Key::ENTER);
+
+ CHECK(key.action_match(match, false, 0.0f, &pressed, &strength, &raw_strength) == true);
+ CHECK(key.action_match(no_match, false, 0.0f, &pressed, &strength, &raw_strength) == false);
+
+ // Check that values are correctly transferred to the pointers.
+ CHECK(pressed == false);
+ CHECK(strength < 0.5);
+ CHECK(raw_strength < 0.5);
+
+ match->set_pressed(true);
+ key.action_match(match, false, 0.0f, &pressed, &strength, &raw_strength);
+
+ CHECK(pressed == true);
+ CHECK(strength > 0.5);
+ CHECK(raw_strength > 0.5);
+
+ // Tests when keycode is None: Then you rely on physical keycode.
+ InputEventKey none_key;
+ none_key.set_physical_keycode(Key::SPACE);
+
+ Ref<InputEventKey> match_none = none_key.create_reference(Key::NONE);
+ match_none->set_physical_keycode(Key::SPACE);
+
+ Ref<InputEventKey> no_match_none = none_key.create_reference(Key::NONE);
+ no_match_none->set_physical_keycode(Key::ENTER);
+
+ CHECK(none_key.action_match(match_none, false, 0.0f, &pressed, &strength, &raw_strength) == true);
+ CHECK(none_key.action_match(no_match_none, false, 0.0f, &pressed, &strength, &raw_strength) == false);
+
+ // Test exact match.
+ InputEventKey key2, ref_key;
+ key2.set_keycode(Key::SPACE);
+
+ Ref<InputEventKey> match2 = ref_key.create_reference(Key::SPACE);
+
+ // Now both press Ctrl and Shift.
+ key2.set_ctrl_pressed(true);
+ key2.set_shift_pressed(true);
+
+ match2->set_ctrl_pressed(true);
+ match2->set_shift_pressed(true);
+
+ // Now they should match.
+ bool exact_match = true;
+ CHECK(key2.action_match(match2, exact_match, 0.0f, &pressed, &strength, &raw_strength) == true);
+
+ // Modify matching key such that it does no longer match in terms of modifiers: Shift
+ // is no longer pressed.
+ match2->set_shift_pressed(false);
+ CHECK(match2->is_shift_pressed() == false);
+ CHECK(key2.action_match(match2, exact_match, 0.0f, &pressed, &strength, &raw_strength) == false);
+}
+
+TEST_CASE("[IsMatch] Keys are correctly matched") {
+ // Key with NONE as keycode.
+ InputEventKey key;
+ key.set_keycode(Key::NONE);
+ key.set_physical_keycode(Key::SPACE);
+
+ // Nullptr.
+ CHECK(key.is_match(nullptr, false) == false);
+
+ Ref<InputEventKey> none_ref = key.create_reference(Key::NONE);
+
+ none_ref->set_physical_keycode(Key::SPACE);
+ CHECK(key.is_match(none_ref, false) == true);
+
+ none_ref->set_physical_keycode(Key::ENTER);
+ CHECK(key.is_match(none_ref, false) == false);
+
+ none_ref->set_physical_keycode(Key::SPACE);
+
+ key.set_ctrl_pressed(true);
+ none_ref->set_ctrl_pressed(false);
+ CHECK(key.is_match(none_ref, true) == false);
+
+ none_ref->set_ctrl_pressed(true);
+ CHECK(key.is_match(none_ref, true) == true);
+
+ // Ref with actual keycode.
+ InputEventKey key2;
+ key2.set_keycode(Key::SPACE);
+
+ Ref<InputEventKey> match = key2.create_reference(Key::SPACE);
+ Ref<InputEventKey> no_match = key2.create_reference(Key::ENTER);
+
+ CHECK(key2.is_match(match, false) == true);
+ CHECK(key2.is_match(no_match, false) == false);
+
+ // Now the keycode is the same, but the modifiers differ.
+ no_match->set_keycode(Key::SPACE);
+
+ key2.set_ctrl_pressed(true);
+ match->set_ctrl_pressed(true);
+ no_match->set_shift_pressed(true);
+
+ CHECK(key2.is_match(match, true) == true);
+ CHECK(key2.is_match(no_match, true) == false);
+}
+} // namespace TestInputEventKey
+
+#endif // TEST_INPUT_EVENT_KEY_H
diff --git a/tests/core/input/test_shortcut.h b/tests/core/input/test_shortcut.h
new file mode 100644
index 0000000000..93edc685ad
--- /dev/null
+++ b/tests/core/input/test_shortcut.h
@@ -0,0 +1,235 @@
+/*************************************************************************/
+/* test_shortcut.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_SHORTCUT_H
+#define TEST_SHORTCUT_H
+
+#include "core/input/input_event.h"
+#include "core/input/shortcut.h"
+#include "core/io/config_file.h"
+#include "core/object/ref_counted.h"
+#include "core/os/keyboard.h"
+#include "core/os/os.h"
+
+#include "tests/test_macros.h"
+
+namespace TestShortcut {
+
+TEST_CASE("[Shortcut] Empty shortcut should have no valid events and text equal to None") {
+ Shortcut s;
+
+ CHECK(s.get_as_text() == "None");
+ CHECK(s.has_valid_event() == false);
+}
+
+TEST_CASE("[Shortcut] Setting and getting an event should result in the same event as the input") {
+ Ref<InputEventKey> k1;
+ Ref<InputEventKey> k2;
+ k1.instantiate();
+ k2.instantiate();
+
+ k1->set_keycode(Key::ENTER);
+ k2->set_keycode(Key::BACKSPACE);
+
+ // Cast to InputEvent so the internal code recognizes the objects.
+ Ref<InputEvent> e1 = k1;
+ Ref<InputEvent> e2 = k2;
+
+ Array input_array;
+ input_array.append(e1);
+ input_array.append(e2);
+
+ Shortcut s;
+ s.set_events(input_array);
+
+ // Get result, read it out, check whether it equals the input.
+ Array result_array = s.get_events();
+ Ref<InputEventKey> result1 = result_array.front();
+ Ref<InputEventKey> result2 = result_array.back();
+
+ CHECK(result1->get_keycode() == k1->get_keycode());
+ CHECK(result2->get_keycode() == k2->get_keycode());
+}
+
+TEST_CASE("[Shortcut] 'set_events_list' should result in the same events as the input") {
+ Ref<InputEventKey> k1;
+ Ref<InputEventKey> k2;
+ k1.instantiate();
+ k2.instantiate();
+
+ k1->set_keycode(Key::ENTER);
+ k2->set_keycode(Key::BACKSPACE);
+
+ // Cast to InputEvent so the set_events_list() method recognizes the objects.
+ Ref<InputEvent> e1 = k1;
+ Ref<InputEvent> e2 = k2;
+
+ List<Ref<InputEvent>> list;
+ list.push_back(e1);
+ list.push_back(e2);
+
+ Shortcut s;
+ s.set_events_list(&list);
+
+ // Get result, read it out, check whether it equals the input.
+ Array result_array = s.get_events();
+ Ref<InputEventKey> result1 = result_array.front();
+ Ref<InputEventKey> result2 = result_array.back();
+
+ CHECK(result1->get_keycode() == k1->get_keycode());
+ CHECK(result2->get_keycode() == k2->get_keycode());
+}
+
+TEST_CASE("[Shortcut] 'matches_event' should correctly match the same event") {
+ Ref<InputEventKey> original; // The one we compare with.
+ Ref<InputEventKey> similar_but_not_equal; // Same keycode, different event.
+ Ref<InputEventKey> different; // Different event, different keycode.
+ Ref<InputEventKey> copy; // Copy of original event.
+
+ original.instantiate();
+ similar_but_not_equal.instantiate();
+ different.instantiate();
+ copy.instantiate();
+
+ original->set_keycode(Key::ENTER);
+ similar_but_not_equal->set_keycode(Key::ENTER);
+ similar_but_not_equal->set_keycode(Key::ESCAPE);
+ copy = original;
+
+ // Only the copy is really the same, so only that one should match.
+ // The rest should not match.
+
+ Ref<InputEvent> e_original = original;
+
+ Ref<InputEvent> e_similar_but_not_equal = similar_but_not_equal;
+ Ref<InputEvent> e_different = different;
+ Ref<InputEvent> e_copy = copy;
+
+ Array a;
+ a.append(e_original);
+ Shortcut s;
+ s.set_events(a);
+
+ CHECK(s.matches_event(e_similar_but_not_equal) == false);
+ CHECK(s.matches_event(e_different) == false);
+
+ CHECK(s.matches_event(e_copy) == true);
+}
+
+TEST_CASE("[Shortcut] 'get_as_text' text representation should be correct") {
+ Ref<InputEventKey> same;
+ // k2 will not go into the shortcut but only be used to compare.
+ Ref<InputEventKey> different;
+
+ same.instantiate();
+ different.instantiate();
+
+ same->set_keycode(Key::ENTER);
+ different->set_keycode(Key::ESCAPE);
+
+ Ref<InputEvent> key_event1 = same;
+
+ Array a;
+ a.append(key_event1);
+ Shortcut s;
+ s.set_events(a);
+
+ CHECK(s.get_as_text() == same->as_text());
+ CHECK(s.get_as_text() != different->as_text());
+}
+
+TEST_CASE("[Shortcut] Event validity should be correctly checked.") {
+ Ref<InputEventKey> valid;
+ // k2 will not go into the shortcut but only be used to compare.
+ Ref<InputEventKey> invalid = nullptr;
+
+ valid.instantiate();
+ valid->set_keycode(Key::ENTER);
+
+ Ref<InputEvent> valid_event = valid;
+ Ref<InputEvent> invalid_event = invalid;
+
+ Array a;
+ a.append(invalid_event);
+ a.append(valid_event);
+
+ Shortcut s;
+ s.set_events(a);
+
+ CHECK(s.has_valid_event() == true);
+
+ Array b;
+ b.append(invalid_event);
+
+ Shortcut shortcut_with_invalid_event;
+ shortcut_with_invalid_event.set_events(b);
+
+ CHECK(shortcut_with_invalid_event.has_valid_event() == false);
+}
+
+TEST_CASE("[Shortcut] Equal arrays should be recognized as such.") {
+ Ref<InputEventKey> k1;
+ // k2 will not go into the shortcut but only be used to compare.
+ Ref<InputEventKey> k2;
+
+ k1.instantiate();
+ k2.instantiate();
+
+ k1->set_keycode(Key::ENTER);
+ k2->set_keycode(Key::ESCAPE);
+
+ Ref<InputEvent> key_event1 = k1;
+ Ref<InputEvent> key_event2 = k2;
+
+ Array same;
+ same.append(key_event1);
+
+ Array same_as_same;
+ same_as_same.append(key_event1);
+
+ Array different1;
+ different1.append(key_event2);
+
+ Array different2;
+ different2.append(key_event1);
+ different2.append(key_event2);
+
+ Array different3;
+
+ Shortcut s;
+
+ CHECK(s.is_event_array_equal(same, same_as_same) == true);
+ CHECK(s.is_event_array_equal(same, different1) == false);
+ CHECK(s.is_event_array_equal(same, different2) == false);
+ CHECK(s.is_event_array_equal(same, different3) == false);
+}
+} // namespace TestShortcut
+
+#endif // TEST_SHORTCUT_H
diff --git a/tests/core/io/test_file_access.h b/tests/core/io/test_file_access.h
index f0e1cceacf..aab62955cb 100644
--- a/tests/core/io/test_file_access.h
+++ b/tests/core/io/test_file_access.h
@@ -78,6 +78,29 @@ TEST_CASE("[FileAccess] CSV read") {
CHECK(row5[1] == "tab separated");
CHECK(row5[2] == "lines, good?");
}
+
+TEST_CASE("[FileAccess] Get as UTF-8 String") {
+ Ref<FileAccess> f_lf = FileAccess::open(TestUtils::get_data_path("line_endings_lf.test.txt"), FileAccess::READ);
+ String s_lf = f_lf->get_as_utf8_string();
+ f_lf->seek(0);
+ String s_lf_nocr = f_lf->get_as_utf8_string(true);
+ CHECK(s_lf == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n");
+ CHECK(s_lf_nocr == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n");
+
+ Ref<FileAccess> f_crlf = FileAccess::open(TestUtils::get_data_path("line_endings_crlf.test.txt"), FileAccess::READ);
+ String s_crlf = f_crlf->get_as_utf8_string();
+ f_crlf->seek(0);
+ String s_crlf_nocr = f_crlf->get_as_utf8_string(true);
+ CHECK(s_crlf == "Hello darkness\r\nMy old friend\r\nI've come to talk\r\nWith you again\r\n");
+ CHECK(s_crlf_nocr == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n");
+
+ Ref<FileAccess> f_cr = FileAccess::open(TestUtils::get_data_path("line_endings_cr.test.txt"), FileAccess::READ);
+ String s_cr = f_cr->get_as_utf8_string();
+ f_cr->seek(0);
+ String s_cr_nocr = f_cr->get_as_utf8_string(true);
+ CHECK(s_cr == "Hello darkness\rMy old friend\rI've come to talk\rWith you again\r");
+ CHECK(s_cr_nocr == "Hello darknessMy old friendI've come to talkWith you again");
+}
} // namespace TestFileAccess
#endif // TEST_FILE_ACCESS_H
diff --git a/tests/core/io/test_image.h b/tests/core/io/test_image.h
index 1c778c3228..36e6b83bfd 100644
--- a/tests/core/io/test_image.h
+++ b/tests/core/io/test_image.h
@@ -161,8 +161,8 @@ TEST_CASE("[Image] Basic getters") {
CHECK(image->get_height() == 4);
CHECK(image->get_size() == Vector2(8, 4));
CHECK(image->get_format() == Image::FORMAT_LA8);
- CHECK(image->get_used_rect() == Rect2(0, 0, 0, 0));
- Ref<Image> image_get_rect = image->get_rect(Rect2(0, 0, 2, 1));
+ CHECK(image->get_used_rect() == Rect2i(0, 0, 0, 0));
+ Ref<Image> image_get_rect = image->get_rect(Rect2i(0, 0, 2, 1));
CHECK(image_get_rect->get_size() == Vector2(2, 1));
}
@@ -213,8 +213,8 @@ TEST_CASE("[Image] Modifying pixels of an image") {
image->get_pixelv(Vector2(0, 0)).is_equal_approx(Color(1, 1, 1, 1)),
"Image's get_pixel() should return the same color value as the one being set with set_pixel() in the same position.");
CHECK_MESSAGE(
- image->get_used_rect() == Rect2(0, 0, 1, 1),
- "Image's get_used_rect should return the expected value, larger than Rect2(0, 0, 0, 0) if it's visible.");
+ image->get_used_rect() == Rect2i(0, 0, 1, 1),
+ "Image's get_used_rect should return the expected value, larger than Rect2i(0, 0, 0, 0) if it's visible.");
image->set_pixelv(Vector2(0, 0), Color(0.5, 0.5, 0.5, 0.5));
Ref<Image> image2 = memnew(Image(3, 3, false, Image::FORMAT_RGBA8));
@@ -233,19 +233,19 @@ TEST_CASE("[Image] Modifying pixels of an image") {
{
const int img_width = 3;
const int img_height = 3;
- Vector<Rect2> rects;
- rects.push_back(Rect2());
- rects.push_back(Rect2(-5, -5, 3, 3));
- rects.push_back(Rect2(img_width, 0, 12, 12));
- rects.push_back(Rect2(0, img_height, 12, 12));
- rects.push_back(Rect2(img_width + 1, img_height + 2, 12, 12));
- rects.push_back(Rect2(1, 1, 1, 1));
- rects.push_back(Rect2(0, 1, 2, 3));
- rects.push_back(Rect2(-5, 0, img_width + 10, 2));
- rects.push_back(Rect2(0, -5, 2, img_height + 10));
- rects.push_back(Rect2(-1, -1, img_width + 1, img_height + 1));
-
- for (const Rect2 &rect : rects) {
+ Vector<Rect2i> rects;
+ rects.push_back(Rect2i());
+ rects.push_back(Rect2i(-5, -5, 3, 3));
+ rects.push_back(Rect2i(img_width, 0, 12, 12));
+ rects.push_back(Rect2i(0, img_height, 12, 12));
+ rects.push_back(Rect2i(img_width + 1, img_height + 2, 12, 12));
+ rects.push_back(Rect2i(1, 1, 1, 1));
+ rects.push_back(Rect2i(0, 1, 2, 3));
+ rects.push_back(Rect2i(-5, 0, img_width + 10, 2));
+ rects.push_back(Rect2i(0, -5, 2, img_height + 10));
+ rects.push_back(Rect2i(-1, -1, img_width + 1, img_height + 1));
+
+ for (const Rect2i &rect : rects) {
Ref<Image> img = memnew(Image(img_width, img_height, false, Image::FORMAT_RGBA8));
CHECK_NOTHROW_MESSAGE(
img->fill_rect(rect, Color(1, 1, 1, 1)),
@@ -267,7 +267,7 @@ TEST_CASE("[Image] Modifying pixels of an image") {
}
// Blend two images together
- image->blend_rect(image2, Rect2(Vector2(0, 0), image2->get_size()), Vector2(0, 0));
+ image->blend_rect(image2, Rect2i(Vector2i(0, 0), image2->get_size()), Vector2i(0, 0));
CHECK_MESSAGE(
image->get_pixel(0, 0).a > 0.7,
"blend_rect() should blend the alpha values of the two images.");
@@ -279,7 +279,7 @@ TEST_CASE("[Image] Modifying pixels of an image") {
image3->set_pixel(0, 0, Color(0, 1, 0, 1));
//blit_rect() two images together
- image->blit_rect(image3, Rect2(Vector2(0, 0), image3->get_size()), Vector2(0, 0));
+ image->blit_rect(image3, Rect2i(Vector2i(0, 0), image3->get_size()), Vector2i(0, 0));
CHECK_MESSAGE(
image->get_pixel(0, 0).is_equal_approx(Color(0, 1, 0, 1)),
"blit_rect() should replace old colors and not blend them.");
@@ -300,4 +300,5 @@ TEST_CASE("[Image] Modifying pixels of an image") {
"flip_y() should not leave old pixels behind.");
}
} // namespace TestImage
+
#endif // TEST_IMAGE_H
diff --git a/tests/core/io/test_marshalls.h b/tests/core/io/test_marshalls.h
index 546a2e9358..7490df2b2c 100644
--- a/tests/core/io/test_marshalls.h
+++ b/tests/core/io/test_marshalls.h
@@ -254,11 +254,13 @@ TEST_CASE("[Marshalls] Invalid data Variant decoding") {
uint8_t some_buffer[1] = { 0x00 };
uint8_t out_of_range_type_buffer[4] = { 0xff }; // Greater than Variant::VARIANT_MAX
+ ERR_PRINT_OFF;
CHECK(decode_variant(variant, some_buffer, /* less than 4 */ 1, &r_len) == ERR_INVALID_DATA);
CHECK(r_len == 0);
CHECK(decode_variant(variant, out_of_range_type_buffer, 4, &r_len) == ERR_INVALID_DATA);
CHECK(r_len == 0);
+ ERR_PRINT_ON;
}
TEST_CASE("[Marshalls] NIL Variant decoding") {
diff --git a/tests/core/io/test_resource.h b/tests/core/io/test_resource.h
index 84d651b63f..c880ca7d2a 100644
--- a/tests/core/io/test_resource.h
+++ b/tests/core/io/test_resource.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef TEST_RESOURCE
-#define TEST_RESOURCE
+#ifndef TEST_RESOURCE_H
+#define TEST_RESOURCE_H
#include "core/io/resource.h"
#include "core/io/resource_loader.h"
@@ -76,8 +76,8 @@ TEST_CASE("[Resource] Saving and loading") {
resource->set_meta("other_resource", child_resource);
const String save_path_binary = OS::get_singleton()->get_cache_path().plus_file("resource.res");
const String save_path_text = OS::get_singleton()->get_cache_path().plus_file("resource.tres");
- ResourceSaver::save(save_path_binary, resource);
- ResourceSaver::save(save_path_text, resource);
+ ResourceSaver::save(resource, save_path_binary);
+ ResourceSaver::save(resource, save_path_text);
const Ref<Resource> &loaded_resource_binary = ResourceLoader::load(save_path_binary);
CHECK_MESSAGE(
@@ -111,4 +111,4 @@ TEST_CASE("[Resource] Saving and loading") {
}
} // namespace TestResource
-#endif // TEST_RESOURCE
+#endif // TEST_RESOURCE_H
diff --git a/tests/core/math/test_aabb.h b/tests/core/math/test_aabb.h
index 526972a82f..447420fc12 100644
--- a/tests/core/math/test_aabb.h
+++ b/tests/core/math/test_aabb.h
@@ -299,34 +299,28 @@ TEST_CASE("[AABB] Get longest/shortest axis") {
"get_shortest_axis_size() should return the expected value.");
}
-#ifndef _MSC_VER
-#warning Support tests need to be re-done
-#endif
-
-/* Support function was actually broken. As it was fixed, the tests now fail. Tests need to be re-done.
-
TEST_CASE("[AABB] Get support") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
- aabb.get_support(Vector3(1, 0, 0)).is_equal_approx(Vector3(-1.5, 7, 3.5)),
+ aabb.get_support(Vector3(1, 0, 0)).is_equal_approx(Vector3(2.5, 2, -2.5)),
"get_support() should return the expected value.");
CHECK_MESSAGE(
- aabb.get_support(Vector3(0.5, 1, 0)).is_equal_approx(Vector3(-1.5, 2, 3.5)),
+ aabb.get_support(Vector3(0.5, 1, 0)).is_equal_approx(Vector3(2.5, 7, -2.5)),
"get_support() should return the expected value.");
CHECK_MESSAGE(
- aabb.get_support(Vector3(0.5, 1, -400)).is_equal_approx(Vector3(-1.5, 2, 3.5)),
+ aabb.get_support(Vector3(0.5, 1, -400)).is_equal_approx(Vector3(2.5, 7, -2.5)),
"get_support() should return the expected value.");
CHECK_MESSAGE(
- aabb.get_support(Vector3(0, -1, 0)).is_equal_approx(Vector3(2.5, 7, 3.5)),
+ aabb.get_support(Vector3(0, -1, 0)).is_equal_approx(Vector3(-1.5, 2, -2.5)),
"get_support() should return the expected value.");
CHECK_MESSAGE(
- aabb.get_support(Vector3(0, -0.1, 0)).is_equal_approx(Vector3(2.5, 7, 3.5)),
+ aabb.get_support(Vector3(0, -0.1, 0)).is_equal_approx(Vector3(-1.5, 2, -2.5)),
"get_support() should return the expected value.");
CHECK_MESSAGE(
- aabb.get_support(Vector3()).is_equal_approx(Vector3(2.5, 7, 3.5)),
+ aabb.get_support(Vector3()).is_equal_approx(Vector3(-1.5, 2, -2.5)),
"get_support() should return the expected value with a null vector.");
}
-*/
+
TEST_CASE("[AABB] Grow") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
diff --git a/tests/core/math/test_basis.h b/tests/core/math/test_basis.h
index ec58d95eed..ae8ca4acde 100644
--- a/tests/core/math/test_basis.h
+++ b/tests/core/math/test_basis.h
@@ -283,4 +283,4 @@ TEST_CASE("[Stress][Basis] Euler conversions") {
}
} // namespace TestBasis
-#endif
+#endif // TEST_BASIS_H
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/math/test_quaternion.h b/tests/core/math/test_quaternion.h
new file mode 100644
index 0000000000..94eef6c463
--- /dev/null
+++ b/tests/core/math/test_quaternion.h
@@ -0,0 +1,389 @@
+/*************************************************************************/
+/* test_quaternion.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_QUATERNION_H
+#define TEST_QUATERNION_H
+
+#include "core/math/math_defs.h"
+#include "core/math/math_funcs.h"
+#include "core/math/quaternion.h"
+#include "core/math/vector3.h"
+
+#include "tests/test_macros.h"
+
+namespace TestQuaternion {
+
+Quaternion quat_euler_yxz_deg(Vector3 angle) {
+ double yaw = Math::deg2rad(angle[1]);
+ double pitch = Math::deg2rad(angle[0]);
+ double roll = Math::deg2rad(angle[2]);
+
+ // Generate YXZ (Z-then-X-then-Y) Quaternion using single-axis Euler
+ // constructor and quaternion product, both tested separately.
+ Quaternion q_y(Vector3(0.0, yaw, 0.0));
+ Quaternion q_p(Vector3(pitch, 0.0, 0.0));
+ Quaternion q_r(Vector3(0.0, 0.0, roll));
+ // Roll-Z is followed by Pitch-X, then Yaw-Y.
+ Quaternion q_yxz = q_y * q_p * q_r;
+
+ return q_yxz;
+}
+
+TEST_CASE("[Quaternion] Default Construct") {
+ Quaternion q;
+
+ CHECK(q[0] == 0.0);
+ CHECK(q[1] == 0.0);
+ CHECK(q[2] == 0.0);
+ CHECK(q[3] == 1.0);
+}
+
+TEST_CASE("[Quaternion] Construct x,y,z,w") {
+ // Values are taken from actual use in another project & are valid (except roundoff error).
+ Quaternion q(0.2391, 0.099, 0.3696, 0.8924);
+
+ CHECK(q[0] == doctest::Approx(0.2391));
+ CHECK(q[1] == doctest::Approx(0.099));
+ CHECK(q[2] == doctest::Approx(0.3696));
+ CHECK(q[3] == doctest::Approx(0.8924));
+}
+
+TEST_CASE("[Quaternion] Construct AxisAngle 1") {
+ // Easy to visualize: 120 deg about X-axis.
+ Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0));
+
+ // 0.866 isn't close enough; doctest::Approx doesn't cut much slack!
+ CHECK(q[0] == doctest::Approx(0.866025)); // Sine of half the angle.
+ CHECK(q[1] == doctest::Approx(0.0));
+ CHECK(q[2] == doctest::Approx(0.0));
+ CHECK(q[3] == doctest::Approx(0.5)); // Cosine of half the angle.
+}
+
+TEST_CASE("[Quaternion] Construct AxisAngle 2") {
+ // Easy to visualize: 30 deg about Y-axis.
+ Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0));
+
+ CHECK(q[0] == doctest::Approx(0.0));
+ CHECK(q[1] == doctest::Approx(0.258819)); // Sine of half the angle.
+ CHECK(q[2] == doctest::Approx(0.0));
+ CHECK(q[3] == doctest::Approx(0.965926)); // Cosine of half the angle.
+}
+
+TEST_CASE("[Quaternion] Construct AxisAngle 3") {
+ // Easy to visualize: 60 deg about Z-axis.
+ Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0));
+
+ CHECK(q[0] == doctest::Approx(0.0));
+ CHECK(q[1] == doctest::Approx(0.0));
+ CHECK(q[2] == doctest::Approx(0.5)); // Sine of half the angle.
+ CHECK(q[3] == doctest::Approx(0.866025)); // Cosine of half the angle.
+}
+
+TEST_CASE("[Quaternion] Construct AxisAngle 4") {
+ // More complex & hard to visualize, so test w/ data from online calculator.
+ Vector3 axis(1.0, 2.0, 0.5);
+ Quaternion q(axis.normalized(), Math::deg2rad(35.0));
+
+ CHECK(q[0] == doctest::Approx(0.131239));
+ CHECK(q[1] == doctest::Approx(0.262478));
+ CHECK(q[2] == doctest::Approx(0.0656194));
+ CHECK(q[3] == doctest::Approx(0.953717));
+}
+
+TEST_CASE("[Quaternion] Construct from Quaternion") {
+ Vector3 axis(1.0, 2.0, 0.5);
+ Quaternion q_src(axis.normalized(), Math::deg2rad(35.0));
+ Quaternion q(q_src);
+
+ CHECK(q[0] == doctest::Approx(0.131239));
+ CHECK(q[1] == doctest::Approx(0.262478));
+ CHECK(q[2] == doctest::Approx(0.0656194));
+ CHECK(q[3] == doctest::Approx(0.953717));
+}
+
+TEST_CASE("[Quaternion] Construct Euler SingleAxis") {
+ double yaw = Math::deg2rad(45.0);
+ double pitch = Math::deg2rad(30.0);
+ double roll = Math::deg2rad(10.0);
+
+ Vector3 euler_y(0.0, yaw, 0.0);
+ Quaternion q_y(euler_y);
+ CHECK(q_y[0] == doctest::Approx(0.0));
+ CHECK(q_y[1] == doctest::Approx(0.382684));
+ CHECK(q_y[2] == doctest::Approx(0.0));
+ CHECK(q_y[3] == doctest::Approx(0.923879));
+
+ Vector3 euler_p(pitch, 0.0, 0.0);
+ Quaternion q_p(euler_p);
+ CHECK(q_p[0] == doctest::Approx(0.258819));
+ CHECK(q_p[1] == doctest::Approx(0.0));
+ CHECK(q_p[2] == doctest::Approx(0.0));
+ CHECK(q_p[3] == doctest::Approx(0.965926));
+
+ Vector3 euler_r(0.0, 0.0, roll);
+ Quaternion q_r(euler_r);
+ CHECK(q_r[0] == doctest::Approx(0.0));
+ CHECK(q_r[1] == doctest::Approx(0.0));
+ CHECK(q_r[2] == doctest::Approx(0.0871558));
+ CHECK(q_r[3] == doctest::Approx(0.996195));
+}
+
+TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") {
+ double yaw = Math::deg2rad(45.0);
+ double pitch = Math::deg2rad(30.0);
+ double roll = Math::deg2rad(10.0);
+
+ // Generate YXZ comparision data (Z-then-X-then-Y) using single-axis Euler
+ // constructor and quaternion product, both tested separately.
+ Vector3 euler_y(0.0, yaw, 0.0);
+ Quaternion q_y(euler_y);
+ Vector3 euler_p(pitch, 0.0, 0.0);
+ Quaternion q_p(euler_p);
+ Vector3 euler_r(0.0, 0.0, roll);
+ Quaternion q_r(euler_r);
+
+ // Roll-Z is followed by Pitch-X.
+ Quaternion check_xz = q_p * q_r;
+ // Then Yaw-Y follows both.
+ Quaternion check_yxz = q_y * check_xz;
+
+ // Test construction from YXZ Euler angles.
+ Vector3 euler_yxz(pitch, yaw, roll);
+ Quaternion q(euler_yxz);
+ CHECK(q[0] == doctest::Approx(check_yxz[0]));
+ CHECK(q[1] == doctest::Approx(check_yxz[1]));
+ CHECK(q[2] == doctest::Approx(check_yxz[2]));
+ CHECK(q[3] == doctest::Approx(check_yxz[3]));
+
+ // Sneak in a test of is_equal_approx.
+ CHECK(q.is_equal_approx(check_yxz));
+}
+
+TEST_CASE("[Quaternion] Construct Basis Euler") {
+ double yaw = Math::deg2rad(45.0);
+ double pitch = Math::deg2rad(30.0);
+ double roll = Math::deg2rad(10.0);
+ Vector3 euler_yxz(pitch, yaw, roll);
+ Quaternion q_yxz(euler_yxz);
+ Basis basis_axes(euler_yxz);
+ Quaternion q(basis_axes);
+ CHECK(q.is_equal_approx(q_yxz));
+}
+
+TEST_CASE("[Quaternion] Construct Basis Axes") {
+ // Arbitrary Euler angles.
+ Vector3 euler_yxz(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34));
+ // Basis vectors from online calculation of rotation matrix.
+ Vector3 i_unit(0.5545787, 0.1823950, 0.8118957);
+ Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555);
+ Vector3 k_unit(-0.6456754, -0.5211586, 0.5581192);
+ // Quaternion from online calculation.
+ Quaternion q_calc(0.2016913, -0.4245716, 0.206033, 0.8582598);
+ // Quaternion from local calculation.
+ Quaternion q_local = quat_euler_yxz_deg(Vector3(31.41, -49.16, 12.34));
+ // Quaternion from Euler angles constructor.
+ Quaternion q_euler(euler_yxz);
+ CHECK(q_calc.is_equal_approx(q_local));
+ CHECK(q_local.is_equal_approx(q_euler));
+
+ // Calculate Basis and construct Quaternion.
+ // When this is written, C++ Basis class does not construct from basis vectors.
+ // This is by design, but may be subject to change.
+ // Workaround by constructing Basis from Euler angles.
+ // basis_axes = Basis(i_unit, j_unit, k_unit);
+ Basis basis_axes(euler_yxz);
+ Quaternion q(basis_axes);
+
+ CHECK(basis_axes.get_column(0).is_equal_approx(i_unit));
+ CHECK(basis_axes.get_column(1).is_equal_approx(j_unit));
+ CHECK(basis_axes.get_column(2).is_equal_approx(k_unit));
+
+ CHECK(q.is_equal_approx(q_calc));
+ CHECK_FALSE(q.inverse().is_equal_approx(q_calc));
+ CHECK(q.is_equal_approx(q_local));
+ CHECK(q.is_equal_approx(q_euler));
+ CHECK(q[0] == doctest::Approx(0.2016913));
+ CHECK(q[1] == doctest::Approx(-0.4245716));
+ CHECK(q[2] == doctest::Approx(0.206033));
+ CHECK(q[3] == doctest::Approx(0.8582598));
+}
+
+TEST_CASE("[Quaternion] Product (book)") {
+ // Example from "Quaternions and Rotation Sequences" by Jack Kuipers, p. 108.
+ Quaternion p(1.0, -2.0, 1.0, 3.0);
+ Quaternion q(-1.0, 2.0, 3.0, 2.0);
+
+ Quaternion pq = p * q;
+ CHECK(pq[0] == doctest::Approx(-9.0));
+ CHECK(pq[1] == doctest::Approx(-2.0));
+ CHECK(pq[2] == doctest::Approx(11.0));
+ CHECK(pq[3] == doctest::Approx(8.0));
+}
+
+TEST_CASE("[Quaternion] Product") {
+ double yaw = Math::deg2rad(45.0);
+ double pitch = Math::deg2rad(30.0);
+ double roll = Math::deg2rad(10.0);
+
+ Vector3 euler_y(0.0, yaw, 0.0);
+ Quaternion q_y(euler_y);
+ CHECK(q_y[0] == doctest::Approx(0.0));
+ CHECK(q_y[1] == doctest::Approx(0.382684));
+ CHECK(q_y[2] == doctest::Approx(0.0));
+ CHECK(q_y[3] == doctest::Approx(0.923879));
+
+ Vector3 euler_p(pitch, 0.0, 0.0);
+ Quaternion q_p(euler_p);
+ CHECK(q_p[0] == doctest::Approx(0.258819));
+ CHECK(q_p[1] == doctest::Approx(0.0));
+ CHECK(q_p[2] == doctest::Approx(0.0));
+ CHECK(q_p[3] == doctest::Approx(0.965926));
+
+ Vector3 euler_r(0.0, 0.0, roll);
+ Quaternion q_r(euler_r);
+ CHECK(q_r[0] == doctest::Approx(0.0));
+ CHECK(q_r[1] == doctest::Approx(0.0));
+ CHECK(q_r[2] == doctest::Approx(0.0871558));
+ CHECK(q_r[3] == doctest::Approx(0.996195));
+
+ // Test ZYX dynamic-axes since test data is available online.
+ // Rotate first about X axis, then new Y axis, then new Z axis.
+ // (Godot uses YXZ Yaw-Pitch-Roll order).
+ Quaternion q_yp = q_y * q_p;
+ CHECK(q_yp[0] == doctest::Approx(0.239118));
+ CHECK(q_yp[1] == doctest::Approx(0.369644));
+ CHECK(q_yp[2] == doctest::Approx(-0.099046));
+ CHECK(q_yp[3] == doctest::Approx(0.892399));
+
+ Quaternion q_ryp = q_r * q_yp;
+ CHECK(q_ryp[0] == doctest::Approx(0.205991));
+ CHECK(q_ryp[1] == doctest::Approx(0.389078));
+ CHECK(q_ryp[2] == doctest::Approx(-0.0208912));
+ CHECK(q_ryp[3] == doctest::Approx(0.897636));
+}
+
+TEST_CASE("[Quaternion] xform unit vectors") {
+ // Easy to visualize: 120 deg about X-axis.
+ // Transform the i, j, & k unit vectors.
+ Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0));
+ Vector3 i_t = q.xform(Vector3(1.0, 0.0, 0.0));
+ Vector3 j_t = q.xform(Vector3(0.0, 1.0, 0.0));
+ Vector3 k_t = q.xform(Vector3(0.0, 0.0, 1.0));
+ //
+ CHECK(i_t.is_equal_approx(Vector3(1.0, 0.0, 0.0)));
+ CHECK(j_t.is_equal_approx(Vector3(0.0, -0.5, 0.866025)));
+ CHECK(k_t.is_equal_approx(Vector3(0.0, -0.866025, -0.5)));
+ CHECK(i_t.length_squared() == doctest::Approx(1.0));
+ CHECK(j_t.length_squared() == doctest::Approx(1.0));
+ CHECK(k_t.length_squared() == doctest::Approx(1.0));
+
+ // Easy to visualize: 30 deg about Y-axis.
+ q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0));
+ i_t = q.xform(Vector3(1.0, 0.0, 0.0));
+ j_t = q.xform(Vector3(0.0, 1.0, 0.0));
+ k_t = q.xform(Vector3(0.0, 0.0, 1.0));
+ //
+ CHECK(i_t.is_equal_approx(Vector3(0.866025, 0.0, -0.5)));
+ CHECK(j_t.is_equal_approx(Vector3(0.0, 1.0, 0.0)));
+ CHECK(k_t.is_equal_approx(Vector3(0.5, 0.0, 0.866025)));
+ CHECK(i_t.length_squared() == doctest::Approx(1.0));
+ CHECK(j_t.length_squared() == doctest::Approx(1.0));
+ CHECK(k_t.length_squared() == doctest::Approx(1.0));
+
+ // Easy to visualize: 60 deg about Z-axis.
+ q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0));
+ i_t = q.xform(Vector3(1.0, 0.0, 0.0));
+ j_t = q.xform(Vector3(0.0, 1.0, 0.0));
+ k_t = q.xform(Vector3(0.0, 0.0, 1.0));
+ //
+ CHECK(i_t.is_equal_approx(Vector3(0.5, 0.866025, 0.0)));
+ CHECK(j_t.is_equal_approx(Vector3(-0.866025, 0.5, 0.0)));
+ CHECK(k_t.is_equal_approx(Vector3(0.0, 0.0, 1.0)));
+ CHECK(i_t.length_squared() == doctest::Approx(1.0));
+ CHECK(j_t.length_squared() == doctest::Approx(1.0));
+ CHECK(k_t.length_squared() == doctest::Approx(1.0));
+}
+
+TEST_CASE("[Quaternion] xform vector") {
+ // Arbitrary quaternion rotates an arbitrary vector.
+ Vector3 euler_yzx(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34));
+ Basis basis_axes(euler_yzx);
+ Quaternion q(basis_axes);
+
+ Vector3 v_arb(3.0, 4.0, 5.0);
+ Vector3 v_rot = q.xform(v_arb);
+ Vector3 v_compare = basis_axes.xform(v_arb);
+
+ CHECK(v_rot.length_squared() == doctest::Approx(v_arb.length_squared()));
+ CHECK(v_rot.is_equal_approx(v_compare));
+}
+
+// Test vector xform for a single combination of Quaternion and Vector.
+void test_quat_vec_rotate(Vector3 euler_yzx, Vector3 v_in) {
+ Basis basis_axes(euler_yzx);
+ Quaternion q(basis_axes);
+
+ Vector3 v_rot = q.xform(v_in);
+ Vector3 v_compare = basis_axes.xform(v_in);
+
+ CHECK(v_rot.length_squared() == doctest::Approx(v_in.length_squared()));
+ CHECK(v_rot.is_equal_approx(v_compare));
+}
+
+TEST_CASE("[Stress][Quaternion] Many vector xforms") {
+ // Many arbitrary quaternions rotate many arbitrary vectors.
+ // For each trial, check that rotation by Quaternion yields same result as
+ // rotation by Basis.
+ const int STEPS = 100; // Number of test steps in each dimension
+ const double delta = 2.0 * Math_PI / STEPS; // Angle increment per step
+ const double delta_vec = 20.0 / STEPS; // Vector increment per step
+ Vector3 vec_arb(1.0, 1.0, 1.0);
+ double x_angle = -Math_PI;
+ double y_angle = -Math_PI;
+ double z_angle = -Math_PI;
+ for (double i = 0; i < STEPS; ++i) {
+ vec_arb[0] = -10.0 + i * delta_vec;
+ x_angle = i * delta - Math_PI;
+ for (double j = 0; j < STEPS; ++j) {
+ vec_arb[1] = -10.0 + j * delta_vec;
+ y_angle = j * delta - Math_PI;
+ for (double k = 0; k < STEPS; ++k) {
+ vec_arb[2] = -10.0 + k * delta_vec;
+ z_angle = k * delta - Math_PI;
+ Vector3 euler_yzx(x_angle, y_angle, z_angle);
+ test_quat_vec_rotate(euler_yzx, vec_arb);
+ }
+ }
+ }
+}
+
+} // namespace TestQuaternion
+
+#endif // TEST_QUATERNION_H
diff --git a/tests/core/math/test_transform_2d.h b/tests/core/math/test_transform_2d.h
new file mode 100644
index 0000000000..697bf63fc5
--- /dev/null
+++ b/tests/core/math/test_transform_2d.h
@@ -0,0 +1,88 @@
+/*************************************************************************/
+/* test_transform_2d.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_TRANSFORM_2D_H
+#define TEST_TRANSFORM_2D_H
+
+#include "core/math/transform_2d.h"
+
+#include "tests/test_macros.h"
+
+namespace TestTransform2D {
+
+Transform2D create_dummy_transform() {
+ return Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
+}
+
+Transform2D identity() {
+ return Transform2D();
+}
+
+TEST_CASE("[Transform2D] translation") {
+ Vector2 offset = Vector2(1, 2);
+
+ // Both versions should give the same result applied to identity.
+ CHECK(identity().translated(offset) == identity().translated_local(offset));
+
+ // Check both versions against left and right multiplications.
+ Transform2D orig = create_dummy_transform();
+ Transform2D T = identity().translated(offset);
+ CHECK(orig.translated(offset) == T * orig);
+ CHECK(orig.translated_local(offset) == orig * T);
+}
+
+TEST_CASE("[Transform2D] scaling") {
+ Vector2 scaling = Vector2(1, 2);
+
+ // Both versions should give the same result applied to identity.
+ CHECK(identity().scaled(scaling) == identity().scaled_local(scaling));
+
+ // Check both versions against left and right multiplications.
+ Transform2D orig = create_dummy_transform();
+ Transform2D S = identity().scaled(scaling);
+ CHECK(orig.scaled(scaling) == S * orig);
+ CHECK(orig.scaled_local(scaling) == orig * S);
+}
+
+TEST_CASE("[Transform2D] rotation") {
+ real_t phi = 1.0;
+
+ // Both versions should give the same result applied to identity.
+ CHECK(identity().rotated(phi) == identity().rotated_local(phi));
+
+ // Check both versions against left and right multiplications.
+ Transform2D orig = create_dummy_transform();
+ Transform2D R = identity().rotated(phi);
+ CHECK(orig.rotated(phi) == R * orig);
+ CHECK(orig.rotated_local(phi) == orig * R);
+}
+} // namespace TestTransform2D
+
+#endif // TEST_TRANSFORM_2D_H
diff --git a/tests/core/math/test_transform_3d.h b/tests/core/math/test_transform_3d.h
new file mode 100644
index 0000000000..da166b43f7
--- /dev/null
+++ b/tests/core/math/test_transform_3d.h
@@ -0,0 +1,89 @@
+/*************************************************************************/
+/* test_transform_3d.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_TRANSFORM_3D_H
+#define TEST_TRANSFORM_3D_H
+
+#include "core/math/transform_3d.h"
+
+#include "tests/test_macros.h"
+
+namespace TestTransform3D {
+
+Transform3D create_dummy_transform() {
+ return Transform3D(Basis(Vector3(1, 2, 3), Vector3(4, 5, 6), Vector3(7, 8, 9)), Vector3(10, 11, 12));
+}
+
+Transform3D identity() {
+ return Transform3D();
+}
+
+TEST_CASE("[Transform3D] translation") {
+ Vector3 offset = Vector3(1, 2, 3);
+
+ // Both versions should give the same result applied to identity.
+ CHECK(identity().translated(offset) == identity().translated_local(offset));
+
+ // Check both versions against left and right multiplications.
+ Transform3D orig = create_dummy_transform();
+ Transform3D T = identity().translated(offset);
+ CHECK(orig.translated(offset) == T * orig);
+ CHECK(orig.translated_local(offset) == orig * T);
+}
+
+TEST_CASE("[Transform3D] scaling") {
+ Vector3 scaling = Vector3(1, 2, 3);
+
+ // Both versions should give the same result applied to identity.
+ CHECK(identity().scaled(scaling) == identity().scaled_local(scaling));
+
+ // Check both versions against left and right multiplications.
+ Transform3D orig = create_dummy_transform();
+ Transform3D S = identity().scaled(scaling);
+ CHECK(orig.scaled(scaling) == S * orig);
+ CHECK(orig.scaled_local(scaling) == orig * S);
+}
+
+TEST_CASE("[Transform3D] rotation") {
+ Vector3 axis = Vector3(1, 2, 3).normalized();
+ real_t phi = 1.0;
+
+ // Both versions should give the same result applied to identity.
+ CHECK(identity().rotated(axis, phi) == identity().rotated_local(axis, phi));
+
+ // Check both versions against left and right multiplications.
+ Transform3D orig = create_dummy_transform();
+ Transform3D R = identity().rotated(axis, phi);
+ CHECK(orig.rotated(axis, phi) == R * orig);
+ CHECK(orig.rotated_local(axis, phi) == orig * R);
+}
+} // namespace TestTransform3D
+
+#endif // TEST_TRANSFORM_3D_H
diff --git a/tests/core/math/test_vector4.h b/tests/core/math/test_vector4.h
new file mode 100644
index 0000000000..4b8759c0ca
--- /dev/null
+++ b/tests/core/math/test_vector4.h
@@ -0,0 +1,312 @@
+/*************************************************************************/
+/* test_vector4.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_VECTOR4_H
+#define TEST_VECTOR4_H
+
+#include "core/math/vector4.h"
+#include "tests/test_macros.h"
+
+#define Math_SQRT3 1.7320508075688772935274463415059
+
+namespace TestVector4 {
+
+TEST_CASE("[Vector4] Axis methods") {
+ Vector4 vector = Vector4(1.2, 3.4, 5.6, -0.9);
+ CHECK_MESSAGE(
+ vector.max_axis_index() == Vector4::Axis::AXIS_Z,
+ "Vector4 max_axis_index should work as expected.");
+ CHECK_MESSAGE(
+ vector.min_axis_index() == Vector4::Axis::AXIS_W,
+ "Vector4 min_axis_index should work as expected.");
+ CHECK_MESSAGE(
+ vector.get_axis(vector.max_axis_index()) == (real_t)5.6,
+ "Vector4 get_axis should work as expected.");
+ CHECK_MESSAGE(
+ vector[vector.min_axis_index()] == (real_t)-0.9,
+ "Vector4 array operator should work as expected.");
+
+ vector.set_axis(Vector4::Axis::AXIS_Y, 4.7);
+ CHECK_MESSAGE(
+ vector.get_axis(Vector4::Axis::AXIS_Y) == (real_t)4.7,
+ "Vector4 set_axis should work as expected.");
+ vector[Vector4::Axis::AXIS_Y] = 3.7;
+ CHECK_MESSAGE(
+ vector[Vector4::Axis::AXIS_Y] == (real_t)3.7,
+ "Vector4 array operator setter should work as expected.");
+}
+
+TEST_CASE("[Vector4] Interpolation methods") {
+ const Vector4 vector1 = Vector4(1, 2, 3, 4);
+ const Vector4 vector2 = Vector4(4, 5, 6, 7);
+ CHECK_MESSAGE(
+ vector1.lerp(vector2, 0.5) == Vector4(2.5, 3.5, 4.5, 5.5),
+ "Vector4 lerp should work as expected.");
+ CHECK_MESSAGE(
+ vector1.lerp(vector2, 1.0 / 3.0).is_equal_approx(Vector4(2, 3, 4, 5)),
+ "Vector4 lerp should work as expected.");
+ CHECK_MESSAGE(
+ vector1.cubic_interpolate(vector2, Vector4(), Vector4(7, 7, 7, 7), 0.5) == Vector4(2.375, 3.5, 4.625, 5.75),
+ "Vector4 cubic_interpolate should work as expected.");
+ CHECK_MESSAGE(
+ vector1.cubic_interpolate(vector2, Vector4(), Vector4(7, 7, 7, 7), 1.0 / 3.0).is_equal_approx(Vector4(1.851851940155029297, 2.962963104248046875, 4.074074268341064453, 5.185185185185)),
+ "Vector4 cubic_interpolate should work as expected.");
+}
+
+TEST_CASE("[Vector4] Length methods") {
+ const Vector4 vector1 = Vector4(10, 10, 10, 10);
+ const Vector4 vector2 = Vector4(20, 30, 40, 50);
+ CHECK_MESSAGE(
+ vector1.length_squared() == 400,
+ "Vector4 length_squared should work as expected and return exact result.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(vector1.length(), 20),
+ "Vector4 length should work as expected.");
+ CHECK_MESSAGE(
+ vector2.length_squared() == 5400,
+ "Vector4 length_squared should work as expected and return exact result.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(vector2.length(), (real_t)73.484692283495),
+ "Vector4 length should work as expected.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(vector1.distance_to(vector2), (real_t)54.772255750517),
+ "Vector4 distance_to should work as expected.");
+}
+
+TEST_CASE("[Vector4] Limiting methods") {
+ const Vector4 vector = Vector4(10, 10, 10, 10);
+ CHECK_MESSAGE(
+ Vector4(-5, 5, 15, -15).clamp(Vector4(), vector) == Vector4(0, 5, 10, 0),
+ "Vector4 clamp should work as expected.");
+ CHECK_MESSAGE(
+ vector.clamp(Vector4(0, 10, 15, 18), Vector4(5, 10, 20, 25)) == Vector4(5, 10, 15, 18),
+ "Vector4 clamp should work as expected.");
+}
+
+TEST_CASE("[Vector4] Normalization methods") {
+ CHECK_MESSAGE(
+ Vector4(1, 0, 0, 0).is_normalized() == true,
+ "Vector4 is_normalized should return true for a normalized vector.");
+ CHECK_MESSAGE(
+ Vector4(1, 1, 1, 1).is_normalized() == false,
+ "Vector4 is_normalized should return false for a non-normalized vector.");
+ CHECK_MESSAGE(
+ Vector4(1, 0, 0, 0).normalized() == Vector4(1, 0, 0, 0),
+ "Vector4 normalized should return the same vector for a normalized vector.");
+ CHECK_MESSAGE(
+ Vector4(1, 1, 0, 0).normalized().is_equal_approx(Vector4(Math_SQRT12, Math_SQRT12, 0, 0)),
+ "Vector4 normalized should work as expected.");
+ CHECK_MESSAGE(
+ Vector4(1, 1, 1, 1).normalized().is_equal_approx(Vector4(0.5, 0.5, 0.5, 0.5)),
+ "Vector4 normalized should work as expected.");
+}
+
+TEST_CASE("[Vector4] Operators") {
+ const Vector4 decimal1 = Vector4(2.3, 4.9, 7.8, 3.2);
+ const Vector4 decimal2 = Vector4(1.2, 3.4, 5.6, 1.7);
+ const Vector4 power1 = Vector4(0.75, 1.5, 0.625, 0.125);
+ const Vector4 power2 = Vector4(0.5, 0.125, 0.25, 0.75);
+ const Vector4 int1 = Vector4(4, 5, 9, 2);
+ const Vector4 int2 = Vector4(1, 2, 3, 1);
+
+ CHECK_MESSAGE(
+ -decimal1 == Vector4(-2.3, -4.9, -7.8, -3.2),
+ "Vector4 change of sign should work as expected.");
+ CHECK_MESSAGE(
+ (decimal1 + decimal2).is_equal_approx(Vector4(3.5, 8.3, 13.4, 4.9)),
+ "Vector4 addition should behave as expected.");
+ CHECK_MESSAGE(
+ (power1 + power2) == Vector4(1.25, 1.625, 0.875, 0.875),
+ "Vector4 addition with powers of two should give exact results.");
+ CHECK_MESSAGE(
+ (int1 + int2) == Vector4(5, 7, 12, 3),
+ "Vector4 addition with integers should give exact results.");
+
+ CHECK_MESSAGE(
+ (decimal1 - decimal2).is_equal_approx(Vector4(1.1, 1.5, 2.2, 1.5)),
+ "Vector4 subtraction should behave as expected.");
+ CHECK_MESSAGE(
+ (power1 - power2) == Vector4(0.25, 1.375, 0.375, -0.625),
+ "Vector4 subtraction with powers of two should give exact results.");
+ CHECK_MESSAGE(
+ (int1 - int2) == Vector4(3, 3, 6, 1),
+ "Vector4 subtraction with integers should give exact results.");
+
+ CHECK_MESSAGE(
+ (decimal1 * decimal2).is_equal_approx(Vector4(2.76, 16.66, 43.68, 5.44)),
+ "Vector4 multiplication should behave as expected.");
+ CHECK_MESSAGE(
+ (power1 * power2) == Vector4(0.375, 0.1875, 0.15625, 0.09375),
+ "Vector4 multiplication with powers of two should give exact results.");
+ CHECK_MESSAGE(
+ (int1 * int2) == Vector4(4, 10, 27, 2),
+ "Vector4 multiplication with integers should give exact results.");
+
+ CHECK_MESSAGE(
+ (decimal1 / decimal2).is_equal_approx(Vector4(1.91666666666666666, 1.44117647058823529, 1.39285714285714286, 1.88235294118)),
+ "Vector4 division should behave as expected.");
+ CHECK_MESSAGE(
+ (power1 / power2) == Vector4(1.5, 12.0, 2.5, 1.0 / 6.0),
+ "Vector4 division with powers of two should give exact results.");
+ CHECK_MESSAGE(
+ (int1 / int2) == Vector4(4, 2.5, 3, 2),
+ "Vector4 division with integers should give exact results.");
+
+ CHECK_MESSAGE(
+ (decimal1 * 2).is_equal_approx(Vector4(4.6, 9.8, 15.6, 6.4)),
+ "Vector4 multiplication should behave as expected.");
+ CHECK_MESSAGE(
+ (power1 * 2) == Vector4(1.5, 3, 1.25, 0.25),
+ "Vector4 multiplication with powers of two should give exact results.");
+ CHECK_MESSAGE(
+ (int1 * 2) == Vector4(8, 10, 18, 4),
+ "Vector4 multiplication with integers should give exact results.");
+
+ CHECK_MESSAGE(
+ (decimal1 / 2).is_equal_approx(Vector4(1.15, 2.45, 3.9, 1.6)),
+ "Vector4 division should behave as expected.");
+ CHECK_MESSAGE(
+ (power1 / 2) == Vector4(0.375, 0.75, 0.3125, 0.0625),
+ "Vector4 division with powers of two should give exact results.");
+ CHECK_MESSAGE(
+ (int1 / 2) == Vector4(2, 2.5, 4.5, 1),
+ "Vector4 division with integers should give exact results.");
+
+ CHECK_MESSAGE(
+ ((String)decimal1) == "(2.3, 4.9, 7.8, 3.2)",
+ "Vector4 cast to String should work as expected.");
+ CHECK_MESSAGE(
+ ((String)decimal2) == "(1.2, 3.4, 5.6, 1.7)",
+ "Vector4 cast to String should work as expected.");
+ CHECK_MESSAGE(
+ ((String)Vector4(9.7, 9.8, 9.9, -1.8)) == "(9.7, 9.8, 9.9, -1.8)",
+ "Vector4 cast to String should work as expected.");
+#ifdef REAL_T_IS_DOUBLE
+ CHECK_MESSAGE(
+ ((String)Vector4(Math_E, Math_SQRT2, Math_SQRT3, Math_SQRT3)) == "(2.71828182845905, 1.4142135623731, 1.73205080756888, 1.73205080756888)",
+ "Vector4 cast to String should print the correct amount of digits for real_t = double.");
+#else
+ CHECK_MESSAGE(
+ ((String)Vector4(Math_E, Math_SQRT2, Math_SQRT3, Math_SQRT3)) == "(2.718282, 1.414214, 1.732051, 1.732051)",
+ "Vector4 cast to String should print the correct amount of digits for real_t = float.");
+#endif // REAL_T_IS_DOUBLE
+}
+
+TEST_CASE("[Vector4] Other methods") {
+ const Vector4 vector = Vector4(1.2, 3.4, 5.6, 1.6);
+ CHECK_MESSAGE(
+ vector.direction_to(Vector4()).is_equal_approx(-vector.normalized()),
+ "Vector4 direction_to should work as expected.");
+ CHECK_MESSAGE(
+ Vector4(1, 1, 1, 1).direction_to(Vector4(2, 2, 2, 2)).is_equal_approx(Vector4(0.5, 0.5, 0.5, 0.5)),
+ "Vector4 direction_to should work as expected.");
+ CHECK_MESSAGE(
+ vector.inverse().is_equal_approx(Vector4(1 / 1.2, 1 / 3.4, 1 / 5.6, 1 / 1.6)),
+ "Vector4 inverse should work as expected.");
+ CHECK_MESSAGE(
+ vector.posmod(2).is_equal_approx(Vector4(1.2, 1.4, 1.6, 1.6)),
+ "Vector4 posmod should work as expected.");
+ CHECK_MESSAGE(
+ (-vector).posmod(2).is_equal_approx(Vector4(0.8, 0.6, 0.4, 0.4)),
+ "Vector4 posmod should work as expected.");
+ CHECK_MESSAGE(
+ vector.posmodv(Vector4(1, 2, 3, 4)).is_equal_approx(Vector4(0.2, 1.4, 2.6, 1.6)),
+ "Vector4 posmodv should work as expected.");
+ CHECK_MESSAGE(
+ (-vector).posmodv(Vector4(2, 3, 4, 5)).is_equal_approx(Vector4(0.8, 2.6, 2.4, 3.4)),
+ "Vector4 posmodv should work as expected.");
+ CHECK_MESSAGE(
+ vector.snapped(Vector4(1, 1, 1, 1)) == Vector4(1, 3, 6, 2),
+ "Vector4 snapped to integers should be the same as rounding.");
+ CHECK_MESSAGE(
+ vector.snapped(Vector4(0.25, 0.25, 0.25, 0.25)) == Vector4(1.25, 3.5, 5.5, 1.5),
+ "Vector4 snapped to 0.25 should give exact results.");
+}
+
+TEST_CASE("[Vector4] Rounding methods") {
+ const Vector4 vector1 = Vector4(1.2, 3.4, 5.6, 1.6);
+ const Vector4 vector2 = Vector4(1.2, -3.4, -5.6, -1.6);
+ CHECK_MESSAGE(
+ vector1.abs() == vector1,
+ "Vector4 abs should work as expected.");
+ CHECK_MESSAGE(
+ vector2.abs() == vector1,
+ "Vector4 abs should work as expected.");
+ CHECK_MESSAGE(
+ vector1.ceil() == Vector4(2, 4, 6, 2),
+ "Vector4 ceil should work as expected.");
+ CHECK_MESSAGE(
+ vector2.ceil() == Vector4(2, -3, -5, -1),
+ "Vector4 ceil should work as expected.");
+
+ CHECK_MESSAGE(
+ vector1.floor() == Vector4(1, 3, 5, 1),
+ "Vector4 floor should work as expected.");
+ CHECK_MESSAGE(
+ vector2.floor() == Vector4(1, -4, -6, -2),
+ "Vector4 floor should work as expected.");
+
+ CHECK_MESSAGE(
+ vector1.round() == Vector4(1, 3, 6, 2),
+ "Vector4 round should work as expected.");
+ CHECK_MESSAGE(
+ vector2.round() == Vector4(1, -3, -6, -2),
+ "Vector4 round should work as expected.");
+
+ CHECK_MESSAGE(
+ vector1.sign() == Vector4(1, 1, 1, 1),
+ "Vector4 sign should work as expected.");
+ CHECK_MESSAGE(
+ vector2.sign() == Vector4(1, -1, -1, -1),
+ "Vector4 sign should work as expected.");
+}
+
+TEST_CASE("[Vector4] Linear algebra methods") {
+ const Vector4 vector_x = Vector4(1, 0, 0, 0);
+ const Vector4 vector_y = Vector4(0, 1, 0, 0);
+ const Vector4 vector1 = Vector4(1.7, 2.3, 1, 9.1);
+ const Vector4 vector2 = Vector4(-8.2, -16, 3, 2.4);
+
+ CHECK_MESSAGE(
+ vector_x.dot(vector_y) == 0.0,
+ "Vector4 dot product of perpendicular vectors should be zero.");
+ CHECK_MESSAGE(
+ vector_x.dot(vector_x) == 1.0,
+ "Vector4 dot product of identical unit vectors should be one.");
+ CHECK_MESSAGE(
+ (vector_x * 10).dot(vector_x * 10) == 100.0,
+ "Vector4 dot product of same direction vectors should behave as expected.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx((vector1 * 2).dot(vector2 * 4), (real_t)-25.9 * 8),
+ "Vector4 dot product should work as expected.");
+}
+} // namespace TestVector4
+
+#endif // TEST_VECTOR4_H
diff --git a/tests/core/math/test_vector4i.h b/tests/core/math/test_vector4i.h
new file mode 100644
index 0000000000..ac63001b24
--- /dev/null
+++ b/tests/core/math/test_vector4i.h
@@ -0,0 +1,148 @@
+/*************************************************************************/
+/* test_vector4i.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_VECTOR4I_H
+#define TEST_VECTOR4I_H
+
+#include "core/math/vector4i.h"
+#include "tests/test_macros.h"
+
+namespace TestVector4i {
+
+TEST_CASE("[Vector4i] Axis methods") {
+ Vector4i vector = Vector4i(1, 2, 3, 4);
+ CHECK_MESSAGE(
+ vector.max_axis_index() == Vector4i::Axis::AXIS_W,
+ "Vector4i max_axis_index should work as expected.");
+ CHECK_MESSAGE(
+ vector.min_axis_index() == Vector4i::Axis::AXIS_X,
+ "Vector4i min_axis_index should work as expected.");
+ CHECK_MESSAGE(
+ vector.get_axis(vector.max_axis_index()) == 4,
+ "Vector4i get_axis should work as expected.");
+ CHECK_MESSAGE(
+ vector[vector.min_axis_index()] == 1,
+ "Vector4i array operator should work as expected.");
+
+ vector.set_axis(Vector4i::Axis::AXIS_Y, 5);
+ CHECK_MESSAGE(
+ vector.get_axis(Vector4i::Axis::AXIS_Y) == 5,
+ "Vector4i set_axis should work as expected.");
+ vector[Vector4i::Axis::AXIS_Y] = 5;
+ CHECK_MESSAGE(
+ vector[Vector4i::Axis::AXIS_Y] == 5,
+ "Vector4i array operator setter should work as expected.");
+}
+
+TEST_CASE("[Vector4i] Clamp method") {
+ const Vector4i vector = Vector4i(10, 10, 10, 10);
+ CHECK_MESSAGE(
+ Vector4i(-5, 5, 15, INT_MAX).clamp(Vector4i(), vector) == Vector4i(0, 5, 10, 10),
+ "Vector4i clamp should work as expected.");
+ CHECK_MESSAGE(
+ vector.clamp(Vector4i(0, 10, 15, -10), Vector4i(5, 10, 20, -5)) == Vector4i(5, 10, 15, -5),
+ "Vector4i clamp should work as expected.");
+}
+
+TEST_CASE("[Vector4i] Length methods") {
+ const Vector4i vector1 = Vector4i(10, 10, 10, 10);
+ const Vector4i vector2 = Vector4i(20, 30, 40, 50);
+ CHECK_MESSAGE(
+ vector1.length_squared() == 400,
+ "Vector4i length_squared should work as expected and return exact result.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(vector1.length(), 20),
+ "Vector4i length should work as expected.");
+ CHECK_MESSAGE(
+ vector2.length_squared() == 5400,
+ "Vector4i length_squared should work as expected and return exact result.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(vector2.length(), 73.4846922835),
+ "Vector4i length should work as expected.");
+}
+
+TEST_CASE("[Vector4i] Operators") {
+ const Vector4i vector1 = Vector4i(4, 5, 9, 2);
+ const Vector4i vector2 = Vector4i(1, 2, 3, 4);
+
+ CHECK_MESSAGE(
+ -vector1 == Vector4i(-4, -5, -9, -2),
+ "Vector4i change of sign should work as expected.");
+ CHECK_MESSAGE(
+ (vector1 + vector2) == Vector4i(5, 7, 12, 6),
+ "Vector4i addition with integers should give exact results.");
+ CHECK_MESSAGE(
+ (vector1 - vector2) == Vector4i(3, 3, 6, -2),
+ "Vector4i subtraction with integers should give exact results.");
+ CHECK_MESSAGE(
+ (vector1 * vector2) == Vector4i(4, 10, 27, 8),
+ "Vector4i multiplication with integers should give exact results.");
+ CHECK_MESSAGE(
+ (vector1 / vector2) == Vector4i(4, 2, 3, 0),
+ "Vector4i division with integers should give exact results.");
+
+ CHECK_MESSAGE(
+ (vector1 * 2) == Vector4i(8, 10, 18, 4),
+ "Vector4i multiplication with integers should give exact results.");
+ CHECK_MESSAGE(
+ (vector1 / 2) == Vector4i(2, 2, 4, 1),
+ "Vector4i division with integers should give exact results.");
+
+ CHECK_MESSAGE(
+ ((Vector4)vector1) == Vector4(4, 5, 9, 2),
+ "Vector4i cast to Vector4 should work as expected.");
+ CHECK_MESSAGE(
+ ((Vector4)vector2) == Vector4(1, 2, 3, 4),
+ "Vector4i cast to Vector4 should work as expected.");
+ CHECK_MESSAGE(
+ Vector4i(Vector4(1.1, 2.9, 3.9, 100.5)) == Vector4i(1, 2, 3, 100),
+ "Vector4i constructed from Vector4 should work as expected.");
+}
+
+TEST_CASE("[Vector4i] Abs and sign methods") {
+ const Vector4i vector1 = Vector4i(1, 3, 5, 7);
+ const Vector4i vector2 = Vector4i(1, -3, -5, 7);
+ CHECK_MESSAGE(
+ vector1.abs() == vector1,
+ "Vector4i abs should work as expected.");
+ CHECK_MESSAGE(
+ vector2.abs() == vector1,
+ "Vector4i abs should work as expected.");
+
+ CHECK_MESSAGE(
+ vector1.sign() == Vector4i(1, 1, 1, 1),
+ "Vector4i sign should work as expected.");
+ CHECK_MESSAGE(
+ vector2.sign() == Vector4i(1, -1, -1, 1),
+ "Vector4i sign should work as expected.");
+}
+} // namespace TestVector4i
+
+#endif // TEST_VECTOR4I_H
diff --git a/tests/core/object/test_class_db.h b/tests/core/object/test_class_db.h
index 7ea9e16ff1..fc329ba0eb 100644
--- a/tests/core/object/test_class_db.h
+++ b/tests/core/object/test_class_db.h
@@ -493,13 +493,13 @@ void add_exposed_classes(Context &r_context) {
}
if (!ClassDB::is_class_exposed(class_name)) {
- MESSAGE(vformat("Ignoring class '%s' because it's not exposed.", class_name).utf8().get_data());
+ MESSAGE(vformat("Ignoring class '%s' because it's not exposed.", class_name));
class_list.pop_front();
continue;
}
if (!ClassDB::is_class_enabled(class_name)) {
- MESSAGE(vformat("Ignoring class '%s' because it's not enabled.", class_name).utf8().get_data());
+ MESSAGE(vformat("Ignoring class '%s' because it's not enabled.", class_name));
class_list.pop_front();
continue;
}
@@ -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/object/test_method_bind.h b/tests/core/object/test_method_bind.h
index 350a08b6e2..2fe0c264a1 100644
--- a/tests/core/object/test_method_bind.h
+++ b/tests/core/object/test_method_bind.h
@@ -155,7 +155,6 @@ public:
TEST_CASE("[MethodBind] check all method binds") {
MethodBindTester *mbt = memnew(MethodBindTester);
- print_line("testing method bind");
mbt->run_tests();
CHECK(mbt->test_valid[MethodBindTester::TEST_METHOD]);
diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h
index 5b9d9cab53..88a3e4ccad 100644
--- a/tests/core/object/test_object.h
+++ b/tests/core/object/test_object.h
@@ -95,8 +95,8 @@ public:
Ref<Script> get_script() const override {
return Ref<Script>();
}
- const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override {
- return Vector<Multiplayer::RPCConfig>();
+ const Variant get_rpc_config() const override {
+ return Variant();
}
ScriptLanguage *get_language() override {
return nullptr;
diff --git a/tests/core/os/test_os.h b/tests/core/os/test_os.h
new file mode 100644
index 0000000000..c46da5e156
--- /dev/null
+++ b/tests/core/os/test_os.h
@@ -0,0 +1,158 @@
+/*************************************************************************/
+/* test_os.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_OS_H
+#define TEST_OS_H
+
+#include "core/os/os.h"
+
+#include "thirdparty/doctest/doctest.h"
+
+namespace TestOS {
+
+TEST_CASE("[OS] Environment variables") {
+#ifdef WINDOWS_ENABLED
+ CHECK_MESSAGE(
+ OS::get_singleton()->has_environment("USERPROFILE"),
+ "The USERPROFILE environment variable should be present.");
+#else
+ CHECK_MESSAGE(
+ OS::get_singleton()->has_environment("HOME"),
+ "The HOME environment variable should be present.");
+#endif
+
+ OS::get_singleton()->set_environment("HELLO", "world");
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_environment("HELLO") == "world",
+ "The previously-set HELLO environment variable should return the expected value.");
+}
+
+TEST_CASE("[OS] Command line arguments") {
+ List<String> arguments = OS::get_singleton()->get_cmdline_args();
+ bool found = false;
+ for (int i = 0; i < arguments.size(); i++) {
+ if (arguments[i] == "--test") {
+ found = true;
+ break;
+ }
+ }
+ CHECK_MESSAGE(
+ found,
+ "The `--test` option must be present in the list of command line arguments.");
+}
+
+TEST_CASE("[OS] Executable and data paths") {
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_executable_path().is_absolute_path(),
+ "The executable path returned should be an absolute path.");
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_data_path().is_absolute_path(),
+ "The user data path returned should be an absolute path.");
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_config_path().is_absolute_path(),
+ "The user configuration path returned should be an absolute path.");
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_cache_path().is_absolute_path(),
+ "The cache path returned should be an absolute path.");
+}
+
+TEST_CASE("[OS] Ticks") {
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_ticks_usec() > 1000,
+ "The returned ticks (in microseconds) must be greater than 1,000.");
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_ticks_msec() > 1,
+ "The returned ticks (in milliseconds) must be greater than 1.");
+}
+
+TEST_CASE("[OS] Feature tags") {
+ CHECK_MESSAGE(
+ OS::get_singleton()->has_feature("editor"),
+ "The binary has the \"editor\" feature tag.");
+ CHECK_MESSAGE(
+ !OS::get_singleton()->has_feature("standalone"),
+ "The binary does not have the \"standalone\" feature tag.");
+ CHECK_MESSAGE(
+ OS::get_singleton()->has_feature("debug"),
+ "The binary has the \"debug\" feature tag.");
+ CHECK_MESSAGE(
+ !OS::get_singleton()->has_feature("release"),
+ "The binary does not have the \"release\" feature tag.");
+}
+
+TEST_CASE("[OS] Process ID") {
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_process_id() >= 1,
+ "The returned process ID should be greater than zero.");
+}
+
+TEST_CASE("[OS] Processor count and memory information") {
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_processor_count() >= 1,
+ "The returned processor count should be greater than zero.");
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_static_memory_usage() >= 1,
+ "The returned static memory usage should be greater than zero.");
+ CHECK_MESSAGE(
+ OS::get_singleton()->get_static_memory_peak_usage() >= 1,
+ "The returned static memory peak usage should be greater than zero.");
+}
+
+TEST_CASE("[OS] Execute") {
+#ifdef WINDOWS_ENABLED
+ List<String> arguments;
+ arguments.push_back("/C");
+ arguments.push_back("dir > NUL");
+ int exit_code;
+ const Error err = OS::get_singleton()->execute("cmd", arguments, nullptr, &exit_code);
+ CHECK_MESSAGE(
+ err == OK,
+ "(Running the command `cmd /C \"dir > NUL\"` returns the expected Godot error code (OK).");
+ CHECK_MESSAGE(
+ exit_code == 0,
+ "Running the command `cmd /C \"dir > NUL\"` returns a zero (successful) exit code.");
+#else
+ List<String> arguments;
+ arguments.push_back("-c");
+ arguments.push_back("ls > /dev/null");
+ int exit_code;
+ const Error err = OS::get_singleton()->execute("sh", arguments, nullptr, &exit_code);
+ CHECK_MESSAGE(
+ err == OK,
+ "(Running the command `sh -c \"ls > /dev/null\"` returns the expected Godot error code (OK).");
+ CHECK_MESSAGE(
+ exit_code == 0,
+ "Running the command `sh -c \"ls > /dev/null\"` returns a zero (successful) exit code.");
+#endif
+}
+
+} // namespace TestOS
+
+#endif // TEST_OS_H
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 0b191d2d94..8914dbfd9a 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,62 @@ TEST_CASE("[String] UTF16 with BOM") {
CHECK(String::utf16(cs) == s);
}
-TEST_CASE("[String] Invalid UTF8") {
+TEST_CASE("[String] UTF8 with CR") {
+ const String base = U"Hello darkness\r\nMy old friend\nI've come to talk\rWith you again";
+
+ String keep_cr;
+ Error err = keep_cr.parse_utf8(base.utf8().get_data());
+ CHECK(err == OK);
+ CHECK(keep_cr == base);
+
+ String no_cr;
+ err = no_cr.parse_utf8(base.utf8().get_data(), -1, true); // Skip CR.
+ CHECK(err == OK);
+ CHECK(no_cr == base.replace("\r", ""));
+}
+
+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 +295,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
}
@@ -664,7 +697,9 @@ TEST_CASE("[String] sprintf") {
format = "fish %-05d frog";
args.clear();
args.push_back(-5);
+ ERR_PRINT_OFF; // Silence warning about 0 ignored.
output = format.sprintf(args, &error);
+ ERR_PRINT_ON;
REQUIRE(error == false);
CHECK(output == String("fish -5 frog"));
@@ -762,7 +797,9 @@ TEST_CASE("[String] sprintf") {
format = "fish %-011f frog";
args.clear();
args.push_back(-99.99);
+ ERR_PRINT_OFF; // Silence warning about 0 ignored.
output = format.sprintf(args, &error);
+ ERR_PRINT_ON;
REQUIRE(error == false);
CHECK(output == String("fish -99.990000 frog"));
@@ -1125,9 +1162,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 +1477,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/core/templates/test_hash_set.h b/tests/core/templates/test_hash_set.h
index 93fc0b26a3..dad149604b 100644
--- a/tests/core/templates/test_hash_set.h
+++ b/tests/core/templates/test_hash_set.h
@@ -38,7 +38,6 @@
namespace TestHashSet {
TEST_CASE("[HashSet] Insert element") {
- print_line("SMALL BEGIN MEM: ", Memory::get_mem_usage());
HashSet<int> set;
HashSet<int>::Iterator e = set.insert(42);
@@ -47,7 +46,6 @@ TEST_CASE("[HashSet] Insert element") {
CHECK(set.has(42));
CHECK(set.find(42));
set.reset();
- print_line("SMALL END MEM: ", Memory::get_mem_usage());
}
TEST_CASE("[HashSet] Insert existing element") {
@@ -225,4 +223,4 @@ TEST_CASE("[HashSet] Copy") {
} // namespace TestHashSet
-#endif // TEST_HASH_MAP_H
+#endif // TEST_HASH_SET_H
diff --git a/tests/core/templates/test_rid.h b/tests/core/templates/test_rid.h
new file mode 100644
index 0000000000..8d4dd0703b
--- /dev/null
+++ b/tests/core/templates/test_rid.h
@@ -0,0 +1,101 @@
+/*************************************************************************/
+/* test_rid.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_RID_H
+#define TEST_RID_H
+
+#include "core/templates/rid.h"
+
+#include "tests/test_macros.h"
+
+namespace TestRID {
+TEST_CASE("[RID] Default Constructor") {
+ RID rid;
+
+ CHECK(rid.get_id() == 0);
+}
+
+TEST_CASE("[RID] Factory method") {
+ RID rid = RID::from_uint64(1);
+
+ CHECK(rid.get_id() == 1);
+}
+
+TEST_CASE("[RID] Operators") {
+ RID rid = RID::from_uint64(1);
+
+ RID rid_zero = RID::from_uint64(0);
+ RID rid_one = RID::from_uint64(1);
+ RID rid_two = RID::from_uint64(2);
+
+ CHECK_FALSE(rid == rid_zero);
+ CHECK(rid == rid_one);
+ CHECK_FALSE(rid == rid_two);
+
+ CHECK_FALSE(rid < rid_zero);
+ CHECK_FALSE(rid < rid_one);
+ CHECK(rid < rid_two);
+
+ CHECK_FALSE(rid <= rid_zero);
+ CHECK(rid <= rid_one);
+ CHECK(rid <= rid_two);
+
+ CHECK(rid > rid_zero);
+ CHECK_FALSE(rid > rid_one);
+ CHECK_FALSE(rid > rid_two);
+
+ CHECK(rid >= rid_zero);
+ CHECK(rid >= rid_one);
+ CHECK_FALSE(rid >= rid_two);
+
+ CHECK(rid != rid_zero);
+ CHECK_FALSE(rid != rid_one);
+ CHECK(rid != rid_two);
+}
+
+TEST_CASE("[RID] 'is_valid' & 'is_null'") {
+ RID rid_zero = RID::from_uint64(0);
+ RID rid_one = RID::from_uint64(1);
+
+ CHECK_FALSE(rid_zero.is_valid());
+ CHECK(rid_zero.is_null());
+
+ CHECK(rid_one.is_valid());
+ CHECK_FALSE(rid_one.is_null());
+}
+
+TEST_CASE("[RID] 'get_local_index'") {
+ CHECK(RID::from_uint64(1).get_local_index() == 1);
+ CHECK(RID::from_uint64(4'294'967'295).get_local_index() == 4'294'967'295);
+ CHECK(RID::from_uint64(4'294'967'297).get_local_index() == 1);
+}
+} // namespace TestRID
+
+#endif // TEST_RID_H
diff --git a/tests/core/templates/test_vector.h b/tests/core/templates/test_vector.h
index f27d6a332e..3fc9264f5a 100644
--- a/tests/core/templates/test_vector.h
+++ b/tests/core/templates/test_vector.h
@@ -291,8 +291,10 @@ TEST_CASE("[Vector] Slice") {
CHECK(slice6[1] == 3);
CHECK(slice6[2] == 4);
+ ERR_PRINT_OFF;
Vector<int> slice7 = vector.slice(5, 1);
- CHECK(slice7.size() == 0);
+ CHECK(slice7.size() == 0); // Expected to fail.
+ ERR_PRINT_ON;
}
TEST_CASE("[Vector] Find, has") {
diff --git a/tests/core/threads/test_worker_thread_pool.h b/tests/core/threads/test_worker_thread_pool.h
new file mode 100644
index 0000000000..641b293c8a
--- /dev/null
+++ b/tests/core/threads/test_worker_thread_pool.h
@@ -0,0 +1,158 @@
+/*************************************************************************/
+/* test_worker_thread_pool.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_WORKER_THREAD_POOL_H
+#define TEST_WORKER_THREAD_POOL_H
+
+#include "core/object/worker_thread_pool.h"
+
+#include "tests/test_macros.h"
+
+namespace TestWorkerThreadPool {
+
+int u32scmp(const char32_t *l, const char32_t *r) {
+ for (; *l == *r && *l && *r; l++, r++) {
+ // Continue.
+ }
+ return *l - *r;
+}
+
+static void static_test(void *p_arg) {
+ SafeNumeric<uint32_t> *counter = (SafeNumeric<uint32_t> *)p_arg;
+ counter->increment();
+}
+
+static SafeNumeric<uint32_t> callable_counter;
+
+static void static_callable_test() {
+ callable_counter.increment();
+}
+
+TEST_CASE("[WorkerThreadPool] Process 256 threads using native task") {
+ const int count = 256;
+ SafeNumeric<uint32_t> counter;
+ WorkerThreadPool::TaskID tasks[count];
+ for (int i = 0; i < count; i++) {
+ tasks[i] = WorkerThreadPool::get_singleton()->add_native_task(static_test, &counter, true);
+ }
+ for (int i = 0; i < count; i++) {
+ WorkerThreadPool::get_singleton()->wait_for_task_completion(tasks[i]);
+ }
+
+ CHECK(counter.get() == count);
+}
+
+TEST_CASE("[WorkerThreadPool] Process 256 threads using native low priority") {
+ const int count = 256;
+ SafeNumeric<uint32_t> counter = SafeNumeric<uint32_t>(0);
+ WorkerThreadPool::TaskID tasks[count];
+ for (int i = 0; i < count; i++) {
+ tasks[i] = WorkerThreadPool::get_singleton()->add_native_task(static_test, &counter, false);
+ }
+ for (int i = 0; i < count; i++) {
+ WorkerThreadPool::get_singleton()->wait_for_task_completion(tasks[i]);
+ }
+
+ CHECK(counter.get() == count);
+}
+
+TEST_CASE("[WorkerThreadPool] Process 256 threads using callable") {
+ const int count = 256;
+ WorkerThreadPool::TaskID tasks[count];
+ callable_counter.set(0);
+ for (int i = 0; i < count; i++) {
+ tasks[i] = WorkerThreadPool::get_singleton()->add_task(callable_mp_static(static_callable_test), true);
+ }
+ for (int i = 0; i < count; i++) {
+ WorkerThreadPool::get_singleton()->wait_for_task_completion(tasks[i]);
+ }
+
+ CHECK(callable_counter.get() == count);
+}
+
+TEST_CASE("[WorkerThreadPool] Process 256 threads using callable low priority") {
+ const int count = 256;
+ WorkerThreadPool::TaskID tasks[count];
+ callable_counter.set(0);
+ for (int i = 0; i < count; i++) {
+ tasks[i] = WorkerThreadPool::get_singleton()->add_task(callable_mp_static(static_callable_test), false);
+ }
+ for (int i = 0; i < count; i++) {
+ WorkerThreadPool::get_singleton()->wait_for_task_completion(tasks[i]);
+ }
+
+ CHECK(callable_counter.get() == count);
+}
+
+static void static_group_test(void *p_arg, uint32_t p_index) {
+ SafeNumeric<uint32_t> *counter = (SafeNumeric<uint32_t> *)p_arg;
+ counter->exchange_if_greater(p_index);
+}
+
+TEST_CASE("[WorkerThreadPool] Process 256 elements on native task group") {
+ const int count = 256;
+ SafeNumeric<uint32_t> counter;
+ WorkerThreadPool::GroupID group = WorkerThreadPool::get_singleton()->add_native_group_task(static_group_test, &counter, count, -1, true);
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group);
+ CHECK(counter.get() == count - 1);
+}
+
+TEST_CASE("[WorkerThreadPool] Process 256 elements on native task group low priority") {
+ const int count = 256;
+ SafeNumeric<uint32_t> counter;
+ WorkerThreadPool::GroupID group = WorkerThreadPool::get_singleton()->add_native_group_task(static_group_test, &counter, count, -1, false);
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group);
+ CHECK(counter.get() == count - 1);
+}
+
+static SafeNumeric<uint32_t> callable_group_counter;
+
+static void static_callable_group_test(uint32_t p_index) {
+ callable_group_counter.exchange_if_greater(p_index);
+}
+
+TEST_CASE("[WorkerThreadPool] Process 256 elements on native task group") {
+ const int count = 256;
+ WorkerThreadPool::GroupID group = WorkerThreadPool::get_singleton()->add_group_task(callable_mp_static(static_callable_group_test), count, -1, true);
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group);
+ CHECK(callable_group_counter.get() == count - 1);
+}
+
+TEST_CASE("[WorkerThreadPool] Process 256 elements on native task group low priority") {
+ const int count = 256;
+ callable_group_counter.set(0);
+ WorkerThreadPool::GroupID group = WorkerThreadPool::get_singleton()->add_group_task(callable_mp_static(static_callable_group_test), count, -1, false);
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group);
+ CHECK(callable_group_counter.get() == count - 1);
+}
+
+} // namespace TestWorkerThreadPool
+
+#endif // TEST_WORKER_THREAD_POOL_H
diff --git a/tests/data/line_endings_cr.test.txt b/tests/data/line_endings_cr.test.txt
new file mode 100644
index 0000000000..556154bb25
--- /dev/null
+++ b/tests/data/line_endings_cr.test.txt
@@ -0,0 +1 @@
+Hello darkness My old friend I've come to talk With you again \ No newline at end of file
diff --git a/tests/data/line_endings_crlf.test.txt b/tests/data/line_endings_crlf.test.txt
new file mode 100644
index 0000000000..a3cbe55b7f
--- /dev/null
+++ b/tests/data/line_endings_crlf.test.txt
@@ -0,0 +1,4 @@
+Hello darkness
+My old friend
+I've come to talk
+With you again
diff --git a/tests/data/line_endings_lf.test.txt b/tests/data/line_endings_lf.test.txt
new file mode 100644
index 0000000000..0aabcd911e
--- /dev/null
+++ b/tests/data/line_endings_lf.test.txt
@@ -0,0 +1,4 @@
+Hello darkness
+My old friend
+I've come to talk
+With you again
diff --git a/tests/scene/test_audio_stream_wav.h b/tests/scene/test_audio_stream_wav.h
new file mode 100644
index 0000000000..92c524525c
--- /dev/null
+++ b/tests/scene/test_audio_stream_wav.h
@@ -0,0 +1,243 @@
+/*************************************************************************/
+/* test_audio_stream_wav.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_AUDIO_STREAM_WAV_H
+#define TEST_AUDIO_STREAM_WAV_H
+
+#include "core/math/math_defs.h"
+#include "core/math/math_funcs.h"
+#include "scene/resources/audio_stream_wav.h"
+
+#include "tests/test_macros.h"
+
+#ifdef TOOLS_ENABLED
+#include "core/io/resource_loader.h"
+#include "editor/import/resource_importer_wav.h"
+#endif
+
+namespace TestAudioStreamWAV {
+
+// Default wav rate for test cases.
+constexpr float WAV_RATE = 44100;
+/* Default wav count for test cases. 1 second of audio is used so that the file can be listened
+to manually if needed. */
+constexpr int WAV_COUNT = WAV_RATE;
+
+float gen_wav(float frequency, float wav_rate, int wav_number) {
+ // formula for generating a sin wave with given frequency.
+ return Math::sin((Math_TAU * frequency / wav_rate) * wav_number);
+}
+
+/* Generates a 440Hz sin wave in channel 0 (mono channel or left stereo channel)
+ * and a 261.63Hz wave in channel 1 (right stereo channel).
+ * These waves correspond to the music notes A4 and C4 respectively.
+ */
+Vector<uint8_t> gen_pcm8_test(float wav_rate, int wav_count, bool stereo) {
+ Vector<uint8_t> buffer;
+ buffer.resize(stereo ? wav_count * 2 : wav_count);
+
+ uint8_t *write_ptr = buffer.ptrw();
+ for (int i = 0; i < buffer.size(); i++) {
+ float wav;
+ if (stereo) {
+ if (i % 2 == 0) {
+ wav = gen_wav(440, wav_rate, i / 2);
+ } else {
+ wav = gen_wav(261.63, wav_rate, i / 2);
+ }
+ } else {
+ wav = gen_wav(440, wav_rate, i);
+ }
+
+ // Map sin wave to full range of 8-bit values.
+ uint8_t wav_8bit = Math::fast_ftoi(((wav + 1) / 2) * UINT8_MAX);
+ // Unlike the .wav format, AudioStreamWAV expects signed 8-bit wavs.
+ uint8_t wav_8bit_signed = wav_8bit - (INT8_MAX + 1);
+ write_ptr[i] = wav_8bit_signed;
+ }
+
+ return buffer;
+}
+
+// Same as gen_pcm8_test but with 16-bit wavs.
+Vector<uint8_t> gen_pcm16_test(float wav_rate, int wav_count, bool stereo) {
+ Vector<uint8_t> buffer;
+ buffer.resize(stereo ? wav_count * 4 : wav_count * 2);
+
+ uint8_t *write_ptr = buffer.ptrw();
+ for (int i = 0; i < buffer.size() / 2; i++) {
+ float wav;
+ if (stereo) {
+ if (i % 2 == 0) {
+ wav = gen_wav(440, wav_rate, i / 2);
+ } else {
+ wav = gen_wav(261.63, wav_rate, i / 2);
+ }
+ } else {
+ wav = gen_wav(440, wav_rate, i);
+ }
+
+ // Map sin wave to full range of 16-bit values.
+ uint16_t wav_16bit = Math::fast_ftoi(((wav + 1) / 2) * UINT16_MAX);
+ // The .wav format expects wavs larger than 8 bits to be signed.
+ uint16_t wav_16bit_signed = wav_16bit - (INT16_MAX + 1);
+ encode_uint16(wav_16bit_signed, write_ptr + (i * 2));
+ }
+
+ return buffer;
+}
+
+void run_test(String file_name, AudioStreamWAV::Format data_format, bool stereo, float wav_rate, float wav_count) {
+ String save_path = OS::get_singleton()->get_cache_path().plus_file(file_name);
+
+ Vector<uint8_t> test_data;
+ if (data_format == AudioStreamWAV::FORMAT_8_BITS) {
+ test_data = gen_pcm8_test(wav_rate, wav_count, stereo);
+ } else {
+ test_data = gen_pcm16_test(wav_rate, wav_count, stereo);
+ }
+
+ Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV);
+ stream->set_mix_rate(wav_rate);
+ CHECK(stream->get_mix_rate() == wav_rate);
+
+ stream->set_format(data_format);
+ CHECK(stream->get_format() == data_format);
+
+ stream->set_stereo(stereo);
+ CHECK(stream->is_stereo() == stereo);
+
+ stream->set_data(test_data);
+ CHECK(stream->get_data() == test_data);
+
+ SUBCASE("Stream length is computed properly") {
+ CHECK(Math::is_equal_approx(stream->get_length(), wav_count / wav_rate));
+ }
+
+ SUBCASE("Stream can be saved as .wav") {
+ REQUIRE(stream->save_to_wav(save_path) == OK);
+
+ Error error;
+ Ref<FileAccess> wav_file = FileAccess::open(save_path, FileAccess::READ, &error);
+ REQUIRE(error == OK);
+
+#if TOOLS_ENABLED
+ // The WAV importer can be used if enabled to check that the saved file is valid.
+ Ref<ResourceImporterWAV> wav_importer = memnew(ResourceImporterWAV);
+
+ List<ResourceImporter::ImportOption> options_list;
+ wav_importer->get_import_options("", &options_list);
+
+ HashMap<StringName, Variant> options_map;
+ for (const ResourceImporter::ImportOption &E : options_list) {
+ options_map[E.option.name] = E.default_value;
+ }
+
+ REQUIRE(wav_importer->import(save_path, save_path, options_map, nullptr) == OK);
+
+ String load_path = save_path + "." + wav_importer->get_save_extension();
+ Ref<AudioStreamWAV> loaded_stream = ResourceLoader::load(load_path, "AudioStreamWAV", ResourceFormatImporter::CACHE_MODE_IGNORE, &error);
+ REQUIRE(error == OK);
+
+ CHECK(loaded_stream->get_format() == stream->get_format());
+ CHECK(loaded_stream->get_loop_mode() == stream->get_loop_mode());
+ CHECK(loaded_stream->get_loop_begin() == stream->get_loop_begin());
+ CHECK(loaded_stream->get_loop_end() == stream->get_loop_end());
+ CHECK(loaded_stream->get_mix_rate() == stream->get_mix_rate());
+ CHECK(loaded_stream->is_stereo() == stream->is_stereo());
+ CHECK(loaded_stream->get_length() == stream->get_length());
+ CHECK(loaded_stream->is_monophonic() == stream->is_monophonic());
+ CHECK(loaded_stream->get_data() == stream->get_data());
+#endif
+ }
+}
+
+TEST_CASE("[AudioStreamWAV] Mono PCM8 format") {
+ run_test("test_pcm8_mono.wav", AudioStreamWAV::FORMAT_8_BITS, false, WAV_RATE, WAV_COUNT);
+}
+
+TEST_CASE("[AudioStreamWAV] Mono PCM16 format") {
+ run_test("test_pcm16_mono.wav", AudioStreamWAV::FORMAT_16_BITS, false, WAV_RATE, WAV_COUNT);
+}
+
+TEST_CASE("[AudioStreamWAV] Stereo PCM8 format") {
+ run_test("test_pcm8_stereo.wav", AudioStreamWAV::FORMAT_8_BITS, true, WAV_RATE, WAV_COUNT);
+}
+
+TEST_CASE("[AudioStreamWAV] Stereo PCM16 format") {
+ run_test("test_pcm16_stereo.wav", AudioStreamWAV::FORMAT_16_BITS, true, WAV_RATE, WAV_COUNT);
+}
+
+TEST_CASE("[AudioStreamWAV] Alternate mix rate") {
+ run_test("test_pcm16_stereo_38000Hz.wav", AudioStreamWAV::FORMAT_16_BITS, true, 38000, 38000);
+}
+
+TEST_CASE("[AudioStreamWAV] save_to_wav() adds '.wav' file extension automatically") {
+ String save_path = OS::get_singleton()->get_cache_path().plus_file("test_wav_extension");
+ Vector<uint8_t> test_data = gen_pcm8_test(WAV_RATE, WAV_COUNT, false);
+ Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV);
+ stream->set_data(test_data);
+
+ REQUIRE(stream->save_to_wav(save_path) == OK);
+ Error error;
+ Ref<FileAccess> wav_file = FileAccess::open(save_path + ".wav", FileAccess::READ, &error);
+ CHECK(error == OK);
+}
+
+TEST_CASE("[AudioStreamWAV] Default values") {
+ Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV);
+ CHECK(stream->get_format() == AudioStreamWAV::FORMAT_8_BITS);
+ CHECK(stream->get_loop_mode() == AudioStreamWAV::LOOP_DISABLED);
+ CHECK(stream->get_loop_begin() == 0);
+ CHECK(stream->get_loop_end() == 0);
+ CHECK(stream->get_mix_rate() == 44100);
+ CHECK(stream->is_stereo() == false);
+ CHECK(stream->get_length() == 0);
+ CHECK(stream->is_monophonic() == false);
+ CHECK(stream->get_data() == Vector<uint8_t>{});
+ CHECK(stream->get_stream_name() == "");
+}
+
+TEST_CASE("[AudioStreamWAV] Save empty file") {
+ run_test("test_empty.wav", AudioStreamWAV::FORMAT_8_BITS, false, WAV_RATE, 0);
+}
+
+TEST_CASE("[AudioStreamWAV] Saving IMA ADPCM is not supported") {
+ String save_path = OS::get_singleton()->get_cache_path().plus_file("test_adpcm.wav");
+ Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV);
+ stream->set_format(AudioStreamWAV::FORMAT_IMA_ADPCM);
+ ERR_PRINT_OFF;
+ CHECK(stream->save_to_wav(save_path) == ERR_UNAVAILABLE);
+ ERR_PRINT_ON;
+}
+
+} // namespace TestAudioStreamWAV
+
+#endif // TEST_AUDIO_STREAM_WAV_H
diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h
index d28380d056..7605f24cf8 100644
--- a/tests/scene/test_code_edit.h
+++ b/tests/scene/test_code_edit.h
@@ -3251,7 +3251,7 @@ TEST_CASE("[SceneTree][CodeEdit] symbol lookup") {
SIGNAL_WATCH(code_edit, "symbol_validate");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(code_edit, Key::META);
#else
SEND_GUI_KEY_EVENT(code_edit, Key::CTRL);
diff --git a/tests/scene/test_path_3d.h b/tests/scene/test_path_3d.h
index 78f4e97f03..8ac3d7b5b4 100644
--- a/tests/scene/test_path_3d.h
+++ b/tests/scene/test_path_3d.h
@@ -81,4 +81,4 @@ TEST_CASE("[Path3D] Curve setter and getter") {
} // namespace TestPath3D
-#endif // TEST_PATH_3D
+#endif // TEST_PATH_3D_H
diff --git a/tests/scene/test_sprite_frames.h b/tests/scene/test_sprite_frames.h
new file mode 100644
index 0000000000..61bbd16493
--- /dev/null
+++ b/tests/scene/test_sprite_frames.h
@@ -0,0 +1,247 @@
+/*************************************************************************/
+/* test_sprite_frames.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_SPRITE_FRAMES_H
+#define TEST_SPRITE_FRAMES_H
+
+#include "scene/resources/sprite_frames.h"
+
+#include "tests/test_macros.h"
+
+namespace TestSpriteFrames {
+const String test_animation_name = "GodotTest";
+
+TEST_CASE("[SpriteFrames] Constructor methods") {
+ const SpriteFrames frames;
+ CHECK_MESSAGE(
+ frames.get_animation_names().size() == 1,
+ "Should be initialized with 1 entry.");
+ CHECK_MESSAGE(
+ frames.get_animation_names().get(0) == "default",
+ "Should be initialized with default entry.");
+}
+
+TEST_CASE("[SpriteFrames] Animation addition, list getter, renaming, removal, and retrieval") {
+ SpriteFrames frames;
+ Vector<String> test_names = { "default", "2", "1", "3" };
+
+ // "default" is there already
+ frames.add_animation("2");
+ frames.add_animation("1");
+ frames.add_animation("3");
+
+ for (int i = 0; i < test_names.size(); i++) {
+ CHECK_MESSAGE(
+ frames.has_animation(test_names[i]),
+ "Add animation properly worked for each value");
+ }
+
+ CHECK_MESSAGE(
+ !frames.has_animation("999"),
+ "Return false when checking for animation that does not exist");
+
+ List<StringName> sname_list;
+ frames.get_animation_list(&sname_list);
+
+ CHECK_MESSAGE(
+ sname_list.size() == test_names.size(),
+ "StringName List getter returned list of expected size");
+
+ for (int i = 0; i < test_names.size(); i++) {
+ CHECK_MESSAGE(
+ sname_list[i] == StringName(test_names[i]),
+ "StringName List getter returned expected values");
+ }
+
+ // get_animation_names() sorts the results.
+ Vector<String> string_vector = frames.get_animation_names();
+ test_names.sort();
+
+ for (int i = 0; i < test_names.size(); i++) {
+ CHECK_MESSAGE(
+ string_vector[i] == test_names[i],
+ "String Vector getter returned expected values");
+ }
+
+ // These error handling cases should not crash.
+ ERR_PRINT_OFF;
+ frames.rename_animation("This does not exist", "0");
+ ERR_PRINT_ON;
+
+ CHECK_MESSAGE(
+ !frames.has_animation("0"),
+ "Correctly handles rename error when entry does not exist");
+
+ // These error handling cases should not crash.
+ ERR_PRINT_OFF;
+ frames.rename_animation("3", "1");
+ ERR_PRINT_ON;
+
+ CHECK_MESSAGE(
+ frames.has_animation("3"),
+ "Correctly handles rename error when entry exists, but new name already exists");
+
+ ERR_PRINT_OFF;
+ frames.add_animation("1");
+ ERR_PRINT_ON;
+
+ CHECK_MESSAGE(
+ frames.get_animation_names().size() == 4,
+ "Correctly does not add when entry already exists");
+
+ frames.rename_animation("3", "9");
+
+ CHECK_MESSAGE(
+ frames.has_animation("9"),
+ "Animation renamed correctly");
+
+ frames.remove_animation("9");
+
+ CHECK_MESSAGE(
+ !frames.has_animation("9"),
+ "Animation removed correctly");
+
+ frames.clear_all();
+
+ CHECK_MESSAGE(
+ frames.get_animation_names().size() == 1,
+ "Clear all removed all animations and re-added the default animation entry");
+}
+
+TEST_CASE("[SpriteFrames] Animation Speed getter and setter") {
+ SpriteFrames frames;
+
+ frames.add_animation(test_animation_name);
+
+ CHECK_MESSAGE(
+ frames.get_animation_speed(test_animation_name) == 5.0,
+ "Sets new animation to default speed");
+
+ frames.set_animation_speed(test_animation_name, 123.0004);
+
+ CHECK_MESSAGE(
+ frames.get_animation_speed(test_animation_name) == 123.0004,
+ "Sets animation to positive double");
+
+ // These error handling cases should not crash.
+ ERR_PRINT_OFF;
+ frames.get_animation_speed("This does not exist");
+ frames.set_animation_speed("This does not exist", 100);
+ frames.set_animation_speed(test_animation_name, -999.999);
+ ERR_PRINT_ON;
+
+ CHECK_MESSAGE(
+ frames.get_animation_speed(test_animation_name) == 123.0004,
+ "Prevents speed of animation being set to a negative value");
+
+ frames.set_animation_speed(test_animation_name, 0.0);
+
+ CHECK_MESSAGE(
+ frames.get_animation_speed(test_animation_name) == 0.0,
+ "Sets animation to zero");
+}
+
+TEST_CASE("[SpriteFrames] Animation Loop getter and setter") {
+ SpriteFrames frames;
+
+ frames.add_animation(test_animation_name);
+
+ CHECK_MESSAGE(
+ frames.get_animation_loop(test_animation_name),
+ "Sets new animation to default loop value.");
+
+ frames.set_animation_loop(test_animation_name, true);
+
+ CHECK_MESSAGE(
+ frames.get_animation_loop(test_animation_name),
+ "Sets animation loop to true");
+
+ frames.set_animation_loop(test_animation_name, false);
+
+ CHECK_MESSAGE(
+ !frames.get_animation_loop(test_animation_name),
+ "Sets animation loop to false");
+
+ // These error handling cases should not crash.
+ ERR_PRINT_OFF;
+ frames.get_animation_loop("This does not exist");
+ frames.set_animation_loop("This does not exist", false);
+ ERR_PRINT_ON;
+}
+
+// TODO
+TEST_CASE("[SpriteFrames] Frame addition, removal, and retrieval") {
+ Ref<Texture2D> dummy_frame1;
+ dummy_frame1.instantiate();
+
+ SpriteFrames frames;
+ frames.add_animation(test_animation_name);
+ frames.add_animation("1");
+ frames.add_animation("2");
+
+ CHECK_MESSAGE(
+ frames.get_frame_count(test_animation_name) == 0,
+ "Animation has a default frame count of 0");
+
+ frames.add_frame(test_animation_name, dummy_frame1, 0);
+ frames.add_frame(test_animation_name, dummy_frame1, 1);
+ frames.add_frame(test_animation_name, dummy_frame1, 2);
+
+ CHECK_MESSAGE(
+ frames.get_frame_count(test_animation_name) == 3,
+ "Adds multiple frames");
+
+ frames.remove_frame(test_animation_name, 1);
+ frames.remove_frame(test_animation_name, 0);
+
+ CHECK_MESSAGE(
+ frames.get_frame_count(test_animation_name) == 1,
+ "Removes multiple frames");
+
+ // These error handling cases should not crash.
+ ERR_PRINT_OFF;
+ frames.add_frame("does not exist", dummy_frame1, 0);
+ frames.remove_frame(test_animation_name, -99);
+ frames.remove_frame("does not exist", 0);
+ ERR_PRINT_ON;
+
+ CHECK_MESSAGE(
+ frames.get_frame_count(test_animation_name) == 1,
+ "Handles bad values when adding or removing frames.");
+
+ frames.clear(test_animation_name);
+
+ CHECK_MESSAGE(
+ frames.get_frame_count(test_animation_name) == 0,
+ "Clears frames.");
+}
+} // namespace TestSpriteFrames
+
+#endif // TEST_SPRITE_FRAMES_H
diff --git a/tests/scene/test_text_edit.h b/tests/scene/test_text_edit.h
index 4098dd7ace..0fce359c5a 100644
--- a/tests/scene/test_text_edit.h
+++ b/tests/scene/test_text_edit.h
@@ -724,7 +724,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
CHECK(text_edit->has_selection());
CHECK(text_edit->get_selected_text() == "t");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::SHIFT | KeyModifierMask::ALT)
#else
SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::SHIFT | KeyModifierMask::CMD)
@@ -736,7 +736,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
CHECK(text_edit->has_selection());
CHECK(text_edit->get_selected_text() == "tes");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::SHIFT | KeyModifierMask::ALT)
#else
SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::SHIFT | KeyModifierMask::CMD)
@@ -1902,7 +1902,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("lines_edited_from");
SIGNAL_DISCARD("caret_changed");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::ALT | KeyModifierMask::SHIFT);
#else
SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
@@ -2013,7 +2013,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("lines_edited_from");
SIGNAL_DISCARD("caret_changed");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::ALT | KeyModifierMask::SHIFT);
#else
SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
@@ -2244,7 +2244,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("lines_edited_from");
SIGNAL_DISCARD("caret_changed");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::UP | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
#else
SEND_GUI_KEY_EVENT(text_edit, Key::HOME | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
@@ -2285,7 +2285,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("lines_edited_from");
SIGNAL_DISCARD("caret_changed");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::DOWN | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
#else
SEND_GUI_KEY_EVENT(text_edit, Key::END | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
@@ -2326,7 +2326,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("lines_edited_from");
SIGNAL_DISCARD("caret_changed");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
#else
SEND_GUI_KEY_EVENT(text_edit, Key::HOME | KeyModifierMask::SHIFT);
@@ -2383,7 +2383,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("lines_edited_from");
SIGNAL_DISCARD("caret_changed");
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
#else
SEND_GUI_KEY_EVENT(text_edit, Key::END | KeyModifierMask::SHIFT);
@@ -3139,7 +3139,7 @@ TEST_CASE("[SceneTree][TextEdit] viewport") {
v_scroll = text_edit->get_v_scroll();
SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, MouseButton::WHEEL_DOWN, Key::NONE);
text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
- CHECK(text_edit->get_v_scroll() > v_scroll);
+ CHECK(text_edit->get_v_scroll() >= v_scroll);
SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, MouseButton::WHEEL_UP, Key::NONE);
text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
CHECK(text_edit->get_v_scroll() == v_scroll);
@@ -3148,7 +3148,7 @@ TEST_CASE("[SceneTree][TextEdit] viewport") {
text_edit->set_v_scroll_speed(10000);
SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_DOWN, MouseButton::WHEEL_DOWN, Key::NONE);
text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
- CHECK(text_edit->get_v_scroll() > v_scroll);
+ CHECK(text_edit->get_v_scroll() >= v_scroll);
SEND_GUI_MOUSE_BUTTON_EVENT(text_edit, Point2i(10, 10), MouseButton::WHEEL_UP, MouseButton::WHEEL_UP, Key::NONE);
text_edit->notification(TextEdit::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
CHECK(text_edit->get_v_scroll() == v_scroll);
diff --git a/tests/scene/test_theme.h b/tests/scene/test_theme.h
index fedffc8449..f5b21eec32 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)) },
@@ -101,18 +101,24 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Good theme type names") {
SUBCASE("set_type_variation") {
for (const StringName &name : names) {
+ if (name == StringName()) { // Skip empty here, not allowed.
+ continue;
+ }
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_type_variation(valid_type_name, name);
- CHECK(ed.has_error == (name == StringName()));
+ CHECK_FALSE(ed.has_error);
}
for (const StringName &name : names) {
+ if (name == StringName()) { // Skip empty here, not allowed.
+ continue;
+ }
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_type_variation(name, valid_type_name);
- CHECK(ed.has_error == (name == StringName()));
+ CHECK_FALSE(ed.has_error);
}
}
}
@@ -125,6 +131,8 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Bad theme type names") {
String::utf8("contains_汉字"),
};
+ ERR_PRINT_OFF; // All these rightfully print errors.
+
SUBCASE("add_type") {
for (const StringName &name : names) {
Ref<Theme> theme = memnew(Theme);
@@ -175,6 +183,8 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Bad theme type names") {
CHECK(ed.has_error);
}
}
+
+ ERR_PRINT_ON;
}
TEST_CASE_FIXTURE(Fixture, "[Theme] Good theme item names") {
@@ -223,6 +233,8 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Bad theme item names") {
String::utf8("contains_汉字"),
};
+ ERR_PRINT_OFF; // All these rightfully print errors.
+
SUBCASE("set_theme_item") {
for (const StringName &name : names) {
for (const DataEntry &entry : valid_data) {
@@ -250,6 +262,8 @@ TEST_CASE_FIXTURE(Fixture, "[Theme] Bad theme item names") {
}
}
}
+
+ ERR_PRINT_ON;
}
} // namespace TestTheme
diff --git a/tests/servers/test_text_server.h b/tests/servers/test_text_server.h
index 066c280fd5..9ebd0f34b4 100644
--- a/tests/servers/test_text_server.h
+++ b/tests/servers/test_text_server.h
@@ -28,23 +28,23 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef TOOLS_ENABLED
-
#ifndef TEST_TEXT_SERVER_H
#define TEST_TEXT_SERVER_H
+#ifdef TOOLS_ENABLED
+
#include "editor/builtin_fonts.gen.h"
#include "servers/text_server.h"
#include "tests/test_macros.h"
namespace TestTextServer {
-TEST_SUITE("[[TextServer]") {
+TEST_SUITE("[TextServer]") {
TEST_CASE("[TextServer] Init, font loading and shaping") {
SUBCASE("[TextServer] Loading fonts") {
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
- TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+ CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC)) {
continue;
@@ -52,7 +52,7 @@ TEST_SUITE("[[TextServer]") {
RID font = ts->create_font();
ts->font_set_data_ptr(font, _font_NotoSans_Regular, _font_NotoSans_Regular_size);
- TEST_FAIL_COND(font == RID(), "Loading font failed.");
+ CHECK_FALSE_MESSAGE(font == RID(), "Loading font failed.");
ts->free_rid(font);
}
}
@@ -60,7 +60,7 @@ TEST_SUITE("[[TextServer]") {
SUBCASE("[TextServer] Text layout: Font fallback") {
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
- TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+ CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
continue;
@@ -79,26 +79,26 @@ TEST_SUITE("[[TextServer]") {
// 6^ 17^
RID ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
int gl_size = ts->shaped_text_get_glyph_count(ctx);
- TEST_FAIL_COND(gl_size == 0, "Shaping failed");
+ CHECK_FALSE_MESSAGE(gl_size == 0, "Shaping failed");
for (int j = 0; j < gl_size; j++) {
if (glyphs[j].start < 6) {
- TEST_FAIL_COND(glyphs[j].font_rid != font[1], "Incorrect font selected.");
+ CHECK_FALSE_MESSAGE(glyphs[j].font_rid != font[1], "Incorrect font selected.");
}
if ((glyphs[j].start > 6) && (glyphs[j].start < 16)) {
- TEST_FAIL_COND(glyphs[j].font_rid != font[0], "Incorrect font selected.");
+ CHECK_FALSE_MESSAGE(glyphs[j].font_rid != font[0], "Incorrect font selected.");
}
if (glyphs[j].start > 16) {
- TEST_FAIL_COND(glyphs[j].font_rid != RID(), "Incorrect font selected.");
- TEST_FAIL_COND(glyphs[j].index != test[glyphs[j].start], "Incorrect glyph index.");
+ CHECK_FALSE_MESSAGE(glyphs[j].font_rid != RID(), "Incorrect font selected.");
+ CHECK_FALSE_MESSAGE(glyphs[j].index != test[glyphs[j].start], "Incorrect glyph index.");
}
- TEST_FAIL_COND((glyphs[j].start < 0 || glyphs[j].end > test.length()), "Incorrect glyph range.");
- TEST_FAIL_COND(glyphs[j].font_size != 16, "Incorrect glyph font size.");
+ CHECK_FALSE_MESSAGE((glyphs[j].start < 0 || glyphs[j].end > test.length()), "Incorrect glyph range.");
+ CHECK_FALSE_MESSAGE(glyphs[j].font_size != 16, "Incorrect glyph font size.");
}
ts->free_rid(ctx);
@@ -113,7 +113,7 @@ TEST_SUITE("[[TextServer]") {
SUBCASE("[TextServer] Text layout: BiDi") {
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
- TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+ CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_BIDI_LAYOUT)) {
continue;
@@ -132,23 +132,23 @@ TEST_SUITE("[[TextServer]") {
// 7^ 26^
RID ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
int gl_size = ts->shaped_text_get_glyph_count(ctx);
- TEST_FAIL_COND(gl_size == 0, "Shaping failed");
+ CHECK_FALSE_MESSAGE(gl_size == 0, "Shaping failed");
for (int j = 0; j < gl_size; j++) {
if (glyphs[j].count > 0) {
if (glyphs[j].start < 7) {
- TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
+ CHECK_FALSE_MESSAGE(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
}
if ((glyphs[j].start > 8) && (glyphs[j].start < 23)) {
- TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) != TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
+ CHECK_FALSE_MESSAGE(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) != TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
}
if (glyphs[j].start > 26) {
- TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
+ CHECK_FALSE_MESSAGE(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
}
}
}
@@ -165,7 +165,7 @@ TEST_SUITE("[[TextServer]") {
SUBCASE("[TextServer] Text layout: Line break and align points") {
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
- TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+ CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
continue;
@@ -186,16 +186,16 @@ TEST_SUITE("[[TextServer]") {
{
String test = U"Test test long text long text\n";
RID ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
ts->shaped_text_update_breaks(ctx);
ts->shaped_text_update_justification_ops(ctx);
const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
int gl_size = ts->shaped_text_get_glyph_count(ctx);
- TEST_FAIL_COND(gl_size != 30, "Invalid glyph count.");
+ CHECK_FALSE_MESSAGE(gl_size != 30, "Invalid glyph count.");
for (int j = 0; j < gl_size; j++) {
bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -203,11 +203,11 @@ TEST_SUITE("[[TextServer]") {
bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
if (j == 4 || j == 9 || j == 14 || j == 19 || j == 24) {
- TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
} else if (j == 29) {
- TEST_FAIL_COND((soft || !space || !hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || !space || !hard || virt || elo), "Invalid glyph flags.");
} else {
- TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
}
}
ts->free_rid(ctx);
@@ -216,21 +216,63 @@ TEST_SUITE("[[TextServer]") {
{
String test = U"الحمـد";
RID ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
+ bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
+ ts->shaped_text_update_breaks(ctx);
+
+ const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
+ int gl_size = ts->shaped_text_get_glyph_count(ctx);
+ CHECK_FALSE_MESSAGE(gl_size != 6, "Invalid glyph count.");
+ for (int j = 0; j < gl_size; j++) {
+ bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
+ bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
+ bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE;
+ bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
+ bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
+ }
+ if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) {
+ ts->shaped_text_update_justification_ops(ctx);
+
+ glyphs = ts->shaped_text_get_glyphs(ctx);
+ gl_size = ts->shaped_text_get_glyph_count(ctx);
+
+ CHECK_FALSE_MESSAGE(gl_size != 6, "Invalid glyph count.");
+ for (int j = 0; j < gl_size; j++) {
+ bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
+ bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
+ bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE;
+ bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
+ bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
+ if (j == 1) {
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || !elo), "Invalid glyph flags.");
+ } else {
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
+ }
+ }
+ }
+ ts->free_rid(ctx);
+ }
+
+ {
+ String test = U"الحمد";
+ RID ctx = ts->create_shaped_text();
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
ts->shaped_text_update_breaks(ctx);
const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
int gl_size = ts->shaped_text_get_glyph_count(ctx);
- TEST_FAIL_COND(gl_size != 6, "Invalid glyph count.");
+ CHECK_FALSE_MESSAGE(gl_size != 5, "Invalid glyph count.");
for (int j = 0; j < gl_size; j++) {
bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE;
bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
- TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
}
if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) {
@@ -239,7 +281,7 @@ TEST_SUITE("[[TextServer]") {
glyphs = ts->shaped_text_get_glyphs(ctx);
gl_size = ts->shaped_text_get_glyph_count(ctx);
- TEST_FAIL_COND(gl_size != 6, "Invalid glyph count.");
+ CHECK_FALSE_MESSAGE(gl_size != 6, "Invalid glyph count.");
for (int j = 0; j < gl_size; j++) {
bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -247,9 +289,9 @@ TEST_SUITE("[[TextServer]") {
bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
if (j == 1) {
- TEST_FAIL_COND((soft || space || hard || virt || !elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || !virt || !elo), "Invalid glyph flags.");
} else {
- TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
}
}
}
@@ -259,15 +301,15 @@ TEST_SUITE("[[TextServer]") {
{
String test = U"الحمـد الرياضي العربي";
RID ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
ts->shaped_text_update_breaks(ctx);
const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
int gl_size = ts->shaped_text_get_glyph_count(ctx);
- TEST_FAIL_COND(gl_size != 21, "Invalid glyph count.");
+ CHECK_FALSE_MESSAGE(gl_size != 21, "Invalid glyph count.");
for (int j = 0; j < gl_size; j++) {
bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -275,9 +317,9 @@ TEST_SUITE("[[TextServer]") {
bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
if (j == 6 || j == 14) {
- TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
} else {
- TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
}
}
@@ -287,7 +329,7 @@ TEST_SUITE("[[TextServer]") {
glyphs = ts->shaped_text_get_glyphs(ctx);
gl_size = ts->shaped_text_get_glyph_count(ctx);
- TEST_FAIL_COND(gl_size != 23, "Invalid glyph count.");
+ CHECK_FALSE_MESSAGE(gl_size != 23, "Invalid glyph count.");
for (int j = 0; j < gl_size; j++) {
bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -295,13 +337,13 @@ TEST_SUITE("[[TextServer]") {
bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
if (j == 7 || j == 16) {
- TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
} else if (j == 3 || j == 9) {
- TEST_FAIL_COND((soft || space || hard || !virt || !elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || !virt || !elo), "Invalid glyph flags.");
} else if (j == 18) {
- TEST_FAIL_COND((soft || space || hard || virt || !elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || !elo), "Invalid glyph flags.");
} else {
- TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
}
}
}
@@ -312,16 +354,16 @@ TEST_SUITE("[[TextServer]") {
{
String test = U"เป็น ภาษา ราชà¸à¸²à¸£ à¹à¸¥à¸° ภาษา";
RID ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
ts->shaped_text_update_breaks(ctx);
ts->shaped_text_update_justification_ops(ctx);
const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
int gl_size = ts->shaped_text_get_glyph_count(ctx);
- TEST_FAIL_COND(gl_size != 25, "Invalid glyph count.");
+ CHECK_FALSE_MESSAGE(gl_size != 25, "Invalid glyph count.");
for (int j = 0; j < gl_size; j++) {
bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -329,9 +371,9 @@ TEST_SUITE("[[TextServer]") {
bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
if (j == 4 || j == 9 || j == 16 || j == 20) {
- TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
} else {
- TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
}
}
ts->free_rid(ctx);
@@ -340,16 +382,16 @@ TEST_SUITE("[[TextServer]") {
if (ts->has_feature(TextServer::FEATURE_BREAK_ITERATORS)) {
String test = U"เป็นภาษาราชà¸à¸²à¸£à¹à¸¥à¸°à¸ à¸²à¸©à¸²";
RID ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
ts->shaped_text_update_breaks(ctx);
ts->shaped_text_update_justification_ops(ctx);
const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
int gl_size = ts->shaped_text_get_glyph_count(ctx);
- TEST_FAIL_COND(gl_size != 25, "Invalid glyph count.");
+ CHECK_FALSE_MESSAGE(gl_size != 25, "Invalid glyph count.");
for (int j = 0; j < gl_size; j++) {
bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -357,9 +399,9 @@ TEST_SUITE("[[TextServer]") {
bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
if (j == 4 || j == 9 || j == 16 || j == 20) {
- TEST_FAIL_COND((!soft || !space || hard || !virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((!soft || !space || hard || !virt || elo), "Invalid glyph flags.");
} else {
- TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+ CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
}
}
ts->free_rid(ctx);
@@ -375,7 +417,7 @@ TEST_SUITE("[[TextServer]") {
SUBCASE("[TextServer] Text layout: Line breaking") {
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
- TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+ CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
continue;
@@ -394,21 +436,21 @@ TEST_SUITE("[[TextServer]") {
font.push_back(font2);
RID ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
bool ok = ts->shaped_text_add_string(ctx, test_1, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
PackedInt32Array brks = ts->shaped_text_get_line_breaks(ctx, 1);
- TEST_FAIL_COND(brks.size() != 6, "Invalid line breaks number.");
+ CHECK_FALSE_MESSAGE(brks.size() != 6, "Invalid line breaks number.");
if (brks.size() == 6) {
- TEST_FAIL_COND(brks[0] != 0, "Invalid line break position.");
- TEST_FAIL_COND(brks[1] != 5, "Invalid line break position.");
+ CHECK_FALSE_MESSAGE(brks[0] != 0, "Invalid line break position.");
+ CHECK_FALSE_MESSAGE(brks[1] != 5, "Invalid line break position.");
- TEST_FAIL_COND(brks[2] != 5, "Invalid line break position.");
- TEST_FAIL_COND(brks[3] != 10, "Invalid line break position.");
+ CHECK_FALSE_MESSAGE(brks[2] != 5, "Invalid line break position.");
+ CHECK_FALSE_MESSAGE(brks[3] != 10, "Invalid line break position.");
- TEST_FAIL_COND(brks[4] != 10, "Invalid line break position.");
- TEST_FAIL_COND(brks[5] != 14, "Invalid line break position.");
+ CHECK_FALSE_MESSAGE(brks[4] != 10, "Invalid line break position.");
+ CHECK_FALSE_MESSAGE(brks[5] != 14, "Invalid line break position.");
}
ts->free_rid(ctx);
@@ -423,7 +465,7 @@ TEST_SUITE("[[TextServer]") {
SUBCASE("[TextServer] Text layout: Justification") {
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
- TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+ CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
continue;
@@ -448,40 +490,40 @@ TEST_SUITE("[[TextServer]") {
float width_old, width;
if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) {
ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
ok = ts->shaped_text_add_string(ctx, test_1, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
width_old = ts->shaped_text_get_width(ctx);
width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND);
- TEST_FAIL_COND((width != width_old), "Invalid fill width.");
+ CHECK_FALSE_MESSAGE((width != width_old), "Invalid fill width.");
width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA);
- TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width.");
+ CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width.");
ts->free_rid(ctx);
ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
ok = ts->shaped_text_add_string(ctx, test_2, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
width_old = ts->shaped_text_get_width(ctx);
width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND);
- TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width.");
+ CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width.");
width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA);
- TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width.");
+ CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width.");
ts->free_rid(ctx);
}
ctx = ts->create_shaped_text();
- TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+ CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
ok = ts->shaped_text_add_string(ctx, test_3, font, 16);
- TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+ CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
width_old = ts->shaped_text_get_width(ctx);
width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND);
- TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width.");
+ CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width.");
ts->free_rid(ctx);
@@ -492,10 +534,31 @@ TEST_SUITE("[[TextServer]") {
}
}
+ SUBCASE("[TextServer] Unicode identifiers") {
+ for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
+ Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
+ CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
+
+ static const char32_t *data[19] = { U"-30", U"100", U"10.1", U"10,1", U"1e2", U"1e-2", U"1e2e3", U"0xAB", U"AB", U"Test1", U"1Test", U"Test*1", U"test_testeT", U"test_tes teT", U"عَلَيْكÙمْ", U"عَلَيْكÙمْTest", U"Ó’Ó–ÓšÓœ", U"_test", U"ÂÃÄÅĀĂĄÇĆĈĊ" };
+ static bool isid[19] = { false, false, false, false, false, false, false, false, true, true, false, false, true, false, true, true, true, true, true };
+ for (int j = 0; j < 19; j++) {
+ String s = String(data[j]);
+ CHECK(ts->is_valid_identifier(s) == isid[j]);
+ }
+
+ if (ts->has_feature(TextServer::FEATURE_UNICODE_IDENTIFIERS)) {
+ // Test UAX 3.2 ZW(N)J usage.
+ CHECK(ts->is_valid_identifier(U"\u0646\u0627\u0645\u0647\u200C\u0627\u06CC"));
+ CHECK(ts->is_valid_identifier(U"\u0D26\u0D43\u0D15\u0D4D\u200C\u0D38\u0D3E\u0D15\u0D4D\u0D37\u0D3F"));
+ CHECK(ts->is_valid_identifier(U"\u0DC1\u0DCA\u200D\u0DBB\u0DD3"));
+ }
+ }
+ }
+
SUBCASE("[TextServer] Strip Diacritics") {
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
- TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+ CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
if (ts->has_feature(TextServer::FEATURE_SHAPING)) {
CHECK(ts->strip_diacritics(U"ٱلسَّلَام٠عَلَيْكÙمْ") == U"ٱلسلام عليكم");
@@ -523,7 +586,7 @@ TEST_SUITE("[[TextServer]") {
continue;
}
- TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+ CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
{
String text1 = U"linguistically similar and effectively form";
// 14^ 22^ 26^ 38^
@@ -561,5 +624,6 @@ TEST_SUITE("[[TextServer]") {
}
}; // namespace TestTextServer
-#endif // TEST_TEXT_SERVER_H
#endif // TOOLS_ENABLED
+
+#endif // TEST_TEXT_SERVER_H
diff --git a/tests/test_macros.h b/tests/test_macros.h
index 6029a9cfc7..69ae0d3124 100644
--- a/tests/test_macros.h
+++ b/tests/test_macros.h
@@ -31,6 +31,7 @@
#ifndef TEST_MACROS_H
#define TEST_MACROS_H
+#include "core/core_globals.h"
#include "core/input/input_map.h"
#include "core/object/message_queue.h"
#include "core/variant/variant.h"
@@ -53,12 +54,12 @@
// Temporarily disable error prints to test failure paths.
// This allows to avoid polluting the test summary with error messages.
-// The `_print_error_enabled` boolean is defined in `core/print_string.cpp` and
+// The `print_error_enabled` boolean is defined in `core/core_globals.cpp` and
// works at global scope. It's used by various loggers in `should_log()` method,
// which are used by error macros which call into `OS::print_error`, effectively
// disabling any error messages to be printed from the engine side (not tests).
-#define ERR_PRINT_OFF _print_error_enabled = false;
-#define ERR_PRINT_ON _print_error_enabled = true;
+#define ERR_PRINT_OFF CoreGlobals::print_error_enabled = false;
+#define ERR_PRINT_ON CoreGlobals::print_error_enabled = true;
// Stringify all `Variant` compatible types for doctest output by default.
// https://github.com/onqtam/doctest/blob/master/doc/markdown/stringification.md
@@ -199,8 +200,8 @@ int register_test_command(String p_command, TestFunc p_function);
// We toggle _print_error_enabled to prevent display server not supported warnings.
#define SEND_GUI_MOUSE_MOTION_EVENT(m_object, m_local_pos, m_mask, m_modifers) \
{ \
- bool errors_enabled = _print_error_enabled; \
- _print_error_enabled = false; \
+ bool errors_enabled = CoreGlobals::print_error_enabled; \
+ CoreGlobals::print_error_enabled = false; \
Ref<InputEventMouseMotion> event; \
event.instantiate(); \
event->set_position(m_local_pos); \
@@ -209,7 +210,7 @@ int register_test_command(String p_command, TestFunc p_function);
_UPDATE_EVENT_MODIFERS(event, m_modifers); \
m_object->get_viewport()->push_input(event); \
MessageQueue::get_singleton()->flush(); \
- _print_error_enabled = errors_enabled; \
+ CoreGlobals::print_error_enabled = errors_enabled; \
}
// Utility class / macros for testing signals
@@ -271,22 +272,20 @@ public:
static SignalWatcher *get_singleton() { return singleton; }
void watch_signal(Object *p_object, const String &p_signal) {
- Vector<Variant> args;
- args.push_back(p_signal);
MethodInfo method_info;
ClassDB::get_signal(p_object->get_class(), p_signal, &method_info);
switch (method_info.arguments.size()) {
case 0: {
- p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_zero), args);
+ p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_zero).bind(p_signal));
} break;
case 1: {
- p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_one), args);
+ p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_one).bind(p_signal));
} break;
case 2: {
- p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_two), args);
+ p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_two).bind(p_signal));
} break;
case 3: {
- p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_three), args);
+ p_object->connect(p_signal, callable_mp(this, &SignalWatcher::_signal_callback_three).bind(p_signal));
} break;
default: {
MESSAGE("Signal ", p_signal, " arg count not supported.");
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index ac0cdf0cc1..3d186711cb 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -30,6 +30,8 @@
#include "test_main.h"
+#include "tests/core/input/test_input_event_key.h"
+#include "tests/core/input/test_shortcut.h"
#include "tests/core/io/test_config_file.h"
#include "tests/core/io/test_file_access.h"
#include "tests/core/io/test_image.h"
@@ -45,16 +47,23 @@
#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_quaternion.h"
#include "tests/core/math/test_random_number_generator.h"
#include "tests/core/math/test_rect2.h"
#include "tests/core/math/test_rect2i.h"
+#include "tests/core/math/test_transform_2d.h"
+#include "tests/core/math/test_transform_3d.h"
#include "tests/core/math/test_vector2.h"
#include "tests/core/math/test_vector2i.h"
#include "tests/core/math/test_vector3.h"
#include "tests/core/math/test_vector3i.h"
+#include "tests/core/math/test_vector4.h"
+#include "tests/core/math/test_vector4i.h"
#include "tests/core/object/test_class_db.h"
#include "tests/core/object/test_method_bind.h"
#include "tests/core/object/test_object.h"
+#include "tests/core/os/test_os.h"
#include "tests/core/string/test_node_path.h"
#include "tests/core/string/test_string.h"
#include "tests/core/string/test_translation.h"
@@ -65,18 +74,22 @@
#include "tests/core/templates/test_local_vector.h"
#include "tests/core/templates/test_lru.h"
#include "tests/core/templates/test_paged_array.h"
+#include "tests/core/templates/test_rid.h"
#include "tests/core/templates/test_vector.h"
#include "tests/core/test_crypto.h"
#include "tests/core/test_hashing_context.h"
#include "tests/core/test_time.h"
+#include "tests/core/threads/test_worker_thread_pool.h"
#include "tests/core/variant/test_array.h"
#include "tests/core/variant/test_dictionary.h"
#include "tests/core/variant/test_variant.h"
#include "tests/scene/test_animation.h"
+#include "tests/scene/test_audio_stream_wav.h"
#include "tests/scene/test_code_edit.h"
#include "tests/scene/test_curve.h"
#include "tests/scene/test_gradient.h"
#include "tests/scene/test_path_3d.h"
+#include "tests/scene/test_sprite_frames.h"
#include "tests/scene/test_text_edit.h"
#include "tests/scene/test_theme.h"
#include "tests/servers/test_text_server.h"
@@ -102,7 +115,7 @@ int test_main(int argc, char *argv[]) {
for (int i = 0; i < argc; i++) {
args.push_back(String::utf8(argv[i]));
}
- OS::get_singleton()->set_cmdline("", args);
+ OS::get_singleton()->set_cmdline("", args, List<String>());
// Run custom test tools.
if (test_commands) {
@@ -210,6 +223,15 @@ struct GodotTestCaseListener : public doctest::IReporter {
SceneTree::get_singleton()->initialize();
return;
}
+
+ if (name.find("Audio") != -1) {
+ // The last driver index should always be the dummy driver.
+ int dummy_idx = AudioDriverManager::get_driver_count() - 1;
+ AudioDriverManager::initialize(dummy_idx);
+ AudioServer *audio_server = memnew(AudioServer);
+ audio_server->init();
+ return;
+ }
}
void test_case_end(const doctest::CurrentTestCaseStats &) override {
@@ -255,7 +277,7 @@ struct GodotTestCaseListener : public doctest::IReporter {
if (RenderingServer::get_singleton()) {
RenderingServer::get_singleton()->sync();
- RenderingServer::get_singleton()->global_variables_clear();
+ RenderingServer::get_singleton()->global_shader_uniforms_clear();
RenderingServer::get_singleton()->finish();
memdelete(RenderingServer::get_singleton());
}
@@ -272,6 +294,11 @@ struct GodotTestCaseListener : public doctest::IReporter {
MessageQueue::get_singleton()->flush();
memdelete(MessageQueue::get_singleton());
}
+
+ if (AudioServer::get_singleton()) {
+ AudioServer::get_singleton()->finish();
+ memdelete(AudioServer::get_singleton());
+ }
}
void test_run_start() override {
diff --git a/tests/test_validate_testing.h b/tests/test_validate_testing.h
index 413a7e351d..1471a952cd 100644
--- a/tests/test_validate_testing.h
+++ b/tests/test_validate_testing.h
@@ -31,6 +31,7 @@
#ifndef TEST_VALIDATE_TESTING_H
#define TEST_VALIDATE_TESTING_H
+#include "core/core_globals.h"
#include "core/os/os.h"
#include "tests/test_macros.h"
@@ -49,10 +50,10 @@ TEST_SUITE("Validate tests") {
}
TEST_CASE("Muting Godot error messages") {
ERR_PRINT_OFF;
- CHECK_MESSAGE(!_print_error_enabled, "Error printing should be disabled.");
+ CHECK_MESSAGE(!CoreGlobals::print_error_enabled, "Error printing should be disabled.");
ERR_PRINT("Still waiting for Godot!"); // This should never get printed!
ERR_PRINT_ON;
- CHECK_MESSAGE(_print_error_enabled, "Error printing should be re-enabled.");
+ CHECK_MESSAGE(CoreGlobals::print_error_enabled, "Error printing should be re-enabled.");
}
TEST_CASE("Stringify Variant types") {
Variant var;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index ed8eb9f48f..664401fca6 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -44,7 +44,7 @@ Files extracted from upstream source:
## certs
- Upstream: Mozilla, via https://github.com/bagder/ca-bundle
-- Version: git (8b263a18fca98ea371e54227837321c5cdaa1ba7, 2021)
+- Version: git (7f33e7eb8472dbcf31fdcf50cd216c89a282825d, 2022)
- License: MPL 2.0
@@ -213,7 +213,7 @@ Files extracted from upstream source:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
-- Version: 4.3.0 (aee123fc83388b8f5acfb301d87bd92eccc5b843, 2022)
+- Version: 5.1.0 (f1f2be776bcd994fa9262622e1a7098a066e5cf7, 2022)
- License: MIT
Files extracted from upstream source:
@@ -231,6 +231,8 @@ Files extracted from upstream source:
Files extracted from upstream source:
- the `common` folder
+- `scriptset.*`, `ucln_in.*`, `uspoof.cpp"` and `uspoof_impl.cpp` from the `i18n` folder
+- `uspoof.h` from the `i18n/unicode` folder
- `LICENSE`
Files generated from upstream source:
@@ -328,15 +330,15 @@ Files extracted from upstream source:
## mbedtls
-- Upstream: https://tls.mbed.org/
-- Version: 2.16.12 (cf4667126010c665341f9e50ef691b7ef8294188, 2021)
+- Upstream: https://github.com/Mbed-TLS/mbedtls
+- Version: 2.18.1 (dd79db10014d85b26d11fe57218431f2e5ede6f2, 2022)
- License: Apache 2.0
File extracted from upstream release tarball:
- All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/` except `config_psa.h` and `psa_util.h`.
- All `*.c` and `*.h` from `library/` to `thirdparty/mbedtls/library/` except those starting with `psa_*`.
-- `LICENSE` and `apache-2.0.txt` files.
+- The `LICENSE` file.
- Applied the patch in `patches/1453.diff` (upstream PR:
https://github.com/ARMmbed/mbedtls/pull/1453).
- Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h`
@@ -597,7 +599,7 @@ Godot. See the patch in the `patches` folder for details.
## spirv-reflect
- Upstream: https://github.com/KhronosGroup/SPIRV-Reflect
-- Version: git (1aceb6af56e74b92a00378842dda5c5a73f49a4b, 2022)
+- Version: git (1ef99b09fa7ce5aee2c5cf70c61a4f7458d27e09, 2022)
- License: Apache 2.0
Does not track Vulkan SDK releases closely, but try to package a commit newer
diff --git a/thirdparty/certs/ca-certificates.crt b/thirdparty/certs/ca-certificates.crt
index e218b024d0..036f630d5b 100644
--- a/thirdparty/certs/ca-certificates.crt
+++ b/thirdparty/certs/ca-certificates.crt
@@ -1,7 +1,7 @@
##
## Bundle of CA Root Certificates
##
-## Certificate data from Mozilla as of: Thu Mar 31 08:10:21 2022 GMT
+## Certificate data from Mozilla as of: Tue Jul 19 14:20:01 2022 GMT
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
@@ -14,7 +14,7 @@
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version 1.29.
-## SHA256: d59c5c83ce7a7635fa95521d8d245677949b86d5574bfcc6f855b6a48f2d5566
+## SHA256: 9bf3799611fb58197f61d45e71ce3dc19f30e7dd73731915872ce5108a7bb066
##
@@ -993,30 +993,6 @@ tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
-----END CERTIFICATE-----
-Hellenic Academic and Research Institutions RootCA 2011
-=======================================================
------BEGIN CERTIFICATE-----
-MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
-O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
-aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
-IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
-AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
-IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
-IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
-1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
-71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
-8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
-3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
-MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
-MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
-b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
-XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
-TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
-/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
-7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
------END CERTIFICATE-----
-
Actalis Authentication Root CA
==============================
-----BEGIN CERTIFICATE-----
@@ -3279,3 +3255,206 @@ PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C
r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh
4rsUecrNIdSUtUlD
-----END CERTIFICATE-----
+
+Telia Root CA v2
+================
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT
+AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2
+MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK
+DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7
+6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q
+9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn
+pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl
+tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW
+5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr
+RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E
+BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4
+M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau
+BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W
+xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ
+8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5
+tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H
+eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C
+y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC
+QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15
+h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70
+sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9
+xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ
+raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc=
+-----END CERTIFICATE-----
+
+D-TRUST BR Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7
+dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu
+QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom
+AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87
+-----END CERTIFICATE-----
+
+D-TRUST EV Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8
+ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ
+raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR
+AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW
+-----END CERTIFICATE-----
+
+DigiCert TLS ECC P384 Root G5
+=============================
+-----BEGIN CERTIFICATE-----
+MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4
+NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg
+Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd
+lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj
+n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB
+/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds
+Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx
+AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA==
+-----END CERTIFICATE-----
+
+DigiCert TLS RSA4096 Root G5
+============================
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG
+EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0
+MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2
+IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8
+7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU
+AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces
+tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa
+zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV
+DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q
+TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy
+z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/
+MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk
+wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E
+FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
+GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN
+lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN
+MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/
+u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G
+OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh
+47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU
+FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ
+yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP
+bEtoL8pU9ozaMv7Da4M/OMZ+
+-----END CERTIFICATE-----
+
+Certainly Root R1
+=================
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE
+BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN
+MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy
+dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O
+5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl
+8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl
+DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI
+XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN
+KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ
+AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb
+rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1
+VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS
+p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz
+HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
+8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v
+MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB
+GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+
+gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH
+JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7
+fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw
+x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S
+X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8=
+-----END CERTIFICATE-----
+
+Certainly Root E1
+=================
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV
+UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0
+MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu
+bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4
+fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9
+YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E
+AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8
+rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
+-----END CERTIFICATE-----
+
+E-Tugra Global Root CA RSA v3
+=============================
+-----BEGIN CERTIFICATE-----
+MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQELBQAwgYAxCzAJ
+BgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAb
+BgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290
+IENBIFJTQSB2MzAeFw0yMDAzMTgwOTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJU
+UjEPMA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRF
+LVR1Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBSU0Eg
+djMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J77gnJY9LTQ91ew6aEOErx
+jYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscxuj7X/iWpKo429NEvx7epXTPcMHD4QGxL
+sqYxYdE0PD0xesevxKenhOGXpOhL9hd87jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF
+/YP9f4RtNGx/ardLAQO/rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8q
+QedmCeFLl+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bGwzrw
+bMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4znKS4iicvObpCdg6
+04nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBOM/J+JjKsBY04pOZ2PJ8QaQ5tndLB
+eSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiM
+bIedBi3x7+PmBvrFZhNb/FAHnnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbg
+h3cXTJ2w2AmoDVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD
+AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSytK7mLfcm1ap1
+LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAImocn+M684uGMQQ
+gC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN4
+38o2Fi+CiJ+8EUdPdk3ILY7r3y18Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/q
+ln0F7psTpURs+APQ3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3s
+SdPkvmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn99t2HVhjY
+sCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQmhty3QUBjYZgv6Rn7rWl
+DdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YAVSgU7NbHEqIbZULpkejLPoeJVF3Zr52X
+nGnnCv8PWniLYypMfUeUP95L6VPQMPHF9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFH
+IK+WEj5jlB0E5y67hscMmoi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiX
+YY60MGo8bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ
+-----END CERTIFICATE-----
+
+E-Tugra Global Root CA ECC v3
+=============================
+-----BEGIN CERTIFICATE-----
+MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNV
+BAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNV
+BAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENB
+IEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEP
+MA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1
+Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2
+w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31
+Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQ
+zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO
+PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W
+Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3
+-----END CERTIFICATE-----
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh
new file mode 100644
index 0000000000..e52a617c86
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh
@@ -0,0 +1,338 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_COVERAGE_HH
+#define OT_LAYOUT_COMMON_COVERAGE_HH
+
+#include "../types.hh"
+#include "CoverageFormat1.hh"
+#include "CoverageFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template<typename Iterator>
+static inline void Coverage_serialize (hb_serialize_context_t *c,
+ Iterator it);
+
+struct Coverage
+{
+
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ CoverageFormat1_3<SmallTypes> format1;
+ CoverageFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BORING_EXPANSION
+ CoverageFormat1_3<MediumTypes>format3;
+ CoverageFormat2_4<MediumTypes>format4;
+#endif
+ } 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));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (u.format3.sanitize (c));
+ case 4: return_trace (u.format4.sanitize (c));
+#endif
+ default:return_trace (true);
+ }
+ }
+
+ /* Has interface. */
+ static constexpr unsigned SENTINEL = NOT_COVERED;
+ typedef unsigned int value_t;
+ value_t operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ /* Predicate. */
+ bool operator () (hb_codepoint_t k) const { return has (k); }
+
+ unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
+ unsigned int get_coverage (hb_codepoint_t glyph_id) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.get_coverage (glyph_id);
+ case 2: return u.format2.get_coverage (glyph_id);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.get_coverage (glyph_id);
+ case 4: return u.format4.get_coverage (glyph_id);
+#endif
+ default:return NOT_COVERED;
+ }
+ }
+
+ unsigned get_population () const
+ {
+ switch (u.format) {
+ case 1: return u.format1.get_population ();
+ case 2: return u.format2.get_population ();
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.get_population ();
+ case 4: return u.format4.get_population ();
+#endif
+ default:return NOT_COVERED;
+ }
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+
+ unsigned count = 0;
+ unsigned num_ranges = 0;
+ hb_codepoint_t last = (hb_codepoint_t) -2;
+ for (auto g: glyphs)
+ {
+ if (last + 1 != g)
+ num_ranges++;
+ last = g;
+ count++;
+ }
+ u.format = count <= num_ranges * 3 ? 1 : 2;
+
+#ifndef HB_NO_BORING_EXPANSION
+ if (count && last > 0xFFFFu)
+ u.format += 2;
+#endif
+
+ switch (u.format)
+ {
+ case 1: return_trace (u.format1.serialize (c, glyphs));
+ case 2: return_trace (u.format2.serialize (c, glyphs));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (u.format3.serialize (c, glyphs));
+ case 4: return_trace (u.format4.serialize (c, glyphs));
+#endif
+ default:return_trace (false);
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto it =
+ + iter ()
+ | hb_filter (c->plan->glyph_map_gsub)
+ | hb_map_retains_sorting (c->plan->glyph_map_gsub)
+ ;
+
+ // Cache the iterator result as it will be iterated multiple times
+ // by the serialize code below.
+ hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
+ Coverage_serialize (c->serializer, glyphs.iter ());
+ return_trace (bool (glyphs));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.intersects (glyphs);
+ case 2: return u.format2.intersects (glyphs);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.intersects (glyphs);
+ case 4: return u.format4.intersects (glyphs);
+#endif
+ default:return false;
+ }
+ }
+ bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.intersects_coverage (glyphs, index);
+ case 2: return u.format2.intersects_coverage (glyphs, index);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.intersects_coverage (glyphs, index);
+ case 4: return u.format4.intersects_coverage (glyphs, index);
+#endif
+ default:return false;
+ }
+ }
+
+ /* Might return false if array looks unsorted.
+ * Used for faster rejection of corrupt data. */
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.collect_coverage (glyphs);
+ case 2: return u.format2.collect_coverage (glyphs);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.collect_coverage (glyphs);
+ case 4: return u.format4.collect_coverage (glyphs);
+#endif
+ default:return false;
+ }
+ }
+
+ template <typename IterableOut,
+ hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+ void intersect_set (const hb_set_t &glyphs, IterableOut &intersect_glyphs) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
+ case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
+ case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
+#endif
+ default:return ;
+ }
+ }
+
+ struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
+ {
+ static constexpr bool is_sorted_iterator = true;
+ iter_t (const Coverage &c_ = Null (Coverage))
+ {
+ memset (this, 0, sizeof (*this));
+ format = c_.u.format;
+ switch (format)
+ {
+ case 1: u.format1.init (c_.u.format1); return;
+ case 2: u.format2.init (c_.u.format2); return;
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: u.format3.init (c_.u.format3); return;
+ case 4: u.format4.init (c_.u.format4); return;
+#endif
+ default: return;
+ }
+ }
+ bool __more__ () const
+ {
+ switch (format)
+ {
+ case 1: return u.format1.__more__ ();
+ case 2: return u.format2.__more__ ();
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.__more__ ();
+ case 4: return u.format4.__more__ ();
+#endif
+ default:return false;
+ }
+ }
+ void __next__ ()
+ {
+ switch (format)
+ {
+ case 1: u.format1.__next__ (); break;
+ case 2: u.format2.__next__ (); break;
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: u.format3.__next__ (); break;
+ case 4: u.format4.__next__ (); break;
+#endif
+ default: break;
+ }
+ }
+ typedef hb_codepoint_t __item_t__;
+ __item_t__ __item__ () const { return get_glyph (); }
+
+ hb_codepoint_t get_glyph () const
+ {
+ switch (format)
+ {
+ case 1: return u.format1.get_glyph ();
+ case 2: return u.format2.get_glyph ();
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.get_glyph ();
+ case 4: return u.format4.get_glyph ();
+#endif
+ default:return 0;
+ }
+ }
+ bool operator != (const iter_t& o) const
+ {
+ if (unlikely (format != o.format)) return true;
+ switch (format)
+ {
+ case 1: return u.format1 != o.u.format1;
+ case 2: return u.format2 != o.u.format2;
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3 != o.u.format3;
+ case 4: return u.format4 != o.u.format4;
+#endif
+ default:return false;
+ }
+ }
+ iter_t __end__ () const
+ {
+ iter_t it = {};
+ it.format = format;
+ switch (format)
+ {
+ case 1: it.u.format1 = u.format1.__end__ (); break;
+ case 2: it.u.format2 = u.format2.__end__ (); break;
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: it.u.format3 = u.format3.__end__ (); break;
+ case 4: it.u.format4 = u.format4.__end__ (); break;
+#endif
+ default: break;
+ }
+ return it;
+ }
+
+ private:
+ unsigned int format;
+ union {
+#ifndef HB_NO_BORING_EXPANSION
+ CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */
+ CoverageFormat1_3<MediumTypes>::iter_t format3;
+#endif
+ CoverageFormat2_4<SmallTypes>::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
+ CoverageFormat1_3<SmallTypes>::iter_t format1;
+ } u;
+ };
+ iter_t iter () const { return iter_t (*this); }
+};
+
+template<typename Iterator>
+static inline void
+Coverage_serialize (hb_serialize_context_t *c,
+ Iterator it)
+{ c->start_embed<Coverage> ()->serialize (c, it); }
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_COMMON_COVERAGE_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh
new file mode 100644
index 0000000000..886babd2d1
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+
+#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
+#define OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+#define NOT_COVERED ((unsigned int) -1)
+
+template <typename Types>
+struct CoverageFormat1_3
+{
+ friend struct Coverage;
+
+ protected:
+ HBUINT16 coverageFormat; /* Format identifier--format = 1 */
+ SortedArray16Of<typename Types::HBGlyphID>
+ glyphArray; /* Array of GlyphIDs--in numerical order */
+ public:
+ DEFINE_SIZE_ARRAY (4, glyphArray);
+
+ private:
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (glyphArray.sanitize (c));
+ }
+
+ unsigned int get_coverage (hb_codepoint_t glyph_id) const
+ {
+ unsigned int i;
+ glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
+ return i;
+ }
+
+ unsigned get_population () const
+ {
+ return glyphArray.len;
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (glyphArray.serialize (c, glyphs));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ /* TODO Speed up, using hb_set_next() and bsearch()? */
+ for (const auto& g : glyphArray.as_array ())
+ if (glyphs->has (g))
+ return true;
+ return false;
+ }
+ bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+ { return glyphs->has (glyphArray[index]); }
+
+ template <typename IterableOut,
+ hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+ void intersect_set (const hb_set_t &glyphs, IterableOut &intersect_glyphs) const
+ {
+ unsigned count = glyphArray.len;
+ for (unsigned i = 0; i < count; i++)
+ if (glyphs.has (glyphArray[i]))
+ intersect_glyphs << glyphArray[i];
+ }
+
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ { return glyphs->add_sorted_array (glyphArray.as_array ()); }
+
+ public:
+ /* Older compilers need this to be public. */
+ struct iter_t
+ {
+ void init (const struct CoverageFormat1_3 &c_) { c = &c_; i = 0; }
+ bool __more__ () const { return i < c->glyphArray.len; }
+ void __next__ () { i++; }
+ hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
+ bool operator != (const iter_t& o) const
+ { return i != o.i; }
+ iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
+
+ private:
+ const struct CoverageFormat1_3 *c;
+ unsigned int i;
+ };
+ private:
+};
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh
new file mode 100644
index 0000000000..4ddb2a73e4
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh
@@ -0,0 +1,233 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
+#define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
+
+#include "RangeRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template <typename Types>
+struct CoverageFormat2_4
+{
+ friend struct Coverage;
+
+ protected:
+ HBUINT16 coverageFormat; /* Format identifier--format = 2 */
+ SortedArray16Of<RangeRecord<Types>>
+ rangeRecord; /* Array of glyph ranges--ordered by
+ * Start GlyphID. rangeCount entries
+ * long */
+ public:
+ DEFINE_SIZE_ARRAY (4, rangeRecord);
+
+ private:
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (rangeRecord.sanitize (c));
+ }
+
+ unsigned int get_coverage (hb_codepoint_t glyph_id) const
+ {
+ const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
+ return likely (range.first <= range.last)
+ ? (unsigned int) range.value + (glyph_id - range.first)
+ : NOT_COVERED;
+ }
+
+ unsigned get_population () const
+ {
+ typename Types::large_int ret = 0;
+ for (const auto &r : rangeRecord)
+ ret += r.get_population ();
+ return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+
+ /* TODO(iter) Write more efficiently? */
+
+ unsigned num_ranges = 0;
+ hb_codepoint_t last = (hb_codepoint_t) -2;
+ for (auto g: glyphs)
+ {
+ if (last + 1 != g)
+ num_ranges++;
+ last = g;
+ }
+
+ if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
+ if (!num_ranges) return_trace (true);
+
+ unsigned count = 0;
+ unsigned range = (unsigned) -1;
+ last = (hb_codepoint_t) -2;
+ for (auto g: glyphs)
+ {
+ if (last + 1 != g)
+ {
+ range++;
+ rangeRecord[range].first = g;
+ rangeRecord[range].value = count;
+ }
+ rangeRecord[range].last = g;
+ last = g;
+ count++;
+ }
+
+ return_trace (true);
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return hb_any (+ hb_iter (rangeRecord)
+ | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
+ }
+ bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+ {
+ auto cmp = [] (const void *pk, const void *pr) -> int
+ {
+ unsigned index = * (const unsigned *) pk;
+ const RangeRecord<Types> &range = * (const RangeRecord<Types> *) pr;
+ if (index < range.value) return -1;
+ if (index > (unsigned int) range.value + (range.last - range.first)) return +1;
+ return 0;
+ };
+
+ auto arr = rangeRecord.as_array ();
+ unsigned idx;
+ if (hb_bsearch_impl (&idx, index,
+ arr.arrayZ, arr.length, sizeof (arr[0]),
+ (int (*)(const void *_key, const void *_item)) cmp))
+ return arr.arrayZ[idx].intersects (*glyphs);
+ return false;
+ }
+
+ template <typename IterableOut,
+ hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+ void intersect_set (const hb_set_t &glyphs, IterableOut &intersect_glyphs) const
+ {
+ for (const auto& range : rangeRecord)
+ {
+ hb_codepoint_t last = range.last;
+ for (hb_codepoint_t g = range.first - 1;
+ glyphs.next (&g) && g <= last;)
+ intersect_glyphs << g;
+ }
+ }
+
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ {
+ for (const auto& range: rangeRecord)
+ if (unlikely (!range.collect_coverage (glyphs)))
+ return false;
+ return true;
+ }
+
+ public:
+ /* Older compilers need this to be public. */
+ struct iter_t
+ {
+ void init (const CoverageFormat2_4 &c_)
+ {
+ c = &c_;
+ coverage = 0;
+ i = 0;
+ j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
+ if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
+ {
+ /* Broken table. Skip. */
+ i = c->rangeRecord.len;
+ j = 0;
+ }
+ }
+ bool __more__ () const { return i < c->rangeRecord.len; }
+ void __next__ ()
+ {
+ if (j >= c->rangeRecord[i].last)
+ {
+ i++;
+ if (__more__ ())
+ {
+ unsigned int old = coverage;
+ j = c->rangeRecord[i].first;
+ coverage = c->rangeRecord[i].value;
+ if (unlikely (coverage != old + 1))
+ {
+ /* Broken table. Skip. Important to avoid DoS.
+ * Also, our callers depend on coverage being
+ * consecutive and monotonically increasing,
+ * ie. iota(). */
+ i = c->rangeRecord.len;
+ j = 0;
+ return;
+ }
+ }
+ else
+ j = 0;
+ return;
+ }
+ coverage++;
+ j++;
+ }
+ hb_codepoint_t get_glyph () const { return j; }
+ bool operator != (const iter_t& o) const
+ { return i != o.i || j != o.j; }
+ iter_t __end__ () const
+ {
+ iter_t it;
+ it.init (*c);
+ it.i = c->rangeRecord.len;
+ it.j = 0;
+ return it;
+ }
+
+ private:
+ const struct CoverageFormat2_4 *c;
+ unsigned int i, coverage;
+ hb_codepoint_t j;
+ };
+ private:
+};
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh
new file mode 100644
index 0000000000..a62629fad3
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
+#define OT_LAYOUT_COMMON_RANGERECORD_HH
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template <typename Types>
+struct RangeRecord
+{
+ typename Types::HBGlyphID first; /* First GlyphID in the range */
+ typename Types::HBGlyphID last; /* Last GlyphID in the range */
+ HBUINT16 value; /* Value */
+
+ DEFINE_SIZE_STATIC (2 + 2 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ int cmp (hb_codepoint_t g) const
+ { return g < first ? -1 : g <= last ? 0 : +1; }
+
+ unsigned get_population () const
+ {
+ if (unlikely (last < first)) return 0;
+ return (last - first + 1);
+ }
+
+ bool intersects (const hb_set_t &glyphs) const
+ { return glyphs.intersects (first, last); }
+
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ { return glyphs->add_range (first, last); }
+};
+
+}
+}
+}
+
+// TODO(garretrieger): This was previously implemented using
+// DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9);
+// but that only works when there is only a single namespace level.
+// The macro should probably be fixed so it can work in this situation.
+extern HB_INTERNAL const unsigned char _hb_Null_OT_RangeRecord[9];
+template <typename Spec>
+struct Null<OT::Layout::Common::RangeRecord<Spec>> {
+ static OT::Layout::Common::RangeRecord<Spec> const & get_null () {
+ return *reinterpret_cast<const OT::Layout::Common::RangeRecord<Spec> *> (_hb_Null_OT_RangeRecord);
+ }
+};
+
+
+#endif // #ifndef OT_LAYOUT_COMMON_RANGERECORD_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..7f58fac8b8
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh
@@ -0,0 +1,301 @@
+#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;
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "cursive attaching glyph at %d to glyph at %d",
+ i, j);
+ }
+
+ buffer->unsafe_to_break (i, j + 1);
+ 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;
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
+ pos[parent].y_offset = 0;
+ else
+ pos[parent].x_offset = 0;
+ }
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "cursive attached glyph at %d to glyph at %d",
+ i, j);
+ }
+
+ 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/GPOS.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh
new file mode 100644
index 0000000000..72829377a6
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh
@@ -0,0 +1,171 @@
+#ifndef OT_LAYOUT_GPOS_GPOS_HH
+#define OT_LAYOUT_GPOS_GPOS_HH
+
+#include "../../../hb-ot-layout-common.hh"
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+#include "PosLookup.hh"
+
+namespace OT {
+
+using Layout::GPOS_impl::PosLookup;
+
+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 = PosLookup;
+
+ 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
+ {
+ TRACE_SANITIZE (this);
+ return_trace (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
+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_GPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh
new file mode 100644
index 0000000000..a2d807cc32
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh
@@ -0,0 +1,56 @@
+#ifndef OT_LAYOUT_GPOS_LIGATUREARRAY_HH
+#define OT_LAYOUT_GPOS_LIGATUREARRAY_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);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_LIGATUREARRAY_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..cb5e8b2689
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh
@@ -0,0 +1,128 @@
+#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);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "attaching mark glyph at %d to glyph at %d",
+ c->buffer->idx, glyph_pos);
+ }
+
+ 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;
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "attached mark glyph at %d to glyph at %d",
+ c->buffer->idx, glyph_pos);
+ }
+
+ 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);
+ }
+};
+
+HB_INTERNAL inline
+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..c99b6b2e4b
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh
@@ -0,0 +1,41 @@
+#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_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ MarkBasePosFormat1_2<MediumTypes> format2;
+#endif
+ } 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)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ 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..ebb8c31c67
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
@@ -0,0 +1,219 @@
+#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. */
+
+template <typename Types>
+struct MarkBasePosFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ markCoverage; /* Offset to MarkCoverage table--from
+ * beginning of MarkBasePos subtable */
+ typename Types::template OffsetTo<Coverage>
+ baseCoverage; /* Offset to BaseCoverage table--from
+ * beginning of MarkBasePos subtable */
+ HBUINT16 classCount; /* Number of classes defined for marks */
+ typename Types::template OffsetTo<MarkArray>
+ markArray; /* Offset to MarkArray table--from
+ * beginning of MarkBasePos subtable */
+ typename Types::template OffsetTo<BaseArray>
+ baseArray; /* Offset to BaseArray table--from
+ * beginning of MarkBasePos subtable */
+
+ public:
+ DEFINE_SIZE_STATIC (4 + 4 * Types::size);
+
+ 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_multiplied (&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..8a4de9ffaa
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh
@@ -0,0 +1,41 @@
+#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_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ MarkLigPosFormat1_2<MediumTypes> format2;
+#endif
+ } 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)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ 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..1a8021237e
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
@@ -0,0 +1,206 @@
+#ifndef OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
+
+#include "LigatureArray.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct MarkLigPosFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ markCoverage; /* Offset to Mark Coverage table--from
+ * beginning of MarkLigPos subtable */
+ typename Types::template OffsetTo<Coverage>
+ ligatureCoverage; /* Offset to Ligature Coverage
+ * table--from beginning of MarkLigPos
+ * subtable */
+ HBUINT16 classCount; /* Number of defined mark classes */
+ typename Types::template OffsetTo<MarkArray>
+ markArray; /* Offset to MarkArray table--from
+ * beginning of MarkLigPos subtable */
+ typename Types::template OffsetTo<LigatureArray>
+ ligatureArray; /* Offset to LigatureArray table--from
+ * beginning of MarkLigPos subtable */
+ public:
+ DEFINE_SIZE_STATIC (4 + 4 * Types::size);
+
+ 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..74b5105c42
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh
@@ -0,0 +1,42 @@
+#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_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ MarkMarkPosFormat1_2<MediumTypes> format2;
+#endif
+ } 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)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ 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..fbcebb8044
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
@@ -0,0 +1,228 @@
+#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. */
+
+template <typename Types>
+struct MarkMarkPosFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ mark1Coverage; /* Offset to Combining Mark1 Coverage
+ * table--from beginning of MarkMarkPos
+ * subtable */
+ typename Types::template OffsetTo<Coverage>
+ mark2Coverage; /* Offset to Combining Mark2 Coverage
+ * table--from beginning of MarkMarkPos
+ * subtable */
+ HBUINT16 classCount; /* Number of defined mark classes */
+ typename Types::template OffsetTo<MarkArray>
+ mark1Array; /* Offset to Mark1Array table--from
+ * beginning of MarkMarkPos subtable */
+ typename Types::template OffsetTo<Mark2Array>
+ mark2Array; /* Offset to Mark2Array table--from
+ * beginning of MarkMarkPos subtable */
+ public:
+ DEFINE_SIZE_STATIC (4 + 4 * Types::size);
+
+ 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 & ~(uint32_t)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..72bfc43dc4
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh
@@ -0,0 +1,46 @@
+#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_3<SmallTypes> format1;
+ PairPosFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BORING_EXPANSION
+ PairPosFormat1_3<MediumTypes> format3;
+ PairPosFormat2_4<MediumTypes> format4;
+#endif
+ } 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)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+#endif
+ 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..3cb207281d
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh
@@ -0,0 +1,193 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
+
+#include "PairSet.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct PairPosFormat1_3
+{
+ using PairSet = GPOS_impl::PairSet<Types>;
+ using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
+
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<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) */
+ Array16Of<typename Types::template OffsetTo<PairSet>>
+ pairSet; /* Array of PairSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (8 + Types::size, 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 ();
+ typename 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 typename Types::template OffsetTo<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 typename Types::template OffsetTo<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 auto & _ :
+ + 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..a80fe0c226
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh
@@ -0,0 +1,328 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
+#define OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
+
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+template <typename Types>
+struct PairPosFormat2_4
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ typename Types::template OffsetTo<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) */
+ typename Types::template OffsetTo<ClassDef>
+ classDef1; /* Offset to ClassDef table--from
+ * beginning of PairPos subtable--for
+ * the first glyph of the pair */
+ typename Types::template OffsetTo<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 (10 + 3 * Types::size, 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:
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerning glyphs at %d,%d",
+ c->buffer->idx, skippy_iter.idx);
+ }
+
+ 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]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerned glyphs at %d,%d",
+ c->buffer->idx, 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/PairSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh
new file mode 100644
index 0000000000..4578fbd1d6
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh
@@ -0,0 +1,189 @@
+#ifndef OT_LAYOUT_GPOS_PAIRSET_HH
+#define OT_LAYOUT_GPOS_PAIRSET_HH
+
+#include "PairValueRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct PairSet
+{
+ template <typename Types2>
+ friend struct PairPosFormat1_3;
+
+ using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
+
+ protected:
+ HBUINT16 len; /* Number of PairValueRecords */
+ PairValueRecord firstPairValueRecord;
+ /* Array of PairValueRecords--ordered
+ * by GlyphID of the second glyph */
+ public:
+ DEFINE_SIZE_MIN (2);
+
+ 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));
+ }
+
+ 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)
+ {
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerning glyphs at %d,%d",
+ c->buffer->idx, pos);
+ }
+
+ 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 (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerned glyphs at %d,%d",
+ c->buffer->idx, 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);
+
+ typename 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);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRSET_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh
new file mode 100644
index 0000000000..bd95abde16
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh
@@ -0,0 +1,99 @@
+#ifndef OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
+#define OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
+
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct PairValueRecord
+{
+ template <typename Types2>
+ friend struct PairSet;
+
+ protected:
+ typename Types::HBGlyphID
+ 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 (Types::size, values);
+
+ 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 ()];
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRVALUERECORD_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..702f578b3c
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh
@@ -0,0 +1,95 @@
+#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);
+
+ 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..7cbdf6dc6c
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh
@@ -0,0 +1,138 @@
+#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;
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (*c->glyph_set, intersection);
+ if (!intersection) 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);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioning glyph at %d",
+ c->buffer->idx);
+ }
+
+ valueFormat.apply_value (c, this, values, buffer->cur_pos());
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioned glyph at %d",
+ c->buffer->idx);
+ }
+
+ 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;
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (glyphset, intersection);
+
+ auto it =
+ + hb_iter (intersection)
+ | 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..518fa9dcb0
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh
@@ -0,0 +1,154 @@
+#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);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioning glyph at %d",
+ c->buffer->idx);
+ }
+
+ valueFormat.apply_value (c, this,
+ &values[index * valueFormat.get_len ()],
+ buffer->cur_pos());
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioned glyph at %d",
+ c->buffer->idx);
+ }
+
+ 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/AlternateSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
index 484f347468..4a9e9672eb 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
@@ -5,12 +5,13 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
+template <typename Types>
struct AlternateSet
{
protected:
- Array16Of<HBGlyphID16>
+ Array16Of<typename Types::HBGlyphID>
alternates; /* Array of alternate GlyphIDs--in
* arbitrary order */
public:
@@ -56,8 +57,23 @@ struct AlternateSet
if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (alternate substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (alternates[alt_index - 1]);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (alternate substitution)",
+ c->buffer->idx - 1);
+ }
+
return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
index e5d999261f..37406179a2 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
@@ -6,14 +6,17 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct AlternateSubst
{
protected:
union {
- HBUINT16 format; /* Format identifier */
- AlternateSubstFormat1 format1;
+ HBUINT16 format; /* Format identifier */
+ AlternateSubstFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ AlternateSubstFormat1_2<MediumTypes> format2;
+#endif
} u;
public:
@@ -24,10 +27,15 @@ struct AlternateSubst
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)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
+ /* TODO This function is unused and not updated to 24bit GIDs. Should be done by using
+ * iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */
bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t<const HBGlyphID16> glyphs,
hb_array_t<const unsigned int> alternate_len_list,
@@ -42,6 +50,9 @@ struct AlternateSubst
default:return_trace (false);
}
}
+
+ /* TODO subset() should choose format. */
+
};
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
index af1cd7bedb..adec65d586 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
@@ -6,20 +6,21 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct AlternateSubstFormat1
+template <typename Types>
+struct AlternateSubstFormat1_2
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- Array16OfOffset16To<AlternateSet>
+ Array16Of<typename Types::template OffsetTo<AlternateSet<Types>>>
alternateSet; /* Array of AlternateSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, alternateSet);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, alternateSet);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -39,9 +40,8 @@ struct AlternateSubstFormat1
| hb_filter (c->parent_active_glyphs (), hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
+ | hb_apply ([c] (const AlternateSet<Types> &_) { _.closure (c); })
;
-
}
void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -52,7 +52,7 @@ struct AlternateSubstFormat1
+ hb_zip (this+coverage, alternateSet)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
+ | hb_apply ([c] (const AlternateSet<Types> &_) { _.collect_glyphs (c); })
;
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh
index bbb88b222f..08fd779f73 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh
@@ -7,7 +7,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ChainContextSubst : ChainContext {};
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh
index f4c78a9f02..968bba0481 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh
@@ -6,7 +6,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh
index 2af54e8ff4..9f8cb46b5e 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh
@@ -7,7 +7,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ContextSubst : Context {};
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh
index 40a3ff439f..831a7dfa2d 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh
@@ -7,7 +7,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ExtensionSubst : Extension<ExtensionSubst>
{
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
index ad153ce8d7..c0ff098f49 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
@@ -1,16 +1,15 @@
#ifndef OT_LAYOUT_GSUB_GSUB_HH
#define OT_LAYOUT_GSUB_GSUB_HH
-// TODO(garretrieger): move to new layout.
#include "../../../hb-ot-layout-gsubgpos.hh"
#include "Common.hh"
#include "SubstLookup.hh"
-using OT::Layout::GSUB::SubstLookup;
-
namespace OT {
+
+using Layout::GSUB_impl::SubstLookup;
+
namespace Layout {
-namespace GSUB {
/*
* GSUB -- Glyph Substitution
@@ -19,6 +18,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
@@ -31,7 +32,10 @@ struct GSUB : GSUBGPOS
}
bool sanitize (hb_sanitize_context_t *c) const
- { return GSUBGPOS::sanitize<SubstLookup> (c); }
+ {
+ TRACE_SANITIZE (this);
+ return_trace (GSUBGPOS::sanitize<SubstLookup> (c));
+ }
HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
hb_face_t *face) const;
@@ -46,10 +50,9 @@ struct GSUB : GSUBGPOS
}
-}
-struct GSUB_accelerator_t : Layout::GSUB::GSUB::accelerator_t {
- GSUB_accelerator_t (hb_face_t *face) : Layout::GSUB::GSUB::accelerator_t (face) {}
+struct GSUB_accelerator_t : Layout::GSUB::accelerator_t {
+ GSUB_accelerator_t (hb_face_t *face) : Layout::GSUB::accelerator_t (face) {}
};
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
index 0448d925d1..f373d921b5 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
@@ -5,18 +5,20 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
+template <typename Types>
struct Ligature
{
protected:
- HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */
- HeadlessArrayOf<HBGlyphID16>
- component; /* Array of component GlyphIDs--start
+ typename Types::HBGlyphID
+ ligGlyph; /* GlyphID of ligature to substitute */
+ HeadlessArrayOf<typename Types::HBGlyphID>
+ component; /* Array of component GlyphIDs--start
* with the second component--ordered
* in writing direction */
public:
- DEFINE_SIZE_ARRAY (4, component);
+ DEFINE_SIZE_ARRAY (Types::size + 2, component);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -62,7 +64,24 @@ struct Ligature
* as a "ligated" substitution. */
if (unlikely (count == 1))
{
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (ligature substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (ligGlyph);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (ligature substitution)",
+ c->buffer->idx - 1);
+ }
+
return_trace (true);
}
@@ -83,6 +102,31 @@ struct Ligature
return_trace (false);
}
+ unsigned pos = 0;
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ unsigned delta = c->buffer->sync_so_far ();
+
+ pos = c->buffer->idx;
+
+ char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0};
+ char *p = buf;
+
+ match_end += delta;
+ for (unsigned i = 0; i < count; i++)
+ {
+ match_positions[i] += delta;
+ if (i)
+ *p++ = ',';
+ sprintf (p, "%u", match_positions[i]);
+ p += strlen(p);
+ }
+
+ c->buffer->message (c->font,
+ "ligating glyphs at %s",
+ buf);
+ }
+
ligate_input (c,
count,
match_positions,
@@ -90,6 +134,14 @@ struct Ligature
ligGlyph,
total_component_count);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "ligated glyph at %d",
+ pos);
+ }
+
return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh
index 185b324b35..637cec7137 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh
@@ -6,12 +6,13 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
+template <typename Types>
struct LigatureSet
{
protected:
- Array16OfOffset16To<Ligature>
+ Array16OfOffset16To<Ligature<Types>>
ligature; /* Array LigatureSet tables
* ordered by preference */
public:
@@ -28,7 +29,7 @@ struct LigatureSet
return
+ hb_iter (ligature)
| hb_map (hb_add (this))
- | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
+ | hb_map ([glyphs] (const Ligature<Types> &_) { return _.intersects (glyphs); })
| hb_any
;
}
@@ -37,7 +38,7 @@ struct LigatureSet
{
+ hb_iter (ligature)
| hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.closure (c); })
+ | hb_apply ([c] (const Ligature<Types> &_) { _.closure (c); })
;
}
@@ -45,7 +46,7 @@ struct LigatureSet
{
+ hb_iter (ligature)
| hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); })
+ | hb_apply ([c] (const Ligature<Types> &_) { _.collect_glyphs (c); })
;
}
@@ -54,7 +55,7 @@ struct LigatureSet
return
+ hb_iter (ligature)
| hb_map (hb_add (this))
- | hb_map ([c] (const Ligature &_) { return _.would_apply (c); })
+ | hb_map ([c] (const Ligature<Types> &_) { return _.would_apply (c); })
| hb_any
;
}
@@ -65,7 +66,7 @@ struct LigatureSet
unsigned int num_ligs = ligature.len;
for (unsigned int i = 0; i < num_ligs; i++)
{
- const Ligature &lig = this+ligature[i];
+ const auto &lig = this+ligature[i];
if (lig.apply (c)) return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
index a029bf5e9f..63707972a8 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
@@ -6,14 +6,17 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct LigatureSubst
{
protected:
union {
- HBUINT16 format; /* Format identifier */
- LigatureSubstFormat1 format1;
+ HBUINT16 format; /* Format identifier */
+ LigatureSubstFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ LigatureSubstFormat1_2<MediumTypes> format2;
+#endif
} u;
public:
@@ -24,10 +27,16 @@ struct LigatureSubst
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)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
+ /* TODO This function is only used by small GIDs, and not updated to 24bit GIDs. Should
+ * be done by using iterators. While at it perhaps using iterator of arrays of hb_codepoint_t
+ * instead. */
bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t<const HBGlyphID16> first_glyphs,
hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
@@ -49,6 +58,9 @@ struct LigatureSubst
default:return_trace (false);
}
}
+
+ /* TODO subset() should choose format. */
+
};
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
index 19dfe98469..32b642c38a 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
@@ -6,20 +6,21 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct LigatureSubstFormat1
+template <typename Types>
+struct LigatureSubstFormat1_2
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- Array16OfOffset16To<LigatureSet>
+ Array16Of<typename Types::template OffsetTo<LigatureSet<Types>>>
ligatureSet; /* Array LigatureSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, ligatureSet);
+ DEFINE_SIZE_ARRAY (4 + Types::size, ligatureSet);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -33,7 +34,7 @@ struct LigatureSubstFormat1
+ hb_zip (this+coverage, ligatureSet)
| hb_filter (*glyphs, hb_first)
| hb_map (hb_second)
- | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
+ | hb_map ([this, glyphs] (const typename Types::template OffsetTo<LigatureSet<Types>> &_)
{ return (this+_).intersects (glyphs); })
| hb_any
;
@@ -48,7 +49,7 @@ struct LigatureSubstFormat1
| hb_filter (c->parent_active_glyphs (), hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
+ | hb_apply ([c] (const LigatureSet<Types> &_) { _.closure (c); })
;
}
@@ -62,7 +63,7 @@ struct LigatureSubstFormat1
+ hb_zip (this+coverage, ligatureSet)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); })
+ | hb_apply ([c] (const LigatureSet<Types> &_) { _.collect_glyphs (c); })
;
}
@@ -73,7 +74,7 @@ struct LigatureSubstFormat1
unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
if (likely (index == NOT_COVERED)) return false;
- const LigatureSet &lig_set = this+ligatureSet[index];
+ const auto &lig_set = this+ligatureSet[index];
return lig_set.would_apply (c);
}
@@ -84,7 +85,7 @@ struct LigatureSubstFormat1
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- const LigatureSet &lig_set = this+ligatureSet[index];
+ const auto &lig_set = this+ligatureSet[index];
return_trace (lig_set.apply (c));
}
@@ -128,7 +129,7 @@ struct LigatureSubstFormat1
hb_set_t new_coverage;
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
| hb_filter (glyphset, hb_first)
- | hb_filter ([&] (const LigatureSet& _) {
+ | hb_filter ([&] (const LigatureSet<Types>& _) {
return _.intersects (&glyphset);
}, hb_second)
| hb_map (hb_first)
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
index b289175504..98f2f5fe7a 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
@@ -6,14 +6,17 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct MultipleSubst
{
protected:
union {
- HBUINT16 format; /* Format identifier */
- MultipleSubstFormat1 format1;
+ HBUINT16 format; /* Format identifier */
+ MultipleSubstFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ MultipleSubstFormat1_2<MediumTypes> format2;
+#endif
} u;
public:
@@ -25,10 +28,15 @@ struct MultipleSubst
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)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
+ /* TODO This function is unused and not updated to 24bit GIDs. Should be done by using
+ * iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */
bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t<const HBGlyphID16> glyphs,
hb_array_t<const unsigned int> substitute_len_list,
@@ -43,6 +51,9 @@ struct MultipleSubst
default:return_trace (false);
}
}
+
+ /* TODO subset() should choose format. */
+
};
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
index 54c6dc8478..89a04ec3b1 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
@@ -6,20 +6,21 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct MultipleSubstFormat1
+template <typename Types>
+struct MultipleSubstFormat1_2
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- Array16OfOffset16To<Sequence>
+ Array16Of<typename Types::template OffsetTo<Sequence<Types>>>
sequence; /* Array of Sequence tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, sequence);
+ DEFINE_SIZE_ARRAY (4 + Types::size, sequence);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -39,7 +40,7 @@ struct MultipleSubstFormat1
| hb_filter (c->parent_active_glyphs (), hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.closure (c); })
+ | hb_apply ([c] (const Sequence<Types> &_) { _.closure (c); })
;
}
@@ -51,7 +52,7 @@ struct MultipleSubstFormat1
+ hb_zip (this+coverage, sequence)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
+ | hb_apply ([c] (const Sequence<Types> &_) { _.collect_glyphs (c); })
;
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
index 435d80fd31..48e208efb9 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
@@ -6,7 +6,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ReverseChainSingleSubst
{
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
index 7a79a9df25..a23e92028e 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
@@ -5,7 +5,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ReverseChainSingleSubstFormat1
{
@@ -33,10 +33,10 @@ struct ReverseChainSingleSubstFormat1
TRACE_SANITIZE (this);
if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
if (!lookahead.sanitize (c, this))
return_trace (false);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
return_trace (substitute.sanitize (c));
}
@@ -45,7 +45,7 @@ struct ReverseChainSingleSubstFormat1
if (!(this+coverage).intersects (glyphs))
return false;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
unsigned int count;
@@ -69,8 +69,8 @@ struct ReverseChainSingleSubstFormat1
{
if (!intersects (c->glyphs)) return;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
+ hb_zip (this+coverage, substitute)
| hb_filter (c->parent_active_glyphs (), hb_first)
@@ -91,12 +91,12 @@ struct ReverseChainSingleSubstFormat1
for (unsigned int i = 0; i < count; i++)
if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
count = lookahead.len;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
count = substitute.len;
c->output->add_array (substitute.arrayZ, substitute.len);
}
@@ -115,8 +115,8 @@ struct ReverseChainSingleSubstFormat1
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
if (unlikely (index >= substitute.len)) return_trace (false);
@@ -131,7 +131,23 @@ struct ReverseChainSingleSubstFormat1
c->buffer->idx + 1, &end_index))
{
c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replacing glyph at %d (reverse chaining substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph_inplace (substitute[index]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (reverse chaining substitution)",
+ c->buffer->idx);
+ }
+
/* Note: We DON'T decrease buffer->idx. The main loop does it
* for us. This is useful for preventing surprises if someone
* calls us through a Context lookup. */
@@ -206,8 +222,8 @@ struct ReverseChainSingleSubstFormat1
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
auto it =
+ hb_zip (this+coverage, substitute)
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
index ebd451e6ba..3d84a5e6ea 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
@@ -5,12 +5,13 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
+template <typename Types>
struct Sequence
{
protected:
- Array16Of<HBGlyphID16>
+ Array16Of<typename Types::HBGlyphID>
substitute; /* String of GlyphIDs to substitute */
public:
DEFINE_SIZE_ARRAY (2, substitute);
@@ -39,17 +40,58 @@ struct Sequence
* as a "multiplied" substitution. */
if (unlikely (count == 1))
{
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (multiple substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (substitute.arrayZ[0]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (multiple subtitution)",
+ c->buffer->idx - 1);
+ }
+
return_trace (true);
}
/* Spec disallows this, but Uniscribe allows it.
* https://github.com/harfbuzz/harfbuzz/issues/253 */
else if (unlikely (count == 0))
{
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "deleting glyph at %d (multiple substitution)",
+ c->buffer->idx);
+ }
+
c->buffer->delete_glyph ();
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "deleted glyph at %d (multiple substitution)",
+ c->buffer->idx);
+ }
+
return_trace (true);
}
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "multiplying glyph at %d",
+ c->buffer->idx);
+ }
+
unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
@@ -64,6 +106,26 @@ struct Sequence
}
c->buffer->skip_glyph ();
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+
+ char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0};
+ char *p = buf;
+
+ for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++)
+ {
+ if (buf < p)
+ *p++ = ',';
+ sprintf (p, "%u", i);
+ p += strlen(p);
+ }
+
+ c->buffer->message (c->font,
+ "multiplied glyphs at %s",
+ buf);
+ }
+
return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
index 786428fe45..6942e6997f 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
@@ -7,15 +7,19 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct SingleSubst
{
protected:
union {
- HBUINT16 format; /* Format identifier */
- SingleSubstFormat1 format1;
- SingleSubstFormat2 format2;
+ HBUINT16 format; /* Format identifier */
+ SingleSubstFormat1_3<SmallTypes> format1;
+ SingleSubstFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BORING_EXPANSION
+ SingleSubstFormat1_3<MediumTypes> format3;
+ SingleSubstFormat2_4<MediumTypes> format4;
+#endif
} u;
public:
@@ -28,6 +32,10 @@ struct SingleSubst
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)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
@@ -45,11 +53,24 @@ struct SingleSubst
if (glyphs)
{
format = 1;
+ hb_codepoint_t mask = 0xFFFFu;
+
+#ifndef HB_NO_BORING_EXPANSION
+ if (+ glyphs
+ | hb_map_retains_sorting (hb_first)
+ | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
+ {
+ format += 2;
+ mask = 0xFFFFFFu;
+ }
+#endif
+
auto get_delta = [=] (hb_codepoint_pair_t _)
- { return (unsigned) (_.second - _.first) & 0xFFFF; };
+ { return (unsigned) (_.second - _.first) & mask; };
delta = get_delta (*glyphs);
- if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
+ if (!hb_all (++(+glyphs), delta, get_delta)) format += 1;
}
+
u.format = format;
switch (u.format) {
case 1: return_trace (u.format1.serialize (c,
@@ -57,6 +78,13 @@ struct SingleSubst
| hb_map_retains_sorting (hb_first),
delta));
case 2: return_trace (u.format2.serialize (c, glyphs));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (u.format3.serialize (c,
+ + glyphs
+ | hb_map_retains_sorting (hb_first),
+ delta));
+ case 4: return_trace (u.format4.serialize (c, glyphs));
+#endif
default:return_trace (false);
}
}
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
index 3c6b2954ce..4b17243d81 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
@@ -5,20 +5,22 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct SingleSubstFormat1
+template <typename Types>
+struct SingleSubstFormat1_3
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- HBUINT16 deltaGlyphID; /* Add to original GlyphID to get
+ typename Types::HBUINT
+ deltaGlyphID; /* Add to original GlyphID to get
* substitute GlyphID, modulo 0x10000 */
public:
- DEFINE_SIZE_STATIC (6);
+ DEFINE_SIZE_STATIC (2 + 2 * Types::size);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -26,6 +28,9 @@ struct SingleSubstFormat1
return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
}
+ hb_codepoint_t get_mask () const
+ { return (1 << (8 * Types::size)) - 1; }
+
bool intersects (const hb_set_t *glyphs) const
{ return (this+coverage).intersects (glyphs); }
@@ -34,14 +39,28 @@ struct SingleSubstFormat1
void closure (hb_closure_context_t *c) const
{
- unsigned d = deltaGlyphID;
-
- + hb_iter (this+coverage)
- | hb_filter (c->parent_active_glyphs ())
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (c->parent_active_glyphs (), intersection);
+
+ /* In degenerate fuzzer-found fonts, but not real fonts,
+ * this table can keep adding new glyphs in each round of closure.
+ * Refuse to close-over, if it maps glyph range to overlapping range. */
+ hb_codepoint_t min_before = intersection.get_min ();
+ hb_codepoint_t max_before = intersection.get_max ();
+ hb_codepoint_t min_after = (min_before + d) & mask;
+ hb_codepoint_t max_after = (max_before + d) & mask;
+ if ((this+coverage).get_population () >= max_before - min_before &&
+ ((min_before <= min_after && min_after <= max_before) ||
+ (min_before <= max_after && max_after <= max_before)))
+ return;
+
+ + hb_iter (intersection)
+ | hb_map ([d, mask] (hb_codepoint_t g) { return (g + d) & mask; })
| hb_sink (c->output)
;
-
}
void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -49,9 +68,11 @@ struct SingleSubstFormat1
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- unsigned d = deltaGlyphID;
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ hb_iter (this+coverage)
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
+ | hb_map ([d, mask] (hb_codepoint_t g) { return (g + d) & mask; })
| hb_sink (c->output)
;
}
@@ -68,11 +89,28 @@ struct SingleSubstFormat1
unsigned int index = (this+coverage).get_coverage (glyph_id);
if (likely (index == NOT_COVERED)) return_trace (false);
- /* According to the Adobe Annotated OpenType Suite, result is always
- * limited to 16bit. */
- glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ glyph_id = (glyph_id + d) & mask;
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (single substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (glyph_id);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (single substitution)",
+ c->buffer->idx - 1);
+ }
+
return_trace (true);
}
@@ -95,14 +133,17 @@ struct SingleSubstFormat1
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
- hb_codepoint_t delta = deltaGlyphID;
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (glyphset, intersection);
auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting ([&] (hb_codepoint_t g) {
+ + hb_iter (intersection)
+ | hb_map_retains_sorting ([d, mask] (hb_codepoint_t g) {
return hb_codepoint_pair_t (g,
- (g + delta) & 0xFFFF); })
+ (g + d) & mask); })
| hb_filter (glyphset, hb_second)
| hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
index df75bb52bb..fb1e90d03e 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
@@ -5,21 +5,22 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct SingleSubstFormat2
+template <typename Types>
+struct SingleSubstFormat2_4
{
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- Array16Of<HBGlyphID16>
+ Array16Of<typename Types::HBGlyphID>
substitute; /* Array of substitute
* GlyphIDs--ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, substitute);
+ DEFINE_SIZE_ARRAY (4 + Types::size, substitute);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -67,8 +68,23 @@ struct SingleSubstFormat2
if (unlikely (index >= substitute.len)) return_trace (false);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (single substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (substitute[index]);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (single substitution)",
+ c->buffer->idx - 1);
+ }
+
return_trace (true);
}
@@ -103,7 +119,7 @@ struct SingleSubstFormat2
+ hb_zip (this+coverage, substitute)
| hb_filter (glyphset, hb_first)
| hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const typename Types::HBGlyphID &> p) -> hb_codepoint_pair_t
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
;
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
index 3419b5a734..320685b868 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
@@ -6,11 +6,11 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct SubstLookup : Lookup
{
- typedef SubstLookupSubTable SubTable;
+ using SubTable = SubstLookupSubTable;
bool sanitize (hb_sanitize_context_t *c) const
{ return Lookup::sanitize<SubTable> (c); }
@@ -25,7 +25,7 @@ struct SubstLookup : Lookup
{
unsigned int type = get_type ();
if (unlikely (type == SubTable::Extension))
- return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse ();
+ return get_subtable (0).u.extension.is_reverse ();
return lookup_type_is_reverse (type);
}
@@ -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,12 +98,15 @@ struct SubstLookup : Lookup
return dispatch (c);
}
- static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
+ template<typename Glyphs, typename Substitutes,
+ hb_requires (hb_is_sorted_source_of (Glyphs,
+ const hb_codepoint_t) &&
+ hb_is_source_of (Substitutes,
+ const hb_codepoint_t))>
bool serialize_single (hb_serialize_context_t *c,
uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const HBGlyphID16> substitutes)
+ Glyphs glyphs,
+ Substitutes substitutes)
{
TRACE_SERIALIZE (this);
if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
@@ -206,8 +207,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/Layout/GSUB/SubstLookupSubTable.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh
index 53e963e2a2..a525fba039 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh
@@ -13,7 +13,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct SubstLookupSubTable
{
diff --git a/thirdparty/harfbuzz/src/OT/Layout/types.hh b/thirdparty/harfbuzz/src/OT/Layout/types.hh
new file mode 100644
index 0000000000..6a43403e94
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/types.hh
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_TYPES_HH
+#define OT_LAYOUT_TYPES_HH
+
+namespace OT {
+namespace Layout {
+
+struct SmallTypes {
+ static constexpr unsigned size = 2;
+ using large_int = uint32_t;
+ using HBUINT = HBUINT16;
+ using HBGlyphID = HBGlyphID16;
+ using Offset = Offset16;
+ template <typename Type, bool has_null=true>
+ using OffsetTo = OT::Offset16To<Type, has_null>;
+ template <typename Type>
+ using ArrayOf = OT::Array16Of<Type>;
+ template <typename Type>
+ using SortedArrayOf = OT::SortedArray16Of<Type>;
+};
+
+struct MediumTypes {
+ static constexpr unsigned size = 3;
+ using large_int = uint64_t;
+ using HBUINT = HBUINT24;
+ using HBGlyphID = HBGlyphID24;
+ using Offset = Offset24;
+ template <typename Type, bool has_null=true>
+ using OffsetTo = OT::Offset24To<Type, has_null>;
+ template <typename Type>
+ using ArrayOf = OT::Array24Of<Type>;
+ template <typename Type>
+ using SortedArrayOf = OT::SortedArray24Of<Type>;
+};
+
+}
+}
+
+#endif /* OT_LAYOUT_TYPES_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
new file mode 100644
index 0000000000..98c2ee4e73
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
@@ -0,0 +1,298 @@
+#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,
+#ifndef HB_NO_BEYOND_64K
+ GID_IS_24BIT = 0x2000
+#endif
+ };
+
+ public:
+ unsigned int get_size () const
+ {
+ unsigned int size = min_size;
+ /* glyphIndex is 24bit instead of 16bit */
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT) size += HBGlyphID24::static_size - HBGlyphID16::static_size;
+#endif
+ /* 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 auto *p = &StructAfter<const HBUINT8> (flags);
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ p += HBGlyphID24::static_size;
+ else
+#endif
+ p += HBGlyphID16::static_size;
+ 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;
+
+ const auto *p = &StructAfter<const HBINT8> (flags);
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ p += HBGlyphID24::static_size;
+ else
+#endif
+ p += HBGlyphID16::static_size;
+ int tx, ty;
+ 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:
+ hb_codepoint_t get_gid () const
+ {
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ return StructAfter<const HBGlyphID24> (flags);
+ else
+#endif
+ return StructAfter<const HBGlyphID16> (flags);
+ }
+ void set_gid (hb_codepoint_t gid)
+ {
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ StructAfter<HBGlyphID24> (flags) = gid;
+ else
+#endif
+ /* TODO assert? */
+ StructAfter<HBGlyphID16> (flags) = gid;
+ }
+
+ protected:
+ HBUINT16 flags;
+ HBUINT24 pad;
+ 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..3efe538f37
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
@@ -0,0 +1,235 @@
+#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 lsb = 0;
+ int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
+ (int) header->xMin - lsb : 0;
+ int tsb = 0;
+ int v_orig = (int) header->yMax +
+#ifndef HB_NO_VERTICAL
+ ((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
+#else
+ 0
+#endif
+ ;
+ unsigned h_adv = glyf_accelerator.hmtx->get_advance_without_var_unscaled (gid);
+ unsigned v_adv =
+#ifndef HB_NO_VERTICAL
+ glyf_accelerator.vmtx->get_advance_without_var_unscaled (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.get_gid ())
+ .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_without_var_scaled (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_without_var_scaled (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..e4a9168b79
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh
@@ -0,0 +1,50 @@
+#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_without_var_scaled (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); */
+ int lsb = hb_min (xMin, xMax);
+ (void) glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb);
+ extents->x_bearing = font->em_scale_x (lsb);
+ 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..7ae8fe3078
--- /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 (_.get_gid(), &new_gid))
+ const_cast<CompositeGlyphRecord &> (_).set_gid (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..bcaf44fc1e
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
@@ -0,0 +1,397 @@
+#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;
+ bool scaled;
+
+ 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, bool scaled)
+ {
+ if (unlikely (empty ()))
+ {
+ extents->width = 0;
+ extents->x_bearing = 0;
+ extents->height = 0;
+ extents->y_bearing = 0;
+ return;
+ }
+ if (scaled)
+ {
+ 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;
+ }
+ else
+ {
+ extents->x_bearing = roundf (min_x);
+ extents->width = roundf (max_x - extents->x_bearing);
+ extents->y_bearing = roundf (max_y);
+ extents->height = roundf (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_, bool scaled_)
+ {
+ font = font_;
+ extents = extents_;
+ phantoms = phantoms_;
+ scaled = scaled_;
+ 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, scaled); }
+
+ bool is_consuming_contour_points () { return extents; }
+ contour_point_t *get_phantoms_sink () { return phantoms; }
+ };
+
+ public:
+ unsigned
+ get_advance_with_var_unscaled (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 (font->num_coords)
+ success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false));
+
+ if (unlikely (!success))
+ return
+#ifndef HB_NO_VERTICAL
+ is_vertical ? vmtx->get_advance_without_var_unscaled (gid) :
+#endif
+ hmtx->get_advance_without_var_unscaled (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);
+ }
+
+ bool get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical, int *lsb) const
+ {
+ if (unlikely (gid >= num_glyphs)) return false;
+
+ 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, false))))
+ return false;
+
+ *lsb = is_vertical
+ ? roundf (phantoms[glyf_impl::PHANTOM_TOP].y) - extents.y_bearing
+ : roundf (phantoms[glyf_impl::PHANTOM_LEFT].x);
+ return true;
+ }
+#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, true));
+#endif
+ return glyph_for_gid (gid).get_extents_without_var_scaled (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/coverage-graph.hh b/thirdparty/harfbuzz/src/graph/coverage-graph.hh
new file mode 100644
index 0000000000..1d9fd0eb5b
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/coverage-graph.hh
@@ -0,0 +1,80 @@
+/*
+ * 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
+ */
+
+#include "graph.hh"
+#include "../OT/Layout/Common/Coverage.hh"
+
+#ifndef GRAPH_COVERAGE_GRAPH_HH
+#define GRAPH_COVERAGE_GRAPH_HH
+
+namespace graph {
+
+struct CoverageFormat1 : public OT::Layout::Common::CoverageFormat1_3<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+ return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size ();
+ }
+};
+
+struct CoverageFormat2 : public OT::Layout::Common::CoverageFormat2_4<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+ return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
+ }
+};
+
+struct Coverage : public OT::Layout::Common::Coverage
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::Layout::Common::Coverage::min_size) return false;
+ switch (u.format)
+ {
+ case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
+ case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
+#ifndef HB_NO_BORING_EXPANSION
+ // Not currently supported
+ case 3:
+ case 4:
+#endif
+ default: return false;
+ }
+ }
+};
+
+
+}
+
+#endif // GRAPH_COVERAGE_GRAPH_HH
diff --git a/thirdparty/harfbuzz/src/graph/graph.hh b/thirdparty/harfbuzz/src/graph/graph.hh
new file mode 100644
index 0000000000..b3aef558a2
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/graph.hh
@@ -0,0 +1,1046 @@
+/*
+ * 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
+ */
+
+#include "../hb-set.hh"
+#include "../hb-priority-queue.hh"
+#include "../hb-serialize.hh"
+
+#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 remove_real_link (unsigned child_index, const void* offset)
+ {
+ for (unsigned i = 0; i < obj.real_links.length; i++)
+ {
+ auto& link = obj.real_links[i];
+ if (link.objidx != child_index)
+ continue;
+
+ if ((obj.head + link.position) != offset)
+ continue;
+
+ obj.real_links.remove (i);
+ return;
+ }
+ }
+
+ 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;
+ }
+
+ size_t table_size () const {
+ return obj.tail - obj.head;
+ }
+
+ 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 if positions are marked as invalid.
+ */
+ void sort_shortest_distance_if_needed ()
+ {
+ if (!positions_invalid) return;
+ sort_shortest_distance ();
+ }
+
+
+ /*
+ * 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 ());
+
+ remap_all_obj_indices (id_map, &sorted_graph);
+ hb_swap (vertices_, sorted_graph);
+
+ if (!check_success (new_id == -1))
+ print_orphaned_nodes ();
+ }
+
+ /*
+ * Finds the set of nodes (placed into roots) that should be assigned unique spaces.
+ * More specifically this looks for the top most 24 bit or 32 bit links in the graph.
+ * Some special casing is done that is specific to the layout of GSUB/GPOS tables.
+ */
+ void find_space_roots (hb_set_t& visited, hb_set_t& roots)
+ {
+ int root_index = (int) root_idx ();
+ for (int i = root_index; i >= 0; i--)
+ {
+ if (visited.has (i)) continue;
+
+ // Only real links can form 32 bit spaces
+ for (auto& l : vertices_[i].obj.real_links)
+ {
+ if (l.is_signed || l.width < 3)
+ continue;
+
+ if (i == root_index && l.width == 3)
+ // Ignore 24bit links from the root node, this skips past the single 24bit
+ // pointer to the lookup list.
+ continue;
+
+ if (l.width == 3)
+ {
+ // A 24bit offset forms a root, unless there is 32bit offsets somewhere
+ // in it's subgraph, then those become the roots instead. This is to make sure
+ // that extension subtables beneath a 24bit lookup become the spaces instead
+ // of the offset to the lookup.
+ hb_set_t sub_roots;
+ find_32bit_roots (l.objidx, sub_roots);
+ if (sub_roots) {
+ for (unsigned sub_root_idx : sub_roots) {
+ roots.add (sub_root_idx);
+ find_subgraph (sub_root_idx, visited);
+ }
+ continue;
+ }
+ }
+
+ roots.add (l.objidx);
+ find_subgraph (l.objidx, visited);
+ }
+ }
+ }
+
+ unsigned index_for_offset(unsigned node_idx, const void* offset) const
+ {
+ const auto& node = object (node_idx);
+ if (offset < node.head || offset >= node.tail) return -1;
+
+ for (const auto& link : node.real_links)
+ {
+ if (offset != node.head + link.position)
+ continue;
+ return link.objidx;
+ }
+
+ return -1;
+ }
+
+
+ /*
+ * Assign unique space numbers to each connected subgraph of 24 bit and/or 32 bit offset(s).
+ * Currently, this is implemented specifically tailored to the structure of a GPOS/GSUB
+ * (including with 24bit offsets) table.
+ */
+ bool assign_spaces ()
+ {
+ update_parents ();
+
+ hb_set_t visited;
+ hb_set_t roots;
+ find_space_roots (visited, roots);
+
+ // Mark everything not in the subgraphs of the roots as visited. This prevents
+ // subgraphs from being connected via nodes not in those 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);
+ }
+
+ size_t find_subgraph_size (unsigned node_idx, hb_set_t& subgraph, unsigned max_depth = -1)
+ {
+ if (subgraph.has (node_idx)) return 0;
+ subgraph.add (node_idx);
+
+ const auto& o = vertices_[node_idx].obj;
+ size_t size = o.tail - o.head;
+ if (max_depth == 0)
+ return size;
+
+ for (const auto& link : o.all_links ())
+ size += find_subgraph_size (link.objidx, subgraph, max_depth - 1);
+ return size;
+ }
+
+ /*
+ * Finds the topmost children of 32bit offsets in the subgraph starting
+ * at node_idx. Found indices are placed into 'found'.
+ */
+ void find_32bit_roots (unsigned node_idx, hb_set_t& found)
+ {
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ {
+ if (!link.is_signed && link.width == 4) {
+ found.add (link.objidx);
+ continue;
+ }
+ find_32bit_roots (link.objidx, found);
+ }
+ }
+
+ /*
+ * Moves the child of old_parent_idx pointed to by old_offset to a new
+ * vertex at the new_offset.
+ */
+ template<typename O>
+ void move_child (unsigned old_parent_idx,
+ const O* old_offset,
+ unsigned new_parent_idx,
+ const O* new_offset)
+ {
+ distance_invalid = true;
+ positions_invalid = true;
+
+ auto& old_v = vertices_[old_parent_idx];
+ auto& new_v = vertices_[new_parent_idx];
+
+ unsigned child_id = index_for_offset (old_parent_idx,
+ old_offset);
+
+ auto* new_link = new_v.obj.real_links.push ();
+ new_link->width = O::static_size;
+ new_link->objidx = child_id;
+ new_link->position = (const char*) new_offset - (const char*) new_v.obj.head;
+
+ auto& child = vertices_[child_id];
+ child.parents.push (new_parent_idx);
+
+ old_v.remove_real_link (child_id, old_offset);
+ child.remove_parent (old_parent_idx);
+ }
+
+ /*
+ * 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;
+ }
+
+
+ /*
+ * Adds a new node to the graph, not connected to anything.
+ */
+ unsigned new_node (char* head, char* tail)
+ {
+ positions_invalid = true;
+ distance_invalid = true;
+
+ auto* clone = vertices_.push ();
+ if (vertices_.in_error ()) {
+ return -1;
+ }
+
+ clone->obj.head = head;
+ clone->obj.tail = tail;
+ clone->distance = 0;
+ clone->space = 0;
+
+ unsigned clone_idx = vertices_.length - 2;
+
+ // 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;
+ }
+
+ /*
+ * 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 24 or 32 bits 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 == 3 || 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/gsubgpos-context.cc b/thirdparty/harfbuzz/src/graph/gsubgpos-context.cc
new file mode 100644
index 0000000000..e0ff6ff85f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/gsubgpos-context.cc
@@ -0,0 +1,71 @@
+/*
+ * 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
+ */
+
+#include "gsubgpos-graph.hh"
+
+namespace graph {
+
+gsubgpos_graph_context_t::gsubgpos_graph_context_t (hb_tag_t table_tag_,
+ graph_t& graph_)
+ : table_tag (table_tag_),
+ graph (graph_),
+ lookup_list_index (0),
+ lookups (),
+ buffers ()
+{
+ if (table_tag_ != HB_OT_TAG_GPOS
+ && table_tag_ != HB_OT_TAG_GSUB)
+ return;
+
+ GSTAR* gstar = graph::GSTAR::graph_to_gstar (graph_);
+ if (gstar) {
+ gstar->find_lookups (graph, lookups);
+ lookup_list_index = gstar->get_lookup_list_index (graph_);
+ }
+}
+
+unsigned gsubgpos_graph_context_t::create_node (unsigned size)
+{
+ char* buffer = (char*) hb_calloc (1, size);
+ if (!buffer)
+ return -1;
+
+ buffers.push (buffer);
+
+ return graph.new_node (buffer, buffer + size);
+}
+
+unsigned gsubgpos_graph_context_t::num_non_ext_subtables () {
+ unsigned count = 0;
+ for (auto l : lookups.values ())
+ {
+ if (l->is_extension (table_tag)) continue;
+ count += l->number_of_subtables ();
+ }
+ return count;
+}
+
+}
diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-context.hh b/thirdparty/harfbuzz/src/graph/gsubgpos-context.hh
new file mode 100644
index 0000000000..49b24198ff
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/gsubgpos-context.hh
@@ -0,0 +1,67 @@
+/*
+ * 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
+ */
+
+#include "graph.hh"
+#include "../hb-ot-layout-gsubgpos.hh"
+
+#ifndef GRAPH_GSUBGPOS_CONTEXT_HH
+#define GRAPH_GSUBGPOS_CONTEXT_HH
+
+namespace graph {
+
+struct Lookup;
+
+struct gsubgpos_graph_context_t
+{
+ hb_tag_t table_tag;
+ graph_t& graph;
+ unsigned lookup_list_index;
+ hb_hashmap_t<unsigned, graph::Lookup*> lookups;
+ hb_vector_t<char*> buffers;
+
+ HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
+ graph_t& graph_);
+
+ ~gsubgpos_graph_context_t ()
+ {
+ for (char* b : buffers)
+ hb_free (b);
+ }
+
+ HB_INTERNAL unsigned create_node (unsigned size);
+
+ void add_buffer (char* buffer)
+ {
+ buffers.push (buffer);
+ }
+
+ private:
+ HB_INTERNAL unsigned num_non_ext_subtables ();
+};
+
+}
+
+#endif // GRAPH_GSUBGPOS_CONTEXT
diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
new file mode 100644
index 0000000000..afa1152c44
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
@@ -0,0 +1,351 @@
+/*
+ * 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
+ */
+
+#include "graph.hh"
+#include "../hb-ot-layout-gsubgpos.hh"
+#include "../OT/Layout/GSUB/ExtensionSubst.hh"
+#include "gsubgpos-context.hh"
+#include "pairpos-graph.hh"
+
+#ifndef GRAPH_GSUBGPOS_GRAPH_HH
+#define GRAPH_GSUBGPOS_GRAPH_HH
+
+namespace graph {
+
+struct Lookup;
+
+template<typename T>
+struct ExtensionFormat1 : public OT::ExtensionFormat1<T>
+{
+ void reset(unsigned type)
+ {
+ this->format = 1;
+ this->extensionLookupType = type;
+ this->extensionOffset = 0;
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ return vertex_len >= OT::ExtensionFormat1<T>::static_size;
+ }
+
+ unsigned get_lookup_type () const
+ {
+ return this->extensionLookupType;
+ }
+
+ unsigned get_subtable_index (graph_t& graph, unsigned this_index) const
+ {
+ return graph.index_for_offset (this_index, &this->extensionOffset);
+ }
+};
+
+struct Lookup : public OT::Lookup
+{
+ unsigned number_of_subtables () const
+ {
+ return subTable.len;
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::Lookup::min_size) return false;
+ return vertex_len >= this->get_size ();
+ }
+
+ bool is_extension (hb_tag_t table_tag) const
+ {
+ return lookupType == extension_type (table_tag);
+ }
+
+ bool make_extension (gsubgpos_graph_context_t& c,
+ unsigned this_index)
+ {
+ unsigned type = lookupType;
+ unsigned ext_type = extension_type (c.table_tag);
+ if (!ext_type || is_extension (c.table_tag))
+ {
+ // NOOP
+ return true;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Promoting lookup type %u (obj %u) to extension.",
+ type,
+ this_index);
+
+ for (unsigned i = 0; i < subTable.len; i++)
+ {
+ unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
+ if (!make_subtable_extension (c,
+ this_index,
+ subtable_index))
+ return false;
+ }
+
+ lookupType = ext_type;
+ return true;
+ }
+
+ bool split_subtables_if_needed (gsubgpos_graph_context_t& c,
+ unsigned this_index)
+ {
+ unsigned type = lookupType;
+ bool is_ext = is_extension (c.table_tag);
+
+ if (c.table_tag != HB_OT_TAG_GPOS)
+ return true;
+
+ if (!is_ext && type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair)
+ return true;
+
+ hb_vector_t<unsigned> all_new_subtables;
+ for (unsigned i = 0; i < subTable.len; i++)
+ {
+ unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
+ if (is_ext) {
+ unsigned ext_subtable_index = subtable_index;
+ ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
+ (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
+ c.graph.object (ext_subtable_index).head;
+ if (!extension->sanitize (c.graph.vertices_[ext_subtable_index]))
+ continue;
+
+ subtable_index = extension->get_subtable_index (c.graph, ext_subtable_index);
+ type = extension->get_lookup_type ();
+ if (type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair)
+ continue;
+ }
+
+ PairPos* pairPos = (PairPos*) c.graph.object (subtable_index).head;
+ if (!pairPos->sanitize (c.graph.vertices_[subtable_index])) continue;
+
+ hb_vector_t<unsigned> new_sub_tables = pairPos->split_subtables (c, subtable_index);
+ if (new_sub_tables.in_error ()) return false;
+ + new_sub_tables.iter() | hb_sink (all_new_subtables);
+ }
+
+ if (all_new_subtables)
+ add_sub_tables (c, this_index, type, all_new_subtables);
+
+ return true;
+ }
+
+ void add_sub_tables (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned type,
+ hb_vector_t<unsigned>& subtable_indices)
+ {
+ bool is_ext = is_extension (c.table_tag);
+ auto& v = c.graph.vertices_[this_index];
+
+ size_t new_size = v.table_size ()
+ + subtable_indices.length * OT::Offset16::static_size;
+ char* buffer = (char*) hb_calloc (1, new_size);
+ c.add_buffer (buffer);
+ memcpy (buffer, v.obj.head, v.table_size());
+
+ v.obj.head = buffer;
+ v.obj.tail = buffer + new_size;
+
+ Lookup* new_lookup = (Lookup*) buffer;
+
+ new_lookup->subTable.len = subTable.len + subtable_indices.length;
+ unsigned offset_index = subTable.len;
+ for (unsigned subtable_id : subtable_indices)
+ {
+ if (is_ext)
+ {
+ unsigned ext_id = create_extension_subtable (c, subtable_id, type);
+ c.graph.vertices_[subtable_id].parents.push (ext_id);
+ subtable_id = ext_id;
+ }
+
+ auto* link = v.obj.real_links.push ();
+ link->width = 2;
+ link->objidx = subtable_id;
+ link->position = (char*) &new_lookup->subTable[offset_index++] -
+ (char*) new_lookup;
+ c.graph.vertices_[subtable_id].parents.push (this_index);
+ }
+
+ // The head location of the lookup has changed, invalidating the lookups map entry
+ // in the context. Update the map.
+ c.lookups.set (this_index, new_lookup);
+ }
+
+ unsigned create_extension_subtable (gsubgpos_graph_context_t& c,
+ unsigned subtable_index,
+ unsigned type)
+ {
+ unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
+
+ unsigned ext_index = c.create_node (extension_size);
+ if (ext_index == (unsigned) -1)
+ return -1;
+
+ auto& ext_vertex = c.graph.vertices_[ext_index];
+ ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
+ (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) ext_vertex.obj.head;
+ extension->reset (type);
+
+ // Make extension point at the subtable.
+ auto* l = ext_vertex.obj.real_links.push ();
+
+ l->width = 4;
+ l->objidx = subtable_index;
+ l->position = 4;
+
+ return ext_index;
+ }
+
+ bool make_subtable_extension (gsubgpos_graph_context_t& c,
+ unsigned lookup_index,
+ unsigned subtable_index)
+ {
+ unsigned type = lookupType;
+
+ unsigned ext_index = create_extension_subtable(c, subtable_index, type);
+ if (ext_index == (unsigned) -1)
+ return false;
+
+ auto& lookup_vertex = c.graph.vertices_[lookup_index];
+ for (auto& l : lookup_vertex.obj.real_links.writer ())
+ {
+ if (l.objidx == subtable_index)
+ // Change lookup to point at the extension.
+ l.objidx = ext_index;
+ }
+
+ // Make extension point at the subtable.
+ auto& ext_vertex = c.graph.vertices_[ext_index];
+ auto& subtable_vertex = c.graph.vertices_[subtable_index];
+ ext_vertex.parents.push (lookup_index);
+ subtable_vertex.remap_parent (lookup_index, ext_index);
+
+ return true;
+ }
+
+ private:
+ unsigned extension_type (hb_tag_t table_tag) const
+ {
+ switch (table_tag)
+ {
+ case HB_OT_TAG_GPOS: return 9;
+ case HB_OT_TAG_GSUB: return 7;
+ default: return 0;
+ }
+ }
+};
+
+template <typename T>
+struct LookupList : public OT::LookupList<T>
+{
+ bool sanitize (const graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::LookupList<T>::min_size) return false;
+ return vertex_len >= OT::LookupList<T>::item_size * this->len;
+ }
+};
+
+struct GSTAR : public OT::GSUBGPOS
+{
+ static GSTAR* graph_to_gstar (graph_t& graph)
+ {
+ const auto& r = graph.root ();
+
+ GSTAR* gstar = (GSTAR*) r.obj.head;
+ if (!gstar->sanitize (r))
+ return nullptr;
+
+ return gstar;
+ }
+
+ const void* get_lookup_list_field_offset () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.get_lookup_list_offset ();
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return u.version2.get_lookup_list_offset ();
+#endif
+ default: return 0;
+ }
+ }
+
+ bool sanitize (const graph_t::vertex_t& vertex)
+ {
+ int64_t len = vertex.obj.tail - vertex.obj.head;
+ if (len < OT::GSUBGPOS::min_size) return false;
+ return len >= get_size ();
+ }
+
+ void find_lookups (graph_t& graph,
+ hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */)
+ {
+ switch (u.version.major) {
+ case 1: find_lookups<SmallTypes> (graph, lookups); break;
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: find_lookups<MediumTypes> (graph, lookups); break;
+#endif
+ }
+ }
+
+ unsigned get_lookup_list_index (graph_t& graph)
+ {
+ return graph.index_for_offset (graph.root_idx (),
+ get_lookup_list_field_offset());
+ }
+
+ template<typename Types>
+ void find_lookups (graph_t& graph,
+ hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */)
+ {
+ unsigned lookup_list_idx = get_lookup_list_index (graph);
+
+ const LookupList<Types>* lookupList =
+ (const LookupList<Types>*) graph.object (lookup_list_idx).head;
+ if (!lookupList->sanitize (graph.vertices_[lookup_list_idx]))
+ return;
+
+ for (unsigned i = 0; i < lookupList->len; i++)
+ {
+ unsigned lookup_idx = graph.index_for_offset (lookup_list_idx, &(lookupList->arrayZ[i]));
+ Lookup* lookup = (Lookup*) graph.object (lookup_idx).head;
+ if (!lookup->sanitize (graph.vertices_[lookup_idx])) continue;
+ lookups.set (lookup_idx, lookup);
+ }
+ }
+};
+
+
+
+
+}
+
+#endif /* GRAPH_GSUBGPOS_GRAPH_HH */
diff --git a/thirdparty/harfbuzz/src/graph/pairpos-graph.hh b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh
new file mode 100644
index 0000000000..3ca4fc701c
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh
@@ -0,0 +1,299 @@
+/*
+ * 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_PAIRPOS_GRAPH_HH
+#define GRAPH_PAIRPOS_GRAPH_HH
+
+#include "coverage-graph.hh"
+#include "../OT/Layout/GPOS/PairPos.hh"
+#include "../OT/Layout/GPOS/PosLookupSubTable.hh"
+
+namespace graph {
+
+struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ unsigned min_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+
+ return vertex_len >=
+ min_size + pairSet.get_size () - pairSet.len.get_size();
+ }
+
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+ {
+ hb_set_t visited;
+
+ const unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
+ const unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
+ const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size
+ + coverage_size;
+
+ unsigned accumulated = base_size;
+ hb_vector_t<unsigned> split_points;
+ for (unsigned i = 0; i < pairSet.len; i++)
+ {
+ unsigned pair_set_index = pair_set_graph_index (c, this_index, i);
+ accumulated += c.graph.find_subgraph_size (pair_set_index, visited);
+ accumulated += SmallTypes::size; // for PairSet offset.
+
+ // TODO(garretrieger): don't count the size of the largest pairset against the limit, since
+ // it will be packed last in the order and does not contribute to
+ // the 64kb limit.
+
+ if (accumulated > (1 << 16))
+ {
+ split_points.push (i);
+ accumulated = base_size;
+ visited.clear (); // Pretend node sharing isn't allowed between splits.
+ }
+ }
+
+ return do_split (c, this_index, split_points);
+ }
+
+ private:
+
+ // Split this PairPos into two or more PairPos's. split_points defines
+ // the indices (first index to include in the new table) to split at.
+ // Returns the object id's of the newly created PairPos subtables.
+ hb_vector_t<unsigned> do_split (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ const hb_vector_t<unsigned> split_points)
+ {
+ hb_vector_t<unsigned> new_objects;
+ if (!split_points)
+ return new_objects;
+
+ for (unsigned i = 0; i < split_points.length; i++)
+ {
+ unsigned start = split_points[i];
+ unsigned end = (i < split_points.length - 1) ? split_points[i + 1] : pairSet.len;
+ unsigned id = clone_range (c, this_index, start, end);
+
+ if (id == (unsigned) -1)
+ {
+ new_objects.reset ();
+ new_objects.allocated = -1; // mark error
+ return new_objects;
+ }
+ new_objects.push (id);
+ }
+
+ if (!shrink (c, this_index, split_points[0]))
+ {
+ new_objects.reset ();
+ new_objects.allocated = -1; // mark error
+ }
+
+ return new_objects;
+ }
+
+ bool shrink (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned count)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Shrinking PairPosFormat1 (%u) to [0, %u).",
+ this_index,
+ count);
+ unsigned old_count = pairSet.len;
+ if (count >= old_count)
+ return true;
+
+ pairSet.len = count;
+ c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
+
+ unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
+ unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
+ auto& coverage_v = c.graph.vertices_[coverage_id];
+ Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
+ if (!coverage_table->sanitize (coverage_v))
+ return false;
+
+ auto new_coverage =
+ + hb_zip (coverage_table->iter (), hb_range ())
+ | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
+ return p.second < count;
+ })
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ return make_coverage (c, new_coverage, coverage_id, coverage_size);
+ }
+
+ // Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
+ // Returns object id of the new object.
+ unsigned clone_range (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned start, unsigned end) const
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Cloning PairPosFormat1 (%u) range [%u, %u).", this_index, start, end);
+
+ unsigned num_pair_sets = end - start;
+ unsigned prime_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size
+ + num_pair_sets * SmallTypes::size;
+
+ unsigned pair_pos_prime_id = c.create_node (prime_size);
+ if (pair_pos_prime_id == (unsigned) -1) return -1;
+
+ PairPosFormat1* pair_pos_prime = (PairPosFormat1*) c.graph.object (pair_pos_prime_id).head;
+ pair_pos_prime->format = this->format;
+ pair_pos_prime->valueFormat[0] = this->valueFormat[0];
+ pair_pos_prime->valueFormat[1] = this->valueFormat[1];
+ pair_pos_prime->pairSet.len = num_pair_sets;
+
+ for (unsigned i = start; i < end; i++)
+ {
+ c.graph.move_child<> (this_index,
+ &pairSet[i],
+ pair_pos_prime_id,
+ &pair_pos_prime->pairSet[i - start]);
+ }
+
+ unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
+ unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
+ auto& coverage_v = c.graph.vertices_[coverage_id];
+ Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
+ if (!coverage_table->sanitize (coverage_v))
+ return false;
+
+ auto new_coverage =
+ + hb_zip (coverage_table->iter (), hb_range ())
+ | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
+ return p.second >= start && p.second < end;
+ })
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ unsigned coverage_prime_id = c.graph.new_node (nullptr, nullptr);
+ auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id];
+ if (!make_coverage (c, new_coverage, coverage_prime_id, coverage_size))
+ return -1;
+
+ auto* coverage_link = c.graph.vertices_[pair_pos_prime_id].obj.real_links.push ();
+ coverage_link->width = SmallTypes::size;
+ coverage_link->objidx = coverage_prime_id;
+ coverage_link->position = 2;
+ coverage_prime_vertex.parents.push (pair_pos_prime_id);
+
+ return pair_pos_prime_id;
+ }
+
+ template<typename It>
+ bool make_coverage (gsubgpos_graph_context_t& c,
+ It glyphs,
+ unsigned dest_obj,
+ unsigned max_size) const
+ {
+ char* buffer = (char*) hb_calloc (1, max_size);
+ hb_serialize_context_t serializer (buffer, max_size);
+ Coverage_serialize (&serializer, glyphs);
+ serializer.end_serialize ();
+ if (serializer.in_error ())
+ {
+ hb_free (buffer);
+ return false;
+ }
+
+ hb_bytes_t coverage_copy = serializer.copy_bytes ();
+ c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
+
+ auto& obj = c.graph.vertices_[dest_obj].obj;
+ obj.head = (char *) coverage_copy.arrayZ;
+ obj.tail = obj.head + coverage_copy.length;
+
+ hb_free (buffer);
+ return true;
+ }
+
+ unsigned pair_set_graph_index (gsubgpos_graph_context_t& c, unsigned this_index, unsigned i) const
+ {
+ return c.graph.index_for_offset (this_index, &pairSet[i]);
+ }
+};
+
+struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ // TODO(garretrieger): implement me!
+ return true;
+ }
+
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+ {
+ // TODO(garretrieger): implement me!
+ return hb_vector_t<unsigned> ();
+ }
+};
+
+struct PairPos : public OT::Layout::GPOS_impl::PairPos
+{
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+ {
+ switch (u.format) {
+ case 1:
+ return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index);
+ case 2:
+ return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: HB_FALLTHROUGH;
+ case 4: HB_FALLTHROUGH;
+ // Don't split 24bit PairPos's.
+#endif
+ default:
+ return hb_vector_t<unsigned> ();
+ }
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < u.format.get_size ()) return false;
+
+ switch (u.format) {
+ case 1:
+ return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
+ case 2:
+ return ((PairPosFormat2*)(&u.format2))->sanitize (vertex);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: HB_FALLTHROUGH;
+ case 4: HB_FALLTHROUGH;
+#endif
+ default:
+ // We don't handle format 3 and 4 here.
+ return false;
+ }
+ }
+};
+
+}
+
+#endif // GRAPH_PAIRPOS_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-bsln-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh
index b52844e75d..bf12d2e699 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh
@@ -42,7 +42,7 @@ struct BaselineTableFormat0Part
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -78,7 +78,7 @@ struct BaselineTableFormat2Part
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
index 1db0f1df92..6cbed82692 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
@@ -415,18 +415,7 @@ struct Lookup
public:
DEFINE_SIZE_UNION (2, format);
};
-/* Lookup 0 has unbounded size (dependant on num_glyphs). So we need to defined
- * special NULL objects for Lookup<> objects, but since it's template our macros
- * don't work. So we have to hand-code them here. UGLY. */
-} /* Close namespace. */
-/* Ugly hand-coded null objects for template Lookup<> :(. */
-extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
-template <typename T>
-struct Null<AAT::Lookup<T>> {
- static AAT::Lookup<T> const & get_null ()
- { return *reinterpret_cast<const AAT::Lookup<T> *> (_hb_Null_AAT_Lookup); }
-};
-namespace AAT {
+DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
enum { DELETED_GLYPH = 0xFFFF };
@@ -681,6 +670,13 @@ struct ObsoleteTypes
const void *base,
const T *array)
{
+ /* https://github.com/harfbuzz/harfbuzz/issues/3483 */
+ /* If offset is less than base, return an offset that would
+ * result in an address half a 32bit address-space away,
+ * to make sure sanitize fails even on 32bit builds. */
+ if (unlikely (offset < unsigned ((const char *) array - (const char *) base)))
+ return INT_MAX / T::static_size;
+
/* https://github.com/harfbuzz/harfbuzz/issues/2816 */
return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size;
}
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh
index 573f0cf9f6..815a1fd2aa 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh
@@ -62,7 +62,7 @@ struct SettingName
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh
index 0bf9bd2912..57c105967d 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh
@@ -48,7 +48,7 @@ struct ActionSubrecordHeader
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
HBUINT16 actionClass; /* The JustClass value associated with this
@@ -65,7 +65,7 @@ struct DecompositionAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
ActionSubrecordHeader
@@ -112,7 +112,7 @@ struct ConditionalAddGlyphAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -137,7 +137,7 @@ struct DuctileGlyphAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -163,7 +163,7 @@ struct RepeatedAddGlyphAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -294,7 +294,7 @@ struct WidthDeltaPair
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
index 0354b47d5a..995492cd5a 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;
}
@@ -751,7 +751,7 @@ struct KerxSubTableHeader
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
public:
@@ -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..aa4ad4cf3c 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);
@@ -980,6 +980,15 @@ struct Chain
setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS;
goto retry;
}
+#ifndef HB_NO_AAT
+ else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE && setting &&
+ /* TODO: Rudimentary language matching. */
+ hb_language_matches (map->face->table.ltag->get_language (setting - 1), map->props.language))
+ {
+ flags &= feature.disableFlags;
+ flags |= feature.enableFlags;
+ }
+#endif
}
}
return flags;
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh
index b1a1512821..51b650fc33 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh
@@ -42,7 +42,7 @@ struct OpticalBounds
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
FWORD leftSide;
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc
index caff204d67..e06d286ff0 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc
@@ -229,7 +229,7 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
*
* <note>Note: does not examine the `GSUB` table.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.3.0
*/
@@ -300,7 +300,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
*
* <note>Note: does not examine the `GPOS` table.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.3.0
*/
@@ -333,7 +333,7 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
* Tests whether the specified face includes any tracking information
* in the `trak` table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.3.0
*/
diff --git a/thirdparty/harfbuzz/src/hb-aat-map.hh b/thirdparty/harfbuzz/src/hb-aat-map.hh
index 5a0fa70544..c914f58d70 100644
--- a/thirdparty/harfbuzz/src/hb-aat-map.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-map.hh
@@ -52,8 +52,9 @@ struct hb_aat_map_builder_t
public:
HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_,
- const hb_segment_properties_t *props_ HB_UNUSED) :
- face (face_) {}
+ const hb_segment_properties_t props_) :
+ face (face_),
+ props (props_) {}
HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1);
@@ -87,6 +88,7 @@ struct hb_aat_map_builder_t
public:
hb_face_t *face;
+ hb_segment_properties_t props;
public:
hb_sorted_vector_t<feature_info_t> features;
diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh
index 05b4df52f1..cc37c073da 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; } \
@@ -109,15 +109,16 @@ struct BEInt<Type, 2>
struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
constexpr operator Type () const
{
-#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
defined(__BYTE_ORDER) && \
(__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
/* Spoon-feed the compiler a big-endian integer with alignment 1.
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- return __builtin_bswap16 (((packed_uint16_t *) this)->v);
+ return __builtin_bswap16 (((packed_uint16_t *) v)->v);
#else /* __BYTE_ORDER == __BIG_ENDIAN */
- return ((packed_uint16_t *) this)->v;
+ return ((packed_uint16_t *) v)->v;
#endif
#else
return (v[0] << 8)
@@ -153,15 +154,16 @@ struct BEInt<Type, 4>
struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
constexpr operator Type () const {
-#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
defined(__BYTE_ORDER) && \
(__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
/* Spoon-feed the compiler a big-endian integer with alignment 1.
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- return __builtin_bswap32 (((packed_uint32_t *) this)->v);
+ return __builtin_bswap32 (((packed_uint32_t *) v)->v);
#else /* __BYTE_ORDER == __BIG_ENDIAN */
- return ((packed_uint32_t *) this)->v;
+ return ((packed_uint32_t *) v)->v;
#endif
#else
return (v[0] << 24)
@@ -227,31 +229,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:
@@ -530,7 +527,6 @@ struct hb_pair_t
T1 first;
T2 second;
};
-#define hb_pair_t(T1,T2) hb_pair_t<T1, T2>
template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
@@ -556,14 +552,14 @@ struct
{
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a <= b ? std::forward<T> (a) : std::forward<T2> (b))
+ (a <= b ? a : b)
}
HB_FUNCOBJ (hb_min);
struct
{
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a >= b ? std::forward<T> (a) : std::forward<T2> (b))
+ (a >= b ? a : b)
}
HB_FUNCOBJ (hb_max);
struct
@@ -862,6 +858,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);
+}
/*
@@ -972,7 +973,7 @@ void hb_qsort(void *base, size_t nel, size_t width,
[void *arg]);
*/
-#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
+#define SORT_R_SWAP(a,b,tmp) ((void) ((tmp) = (a)), (void) ((a) = (b)), (b) = (tmp))
/* swap a and b */
/* a and b must not be equal! */
diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh
index 1963698cf7..826a901819 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_) {}
@@ -101,10 +100,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
/* Ouch. The operator== compares the contents of the array. For range-based for loops,
* it's best if we can just compare arrayZ, though comparing contents is still fast,
* but also would require that Type has operator==. As such, we optimize this operator
- * for range-based for loop and just compare arrayZ. No need to compare length, as we
- * assume we're only compared to .end(). */
+ * for range-based for loop and just compare arrayZ and length. */
bool operator != (const hb_array_t& o) const
- { return arrayZ != o.arrayZ; }
+ { return this->arrayZ != o.arrayZ || this->length != o.length; }
/* Extra operators.
*/
@@ -221,11 +219,8 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
if (end < start + 2)
return;
- for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--) {
- Type temp = arrayZ[rhs];
- arrayZ[rhs] = arrayZ[lhs];
- arrayZ[lhs] = temp;
- }
+ for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--)
+ hb_swap (arrayZ[rhs], arrayZ[lhs]);
}
hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
@@ -314,7 +309,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_) {}
@@ -330,6 +324,8 @@ struct hb_sorted_array_t :
{ hb_array_t<Type> (*this) = o; return *this; }
/* Iterator implementation. */
+
+ /* See comment in hb_array_of::operator != */
bool operator != (const hb_sorted_array_t& o) const
{ return this->arrayZ != o.arrayZ || this->length != o.length; }
diff --git a/thirdparty/harfbuzz/src/hb-atomic.hh b/thirdparty/harfbuzz/src/hb-atomic.hh
index e640d1b586..d6dfb0f57a 100644
--- a/thirdparty/harfbuzz/src/hb-atomic.hh
+++ b/thirdparty/harfbuzz/src/hb-atomic.hh
@@ -111,6 +111,19 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#endif
+#ifndef _hb_compiler_memory_r_barrier
+/* This we always use std::atomic for; and should never be disabled...
+ * except that MSVC gives me an internal compiler error on it. */
+#if !defined(_MSC_VER)
+#include <atomic>
+#define _hb_compiler_memory_r_barrier() std::atomic_signal_fence (std::memory_order_acquire)
+#else
+#define _hb_compiler_memory_r_barrier() do {} while (0)
+#endif
+#endif
+
+
+
#ifndef _hb_memory_r_barrier
#define _hb_memory_r_barrier() _hb_memory_barrier ()
#endif
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-page.hh b/thirdparty/harfbuzz/src/hb-bit-page.hh
index cbe918ee40..95ae1b7bf9 100644
--- a/thirdparty/harfbuzz/src/hb-bit-page.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-page.hh
@@ -55,7 +55,7 @@ struct hb_bit_page_t
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
- void set (hb_codepoint_t g, bool v) { if (v) add (g); else del (g); }
+ void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
void add_range (hb_codepoint_t a, hb_codepoint_t b)
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..4765af67ce 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;
@@ -465,12 +465,10 @@ struct hb_bit_set_t
}
public:
- template <typename Op>
- void process (const Op& op, const hb_bit_set_t &other)
+ void process_ (hb_bit_page_t::vector_t (*op) (const hb_bit_page_t::vector_t &, const hb_bit_page_t::vector_t &),
+ bool passthru_left, bool passthru_right,
+ const hb_bit_set_t &other)
{
- const bool passthru_left = op (1, 0);
- const bool passthru_right = op (0, 1);
-
if (unlikely (!successful)) return;
dirty ();
@@ -590,6 +588,15 @@ struct hb_bit_set_t
assert (!count);
resize (newCount);
}
+ template <typename Op>
+ static hb_bit_page_t::vector_t
+ op_ (const hb_bit_page_t::vector_t &a, const hb_bit_page_t::vector_t &b)
+ { return Op{} (a, b); }
+ template <typename Op>
+ void process (const Op& op, const hb_bit_set_t &other)
+ {
+ process_ (op_<Op>, op (1, 0), op (0, 1), other);
+ }
void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); }
void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); }
@@ -607,7 +614,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 +632,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 +645,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 +732,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 +773,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 +900,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 +924,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 +934,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..9bc12ea3fa 100644
--- a/thirdparty/harfbuzz/src/hb-blob.cc
+++ b/thirdparty/harfbuzz/src/hb-blob.cc
@@ -99,7 +99,7 @@ hb_blob_create (const char *data,
* is zero. This is in contrast to hb_blob_create(), which returns the singleton
* empty blob (as returned by hb_blob_get_empty()) if @length is zero.
*
- * Return value: New blob, or %NULL if failed. Destroy with hb_blob_destroy().
+ * Return value: New blob, or `NULL` if failed. Destroy with hb_blob_destroy().
*
* Since: 2.8.2
**/
@@ -263,8 +263,6 @@ hb_blob_destroy (hb_blob_t *blob)
{
if (!hb_object_destroy (blob)) return;
- blob->fini_shallow ();
-
hb_free (blob);
}
@@ -278,7 +276,7 @@ hb_blob_destroy (hb_blob_t *blob)
*
* Attaches a user-data key/data pair to the specified blob.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -305,7 +303,7 @@ hb_blob_set_user_data (hb_blob_t *blob,
* Since: 0.9.2
**/
void *
-hb_blob_get_user_data (hb_blob_t *blob,
+hb_blob_get_user_data (const hb_blob_t *blob,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (blob, key);
@@ -335,7 +333,7 @@ hb_blob_make_immutable (hb_blob_t *blob)
*
* Tests whether a blob is immutable.
*
- * Return value: %true if @blob is immutable, %false otherwise
+ * Return value: `true` if @blob is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -369,7 +367,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
**/
@@ -394,7 +392,7 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
* fails.
*
* Returns: (transfer none) (array length=length): Writable blob data,
- * or %NULL if failed.
+ * or `NULL` if failed.
*
* Since: 0.9.2
**/
@@ -572,7 +570,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);
@@ -620,7 +618,7 @@ hb_blob_create_from_file (const char *file_name)
* specified binary font file.
*
* Returns: An #hb_blob_t pointer with the content of the file,
- * or %NULL if failed.
+ * or `NULL` if failed.
*
* Since: 2.8.2
**/
diff --git a/thirdparty/harfbuzz/src/hb-blob.h b/thirdparty/harfbuzz/src/hb-blob.h
index 203f9e19dd..4eb42314da 100644
--- a/thirdparty/harfbuzz/src/hb-blob.h
+++ b/thirdparty/harfbuzz/src/hb-blob.h
@@ -135,7 +135,7 @@ hb_blob_set_user_data (hb_blob_t *blob,
HB_EXTERN void *
-hb_blob_get_user_data (hb_blob_t *blob,
+hb_blob_get_user_data (const hb_blob_t *blob,
hb_user_data_key_t *key);
diff --git a/thirdparty/harfbuzz/src/hb-blob.hh b/thirdparty/harfbuzz/src/hb-blob.hh
index a3683a681e..b1b3b94d3d 100644
--- a/thirdparty/harfbuzz/src/hb-blob.hh
+++ b/thirdparty/harfbuzz/src/hb-blob.hh
@@ -38,7 +38,7 @@
struct hb_blob_t
{
- void fini_shallow () { destroy_user_data (); }
+ ~hb_blob_t () { destroy_user_data (); }
void destroy_user_data ()
{
@@ -61,12 +61,12 @@ struct hb_blob_t
public:
hb_object_header_t header;
- const char *data;
- unsigned int length;
- hb_memory_mode_t mode;
+ const char *data = nullptr;
+ unsigned int length = 0;
+ hb_memory_mode_t mode = (hb_memory_mode_t) 0;
- void *user_data;
- hb_destroy_func_t destroy;
+ void *user_data = nullptr;
+ hb_destroy_func_t destroy = nullptr;
};
diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
index e80cfea6e7..44c802a00c 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
@@ -32,15 +32,16 @@
#include "hb.hh"
-#line 36 "hb-buffer-deserialize-json.hh"
+#line 33 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = {
0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u,
120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u,
- 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
- 34u, 92u, 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
- 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0
+ 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u,
+ 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u, 9u, 125u,
+ 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 93u,
+ 9u, 123u, 0u, 0u, 0
};
static const char _deserialize_json_key_spans[] = {
@@ -48,9 +49,10 @@ static const char _deserialize_json_key_spans[] = {
10, 117, 117, 117, 1, 50, 49, 10,
117, 117, 1, 1, 50, 49, 117, 117,
2, 1, 50, 49, 10, 117, 117, 1,
- 50, 49, 10, 117, 117, 1, 50, 49,
- 59, 117, 59, 117, 117, 1, 50, 49,
- 117, 85, 115, 0
+ 50, 49, 10, 117, 117, 1, 1, 50,
+ 49, 117, 117, 1, 50, 49, 59, 117,
+ 59, 117, 117, 1, 50, 49, 117, 85,
+ 115, 0
};
static const short _deserialize_json_index_offsets[] = {
@@ -58,9 +60,10 @@ static const short _deserialize_json_index_offsets[] = {
271, 282, 400, 518, 636, 638, 689, 739,
750, 868, 986, 988, 990, 1041, 1091, 1209,
1327, 1330, 1332, 1383, 1433, 1444, 1562, 1680,
- 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2083,
- 2133, 2193, 2311, 2371, 2489, 2607, 2609, 2660,
- 2710, 2828, 2914, 3030
+ 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2034,
+ 2085, 2135, 2253, 2371, 2373, 2424, 2474, 2534,
+ 2652, 2712, 2830, 2948, 2950, 3001, 3051, 3169,
+ 3255, 3371
};
static const char _deserialize_json_indicies[] = {
@@ -82,28 +85,28 @@ static const char _deserialize_json_indicies[] = {
3, 3, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 3, 1, 4, 1,
- 5, 1, 6, 7, 1, 1, 8, 1,
+ 5, 1, 6, 7, 1, 8, 9, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 9, 1, 10, 11,
- 1, 12, 1, 12, 12, 12, 12, 12,
+ 1, 1, 1, 1, 10, 1, 11, 12,
+ 1, 13, 1, 13, 13, 13, 13, 13,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 12, 1, 1, 1, 1, 1,
+ 1, 1, 13, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 13, 1, 13, 13,
- 13, 13, 13, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 14, 1, 14, 14,
+ 14, 14, 14, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 13, 1, 1,
+ 1, 1, 1, 1, 1, 14, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 14, 1, 1, 15, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 1,
- 17, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 1, 19, 19, 19, 19, 19,
+ 1, 1, 15, 1, 1, 16, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 1,
+ 18, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 1, 20, 20, 20, 20, 20,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 19, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 20, 1,
+ 1, 1, 20, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 21, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -113,11 +116,11 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 21,
- 1, 22, 22, 22, 22, 22, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 22,
+ 1, 23, 23, 23, 23, 23, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 22, 1, 1, 1, 1, 1, 1, 1,
+ 23, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 3, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -128,41 +131,58 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 23, 1, 19,
- 19, 19, 19, 19, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 24, 1, 20,
+ 20, 20, 20, 20, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 20, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 21, 1, 1, 1, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 22, 1, 25, 1, 25,
+ 25, 25, 25, 25, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 25, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 19, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 20, 1, 1, 1, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18,
+ 26, 1, 26, 26, 26, 26, 26, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 26, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 27, 1,
+ 1, 28, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 1, 30, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 1, 32,
+ 32, 32, 32, 32, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 32, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 33, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 21, 1, 24, 1, 24,
- 24, 24, 24, 24, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 24, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 25, 1, 25, 25, 25, 25, 25, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 34, 1, 32, 32, 32,
+ 32, 32, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 25, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 26, 1,
- 1, 27, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 1, 29, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 1, 31,
- 31, 31, 31, 31, 1, 1, 1, 1,
+ 1, 1, 1, 1, 32, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 31, 1,
+ 33, 1, 1, 1, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 32, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -170,41 +190,41 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 34, 1, 35, 1, 36, 1, 36,
+ 36, 36, 36, 36, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 36, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 33, 1, 31, 31, 31,
- 31, 31, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 31, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 32, 1, 1, 1, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 1, 1,
+ 37, 1, 37, 37, 37, 37, 37, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 37, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 38, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 1, 40, 40, 40, 40,
+ 40, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 40, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 41,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 33, 1, 34, 1, 35, 1, 35,
- 35, 35, 35, 35, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 35, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 36, 1, 36, 36, 36, 36, 36, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 36, 1, 1, 1, 1, 1, 1,
+ 42, 1, 40, 40, 40, 40, 40, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 37, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 1, 39, 39, 39, 39,
- 39, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 39, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 40,
+ 1, 40, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 41, 1, 1,
+ 1, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -212,137 +232,130 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 42, 1,
+ 44, 45, 1, 46, 1, 46, 46, 46,
+ 46, 46, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 46, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 41, 1, 39, 39, 39, 39, 39, 1,
+ 1, 1, 1, 1, 1, 1, 47, 1,
+ 47, 47, 47, 47, 47, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 47,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 39, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 40, 1, 1,
- 1, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 48, 1, 1, 49,
+ 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 1, 51, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 1, 53, 53, 53,
+ 53, 53, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 53, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 54, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 41, 1,
- 43, 44, 1, 45, 1, 45, 45, 45,
- 45, 45, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 45, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 46, 1,
- 46, 46, 46, 46, 46, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 46,
+ 1, 55, 1, 53, 53, 53, 53, 53,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 47, 1, 1, 48,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 1, 50, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 1, 52, 52, 52,
- 52, 52, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 52, 1, 1, 1,
+ 1, 1, 53, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 54, 1,
+ 1, 1, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 53, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 55,
+ 1, 56, 1, 56, 56, 56, 56, 56,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 56, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 54, 1, 52, 52, 52, 52, 52,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 57, 1, 57, 57,
+ 57, 57, 57, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 52, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 53, 1,
- 1, 1, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 57, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 58, 1, 1, 59, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 1,
+ 61, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 1, 63, 63, 63, 63, 63,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 63, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 64, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 54,
- 1, 55, 1, 55, 55, 55, 55, 55,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 55, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 56, 1, 56, 56,
- 56, 56, 56, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 56, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 65,
+ 1, 63, 63, 63, 63, 63, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 57, 1, 1, 58, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 1,
- 60, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 1, 62, 62, 62, 62, 62,
1, 1, 1, 1, 1, 1, 1, 1,
+ 63, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 64, 1, 1, 1,
+ 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 62, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 63, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 65, 1, 66,
+ 1, 67, 1, 67, 67, 67, 67, 67,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 67, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 64,
- 1, 62, 62, 62, 62, 62, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 68, 1, 68, 68,
+ 68, 68, 68, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 62, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 63, 1, 1, 1,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 68, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 69, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 1,
+ 71, 71, 71, 71, 71, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 71,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 72, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 64, 1, 65,
- 1, 65, 65, 65, 65, 65, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 65, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 66, 1, 66, 66, 66, 66,
- 66, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 66, 1, 67, 1, 1,
+ 1, 1, 1, 1, 73, 1, 71, 71,
+ 71, 71, 71, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 68, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 1, 71, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 72, 70, 73, 73, 73, 73, 73, 1,
+ 1, 1, 1, 1, 1, 71, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 72, 1, 1, 1, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 73, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 74, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -350,21 +363,33 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 73, 1, 75, 1, 75, 75,
+ 75, 75, 75, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 75, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 75, 1,
- 70, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 76,
+ 1, 76, 76, 76, 76, 76, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 76, 1, 77, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 78, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 1, 81, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 82, 80, 83,
+ 83, 83, 83, 83, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 83, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 70, 1, 76, 76, 76, 76,
- 76, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 84, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 76, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 77,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -373,67 +398,85 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 85, 1, 80, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 78, 1, 76, 76, 76, 76, 76, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 76, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 77, 1, 1,
- 1, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 80,
+ 1, 86, 86, 86, 86, 86, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 86, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 87, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 78, 1,
- 80, 1, 80, 80, 80, 80, 80, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 80, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 88, 1, 86,
+ 86, 86, 86, 86, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 81, 1, 81, 81, 81,
- 81, 81, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 86, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 81, 1, 1, 1,
+ 1, 1, 87, 1, 1, 1, 89, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 82, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 1, 76,
- 76, 76, 76, 76, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 76, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 77, 1, 1, 1, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 88, 1, 90, 1, 90,
+ 90, 90, 90, 90, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 90, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 78, 1, 85, 85, 85,
- 85, 85, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 85, 1, 1, 1,
+ 91, 1, 91, 91, 91, 91, 91, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 91, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 92, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 1, 86, 86, 86, 86,
86, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 86, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 87,
+ 1, 1, 1, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 88, 1, 95, 95, 95, 95, 95, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 95, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 96, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 87, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 97, 1,
+ 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -442,46 +485,52 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 2, 1, 1,
- 0
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 1, 1, 0
};
static const char _deserialize_json_trans_targs[] = {
1, 0, 2, 2, 3, 4, 18, 24,
- 37, 45, 5, 12, 6, 7, 8, 9,
- 11, 9, 11, 10, 2, 49, 10, 49,
- 13, 14, 15, 16, 17, 16, 17, 10,
- 2, 49, 19, 20, 21, 22, 23, 10,
- 2, 49, 23, 25, 31, 26, 27, 28,
- 29, 30, 29, 30, 10, 2, 49, 32,
- 33, 34, 35, 36, 35, 36, 10, 2,
- 49, 38, 39, 40, 43, 44, 40, 41,
- 42, 10, 2, 49, 10, 2, 49, 44,
- 46, 47, 43, 48, 48, 49, 50, 51
+ 37, 43, 51, 5, 12, 6, 7, 8,
+ 9, 11, 9, 11, 10, 2, 55, 10,
+ 55, 13, 14, 15, 16, 17, 16, 17,
+ 10, 2, 55, 19, 20, 21, 22, 23,
+ 10, 2, 55, 23, 25, 31, 26, 27,
+ 28, 29, 30, 29, 30, 10, 2, 55,
+ 32, 33, 34, 35, 36, 35, 36, 10,
+ 2, 55, 38, 39, 40, 41, 42, 10,
+ 2, 55, 42, 44, 45, 46, 49, 50,
+ 46, 47, 48, 10, 2, 55, 10, 2,
+ 55, 50, 52, 53, 49, 54, 54, 55,
+ 56, 57
};
static const char _deserialize_json_trans_actions[] = {
0, 0, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 2, 2,
- 2, 0, 0, 3, 3, 4, 0, 5,
- 0, 0, 2, 2, 2, 0, 0, 6,
- 6, 7, 0, 0, 0, 2, 2, 8,
- 8, 9, 0, 0, 0, 0, 0, 2,
- 2, 2, 0, 0, 10, 10, 11, 0,
- 0, 2, 2, 2, 0, 0, 12, 12,
- 13, 0, 0, 2, 14, 14, 0, 15,
- 0, 16, 16, 17, 18, 18, 19, 15,
- 0, 0, 20, 20, 21, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 0, 0, 3, 3, 4, 0,
+ 5, 0, 0, 2, 2, 2, 0, 0,
+ 6, 6, 7, 0, 0, 0, 2, 2,
+ 8, 8, 9, 0, 0, 0, 0, 0,
+ 2, 2, 2, 0, 0, 10, 10, 11,
+ 0, 0, 2, 2, 2, 0, 0, 12,
+ 12, 13, 0, 0, 0, 2, 2, 14,
+ 14, 15, 0, 0, 0, 2, 16, 16,
+ 0, 17, 0, 18, 18, 19, 20, 20,
+ 21, 17, 0, 0, 22, 22, 23, 0,
+ 0, 0
};
static const int deserialize_json_start = 1;
-static const int deserialize_json_first_final = 49;
+static const int deserialize_json_first_final = 55;
static const int deserialize_json_error = 0;
static const int deserialize_json_en_main = 1;
-#line 108 "hb-buffer-deserialize-json.rl"
+#line 111 "hb-buffer-deserialize-json.rl"
static hb_bool_t
@@ -508,12 +557,12 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer,
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 512 "hb-buffer-deserialize-json.hh"
+#line 554 "hb-buffer-deserialize-json.hh"
{
cs = deserialize_json_start;
}
-#line 517 "hb-buffer-deserialize-json.hh"
+#line 557 "hb-buffer-deserialize-json.hh"
{
int _slen;
int _trans;
@@ -561,25 +610,25 @@ _resume:
tok = p;
}
break;
- case 15:
+ case 17:
#line 55 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 21:
+ case 23:
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 16:
+ case 18:
#line 58 "hb-buffer-deserialize-json.rl"
{
/* TODO Unescape \" and \\ if found. */
if (!hb_font_glyph_from_string (font,
- tok, p - tok,
+ tok+1, p - tok - 2, /* Skip "" */
&info.codepoint))
return false;
}
break;
- case 18:
+ case 20:
#line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
break;
@@ -604,6 +653,10 @@ _resume:
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
break;
case 14:
+#line 72 "hb-buffer-deserialize-json.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+ break;
+ case 16:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
@@ -611,7 +664,7 @@ _resume:
#line 55 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 20:
+ case 22:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
@@ -619,12 +672,12 @@ _resume:
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 17:
+ case 19:
#line 58 "hb-buffer-deserialize-json.rl"
{
/* TODO Unescape \" and \\ if found. */
if (!hb_font_glyph_from_string (font,
- tok, p - tok,
+ tok+1, p - tok - 2, /* Skip "" */
&info.codepoint))
return false;
}
@@ -637,7 +690,7 @@ _resume:
*end_ptr = p;
}
break;
- case 19:
+ case 21:
#line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
#line 43 "hb-buffer-deserialize-json.rl"
@@ -709,7 +762,19 @@ _resume:
*end_ptr = p;
}
break;
-#line 713 "hb-buffer-deserialize-json.hh"
+ case 15:
+#line 72 "hb-buffer-deserialize-json.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-json.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+#line 735 "hb-buffer-deserialize-json.hh"
}
_again:
@@ -721,7 +786,7 @@ _again:
_out: {}
}
-#line 136 "hb-buffer-deserialize-json.rl"
+#line 139 "hb-buffer-deserialize-json.rl"
*end_ptr = p;
diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
index 06a605e225..8fbcdcc18c 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
@@ -32,29 +32,32 @@
#include "hb.hh"
-#line 36 "hb-buffer-deserialize-text.hh"
+#line 33 "hb-buffer-deserialize-text.hh"
static const unsigned char _deserialize_text_trans_keys[] = {
0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 45u, 57u,
- 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u,
- 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 9u, 124u,
+ 48u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u,
+ 44u, 57u, 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u,
9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 0
+ 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
+ 9u, 124u, 9u, 124u, 9u, 124u, 0
};
static const char _deserialize_text_key_spans[] = {
0, 83, 1, 1, 55, 77, 10, 13,
- 10, 10, 13, 10, 1, 13, 10, 14,
- 82, 13, 10, 116, 116, 0, 77, 116,
+ 10, 10, 10, 13, 10, 1, 13, 10,
+ 14, 82, 13, 10, 116, 116, 0, 77,
+ 116, 116, 116, 116, 116, 116, 116, 116,
116, 116, 116, 116, 116, 116, 116, 116,
- 116, 116, 116, 116, 116
+ 116, 116, 116
};
static const short _deserialize_text_index_offsets[] = {
0, 0, 84, 86, 88, 144, 222, 233,
- 247, 258, 269, 283, 294, 296, 310, 321,
- 336, 419, 433, 444, 561, 678, 679, 757,
- 874, 991, 1108, 1225, 1342, 1459, 1576, 1693,
- 1810, 1927, 2044, 2161, 2278
+ 247, 258, 269, 280, 294, 305, 307, 321,
+ 332, 347, 430, 444, 455, 572, 689, 690,
+ 768, 885, 1002, 1119, 1236, 1353, 1470, 1587,
+ 1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523,
+ 2640, 2757, 2874
};
static const char _deserialize_text_indicies[] = {
@@ -91,50 +94,52 @@ static const char _deserialize_text_indicies[] = {
12, 12, 12, 12, 12, 12, 12, 1,
13, 14, 14, 14, 14, 14, 14, 14,
14, 14, 1, 15, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 1, 17, 1,
- 1, 18, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 1, 20, 21, 21, 21,
+ 16, 16, 16, 16, 16, 1, 17, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 1, 19, 1, 1, 20, 21, 21, 21,
21, 21, 21, 21, 21, 21, 1, 22,
- 1, 23, 1, 1, 24, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 1, 26,
+ 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 1, 24, 1, 25, 1, 1, 26,
27, 27, 27, 27, 27, 27, 27, 27,
- 27, 1, 22, 1, 1, 1, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 1, 28, 28, 1, 1, 1, 1, 1,
+ 27, 1, 28, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 1, 24, 1, 1,
+ 1, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 1, 30, 30, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 28, 1, 1, 28, 1,
+ 1, 1, 1, 1, 1, 1, 30, 1,
+ 1, 30, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 30, 30, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 28, 28, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 30, 1, 31,
+ 1, 1, 32, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 1, 34, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 1,
+ 36, 36, 36, 36, 36, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 28, 1, 29, 1, 1, 30,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 1, 32, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 1, 34, 34, 34,
- 34, 34, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 36,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 34, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 1, 1, 1, 38, 39, 1, 1,
+ 37, 37, 37, 37, 37, 37, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 1, 1,
- 1, 36, 37, 1, 1, 35, 35, 35,
- 35, 35, 35, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 35, 35, 35,
- 35, 35, 35, 1, 1, 1, 1, 1,
+ 37, 37, 37, 37, 37, 37, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 38, 1, 39, 39, 39, 39, 39, 1,
+ 1, 1, 1, 40, 1, 41, 41, 41,
+ 41, 41, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 41, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 39, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 40,
+ 1, 1, 42, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -142,24 +147,23 @@ static const char _deserialize_text_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 41, 1, 1,
- 7, 7, 7, 7, 7, 1, 1, 1,
+ 43, 1, 1, 7, 7, 7, 7, 7,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 7,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 7, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 4, 1, 42, 42,
- 42, 42, 42, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 4,
+ 1, 44, 44, 44, 44, 44, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 42, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 44, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 43, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 45, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -167,68 +171,83 @@ static const char _deserialize_text_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 44, 1, 42, 42, 42, 42, 42,
+ 1, 1, 1, 1, 46, 1, 44, 44,
+ 44, 44, 44, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 44, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 42, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 1,
+ 1, 1, 1, 45, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 1, 1, 1, 1,
- 43, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 44, 1,
- 47, 47, 47, 47, 47, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 47,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 48, 1, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 49, 46, 46, 50,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 51, 52, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 53, 46, 54, 54, 54,
- 54, 54, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 54, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 55,
- 1, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 56, 28, 28, 57, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 58, 59, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 60, 28, 61, 61, 61, 61, 61, 1,
+ 1, 46, 1, 49, 49, 49, 49, 49,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 49, 48, 48, 50, 48, 48,
+ 48, 48, 48, 48, 48, 51, 1, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 52,
+ 48, 48, 53, 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, 48, 48, 54, 55,
+ 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, 48, 48, 48, 48, 48, 56, 48,
+ 57, 57, 57, 57, 57, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 57,
+ 30, 30, 58, 30, 30, 30, 30, 30,
+ 30, 30, 59, 1, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 60, 30, 30, 61,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 62, 63, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 64, 30, 57, 57, 57,
+ 57, 57, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 57, 30, 30, 58,
+ 30, 30, 30, 30, 30, 30, 30, 59,
+ 1, 30, 30, 30, 65, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 30, 30,
+ 30, 60, 30, 30, 61, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 62, 63, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 64, 30, 67, 67, 67, 67, 67, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 61, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 62, 1, 1,
+ 1, 67, 1, 1, 68, 1, 1, 1,
+ 1, 1, 1, 1, 1, 69, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 63, 1,
+ 1, 1, 1, 1, 1, 1, 70, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 64, 1, 65,
- 65, 65, 65, 65, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 71, 1, 72,
+ 72, 72, 72, 72, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 65, 1,
+ 1, 1, 1, 1, 1, 1, 72, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -236,172 +255,238 @@ static const char _deserialize_text_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 40, 1, 1, 1, 1,
+ 1, 1, 1, 42, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 66, 1, 67, 67, 67, 67,
- 67, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 67, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 48, 1,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 49, 46, 46, 50, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 51,
- 52, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 53,
- 46, 68, 68, 68, 68, 68, 1, 1,
+ 1, 1, 73, 1, 74, 74, 74, 74,
+ 74, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 74, 48, 48, 50, 48,
+ 48, 48, 48, 48, 48, 48, 51, 1,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 52, 48, 48, 53, 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, 48, 48, 54,
+ 55, 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, 48, 48, 48, 48, 48, 56,
+ 48, 75, 75, 75, 75, 75, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 68, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 69, 1, 1, 1, 1,
+ 75, 1, 1, 76, 1, 1, 1, 1,
+ 1, 1, 1, 77, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 70, 1, 1, 1, 1, 1, 1, 1,
+ 78, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 43, 1, 1,
+ 1, 1, 1, 1, 1, 45, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 71, 1, 72, 72,
- 72, 72, 72, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 79, 1, 80, 80,
+ 80, 80, 80, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 72, 1, 1,
+ 1, 1, 1, 1, 1, 80, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 73, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 74, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 81, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 75, 1, 72, 72, 72, 72, 72,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 82, 1, 80, 80, 80, 80, 80,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 72, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 73, 1, 1,
- 1, 1, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 80, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 74,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 81,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 75, 1,
- 68, 68, 68, 68, 68, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 68,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 69, 1, 1, 1, 1, 76,
- 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 1, 1, 1, 1, 1, 1, 70,
+ 1, 1, 1, 1, 1, 1, 82, 1,
+ 84, 84, 84, 84, 84, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 84,
+ 1, 1, 85, 1, 1, 1, 1, 1,
+ 1, 1, 86, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 43, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 71, 1, 77, 77, 77,
- 77, 77, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 87, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 88, 1, 84, 84, 84,
+ 84, 84, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 84, 1, 1, 85,
+ 1, 1, 1, 1, 1, 1, 1, 86,
+ 1, 1, 1, 1, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 77, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 87, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 88, 1, 75, 75, 75, 75, 75, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 75, 1, 1, 76, 1, 1, 1,
+ 1, 1, 1, 1, 77, 1, 1, 1,
+ 1, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 1, 1, 1, 1, 1,
1, 78, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 45, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 79, 1, 77, 77, 77, 77, 77, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 77, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 79, 1, 90,
+ 90, 90, 90, 90, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 90, 1,
+ 1, 91, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 78, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 79, 1, 61,
- 61, 61, 61, 61, 1, 1, 1, 1,
+ 1, 1, 1, 92, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 61, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 62, 1, 1, 1, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 93, 1, 90, 90, 90, 90,
+ 90, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 90, 1, 1, 91, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 63, 1, 1, 1, 1,
+ 92, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 93,
+ 1, 67, 67, 67, 67, 67, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 64, 1, 0
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 67, 1, 1, 68, 1, 1, 1, 1,
+ 1, 1, 1, 1, 69, 1, 1, 1,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 70, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 71, 1, 94, 94,
+ 94, 94, 94, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 94, 30, 30,
+ 58, 30, 30, 30, 30, 30, 30, 30,
+ 59, 1, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 60, 30, 30, 61, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 62, 95, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 96, 30, 94, 94, 94, 94, 94,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 94, 30, 30, 58, 30, 30,
+ 30, 30, 30, 30, 30, 59, 1, 30,
+ 30, 30, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 30, 30, 30, 60,
+ 30, 30, 61, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 62, 95,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 96, 30,
+ 0
};
static const char _deserialize_text_trans_targs[] = {
- 1, 0, 2, 25, 3, 4, 19, 5,
- 23, 24, 8, 27, 36, 27, 36, 30,
- 33, 11, 12, 15, 12, 15, 13, 14,
- 31, 32, 31, 32, 26, 18, 34, 35,
- 34, 35, 20, 19, 6, 21, 22, 20,
- 21, 22, 20, 21, 22, 24, 26, 26,
- 7, 9, 10, 16, 21, 29, 26, 7,
- 9, 10, 16, 21, 29, 28, 17, 21,
- 29, 28, 29, 29, 28, 7, 10, 29,
- 28, 7, 21, 29, 33, 28, 21, 29
+ 1, 0, 2, 26, 3, 4, 20, 5,
+ 24, 25, 8, 29, 40, 29, 40, 32,
+ 37, 33, 34, 12, 13, 16, 13, 16,
+ 14, 15, 35, 36, 35, 36, 27, 19,
+ 38, 39, 38, 39, 21, 20, 6, 22,
+ 23, 21, 22, 23, 21, 22, 23, 25,
+ 27, 27, 28, 7, 9, 11, 17, 22,
+ 31, 27, 28, 7, 9, 11, 17, 22,
+ 31, 41, 42, 30, 10, 18, 22, 31,
+ 30, 31, 31, 30, 10, 7, 11, 31,
+ 30, 22, 31, 34, 30, 10, 7, 22,
+ 31, 37, 30, 10, 22, 31, 27, 22,
+ 31, 42
};
static const char _deserialize_text_trans_actions[] = {
0, 0, 0, 0, 1, 0, 2, 0,
2, 2, 3, 4, 4, 5, 5, 4,
- 4, 3, 3, 3, 0, 0, 6, 3,
- 4, 4, 5, 5, 5, 3, 4, 4,
- 5, 5, 7, 8, 9, 7, 7, 0,
- 0, 0, 10, 10, 10, 8, 12, 13,
- 14, 14, 14, 15, 11, 11, 17, 18,
- 18, 18, 0, 16, 16, 19, 20, 19,
- 19, 0, 0, 13, 10, 21, 21, 10,
- 22, 23, 22, 22, 5, 24, 24, 24
+ 4, 4, 4, 3, 3, 3, 0, 0,
+ 6, 3, 4, 4, 5, 5, 5, 3,
+ 4, 4, 5, 5, 7, 8, 9, 7,
+ 7, 0, 0, 0, 10, 10, 10, 8,
+ 12, 13, 14, 15, 15, 15, 16, 11,
+ 11, 18, 19, 20, 20, 20, 0, 17,
+ 17, 4, 4, 21, 22, 22, 21, 21,
+ 0, 0, 13, 10, 23, 23, 23, 10,
+ 24, 24, 24, 5, 25, 26, 26, 25,
+ 25, 5, 27, 28, 27, 27, 30, 29,
+ 29, 5
};
static const char _deserialize_text_eof_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 7, 0, 0, 0, 10,
- 10, 11, 16, 19, 0, 11, 10, 22,
- 22, 10, 24, 24, 19
+ 0, 0, 0, 0, 7, 0, 0, 0,
+ 10, 10, 11, 17, 17, 21, 0, 11,
+ 10, 24, 24, 25, 25, 10, 27, 27,
+ 21, 29, 29
};
static const int deserialize_text_start = 1;
-static const int deserialize_text_first_final = 19;
+static const int deserialize_text_first_final = 20;
static const int deserialize_text_error = 0;
static const int deserialize_text_en_main = 1;
-#line 114 "hb-buffer-deserialize-text.rl"
+#line 117 "hb-buffer-deserialize-text.rl"
static hb_bool_t
@@ -424,12 +509,12 @@ _hb_buffer_deserialize_text (hb_buffer_t *buffer,
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 428 "hb-buffer-deserialize-text.hh"
+#line 506 "hb-buffer-deserialize-text.hh"
{
cs = deserialize_text_start;
}
-#line 433 "hb-buffer-deserialize-text.hh"
+#line 509 "hb-buffer-deserialize-text.hh"
{
int _slen;
int _trans;
@@ -475,7 +560,7 @@ _resume:
#line 56 "hb-buffer-deserialize-text.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 18:
+ case 20:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimiters. */
@@ -489,7 +574,7 @@ _resume:
#line 66 "hb-buffer-deserialize-text.rl"
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
break;
- case 21:
+ case 23:
#line 68 "hb-buffer-deserialize-text.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
break;
@@ -497,15 +582,19 @@ _resume:
#line 69 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
break;
- case 23:
+ case 26:
#line 70 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
break;
- case 20:
+ case 22:
#line 71 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
break;
- case 15:
+ case 28:
+#line 72 "hb-buffer-deserialize-text.rl"
+ { if (!parse_int (tok, p, &pos.y_advance)) return false; }
+ break;
+ case 16:
#line 38 "hb-buffer-deserialize-text.rl"
{
memset (&info, 0, sizeof (info));
@@ -532,7 +621,7 @@ _resume:
#line 56 "hb-buffer-deserialize-text.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 16:
+ case 17:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimiters. */
@@ -550,6 +639,18 @@ _resume:
*end_ptr = p;
}
break;
+ case 19:
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 55 "hb-buffer-deserialize-text.rl"
+ { if (unlikely (!buffer->ensure_glyphs ())) return false; }
+ break;
case 7:
#line 66 "hb-buffer-deserialize-text.rl"
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
@@ -574,7 +675,7 @@ _resume:
*end_ptr = p;
}
break;
- case 22:
+ case 25:
#line 70 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -586,7 +687,7 @@ _resume:
*end_ptr = p;
}
break;
- case 19:
+ case 21:
#line 71 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -598,7 +699,7 @@ _resume:
*end_ptr = p;
}
break;
- case 24:
+ case 27:
#line 72 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -610,6 +711,18 @@ _resume:
*end_ptr = p;
}
break;
+ case 24:
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
case 12:
#line 38 "hb-buffer-deserialize-text.rl"
{
@@ -623,7 +736,7 @@ _resume:
#line 55 "hb-buffer-deserialize-text.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 14:
+ case 15:
#line 38 "hb-buffer-deserialize-text.rl"
{
memset (&info, 0, sizeof (info));
@@ -642,7 +755,7 @@ _resume:
return false;
}
break;
- case 17:
+ case 18:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimiters. */
@@ -662,6 +775,26 @@ _resume:
*end_ptr = p;
}
break;
+ case 29:
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
case 11:
#line 38 "hb-buffer-deserialize-text.rl"
{
@@ -689,6 +822,49 @@ _resume:
*end_ptr = p;
}
break;
+ case 14:
+#line 38 "hb-buffer-deserialize-text.rl"
+ {
+ memset (&info, 0, sizeof (info));
+ memset (&pos , 0, sizeof (pos ));
+}
+#line 51 "hb-buffer-deserialize-text.rl"
+ {
+ tok = p;
+}
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 55 "hb-buffer-deserialize-text.rl"
+ { if (unlikely (!buffer->ensure_glyphs ())) return false; }
+ break;
+ case 30:
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 55 "hb-buffer-deserialize-text.rl"
+ { if (unlikely (!buffer->ensure_glyphs ())) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
case 13:
#line 38 "hb-buffer-deserialize-text.rl"
{
@@ -718,7 +894,7 @@ _resume:
*end_ptr = p;
}
break;
-#line 722 "hb-buffer-deserialize-text.hh"
+#line 826 "hb-buffer-deserialize-text.hh"
}
_again:
@@ -730,7 +906,7 @@ _again:
if ( p == eof )
{
switch ( _deserialize_text_eof_actions[cs] ) {
- case 16:
+ case 17:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimiters. */
@@ -772,7 +948,7 @@ _again:
*end_ptr = p;
}
break;
- case 22:
+ case 25:
#line 70 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -784,7 +960,7 @@ _again:
*end_ptr = p;
}
break;
- case 19:
+ case 21:
#line 71 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -796,7 +972,7 @@ _again:
*end_ptr = p;
}
break;
- case 24:
+ case 27:
#line 72 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -808,6 +984,38 @@ _again:
*end_ptr = p;
}
break;
+ case 24:
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 29:
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
case 11:
#line 38 "hb-buffer-deserialize-text.rl"
{
@@ -835,14 +1043,14 @@ _again:
*end_ptr = p;
}
break;
-#line 839 "hb-buffer-deserialize-text.hh"
+#line 953 "hb-buffer-deserialize-text.hh"
}
}
_out: {}
}
-#line 138 "hb-buffer-deserialize-text.rl"
+#line 141 "hb-buffer-deserialize-text.rl"
*end_ptr = p;
diff --git a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
index 6539b89640..d1e1775430 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,13 +50,13 @@ static const char *serialize_formats[] = {
const char **
hb_buffer_serialize_list_formats ()
{
- return serialize_formats;
+ return _hb_buffer_serialize_formats;
}
/**
* hb_buffer_serialize_format_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
+ * @len: length of @str, or -1 if string is `NULL` terminated
*
* Parses a string into an #hb_buffer_serialize_format_t. Does not check if
* @str is a valid buffer serialization format, use
@@ -78,11 +78,11 @@ hb_buffer_serialize_format_from_string (const char *str, int len)
* hb_buffer_serialize_format_to_string:
* @format: an #hb_buffer_serialize_format_t to convert.
*
- * Converts @format to the string corresponding it, or %NULL if it is not a valid
+ * Converts @format to the string corresponding it, or `NULL` if it is not a valid
* #hb_buffer_serialize_format_t.
*
* Return value: (transfer none):
- * A %NULL terminated string corresponding to @format. Should not be freed.
+ * A `NULL` terminated string corresponding to @format. Should not be freed.
*
* Since: 0.9.7
**/
@@ -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.
@@ -727,7 +727,7 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
* hb_buffer_deserialize_glyphs:
* @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len): string to deserialize
- * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
+ * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated
* @end_ptr: (out) (optional): output pointer to the character after last
* consumed one.
* @font: (nullable): font for getting glyph IDs
@@ -736,7 +736,7 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
* Deserializes glyphs @buffer from textual representation in the format
* produced by hb_buffer_serialize_glyphs().
*
- * Return value: %true if @buf is not fully consumed, %false otherwise.
+ * Return value: `true` if @buf is not fully consumed, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -800,7 +800,7 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
* hb_buffer_deserialize_unicode:
* @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len): string to deserialize
- * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
+ * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated
* @end_ptr: (out) (optional): output pointer to the character after last
* consumed one.
* @format: the #hb_buffer_serialize_format_t of the input @buf
@@ -808,7 +808,7 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
* Deserializes Unicode @buffer from textual representation in the format
* produced by hb_buffer_serialize_unicode().
*
- * Return value: %true if @buf is not fully consumed, %false otherwise.
+ * Return value: `true` if @buf is not fully consumed, `false` otherwise.
*
* Since: 2.7.3
**/
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..57a5ae03ed 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer.cc
@@ -51,7 +51,7 @@
* Checks the equality of two #hb_segment_properties_t's.
*
* Return value:
- * %true if all properties of @a equal those of @b, %false otherwise.
+ * `true` if all properties of @a equal those of @b, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -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.
}
@@ -384,9 +387,11 @@ hb_buffer_t::clear_positions ()
hb_memset (pos, 0, sizeof (pos[0]) * len);
}
-void
+bool
hb_buffer_t::sync ()
{
+ bool ret = false;
+
assert (have_output);
assert (idx <= len);
@@ -400,12 +405,39 @@ hb_buffer_t::sync ()
info = out_info;
}
len = out_len;
+ ret = true;
reset:
have_output = false;
out_len = 0;
out_info = info;
idx = 0;
+
+ return ret;
+}
+
+int
+hb_buffer_t::sync_so_far ()
+{
+ bool had_output = have_output;
+ unsigned out_i = out_len;
+ unsigned i = idx;
+ unsigned old_idx = idx;
+
+ if (sync ())
+ idx = out_i;
+ else
+ idx = i;
+
+ if (had_output)
+ {
+ have_output = true;
+ out_len = idx;
+ }
+
+ assert (idx <= len);
+
+ return idx - old_idx;
}
bool
@@ -542,7 +574,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 +656,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
HB_SEGMENT_PROPERTIES_DEFAULT,
false, /* successful */
+ true, /* shaping_failed */
false, /* have_output */
true /* have_positions */
@@ -631,16 +665,16 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
/**
- * hb_buffer_create: (Xconstructor)
+ * hb_buffer_create:
*
* Creates a new #hb_buffer_t with all properties to defaults.
*
* Return value: (transfer full):
* A newly allocated #hb_buffer_t with a reference count of 1. The initial
* reference count should be released with hb_buffer_destroy() when you are done
- * using the #hb_buffer_t. This function never returns %NULL. If memory cannot
+ * using the #hb_buffer_t. This function never returns `NULL`. If memory cannot
* be allocated, a special #hb_buffer_t object will be returned on which
- * hb_buffer_allocation_successful() returns %false.
+ * hb_buffer_allocation_successful() returns `false`.
*
* Since: 0.9.2
**/
@@ -770,7 +804,7 @@ hb_buffer_destroy (hb_buffer_t *buffer)
*
* Attaches a user-data key/data pair to the specified buffer.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -797,7 +831,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
* Since: 0.9.2
**/
void *
-hb_buffer_get_user_data (hb_buffer_t *buffer,
+hb_buffer_get_user_data (const hb_buffer_t *buffer,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (buffer, key);
@@ -834,7 +868,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 +910,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 +953,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 +997,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 +1041,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 +1077,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 +1115,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 +1154,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 +1195,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 +1235,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 +1275,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;
}
@@ -1273,7 +1307,7 @@ hb_buffer_clear_contents (hb_buffer_t *buffer)
* Pre allocates memory for @buffer to fit at least @size number of items.
*
* Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise
+ * `true` if @buffer memory allocation succeeded, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1290,7 +1324,7 @@ hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
* Check if allocating memory for the buffer succeeded.
*
* Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise.
+ * `true` if @buffer memory allocation succeeded, `false` otherwise.
*
* Since: 0.9.2
**/
@@ -1335,7 +1369,7 @@ hb_buffer_add (hb_buffer_t *buffer,
* end.
*
* Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise.
+ * `true` if @buffer memory allocation succeeded, `false` otherwise.
*
* Since: 0.9.2
**/
@@ -1381,7 +1415,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;
}
@@ -1421,7 +1455,7 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
* If buffer did not have positions before, the positions will be
* initialized to zeros, unless this function is called from
* within a buffer message callback (see hb_buffer_set_message_func()),
- * in which case %NULL is returned.
+ * in which case `NULL` is returned.
*
* Return value: (transfer none) (array length=length):
* The @buffer glyph position array.
@@ -1456,7 +1490,7 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
* and cleared of position data when hb_buffer_clear_contents() is called.
*
* Return value:
- * %true if the @buffer has position array, %false otherwise.
+ * `true` if the @buffer has position array, `false` otherwise.
*
* Since: 2.7.3
**/
@@ -1640,10 +1674,10 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
* @buffer: An #hb_buffer_t
* @text: (array length=text_length) (element-type uint8_t): An array of UTF-8
* characters to append.
- * @text_length: The length of the @text, or -1 if it is %NULL terminated.
+ * @text_length: The length of the @text, or -1 if it is `NULL` terminated.
* @item_offset: The offset of the first character to add to the @buffer.
* @item_length: The number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated).
+ * end of @text (assuming it is `NULL` terminated).
*
* See hb_buffer_add_codepoints().
*
@@ -1666,10 +1700,10 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer,
* hb_buffer_add_utf16:
* @buffer: An #hb_buffer_t
* @text: (array length=text_length): An array of UTF-16 characters to append
- * @text_length: The length of the @text, or -1 if it is %NULL terminated
+ * @text_length: The length of the @text, or -1 if it is `NULL` terminated
* @item_offset: The offset of the first character to add to the @buffer
* @item_length: The number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated)
+ * end of @text (assuming it is `NULL` terminated)
*
* See hb_buffer_add_codepoints().
*
@@ -1692,10 +1726,10 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer,
* hb_buffer_add_utf32:
* @buffer: An #hb_buffer_t
* @text: (array length=text_length): An array of UTF-32 characters to append
- * @text_length: The length of the @text, or -1 if it is %NULL terminated
+ * @text_length: The length of the @text, or -1 if it is `NULL` terminated
* @item_offset: The offset of the first character to add to the @buffer
* @item_length: The number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated)
+ * end of @text (assuming it is `NULL` terminated)
*
* See hb_buffer_add_codepoints().
*
@@ -1719,10 +1753,10 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
* @buffer: An #hb_buffer_t
* @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
* characters to append
- * @text_length: the length of the @text, or -1 if it is %NULL terminated
+ * @text_length: the length of the @text, or -1 if it is `NULL` terminated
* @item_offset: the offset of the first character to add to the @buffer
* @item_length: the number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated)
+ * end of @text (assuming it is `NULL` terminated)
*
* Similar to hb_buffer_add_codepoints(), but allows only access to first 256
* Unicode code points that can fit in 8-bit strings.
@@ -1745,10 +1779,10 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer,
* hb_buffer_add_codepoints:
* @buffer: a #hb_buffer_t to append characters to.
* @text: (array length=text_length): an array of Unicode code points to append.
- * @text_length: the length of the @text, or -1 if it is %NULL terminated.
+ * @text_length: the length of the @text, or -1 if it is `NULL` terminated.
* @item_offset: the offset of the first code point to add to the @buffer.
* @item_length: the number of code points to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated).
+ * end of @text (assuming it is `NULL` terminated).
*
* Appends characters from @text array to @buffer. The @item_offset is the
* position of the first character from @text that will be appended, and
@@ -2085,8 +2119,16 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
bool
hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
{
+ assert (!have_output || (out_info == info && out_len == idx));
+
+ message_depth++;
+
char buf[100];
vsnprintf (buf, sizeof (buf), fmt, ap);
- return (bool) this->message_func (this, font, buf, this->message_data);
+ bool ret = (bool) this->message_func (this, font, buf, this->message_data);
+
+ message_depth--;
+
+ return ret;
}
#endif
diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h
index 14aaa5e1f5..c6af759fb9 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.h
+++ b/thirdparty/harfbuzz/src/hb-buffer.h
@@ -142,6 +142,15 @@ typedef struct hb_glyph_info_t {
* shaping, otherwise the buffer flag will not be
* reliably produced.
* Since: 4.0.0
+ * @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL: In scripts that use elongation (Arabic,
+ Mongolian, Syriac, etc.), this flag signifies
+ that it is safe to insert a U+0640 TATWEEL
+ character *before* this cluster for elongation.
+ This flag does not determine the
+ script-specific elongation places, but only
+ when it is safe to do the elongation without
+ interrupting text shaping.
+ Since: 5.1.0
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*
* Flags for #hb_glyph_info_t.
@@ -149,10 +158,11 @@ typedef struct hb_glyph_info_t {
* Since: 1.5.0
*/
typedef enum { /*< flags >*/
- HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
- HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
+ HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
+ HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
+ HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL = 0x00000004,
- HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */
+ HB_GLYPH_FLAG_DEFINED = 0x00000007 /* OR of all defined flags */
} hb_glyph_flags_t;
HB_EXTERN hb_glyph_flags_t
@@ -266,7 +276,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
hb_bool_t replace);
HB_EXTERN void *
-hb_buffer_get_user_data (hb_buffer_t *buffer,
+hb_buffer_get_user_data (const hb_buffer_t *buffer,
hb_user_data_key_t *key);
@@ -289,7 +299,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 +307,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 +329,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 +383,11 @@ 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_PRODUCE_SAFE_TO_INSERT_TATWEEL:
+ * flag indicating that the @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL
+ * glyph-flag should be produced by the shaper. By default
+ * it will not be produced. Since: 5.1.0
+ * @HB_BUFFER_FLAG_DEFINED: All currently defined flags: Since: 4.4.0
*
* Flags for #hb_buffer_t.
*
@@ -386,7 +401,10 @@ 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_PRODUCE_SAFE_TO_INSERT_TATWEEL = 0x00000080u,
+
+ HB_BUFFER_FLAG_DEFINED = 0x000000FFu
} hb_buffer_flags_t;
HB_EXTERN void
@@ -394,7 +412,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 +454,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 +471,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 +567,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 +601,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 +614,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;
/**
@@ -749,16 +770,16 @@ hb_buffer_diff (hb_buffer_t *buffer,
* hb_buffer_message_func_t:
* @buffer: An #hb_buffer_t to work upon
* @font: The #hb_font_t the @buffer is shaped with
- * @message: %NULL-terminated message passed to the function
+ * @message: `NULL`-terminated message passed to the function
* @user_data: User data pointer passed by the caller
*
* A callback method for #hb_buffer_t. The method gets called with the
* #hb_buffer_t it was set on, the #hb_font_t the buffer is shaped with and a
* message describing what step of the shaping process will be performed.
- * Returning %false from this method will skip this shaping step and move to
+ * Returning `false` from this method will skip this shaping step and move to
* the next one.
*
- * Return value: %true to perform the shaping step, %false to skip it.
+ * Return value: `true` to perform the shaping step, `false` to skip it.
*
* Since: 1.1.3
*/
diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh
index bc6992905e..26c3f0fac8 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]; }
@@ -285,7 +288,8 @@ struct hb_buffer_t
HB_INTERNAL void guess_segment_properties ();
- HB_INTERNAL void sync ();
+ HB_INTERNAL bool sync ();
+ HB_INTERNAL int sync_so_far ();
HB_INTERNAL void clear_output ();
HB_INTERNAL void clear_positions ();
@@ -458,6 +462,17 @@ struct hb_buffer_t
start, end,
true);
}
+ void safe_to_insert_tatweel (unsigned int start = 0, unsigned int end = -1)
+ {
+ if ((flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL) == 0)
+ {
+ unsafe_to_break (start, end);
+ return;
+ }
+ _set_glyph_flags (HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL,
+ start, end,
+ true);
+ }
void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
{
if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
@@ -549,18 +564,14 @@ struct hb_buffer_t
#ifdef HB_NO_BUFFER_MESSAGE
return true;
#else
- if (!messaging ())
+ if (likely (!messaging ()))
return true;
- message_depth++;
-
va_list ap;
va_start (ap, fmt);
bool ret = message_impl (font, fmt, ap);
va_end (ap);
- message_depth--;
-
return ret;
#endif
}
@@ -619,9 +630,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-cff-interp-cs-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh
index 2983ae54a1..f93c83ab45 100644
--- a/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh
+++ b/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh
@@ -57,6 +57,7 @@ struct call_context_t
/* call stack */
const unsigned int kMaxCallLimit = 10;
+const unsigned int kMaxOps = 10000;
struct call_stack_t : cff_stack_t<call_context_t, kMaxCallLimit> {};
template <typename SUBRS>
@@ -881,7 +882,13 @@ struct cs_interpreter_t : interpreter_t<ENV>
{
SUPER::env.set_endchar (false);
+ unsigned max_ops = kMaxOps;
for (;;) {
+ if (unlikely (!--max_ops))
+ {
+ SUPER::env.set_error ();
+ break;
+ }
OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
if (unlikely (SUPER::env.in_error ()))
return false;
diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc
index 41229b9183..e6512872e8 100644
--- a/thirdparty/harfbuzz/src/hb-common.cc
+++ b/thirdparty/harfbuzz/src/hb-common.cc
@@ -108,7 +108,7 @@ _hb_options_init ()
/**
* hb_tag_from_string:
* @str: (array length=len) (element-type uint8_t): String to convert
- * @len: Length of @str, or -1 if it is %NULL-terminated
+ * @len: Length of @str, or -1 if it is `NULL`-terminated
*
* Converts a string into an #hb_tag_t. Valid tags
* are four characters. Shorter input strings will be
@@ -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",
@@ -170,7 +170,7 @@ const char direction_strings[][4] = {
/**
* hb_direction_from_string:
* @str: (array length=len) (element-type uint8_t): String to convert
- * @len: Length of @str, or -1 if it is %NULL-terminated
+ * @len: Length of @str, or -1 if it is `NULL`-terminated
*
* Converts a string to an #hb_direction_t.
*
@@ -357,7 +357,7 @@ retry:
* hb_language_from_string:
* @str: (array length=len) (element-type uint8_t): a string representing
* a BCP 47 language tag
- * @len: length of the @str, or -1 if it is %NULL-terminated.
+ * @len: length of the @str, or -1 if it is `NULL`-terminated.
*
* Converts @str representing a BCP 47 language tag to the corresponding
* #hb_language_t.
@@ -396,7 +396,7 @@ hb_language_from_string (const char *str, int len)
* Converts an #hb_language_t to a string.
*
* Return value: (transfer none):
- * A %NULL-terminated string representing the @language. Must not be freed by
+ * A `NULL`-terminated string representing the @language. Must not be freed by
* the caller.
*
* Since: 0.9.2
@@ -441,6 +441,38 @@ hb_language_get_default ()
return language;
}
+/**
+ * hb_language_matches:
+ * @language: The #hb_language_t to work on
+ * @specific: Another #hb_language_t
+ *
+ * Check whether a second language tag is the same or a more
+ * specific version of the provided language tag. For example,
+ * "fa_IR.utf8" is a more specific tag for "fa" or for "fa_IR".
+ *
+ * Return value: `true` if languages match, `false` otherwise.
+ *
+ * Since: 5.0.0
+ **/
+hb_bool_t
+hb_language_matches (hb_language_t language,
+ hb_language_t specific)
+{
+ if (language == specific) return true;
+ if (!language || !specific) return false;
+
+ const char *l = language->s;
+ const char *s = specific->s;
+ unsigned ll = strlen (l);
+ unsigned sl = strlen (s);
+
+ if (ll > sl)
+ return false;
+
+ return strncmp (l, s, ll) == 0 &&
+ (s[ll] == '\0' || s[ll] == '-');
+}
+
/* hb_script_t */
@@ -498,7 +530,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
* hb_script_from_string:
* @str: (array length=len) (element-type uint8_t): a string representing an
* ISO 15924 tag.
- * @len: length of the @str, or -1 if it is %NULL-terminated.
+ * @len: length of the @str, or -1 if it is `NULL`-terminated.
*
* Converts a string @str representing an ISO 15924 script tag to a
* corresponding #hb_script_t. Shorthand for hb_tag_from_string() then
@@ -693,8 +725,8 @@ hb_version_string ()
* Tests the library version against a minimum value,
* as three integer components.
*
- * Return value: %true if the library is equal to or greater than
- * the test value, %false otherwise
+ * Return value: `true` if the library is equal to or greater than
+ * the test value, `false` otherwise
*
* Since: 0.9.30
**/
@@ -881,7 +913,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
/**
* hb_feature_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
+ * @len: length of @str, or -1 if string is `NULL` terminated
* @feature: (out): the #hb_feature_t to initialize with the parsed values
*
* Parses a string into a #hb_feature_t.
@@ -923,7 +955,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
* </informaltable>
*
* Return value:
- * %true if @str is successfully parsed, %false otherwise
+ * `true` if @str is successfully parsed, `false` otherwise
*
* Since: 0.9.5
**/
@@ -954,7 +986,7 @@ hb_feature_from_string (const char *str, int len,
* @buf: (array length=size) (out): output string
* @size: the allocated size of @buf
*
- * Converts a #hb_feature_t into a %NULL-terminated string in the format
+ * Converts a #hb_feature_t into a `NULL`-terminated string in the format
* understood by hb_feature_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
@@ -1022,7 +1054,7 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation
/**
* hb_variation_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
+ * @len: length of @str, or -1 if string is `NULL` terminated
* @variation: (out): the #hb_variation_t to initialize with the parsed values
*
* Parses a string into a #hb_variation_t.
@@ -1035,7 +1067,7 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation
* number. For example `wght=500`, or `slnt=-7.5`.
*
* Return value:
- * %true if @str is successfully parsed, %false otherwise
+ * `true` if @str is successfully parsed, `false` otherwise
*
* Since: 1.4.2
*/
@@ -1107,7 +1139,7 @@ get_C_locale ()
* @buf: (array length=size) (out): output string
* @size: the allocated size of @buf
*
- * Converts an #hb_variation_t into a %NULL-terminated string in the format
+ * Converts an #hb_variation_t into a `NULL`-terminated string in the format
* understood by hb_variation_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h
index 7b897a6c51..7c7ad87c7c 100644
--- a/thirdparty/harfbuzz/src/hb-common.h
+++ b/thirdparty/harfbuzz/src/hb-common.h
@@ -326,6 +326,9 @@ hb_language_to_string (hb_language_t language);
HB_EXTERN hb_language_t
hb_language_get_default (void);
+HB_EXTERN hb_bool_t
+hb_language_matches (hb_language_t language,
+ hb_language_t specific);
/**
* hb_script_t:
diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh
index 4b46dea938..db8ec0e908 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
@@ -97,6 +98,11 @@
/* Closure of options. */
+#ifdef HB_NO_BORING_EXPANSION
+#define HB_NO_BEYOND_64K
+#define HB_NO_VARIATIONS2
+#endif
+
#ifdef HB_DISABLE_DEPRECATED
#define HB_IF_NOT_DEPRECATED(x)
#else
@@ -145,10 +151,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 +169,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..c4d9d29e23
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-cplusplus.hh
@@ -0,0 +1,221 @@
+/*
+ * 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) (const 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
+
+
+#ifdef HB_SUBSET_H
+
+#define HB_DEFINE_VTABLE(name) \
+ template<> \
+ struct vtable<hb_##name##_t> \
+ : vtable_t<hb_##name##_t, \
+ nullptr, \
+ &hb_##name##_reference, \
+ &hb_##name##_destroy, \
+ &hb_##name##_set_user_data, \
+ &hb_##name##_get_user_data> {}
+
+
+HB_DEFINE_VTABLE (subset_input);
+HB_DEFINE_VTABLE (subset_plan);
+
+#undef HB_DEFINE_VTABLE
+
+#endif
+
+
+} // namespace hb
+
+/* Workaround for GCC < 7, see:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480
+ * https://stackoverflow.com/a/25594741 */
+namespace std {
+
+
+template<typename T>
+struct 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 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;
+ }
+};
+
+
+} // namespace std
+
+#endif /* __cplusplus */
+
+#endif /* HB_CPLUSPLUS_HH */
diff --git a/thirdparty/harfbuzz/src/hb-debug.hh b/thirdparty/harfbuzz/src/hb-debug.hh
index 3ac7440e80..905a46a087 100644
--- a/thirdparty/harfbuzz/src/hb-debug.hh
+++ b/thirdparty/harfbuzz/src/hb-debug.hh
@@ -460,4 +460,9 @@ struct hb_no_trace_t {
#endif
+#ifndef HB_BUFFER_MESSAGE_MORE
+#define HB_BUFFER_MESSAGE_MORE (HB_DEBUG+1)
+#endif
+
+
#endif /* HB_DEBUG_HH */
diff --git a/thirdparty/harfbuzz/src/hb-deprecated.h b/thirdparty/harfbuzz/src/hb-deprecated.h
index a130d77f77..333dc3cd4c 100644
--- a/thirdparty/harfbuzz/src/hb-deprecated.h
+++ b/thirdparty/harfbuzz/src/hb-deprecated.h
@@ -93,7 +93,7 @@ HB_BEGIN_DECLS
* This method should retrieve the glyph ID for a specified Unicode code point
* font, with an optional variation selector.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
* Deprecated: 1.2.3
*
**/
diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc
index f177ff31c0..de05b7d871 100644
--- a/thirdparty/harfbuzz/src/hb-directwrite.cc
+++ b/thirdparty/harfbuzz/src/hb-directwrite.cc
@@ -43,6 +43,14 @@
* Functions for using HarfBuzz with DirectWrite fonts.
**/
+/* Declare object creator for dynamic support of DWRITE */
+typedef HRESULT (WINAPI *t_DWriteCreateFactory)(
+ DWRITE_FACTORY_TYPE factoryType,
+ REFIID iid,
+ IUnknown **factory
+);
+
+
/*
* DirectWrite font stream helpers
*/
@@ -137,6 +145,7 @@ public:
struct hb_directwrite_face_data_t
{
+ HMODULE dwrite_dll;
IDWriteFactory *dwriteFactory;
IDWriteFontFile *fontFile;
DWriteFontFileStream *fontFileStream;
@@ -158,12 +167,33 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
return nullptr; \
} HB_STMT_END
+ data->dwrite_dll = LoadLibrary (TEXT ("DWRITE"));
+ if (unlikely (!data->dwrite_dll))
+ FAIL ("Cannot find DWrite.DLL");
+
+ t_DWriteCreateFactory p_DWriteCreateFactory;
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
+
+ p_DWriteCreateFactory = (t_DWriteCreateFactory)
+ GetProcAddress (data->dwrite_dll, "DWriteCreateFactory");
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+ if (unlikely (!p_DWriteCreateFactory))
+ FAIL ("Cannot find DWriteCreateFactory().");
+
HRESULT hr;
// TODO: factory and fontFileLoader should be cached separately
IDWriteFactory* dwriteFactory;
- hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
- (IUnknown**) &dwriteFactory);
+ hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
+ (IUnknown**) &dwriteFactory);
if (unlikely (hr != S_OK))
FAIL ("Failed to run DWriteCreateFactory().");
@@ -227,6 +257,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
delete data->fontFileStream;
if (data->faceBlob)
hb_blob_destroy (data->faceBlob);
+ if (data->dwrite_dll)
+ FreeLibrary (data->dwrite_dll);
if (data)
delete data;
}
@@ -241,17 +273,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..46797e64e6 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,32 +91,54 @@ 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; \
+ } \
+ return; \
+ \
+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.
*
* Return value: (transfer full):
* A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
* reference count should be released with hb_draw_funcs_destroy when you are
- * done using the #hb_draw_funcs_t. This function never returns %NULL. If
+ * done using the #hb_draw_funcs_t. This function never returns `NULL`. If
* memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
* be returned.
*
@@ -177,11 +201,16 @@ 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->destroy);
+ hb_free (dfuncs->user_data);
hb_free (dfuncs);
}
@@ -209,7 +238,7 @@ hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
*
* Checks whether @dfuncs is immutable.
*
- * Return value: %true if @dfuncs is immutable, %false otherwise
+ * Return value: `true` if @dfuncs is immutable, `false` otherwise
*
* Since: 4.0.0
**/
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..61adbdd503 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
*
@@ -315,7 +315,7 @@ hb_face_destroy (hb_face_t *face)
*
* Attaches a user-data key/data pair to the given face object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -371,7 +371,7 @@ hb_face_make_immutable (hb_face_t *face)
*
* Tests whether the given face object is immutable.
*
- * Return value: %true is @face is immutable, %false otherwise
+ * Return value: `true` is @face is immutable, `false` otherwise
*
* Since: 0.9.2
**/
diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc
index 5700e06271..856bbdda32 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);
}
@@ -764,7 +754,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
*
* Attaches a user-data key/data pair to the specified font-functions structure.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -791,8 +781,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
* Since: 0.9.2
**/
void *
-hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
- hb_user_data_key_t *key)
+hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key)
{
return hb_object_get_user_data (ffuncs, key);
}
@@ -821,7 +811,7 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
*
* Tests whether a font-functions structure is immutable.
*
- * Return value: %true if @ffuncs is immutable, %false otherwise
+ * Return value: `true` if @ffuncs is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -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
@@ -887,7 +903,7 @@ hb_font_t::has_func (unsigned int i)
* Fetches the extents for a specified font, for horizontal
* text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.1.3
**/
@@ -906,7 +922,7 @@ hb_font_get_h_extents (hb_font_t *font,
* Fetches the extents for a specified font, for vertical
* text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.1.3
**/
@@ -930,7 +946,7 @@ hb_font_get_v_extents (hb_font_t *font,
* If @variation_selector is 0, calls hb_font_get_nominal_glyph();
* otherwise calls hb_font_get_variation_glyph().
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -958,7 +974,7 @@ hb_font_get_glyph (hb_font_t *font,
* for code points modified by variation selectors. For variation-selector
* support, user hb_font_get_variation_glyph() or use hb_font_get_glyph().
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.2.3
**/
@@ -1010,7 +1026,7 @@ hb_font_get_nominal_glyphs (hb_font_t *font,
* by the specified variation-selector code point, in the specified
* font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.2.3
**/
@@ -1120,7 +1136,7 @@ hb_font_get_glyph_v_advances (hb_font_t* font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for horizontal text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1143,7 +1159,7 @@ hb_font_get_glyph_h_origin (hb_font_t *font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for vertical text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1216,7 +1232,7 @@ hb_font_get_glyph_v_kerning (hb_font_t *font,
* Fetches the #hb_glyph_extents_t data for a glyph ID
* in the specified font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1239,7 +1255,7 @@ hb_font_get_glyph_extents (hb_font_t *font,
* Fetches the (x,y) coordinates of a specified contour-point index
* in the specified glyph, within the specified font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1262,7 +1278,7 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
*
* Fetches the glyph-name string for a glyph ID in the specified @font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1286,7 +1302,7 @@ hb_font_get_glyph_name (hb_font_t *font,
*
* <note>Note: @len == -1 means the name string is null-terminated.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1521,7 +1537,7 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1550,7 +1566,7 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1601,7 +1617,7 @@ hb_font_glyph_to_string (hb_font_t *font,
*
* <note>Note: @len == -1 means the string is null-terminated.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -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 */
@@ -1654,6 +1675,7 @@ _hb_font_create (hb_face_t *face)
if (unlikely (!face))
face = hb_face_get_empty ();
+
if (!(font = hb_object_create<hb_font_t> ()))
return hb_font_get_empty ();
@@ -1662,14 +1684,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 +1738,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 +1769,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 +1791,8 @@ hb_font_create_sub_font (hb_font_t *parent)
}
}
+ font->mults_changed ();
+
return font;
}
@@ -1841,7 +1867,7 @@ hb_font_destroy (hb_font_t *font)
*
* Attaches a user-data key/data pair to the specified font object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1852,6 +1878,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);
}
@@ -1868,7 +1897,7 @@ hb_font_set_user_data (hb_font_t *font,
* Since: 0.9.2
**/
void *
-hb_font_get_user_data (hb_font_t *font,
+hb_font_get_user_data (const hb_font_t *font,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (font, key);
@@ -1900,7 +1929,7 @@ hb_font_make_immutable (hb_font_t *font)
*
* Tests whether a font object is immutable.
*
- * Return value: %true if @font is immutable, %false otherwise
+ * Return value: `true` if @font is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1911,6 +1940,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 +1994,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 +2041,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 +2100,8 @@ hb_font_set_funcs (hb_font_t *font,
return;
}
+ font->serial++;
+
if (font->destroy)
font->destroy (font->user_data);
@@ -2059,6 +2139,8 @@ hb_font_set_funcs_data (hb_font_t *font,
return;
}
+ font->serial++;
+
if (font->destroy)
font->destroy (font->user_data);
@@ -2085,6 +2167,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 +2214,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 +2261,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 +2313,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 +2365,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);
@@ -2283,6 +2387,10 @@ hb_font_set_variations (hb_font_t *font,
return;
}
+ /* Initialize design coords to default from fvar. */
+ for (unsigned int i = 0; i < coords_length; i++)
+ design_coords[i] = axes[i].get_default ();
+
for (unsigned int i = 0; i < variations_length; i++)
{
const auto tag = variations[i].tag;
@@ -2322,6 +2430,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 +2465,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 +2503,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..e2c3df4a5a 100644
--- a/thirdparty/harfbuzz/src/hb-font.h
+++ b/thirdparty/harfbuzz/src/hb-font.h
@@ -86,8 +86,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
HB_EXTERN void *
-hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
- hb_user_data_key_t *key);
+hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key);
HB_EXTERN void
@@ -198,7 +198,7 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
* This method should retrieve the nominal glyph ID for a specified Unicode code
* point. Glyph IDs must be returned in a #hb_codepoint_t output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data,
@@ -221,7 +221,7 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo
* followed by a specified Variation Selector code point. Glyph IDs must be
* returned in a #hb_codepoint_t output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data,
@@ -362,7 +362,7 @@ typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
* origin for a glyph. Each coordinate must be returned in an #hb_position_t
* output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
@@ -434,7 +434,7 @@ typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
* This method should retrieve the extents for a specified glyph. Extents must be
* returned in an #hb_glyph_extents output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
@@ -458,7 +458,7 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo
* specified contour point in a glyph. Each coordinate must be returned as
* an #hb_position_t output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data,
@@ -481,7 +481,7 @@ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, vo
* This method should retrieve the glyph name that corresponds to a
* glyph ID. The name should be returned in a string output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data,
@@ -503,7 +503,7 @@ typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_
* This method should retrieve the glyph ID that corresponds to a glyph-name
* string.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data,
@@ -993,7 +993,7 @@ hb_font_set_user_data (hb_font_t *font,
HB_EXTERN void *
-hb_font_get_user_data (hb_font_t *font,
+hb_font_get_user_data (const hb_font_t *font,
hb_user_data_key_t *key);
HB_EXTERN void
@@ -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..ef073475cb 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,82 @@ _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)
+{
+ float x_mult = 1.f, y_mult = 1.f;
+
+ if (font->x_scale < 0) x_mult = -x_mult;
+ if (font->y_scale < 0) y_mult = -y_mult;
+
+ if (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
+ ) && ft_face->num_fixed_sizes)
+ {
+#ifdef HAVE_FT_GET_TRANSFORM
+ /* Bitmap font, eg. bitmap color emoji. */
+ /* TODO Pick largest size? */
+ int x_scale = ft_face->available_sizes[0].x_ppem;
+ int y_scale = ft_face->available_sizes[0].y_ppem;
+ FT_Set_Char_Size (ft_face,
+ x_scale, y_scale,
+ 0, 0);
+
+ /* This contains the sign that was previously in x_mult/y_mult. */
+ x_mult = (float) font->x_scale / x_scale;
+ y_mult = (float) font->y_scale / y_scale;
+#endif
+ }
+ else
+ { /* Shrug */ }
+
+
+ if (x_mult != 1.f || y_mult != 1.f)
+ {
+ FT_Matrix matrix = { (int) roundf (x_mult * (1<<16)), 0,
+ 0, (int) roundf (y_mult * (1<<16))};
+ FT_Set_Transform (ft_face, &matrix, nullptr);
+ }
+
+#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
+ unsigned int num_coords;
+ const float *coords = hb_font_get_var_coords_design (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] * 65536.f;
+ FT_Set_Var_Design_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,13 +259,13 @@ 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
* font object.
*
- * Return value: (nullable): the FT_Face found or %NULL
+ * Return value: (nullable): the FT_Face found or `NULL`
*
* Since: 0.9.2
**/
@@ -203,13 +281,13 @@ 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
* you call hb_ft_font_unlock_face().
*
- * Return value: (nullable): the FT_Face associated with @font or %NULL
+ * Return value: (nullable) (transfer none): the FT_Face associated with @font or `NULL`
* Since: 2.6.5
**/
FT_Face
@@ -226,7 +304,7 @@ hb_ft_font_lock_face (hb_font_t *font)
}
/**
- * hb_ft_font_unlock_face:
+ * hb_ft_font_unlock_face: (skip)
* @font: #hb_font_t to work upon
*
* Releases an FT_Face previously obtained with hb_ft_font_lock_face().
@@ -246,7 +324,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 +336,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;
}
@@ -335,13 +428,13 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
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;
- }
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_face, &matrix, nullptr);
+ float mult = matrix.xx / 65536.f;
+#else
+ float mult = font->x_scale < 0 ? -1 : +1;
+#endif
for (unsigned int i = 0; i < count; i++)
{
@@ -357,7 +450,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
ft_font->advance_cache.set (glyph, v);
}
- *first_advance = (v * mult + (1<<9)) >> 10;
+ *first_advance = (int) (v * mult + (1<<9)) >> 10;
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
@@ -373,12 +466,18 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Fixed v;
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_font->ft_face, &matrix, nullptr);
+ float y_mult = matrix.yy / 65536.f;
+#else
+ float y_mult = font->y_scale < 0 ? -1 : +1;
+#endif
if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
return 0;
- if (font->y_scale < 0)
- v = -v;
+ v = (int) (y_mult * v);
/* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
* have a Y growing upward. Hence the extra negation. */
@@ -399,6 +498,15 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
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;
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_face, &matrix, nullptr);
+ float x_mult = matrix.xx / 65536.f;
+ float y_mult = matrix.yy / 65536.f;
+#else
+ float x_mult = font->x_scale < 0 ? -1 : +1;
+ float y_mult = font->y_scale < 0 ? -1 : +1;
+#endif
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
@@ -408,10 +516,8 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
*x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX;
*y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
- if (font->x_scale < 0)
- *x = -*x;
- if (font->y_scale < 0)
- *y = -*y;
+ *x = (hb_position_t) (x_mult * *x);
+ *y = (hb_position_t) (y_mult * *y);
return true;
}
@@ -426,6 +532,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;
@@ -446,24 +553,24 @@ hb_ft_get_glyph_extents (hb_font_t *font,
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;
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_face, &matrix, nullptr);
+ float x_mult = matrix.xx / 65536.f;
+ float y_mult = matrix.yy / 65536.f;
+#else
+ float x_mult = font->x_scale < 0 ? -1 : +1;
+ float y_mult = font->y_scale < 0 ? -1 : +1;
+#endif
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
- extents->x_bearing = ft_face->glyph->metrics.horiBearingX;
- extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
- extents->width = ft_face->glyph->metrics.width;
- extents->height = -ft_face->glyph->metrics.height;
- if (font->x_scale < 0)
- {
- extents->x_bearing = -extents->x_bearing;
- extents->width = -extents->width;
- }
- if (font->y_scale < 0)
- {
- extents->y_bearing = -extents->y_bearing;
- extents->height = -extents->height;
- }
+ extents->x_bearing = (hb_position_t) (x_mult * ft_face->glyph->metrics.horiBearingX);
+ extents->y_bearing = (hb_position_t) (y_mult * ft_face->glyph->metrics.horiBearingY);
+ extents->width = (hb_position_t) (x_mult * ft_face->glyph->metrics.width);
+ extents->height = (hb_position_t) (y_mult * -ft_face->glyph->metrics.height);
+
return true;
}
@@ -556,15 +663,32 @@ 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);
- if (font->y_scale < 0)
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_face, &matrix, nullptr);
+ float y_mult = matrix.yy / 65536.f;
+#else
+ float y_mult = font->y_scale < 0 ? -1 : +1;
+#endif
+
+ if (ft_face->units_per_EM != 0)
{
- metrics->ascender = -metrics->ascender;
- metrics->descender = -metrics->descender;
- metrics->line_gap = -metrics->line_gap;
+ 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);
}
+ else
+ {
+ /* Bitmap-only font, eg. color bitmap font. */
+ metrics->ascender = ft_face->size->metrics.ascender;
+ metrics->descender = ft_face->size->metrics.descender;
+ metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender);
+ }
+
+ metrics->ascender = (hb_position_t) (y_mult * metrics->ascender);
+ metrics->descender = (hb_position_t) (y_mult * metrics->descender);
+ metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap);
+
return true;
}
@@ -961,6 +1085,34 @@ hb_ft_font_changed (hb_font_t *font)
#endif
}
#endif
+
+ ft_font->advance_cache.clear ();
+ ft_font->cached_serial = font->serial;
+}
+
+/**
+ * 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);
}
/**
@@ -1081,35 +1233,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-graphite2.cc b/thirdparty/harfbuzz/src/hb-graphite2.cc
index 63dc18b466..4d0e687c75 100644
--- a/thirdparty/harfbuzz/src/hb-graphite2.cc
+++ b/thirdparty/harfbuzz/src/hb-graphite2.cc
@@ -158,7 +158,7 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
}
/**
- * hb_graphite2_face_get_gr_face:
+ * hb_graphite2_face_get_gr_face: (skip)
* @face: @hb_face_t to query
*
* Fetches the Graphite2 gr_face corresponding to the specified
@@ -195,10 +195,10 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED
#ifndef HB_DISABLE_DEPRECATED
/**
- * hb_graphite2_font_get_gr_font:
+ * hb_graphite2_font_get_gr_font: (skip)
* @font: An #hb_font_t
*
- * Always returns %NULL. Use hb_graphite2_face_get_gr_face() instead.
+ * Always returns `NULL`. Use hb_graphite2_face_get_gr_face() instead.
*
* Return value: (nullable): Graphite2 font associated with @font.
*
@@ -223,7 +223,7 @@ struct hb_graphite2_cluster_t {
unsigned int base_glyph;
unsigned int num_glyphs;
unsigned int cluster;
- unsigned int advance;
+ int advance;
};
hb_bool_t
diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh
index 43a3098f65..1a3ab43de0 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()); }
@@ -263,6 +253,8 @@ struct hb_is_iterator_of
};
#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
+#define hb_is_sorted_iterator_of(Iter, Item) (hb_is_iterator_of<Iter, Item>::value && Iter::is_sorted_iterator)
+#define hb_is_sorted_iterator(Iter) hb_is_sorted_iterator_of (Iter, typename Iter::item_t)
/* hb_is_iterable() */
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..5c5f5de59e 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.
*
@@ -56,8 +56,6 @@ hb_map_create ()
if (!(map = hb_object_create<hb_map_t> ()))
return hb_map_get_empty ();
- map->init_shallow ();
-
return map;
}
@@ -107,8 +105,6 @@ hb_map_destroy (hb_map_t *map)
{
if (!hb_object_destroy (map)) return;
- map->fini_shallow ();
-
hb_free (map);
}
@@ -122,7 +118,7 @@ hb_map_destroy (hb_map_t *map)
*
* Attaches a user-data key/data pair to the specified map.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 1.7.7
**/
@@ -149,7 +145,7 @@ hb_map_set_user_data (hb_map_t *map,
* Since: 1.7.7
**/
void *
-hb_map_get_user_data (hb_map_t *map,
+hb_map_get_user_data (const hb_map_t *map,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (map, key);
@@ -162,7 +158,7 @@ hb_map_get_user_data (hb_map_t *map,
*
* Tests whether memory allocation for a set was successful.
*
- * Return value: %true if allocation succeeded, %false otherwise
+ * Return value: `true` if allocation succeeded, `false` otherwise
*
* Since: 1.7.7
**/
@@ -172,6 +168,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:
@@ -232,7 +247,7 @@ hb_map_del (hb_map_t *map,
*
* Tests whether @key is an element of @map.
*
- * Return value: %true if @key is found in @map, %false otherwise
+ * Return value: `true` if @key is found in @map, `false` otherwise
*
* Since: 1.7.7
**/
@@ -264,7 +279,7 @@ hb_map_clear (hb_map_t *map)
*
* Tests whether @map is empty (contains no elements).
*
- * Return value: %true if @map is empty
+ * Return value: `true` if @map is empty
*
* Since: 1.7.7
**/
@@ -298,7 +313,7 @@ hb_map_get_population (const hb_map_t *map)
* Tests whether @map and @other are equal (contain the same
* elements).
*
- * Return value: %true if the two maps are equal, %false otherwise.
+ * Return value: `true` if the two maps are equal, `false` otherwise.
*
* Since: 4.3.0
**/
@@ -309,3 +324,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..3a067c5c73 100644
--- a/thirdparty/harfbuzz/src/hb-map.h
+++ b/thirdparty/harfbuzz/src/hb-map.h
@@ -74,7 +74,7 @@ hb_map_set_user_data (hb_map_t *map,
hb_bool_t replace);
HB_EXTERN void *
-hb_map_get_user_data (hb_map_t *map,
+hb_map_get_user_data (const hb_map_t *map,
hb_user_data_key_t *key);
@@ -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..8302e3f8c7 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;
@@ -120,21 +124,20 @@ struct hb_hashmap_t
hb_swap (a.prime, b.prime);
hb_swap (a.items, b.items);
}
- void init_shallow ()
+ void init ()
{
+ hb_object_init (this);
+
successful = true;
population = occupancy = 0;
mask = 0;
prime = 0;
items = nullptr;
}
- void init ()
- {
- hb_object_init (this);
- init_shallow ();
- }
- void fini_shallow ()
+ void fini ()
{
+ hb_object_fini (this);
+
if (likely (items)) {
unsigned size = mask + 1;
for (unsigned i = 0; i < size; i++)
@@ -144,11 +147,6 @@ struct hb_hashmap_t
}
population = occupancy = 0;
}
- void fini ()
- {
- hb_object_fini (this);
- fini_shallow ();
- }
void reset ()
{
@@ -200,27 +198,34 @@ 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
+ template <typename VV=V>
+ bool has (K key, VV **vp = nullptr) const
{
- V v = (*this)[k];
- if (vp) *vp = v;
- const V vinv = hb_coerce<V> (vINVALID);
- return v != vinv;
+ if (unlikely (!items))
+ 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
+ return false;
}
/* Projection. */
V operator () (K k) const { return get (k); }
@@ -242,8 +247,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 +277,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)
@@ -278,6 +290,12 @@ struct hb_hashmap_t
| hb_map (&item_t::key)
| hb_map (hb_ridentity)
)
+ auto keys_ref () const HB_AUTO_RETURN
+ (
+ + hb_array (items, mask ? mask + 1 : 0)
+ | hb_filter (&item_t::is_real)
+ | hb_map (&item_t::key)
+ )
auto values () const HB_AUTO_RETURN
(
+ hb_array (items, mask ? mask + 1 : 0)
@@ -285,6 +303,12 @@ struct hb_hashmap_t
| hb_map (&item_t::value)
| hb_map (hb_ridentity)
)
+ auto values_ref () const HB_AUTO_RETURN
+ (
+ + hb_array (items, mask ? mask + 1 : 0)
+ | hb_filter (&item_t::is_real)
+ | hb_map (&item_t::value)
+ )
/* Sink interface. */
hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
@@ -293,19 +317,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 +334,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 +426,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;
@@ -427,4 +444,37 @@ struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_map_t (const Iterable &o) : hashmap (o) {}
};
+template <typename K, typename V>
+static inline
+hb_hashmap_t<K, V>* hb_hashmap_create ()
+{
+ using hashmap = hb_hashmap_t<K, V>;
+ hashmap* map;
+ if (!(map = hb_object_create<hashmap> ()))
+ return nullptr;
+
+ return map;
+}
+
+template <typename K, typename V>
+static inline
+void hb_hashmap_destroy (hb_hashmap_t<K, V>* map)
+{
+ if (!hb_object_destroy (map))
+ return;
+
+ hb_free (map);
+}
+
+namespace hb {
+
+template <typename K, typename V>
+struct vtable<hb_hashmap_t<K, V>>
+{
+ static constexpr auto destroy = hb_hashmap_destroy<K,V>;
+};
+
+}
+
+
#endif /* HB_MAP_HH */
diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh
index 90757d38ac..1921ccbb6d 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 && !defined(__clang__)
#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..0d7f4da79e 100644
--- a/thirdparty/harfbuzz/src/hb-null.hh
+++ b/thirdparty/harfbuzz/src/hb-null.hh
@@ -37,7 +37,25 @@
/* Global nul-content Null pool. Enlarge as necessary. */
-#define HB_NULL_POOL_SIZE 384
+#define HB_NULL_POOL_SIZE 448
+
+template <typename T, typename>
+struct _hb_has_min_size : hb_false_type {};
+template <typename T>
+struct _hb_has_min_size<T, hb_void_t<decltype (T::min_size)>>
+ : hb_true_type {};
+template <typename T>
+using hb_has_min_size = _hb_has_min_size<T, void>;
+#define hb_has_min_size(T) hb_has_min_size<T>::value
+
+template <typename T, typename>
+struct _hb_has_null_size : hb_false_type {};
+template <typename T>
+struct _hb_has_null_size<T, hb_void_t<decltype (T::null_size)>>
+ : hb_true_type {};
+template <typename T>
+using hb_has_null_size = _hb_has_null_size<T, void>;
+#define hb_has_null_size(T) hb_has_null_size<T>::value
/* 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 +126,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 () { \
@@ -117,8 +135,19 @@ struct NullHelper
}; \
namespace Namespace { \
static_assert (true, "") /* Require semicolon after. */
+#define DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1(Namespace, Type, Size) \
+ } /* Close namespace. */ \
+ extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Size]; \
+ template <typename Spec> \
+ struct Null<Namespace::Type<Spec>> { \
+ static Namespace::Type<Spec> const & get_null () { \
+ return *reinterpret_cast<const Namespace::Type<Spec> *> (_hb_Null_##Namespace##_##Type); \
+ } \
+ }; \
+ 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[sizeof (_hb_Null_##Namespace##_##Type)]
/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
#define DECLARE_NULL_INSTANCE(Type) \
diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh
index 4b5bc32ade..f6c7a56991 100644
--- a/thirdparty/harfbuzz/src/hb-object.hh
+++ b/thirdparty/harfbuzz/src/hb-object.hh
@@ -222,8 +222,11 @@ static inline Type *hb_object_create ()
if (unlikely (!obj))
return obj;
+ new (obj) Type;
+
hb_object_init (obj);
hb_object_trace (obj, HB_FUNC);
+
return obj;
}
template <typename Type>
@@ -269,6 +272,9 @@ static inline bool hb_object_destroy (Type *obj)
return false;
hb_object_fini (obj);
+
+ obj->~Type ();
+
return true;
}
template <typename Type>
@@ -280,7 +286,7 @@ static inline void hb_object_fini (Type *obj)
{
user_data->fini ();
hb_free (user_data);
- user_data = nullptr;
+ obj->header.user_data.set_relaxed (nullptr);
}
}
template <typename Type>
diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh
index aee7064be3..d0d01a68c5 100644
--- a/thirdparty/harfbuzz/src/hb-open-type.hh
+++ b/thirdparty/harfbuzz/src/hb-open-type.hh
@@ -105,7 +105,7 @@ struct IntType
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
BEInt<Type, Size> v;
@@ -170,7 +170,7 @@ struct LONGDATETIME
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
HBINT32 major;
@@ -196,6 +196,10 @@ struct HBGlyphID16 : HBUINT16
{
HBGlyphID16& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
};
+struct HBGlyphID24 : HBUINT24
+{
+ HBGlyphID24& operator = (uint32_t i) { HBUINT24::operator= (i); return *this; }
+};
/* Script/language-system/feature index */
struct Index : HBUINT16 {
@@ -300,6 +304,10 @@ struct _hb_has_null<Type, true>
template <typename Type, typename OffsetType, bool has_null=true>
struct OffsetTo : Offset<OffsetType, has_null>
{
+ // Make sure Type is not unbounded; works only for types that are fully defined at OffsetTo time.
+ static_assert (has_null == false ||
+ (hb_has_null_size (Type) || !hb_has_min_size (Type)), "");
+
HB_DELETE_COPY_ASSIGN (OffsetTo);
OffsetTo () = default;
@@ -450,14 +458,16 @@ struct UnsizedArrayOf
{
unsigned int i = (unsigned int) i_;
const Type *p = &arrayZ[i];
- if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) arrayZ)) return Null (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return *p;
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
Type *p = &arrayZ[i];
- if (unlikely (p < arrayZ)) return Crap (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) arrayZ)) return Crap (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return *p;
}
@@ -550,14 +560,16 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_
{
unsigned int i = (unsigned int) i_;
const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
- if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Null (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return this+*p;
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
- if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Crap (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return this+*p;
}
@@ -608,12 +620,14 @@ struct ArrayOf
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= len)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= len)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
@@ -729,6 +743,7 @@ struct ArrayOf
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
template <typename Type> using Array16Of = ArrayOf<Type, HBUINT16>;
+template <typename Type> using Array24Of = ArrayOf<Type, HBUINT24>;
template <typename Type> using Array32Of = ArrayOf<Type, HBUINT32>;
using PString = ArrayOf<HBUINT8, HBUINT8>;
@@ -738,26 +753,28 @@ template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUI
template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
/* Array of offsets relative to the beginning of the array itself. */
-template <typename Type>
-struct List16OfOffset16To : Array16OfOffset16To<Type>
+template <typename Type, typename OffsetType>
+struct List16OfOffsetTo : ArrayOf<OffsetTo<Type, OffsetType>, HBUINT16>
{
const Type& operator [] (int i_) const
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= this->len)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return this+this->arrayZ[i];
}
const Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= this->len)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return this+this->arrayZ[i];
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- struct List16OfOffset16To<Type> *out = c->serializer->embed (*this);
+ struct List16OfOffsetTo *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
unsigned int count = this->len;
for (unsigned int i = 0; i < count; i++)
@@ -769,10 +786,13 @@ struct List16OfOffset16To : Array16OfOffset16To<Type>
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
{
TRACE_SANITIZE (this);
- return_trace (Array16OfOffset16To<Type>::sanitize (c, this, std::forward<Ts> (ds)...));
+ return_trace ((Array16Of<OffsetTo<Type, OffsetType>>::sanitize (c, this, std::forward<Ts> (ds)...)));
}
};
+template <typename Type>
+using List16OfOffset16To = List16OfOffsetTo<Type, HBUINT16>;
+
/* An array starting at second element. */
template <typename Type, typename LenType=HBUINT16>
struct HeadlessArrayOf
@@ -785,12 +805,14 @@ struct HeadlessArrayOf
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= lenP1 || !i)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i-1];
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= lenP1 || !i)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i-1];
}
unsigned int get_size () const
@@ -869,12 +891,14 @@ struct ArrayOfM1
{
unsigned int i = (unsigned int) i_;
if (unlikely (i > lenM1)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i > lenM1)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
unsigned int get_size () const
@@ -961,6 +985,7 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
};
template <typename Type> using SortedArray16Of = SortedArrayOf<Type, HBUINT16>;
+template <typename Type> using SortedArray24Of = SortedArrayOf<Type, HBUINT24>;
template <typename Type> using SortedArray32Of = SortedArrayOf<Type, HBUINT32>;
/*
@@ -1053,12 +1078,14 @@ struct VarSizedBinSearchArrayOf
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= get_length ())) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= get_length ())) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
}
unsigned int get_length () const
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-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
index dac755c02c..f01d383bdc 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
@@ -145,7 +145,7 @@ struct BaseGlyphRecord
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
public:
@@ -524,6 +524,7 @@ struct PaintSweepGradient
};
struct Paint;
+
// Paint a non-COLR glyph, filled as indicated by paint.
struct PaintGlyph
{
@@ -1152,6 +1153,8 @@ struct Paint
Variable<PaintSkewAroundCenter> paintformat31;
PaintComposite paintformat32;
} u;
+ public:
+ DEFINE_SIZE_MIN (2);
};
struct BaseGlyphPaintRecord
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-color.cc b/thirdparty/harfbuzz/src/hb-ot-color.cc
index 16077765bd..a9ae013682 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-color.cc
@@ -61,7 +61,7 @@
*
* Tests whether a face includes a `CPAL` color-palette table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.1.0
*/
@@ -192,7 +192,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face,
*
* Tests whether a face includes any `COLR` color layers.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.1.0
*/
@@ -239,7 +239,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
*
* Tests whether a face includes any `SVG` glyph images.
*
- * Return value: %true if data found, %false otherwise.
+ * Return value: `true` if data found, `false` otherwise.
*
* Since: 2.1.0
*/
@@ -279,7 +279,7 @@ hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
*
* Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables).
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.1.0
*/
diff --git a/thirdparty/harfbuzz/src/hb-ot-color.h b/thirdparty/harfbuzz/src/hb-ot-color.h
index c23ce4de44..d11e07e230 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color.h
+++ b/thirdparty/harfbuzz/src/hb-ot-color.h
@@ -102,6 +102,10 @@ hb_ot_color_has_layers (hb_face_t *face);
*
* Pairs of glyph and color index.
*
+ * A color index of 0xFFFF does not refer to a palette
+ * color, but indicates that the foreground color should
+ * be used.
+ *
* Since: 2.1.0
**/
typedef struct hb_ot_color_layer_t {
diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc
index 0f44ee4d5f..3f13b9994a 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::HVAR &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)
+ {
+ 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)
{
- *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);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->em_scale_x (hmtx.get_advance_with_var_unscaled (*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_with_var_unscaled (*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::VVAR &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_with_var_unscaled (*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,24 +285,36 @@ 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;
const OT::VORG &VORG = *ot_face->VORG;
if (VORG.has_data ())
{
- *y = font->em_scale_y (VORG.get_y_origin (glyph));
+ float delta = 0;
+
+#ifndef HB_NO_VAR
+ const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+ const OT::VVAR &VVAR = *vmtx.var_table;
+ if (font->num_coords)
+ VVAR.get_vorg_delta_unscaled (glyph,
+ font->coords, font->num_coords,
+ &delta);
+#endif
+
+ *y = font->em_scalef_y (VORG.get_y_origin (glyph) + delta);
return true;
}
hb_glyph_extents_t extents = {0};
if (ot_face->glyf->get_extents (font, glyph, &extents))
{
- if (ot_face->vmtx->has_data ())
+ const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+ int tsb = 0;
+ if (vmtx.get_leading_bearing_with_var_unscaled (font, glyph, &tsb))
{
- const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
- hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
*y = extents.y_bearing + font->em_scale_y (tsb);
return true;
}
@@ -208,7 +342,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 +369,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 +385,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,23 +503,28 @@ _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
-int
-_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
+bool
+_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical,
+ int *lsb)
{
- return font->face->table.glyf->get_side_bearing_var (font, glyph, is_vertical);
+ return font->face->table.glyf->get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
}
unsigned
-_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
+_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
{
- return font->face->table.glyf->get_advance_var (font, glyph, is_vertical);
+ return font->face->table.glyf->get_advance_with_var_unscaled (font, glyph, is_vertical);
}
#endif
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..50e4b54fde 100644
--- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -43,11 +43,11 @@
#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
-HB_INTERNAL int
-_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+HB_INTERNAL bool
+_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical, int *lsb);
HB_INTERNAL unsigned
-_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
namespace OT {
@@ -62,7 +62,7 @@ struct LongMetric
};
-template <typename T, typename H>
+template <typename T/*Data table type*/, typename H/*Header table type*/, typename V/*Var table type*/>
struct hmtxvmtx
{
bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
@@ -135,9 +135,9 @@ struct hmtxvmtx
auto& plan = c->plan;
num_long_metrics = plan->num_output_glyphs ();
hb_codepoint_t old_gid = 0;
- unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0;
+ unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance_without_var_unscaled (old_gid) : 0;
while (num_long_metrics > 1 &&
- last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0))
+ last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance_without_var_unscaled (old_gid) : 0))
{
num_long_metrics--;
}
@@ -150,7 +150,9 @@ struct hmtxvmtx
hb_codepoint_t old_gid;
if (!c->plan->old_gid_for_new_gid (_, &old_gid))
return hb_pair (0u, 0);
- return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
+ int lsb = 0;
+ (void) _mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb);
+ return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
})
;
@@ -173,7 +175,7 @@ struct hmtxvmtx
accelerator_t (hb_face_t *face)
{
table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
- var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
+ var_table = hb_sanitize_context_t ().reference_table<V> (face, T::variationsTag);
default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face);
@@ -221,36 +223,46 @@ struct hmtxvmtx
bool has_data () const { return (bool) num_bearings; }
- int get_side_bearing (hb_codepoint_t glyph) const
+ bool get_leading_bearing_without_var_unscaled (hb_codepoint_t glyph,
+ int *lsb) const
{
if (glyph < num_long_metrics)
- return table->longMetricZ[glyph].sb;
+ {
+ *lsb = table->longMetricZ[glyph].sb;
+ return true;
+ }
if (unlikely (glyph >= num_bearings))
- return 0;
+ return false;
const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
- return bearings[glyph - num_long_metrics];
+ *lsb = bearings[glyph - num_long_metrics];
+ return true;
}
- int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const
+ bool get_leading_bearing_with_var_unscaled (hb_font_t *font,
+ hb_codepoint_t glyph,
+ int *lsb) const
{
- int side_bearing = get_side_bearing (glyph);
+ if (!font->num_coords)
+ return get_leading_bearing_without_var_unscaled (glyph, lsb);
#ifndef HB_NO_VAR
- if (unlikely (glyph >= num_bearings) || !font->num_coords)
- 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?!
+ float delta;
+ if (var_table->get_lsb_delta_unscaled (glyph, font->coords, font->num_coords, &delta) &&
+ get_leading_bearing_without_var_unscaled (glyph, lsb))
+ {
+ *lsb += roundf (delta);
+ return true;
+ }
- return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+ return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx, lsb);
#else
- return side_bearing;
+ return false;
#endif
}
- unsigned int get_advance (hb_codepoint_t glyph) const
+ unsigned int get_advance_without_var_unscaled (hb_codepoint_t glyph) const
{
/* OpenType case. */
if (glyph < num_bearings)
@@ -262,7 +274,7 @@ struct hmtxvmtx
if (unlikely (!num_advances))
return default_advance;
-#ifdef HB_NO_BORING_EXPANSION
+#ifdef HB_NO_BEYOND_64K
return 0;
#endif
@@ -275,7 +287,7 @@ struct hmtxvmtx
/* TODO Optimize */
if (num_bearings == num_advances)
- return get_advance (num_bearings - 1);
+ return get_advance_without_var_unscaled (num_bearings - 1);
const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics];
@@ -283,19 +295,22 @@ struct hmtxvmtx
return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)];
}
- unsigned int get_advance (hb_codepoint_t glyph,
- hb_font_t *font) const
+ unsigned get_advance_with_var_unscaled (hb_codepoint_t glyph,
+ hb_font_t *font,
+ VariationStore::cache_t *store_cache = nullptr) const
{
- unsigned int advance = get_advance (glyph);
+ unsigned int advance = get_advance_without_var_unscaled (glyph);
#ifndef HB_NO_VAR
if (unlikely (glyph >= num_bearings) || !font->num_coords)
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_delta_unscaled (glyph,
+ font->coords, font->num_coords,
+ store_cache)); // TODO Optimize?!
- return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+ return _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
#else
return advance;
#endif
@@ -310,9 +325,9 @@ struct hmtxvmtx
unsigned int default_advance;
- private:
+ public:
hb_blob_ptr_t<hmtxvmtx> table;
- hb_blob_ptr_t<HVARVVAR> var_table;
+ hb_blob_ptr_t<V> var_table;
};
protected:
@@ -345,12 +360,12 @@ struct hmtxvmtx
DEFINE_SIZE_ARRAY (0, longMetricZ);
};
-struct hmtx : hmtxvmtx<hmtx, hhea> {
+struct hmtx : hmtxvmtx<hmtx, hhea, HVAR> {
static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
static constexpr bool is_horizontal = true;
};
-struct vmtx : hmtxvmtx<vmtx, vhea> {
+struct vmtx : hmtxvmtx<vmtx, vhea, VVAR> {
static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
static constexpr bool is_horizontal = false;
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
index 1b9dfcd3f5..8179e5acd5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
@@ -49,7 +49,7 @@ struct BaseCoordFormat1
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
index b644df708d..0532039aad 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
@@ -35,6 +35,14 @@
#include "hb-set.hh"
#include "hb-bimap.hh"
+#include "OT/Layout/Common/Coverage.hh"
+#include "OT/Layout/types.hh"
+
+// TODO(garretrieger): cleanup these after migration.
+using OT::Layout::Common::Coverage;
+using OT::Layout::Common::RangeRecord;
+using OT::Layout::SmallTypes;
+using OT::Layout::MediumTypes;
#ifndef HB_MAX_NESTING_LEVEL
#define HB_MAX_NESTING_LEVEL 64
@@ -46,10 +54,10 @@
/*
* The maximum number of times a lookup can be applied during shaping.
* Used to limit the number of iterations of the closure algorithm.
- * This must be larger than the number of times add_pause() is
+ * This must be larger than the number of times add_gsub_pause() is
* called in a collect_features call of any shaper.
*/
-#define HB_CLOSURE_MAX_STAGES 32
+#define HB_CLOSURE_MAX_STAGES 12
#endif
#ifndef HB_MAX_SCRIPTS
@@ -64,10 +72,6 @@
#define HB_MAX_LANGSYS_FEATURE_COUNT 50000
#endif
-#ifndef HB_MAX_FEATURES
-#define HB_MAX_FEATURES 750
-#endif
-
#ifndef HB_MAX_FEATURE_INDICES
#define HB_MAX_FEATURE_INDICES 1500
#endif
@@ -79,14 +83,6 @@
namespace OT {
-
-#define NOT_COVERED ((unsigned int) -1)
-
-
-template<typename Iterator>
-static inline void Coverage_serialize (hb_serialize_context_t *c,
- Iterator it);
-
template<typename Iterator>
static inline void ClassDef_serialize (hb_serialize_context_t *c,
Iterator it);
@@ -102,7 +98,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 +118,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 +158,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_),
@@ -377,6 +373,51 @@ HB_FUNCOBJ (serialize_math_record_array);
* Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
*/
+struct IndexArray : Array16Of<Index>
+{
+ bool intersects (const hb_map_t *indexes) const
+ { return hb_any (*this, indexes); }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ hb_subset_layout_context_t *l,
+ Iterator it)
+ {
+ if (!it) return;
+ if (unlikely (!c->extend_min ((*this)))) return;
+
+ for (const auto _ : it)
+ {
+ if (!l->visitLookupIndex()) break;
+
+ Index i;
+ i = _;
+ c->copy (i);
+ this->len++;
+ }
+ }
+
+ unsigned int get_indexes (unsigned int start_offset,
+ unsigned int *_count /* IN/OUT */,
+ unsigned int *_indexes /* OUT */) const
+ {
+ if (_count)
+ {
+ + this->sub_array (start_offset, _count)
+ | hb_sink (hb_array (_indexes, *_count))
+ ;
+ }
+ return this->len;
+ }
+
+ void add_indexes_to (hb_set_t* output /* OUT */) const
+ {
+ output->add_array (as_array ());
+ }
+};
+
+
struct Record_sanitize_closure_t {
hb_tag_t tag;
const void *list_base;
@@ -465,366 +506,6 @@ struct RecordListOf : RecordArrayOf<Type>
}
};
-struct Feature;
-
-struct RecordListOfFeature : RecordListOf<Feature>
-{
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- unsigned count = this->len;
- + hb_zip (*this, hb_range (count))
- | hb_filter (l->feature_index_map, hb_second)
- | hb_map (hb_first)
- | hb_apply (subset_record_array (l, out, this))
- ;
- return_trace (true);
- }
-};
-
-struct Script;
-struct RecordListOfScript : RecordListOf<Script>
-{
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- unsigned count = this->len;
- for (auto _ : + hb_zip (*this, hb_range (count)))
- {
- auto snap = c->serializer->snapshot ();
- l->cur_script_index = _.second;
- bool ret = _.first.subset (l, this);
- if (!ret) c->serializer->revert (snap);
- else out->len++;
- }
-
- return_trace (true);
- }
-};
-
-struct RangeRecord
-{
- int cmp (hb_codepoint_t g) const
- { return g < first ? -1 : g <= last ? 0 : +1; }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- { return glyphs->intersects (first, last); }
-
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- { return glyphs->add_range (first, last); }
-
- HBGlyphID16 first; /* First GlyphID in the range */
- HBGlyphID16 last; /* Last GlyphID in the range */
- HBUINT16 value; /* Value */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
-
-
-struct IndexArray : Array16Of<Index>
-{
- bool intersects (const hb_map_t *indexes) const
- { return hb_any (*this, indexes); }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- hb_subset_layout_context_t *l,
- Iterator it)
- {
- if (!it) return;
- if (unlikely (!c->extend_min ((*this)))) return;
-
- for (const auto _ : it)
- {
- if (!l->visitLookupIndex()) break;
-
- Index i;
- i = _;
- c->copy (i);
- this->len++;
- }
- }
-
- unsigned int get_indexes (unsigned int start_offset,
- unsigned int *_count /* IN/OUT */,
- unsigned int *_indexes /* OUT */) const
- {
- if (_count)
- {
- + this->sub_array (start_offset, _count)
- | hb_sink (hb_array (_indexes, *_count))
- ;
- }
- return this->len;
- }
-
- void add_indexes_to (hb_set_t* output /* OUT */) const
- {
- output->add_array (as_array ());
- }
-};
-
-
-struct LangSys
-{
- unsigned int get_feature_count () const
- { return featureIndex.len; }
- hb_tag_t get_feature_index (unsigned int i) const
- { return featureIndex[i]; }
- unsigned int get_feature_indexes (unsigned int start_offset,
- unsigned int *feature_count /* IN/OUT */,
- unsigned int *feature_indexes /* OUT */) const
- { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
- void add_feature_indexes_to (hb_set_t *feature_indexes) const
- { featureIndex.add_indexes_to (feature_indexes); }
-
- bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
- unsigned int get_required_feature_index () const
- {
- if (reqFeatureIndex == 0xFFFFu)
- return Index::NOT_FOUND_INDEX;
- return reqFeatureIndex;
- }
-
- LangSys* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- return_trace (c->embed (*this));
- }
-
- bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
- {
- if (reqFeatureIndex != o.reqFeatureIndex)
- return false;
-
- auto iter =
- + hb_iter (featureIndex)
- | hb_filter (feature_index_map)
- | hb_map (feature_index_map)
- ;
-
- auto o_iter =
- + hb_iter (o.featureIndex)
- | hb_filter (feature_index_map)
- | hb_map (feature_index_map)
- ;
-
- for (; iter && o_iter; iter++, o_iter++)
- {
- unsigned a = *iter;
- unsigned b = *o_iter;
- if (a != b) return false;
- }
-
- if (iter || o_iter) return false;
-
- return true;
- }
-
- void collect_features (hb_prune_langsys_context_t *c) const
- {
- if (!has_required_feature () && !get_feature_count ()) return;
- if (has_required_feature () &&
- c->duplicate_feature_map->has (reqFeatureIndex))
- c->new_feature_indexes->add (get_required_feature_index ());
-
- + hb_iter (featureIndex)
- | hb_filter (c->duplicate_feature_map)
- | hb_sink (c->new_feature_indexes)
- ;
- }
-
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l,
- const Tag *tag = nullptr) const
- {
- TRACE_SUBSET (this);
- 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;
-
- if (!l->visitFeatureIndex (featureIndex.len))
- return_trace (false);
-
- auto it =
- + hb_iter (featureIndex)
- | hb_filter (l->feature_index_map)
- | hb_map (l->feature_index_map)
- ;
-
- bool ret = bool (it);
- out->featureIndex.serialize (c->serializer, l, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c,
- const Record_sanitize_closure_t * = nullptr) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && featureIndex.sanitize (c));
- }
-
- Offset16 lookupOrderZ; /* = Null (reserved for an offset to a
- * reordering table) */
- HBUINT16 reqFeatureIndex;/* Index of a feature required for this
- * language system--if no required features
- * = 0xFFFFu */
- IndexArray featureIndex; /* Array of indices into the FeatureList */
- public:
- DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
-};
-DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
-
-struct Script
-{
- unsigned int get_lang_sys_count () const
- { return langSys.len; }
- const Tag& get_lang_sys_tag (unsigned int i) const
- { return langSys.get_tag (i); }
- unsigned int get_lang_sys_tags (unsigned int start_offset,
- unsigned int *lang_sys_count /* IN/OUT */,
- hb_tag_t *lang_sys_tags /* OUT */) const
- { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
- const LangSys& get_lang_sys (unsigned int i) const
- {
- if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
- return this+langSys[i].offset;
- }
- bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
- { return langSys.find_index (tag, index); }
-
- bool has_default_lang_sys () const { return defaultLangSys != 0; }
- const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
-
- void prune_langsys (hb_prune_langsys_context_t *c,
- unsigned script_index) const
- {
- if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
- if (!c->visitScript ()) return;
-
- 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);
- return;
- }
- }
-
- unsigned langsys_count = get_lang_sys_count ();
- if (has_default_lang_sys ())
- {
- //only collect features from non-redundant langsys
- const LangSys& d = get_default_lang_sys ();
- if (c->visitLangsys (d.get_feature_count ())) {
- d.collect_features (c);
- }
-
- for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
- {
- const LangSys& l = this+_.first.offset;
- if (!c->visitLangsys (l.get_feature_count ())) continue;
- if (l.compare (d, c->duplicate_feature_map)) continue;
-
- l.collect_features (c);
- c->script_langsys_map->get (script_index)->add (_.second);
- }
- }
- else
- {
- for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
- {
- const LangSys& l = this+_.first.offset;
- if (!c->visitLangsys (l.get_feature_count ())) continue;
- l.collect_features (c);
- c->script_langsys_map->get (script_index)->add (_.second);
- }
- }
- }
-
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l,
- const Tag *tag) const
- {
- TRACE_SUBSET (this);
- if (!l->visitScript ()) return_trace (false);
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- bool defaultLang = false;
- if (has_default_lang_sys ())
- {
- c->serializer->push ();
- const LangSys& ls = this+defaultLangSys;
- bool ret = ls.subset (c, l);
- if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
- {
- c->serializer->pop_discard ();
- out->defaultLangSys = 0;
- }
- else
- {
- c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
- defaultLang = true;
- }
- }
-
- const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
- if (active_langsys)
- {
- unsigned count = langSys.len;
- + hb_zip (langSys, hb_range (count))
- | hb_filter (active_langsys, hb_second)
- | hb_map (hb_first)
- | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
- | hb_apply (subset_record_array (l, &(out->langSys), this))
- ;
- }
-
- return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
- }
-
- bool sanitize (hb_sanitize_context_t *c,
- const Record_sanitize_closure_t * = nullptr) const
- {
- TRACE_SANITIZE (this);
- return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
- }
-
- protected:
- Offset16To<LangSys>
- defaultLangSys; /* Offset to DefaultLangSys table--from
- * beginning of Script table--may be Null */
- RecordArrayOf<LangSys>
- langSys; /* Array of LangSysRecords--listed
- * alphabetically by LangSysTag */
- public:
- DEFINE_SIZE_ARRAY_SIZED (4, langSys);
-};
-
-typedef RecordListOfScript ScriptList;
-
-
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
struct FeatureParamsSize
{
@@ -1107,6 +788,7 @@ struct FeatureParams
DEFINE_SIZE_MIN (0);
};
+
struct Feature
{
unsigned int get_lookup_count () const
@@ -1202,9 +884,294 @@ struct Feature
DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
};
+struct RecordListOfFeature : RecordListOf<Feature>
+{
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ unsigned count = this->len;
+ + hb_zip (*this, hb_range (count))
+ | hb_filter (l->feature_index_map, hb_second)
+ | hb_map (hb_first)
+ | hb_apply (subset_record_array (l, out, this))
+ ;
+ return_trace (true);
+ }
+};
+
typedef RecordListOf<Feature> FeatureList;
+struct LangSys
+{
+ unsigned int get_feature_count () const
+ { return featureIndex.len; }
+ hb_tag_t get_feature_index (unsigned int i) const
+ { return featureIndex[i]; }
+ unsigned int get_feature_indexes (unsigned int start_offset,
+ unsigned int *feature_count /* IN/OUT */,
+ unsigned int *feature_indexes /* OUT */) const
+ { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
+ void add_feature_indexes_to (hb_set_t *feature_indexes) const
+ { featureIndex.add_indexes_to (feature_indexes); }
+
+ bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
+ unsigned int get_required_feature_index () const
+ {
+ if (reqFeatureIndex == 0xFFFFu)
+ return Index::NOT_FOUND_INDEX;
+ return reqFeatureIndex;
+ }
+
+ LangSys* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed (*this));
+ }
+
+ bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
+ {
+ if (reqFeatureIndex != o.reqFeatureIndex)
+ return false;
+
+ auto iter =
+ + hb_iter (featureIndex)
+ | hb_filter (feature_index_map)
+ | hb_map (feature_index_map)
+ ;
+
+ auto o_iter =
+ + hb_iter (o.featureIndex)
+ | hb_filter (feature_index_map)
+ | hb_map (feature_index_map)
+ ;
+
+ for (; iter && o_iter; iter++, o_iter++)
+ {
+ unsigned a = *iter;
+ unsigned b = *o_iter;
+ if (a != b) return false;
+ }
+
+ if (iter || o_iter) return false;
+
+ return true;
+ }
+
+ void collect_features (hb_prune_langsys_context_t *c) const
+ {
+ if (!has_required_feature () && !get_feature_count ()) return;
+ if (has_required_feature () &&
+ c->duplicate_feature_map->has (reqFeatureIndex))
+ c->new_feature_indexes->add (get_required_feature_index ());
+
+ + hb_iter (featureIndex)
+ | hb_filter (c->duplicate_feature_map)
+ | hb_sink (c->new_feature_indexes)
+ ;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l,
+ const Tag *tag = nullptr) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ const unsigned *v;
+ out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
+
+ if (!l->visitFeatureIndex (featureIndex.len))
+ return_trace (false);
+
+ auto it =
+ + hb_iter (featureIndex)
+ | hb_filter (l->feature_index_map)
+ | hb_map (l->feature_index_map)
+ ;
+
+ bool ret = bool (it);
+ out->featureIndex.serialize (c->serializer, l, it);
+ return_trace (ret);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c,
+ const Record_sanitize_closure_t * = nullptr) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && featureIndex.sanitize (c));
+ }
+
+ Offset16 lookupOrderZ; /* = Null (reserved for an offset to a
+ * reordering table) */
+ HBUINT16 reqFeatureIndex;/* Index of a feature required for this
+ * language system--if no required features
+ * = 0xFFFFu */
+ IndexArray featureIndex; /* Array of indices into the FeatureList */
+ public:
+ DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
+
+struct Script
+{
+ unsigned int get_lang_sys_count () const
+ { return langSys.len; }
+ const Tag& get_lang_sys_tag (unsigned int i) const
+ { return langSys.get_tag (i); }
+ unsigned int get_lang_sys_tags (unsigned int start_offset,
+ unsigned int *lang_sys_count /* IN/OUT */,
+ hb_tag_t *lang_sys_tags /* OUT */) const
+ { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
+ const LangSys& get_lang_sys (unsigned int i) const
+ {
+ if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
+ return this+langSys[i].offset;
+ }
+ bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
+ { return langSys.find_index (tag, index); }
+
+ bool has_default_lang_sys () const { return defaultLangSys != 0; }
+ const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
+
+ void prune_langsys (hb_prune_langsys_context_t *c,
+ unsigned script_index) const
+ {
+ if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
+ if (!c->visitScript ()) return;
+
+ if (!c->script_langsys_map->has (script_index))
+ {
+ 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 ();
+ if (has_default_lang_sys ())
+ {
+ //only collect features from non-redundant langsys
+ const LangSys& d = get_default_lang_sys ();
+ if (c->visitLangsys (d.get_feature_count ())) {
+ d.collect_features (c);
+ }
+
+ for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+ {
+ const LangSys& l = this+_.first.offset;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
+ if (l.compare (d, c->duplicate_feature_map)) continue;
+
+ l.collect_features (c);
+ c->script_langsys_map->get (script_index)->add (_.second);
+ }
+ }
+ else
+ {
+ for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+ {
+ const LangSys& l = this+_.first.offset;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
+ l.collect_features (c);
+ c->script_langsys_map->get (script_index)->add (_.second);
+ }
+ }
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l,
+ const Tag *tag) const
+ {
+ TRACE_SUBSET (this);
+ if (!l->visitScript ()) return_trace (false);
+ if (tag && !c->plan->layout_scripts->has (*tag))
+ return false;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ bool defaultLang = false;
+ if (has_default_lang_sys ())
+ {
+ c->serializer->push ();
+ const LangSys& ls = this+defaultLangSys;
+ bool ret = ls.subset (c, l);
+ if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
+ {
+ c->serializer->pop_discard ();
+ out->defaultLangSys = 0;
+ }
+ else
+ {
+ c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
+ defaultLang = true;
+ }
+ }
+
+ const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
+ if (active_langsys)
+ {
+ unsigned count = langSys.len;
+ + hb_zip (langSys, hb_range (count))
+ | hb_filter (active_langsys, hb_second)
+ | hb_map (hb_first)
+ | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
+ | hb_apply (subset_record_array (l, &(out->langSys), this))
+ ;
+ }
+
+ return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c,
+ const Record_sanitize_closure_t * = nullptr) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
+ }
+
+ protected:
+ Offset16To<LangSys>
+ defaultLangSys; /* Offset to DefaultLangSys table--from
+ * beginning of Script table--may be Null */
+ RecordArrayOf<LangSys>
+ langSys; /* Array of LangSysRecords--listed
+ * alphabetically by LangSysTag */
+ public:
+ DEFINE_SIZE_ARRAY_SIZED (4, langSys);
+};
+
+struct RecordListOfScript : RecordListOf<Script>
+{
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ unsigned count = this->len;
+ for (auto _ : + hb_zip (*this, hb_range (count)))
+ {
+ auto snap = c->serializer->snapshot ();
+ l->cur_script_index = _.second;
+ bool ret = _.first.subset (l, this);
+ if (!ret) c->serializer->revert (snap);
+ else out->len++;
+ }
+
+ return_trace (true);
+ }
+};
+
+typedef RecordListOfScript ScriptList;
+
+
+
struct LookupFlag : HBUINT16
{
enum Flags {
@@ -1346,7 +1313,7 @@ struct Lookup
if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
return_trace (false);
- if (unlikely (get_type () == TSubTable::Extension && subtables && !c->get_edit_count ()))
+ if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
{
/* The spec says all subtables of an Extension lookup should
* have the same type, which shall not be the Extension type
@@ -1366,7 +1333,7 @@ struct Lookup
return_trace (true);
}
- private:
+ protected:
HBUINT16 lookupType; /* Different enumerations for GSUB and GPOS */
HBUINT16 lookupFlag; /* Lookup qualifiers */
Array16Of<Offset16>
@@ -1378,10 +1345,11 @@ struct Lookup
DEFINE_SIZE_ARRAY (6, subTable);
};
-typedef List16OfOffset16To<Lookup> LookupList;
+template <typename Types>
+using LookupList = List16OfOffsetTo<Lookup, typename Types::HBUINT>;
-template <typename TLookup>
-struct LookupOffsetList : List16OfOffset16To<TLookup>
+template <typename TLookup, typename OffsetType>
+struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
{
bool subset (hb_subset_context_t *c,
hb_subset_layout_context_t *l) const
@@ -1411,470 +1379,6 @@ struct LookupOffsetList : List16OfOffset16To<TLookup>
* Coverage Table
*/
-struct CoverageFormat1
-{
- friend struct Coverage;
-
- private:
- unsigned int get_coverage (hb_codepoint_t glyph_id) const
- {
- unsigned int i;
- glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
- return i;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c, Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- return_trace (glyphArray.serialize (c, glyphs));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (glyphArray.sanitize (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- /* TODO Speed up, using hb_set_next() and bsearch()? */
- for (const auto& g : glyphArray.as_array ())
- if (glyphs->has (g))
- return true;
- return false;
- }
- bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
- { return glyphs->has (glyphArray[index]); }
-
- void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
- {
- unsigned count = glyphArray.len;
- for (unsigned i = 0; i < count; i++)
- if (glyphs->has (glyphArray[i]))
- intersect_glyphs->add (glyphArray[i]);
- }
-
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- { return glyphs->add_sorted_array (glyphArray.as_array ()); }
-
- public:
- /* Older compilers need this to be public. */
- struct iter_t
- {
- void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }
- void fini () {}
- bool more () const { return i < c->glyphArray.len; }
- void next () { i++; }
- hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
- bool operator != (const iter_t& o) const
- { return i != o.i; }
- iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
-
- private:
- const struct CoverageFormat1 *c;
- unsigned int i;
- };
- private:
-
- protected:
- HBUINT16 coverageFormat; /* Format identifier--format = 1 */
- SortedArray16Of<HBGlyphID16>
- glyphArray; /* Array of GlyphIDs--in numerical order */
- public:
- DEFINE_SIZE_ARRAY (4, glyphArray);
-};
-
-struct CoverageFormat2
-{
- friend struct Coverage;
-
- private:
- unsigned int get_coverage (hb_codepoint_t glyph_id) const
- {
- const RangeRecord &range = rangeRecord.bsearch (glyph_id);
- return likely (range.first <= range.last)
- ? (unsigned int) range.value + (glyph_id - range.first)
- : NOT_COVERED;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c, Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
-
- /* TODO(iter) Write more efficiently? */
-
- unsigned num_ranges = 0;
- hb_codepoint_t last = (hb_codepoint_t) -2;
- for (auto g: glyphs)
- {
- if (last + 1 != g)
- num_ranges++;
- last = g;
- }
-
- if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
- if (!num_ranges) return_trace (true);
-
- unsigned count = 0;
- unsigned range = (unsigned) -1;
- last = (hb_codepoint_t) -2;
- for (auto g: glyphs)
- {
- if (last + 1 != g)
- {
- range++;
- rangeRecord[range].first = g;
- rangeRecord[range].value = count;
- }
- rangeRecord[range].last = g;
- last = g;
- count++;
- }
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (rangeRecord.sanitize (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- return hb_any (+ hb_iter (rangeRecord.as_array ())
- | hb_map ([glyphs] (const RangeRecord &range) { return range.intersects (glyphs); }));
- }
- bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
- {
- auto cmp = [] (const void *pk, const void *pr) -> int
- {
- unsigned index = * (const unsigned *) pk;
- const RangeRecord &range = * (const RangeRecord *) pr;
- if (index < range.value) return -1;
- if (index > (unsigned int) range.value + (range.last - range.first)) return +1;
- return 0;
- };
-
- auto arr = rangeRecord.as_array ();
- unsigned idx;
- if (hb_bsearch_impl (&idx, index,
- arr.arrayZ, arr.length, sizeof (arr[0]),
- (int (*)(const void *_key, const void *_item)) cmp))
- return arr.arrayZ[idx].intersects (glyphs);
- return false;
- }
-
- void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
- {
- for (const auto& range : rangeRecord.as_array ())
- {
- if (!range.intersects (glyphs)) continue;
- unsigned last = range.last;
- for (hb_codepoint_t g = range.first - 1;
- glyphs->next (&g) && g <= last;)
- intersect_glyphs->add (g);
- }
- }
-
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- {
- unsigned int count = rangeRecord.len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
- return false;
- return true;
- }
-
- public:
- /* Older compilers need this to be public. */
- struct iter_t
- {
- void init (const CoverageFormat2 &c_)
- {
- c = &c_;
- coverage = 0;
- i = 0;
- j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
- if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
- {
- /* Broken table. Skip. */
- i = c->rangeRecord.len;
- }
- }
- void fini () {}
- bool more () const { return i < c->rangeRecord.len; }
- void next ()
- {
- if (j >= c->rangeRecord[i].last)
- {
- i++;
- if (more ())
- {
- unsigned int old = coverage;
- j = c->rangeRecord[i].first;
- coverage = c->rangeRecord[i].value;
- if (unlikely (coverage != old + 1))
- {
- /* Broken table. Skip. Important to avoid DoS.
- * Also, our callers depend on coverage being
- * consecutive and monotonically increasing,
- * ie. iota(). */
- i = c->rangeRecord.len;
- return;
- }
- }
- else
- j = 0;
- return;
- }
- coverage++;
- j++;
- }
- hb_codepoint_t get_glyph () const { return j; }
- bool operator != (const iter_t& o) const
- { return i != o.i || j != o.j; }
- iter_t __end__ () const
- {
- iter_t it;
- it.init (*c);
- it.i = c->rangeRecord.len;
- it.j = 0;
- return it;
- }
-
- private:
- const struct CoverageFormat2 *c;
- unsigned int i, coverage;
- hb_codepoint_t j;
- };
- private:
-
- protected:
- HBUINT16 coverageFormat; /* Format identifier--format = 2 */
- SortedArray16Of<RangeRecord>
- rangeRecord; /* Array of glyph ranges--ordered by
- * Start GlyphID. rangeCount entries
- * long */
- public:
- DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct Coverage
-{
- /* Has interface. */
- static constexpr unsigned SENTINEL = NOT_COVERED;
- typedef unsigned int value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
- /* Predicate. */
- bool operator () (hb_codepoint_t k) const { return has (k); }
-
- unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
- unsigned int get_coverage (hb_codepoint_t glyph_id) const
- {
- switch (u.format) {
- case 1: return u.format1.get_coverage (glyph_id);
- case 2: return u.format2.get_coverage (glyph_id);
- default:return NOT_COVERED;
- }
- }
-
- template <typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c, Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
-
- unsigned count = 0;
- unsigned num_ranges = 0;
- hb_codepoint_t last = (hb_codepoint_t) -2;
- for (auto g: glyphs)
- {
- if (last + 1 != g)
- num_ranges++;
- last = g;
- count++;
- }
- u.format = count <= num_ranges * 3 ? 1 : 2;
-
- switch (u.format)
- {
- case 1: return_trace (u.format1.serialize (c, glyphs));
- case 2: return_trace (u.format2.serialize (c, glyphs));
- default:return_trace (false);
- }
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto it =
- + iter ()
- | hb_filter (c->plan->glyph_map_gsub)
- | hb_map_retains_sorting (c->plan->glyph_map_gsub)
- ;
-
- // Cache the iterator result as it will be iterated multiple times
- // by the serialize code below.
- hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
- Coverage_serialize (c->serializer, glyphs.iter ());
- return_trace (bool (glyphs));
- }
-
- 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));
- default:return_trace (true);
- }
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- switch (u.format)
- {
- case 1: return u.format1.intersects (glyphs);
- case 2: return u.format2.intersects (glyphs);
- default:return false;
- }
- }
- bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
- {
- switch (u.format)
- {
- case 1: return u.format1.intersects_coverage (glyphs, index);
- case 2: return u.format2.intersects_coverage (glyphs, index);
- default:return false;
- }
- }
-
- /* Might return false if array looks unsorted.
- * Used for faster rejection of corrupt data. */
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- {
- switch (u.format)
- {
- case 1: return u.format1.collect_coverage (glyphs);
- case 2: return u.format2.collect_coverage (glyphs);
- default:return false;
- }
- }
-
- void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
- {
- switch (u.format)
- {
- case 1: return u.format1.intersected_coverage_glyphs (glyphs, intersect_glyphs);
- case 2: return u.format2.intersected_coverage_glyphs (glyphs, intersect_glyphs);
- default:return ;
- }
- }
-
- struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
- {
- static constexpr bool is_sorted_iterator = true;
- iter_t (const Coverage &c_ = Null (Coverage))
- {
- memset (this, 0, sizeof (*this));
- format = c_.u.format;
- switch (format)
- {
- case 1: u.format1.init (c_.u.format1); return;
- case 2: u.format2.init (c_.u.format2); return;
- default: return;
- }
- }
- bool __more__ () const
- {
- switch (format)
- {
- case 1: return u.format1.more ();
- case 2: return u.format2.more ();
- default:return false;
- }
- }
- void __next__ ()
- {
- switch (format)
- {
- case 1: u.format1.next (); break;
- case 2: u.format2.next (); break;
- default: break;
- }
- }
- typedef hb_codepoint_t __item_t__;
- __item_t__ __item__ () const { return get_glyph (); }
-
- hb_codepoint_t get_glyph () const
- {
- switch (format)
- {
- case 1: return u.format1.get_glyph ();
- case 2: return u.format2.get_glyph ();
- default:return 0;
- }
- }
- bool operator != (const iter_t& o) const
- {
- if (unlikely (format != o.format)) return true;
- switch (format)
- {
- case 1: return u.format1 != o.u.format1;
- case 2: return u.format2 != o.u.format2;
- default:return false;
- }
- }
- iter_t __end__ () const
- {
- iter_t it = {};
- it.format = format;
- switch (format)
- {
- case 1: it.u.format1 = u.format1.__end__ (); break;
- case 2: it.u.format2 = u.format2.__end__ (); break;
- default: break;
- }
- return it;
- }
-
- private:
- unsigned int format;
- union {
- CoverageFormat2::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
- CoverageFormat1::iter_t format1;
- } u;
- };
- iter_t iter () const { return iter_t (*this); }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- CoverageFormat1 format1;
- CoverageFormat2 format2;
- } u;
- public:
- DEFINE_SIZE_UNION (2, format);
-};
-
-template<typename Iterator>
-static inline void
-Coverage_serialize (hb_serialize_context_t *c,
- Iterator it)
-{ c->start_embed<Coverage> ()->serialize (c, it); }
static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
const hb_set_t &klasses,
@@ -1916,7 +1420,8 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
* Class Definition Table
*/
-struct ClassDefFormat1
+template <typename Types>
+struct ClassDefFormat1_3
{
friend struct ClassDef;
@@ -1927,7 +1432,7 @@ struct ClassDefFormat1
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c,
Iterator it)
{
@@ -2004,6 +1509,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
{
@@ -2119,14 +1626,16 @@ struct ClassDefFormat1
protected:
HBUINT16 classFormat; /* Format identifier--format = 1 */
- HBGlyphID16 startGlyph; /* First GlyphID of the classValueArray */
- Array16Of<HBUINT16>
+ typename Types::HBGlyphID
+ startGlyph; /* First GlyphID of the classValueArray */
+ typename Types::template ArrayOf<HBUINT16>
classValue; /* Array of Class Values--one per GlyphID */
public:
- DEFINE_SIZE_ARRAY (6, classValue);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, classValue);
};
-struct ClassDefFormat2
+template <typename Types>
+struct ClassDefFormat2_4
{
friend struct ClassDef;
@@ -2137,7 +1646,7 @@ struct ClassDefFormat2
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c,
Iterator it)
{
@@ -2155,12 +1664,12 @@ struct ClassDefFormat2
hb_codepoint_t prev_gid = (*it).first;
unsigned prev_klass = (*it).second;
- RangeRecord range_rec;
+ RangeRecord<Types> range_rec;
range_rec.first = prev_gid;
range_rec.last = prev_gid;
range_rec.value = prev_klass;
- RangeRecord *record = c->copy (range_rec);
+ auto *record = c->copy (range_rec);
if (unlikely (!record)) return_trace (false);
for (const auto gid_klass_pair : + (++it))
@@ -2203,13 +1712,14 @@ struct ClassDefFormat2
hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
+ unsigned num_source_glyphs = c->plan->source->get_num_glyphs ();
unsigned count = rangeRecord.len;
for (unsigned i = 0; i < count; i++)
{
unsigned klass = rangeRecord[i].value;
if (!klass) continue;
hb_codepoint_t start = rangeRecord[i].first;
- hb_codepoint_t end = rangeRecord[i].last + 1;
+ hb_codepoint_t end = hb_min (rangeRecord[i].last + 1, num_source_glyphs);
for (hb_codepoint_t g = start; g < end; g++)
{
hb_codepoint_t new_gid = glyph_map[g];
@@ -2240,6 +1750,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
{
@@ -2271,7 +1783,7 @@ struct ClassDefFormat2
for (unsigned int i = 0; i < count; i++)
{
const auto& range = rangeRecord[i];
- if (range.intersects (glyphs) && range.value)
+ if (range.intersects (*glyphs) && range.value)
return true;
}
return false;
@@ -2295,11 +1807,8 @@ struct ClassDefFormat2
return true;
/* Fall through. */
}
- /* TODO Speed up, using set overlap first? */
- /* TODO(iter) Rewrite as dagger. */
- const RangeRecord *arr = rangeRecord.arrayZ;
- for (unsigned int i = 0; i < count; i++)
- if (arr[i].value == klass && arr[i].intersects (glyphs))
+ for (const auto &range : rangeRecord)
+ if (range.value == klass && range.intersects (*glyphs))
return true;
return false;
}
@@ -2373,18 +1882,18 @@ struct ClassDefFormat2
if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
intersect_classes->add (0);
- for (const RangeRecord& record : rangeRecord.iter ())
- if (record.intersects (glyphs))
+ for (const auto& record : rangeRecord.iter ())
+ if (record.intersects (*glyphs))
intersect_classes->add (record.value);
}
protected:
HBUINT16 classFormat; /* Format identifier--format = 2 */
- SortedArray16Of<RangeRecord>
+ typename Types::template SortedArrayOf<RangeRecord<Types>>
rangeRecord; /* Array of glyph ranges--ordered by
* Start GlyphID */
public:
- DEFINE_SIZE_ARRAY (4, rangeRecord);
+ DEFINE_SIZE_ARRAY (2 + Types::size, rangeRecord);
};
struct ClassDef
@@ -2403,12 +1912,16 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.get_class (glyph_id);
case 2: return u.format2.get_class (glyph_id);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.get_class (glyph_id);
+ case 4: return u.format4.get_class (glyph_id);
+#endif
default:return 0;
}
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero)
{
TRACE_SERIALIZE (this);
@@ -2417,10 +1930,11 @@ struct ClassDef
auto it = + it_with_class_zero | hb_filter (hb_second);
unsigned format = 2;
+ hb_codepoint_t glyph_max = 0;
if (likely (it))
{
hb_codepoint_t glyph_min = (*it).first;
- hb_codepoint_t glyph_max = glyph_min;
+ glyph_max = glyph_min;
unsigned num_glyphs = 0;
unsigned num_ranges = 1;
@@ -2445,12 +1959,22 @@ struct ClassDef
if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3)
format = 1;
}
+
+#ifndef HB_NO_BEYOND_64K
+ if (glyph_max > 0xFFFFu)
+ format += 2;
+#endif
+
u.format = format;
switch (u.format)
{
case 1: return_trace (u.format1.serialize (c, it));
case 2: return_trace (u.format2.serialize (c, it));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.serialize (c, it));
+ case 4: return_trace (u.format4.serialize (c, it));
+#endif
default:return_trace (false);
}
}
@@ -2465,6 +1989,10 @@ struct ClassDef
switch (u.format) {
case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+ case 4: return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+#endif
default:return_trace (false);
}
}
@@ -2476,10 +2004,27 @@ struct ClassDef
switch (u.format) {
case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.sanitize (c));
+ case 4: return_trace (u.format4.sanitize (c));
+#endif
default:return_trace (true);
}
}
+ unsigned cost () const
+ {
+ switch (u.format) {
+ case 1: return u.format1.cost ();
+ case 2: return u.format2.cost ();
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.cost ();
+ case 4: return u.format4.cost ();
+#endif
+ default:return 0u;
+ }
+ }
+
/* Might return false if array looks unsorted.
* Used for faster rejection of corrupt data. */
template <typename set_t>
@@ -2488,6 +2033,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.collect_coverage (glyphs);
case 2: return u.format2.collect_coverage (glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.collect_coverage (glyphs);
+ case 4: return u.format4.collect_coverage (glyphs);
+#endif
default:return false;
}
}
@@ -2500,6 +2049,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.collect_class (glyphs, klass);
case 2: return u.format2.collect_class (glyphs, klass);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.collect_class (glyphs, klass);
+ case 4: return u.format4.collect_class (glyphs, klass);
+#endif
default:return false;
}
}
@@ -2509,6 +2062,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersects (glyphs);
case 2: return u.format2.intersects (glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersects (glyphs);
+ case 4: return u.format4.intersects (glyphs);
+#endif
default:return false;
}
}
@@ -2517,6 +2074,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersects_class (glyphs, klass);
case 2: return u.format2.intersects_class (glyphs, klass);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersects_class (glyphs, klass);
+ case 4: return u.format4.intersects_class (glyphs, klass);
+#endif
default:return false;
}
}
@@ -2526,6 +2087,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+ case 4: return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+#endif
default:return;
}
}
@@ -2535,6 +2100,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersected_classes (glyphs, intersect_classes);
case 2: return u.format2.intersected_classes (glyphs, intersect_classes);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersected_classes (glyphs, intersect_classes);
+ case 4: return u.format4.intersected_classes (glyphs, intersect_classes);
+#endif
default:return;
}
}
@@ -2542,9 +2111,13 @@ struct ClassDef
protected:
union {
- HBUINT16 format; /* Format identifier */
- ClassDefFormat1 format1;
- ClassDefFormat2 format2;
+ HBUINT16 format; /* Format identifier */
+ ClassDefFormat1_3<SmallTypes> format1;
+ ClassDefFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BEYOND_64K
+ ClassDefFormat1_3<MediumTypes>format3;
+ ClassDefFormat2_4<MediumTypes>format4;
+#endif
} u;
public:
DEFINE_SIZE_UNION (2, format);
@@ -2601,14 +2174,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 +2204,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 +2261,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 +2271,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 +2289,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 +2328,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 +2343,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 +2442,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 +2499,31 @@ struct VarData
struct VariationStore
{
+ using cache_t = VarRegionList::cache_t;
+
+ cache_t *create_cache () const
+ {
+#ifdef HB_NO_VAR
+ return nullptr;
+#endif
+ 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 +2534,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
@@ -2889,6 +2566,10 @@ struct VariationStore
const hb_array_t <hb_inc_bimap_t> &inner_maps)
{
TRACE_SERIALIZE (this);
+#ifdef HB_NO_VAR
+ return_trace (false);
+#endif
+
if (unlikely (!c->extend_min (this))) return_trace (false);
unsigned int set_count = 0;
@@ -2940,6 +2621,9 @@ struct VariationStore
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
+#ifdef HB_NO_VAR
+ return_trace (false);
+#endif
VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> ();
if (unlikely (!varstore_prime)) return_trace (false);
@@ -2967,7 +2651,12 @@ struct VariationStore
}
unsigned int get_region_index_count (unsigned int major) const
- { return (this+dataSets[major]).get_region_index_count (); }
+ {
+#ifdef HB_NO_VAR
+ return 0;
+#endif
+ return (this+dataSets[major]).get_region_index_count ();
+ }
void get_region_scalars (unsigned int major,
const int *coords, unsigned int coord_count,
@@ -2985,7 +2674,13 @@ struct VariationStore
&scalars[0], num_scalars);
}
- unsigned int get_sub_table_count () const { return dataSets.len; }
+ unsigned int get_sub_table_count () const
+ {
+#ifdef HB_NO_VAR
+ return 0;
+#endif
+ return dataSets.len;
+ }
protected:
HBUINT16 format;
@@ -2995,6 +2690,8 @@ struct VariationStore
DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
};
+#undef REGION_CACHE_ITEM_CACHE_INVALID
+
/*
* Feature Variations
*/
@@ -3462,11 +3159,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 +3201,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 +3228,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 +3240,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 +3258,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..5bc26d9182 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
@@ -510,6 +510,101 @@ struct MarkGlyphSets
*/
+template <typename Types>
+struct GDEFVersion1_2
+{
+ friend struct GDEF;
+
+ protected:
+ FixedVersion<>version; /* Version of the GDEF table--currently
+ * 0x00010003u */
+ typename Types::template OffsetTo<ClassDef>
+ glyphClassDef; /* Offset to class definition table
+ * for glyph type--from beginning of
+ * GDEF header (may be Null) */
+ typename Types::template OffsetTo<AttachList>
+ attachList; /* Offset to list of glyphs with
+ * attachment points--from beginning
+ * of GDEF header (may be Null) */
+ typename Types::template OffsetTo<LigCaretList>
+ ligCaretList; /* Offset to list of positioning points
+ * for ligature carets--from beginning
+ * of GDEF header (may be Null) */
+ typename Types::template OffsetTo<ClassDef>
+ markAttachClassDef; /* Offset to class definition table for
+ * mark attachment type--from beginning
+ * of GDEF header (may be Null) */
+ typename Types::template OffsetTo<MarkGlyphSets>
+ markGlyphSetsDef; /* Offset to the table of mark set
+ * definitions--from beginning of GDEF
+ * header (may be NULL). Introduced
+ * in version 0x00010002. */
+ Offset32To<VariationStore>
+ varStore; /* Offset to the table of Item Variation
+ * Store--from beginning of GDEF
+ * header (may be NULL). Introduced
+ * in version 0x00010003. */
+ public:
+ DEFINE_SIZE_MIN (4 + 4 * Types::size);
+
+ unsigned int get_size () const
+ {
+ return min_size +
+ (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
+ (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (version.sanitize (c) &&
+ glyphClassDef.sanitize (c, this) &&
+ attachList.sanitize (c, this) &&
+ ligCaretList.sanitize (c, this) &&
+ markAttachClassDef.sanitize (c, this) &&
+ (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
+ (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
+ bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
+ bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
+ bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
+
+ bool subset_markglyphsetsdef = false;
+ if (version.to_int () >= 0x00010002u)
+ {
+ subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
+ }
+
+ bool subset_varstore = false;
+ if (version.to_int () >= 0x00010003u)
+ {
+ subset_varstore = out->varStore.serialize_subset (c, varStore, this);
+ }
+
+ if (subset_varstore)
+ {
+ out->version.minor = 3;
+ } else if (subset_markglyphsetsdef) {
+ out->version.minor = 2;
+ } else {
+ out->version.minor = 0;
+ }
+
+ return_trace (subset_glyphclassdef || subset_attachlist ||
+ subset_ligcaretlist || subset_markattachclassdef ||
+ (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||
+ (out->version.to_int () >= 0x00010003u && subset_varstore));
+ }
+};
+
struct GDEF
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
@@ -522,42 +617,190 @@ struct GDEF
ComponentGlyph = 4
};
- bool has_data () const { return version.to_int (); }
- bool has_glyph_classes () const { return glyphClassDef != 0; }
+ unsigned int get_size () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.get_size ();
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.get_size ();
+#endif
+ default: return u.version.static_size;
+ }
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!u.version.sanitize (c))) return_trace (false);
+ switch (u.version.major) {
+ case 1: return_trace (u.version1.sanitize (c));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return_trace (u.version2.sanitize (c));
+#endif
+ default: return_trace (true);
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.subset (c);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.subset (c);
+#endif
+ default: return false;
+ }
+ }
+
+ bool has_glyph_classes () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.glyphClassDef != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.glyphClassDef != 0;
+#endif
+ default: return false;
+ }
+ }
+ const ClassDef &get_glyph_class_def () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.glyphClassDef;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.glyphClassDef;
+#endif
+ default: return Null(ClassDef);
+ }
+ }
+ bool has_attach_list () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.attachList != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.attachList != 0;
+#endif
+ default: return false;
+ }
+ }
+ const AttachList &get_attach_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.attachList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.attachList;
+#endif
+ default: return Null(AttachList);
+ }
+ }
+ bool has_lig_carets () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.ligCaretList != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.ligCaretList != 0;
+#endif
+ default: return false;
+ }
+ }
+ const LigCaretList &get_lig_caret_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.ligCaretList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.ligCaretList;
+#endif
+ default: return Null(LigCaretList);
+ }
+ }
+ bool has_mark_attachment_types () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.markAttachClassDef != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.markAttachClassDef != 0;
+#endif
+ default: return false;
+ }
+ }
+ const ClassDef &get_mark_attach_class_def () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.markAttachClassDef;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.markAttachClassDef;
+#endif
+ default: return Null(ClassDef);
+ }
+ }
+ bool has_mark_glyph_sets () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.markGlyphSetsDef != 0;
+#endif
+ default: return false;
+ }
+ }
+ const MarkGlyphSets &get_mark_glyph_sets () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.markGlyphSetsDef;
+#endif
+ default: return Null(MarkGlyphSets);
+ }
+ }
+ bool has_var_store () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.varStore != 0;
+#endif
+ default: return false;
+ }
+ }
+ const VariationStore &get_var_store () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.varStore;
+#endif
+ default: return Null(VariationStore);
+ }
+ }
+
+
+ bool has_data () const { return u.version.to_int (); }
unsigned int get_glyph_class (hb_codepoint_t glyph) const
- { return (this+glyphClassDef).get_class (glyph); }
+ { return get_glyph_class_def ().get_class (glyph); }
void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
- { (this+glyphClassDef).collect_class (glyphs, klass); }
+ { get_glyph_class_def ().collect_class (glyphs, klass); }
- bool has_mark_attachment_types () const { return markAttachClassDef != 0; }
unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
- { return (this+markAttachClassDef).get_class (glyph); }
+ { return get_mark_attach_class_def ().get_class (glyph); }
- bool has_attach_points () const { return attachList != 0; }
unsigned int get_attach_points (hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *point_count /* IN/OUT */,
unsigned int *point_array /* OUT */) const
- { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
+ { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); }
- bool has_lig_carets () const { return ligCaretList != 0; }
unsigned int get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
hb_position_t *caret_array /* OUT */) const
- { return (this+ligCaretList).get_lig_carets (font,
- direction, glyph_id, get_var_store(),
- start_offset, caret_count, caret_array); }
+ { return get_lig_caret_list ().get_lig_carets (font,
+ direction, glyph_id, get_var_store(),
+ start_offset, caret_count, caret_array); }
- bool has_mark_sets () const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
- { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
-
- bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; }
- const VariationStore &get_var_store () const
- { return version.to_int () >= 0x00010003u ? this+varStore : Null (VariationStore); }
+ { return get_mark_glyph_sets ().covers (set_index, glyph_id); }
/* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
* glyph class and other bits, and high 8-bit the mark attachment type (if any).
@@ -571,7 +814,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:
@@ -599,20 +842,13 @@ struct GDEF
hb_blob_ptr_t<GDEF> table;
};
- unsigned int get_size () const
- {
- return min_size +
- (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
- (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
- }
-
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- { (this+ligCaretList).collect_variation_indices (c); }
+ { get_lig_caret_list ().collect_variation_indices (c); }
void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
hb_map_t *layout_variation_idx_map /* OUT */) const
{
- if (version.to_int () < 0x00010003u || !varStore) return;
+ if (!has_var_store ()) return;
if (layout_variation_indices->is_empty ()) return;
unsigned new_major = 0, new_minor = 0;
@@ -620,7 +856,7 @@ struct GDEF
for (unsigned idx : layout_variation_indices->iter ())
{
uint16_t major = idx >> 16;
- if (major >= (this+varStore).get_sub_table_count ()) break;
+ if (major >= get_var_store ().get_sub_table_count ()) break;
if (major != last_major)
{
new_minor = 0;
@@ -634,84 +870,16 @@ struct GDEF
}
}
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (*this);
- if (unlikely (!out)) return_trace (false);
-
- bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
- bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
- bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
- bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
-
- bool subset_markglyphsetsdef = true;
- if (version.to_int () >= 0x00010002u)
- {
- subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
- if (!subset_markglyphsetsdef &&
- version.to_int () == 0x00010002u)
- out->version.minor = 0;
- }
-
- bool subset_varstore = true;
- if (version.to_int () >= 0x00010003u)
- {
- subset_varstore = out->varStore.serialize_subset (c, varStore, this);
- if (!subset_varstore && version.to_int () == 0x00010003u)
- out->version.minor = 2;
- }
-
- return_trace (subset_glyphclassdef || subset_attachlist ||
- subset_ligcaretlist || subset_markattachclassdef ||
- (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||
- (out->version.to_int () >= 0x00010003u && subset_varstore));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (version.sanitize (c) &&
- likely (version.major == 1) &&
- glyphClassDef.sanitize (c, this) &&
- attachList.sanitize (c, this) &&
- ligCaretList.sanitize (c, this) &&
- markAttachClassDef.sanitize (c, this) &&
- (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
- (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
- }
-
protected:
- FixedVersion<>version; /* Version of the GDEF table--currently
- * 0x00010003u */
- Offset16To<ClassDef>
- glyphClassDef; /* Offset to class definition table
- * for glyph type--from beginning of
- * GDEF header (may be Null) */
- Offset16To<AttachList>
- attachList; /* Offset to list of glyphs with
- * attachment points--from beginning
- * of GDEF header (may be Null) */
- Offset16To<LigCaretList>
- ligCaretList; /* Offset to list of positioning points
- * for ligature carets--from beginning
- * of GDEF header (may be Null) */
- Offset16To<ClassDef>
- markAttachClassDef; /* Offset to class definition table for
- * mark attachment type--from beginning
- * of GDEF header (may be Null) */
- Offset16To<MarkGlyphSets>
- markGlyphSetsDef; /* Offset to the table of mark set
- * definitions--from beginning of GDEF
- * header (may be NULL). Introduced
- * in version 0x00010002. */
- Offset32To<VariationStore>
- varStore; /* Offset to the table of Item Variation
- * Store--from beginning of GDEF
- * header (may be NULL). Introduced
- * in version 0x00010003. */
+ union {
+ FixedVersion<> version; /* Version identifier */
+ GDEFVersion1_2<SmallTypes> version1;
+#ifndef HB_NO_BEYOND_64K
+ GDEFVersion1_2<MediumTypes> version2;
+#endif
+ } u;
public:
- DEFINE_SIZE_MIN (12);
+ DEFINE_SIZE_MIN (4);
};
struct GDEF_accelerator_t : GDEF::accelerator_t {
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
index 2f9186a2a7..8fe987fc50 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/GPOS.hh"
namespace OT {
+namespace Layout {
+namespace GPOS_impl {
-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) {}
-};
-
-
+// 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,8 @@ template <typename context_t>
}
#endif
-
+} /* namespace GPOS_impl */
+} /* namespace Layout */
} /* 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..50301ff1d9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -32,9 +32,8 @@
#include "OT/Layout/GSUB/GSUB.hh"
namespace OT {
-
-using Layout::GSUB::SubstLookup;
-using Layout::GSUB::ExtensionSubst;
+namespace Layout {
+namespace GSUB_impl {
// TODO(garretrieger): Move into the new layout directory.
/* Out-of-class implementation for methods recursing */
@@ -59,13 +58,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;
@@ -79,7 +81,8 @@ template <typename context_t>
}
#endif
-
+} /* namespace GSUB_impl */
+} /* namespace Layout */
} /* namespace OT */
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
index c9750ff63b..c77ec12fbe 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));
@@ -154,7 +150,7 @@ struct hb_closure_context_t :
bool pop_cur_done_glyphs ()
{
- if (active_glyphs_stack.length < 1)
+ if (!active_glyphs_stack)
return false;
active_glyphs_stack.pop ();
@@ -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, unsigned 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,15 +427,15 @@ struct hb_ot_apply_context_t :
MATCH_MAYBE
};
- may_match_t may_match (const hb_glyph_info_t &info,
- const HBUINT16 *glyph_data) const
+ may_match_t may_match (hb_glyph_info_t &info,
+ hb_codepoint_t glyph_data) const
{
if (!(info.mask & mask) ||
(syllable && syllable != info.syllable ()))
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;
}
@@ -483,7 +476,10 @@ struct hb_ot_apply_context_t :
void init (hb_ot_apply_context_t *c_, bool context_match = false)
{
c = c_;
- match_glyph_data = nullptr;
+ match_glyph_data16 = nullptr;
+#ifndef HB_NO_BEYOND_64K
+ match_glyph_data24 = nullptr;
+#endif
matcher.set_match_func (nullptr, nullptr);
matcher.set_lookup_props (c->lookup_props);
/* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
@@ -498,12 +494,24 @@ struct hb_ot_apply_context_t :
matcher.set_lookup_props (lookup_props);
}
void set_match_func (matcher_t::match_func_t match_func_,
- const void *match_data_,
- const HBUINT16 glyph_data[])
+ const void *match_data_)
{
matcher.set_match_func (match_func_, match_data_);
- match_glyph_data = glyph_data;
}
+ void set_glyph_data (const HBUINT16 glyph_data[])
+ {
+ match_glyph_data16 = glyph_data;
+#ifndef HB_NO_BEYOND_64K
+ match_glyph_data24 = nullptr;
+#endif
+ }
+#ifndef HB_NO_BEYOND_64K
+ void set_glyph_data (const HBUINT24 glyph_data[])
+ {
+ match_glyph_data16 = nullptr;
+ match_glyph_data24 = glyph_data;
+ }
+#endif
void reset (unsigned int start_index_,
unsigned int num_items_)
@@ -517,7 +525,7 @@ struct hb_ot_apply_context_t :
void reject ()
{
num_items++;
- if (match_glyph_data) match_glyph_data--;
+ backup_glyph_data ();
}
matcher_t::may_skip_t
@@ -530,19 +538,19 @@ 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))
continue;
- matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+ matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
if (match == matcher_t::MATCH_YES ||
(match == matcher_t::MATCH_MAYBE &&
skip == matcher_t::SKIP_NO))
{
num_items--;
- if (match_glyph_data) match_glyph_data++;
+ advance_glyph_data ();
return true;
}
@@ -563,19 +571,19 @@ 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))
continue;
- matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+ matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
if (match == matcher_t::MATCH_YES ||
(match == matcher_t::MATCH_MAYBE &&
skip == matcher_t::SKIP_NO))
{
num_items--;
- if (match_glyph_data) match_glyph_data++;
+ advance_glyph_data ();
return true;
}
@@ -591,11 +599,43 @@ struct hb_ot_apply_context_t :
return false;
}
+ hb_codepoint_t
+ get_glyph_data ()
+ {
+ if (match_glyph_data16) return *match_glyph_data16;
+#ifndef HB_NO_BEYOND_64K
+ else
+ if (match_glyph_data24) return *match_glyph_data24;
+#endif
+ return 0;
+ }
+ void
+ advance_glyph_data ()
+ {
+ if (match_glyph_data16) match_glyph_data16++;
+#ifndef HB_NO_BEYOND_64K
+ else
+ if (match_glyph_data24) match_glyph_data24++;
+#endif
+ }
+ void
+ backup_glyph_data ()
+ {
+ if (match_glyph_data16) match_glyph_data16--;
+#ifndef HB_NO_BEYOND_64K
+ else
+ if (match_glyph_data24) match_glyph_data24--;
+#endif
+ }
+
unsigned int idx;
protected:
hb_ot_apply_context_t *c;
matcher_t matcher;
- const HBUINT16 *match_glyph_data;
+ const HBUINT16 *match_glyph_data16;
+#ifndef HB_NO_BEYOND_64K
+ const HBUINT24 *match_glyph_data24;
+#endif
unsigned int num_items;
unsigned int end;
@@ -611,7 +651,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 +664,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 +700,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 +783,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 +840,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 +850,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 +905,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 bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned 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 void (*collect_glyphs_func_t) (hb_set_t *glyphs, unsigned value, const void *data);
+typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
struct ContextClosureFuncs
{
@@ -863,20 +1006,25 @@ 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)
+static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED)
{
return glyphs->has (value);
}
-static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
return class_def.intersects_class (glyphs, value);
}
-static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data)
{
- const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
+ Offset16To<Coverage> coverage;
+ coverage = value;
return (data+coverage).intersects (glyphs);
}
@@ -895,68 +1043,84 @@ static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const vo
{
Offset16To<Coverage> coverage;
coverage = value;
- (data+coverage).intersected_coverage_glyphs (glyphs, intersected_glyphs);
+ (data+coverage).intersect_set (*glyphs, *intersected_glyphs);
}
+template <typename HBUINT>
static inline bool array_is_subset_of (const hb_set_t *glyphs,
unsigned int count,
- const HBUINT16 values[],
+ const HBUINT values[],
intersects_func_t intersects_func,
const void *intersects_data)
{
- for (const HBUINT16 &_ : + hb_iter (values, count))
+ for (const auto &_ : + hb_iter (values, count))
if (!intersects_func (glyphs, _, intersects_data)) return false;
return true;
}
-static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+static inline void collect_glyph (hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED)
{
glyphs->add (value);
}
-static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline void collect_class (hb_set_t *glyphs, unsigned value, const void *data)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
class_def.collect_class (glyphs, value);
}
-static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline void collect_coverage (hb_set_t *glyphs, unsigned value, const void *data)
{
- const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
+ Offset16To<Coverage> coverage;
+ coverage = value;
(data+coverage).collect_coverage (glyphs);
}
+template <typename HBUINT>
static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
hb_set_t *glyphs,
unsigned int count,
- const HBUINT16 values[],
+ const HBUINT values[],
collect_glyphs_func_t collect_func,
const void *collect_data)
{
return
+ hb_iter (values, count)
- | hb_apply ([&] (const HBUINT16 &_) { collect_func (glyphs, _, collect_data); })
+ | hb_apply ([&] (const HBUINT &_) { collect_func (glyphs, _, collect_data); })
;
}
-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, unsigned 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, unsigned 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, unsigned value, const void *data)
{
- const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
- return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
+ 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, unsigned value, const void *data)
+{
+ Offset16To<Coverage> coverage;
+ coverage = value;
+ return (data+coverage).get_coverage (info.codepoint) != NOT_COVERED;
}
+template <typename HBUINT>
static inline bool would_match_input (hb_would_apply_context_t *c,
unsigned int count, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
match_func_t match_func,
const void *match_data)
{
@@ -964,14 +1128,19 @@ 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;
}
+template <typename HBUINT>
static inline bool match_input (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
match_func_t match_func,
const void *match_data,
unsigned int *end_position,
@@ -986,7 +1155,8 @@ static inline bool match_input (hb_ot_apply_context_t *c,
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, count - 1);
- skippy_iter.set_match_func (match_func, match_data, input);
+ skippy_iter.set_match_func (match_func, match_data);
+ skippy_iter.set_glyph_data (input);
/*
* This is perhaps the trickiest part of OpenType... Remarks:
@@ -1207,9 +1377,10 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
return_trace (true);
}
+template <typename HBUINT>
static inline bool match_backtrack (hb_ot_apply_context_t *c,
unsigned int count,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
match_func_t match_func,
const void *match_data,
unsigned int *match_start)
@@ -1218,7 +1389,8 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
skippy_iter.reset (c->buffer->backtrack_len (), count);
- skippy_iter.set_match_func (match_func, match_data, backtrack);
+ skippy_iter.set_match_func (match_func, match_data);
+ skippy_iter.set_glyph_data (backtrack);
for (unsigned int i = 0; i < count; i++)
{
@@ -1234,9 +1406,10 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
return_trace (true);
}
+template <typename HBUINT>
static inline bool match_lookahead (hb_ot_apply_context_t *c,
unsigned int count,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
match_func_t match_func,
const void *match_data,
unsigned int start_index,
@@ -1246,7 +1419,8 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
skippy_iter.reset (start_index - 1, count);
- skippy_iter.set_match_func (match_func, match_data, lookahead);
+ skippy_iter.set_match_func (match_func, match_data);
+ skippy_iter.set_glyph_data (lookahead);
for (unsigned int i = 0; i < count; i++)
{
@@ -1310,8 +1484,9 @@ static unsigned serialize_lookuprecord_array (hb_serialize_context_t *c,
enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 };
+template <typename HBUINT>
static void context_closure_recurse_lookups (hb_closure_context_t *c,
- unsigned inputCount, const HBUINT16 input[],
+ unsigned inputCount, const HBUINT input[],
unsigned lookupCount,
const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */,
unsigned value,
@@ -1427,9 +1602,28 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
if (unlikely (buffer->max_ops <= 0))
break;
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ if (buffer->have_output)
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "recursing to lookup %u at %d",
+ (unsigned) lookupRecord[i].lookupListIndex,
+ buffer->idx);
+ }
+
if (!c->recurse (lookupRecord[i].lookupListIndex))
continue;
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ if (buffer->have_output)
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "recursed to lookup %u",
+ (unsigned) lookupRecord[i].lookupListIndex);
+ }
+
unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
int delta = new_len - orig_len;
@@ -1530,9 +1724,10 @@ struct ContextApplyLookupContext
const void *match_data;
};
+template <typename HBUINT>
static inline bool context_intersects (const hb_set_t *glyphs,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
ContextClosureLookupContext &lookup_context)
{
return array_is_subset_of (glyphs,
@@ -1540,9 +1735,10 @@ static inline bool context_intersects (const hb_set_t *glyphs,
lookup_context.funcs.intersects, lookup_context.intersects_data);
}
+template <typename HBUINT>
static inline void context_closure_lookup (hb_closure_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */
@@ -1560,9 +1756,10 @@ static inline void context_closure_lookup (hb_closure_context_t *c,
lookup_context.funcs.intersected_glyphs);
}
+template <typename HBUINT>
static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ContextCollectGlyphsLookupContext &lookup_context)
@@ -1574,9 +1771,10 @@ static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c
lookupCount, lookupRecord);
}
+template <typename HBUINT>
static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount HB_UNUSED,
const LookupRecord lookupRecord[] HB_UNUSED,
ContextApplyLookupContext &lookup_context)
@@ -1585,9 +1783,11 @@ static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data);
}
+
+template <typename HBUINT>
static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ContextApplyLookupContext &lookup_context)
@@ -1613,6 +1813,7 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
}
}
+template <typename Types>
struct Rule
{
bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
@@ -1626,8 +1827,8 @@ struct Rule
{
if (unlikely (c->lookup_limit_exceeded ())) return;
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
context_closure_lookup (c,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
@@ -1640,16 +1841,16 @@ struct Rule
if (unlikely (c->lookup_limit_exceeded ())) return;
if (!intersects (c->glyphs, lookup_context)) return;
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
recurse_lookups (c, lookupCount, lookupRecord.arrayZ);
}
void collect_glyphs (hb_collect_glyphs_context_t *c,
ContextCollectGlyphsLookupContext &lookup_context) const
{
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
context_collect_glyphs_lookup (c,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
@@ -1659,8 +1860,8 @@ struct Rule
bool would_apply (hb_would_apply_context_t *c,
ContextApplyLookupContext &lookup_context) const
{
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
return context_would_apply_lookup (c,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
@@ -1671,8 +1872,8 @@ struct Rule
ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
}
@@ -1685,7 +1886,7 @@ struct Rule
if (unlikely (!c->extend_min (out))) return_trace (false);
out->inputCount = inputCount;
- const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
+ const auto input = inputZ.as_array (inputCount - 1);
for (const auto org : input)
{
HBUINT16 d;
@@ -1693,8 +1894,8 @@ struct Rule
c->copy (d);
}
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (lookupCount), lookup_map);
return_trace (c->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
@@ -1706,7 +1907,7 @@ struct Rule
{
TRACE_SUBSET (this);
if (unlikely (!inputCount)) return_trace (false);
- const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
+ const auto input = inputZ.as_array (inputCount - 1);
const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map;
if (!hb_all (input, mapping)) return_trace (false);
@@ -1729,7 +1930,7 @@ struct Rule
* glyph sequence--includes the first
* glyph */
HBUINT16 lookupCount; /* Number of LookupRecords */
- UnsizedArrayOf<HBUINT16>
+ UnsizedArrayOf<typename Types::HBUINT>
inputZ; /* Array of match inputs--start with
* second glyph */
/*UnsizedArrayOf<LookupRecord>
@@ -1739,8 +1940,11 @@ struct Rule
DEFINE_SIZE_ARRAY (4, inputZ);
};
+template <typename Types>
struct RuleSet
{
+ using Rule = OT::Rule<Types>;
+
bool intersects (const hb_set_t *glyphs,
ContextClosureLookupContext &lookup_context) const
{
@@ -1853,8 +2057,11 @@ struct RuleSet
};
-struct ContextFormat1
+template <typename Types>
+struct ContextFormat1_4
{
+ using RuleSet = OT::RuleSet<Types>;
+
bool intersects (const hb_set_t *glyphs) const
{
struct ContextClosureLookupContext lookup_context = {
@@ -1878,9 +2085,8 @@ struct ContextFormat1
void closure (hb_closure_context_t *c) const
{
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
- cur_active_glyphs);
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs);
struct ContextClosureLookupContext lookup_context = {
{intersects_glyph, intersected_glyph},
@@ -1991,19 +2197,22 @@ struct ContextFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Array16OfOffset16To<RuleSet>
+ Array16Of<typename Types::template OffsetTo<RuleSet>>
ruleSet; /* Array of RuleSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, ruleSet);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
};
-struct ContextFormat2
+template <typename Types>
+struct ContextFormat2_5
{
+ using RuleSet = OT::RuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
if (!(this+coverage).intersects (glyphs))
@@ -2018,7 +2227,7 @@ struct ContextFormat2
};
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -2044,8 +2253,8 @@ struct ContextFormat2
if (!(this+coverage).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
const ClassDef &class_def = this+classDef;
@@ -2060,7 +2269,7 @@ struct ContextFormat2
| hb_filter ([&] (unsigned _)
{ return class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
- | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<RuleSet>&> _)
+ | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<RuleSet>&> _)
{
const RuleSet& rule_set = this+_.second;
rule_set.closure (c, _.first, lookup_context);
@@ -2125,19 +2334,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));
}
@@ -2155,7 +2399,7 @@ struct ContextFormat2
const hb_set_t* glyphset = c->plan->glyphset_gsub ();
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
(this+classDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -2201,22 +2445,24 @@ struct ContextFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
classDef; /* Offset to glyph ClassDef table--from
* beginning of table */
- Array16OfOffset16To<RuleSet>
+ Array16Of<typename Types::template OffsetTo<RuleSet>>
ruleSet; /* Array of RuleSet tables
* ordered by class */
public:
- DEFINE_SIZE_ARRAY (8, ruleSet);
+ DEFINE_SIZE_ARRAY (4 + 2 * Types::size, ruleSet);
};
struct ContextFormat3
{
+ using RuleSet = OT::RuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
if (!(this+coverageZ[0]).intersects (glyphs))
@@ -2240,8 +2486,8 @@ struct ContextFormat3
if (!(this+coverageZ[0]).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
@@ -2333,7 +2579,7 @@ struct ContextFormat3
if (!o->serialize_subset (c, offset, this)) return_trace (false);
}
- const UnsizedArrayOf<LookupRecord>& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount));
+ const auto& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount));
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
@@ -2380,16 +2626,24 @@ struct Context
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BEYOND_64K
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- HBUINT16 format; /* Format identifier */
- ContextFormat1 format1;
- ContextFormat2 format2;
- ContextFormat3 format3;
+ HBUINT16 format; /* Format identifier */
+ ContextFormat1_4<SmallTypes> format1;
+ ContextFormat2_5<SmallTypes> format2;
+ ContextFormat3 format3;
+#ifndef HB_NO_BEYOND_64K
+ ContextFormat1_4<MediumTypes> format4;
+ ContextFormat2_5<MediumTypes> format5;
+#endif
} u;
};
@@ -2411,17 +2665,18 @@ struct ChainContextCollectGlyphsLookupContext
struct ChainContextApplyLookupContext
{
- ContextApplyFuncs funcs;
+ ChainContextApplyFuncs funcs;
const void *match_data[3];
};
+template <typename HBUINT>
static inline bool chain_context_intersects (const hb_set_t *glyphs,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
ChainContextClosureLookupContext &lookup_context)
{
return array_is_subset_of (glyphs,
@@ -2435,13 +2690,14 @@ static inline bool chain_context_intersects (const hb_set_t *glyphs,
lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
}
+template <typename HBUINT>
static inline void chain_context_closure_lookup (hb_closure_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
unsigned value,
@@ -2461,13 +2717,14 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c,
lookup_context.funcs.intersected_glyphs);
}
+template <typename HBUINT>
static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ChainContextCollectGlyphsLookupContext &lookup_context)
@@ -2485,13 +2742,14 @@ static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_contex
lookupCount, lookupRecord);
}
+template <typename HBUINT>
static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[] HB_UNUSED,
+ const HBUINT backtrack[] HB_UNUSED,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[] HB_UNUSED,
+ const HBUINT lookahead[] HB_UNUSED,
unsigned int lookupCount HB_UNUSED,
const LookupRecord lookupRecord[] HB_UNUSED,
ChainContextApplyLookupContext &lookup_context)
@@ -2499,16 +2757,17 @@ 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]);
}
+template <typename HBUINT>
static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ChainContextApplyLookupContext &lookup_context)
@@ -2518,11 +2777,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 +2791,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);
@@ -2547,12 +2806,13 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
return true;
}
+template <typename Types>
struct ChainRule
{
bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
{
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
return chain_context_intersects (glyphs,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2565,9 +2825,9 @@ struct ChainRule
{
if (unlikely (c->lookup_limit_exceeded ())) return;
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
chain_context_closure_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2583,18 +2843,18 @@ struct ChainRule
if (unlikely (c->lookup_limit_exceeded ())) return;
if (!intersects (c->glyphs, lookup_context)) return;
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
recurse_lookups (c, lookup.len, lookup.arrayZ);
}
void collect_glyphs (hb_collect_glyphs_context_t *c,
ChainContextCollectGlyphsLookupContext &lookup_context) const
{
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
chain_context_collect_glyphs_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2606,9 +2866,9 @@ struct ChainRule
bool would_apply (hb_would_apply_context_t *c,
ChainContextApplyLookupContext &lookup_context) const
{
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return chain_context_would_apply_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2619,9 +2879,9 @@ struct ChainRule
bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return_trace (chain_context_apply_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2654,22 +2914,22 @@ struct ChainRule
serialize_array (c, backtrack.len, + backtrack.iter ()
| hb_map (mapping));
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (input_map) mapping = input_map;
serialize_array (c, input.lenP1, + input.iter ()
| hb_map (mapping));
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (lookahead_map) mapping = lookahead_map;
serialize_array (c, lookahead.len, + lookahead.iter ()
| hb_map (mapping));
- const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
- HBUINT16* lookupCount = c->embed (&(lookupRecord.len));
+ HBUINT16* lookupCount = c->embed (&(lookup.len));
if (!lookupCount) return_trace (false);
- unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (), lookup_map);
+ unsigned count = serialize_lookuprecord_array (c, lookup.as_array (), lookup_map);
return_trace (c->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
@@ -2681,8 +2941,8 @@ struct ChainRule
{
TRACE_SUBSET (this);
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!backtrack_map)
{
@@ -2711,23 +2971,23 @@ struct ChainRule
{
TRACE_SANITIZE (this);
if (!backtrack.sanitize (c)) return_trace (false);
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!input.sanitize (c)) return_trace (false);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!lookahead.sanitize (c)) return_trace (false);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return_trace (lookup.sanitize (c));
}
protected:
- Array16Of<HBUINT16>
+ Array16Of<typename Types::HBUINT>
backtrack; /* Array of backtracking values
* (to be matched before the input
* sequence) */
- HeadlessArrayOf<HBUINT16>
+ HeadlessArrayOf<typename Types::HBUINT>
inputX; /* Array of input values (start with
* second glyph) */
- Array16Of<HBUINT16>
+ Array16Of<typename Types::HBUINT>
lookaheadX; /* Array of lookahead values's (to be
* matched after the input sequence) */
Array16Of<LookupRecord>
@@ -2737,8 +2997,11 @@ struct ChainRule
DEFINE_SIZE_MIN (8);
};
+template <typename Types>
struct ChainRuleSet
{
+ using ChainRule = OT::ChainRule<Types>;
+
bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
{
return
@@ -2851,8 +3114,11 @@ struct ChainRuleSet
DEFINE_SIZE_ARRAY (2, rule);
};
-struct ChainContextFormat1
+template <typename Types>
+struct ChainContextFormat1_4
{
+ using ChainRuleSet = OT::ChainRuleSet<Types>;
+
bool intersects (const hb_set_t *glyphs) const
{
struct ChainContextClosureLookupContext lookup_context = {
@@ -2876,8 +3142,8 @@ struct ChainContextFormat1
void closure (hb_closure_context_t *c) const
{
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
struct ChainContextClosureLookupContext lookup_context = {
@@ -2934,7 +3200,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 +3216,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));
@@ -2988,18 +3254,21 @@ struct ChainContextFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Array16OfOffset16To<ChainRuleSet>
+ Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
ruleSet; /* Array of ChainRuleSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, ruleSet);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
};
-struct ChainContextFormat2
+template <typename Types>
+struct ChainContextFormat2_5
{
+ using ChainRuleSet = OT::ChainRuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
if (!(this+coverage).intersects (glyphs))
@@ -3018,7 +3287,7 @@ struct ChainContextFormat2
};
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
input_class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -3043,8 +3312,8 @@ struct ChainContextFormat2
if (!(this+coverage).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
@@ -3064,7 +3333,7 @@ struct ChainContextFormat2
| hb_filter ([&] (unsigned _)
{ return input_class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
- | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<ChainRuleSet>&> _)
+ | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<ChainRuleSet>&> _)
{
const ChainRuleSet& chainrule_set = this+_.second;
chainrule_set.closure (c, _.first, lookup_context);
@@ -3134,7 +3403,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 +3413,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 +3449,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_5 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));
}
@@ -3189,7 +3497,7 @@ struct ChainContextFormat2
const hb_set_t* glyphset = c->plan->glyphset_gsub ();
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
(this+inputClassDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -3244,38 +3552,40 @@ struct ChainContextFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
backtrackClassDef; /* Offset to glyph ClassDef table
* containing backtrack sequence
* data--from beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
inputClassDef; /* Offset to glyph ClassDef
* table containing input sequence
* data--from beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
lookaheadClassDef; /* Offset to glyph ClassDef table
* containing lookahead sequence
* data--from beginning of table */
- Array16OfOffset16To<ChainRuleSet>
+ Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
ruleSet; /* Array of ChainRuleSet tables
* ordered by class */
public:
- DEFINE_SIZE_ARRAY (12, ruleSet);
+ DEFINE_SIZE_ARRAY (4 + 4 * Types::size, ruleSet);
};
struct ChainContextFormat3
{
+ using RuleSet = OT::RuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!(this+input[0]).intersects (glyphs))
return false;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
struct ChainContextClosureLookupContext lookup_context = {
{intersects_coverage, intersected_coverage_glyphs},
ContextFormat::CoverageBasedContext,
@@ -3293,18 +3603,18 @@ struct ChainContextFormat3
void closure (hb_closure_context_t *c) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!(this+input[0]).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
struct ChainContextClosureLookupContext lookup_context = {
{intersects_coverage, intersected_coverage_glyphs},
ContextFormat::CoverageBasedContext,
@@ -3325,9 +3635,9 @@ struct ChainContextFormat3
if (!intersects (c->glyphs))
return;
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
recurse_lookups (c, lookup.len, lookup.arrayZ);
}
@@ -3335,12 +3645,13 @@ struct ChainContextFormat3
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
(this+input[0]).collect_coverage (c->input);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
+
struct ChainContextCollectGlyphsLookupContext lookup_context = {
{collect_coverage},
{this, this, this}
@@ -3355,11 +3666,11 @@ struct ChainContextFormat3
bool would_apply (hb_would_apply_context_t *c) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
struct ChainContextApplyLookupContext lookup_context = {
- {match_coverage},
+ {{match_coverage, match_coverage, match_coverage}},
{this, this, this}
};
return chain_context_would_apply_lookup (c,
@@ -3371,22 +3682,22 @@ struct ChainContextFormat3
const Coverage &get_coverage () const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
return this+input[0];
}
bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
struct ChainContextApplyLookupContext lookup_context = {
- {match_coverage},
+ {{match_coverage, match_coverage, match_coverage}},
{this, this, this}
};
return_trace (chain_context_apply_lookup (c,
@@ -3426,21 +3737,21 @@ struct ChainContextFormat3
if (!serialize_coverage_offsets (c, backtrack.iter (), this))
return_trace (false);
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!serialize_coverage_offsets (c, input.iter (), this))
return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!serialize_coverage_offsets (c, lookahead.iter (), this))
return_trace (false);
- const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
- HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookupRecord.len);
+ HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookup.len);
if (!lookupCount) return_trace (false);
- unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (), lookup_map);
+ unsigned count = serialize_lookuprecord_array (c->serializer, lookup.as_array (), lookup_map);
return_trace (c->serializer->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
@@ -3448,12 +3759,12 @@ struct ChainContextFormat3
{
TRACE_SANITIZE (this);
if (!backtrack.sanitize (c, this)) return_trace (false);
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!input.sanitize (c, this)) return_trace (false);
if (!input.len) return_trace (false); /* To be consistent with Context. */
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!lookahead.sanitize (c, this)) return_trace (false);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return_trace (lookup.sanitize (c));
}
@@ -3489,16 +3800,24 @@ struct ChainContext
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BEYOND_64K
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- HBUINT16 format; /* Format identifier */
- ChainContextFormat1 format1;
- ChainContextFormat2 format2;
- ChainContextFormat3 format3;
+ HBUINT16 format; /* Format identifier */
+ ChainContextFormat1_4<SmallTypes> format1;
+ ChainContextFormat2_5<SmallTypes> format2;
+ ChainContextFormat3 format3;
+#ifndef HB_NO_BEYOND_64K
+ ChainContextFormat1_4<MediumTypes> format4;
+ ChainContextFormat2_5<MediumTypes> format5;
+#endif
} u;
};
@@ -3623,60 +3942,273 @@ 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
+};
+
+template <typename Types>
+struct GSUBGPOSVersion1_2
+{
+ friend struct GSUBGPOS;
+
+ protected:
+ FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
+ * to 0x00010000u */
+ typename Types:: template OffsetTo<ScriptList>
+ scriptList; /* ScriptList table */
+ typename Types::template OffsetTo<FeatureList>
+ featureList; /* FeatureList table */
+ typename Types::template OffsetTo<LookupList<Types>>
+ lookupList; /* LookupList table */
+ Offset32To<FeatureVariations>
+ featureVars; /* Offset to Feature Variations
+ table--from beginning of table
+ * (may be NULL). Introduced
+ * in version 0x00010001. */
+ public:
+ DEFINE_SIZE_MIN (4 + 3 * Types::size);
+
+ unsigned int get_size () const
+ {
+ return min_size +
+ (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
+ }
+
+ const typename Types::template OffsetTo<LookupList<Types>>* get_lookup_list_offset () const
+ {
+ return &lookupList;
+ }
+
+ template <typename TLookup>
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList;
+ if (unlikely (!(scriptList.sanitize (c, this) &&
+ featureList.sanitize (c, this) &&
+ reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
+ return_trace (false);
+
+#ifndef HB_NO_VAR
+ if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
+ return_trace (false);
+#endif
+
+ return_trace (true);
+ }
+
+ template <typename TLookup>
+ bool subset (hb_subset_layout_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->subset_context->serializer->embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ typedef LookupOffsetList<TLookup, typename Types::HBUINT> TLookupList;
+ reinterpret_cast<typename Types::template OffsetTo<TLookupList> &> (out->lookupList)
+ .serialize_subset (c->subset_context,
+ reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList),
+ this,
+ c);
+
+ reinterpret_cast<typename Types::template OffsetTo<RecordListOfFeature> &> (out->featureList)
+ .serialize_subset (c->subset_context,
+ reinterpret_cast<const typename Types::template OffsetTo<RecordListOfFeature> &> (featureList),
+ this,
+ c);
+
+ out->scriptList.serialize_subset (c->subset_context,
+ scriptList,
+ this,
+ c);
+
+#ifndef HB_NO_VAR
+ if (version.to_int () >= 0x00010001u)
+ {
+ bool ret = out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
+ if (!ret && version.major == 1)
+ {
+ out->version.major = 1;
+ out->version.minor = 0;
+ }
+ }
+#endif
+
+ return_trace (true);
+ }
};
struct GSUBGPOS
{
- bool has_data () const { return version.to_int (); }
+ unsigned int get_size () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.get_size ();
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.get_size ();
+#endif
+ default: return u.version.static_size;
+ }
+ }
+
+ template <typename TLookup>
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!u.version.sanitize (c))) return_trace (false);
+ switch (u.version.major) {
+ case 1: return_trace (u.version1.sanitize<TLookup> (c));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return_trace (u.version2.sanitize<TLookup> (c));
+#endif
+ default: return_trace (true);
+ }
+ }
+
+ template <typename TLookup>
+ bool subset (hb_subset_layout_context_t *c) const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.subset<TLookup> (c);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.subset<TLookup> (c);
+#endif
+ default: return false;
+ }
+ }
+
+ const ScriptList &get_script_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.scriptList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.scriptList;
+#endif
+ default: return Null (ScriptList);
+ }
+ }
+ const FeatureList &get_feature_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.featureList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.featureList;
+#endif
+ default: return Null (FeatureList);
+ }
+ }
+ unsigned int get_lookup_count () const
+ {
+ switch (u.version.major) {
+ case 1: return (this+u.version1.lookupList).len;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return (this+u.version2.lookupList).len;
+#endif
+ default: return 0;
+ }
+ }
+ const Lookup& get_lookup (unsigned int i) const
+ {
+ switch (u.version.major) {
+ case 1: return (this+u.version1.lookupList)[i];
+#ifndef HB_NO_BEYOND_64K
+ case 2: return (this+u.version2.lookupList)[i];
+#endif
+ default: return Null (Lookup);
+ }
+ }
+ const FeatureVariations &get_feature_variations () const
+ {
+ switch (u.version.major) {
+ case 1: return (u.version.to_int () >= 0x00010001u ? this+u.version1.featureVars : Null (FeatureVariations));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.featureVars;
+#endif
+ default: return Null (FeatureVariations);
+ }
+ }
+
+ bool has_data () const { return u.version.to_int (); }
unsigned int get_script_count () const
- { return (this+scriptList).len; }
+ { return get_script_list ().len; }
const Tag& get_script_tag (unsigned int i) const
- { return (this+scriptList).get_tag (i); }
+ { return get_script_list ().get_tag (i); }
unsigned int get_script_tags (unsigned int start_offset,
unsigned int *script_count /* IN/OUT */,
hb_tag_t *script_tags /* OUT */) const
- { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
+ { return get_script_list ().get_tags (start_offset, script_count, script_tags); }
const Script& get_script (unsigned int i) const
- { return (this+scriptList)[i]; }
+ { return get_script_list ()[i]; }
bool find_script_index (hb_tag_t tag, unsigned int *index) const
- { return (this+scriptList).find_index (tag, index); }
+ { return get_script_list ().find_index (tag, index); }
unsigned int get_feature_count () const
- { return (this+featureList).len; }
+ { return get_feature_list ().len; }
hb_tag_t get_feature_tag (unsigned int i) const
- { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
+ { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : get_feature_list ().get_tag (i); }
unsigned int get_feature_tags (unsigned int start_offset,
unsigned int *feature_count /* IN/OUT */,
hb_tag_t *feature_tags /* OUT */) const
- { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
+ { return get_feature_list ().get_tags (start_offset, feature_count, feature_tags); }
const Feature& get_feature (unsigned int i) const
- { return (this+featureList)[i]; }
+ { return get_feature_list ()[i]; }
bool find_feature_index (hb_tag_t tag, unsigned int *index) const
- { return (this+featureList).find_index (tag, index); }
-
- unsigned int get_lookup_count () const
- { return (this+lookupList).len; }
- const Lookup& get_lookup (unsigned int i) const
- { return (this+lookupList)[i]; }
+ { return get_feature_list ().find_index (tag, index); }
bool find_variations_index (const int *coords, unsigned int num_coords,
unsigned int *index) const
@@ -3685,18 +4217,17 @@ struct GSUBGPOS
*index = FeatureVariations::NOT_FOUND_INDEX;
return false;
#endif
- return (version.to_int () >= 0x00010001u ? this+featureVars : Null (FeatureVariations))
- .find_index (coords, num_coords, index);
+ return get_feature_variations ().find_index (coords, num_coords, index);
}
const Feature& get_feature_variation (unsigned int feature_index,
unsigned int variations_index) const
{
#ifndef HB_NO_VAR
if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
- version.to_int () >= 0x00010001u)
+ u.version.to_int () >= 0x00010001u)
{
- const Feature *feature = (this+featureVars).find_substitute (variations_index,
- feature_index);
+ const Feature *feature = get_feature_variations ().find_substitute (variations_index,
+ feature_index);
if (feature)
return *feature;
}
@@ -3708,8 +4239,7 @@ struct GSUBGPOS
hb_set_t *lookup_indexes /* OUT */) const
{
#ifndef HB_NO_VAR
- if (version.to_int () >= 0x00010001u)
- (this+featureVars).collect_lookups (feature_indexes, lookup_indexes);
+ get_feature_variations ().collect_lookups (feature_indexes, lookup_indexes);
#endif
}
@@ -3721,6 +4251,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 +4261,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);
@@ -3742,118 +4274,6 @@ struct GSUBGPOS
}
}
- template <typename TLookup>
- bool subset (hb_subset_layout_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->subset_context->serializer->embed (*this);
- if (unlikely (!out)) return_trace (false);
-
- typedef LookupOffsetList<TLookup> TLookupList;
- reinterpret_cast<Offset16To<TLookupList> &> (out->lookupList)
- .serialize_subset (c->subset_context,
- reinterpret_cast<const Offset16To<TLookupList> &> (lookupList),
- this,
- c);
-
- reinterpret_cast<Offset16To<RecordListOfFeature> &> (out->featureList)
- .serialize_subset (c->subset_context,
- reinterpret_cast<const Offset16To<RecordListOfFeature> &> (featureList),
- this,
- c);
-
- out->scriptList.serialize_subset (c->subset_context,
- scriptList,
- this,
- c);
-
-#ifndef HB_NO_VAR
- if (version.to_int () >= 0x00010001u)
- {
- bool ret = out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
- if (!ret)
- {
- out->version.major = 1;
- out->version.minor = 0;
- }
- }
-#endif
-
- return_trace (true);
- }
-
- void find_duplicate_features (const hb_map_t *lookup_indices,
- const hb_set_t *feature_indices,
- 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;
- //find out duplicate features after subset
- for (unsigned i : feature_indices->iter ())
- {
- hb_tag_t t = get_feature_tag (i);
- 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);
- return;
- }
- if (unique_features.get (t))
- unique_features.get (t)->add (i);
- duplicate_feature_map->set (i, i);
- continue;
- }
-
- bool found = false;
-
- hb_set_t* same_tag_features = unique_features.get (t);
- for (unsigned other_f_index : same_tag_features->iter ())
- {
- const Feature& f = get_feature (i);
- const Feature& other_f = get_feature (other_f_index);
-
- auto f_iter =
- + hb_iter (f.lookupIndex)
- | hb_filter (lookup_indices)
- ;
-
- auto other_f_iter =
- + hb_iter (other_f.lookupIndex)
- | hb_filter (lookup_indices)
- ;
-
- bool is_equal = true;
- for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
- {
- unsigned a = *f_iter;
- unsigned b = *other_f_iter;
- if (a != b) { is_equal = false; break; }
- }
-
- if (is_equal == false || f_iter || other_f_iter) continue;
-
- found = true;
- duplicate_feature_map->set (i, other_f_index);
- break;
- }
-
- if (found == false)
- {
- same_tag_features->add (i);
- 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 */
hb_set_t *feature_indices /* IN/OUT */) const
{
@@ -3862,8 +4282,7 @@ struct GSUBGPOS
// if the FeatureVariation's table and the alternate version(s) intersect the
// set of lookup indices.
hb_set_t alternate_feature_indices;
- if (version.to_int () >= 0x00010001u)
- (this+featureVars).closure_features (lookup_indices, &alternate_feature_indices);
+ get_feature_variations ().closure_features (lookup_indices, &alternate_feature_indices);
if (unlikely (alternate_feature_indices.in_error()))
{
feature_indices->err ();
@@ -3896,32 +4315,6 @@ struct GSUBGPOS
}
}
- unsigned int get_size () const
- {
- return min_size +
- (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
- }
-
- template <typename TLookup>
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- typedef List16OfOffset16To<TLookup> TLookupList;
- if (unlikely (!(version.sanitize (c) &&
- likely (version.major == 1) &&
- scriptList.sanitize (c, this) &&
- featureList.sanitize (c, this) &&
- reinterpret_cast<const Offset16To<TLookupList> &> (lookupList).sanitize (c, this))))
- return_trace (false);
-
-#ifndef HB_NO_VAR
- if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
- return_trace (false);
-#endif
-
- return_trace (true);
- }
-
template <typename T>
struct accelerator_t
{
@@ -3961,21 +4354,15 @@ struct GSUBGPOS
};
protected:
- FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
- * to 0x00010000u */
- Offset16To<ScriptList>
- scriptList; /* ScriptList table */
- Offset16To<FeatureList>
- featureList; /* FeatureList table */
- Offset16To<LookupList>
- lookupList; /* LookupList table */
- Offset32To<FeatureVariations>
- featureVars; /* Offset to Feature Variations
- table--from beginning of table
- * (may be NULL). Introduced
- * in version 0x00010001. */
+ union {
+ FixedVersion<> version; /* Version identifier */
+ GSUBGPOSVersion1_2<SmallTypes> version1;
+#ifndef HB_NO_BEYOND_64K
+ GSUBGPOSVersion1_2<MediumTypes> version2;
+#endif
+ } u;
public:
- DEFINE_SIZE_MIN (10);
+ DEFINE_SIZE_MIN (4);
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc
index f4ea21a4f9..f9c0daa486 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"
@@ -54,7 +54,8 @@
#include "hb-aat-layout-morx-table.hh"
#include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise.
-using OT::Layout::GSUB::GSUB;
+using OT::Layout::GSUB;
+using OT::Layout::GPOS;
/**
* SECTION:hb-ot-layout
@@ -78,7 +79,7 @@ using OT::Layout::GSUB::GSUB;
* Tests whether a face includes any kerning data in the 'kern' table.
* Does NOT test for kerning lookups in the GPOS table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
bool
@@ -94,7 +95,7 @@ hb_ot_layout_has_kerning (hb_face_t *face)
* Tests whether a face includes any state-machine kerning in the 'kern' table.
* Does NOT examine the GPOS table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
bool
@@ -114,7 +115,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face)
*
* Does NOT examine the GPOS table.
*
- * Return value: %true is data found, %false otherwise
+ * Return value: `true` is data found, `false` otherwise
*
**/
bool
@@ -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;
}
}
@@ -272,7 +272,7 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
*
* Tests whether a face has any glyph classes defined in its GDEF table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
hb_bool_t
@@ -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
@@ -461,7 +461,7 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face,
* Fetches the index if a given script tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the script is found, %false otherwise
+ * Return value: `true` if the script is found, `false` otherwise
*
**/
hb_bool_t
@@ -535,7 +535,7 @@ hb_ot_layout_table_choose_script (hb_face_t *face,
* #HB_OT_LAYOUT_NO_SCRIPT_INDEX.
*
* Return value:
- * %true if one of the requested scripts is selected, %false if a fallback
+ * `true` if one of the requested scripts is selected, `false` if a fallback
* script is selected or if no scripts are selected.
*
* Since: 2.0.0
@@ -628,7 +628,7 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
* Fetches the index for a given feature tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
**/
bool
hb_ot_layout_table_find_feature (hb_face_t *face,
@@ -695,7 +695,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
* Fetches the index of a given language tag in the specified face's GSUB table
* or GPOS table, underneath the specified script tag.
*
- * Return value: %true if the language tag is found, %false otherwise
+ * Return value: `true` if the language tag is found, `false` otherwise
*
* Since: 0.6.0
* Deprecated: 2.0.0
@@ -730,10 +730,10 @@ hb_ot_layout_script_find_language (hb_face_t *face,
* in the specified face's GSUB or GPOS table, underneath the specified script
* index.
*
- * If none of the given language tags is found, %false is returned and
+ * If none of the given language tags is found, `false` is returned and
* @language_index is set to the default language index.
*
- * Return value: %true if one of the given language tags is found, %false otherwise
+ * Return value: `true` if one of the given language tags is found, `false` otherwise
*
* Since: 2.0.0
**/
@@ -776,7 +776,7 @@ hb_ot_layout_script_select_language (hb_face_t *face,
* Fetches the index of a requested feature in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
**/
hb_bool_t
@@ -807,7 +807,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
* Fetches the tag of a requested feature index in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
* Since: 0.9.30
**/
@@ -917,7 +917,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face,
* Fetches the index of a given feature tag in the specified face's GSUB table
* or GPOS table, underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
**/
hb_bool_t
@@ -1314,7 +1314,7 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
* Fetches a list of feature variations in the specified face's GSUB table
* or GPOS table, at the specified variation coordinates.
*
- * Return value: %true if feature variations were found, %false otherwise.
+ * Return value: `true` if feature variations were found, `false` otherwise.
*
**/
hb_bool_t
@@ -1377,7 +1377,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
*
* Tests whether the specified face includes any GSUB substitutions.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
hb_bool_t
@@ -1399,7 +1399,7 @@ hb_ot_layout_has_substitution (hb_face_t *face)
* Tests whether a specified lookup in the specified face would
* trigger a substitution on the given glyph sequence.
*
- * Return value: %true if a substitution would be triggered, %false otherwise
+ * Return value: `true` if a substitution would be triggered, `false` otherwise
*
* Since: 0.9.7
**/
@@ -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
*/
@@ -1567,7 +1561,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
*
* Tests whether the specified face includes any GPOS positioning.
*
- * Return value: %true if the face has GPOS data, %false otherwise
+ * Return value: `true` if the face has GPOS data, `false` otherwise
*
**/
hb_bool_t
@@ -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);
}
@@ -1640,7 +1634,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
* For more information on this distinction, see the [`size` feature documentation](
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size).
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.10
**/
@@ -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 ();
@@ -1704,7 +1698,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
* Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
* "Character Variant" ('cvXX') features.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.0.0
**/
@@ -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++)
{
@@ -2051,7 +2051,7 @@ hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script)
*
* Fetches a baseline value from the face.
*
- * Return value: %true if found baseline value in the font.
+ * Return value: `true` if found baseline value in the font.
*
* Since: 2.6.0
**/
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh
index 75bba0bc50..de06610cb5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh
@@ -110,7 +110,7 @@ namespace OT {
struct hb_ot_apply_context_t;
struct hb_ot_layout_lookup_accelerator_t;
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct SubstLookup;
}
}
@@ -118,7 +118,7 @@ namespace GSUB {
HB_INTERNAL void
hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
- const OT::Layout::GSUB::SubstLookup &lookup,
+ const OT::Layout::GSUB_impl::SubstLookup &lookup,
const OT::hb_ot_layout_lookup_accelerator_t &accel);
@@ -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-map.cc b/thirdparty/harfbuzz/src/hb-ot-map.cc
index f085c78ff8..39215b335f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-map.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-map.cc
@@ -43,7 +43,7 @@ void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_o
hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
- const hb_segment_properties_t *props_)
+ const hb_segment_properties_t &props_)
{
memset (this, 0, sizeof (*this));
@@ -52,7 +52,7 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
stages[table_index].init ();
face = face_;
- props = *props_;
+ props = props_;
/* Fetch script/language indices for GSUB/GPOS. We need these later to skip
* features not available in either table and not waste precious bits for them. */
@@ -109,6 +109,21 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag,
info->stage[1] = current_stage[1];
}
+bool hb_ot_map_builder_t::has_feature (hb_tag_t tag)
+{
+ for (unsigned int table_index = 0; table_index < 2; table_index++)
+ {
+ if (hb_ot_layout_language_find_feature (face,
+ table_tags[table_index],
+ script_index[table_index],
+ language_index[table_index],
+ tag,
+ nullptr))
+ return true;
+ }
+ return false;
+}
+
void
hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
unsigned int table_index,
diff --git a/thirdparty/harfbuzz/src/hb-ot-map.hh b/thirdparty/harfbuzz/src/hb-ot-map.hh
index f1cbf752fc..a7b5eec30d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-map.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-map.hh
@@ -139,19 +139,15 @@ struct hb_ot_map_t
return map ? map->stage[table_index] : UINT_MAX;
}
- void get_stage_lookups (unsigned int table_index, unsigned int stage,
- const struct lookup_map_t **plookups, unsigned int *lookup_count) const
+ hb_array_t<const hb_ot_map_t::lookup_map_t>
+ get_stage_lookups (unsigned int table_index, unsigned int stage) const
{
if (unlikely (stage > stages[table_index].length))
- {
- *plookups = nullptr;
- *lookup_count = 0;
- return;
- }
+ return hb_array<const hb_ot_map_t::lookup_map_t> (nullptr, 0);
+
unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
unsigned int end = stage < stages[table_index].length ? stages[table_index][stage].last_lookup : lookups[table_index].length;
- *plookups = end == start ? nullptr : &lookups[table_index][start];
- *lookup_count = end - start;
+ return lookups[table_index].as_array ().sub_array (start, end - start);
}
HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
@@ -167,7 +163,7 @@ struct hb_ot_map_t
private:
- hb_mask_t global_mask;
+ hb_mask_t global_mask = 0;
hb_sorted_vector_t<feature_map_t> features;
hb_vector_t<lookup_map_t> lookups[2]; /* GSUB/GPOS */
@@ -204,7 +200,7 @@ struct hb_ot_map_builder_t
public:
HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
- const hb_segment_properties_t *props_);
+ const hb_segment_properties_t &props_);
HB_INTERNAL ~hb_ot_map_builder_t ();
@@ -212,6 +208,8 @@ struct hb_ot_map_builder_t
hb_ot_map_feature_flags_t flags=F_NONE,
unsigned int value=1);
+ HB_INTERNAL bool has_feature (hb_tag_t tag);
+
void add_feature (const hb_ot_map_feature_t &feat)
{ add_feature (feat.tag, feat.flags); }
diff --git a/thirdparty/harfbuzz/src/hb-ot-math.cc b/thirdparty/harfbuzz/src/hb-ot-math.cc
index f44ac35849..c515867bdf 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-math.cc
@@ -56,7 +56,7 @@
*
* Tests whether a face has a `MATH` table.
*
- * Return value: %true if the table is found, %false otherwise
+ * Return value: `true` if the table is found, `false` otherwise
*
* Since: 1.3.3
**/
@@ -142,7 +142,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
*
* Tests whether the given glyph index is an extended shape in the face.
*
- * Return value: %true if the glyph is an extended shape, %false otherwise
+ * Return value: `true` if the glyph is an extended shape, `false` otherwise
*
* Since: 1.3.3
**/
diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.cc b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
index f9c4b96fff..5b12482b97 100644
--- a/thirdparty/harfbuzz/src/hb-ot-metrics.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
@@ -71,12 +71,12 @@ _hb_ot_metrics_get_position_common (hb_font_t *font,
#endif
#define GET_METRIC_X(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_x (_fix_ascender_descender ( \
- face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
+ ((void) (position && (*position = font->em_scalef_x (_fix_ascender_descender ( \
+ face->table.TABLE->ATTR + GET_VAR, metrics_tag)))), true))
#define GET_METRIC_Y(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
- face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
+ ((void) (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
+ face->table.TABLE->ATTR + GET_VAR, metrics_tag)))), true))
case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) ||
@@ -154,10 +154,10 @@ hb_ot_metrics_get_position (hb_font_t *font,
#endif
#define GET_METRIC_X(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR)), true))
+ ((void) (position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR))), true))
#define GET_METRIC_Y(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true))
+ ((void) (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR))), true))
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent);
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent);
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..1f2131ffcc 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,19 @@ _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);
+
+ // '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 (!exact && c &&
+ hb_language_matches (b->language, a->language))
+ return 0;
+
+ return c;
}
static int
@@ -178,7 +189,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 +341,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-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
index a4844e94bc..a4c0c4aa17 100644
--- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
@@ -263,10 +263,10 @@ struct post
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) &&
- (version.to_int () == 0x00010000 ||
- (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
- version.to_int () == 0x00030000)));
+ return_trace (c->check_struct (this) &&
+ (version.to_int () == 0x00010000 ||
+ (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
+ version.to_int () == 0x00030000));
}
public:
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-complex-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
deleted file mode 100644
index c8e5151694..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
+++ /dev/null
@@ -1,1570 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.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]
- * # ArabicShaping-14.0.0.txt
- * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
- * # DerivedCoreProperties-14.0.0.txt
- * # Date: 2021-08-12, 23:12:53 GMT
- * # Blocks-14.0.0.txt
- * # Date: 2021-01-22, 23:29:00 GMT [KW]
- * # Scripts-14.0.0.txt
- * # Date: 2021-07-10, 00:35:31 GMT
- * # Override values For Indic_Syllabic_Category
- * # Not derivable
- * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
- * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
- * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
- * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
- * # Override values For Indic_Positional_Category
- * # Not derivable
- * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
- * # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
- * # Updated for L2/19-083 by Andrew Glass 2019-05-06
- * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
- * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
- * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
- * UnicodeData.txt does not have a header.
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-use-machine.hh"
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-macros"
-#define B USE(B) /* BASE */
-#define CGJ USE(CGJ) /* CGJ */
-#define CS USE(CS) /* CONS_WITH_STACKER */
-#define G USE(G) /* HIEROGLYPH */
-#define GB USE(GB) /* BASE_OTHER */
-#define H USE(H) /* HALANT */
-#define HN USE(HN) /* HALANT_NUM */
-#define IS USE(IS) /* INVISIBLE_STACKER */
-#define J USE(J) /* HIEROGLYPH_JOINER */
-#define N USE(N) /* BASE_NUM */
-#define O USE(O) /* OTHER */
-#define R USE(R) /* REPHA */
-#define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
-#define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */
-#define SUB USE(SUB) /* CONS_SUB */
-#define Sk USE(Sk) /* SAKOT */
-#define WJ USE(WJ) /* Word_Joiner */
-#define ZWNJ USE(ZWNJ) /* ZWNJ */
-#define CMAbv USE(CMAbv)
-#define CMBlw USE(CMBlw)
-#define FAbv USE(FAbv)
-#define FBlw USE(FBlw)
-#define FPst USE(FPst)
-#define FMAbv USE(FMAbv)
-#define FMBlw USE(FMBlw)
-#define FMPst USE(FMPst)
-#define MAbv USE(MAbv)
-#define MBlw USE(MBlw)
-#define MPst USE(MPst)
-#define MPre USE(MPre)
-#define SMAbv USE(SMAbv)
-#define SMBlw USE(SMBlw)
-#define VAbv USE(VAbv)
-#define VBlw USE(VBlw)
-#define VPst USE(VPst)
-#define VPre USE(VPre)
-#define VMAbv USE(VMAbv)
-#define VMBlw USE(VMBlw)
-#define VMPst USE(VMPst)
-#define VMPre USE(VMPre)
-#pragma GCC diagnostic pop
-
-static const uint8_t use_table[] = {
-
-
-#define use_offset_0x0028u 0
-
-
- /* Basic Latin */
- O, O, O, O, O, GB, O, O,
- /* 0030 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0x00a0u 24
-
-
- /* Latin-1 Supplement */
-
- /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O, O,
- /* 00B0 */ O, O, FMPst, FMPst, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 00D0 */ O, O, O, O, O, O, O, GB,
-
-#define use_offset_0x0348u 80
-
-
- /* Combining Diacritical Marks */
- O, O, O, O, O, O, O, CGJ,
-
-#define use_offset_0x0640u 88
-
-
- /* Arabic */
-
- /* 0640 */ B, O, O, O, O, O, O, O,
-
-#define use_offset_0x07c8u 96
-
-
- /* NKo */
- O, O, B, B, B, B, B, B,
- /* 07D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 07E0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
- /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, O, O, O, B, WJ, WJ, VMAbv, O, O,
-
-#define use_offset_0x0840u 152
-
-
- /* Mandaic */
-
- /* 0840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0850 */ B, B, B, B, B, B, B, B, B, CMBlw, CMBlw, CMBlw, WJ, WJ, O, WJ,
-
-#define use_offset_0x0900u 184
-
-
- /* Devanagari */
-
- /* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0930 */ B, B, B, B, B, B, B, B, B, B, VAbv, VPst, CMBlw, B, VPst, VPre,
- /* 0940 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VPst, VPst, VPst, VPst, H, VPre, VPst,
- /* 0950 */ O, VMAbv, VMBlw, O, O, VAbv, VBlw, VBlw, B, B, B, B, B, B, B, B,
- /* 0960 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0970 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
-
- /* Bengali */
-
- /* 0980 */ GB, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B,
- /* 0990 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 09A0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 09B0 */ B, WJ, B, WJ, WJ, WJ, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre,
- /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, O, WJ,
- /* 09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, B, B, WJ, B,
- /* 09E0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FMAbv, WJ,
-
- /* Gurmukhi */
-
- /* 0A00 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B,
- /* 0A10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0A20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0A30 */ B, WJ, B, B, WJ, B, B, WJ, B, B, WJ, WJ, CMBlw, WJ, VPst, VPre,
- /* 0A40 */ VPst, VBlw, VBlw, WJ, WJ, WJ, WJ, VAbv, VAbv, WJ, WJ, VAbv, VAbv, H, WJ, WJ,
- /* 0A50 */ WJ, VMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, WJ, B, WJ,
- /* 0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Gujarati */
-
- /* 0A80 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, B, B, B, WJ, B,
- /* 0A90 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0AA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0AB0 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre,
- /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, WJ, VAbv, VAbv, VAbv, WJ, VPst, VPst, H, WJ, WJ,
- /* 0AD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 0AE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0AF0 */ O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv,
-
- /* Oriya */
-
- /* 0B00 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B,
- /* 0B10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0B20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0B30 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv,
- /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ,
- /* 0B50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ, B, B, WJ, B,
- /* 0B60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0B70 */ O, B, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Tamil */
-
- /* 0B80 */ WJ, WJ, VMAbv, O, WJ, B, B, B, B, B, B, WJ, WJ, WJ, B, B,
- /* 0B90 */ B, WJ, B, B, B, B, WJ, WJ, WJ, B, B, WJ, B, WJ, B, B,
- /* 0BA0 */ WJ, WJ, WJ, B, B, WJ, WJ, WJ, B, B, B, WJ, WJ, WJ, B, B,
- /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, VPst, VPst,
- /* 0BC0 */ VAbv, VPst, VPst, WJ, WJ, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, WJ, WJ,
- /* 0BD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ,
-
- /* Telugu */
-
- /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, WJ, B, B,
- /* 0C10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0C20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0C30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, CMBlw, B, VAbv, VAbv,
- /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ,
- /* 0C50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VBlw, WJ, B, B, B, WJ, WJ, O, WJ, WJ,
- /* 0C60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, O, O, O, O,
-
- /* Kannada */
-
- /* 0C80 */ B, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, WJ, B, B,
- /* 0C90 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0CA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0CB0 */ B, B, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv,
- /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ,
- /* 0CD0 */ WJ, WJ, WJ, WJ, WJ, VPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, O, B, WJ,
- /* 0CE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0CF0 */ WJ, CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Malayalam */
-
- /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, B, B, B, B, B, B, B, B, B, WJ, B, B,
- /* 0D10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, VAbv, VAbv, B, VPst, VPst,
- /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, R, O,
- /* 0D50 */ WJ, WJ, WJ, WJ, O, O, O, VPst, O, O, O, O, O, O, O, B,
- /* 0D60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Sinhala */
-
- /* 0D80 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, B, B, B,
- /* 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,
- /* 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,
-
-#define use_offset_0x0f00u 1456
-
-
- /* Tibetan */
-
- /* 0F00 */ B, B, O, O, B, B, B, O, O, O, O, O, O, O, O, O,
- /* 0F10 */ O, O, O, O, O, O, O, O, VBlw, VBlw, O, O, O, O, O, O,
- /* 0F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0F30 */ B, B, B, B, O, FBlw, O, FBlw, O, CMAbv, O, O, O, O, VPst, VPre,
- /* 0F40 */ B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, B,
- /* 0F50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
- /* 0F70 */ WJ, CMBlw, VBlw, VAbv, VAbv, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VMAbv, O,
- /* 0F80 */ VBlw, VAbv, VMAbv, VMAbv, VBlw, O, VMAbv, VMAbv, B, B, B, B, B, SUB, SUB, SUB,
- /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 0FA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, O, O,
- /* 0FC0 */ O, O, O, O, O, O, FBlw, O,
-
-#define use_offset_0x1000u 1656
-
-
- /* Myanmar */
-
- /* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1020 */ B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VAbv, VAbv, VBlw,
- /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B,
- /* 1040 */ B, B, B, B, B, B, B, B, B, B, O, GB, O, O, GB, O,
- /* 1050 */ B, B, B, B, B, B, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw,
- /* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B,
- /* 1070 */ B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B, B, B, B, B, B, B,
- /* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst,
- /* 1090 */ B, B, B, B, B, B, B, B, B, B, VMPst, VMPst, VPst, VAbv, O, O,
-
-#define use_offset_0x1700u 1816
-
-
- /* Tagalog */
-
- /* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1710 */ B, B, VAbv, VBlw, VBlw, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B,
-
- /* Hanunoo */
-
- /* 1720 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1730 */ B, B, VAbv, VBlw, VPst, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Buhid */
-
- /* 1740 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1750 */ B, B, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Tagbanwa */
-
- /* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B, B,
- /* 1770 */ B, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Khmer */
-
- /* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 17B0 */ B, B, B, B, CGJ, CGJ, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre,
- /* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FMAbv, FAbv, CMAbv, FMAbv, VMAbv,
- /* 17D0 */ FMAbv, VAbv, IS, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, WJ, WJ,
- /* 17E0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 17F0 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Mongolian */
-
- /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, CGJ, CGJ, CGJ, WJ, CGJ,
- /* 1810 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 1820 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1830 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1870 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 1880 */ GB, GB, GB, GB, GB, CMAbv, CMAbv, B, B, B, B, B, B, B, B, B,
- /* 1890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18A0 */ B, B, B, B, B, B, B, B, B, CMBlw, B, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x1900u 2248
-
-
- /* Limbu */
-
- /* 1900 */ GB, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ,
- /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, WJ, WJ, WJ, WJ,
- /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VMAbv, FMBlw, WJ, WJ, WJ, WJ,
- /* 1940 */ O, WJ, WJ, WJ, O, O, B, B, B, B, B, B, B, B, B, B,
-
- /* Tai Le */
-
- /* 1950 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ,
- /* 1970 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* New Tai Lue */
-
- /* 1980 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ,
- /* 19B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 19D0 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, O, O,
- /* 19E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 19F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Buginese */
-
- /* 1A00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A10 */ B, B, B, B, B, B, B, VAbv, VAbv, VPre, VPst, VAbv, WJ, WJ, O, O,
-
- /* Tai Tham */
-
- /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, WJ,
- /* 1A60 */ Sk, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre,
- /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, VMAbv, VMAbv, WJ, WJ, VMBlw,
- /* 1A80 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 1A90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x1b00u 2664
-
-
- /* Balinese */
-
- /* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre,
- /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
- /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 1B60 */ O, O, O, O, O, O, O, O, O, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
- /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, WJ,
-
- /* Sundanese */
-
- /* 1B80 */ VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, IS, SUB, SUB, B, B,
- /* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
-
- /* Batak */
-
- /* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BE0 */ B, B, B, B, B, B, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv,
- /* 1BF0 */ FAbv, FAbv, CMBlw, CMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O,
-
- /* Lepcha */
-
- /* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv,
- /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, WJ, WJ, WJ, O, O, O, O, O,
- /* 1C40 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B,
-
-#define use_offset_0x1cd0u 3000
-
-
- /* Vedic Extensions */
-
- /* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw,
- /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O,
- /* 1CF0 */ O, O, O, O, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, GB, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x1df8u 3048
-
-
- /* Combining Diacritical Marks Supplement */
- O, O, O, FMAbv, O, O, O, O,
-
-#define use_offset_0x2008u 3056
-
-
- /* General Punctuation */
- O, O, O, WJ, ZWNJ, CGJ, WJ, WJ,
- /* 2010 */ GB, GB, GB, GB, GB, O, O, O, O, O, O, O, O, O, O, O,
- /* 2020 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, O,
- /* 2030 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 2040 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 2050 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 2060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Superscripts and Subscripts */
-
- /* 2070 */ O, O, WJ, WJ, FMPst, O, O, O, O, O, O, O, O, O, O, O,
- /* 2080 */ O, O, FMPst, FMPst, FMPst, O, O, O,
-
-#define use_offset_0x20f0u 3184
-
-
- /* Combining Diacritical Marks for Symbols */
-
- /* 20F0 */ VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x25c8u 3192
-
-
- /* Geometric Shapes */
- O, O, O, O, B, O, O, O,
-
-#define use_offset_0x2d30u 3200
-
-
- /* Tifinagh */
-
- /* 2D30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D60 */ B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B,
- /* 2D70 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, H,
-
-#define use_offset_0xa800u 3280
-
-
- /* Syloti Nagri */
-
- /* A800 */ B, B, VAbv, B, B, B, H, B, B, B, B, VMAbv, B, B, B, B,
- /* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, VBlw, WJ, WJ, WJ,
- /* A830 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Phags-pa */
-
- /* A840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A870 */ B, B, B, B, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Saurashtra */
-
- /* A880 */ VMPst, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A8B0 */ B, B, B, B, MPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst,
- /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O,
- /* A8D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Devanagari Extended */
-
- /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
- /* A8F0 */ VMAbv, VMAbv, B, B, O, O, O, O, O, O, O, O, O, O, B, VAbv,
-
- /* Kayah Li */
-
- /* A900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A920 */ B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VAbv, VMBlw, VMBlw, VMBlw, O, O,
-
- /* Rejang */
-
- /* A930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A940 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VBlw, VBlw, VBlw, VBlw, FAbv,
- /* A950 */ FAbv, FAbv, FPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O,
- /* A960 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ,
-
- /* Javanese */
-
- /* A980 */ VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, MBlw, MPst, MBlw,
- /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O,
- /* A9D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O,
-
- /* Myanmar Extended-B */
-
- /* A9E0 */ B, B, B, B, B, VAbv, O, B, B, B, B, B, B, B, B, B,
- /* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ,
-
- /* Cham */
-
- /* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA20 */ B, B, B, B, B, B, B, B, B, VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre,
- /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MAbv, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, WJ, WJ,
- /* AA50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, O, O, O,
-
- /* Myanmar Extended-A */
-
- /* AA60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA70 */ O, B, B, B, GB, GB, GB, O, O, O, B, VMPst, VMAbv, VMPst, B, B,
-
- /* Tai Viet */
-
- /* AA80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AAA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AAB0 */ VAbv, B, VAbv, VAbv, VBlw, B, B, VAbv, VAbv, B, B, B, B, B, VAbv, VMAbv,
- /* AAC0 */ B, VMAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* AAD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O,
-
- /* Meetei Mayek Extensions */
-
- /* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst,
- /* AAF0 */ O, O, O, O, O, VMPst, IS, WJ,
-
-#define use_offset_0xabc0u 4040
-
-
- /* Meetei Mayek */
-
- /* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* ABD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, WJ, WJ,
- /* ABF0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0xfe00u 4104
-
-
- /* Variation Selectors */
-
- /* FE00 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
-
-#define use_offset_0xfef8u 4120
-
-
- /* Arabic Presentation Forms-B */
- O, O, O, O, O, WJ, WJ, WJ,
-
-#define use_offset_0xfff0u 4128
-
-
- /* Specials */
-
- /* FFF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, WJ, WJ,
-
-#define use_offset_0x10570u 4144
-
-
- /* Vithkuqi */
-
- /* 10570 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B,
- /* 10580 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B,
- /* 10590 */ B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B, B,
- /* 105A0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 105B0 */ B, B, WJ, B, B, B, B, B, B, B, WJ, B, B, WJ, WJ, WJ,
-
-#define use_offset_0x10a00u 4224
-
-
- /* Kharoshthi */
-
- /* 10A00 */ B, VBlw, VBlw, VBlw, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, VPst, VMBlw, VMBlw, VMAbv,
- /* 10A10 */ B, B, B, B, WJ, B, B, B, WJ, B, B, B, B, B, B, B,
- /* 10A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10A30 */ B, B, B, B, B, B, WJ, WJ, CMBlw, CMBlw, CMBlw, WJ, WJ, WJ, WJ, IS,
- /* 10A40 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x10ac0u 4304
-
-
- /* Manichaean */
-
- /* 10AC0 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B,
- /* 10AD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, WJ, WJ, WJ, WJ, B, B, B, B, B,
-
-#define use_offset_0x10b80u 4352
-
-
- /* Psalter Pahlavi */
-
- /* 10B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10B90 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, WJ, WJ, WJ,
- /* 10BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, O,
-
-#define use_offset_0x10d00u 4400
-
-
- /* Hanifi Rohingya */
-
- /* 10D00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10D20 */ B, B, B, B, VMAbv, VMAbv, VMAbv, CMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10D30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x10e80u 4464
-
-
- /* Yezidi */
-
- /* 10E80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10E90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10EA0 */ B, B, B, B, B, B, B, B, B, B, WJ, VAbv, VAbv, O, WJ, WJ,
- /* 10EB0 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x10f30u 4520
-
-
- /* Sogdian */
-
- /* 10F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10F40 */ B, B, B, B, B, B, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,
- /* 10F50 */ VMBlw, B, B, B, B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Old Uyghur */
-
- /* 10F70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10F80 */ B, B, CMBlw, CMBlw, CMBlw, CMBlw, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Chorasmian */
-
- /* 10FB0 */ B, O, B, B, B, B, B, O, B, B, B, B, B, B, B, B,
- /* 10FC0 */ O, B, B, B, B, O, O, O, O, B, B, B, WJ, WJ, WJ, WJ,
- /* 10FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10FE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 10FF0 */ O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Brahmi */
-
- /* 11000 */ VMPst, VMAbv, VMPst, CS, CS, B, B, B, B, B, B, B, B, B, B, B,
- /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw,
- /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, WJ, WJ,
- /* 11050 */ WJ, WJ, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
- /* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B,
- /* 11070 */ VAbv, B, B, VAbv, VAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, HN,
-
- /* Kaithi */
-
- /* 11080 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O,
- /* 110C0 */ O, O, VBlw, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x11100u 4928
-
-
- /* Chakma */
-
- /* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11120 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VBlw, VAbv, VAbv,
- /* 11130 */ VBlw, VAbv, VAbv, IS, CMAbv, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 11140 */ O, O, O, O, B, VPst, VPst, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Mahajani */
-
- /* 11150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11170 */ B, B, B, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Sharada */
-
- /* 11180 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,
- /* 111C0 */ H, B, R, R, O, O, O, O, O, FMBlw, CMBlw, VAbv, VBlw, O, VPre, VMAbv,
- /* 111D0 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O,
-
- /* Sinhala Archaic Numbers */
-
- /* 111E0 */ WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111F0 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Khojki */
-
- /* 11200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11210 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw,
- /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, WJ,
-
-#define use_offset_0x11280u 5248
-
-
- /* Multani */
-
- /* 11280 */ B, B, B, B, B, B, B, WJ, B, WJ, B, B, B, B, WJ, B,
- /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B,
- /* 112A0 */ B, B, B, B, B, B, B, B, B, O, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Khudawadi */
-
- /* 112B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv,
- /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, WJ, WJ, WJ, WJ, WJ,
- /* 112F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Grantha */
-
- /* 11300 */ VMAbv, VMAbv, VMAbv, VMAbv, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B,
- /* 11310 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11320 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 11330 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, CMBlw, CMBlw, B, VPst, VPst,
- /* 11340 */ VAbv, VPst, VPst, VPst, VPst, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ,
- /* 11350 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, O, B, B,
- /* 11360 */ B, B, VPst, VPst, WJ, WJ, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ,
- /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ,
-
-#define use_offset_0x11400u 5496
-
-
- /* Newa */
-
- /* 11400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv,
- /* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O,
- /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, WJ, O, FMAbv, B,
- /* 11460 */ CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Tirhuta */
-
- /* 11480 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv,
- /* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 114D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x11580u 5720
-
-
- /* Siddham */
-
- /* 11580 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
- /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H,
- /* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, WJ, WJ,
- /* 115E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 115F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Modi */
-
- /* 11600 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H,
- /* 11640 */ VAbv, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11650 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ,
- /* 11670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Takri */
-
- /* 11680 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst,
- /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, B, O, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 116C0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 116D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 116E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 116F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Ahom */
-
- /* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, MBlw, MPre, MAbv,
- /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ,
- /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
- /* 11740 */ B, B, B, B, B, B, B, WJ,
-
-#define use_offset_0x11800u 6176
-
-
- /* Dogra */
-
- /* 11800 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw,
- /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x11900u 6240
-
-
- /* Dives Akuru */
-
- /* 11900 */ B, B, B, B, B, B, B, WJ, WJ, B, WJ, WJ, B, B, B, B,
- /* 11910 */ B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B,
- /* 11920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11930 */ VPst, VPst, VPst, VPst, VPst, VPre, WJ, VPre, VPre, WJ, WJ, VMAbv, VMAbv, VPst, IS, R,
- /* 11940 */ MPst, R, MPst, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x119a0u 6336
-
-
- /* Nandinagari */
-
- /* 119A0 */ B, B, B, B, B, B, B, B, WJ, WJ, B, B, B, B, B, B,
- /* 119B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 119C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 119D0 */ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VAbv, VAbv, VPst, VPst, VMPst, VMPst,
- /* 119E0 */ H, B, O, O, VPre, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 119F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Zanabazar Square */
-
- /* 11A00 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, B, B, B, B, B,
- /* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A30 */ B, B, B, FMBlw, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB,
- /* 11A40 */ O, O, O, O, O, GB, O, IS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Soyombo */
-
- /* 11A50 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VBlw, VBlw, VBlw, B, B, B, B,
- /* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A80 */ B, B, B, B, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw,
- /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, IS, O, O, O, B, O, O,
-
-#define use_offset_0x11c00u 6592
-
-
- /* Bhaiksuki */
-
- /* 11C00 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 11C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
- /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H,
- /* 11C40 */ B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
-
- /* Marchen */
-
- /* 11C70 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C90 */ WJ, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, WJ,
-
-#define use_offset_0x11d00u 6776
-
-
- /* Masaram Gondi */
-
- /* 11D00 */ B, B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B,
- /* 11D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, WJ, WJ, WJ, VAbv, WJ, VAbv, VAbv, WJ, VAbv,
- /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, IS, R, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11D50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Gunjala Gondi */
-
- /* 11D60 */ B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B,
- /* 11D70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D80 */ B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VPst, VPst, WJ,
- /* 11D90 */ VAbv, VAbv, WJ, VPst, VPst, VMAbv, VMPst, IS, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x11ee0u 6952
-
-
- /* Makasar */
-
- /* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O,
-
-#define use_offset_0x13000u 6976
-
-
- /* Egyptian Hieroglyphs */
-
- /* 13000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13030 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13040 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13050 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13060 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13070 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13080 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13130 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13140 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13170 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13180 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13210 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13220 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13230 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13240 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13250 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13260 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13270 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13280 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13300 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13310 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13320 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13330 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13340 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13350 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13360 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13370 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13380 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13390 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ,
-
- /* Egyptian Hieroglyph Format Controls */
-
- /* 13430 */ H, H, H, H, H, H, H, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x16ac0u 8064
-
-
- /* Tangsa */
-
- /* 16AC0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 16AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 16AE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ,
- /* 16AF0 */ O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Pahawh Hmong */
-
- /* 16B00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16B30 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O,
-
-#define use_offset_0x16f00u 8184
-
-
- /* Miao */
-
- /* 16F00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F40 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, CMBlw,
- /* 16F50 */ O, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F60 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F70 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, VMBlw,
- /* 16F90 */ VMBlw, VMBlw, VMBlw, O, O, O, O, O,
-
-#define use_offset_0x16fe0u 8336
-
-
- /* Ideographic Symbols and Punctuation */
-
- /* 16FE0 */ O, O, O, O, B, WJ, WJ, WJ,
-
-#define use_offset_0x18b00u 8344
-
-
- /* Khitan Small Script */
-
- /* 18B00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BF0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CD0 */ B, B, B, B, B, B, WJ, WJ,
-
-#define use_offset_0x1bc00u 8816
-
-
- /* Duployan */
-
- /* 1BC00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC60 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ,
- /* 1BC70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
- /* 1BC80 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 1BC90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, CMBlw, CMBlw, O,
-
-#define use_offset_0x1d170u 8976
-
-
- /* Musical Symbols */
-
- /* 1D170 */ O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O,
-
-#define use_offset_0x1e100u 8992
-
-
- /* Nyiakeng Puachue Hmong */
-
- /* 1E100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
- /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, WJ, WJ,
- /* 1E140 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B, B,
-
-#define use_offset_0x1e290u 9072
-
-
- /* Toto */
-
- /* 1E290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E2A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, WJ,
- /* 1E2B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Wancho */
-
- /* 1E2C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E2D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E2E0 */ B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv,
- /* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, O,
-
-#define use_offset_0x1e900u 9184
-
-
- /* Adlam */
-
- /* 1E900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, WJ, WJ, WJ, WJ,
- /* 1E950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O,
-
-#define use_offset_0xe0000u 9280
-
-
- /* Tags */
-
- /* E0000 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0010 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0020 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0030 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0040 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0050 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0070 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* No_Block */
-
- /* E0080 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0090 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Variation Selectors Supplement */
-
- /* E0100 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0110 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0120 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0130 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0140 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0150 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0160 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0170 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0180 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0190 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01A0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01B0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01C0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01D0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01E0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
-
- /* No_Block */
-
- /* E01F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0200 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0210 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0220 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0230 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0240 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0250 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0260 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0270 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0280 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0290 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0300 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0310 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0320 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0330 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0340 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0350 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0360 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0370 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0380 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0390 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0400 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0410 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0420 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0430 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0440 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0450 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0460 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0480 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0490 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0500 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0510 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0520 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0530 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0540 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0550 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0560 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0570 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0580 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0590 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0600 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0610 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0620 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0630 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0640 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0650 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0660 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0680 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0690 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0700 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0710 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0720 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0730 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0740 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0750 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0760 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0770 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0780 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0790 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0800 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0810 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0820 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0830 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0840 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0850 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0860 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0870 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0880 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0890 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0900 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0910 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0920 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0930 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0940 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0950 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0960 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0970 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0980 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0990 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0ED0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
-}; /* Table items: 13376; occupancy: 84% */
-
-static inline uint8_t
-hb_use_get_category (hb_glyph_info_t info)
-{
- hb_codepoint_t u = info.codepoint;
- switch (u >> 12)
- {
- case 0x0u:
- if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
- if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0640u, 0x0647u)) return use_table[u - 0x0640u + use_offset_0x0640u];
- if (hb_in_range<hb_codepoint_t> (u, 0x07C8u, 0x07FFu)) return use_table[u - 0x07C8u + use_offset_0x07c8u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0840u, 0x085Fu)) return use_table[u - 0x0840u + use_offset_0x0840u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0F00u, 0x0FC7u)) return use_table[u - 0x0F00u + use_offset_0x0f00u];
- break;
-
- case 0x1u:
- if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1700u, 0x18AFu)) return use_table[u - 0x1700u + use_offset_0x1700u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u];
- break;
-
- case 0x2u:
- if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2087u)) return use_table[u - 0x2008u + use_offset_0x2008u];
- if (hb_in_range<hb_codepoint_t> (u, 0x20F0u, 0x20F7u)) return use_table[u - 0x20F0u + use_offset_0x20f0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x25C8u, 0x25CFu)) return use_table[u - 0x25C8u + use_offset_0x25c8u];
- if (hb_in_range<hb_codepoint_t> (u, 0x2D30u, 0x2D7Fu)) return use_table[u - 0x2D30u + use_offset_0x2d30u];
- break;
-
- case 0xAu:
- if (hb_in_range<hb_codepoint_t> (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u];
- if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
- break;
-
- case 0xFu:
- if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u];
- if (hb_in_range<hb_codepoint_t> (u, 0xFEF8u, 0xFEFFu)) return use_table[u - 0xFEF8u + use_offset_0xfef8u];
- if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u];
- break;
-
- case 0x10u:
- if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10570u, 0x105BFu)) return use_table[u - 0x10570u + use_offset_0x10570u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A4Fu)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return use_table[u - 0x10B80u + use_offset_0x10b80u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D3Fu)) return use_table[u - 0x10D00u + use_offset_0x10d00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10E80u, 0x10EB7u)) return use_table[u - 0x10E80u + use_offset_0x10e80u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
- break;
-
- case 0x11u:
- if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x11747u)) return use_table[u - 0x11580u + use_offset_0x11580u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11800u, 0x1183Fu)) return use_table[u - 0x11800u + use_offset_0x11800u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11900u, 0x1195Fu)) return use_table[u - 0x11900u + use_offset_0x11900u];
- if (hb_in_range<hb_codepoint_t> (u, 0x119A0u, 0x11A9Fu)) return use_table[u - 0x119A0u + use_offset_0x119a0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11D00u, 0x11DAFu)) return use_table[u - 0x11D00u + use_offset_0x11d00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11EE0u, 0x11EF7u)) return use_table[u - 0x11EE0u + use_offset_0x11ee0u];
- break;
-
- case 0x13u:
- if (hb_in_range<hb_codepoint_t> (u, 0x13000u, 0x1343Fu)) return use_table[u - 0x13000u + use_offset_0x13000u];
- break;
-
- case 0x16u:
- if (hb_in_range<hb_codepoint_t> (u, 0x16AC0u, 0x16B37u)) return use_table[u - 0x16AC0u + use_offset_0x16ac0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x16F00u, 0x16F97u)) return use_table[u - 0x16F00u + use_offset_0x16f00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x16FE0u, 0x16FE7u)) return use_table[u - 0x16FE0u + use_offset_0x16fe0u];
- break;
-
- case 0x18u:
- if (hb_in_range<hb_codepoint_t> (u, 0x18B00u, 0x18CD7u)) return use_table[u - 0x18B00u + use_offset_0x18b00u];
- break;
-
- case 0x1Bu:
- if (hb_in_range<hb_codepoint_t> (u, 0x1BC00u, 0x1BC9Fu)) return use_table[u - 0x1BC00u + use_offset_0x1bc00u];
- break;
-
- case 0x1Du:
- if (hb_in_range<hb_codepoint_t> (u, 0x1D170u, 0x1D17Fu)) return use_table[u - 0x1D170u + use_offset_0x1d170u];
- break;
-
- case 0x1Eu:
- if (hb_in_range<hb_codepoint_t> (u, 0x1E100u, 0x1E14Fu)) return use_table[u - 0x1E100u + use_offset_0x1e100u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1E290u, 0x1E2FFu)) return use_table[u - 0x1E290u + use_offset_0x1e290u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E95Fu)) return use_table[u - 0x1E900u + use_offset_0x1e900u];
- break;
-
- case 0xE0u:
- if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u];
- break;
-
- case 0xE1u:
- if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u];
- break;
-
- default:
- break;
- }
- if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED)
- return WJ;
- return O;
-}
-
-#undef B
-#undef CGJ
-#undef CS
-#undef G
-#undef GB
-#undef H
-#undef HN
-#undef IS
-#undef J
-#undef N
-#undef O
-#undef R
-#undef SB
-#undef SE
-#undef SUB
-#undef Sk
-#undef WJ
-#undef ZWNJ
-#undef CMAbv
-#undef CMBlw
-#undef FAbv
-#undef FBlw
-#undef FPst
-#undef FMAbv
-#undef FMBlw
-#undef FMPst
-#undef MAbv
-#undef MBlw
-#undef MPst
-#undef MPre
-#undef SMAbv
-#undef SMBlw
-#undef VAbv
-#undef VBlw
-#undef VPst
-#undef VPre
-#undef VMAbv
-#undef VMBlw
-#undef VMPst
-#undef VMPre
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_TABLE_HH */
-/* == End of generated table == */
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..7f679cfd39 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"
@@ -53,11 +53,11 @@ _hb_codepoint_is_regional_indicator (hb_codepoint_t u)
#ifndef HB_NO_AAT_SHAPE
static inline bool
-_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t *props)
+_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t &props)
{
/* https://github.com/harfbuzz/harfbuzz/issues/2124 */
return hb_aat_layout_has_substitution (face) &&
- (HB_DIRECTION_IS_HORIZONTAL (props->direction) || !hb_ot_layout_has_substitution (face));
+ (HB_DIRECTION_IS_HORIZONTAL (props.direction) || !hb_ot_layout_has_substitution (face));
}
#endif
@@ -77,23 +77,23 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
unsigned int num_user_features);
hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face,
- const hb_segment_properties_t *props) :
+ const hb_segment_properties_t &props) :
face (face),
- props (*props),
+ props (props),
map (face, props),
aat_map (face, props)
#ifndef HB_NO_AAT_SHAPE
, 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
@@ -225,7 +225,7 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face,
#endif
hb_ot_shape_planner_t planner (face,
- &key->props);
+ key->props);
hb_ot_shape_collect_features (&planner,
key->user_features,
@@ -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);
@@ -1141,6 +1141,18 @@ hb_propagate_flags (hb_buffer_t *buffer)
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS))
return;
+ /* If we are producing SAFE_TO_INSERT_TATWEEL, then do two things:
+ *
+ * - If the places that the Arabic shaper marked as SAFE_TO_INSERT_TATWEEL,
+ * are UNSAFE_TO_BREAK, then clear the SAFE_TO_INSERT_TATWEEL,
+ * - Any place that is SAFE_TO_INSERT_TATWEEL, is also now UNSAFE_TO_BREAK.
+ *
+ * We couldn't make this interaction earlier. It has to be done here.
+ */
+ bool flip_tatweel = buffer->flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL;
+
+ bool clear_concat = (buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0;
+
hb_glyph_info_t *info = buffer->info;
foreach_cluster (buffer, start, end)
@@ -1148,9 +1160,20 @@ hb_propagate_flags (hb_buffer_t *buffer)
unsigned int mask = 0;
for (unsigned int i = start; i < end; i++)
mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED;
- if (mask)
- for (unsigned int i = start; i < end; i++)
- info[i].mask |= mask;
+
+ if (flip_tatweel)
+ {
+ if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
+ mask &= ~HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL;
+ if (mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL)
+ mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
+ }
+
+ if (clear_concat)
+ mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
+
+ for (unsigned int i = start; i < end; i++)
+ info[i].mask = mask;
}
}
@@ -1159,8 +1182,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..cd6f15cbe2 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.hh
@@ -60,8 +60,10 @@ struct hb_shape_plan_key_t;
struct hb_ot_shape_plan_t
{
+ ~hb_ot_shape_plan_t () { fini (); }
+
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,10 +160,10 @@ 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);
+ const hb_segment_properties_t &props);
HB_INTERNAL void compile (hb_ot_shape_plan_t &plan,
const hb_ot_shape_plan_key_t &key);
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..ed2748b828 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;
@@ -193,26 +201,24 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
* work. However, testing shows that rlig and calt are applied
* together for Mongolian in Uniscribe. As such, we only add a
* pause for Arabic, not other scripts.
- *
- * A pause after calt is required to make KFGQPC Uthmanic Script HAFS
- * work correctly. See https://github.com/harfbuzz/harfbuzz/issues/505
*/
map->enable_feature (HB_TAG('s','t','c','h'));
map->add_gsub_pause (record_stch);
- map->enable_feature (HB_TAG('c','c','m','p'));
- map->enable_feature (HB_TAG('l','o','c','l'));
+ map->enable_feature (HB_TAG('c','c','m','p'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('l','o','c','l'), F_MANUAL_ZWJ);
map->add_gsub_pause (nullptr);
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
{
bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
- map->add_feature (arabic_features[i], has_fallback ? F_HAS_FALLBACK : F_NONE);
+ map->add_feature (arabic_features[i], F_MANUAL_ZWJ | (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
@@ -223,10 +229,16 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
if (plan->props.script == HB_SCRIPT_ARABIC)
map->add_gsub_pause (arabic_fallback_shape);
- /* No pause after rclt. See 98460779bae19e4d64d29461ff154b3527bf8420. */
- map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
- map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
- map->add_gsub_pause (nullptr);
+ map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
+ /* https://github.com/harfbuzz/harfbuzz/issues/1573 */
+ if (!map->has_feature (HB_TAG('r','c','l','t')))
+ {
+ map->add_gsub_pause (nullptr);
+ map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
+ }
+
+ map->enable_feature (HB_TAG('l','i','g','a'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('c','l','i','g'), F_MANUAL_ZWJ);
/* The spec includes 'cswh'. Earlier versions of Windows
* used to enable this by default, but testing suggests
@@ -236,11 +248,11 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
* Note that IranNastaliq uses this feature extensively
* to fixup broken glyph sequences. Oh well...
* Test case: U+0643,U+0640,U+0631. */
- //map->enable_feature (HB_TAG('c','s','w','h'));
- map->enable_feature (HB_TAG('m','s','e','t'));
+ //map->enable_feature (HB_TAG('c','s','w','h'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('m','s','e','t'), F_MANUAL_ZWJ);
}
-#include "hb-ot-shape-complex-arabic-fallback.hh"
+#include "hb-ot-shaper-arabic-fallback.hh"
struct arabic_shape_plan_t
{
@@ -319,7 +331,7 @@ arabic_joining (hb_buffer_t *buffer)
if (entry->prev_action != NONE && prev != UINT_MAX)
{
info[prev].arabic_shaping_action() = entry->prev_action;
- buffer->unsafe_to_break (prev, i + 1);
+ buffer->safe_to_insert_tatweel (prev, i + 1);
}
else
{
@@ -353,7 +365,7 @@ arabic_joining (hb_buffer_t *buffer)
if (entry->prev_action != NONE && prev != UINT_MAX)
{
info[prev].arabic_shaping_action() = entry->prev_action;
- buffer->unsafe_to_break (prev, buffer->len);
+ buffer->safe_to_insert_tatweel (prev, buffer->len);
}
else if (2 <= state && state <= 5) /* States that have a possible prev_action. */
{
@@ -405,7 +417,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 +631,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 +699,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 +730,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 */
@@ -728,12 +738,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
data_destroy_arabic,
nullptr, /* preprocess_text */
postprocess_glyphs_arabic,
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
nullptr, /* compose */
setup_masks_arabic,
- HB_TAG_NONE, /* gpos_tag */
reorder_marks_arabic,
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
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..2f6f499eec 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 */
@@ -39,19 +39,19 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
nullptr, /* compose */
nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
/* 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 */
@@ -59,12 +59,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_dumber =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
nullptr, /* compose */
nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc
index 3bc9e9b961..c90476bc46 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,
@@ -422,12 +422,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
data_destroy_hangul,
preprocess_text_hangul,
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
nullptr, /* decompose */
nullptr, /* compose */
setup_masks_hangul,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hebrew.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc
index 334d3ded82..e18edd6b3f 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
@@ -89,7 +89,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
found = true;
}
break;
- case 0x05B7u: /* patah */
+ case 0x05B7u: /* PATAH */
if (a == 0x05F2u) { /* YIDDISH YOD YOD */
*ab = 0xFB1Fu;
found = true;
@@ -162,8 +162,34 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
return found;
}
+static void
+reorder_marks_hebrew (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ unsigned int start,
+ unsigned int end)
+{
+ hb_glyph_info_t *info = buffer->info;
+
+ for (unsigned i = start + 2; i < end; i++)
+ {
+ unsigned c0 = info_cc (info[i - 2]);
+ unsigned c1 = info_cc (info[i - 1]);
+ unsigned c2 = info_cc (info[i - 0]);
+
+ if ((c0 == HB_MODIFIED_COMBINING_CLASS_CCC17 || c0 == HB_MODIFIED_COMBINING_CLASS_CCC18) /* patach or qamats */ &&
+ (c1 == HB_MODIFIED_COMBINING_CLASS_CCC10 || c1 == HB_MODIFIED_COMBINING_CLASS_CCC14) /* sheva or hiriq */ &&
+ (c2 == HB_MODIFIED_COMBINING_CLASS_CCC22 || c2 == HB_UNICODE_COMBINING_CLASS_BELOW) /* meteg or below */)
+ {
+ buffer->merge_clusters (i - 1, i + 1);
+ hb_swap (info[i - 1], info[i]);
+ break;
+ }
+ }
-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 */
@@ -171,12 +197,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
compose_hebrew,
nullptr, /* setup_masks */
+ reorder_marks_hebrew,
HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */
- nullptr, /* reorder_marks */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
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..d3a7cce3de
--- /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 54 "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 74 "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 415 "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 427 "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 439 "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 521 "hb-ot-shaper-indic-machine.hh"
+ }
+
+_again:
+ switch ( _indic_syllable_machine_to_state_actions[cs] ) {
+ case 9:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 528 "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..6eb400ab16 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,79 @@
*/
+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_;
+ lookups = map->get_stage_lookups (0/*GSUB*/,
+ map->get_feature_stage (0/*GSUB*/, feature_tag));
+ }
+
+ bool would_substitute (const hb_codepoint_t *glyphs,
+ unsigned int glyphs_count,
+ hb_face_t *face) const
+ {
+ for (const auto &lookup : lookups)
+ if (hb_ot_layout_lookup_would_substitute (face, lookup.index, glyphs, glyphs_count, zero_context))
+ return true;
+ return false;
+ }
+
+ private:
+ hb_array_t<const hb_ot_map_t::lookup_map_t> lookups;
+ 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 +120,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 +141,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 +149,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 +268,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 +418,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 +430,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 +442,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 +476,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 +512,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 +530,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 +539,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 +638,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 +674,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 +696,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 +729,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 +860,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 +890,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 +923,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 +966,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 +989,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 +1001,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 +1067,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 +1116,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 +1133,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 +1206,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 +1316,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 +1376,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 +1425,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 +1463,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 +1498,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 +1518,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,
@@ -1556,12 +1526,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
data_destroy_indic,
preprocess_text_indic,
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
decompose_indic,
compose_indic,
setup_masks_indic,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
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..2c40663bdd
--- /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 49 "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 65 "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 287 "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 299 "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 311 "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 368 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+_again:
+ switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
+ case 6:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 375 "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..d9795589fa 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,
@@ -357,12 +368,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_khmer =
data_destroy_khmer,
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
decompose_khmer,
compose_khmer,
setup_masks_khmer,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
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..464cf796d4
--- /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 51 "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 76 "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 436 "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 448 "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 460 "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 498 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+_again:
+ switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
+ case 1:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 505 "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..78bd8de524 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 */
@@ -282,12 +320,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
nullptr, /* decompose */
nullptr, /* compose */
setup_masks_myanmar,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
false, /* fallback_position */
};
@@ -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 */
@@ -304,12 +342,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
nullptr, /* decompose */
nullptr, /* compose */
nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
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..15349b1e64 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 */
@@ -379,12 +379,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
nullptr, /* data_destroy */
preprocess_text_thai,
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
nullptr, /* compose */
nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
false,/* fallback_position */
};
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..5b3ec05616
--- /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 54 "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 96 "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 773 "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 782 "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 794 "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 866 "hb-ot-shaper-use-machine.hh"
+ }
+
+_again:
+ switch ( _use_syllable_machine_to_state_actions[cs] ) {
+ case 1:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 873 "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-shaper-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
new file mode 100644
index 0000000000..e45ea30e60
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
@@ -0,0 +1,418 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.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]
+ * # ArabicShaping-14.0.0.txt
+ * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
+ * # DerivedCoreProperties-14.0.0.txt
+ * # Date: 2021-08-12, 23:12:53 GMT
+ * # Blocks-14.0.0.txt
+ * # Date: 2021-01-22, 23:29:00 GMT [KW]
+ * # Scripts-14.0.0.txt
+ * # Date: 2021-07-10, 00:35:31 GMT
+ * # Override values For Indic_Syllabic_Category
+ * # Not derivable
+ * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
+ * # Override values For Indic_Positional_Category
+ * # Not derivable
+ * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
+ * # Updated for L2/19-083 by Andrew Glass 2019-05-06
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
+ * UnicodeData.txt does not have a header.
+ */
+
+#ifndef HB_OT_SHAPER_USE_TABLE_HH
+#define HB_OT_SHAPER_USE_TABLE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper-use-machine.hh"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+#define B USE(B) /* BASE */
+#define CGJ USE(CGJ) /* CGJ */
+#define CS USE(CS) /* CONS_WITH_STACKER */
+#define G USE(G) /* HIEROGLYPH */
+#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 */
+#define O USE(O) /* OTHER */
+#define R USE(R) /* REPHA */
+#define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
+#define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */
+#define SUB USE(SUB) /* CONS_SUB */
+#define Sk USE(Sk) /* SAKOT */
+#define WJ USE(WJ) /* Word_Joiner */
+#define ZWNJ USE(ZWNJ) /* ZWNJ */
+#define CMAbv USE(CMAbv)
+#define CMBlw USE(CMBlw)
+#define FAbv USE(FAbv)
+#define FBlw USE(FBlw)
+#define FPst USE(FPst)
+#define FMAbv USE(FMAbv)
+#define FMBlw USE(FMBlw)
+#define FMPst USE(FMPst)
+#define MAbv USE(MAbv)
+#define MBlw USE(MBlw)
+#define MPst USE(MPst)
+#define MPre USE(MPre)
+#define SMAbv USE(SMAbv)
+#define SMBlw USE(SMBlw)
+#define VAbv USE(VAbv)
+#define VBlw USE(VBlw)
+#define VPst USE(VPst)
+#define VPre USE(VPre)
+#define VMAbv USE(VMAbv)
+#define VMBlw USE(VMBlw)
+#define VMPst USE(VMPst)
+#define VMPre USE(VMPre)
+#pragma GCC diagnostic pop
+
+static const uint8_t
+hb_use_u8[3083] =
+{
+ 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 14, 0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 4, 2, 2,
+ 5, 6, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 2, 2, 17,
+ 18, 19, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 2, 33, 2, 2, 2,
+ 2, 34, 35, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 37, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 38, 39, 40, 41, 42, 43, 2, 44, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 46, 2,
+ 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 48, 49, 2, 2, 2,
+ 2, 2, 2, 2, 2, 50, 51, 2, 52, 2, 2, 53, 2, 2, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 2, 64, 65, 2, 66, 67, 68, 69,
+ 2, 70, 2, 71, 72, 73, 74, 2, 2, 75, 76, 77, 78, 2, 79, 2,
+ 2, 80, 80, 80, 80, 80, 80, 80, 80, 81, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 82, 83, 2, 2, 2, 2, 2, 2, 2, 84,
+ 85, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 80, 80, 80, 86, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 87, 88, 2, 2, 2, 2, 2,
+ 2, 2, 2, 89, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 90, 2, 2, 91, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 93, 93, 94, 95, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4,
+ 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 8, 9, 9, 9, 9, 0, 0, 0, 7, 10,
+ 0, 2, 2, 2, 2, 11, 12, 0, 0, 9, 13, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 14, 15, 16, 17, 18, 19, 20, 14, 21, 22,
+ 23, 10, 24, 25, 18, 2, 2, 2, 2, 2, 18, 0, 2, 2, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 26, 27, 28, 2, 2, 2, 7,
+ 28, 7, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, 2,
+ 2, 7, 7, 0, 2, 2, 0, 15, 16, 17, 18, 29, 30, 31, 30, 32,
+ 0, 0, 0, 0, 33, 0, 0, 2, 28, 2, 0, 0, 0, 0, 0, 7,
+ 34, 10, 13, 28, 2, 2, 7, 0, 28, 7, 2, 28, 7, 2, 0, 35,
+ 16, 17, 29, 0, 25, 36, 25, 37, 0, 38, 0, 0, 0, 28, 2, 7,
+ 7, 0, 0, 0, 2, 2, 2, 2, 2, 39, 40, 41, 0, 0, 0, 0,
+ 0, 10, 13, 28, 2, 2, 2, 2, 28, 2, 28, 2, 2, 2, 2, 2,
+ 2, 7, 2, 28, 2, 2, 0, 15, 16, 17, 18, 19, 25, 20, 33, 22,
+ 0, 0, 0, 0, 0, 28, 9, 39, 42, 10, 27, 28, 2, 2, 2, 7,
+ 28, 7, 2, 28, 2, 2, 0, 15, 43, 0, 0, 25, 20, 0, 0, 2,
+ 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 44, 28, 2, 2, 7, 0,
+ 2, 7, 2, 2, 0, 28, 7, 7, 2, 0, 28, 7, 0, 2, 7, 0,
+ 2, 2, 2, 2, 2, 2, 0, 0, 21, 14, 45, 0, 46, 31, 46, 32,
+ 0, 0, 0, 0, 33, 0, 0, 0, 0, 13, 27, 47, 2, 2, 2, 7,
+ 2, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 15,
+ 20, 14, 21, 45, 20, 36, 20, 37, 0, 0, 0, 25, 29, 2, 7, 0,
+ 0, 8, 27, 28, 2, 2, 2, 7, 2, 2, 2, 28, 2, 2, 0, 15,
+ 43, 0, 0, 33, 45, 0, 0, 0, 7, 48, 49, 0, 0, 0, 0, 0,
+ 0, 9, 27, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 50, 51,
+ 21, 21, 17, 29, 46, 31, 46, 32, 52, 0, 0, 0, 33, 0, 0, 0,
+ 28, 10, 27, 28, 2, 2, 2, 2, 2, 2, 2, 2, 7, 0, 2, 2,
+ 2, 2, 28, 2, 2, 2, 2, 28, 0, 2, 2, 2, 7, 0, 53, 0,
+ 33, 21, 20, 29, 29, 16, 46, 46, 23, 0, 21, 0, 0, 0, 0, 0,
+ 0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0,
+ 0, 2, 2, 54, 54, 55, 0, 0, 16, 2, 2, 2, 2, 28, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 7, 0, 56, 19, 57, 20, 20, 18, 18,
+ 44, 19, 9, 29, 9, 2, 2, 58, 59, 59, 59, 59, 59, 60, 59, 59,
+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61,
+ 0, 0, 0, 0, 62, 0, 0, 0, 0, 2, 2, 2, 2, 2, 63, 43,
+ 57, 64, 20, 20, 65, 66, 67, 68, 69, 2, 2, 2, 2, 2, 1, 0,
+ 3, 2, 2, 2, 21, 18, 2, 2, 70, 69, 71, 72, 63, 71, 27, 27,
+ 2, 50, 20, 51, 2, 2, 2, 2, 2, 2, 73, 74, 75, 27, 27, 76,
+ 77, 2, 2, 2, 2, 2, 27, 43, 0, 2, 57, 78, 0, 0, 0, 0,
+ 28, 2, 57, 45, 0, 0, 0, 0, 0, 2, 57, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 2, 7, 2, 7, 57, 0, 0, 0, 0, 0,
+ 0, 2, 2, 79, 43, 20, 57, 18, 46, 46, 46, 46, 13, 80, 81, 82,
+ 83, 84, 85, 0, 0, 0, 0, 86, 0, 7, 0, 0, 28, 0, 87, 79,
+ 88, 2, 2, 2, 2, 7, 0, 0, 0, 40, 40, 89, 90, 2, 2, 2,
+ 2, 2, 2, 2, 2, 11, 7, 0, 0, 91, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 7, 20, 78, 43, 20, 92, 59, 0,
+ 0, 93, 94, 93, 93, 95, 96, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0,
+ 0, 2, 2, 2, 2, 27, 0, 0, 0, 2, 2, 2, 2, 2, 7, 0,
+ 0, 2, 2, 2, 50, 97, 43, 0, 0, 2, 2, 98, 99, 100, 101, 59,
+ 61, 102, 14, 43, 20, 57, 19, 78, 46, 46, 74, 9, 9, 9, 103, 44,
+ 38, 9, 104, 72, 2, 2, 2, 2, 2, 2, 2, 105, 20, 18, 18, 20,
+ 46, 46, 20, 106, 2, 2, 2, 7, 0, 0, 0, 0, 0, 0, 107, 108,
+ 109, 109, 109, 0, 0, 0, 0, 0, 0, 104, 72, 2, 2, 2, 2, 2,
+ 2, 58, 59, 57, 23, 20, 110, 59, 2, 2, 2, 2, 105, 20, 21, 43,
+ 43, 100, 12, 0, 0, 0, 0, 0, 0, 2, 2, 59, 16, 46, 21, 111,
+ 100, 100, 100, 112, 113, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 28,
+ 2, 9, 44, 114, 114, 114, 9, 114, 114, 13, 114, 114, 114, 24, 0, 38,
+ 0, 0, 0, 115, 116, 9, 3, 0, 0, 0, 0, 0, 0, 0, 117, 0,
+ 0, 0, 0, 0, 0, 0, 4, 118, 119, 40, 40, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 119, 119, 120, 119, 119, 119, 119, 119, 119, 119,
+ 119, 0, 0, 121, 0, 0, 0, 0, 0, 0, 5, 121, 0, 0, 0, 0,
+ 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
+ 0, 2, 2, 2, 2, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0,
+ 122, 2, 51, 2, 106, 2, 8, 2, 2, 2, 63, 17, 14, 0, 0, 29,
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 27, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 123, 21, 21, 21, 21, 21, 21, 21, 124, 0, 0, 0, 0,
+ 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0,
+ 50, 2, 2, 2, 20, 20, 125, 114, 0, 2, 2, 2, 126, 18, 57, 18,
+ 111, 100, 127, 0, 0, 0, 0, 0, 0, 9, 128, 2, 2, 2, 2, 2,
+ 2, 2, 129, 21, 20, 18, 46, 130, 131, 132, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 50, 28, 2, 2, 2, 2, 2, 2, 2, 2, 8, 20, 57,
+ 97, 74, 133, 134, 135, 0, 0, 0, 0, 2, 136, 2, 2, 2, 2, 137,
+ 0, 28, 2, 40, 3, 0, 77, 13, 2, 51, 20, 138, 50, 51, 2, 2,
+ 103, 8, 7, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 139, 19,
+ 23, 0, 0, 140, 141, 0, 0, 0, 0, 2, 63, 43, 21, 78, 45, 142,
+ 0, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0,
+ 4, 119, 119, 119, 119, 120, 0, 0, 0, 2, 2, 2, 2, 2, 7, 2,
+ 2, 2, 7, 2, 28, 2, 2, 2, 2, 2, 28, 2, 2, 2, 28, 7,
+ 0, 126, 18, 25, 29, 0, 0, 143, 144, 2, 2, 28, 2, 28, 2, 2,
+ 2, 2, 2, 2, 0, 12, 35, 0, 145, 2, 2, 11, 35, 0, 28, 2,
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 2, 2,
+ 7, 2, 2, 9, 39, 0, 0, 0, 0, 2, 2, 2, 2, 2, 25, 36,
+ 0, 2, 2, 2, 114, 114, 114, 114, 114, 146, 2, 7, 0, 0, 0, 0,
+ 0, 2, 12, 12, 0, 0, 0, 0, 0, 7, 2, 2, 7, 2, 2, 2,
+ 2, 28, 2, 7, 0, 28, 2, 0, 0, 147, 148, 149, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 20, 20, 18, 18, 18, 20, 20, 132, 0, 0, 0,
+ 0, 0, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 2, 2, 2, 2,
+ 2, 51, 50, 51, 0, 0, 0, 0, 151, 9, 72, 2, 2, 2, 2, 2,
+ 2, 16, 17, 19, 14, 22, 35, 0, 0, 0, 29, 0, 0, 0, 0, 0,
+ 0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 126, 18, 20, 152,
+ 20, 19, 153, 154, 2, 2, 2, 2, 2, 0, 0, 63, 155, 0, 0, 0,
+ 0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20,
+ 20, 106, 156, 0, 0, 157, 158, 29, 159, 28, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 160, 42, 0, 0, 0,
+ 44, 2, 2, 2, 7, 7, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2,
+ 28, 2, 2, 2, 2, 2, 2, 2, 8, 16, 17, 19, 20, 161, 29, 0,
+ 0, 9, 9, 28, 2, 2, 2, 7, 28, 7, 2, 28, 2, 2, 56, 15,
+ 21, 14, 21, 45, 30, 31, 30, 32, 0, 0, 0, 0, 33, 0, 0, 0,
+ 2, 2, 21, 0, 9, 9, 9, 44, 0, 9, 9, 44, 0, 0, 0, 0,
+ 0, 2, 2, 63, 23, 18, 18, 18, 20, 21, 124, 13, 15, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 0, 0, 162, 163, 0, 0, 0, 0, 0, 0,
+ 0, 16, 17, 18, 18, 64, 97, 23, 159, 9, 164, 7, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 2, 2, 63, 23, 18, 18, 0, 46, 46, 9,
+ 165, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 18,
+ 0, 21, 17, 18, 18, 19, 14, 80, 165, 36, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 8, 166, 23, 18, 20, 20, 164, 7, 0, 0,
+ 0, 2, 2, 2, 2, 2, 7, 41, 134, 21, 20, 18, 74, 19, 20, 0,
+ 0, 2, 2, 2, 7, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 16,
+ 17, 18, 19, 20, 103, 165, 35, 0, 0, 2, 2, 2, 7, 28, 0, 2,
+ 2, 2, 2, 28, 7, 2, 2, 2, 2, 21, 21, 16, 30, 31, 10, 167,
+ 168, 169, 170, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2,
+ 2, 63, 23, 18, 18, 0, 20, 21, 27, 106, 0, 31, 0, 0, 0, 0,
+ 0, 50, 18, 20, 20, 20, 138, 2, 2, 2, 171, 172, 9, 13, 173, 70,
+ 174, 0, 0, 1, 145, 0, 0, 0, 0, 50, 18, 20, 14, 17, 18, 2,
+ 2, 2, 2, 156, 156, 156, 175, 175, 175, 175, 175, 175, 13, 176, 0, 28,
+ 0, 20, 18, 18, 29, 20, 20, 9, 165, 0, 59, 59, 59, 59, 59, 59,
+ 59, 64, 19, 80, 44, 0, 0, 0, 0, 2, 2, 2, 7, 2, 28, 2,
+ 2, 50, 20, 20, 29, 0, 36, 20, 25, 9, 158, 177, 173, 0, 0, 0,
+ 0, 2, 2, 2, 28, 7, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21,
+ 45, 20, 33, 80, 66, 0, 0, 0, 0, 2, 178, 64, 45, 0, 0, 0,
+ 0, 179, 179, 179, 106, 7, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 7, 0, 56, 180, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,
+ 38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56,
+ 35, 0, 4, 119, 119, 119, 120, 0, 0, 9, 9, 9, 47, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ 44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 42, 42, 42, 90, 0,
+ 0, O, O, O, GB, B, B, GB, O, O, WJ,FMPst,FMPst, O, CGJ, B,
+ O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,
+ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre,
+ VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,VMPst, O, B, VBlw, O, O, VPre, VPre,
+ O, VPre, H, O, VPst,FMAbv, O,CMBlw, O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,
+ CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst, VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv,
+ B, O, CS, CS, O, B, VAbv, VAbv, B, R, O, HVM, O, O, FBlw, O,
+ CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB, SUB, O, SUB, SUB, O, FBlw, O, B,
+ VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,
+ VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ,
+ CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B,
+ CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst,
+ FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,
+ VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw,
+ FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, CS,VMPst, O,FMAbv, ZWNJ, CGJ, WJ,
+ WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst,
+ VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw,
+ O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,
+ VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O,
+ HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R, O,FMBlw,CMBlw, VAbv, VPre,
+ VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv,
+ VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, MBlw, MBlw, GB, FBlw,
+ FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, H, H, O, VBlw,
+};
+static const uint16_t
+hb_use_u16[768] =
+{
+ 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 11,
+ 0, 0, 0, 0, 9, 12, 0, 0, 13, 9, 9, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 17, 25, 26, 20, 21, 27, 28, 29, 30, 31,
+ 32, 33, 21, 34, 35, 0, 17, 36, 37, 20, 21, 38, 23, 39, 17, 40,
+ 41, 42, 43, 44, 45, 46, 30, 0, 47, 48, 21, 49, 50, 51, 17, 0,
+ 52, 48, 21, 53, 50, 54, 17, 55, 56, 48, 9, 57, 58, 59, 17, 0,
+ 60, 61, 9, 62, 63, 64, 30, 65, 66, 67, 9, 68, 69, 9, 70, 71,
+ 72, 73, 74, 75, 76, 0, 0, 0, 9, 9, 77, 78, 79, 80, 81, 82,
+ 83, 84, 0, 0, 0, 0, 0, 0, 9, 85, 9, 86, 9, 87, 88, 89,
+ 9, 9, 9, 90, 91, 92, 2, 0, 93, 0, 9, 9, 9, 9, 9, 94,
+ 95, 9, 96, 0, 0, 0, 0, 0, 97, 98, 99,100, 30, 9,101,102,
+ 9, 9,103, 9,104,105, 0, 0, 9,106, 9, 9, 9,107,108,109,
+ 2, 2, 0, 0, 0, 0, 0, 0,110, 9, 9,111,112, 2,113,114,
+ 115, 9,116, 9, 9, 9,117,118, 9, 9,119,120,121, 0, 0, 0,
+ 0, 0, 0, 0, 0,122,123,124, 0, 0, 0, 0, 0, 0, 0,125,
+ 126,127,128, 0, 0, 0,129,130,131, 0, 0, 0, 0, 0, 0,132,
+ 0, 0, 0, 0,133, 0, 0, 0, 0, 0, 0, 9, 9, 9,134,135,
+ 136, 9,137, 0, 9, 9, 9,138,139, 9, 9,140,141, 2,142,143,
+ 9, 9,144, 9,145,146, 0, 0,147, 9, 9,148,149, 2,150, 98,
+ 9, 9,151,152,153, 2, 9,154, 9, 9, 9,155,156, 0,157,158,
+ 0, 0, 0, 0, 9, 9,159, 2,160, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,161, 0, 0, 0, 0, 0, 0, 0,162,
+ 0, 0, 0, 0, 0, 0, 0,163,163,164, 33,165, 0, 0, 0, 0,
+ 166,167, 9,168, 94, 0, 0, 0, 0, 0, 0, 0, 69, 9,169, 0,
+ 9,170,171, 0, 0, 0, 0, 0, 9, 9,172, 2, 0, 0, 0, 0,
+ 9, 9,173,170, 0, 0, 0, 0, 0, 0, 0, 9,174,175, 0, 9,
+ 176, 0, 0,177,178, 0, 0, 0,179, 9, 9,180,181,182,183,184,
+ 185, 9, 9,186,187, 0, 0, 0,188, 9,189,190,191, 9, 9,192,
+ 185, 9, 9,193,194,105,195,102, 9, 33,196,197, 0, 0, 0, 0,
+ 198,199, 94, 9, 9,200,201, 2,202, 20, 21,203,204,205,206,207,
+ 9, 9, 9,208,209,210,211, 0,195, 9, 9,212,213, 2, 0, 0,
+ 9, 9,214,215,216,217, 0, 0, 9, 9, 9,218,219, 2, 0, 0,
+ 9, 9,220,221, 2, 0, 0, 0, 9,222,223,103,224, 0, 0, 0,
+ 9, 9,225,226, 0, 0, 0, 0,227,228, 9,229,230, 2, 0, 0,
+ 0, 0,231, 9, 9,232,233, 0,234, 9, 9,235,236,237, 9, 9,
+ 238,239, 0, 0, 0, 0, 0, 0, 21, 9,214,240, 7, 9, 70, 18,
+ 9,241, 73,242, 0, 0, 0, 0,243, 9, 9,244,245, 2,246, 9,
+ 247,248, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,249,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 98,250, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 9, 9, 9,251, 0, 0, 0, 0,
+ 9, 9, 9, 9,252,253,254,254,255,256, 0, 0, 0, 0,257, 0,
+ 9, 9, 9, 9, 9,258, 0, 0, 9, 9, 9, 9, 9, 9,105, 70,
+ 94,259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,260,
+ 9, 9, 70,261,262, 0, 0, 0, 0, 9,263, 0, 9, 9,264, 2,
+ 9, 9, 9, 9,265, 2, 0, 0,129,129,129,129,129,129,129,129,
+ 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,129,
+};
+
+static inline unsigned
+hb_use_b4 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline uint_fast8_t
+hb_use_get_category (unsigned u)
+{
+ return u<921600u?hb_use_u8[2721+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+}
+
+#undef B
+#undef CGJ
+#undef CS
+#undef G
+#undef GB
+#undef H
+#undef HN
+#undef HVM
+#undef IS
+#undef J
+#undef N
+#undef O
+#undef R
+#undef SB
+#undef SE
+#undef SUB
+#undef Sk
+#undef WJ
+#undef ZWNJ
+#undef CMAbv
+#undef CMBlw
+#undef FAbv
+#undef FBlw
+#undef FPst
+#undef FMAbv
+#undef FMBlw
+#undef FMPst
+#undef MAbv
+#undef MBlw
+#undef MPst
+#undef MPre
+#undef SMAbv
+#undef SMBlw
+#undef VAbv
+#undef VBlw
+#undef VPst
+#undef VPre
+#undef VMAbv
+#undef VMBlw
+#undef VMPst
+#undef VMPre
+
+
+#ifdef HB_USE_TABLE_MAIN
+int main (int argc, char **argv)
+{
+ if (argc != 2)
+ {
+ for (unsigned u = 0; u < 0x10FFFFu; u++)
+ printf ("U+%04X %d\n", u, hb_use_get_category (u));
+ return 0;
+ }
+
+ hb_codepoint_t u;
+ sscanf (argv[1], "%x", &u);
+
+ printf ("%d\n", hb_use_get_category (u));
+
+ return 0;
+}
+
+#endif
+
+
+#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..c40ec52f9c 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++)
@@ -205,7 +206,7 @@ setup_masks_use (const hb_ot_shape_plan_t *plan,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- info[i].use_category() = hb_use_get_category (info[i]);
+ info[i].use_category() = hb_use_get_category (info[i].codepoint);
}
static void
@@ -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 */
@@ -488,12 +490,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
data_destroy_use,
preprocess_text_use,
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
nullptr, /* decompose */
compose_use,
setup_masks_use,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
false, /* fallback_position */
};
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..e160987f83 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().
@@ -117,8 +117,6 @@ struct hb_ot_complex_shaper_t
hb_font_t *font);
- hb_ot_shape_normalization_mode_t normalization_preference;
-
/* decompose()
* Called during shape()'s normalization.
* May be NULL.
@@ -147,12 +145,6 @@ struct hb_ot_complex_shaper_t
hb_buffer_t *buffer,
hb_font_t *font);
- /* gpos_tag()
- * If not HB_TAG_NONE, then must match found GPOS script tag for
- * GPOS to be applied. Otherwise, fallback positioning will be used.
- */
- hb_tag_t gpos_tag;
-
/* reorder_marks()
* Called during shape().
* Shapers can use to modify ordering of combining marks.
@@ -163,23 +155,31 @@ struct hb_ot_complex_shaper_t
unsigned int start,
unsigned int end);
+ /* gpos_tag()
+ * If not HB_TAG_NONE, then must match found GPOS script tag for
+ * GPOS to be applied. Otherwise, fallback positioning will be used.
+ */
+ hb_tag_t gpos_tag;
+
+ hb_ot_shape_normalization_mode_t normalization_preference;
+
hb_ot_shape_zero_width_marks_type_t zero_width_marks;
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-stat-table.hh b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
index 41d1734b39..d83bf14219 100644
--- a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
@@ -57,6 +57,31 @@ enum
// Reserved = 0xFFFC /* Reserved for future use — set to zero. */
};
+struct StatAxisRecord
+{
+ int cmp (hb_tag_t key) const { return tag.cmp (key); }
+
+ hb_ot_name_id_t get_name_id () const { return nameID; }
+
+ hb_tag_t get_axis_tag () const { return tag; }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (likely (c->check_struct (this)));
+ }
+
+ protected:
+ Tag tag; /* A tag identifying the axis of design variation. */
+ NameID nameID; /* The name ID for entries in the 'name' table that
+ * provide a display string for this axis. */
+ HBUINT16 ordering; /* A value that applications can use to determine
+ * primary sorting of face names, or for ordering
+ * of descriptors when composing family or face names. */
+ public:
+ DEFINE_SIZE_STATIC (8);
+};
+
struct AxisValueFormat1
{
unsigned int get_axis_index () const { return axisIndex; }
@@ -64,10 +89,41 @@ struct AxisValueFormat1
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+ hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ unsigned axis_idx = get_axis_index ();
+ return axis_records[axis_idx].get_axis_tag ();
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_tag_t axis_tag = get_axis_tag (axis_records);
+ float axis_value = get_value ();
+
+ if (!user_axes_location->has (axis_tag) ||
+ fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
+ return true;
+
+ return false;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location;
+
+ if (keep_axis_value (axis_records, user_axes_location))
+ return_trace (c->serializer->embed (this));
+
+ return_trace (false);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -92,10 +148,41 @@ struct AxisValueFormat2
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+ hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ unsigned axis_idx = get_axis_index ();
+ return axis_records[axis_idx].get_axis_tag ();
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_tag_t axis_tag = get_axis_tag (axis_records);
+ float axis_value = get_value ();
+
+ if (!user_axes_location->has (axis_tag) ||
+ fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
+ return true;
+
+ return false;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location;
+
+ if (keep_axis_value (axis_records, user_axes_location))
+ return_trace (c->serializer->embed (this));
+
+ return_trace (false);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -124,10 +211,41 @@ struct AxisValueFormat3
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+ hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ unsigned axis_idx = get_axis_index ();
+ return axis_records[axis_idx].get_axis_tag ();
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_tag_t axis_tag = get_axis_tag (axis_records);
+ float axis_value = get_value ();
+
+ if (!user_axes_location->has (axis_tag) ||
+ fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
+ return true;
+
+ return false;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location;
+
+ if (keep_axis_value (axis_records, user_axes_location))
+ return_trace (c->serializer->embed (this));
+
+ return_trace (false);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -155,7 +273,7 @@ struct AxisValueRecord
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -172,12 +290,47 @@ struct AxisValueFormat4
const AxisValueRecord &get_axis_record (unsigned int axis_index) const
{ return axisValues.as_array (axisCount)[axis_index]; }
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount);
+
+ for (const auto& rec : axis_value_records)
+ {
+ unsigned axis_idx = rec.get_axis_index ();
+ float axis_value = rec.get_value ();
+ hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag ();
+
+ if (user_axes_location->has (axis_tag) &&
+ fabsf(axis_value - user_axes_location->get (axis_tag)) > 0.001f)
+ return false;
+ }
+
+ return true;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location = c->plan->user_axes_location;
+ if (!keep_axis_value (axis_records, user_axes_location))
+ return_trace (false);
+
+ unsigned total_size = min_size + axisCount * AxisValueRecord::static_size;
+ auto *out = c->serializer->allocate_size<AxisValueFormat4> (total_size);
+ if (unlikely (!out)) return_trace (false);
+ memcpy (out, this, total_size);
+ return_trace (true);
+ }
+
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (likely (c->check_struct (this) &&
+ axisValues.sanitize (c, axisCount)));
}
protected:
@@ -234,6 +387,33 @@ struct AxisValue
}
}
+ 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)...));
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.keep_axis_value (axis_records, user_axes_location);
+ case 2: return u.format2.keep_axis_value (axis_records, user_axes_location);
+ case 3: return u.format3.keep_axis_value (axis_records, user_axes_location);
+ case 4: return u.format4.keep_axis_value (axis_records, user_axes_location);
+ default:return false;
+ }
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -263,27 +443,35 @@ struct AxisValue
DEFINE_SIZE_UNION (2, format);
};
-struct StatAxisRecord
+struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>>
{
- int cmp (hb_tag_t key) const { return tag.cmp (key); }
+ bool subset (hb_subset_context_t *c,
+ unsigned axisValueCount,
+ unsigned& count,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!out)) return_trace (false);
- hb_ot_name_id_t get_name_id () const { return nameID; }
+ auto axisValueOffsets = as_array (axisValueCount);
+ count = 0;
+ for (const auto& offset : axisValueOffsets)
+ {
+ if (!offset) continue;
+ auto o_snap = c->serializer->snapshot ();
+ auto *o = c->serializer->embed (offset);
+ if (!o) return_trace (false);
+ if (!o->serialize_subset (c, offset, this, axis_records))
+ {
+ c->serializer->revert (o_snap);
+ continue;
+ }
+ count++;
+ }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (count);
}
-
- protected:
- Tag tag; /* A tag identifying the axis of design variation. */
- NameID nameID; /* The name ID for entries in the 'name' table that
- * provide a display string for this axis. */
- HBUINT16 ordering; /* A value that applications can use to determine
- * primary sorting of face names, or for ordering
- * of descriptors when composing family or face names. */
- public:
- DEFINE_SIZE_STATIC (8);
};
struct STAT
@@ -329,7 +517,8 @@ struct STAT
return axis_value.get_value_name_id ();
}
- void collect_name_ids (hb_set_t *nameids_to_retain) const
+ void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ hb_set_t *nameids_to_retain /* OUT */) const
{
if (!has_data ()) return;
@@ -338,13 +527,38 @@ struct STAT
| hb_sink (nameids_to_retain)
;
+ auto designAxes = get_design_axes ();
+
+ get_axis_value_offsets ()
| hb_map (hb_add (&(this + offsetToAxisValueOffsets)))
+ | hb_filter ([&] (const AxisValue& _)
+ { return _.keep_axis_value (designAxes, user_axes_location); })
| hb_map (&AxisValue::get_value_name_id)
| hb_sink (nameids_to_retain)
;
}
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ STAT *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ auto designAxes = get_design_axes ();
+ for (unsigned i = 0; i < (unsigned)designAxisCount; i++)
+ if (unlikely (!c->serializer->embed (designAxes[i])))
+ return_trace (false);
+
+ if (designAxisCount)
+ c->serializer->check_assign (out->designAxesOffset, this->get_size (),
+ HB_SERIALIZE_ERROR_INT_OVERFLOW);
+
+ unsigned count = 0;
+ out->offsetToAxisValueOffsets.serialize_subset (c, offsetToAxisValueOffsets, this,
+ axisValueCount, count, designAxes);
+ return_trace (c->serializer->check_assign (out->axisValueCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -381,7 +595,7 @@ struct STAT
* set to zero; if designAxisCount is greater
* than zero, must be greater than zero. */
HBUINT16 axisValueCount; /* The number of axis value tables. */
- NNOffset32To<UnsizedArrayOf<Offset16To<AxisValue>>>
+ NNOffset32To<AxisValueOffsetArray>
offsetToAxisValueOffsets;
/* Offset in bytes from the beginning of
* the STAT table to the start of the design
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..ceb3bf6df5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc
@@ -214,6 +214,8 @@ lang_matches (const char *lang_str,
const char *spec,
unsigned spec_len)
{
+ /* Same as hb_language_matches(); duplicated. */
+
if (likely ((unsigned) (limit - lang_str) < spec_len))
return false;
@@ -263,15 +265,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 +286,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 +296,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 +329,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 +338,7 @@ hb_ot_tags_from_language (const char *lang_str,
*count = 1;
return;
}
+#endif
*count = 0;
}
@@ -472,11 +483,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 +498,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 +611,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 +622,7 @@ test_langs_sorted ()
abort();
}
}
+#endif
}
int
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
index 65f26c1d22..5946aef635 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
@@ -28,6 +28,8 @@
#define HB_OT_VAR_AVAR_TABLE_HH
#include "hb-open-type.hh"
+#include "hb-ot-var-common.hh"
+
/*
* avar -- Axis Variations
@@ -40,6 +42,28 @@
namespace OT {
+/* "Spec": https://github.com/be-fonts/boring-expansion-spec/issues/14 */
+struct avarV2Tail
+{
+ friend struct avar;
+
+ bool sanitize (hb_sanitize_context_t *c,
+ const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (varIdxMap.sanitize (c, base) &&
+ varStore.sanitize (c, base));
+ }
+
+ protected:
+ Offset32To<DeltaSetIndexMap> varIdxMap; /* Offset from the beginning of 'avar' table. */
+ Offset32To<VariationStore> varStore; /* Offset from the beginning of 'avar' table. */
+
+ public:
+ DEFINE_SIZE_STATIC (8);
+};
+
+
struct AxisValueMap
{
bool sanitize (hb_sanitize_context_t *c) const
@@ -106,12 +130,24 @@ struct avar
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;
+ bool has_data () const { return version.to_int (); }
+
+ const SegmentMaps* get_segment_maps () const
+ { return &firstAxisSegmentMaps; }
+
+ unsigned get_axis_count () const
+ { return axisCount; }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- if (unlikely (!(version.sanitize (c) &&
- version.major == 1 &&
- c->check_struct (this))))
+ if (!(version.sanitize (c) &&
+ (version.major == 1
+#ifndef HB_NO_VARIATIONS2
+ || version.major == 2
+#endif
+ ) &&
+ c->check_struct (this)))
return_trace (false);
const SegmentMaps *map = &firstAxisSegmentMaps;
@@ -123,6 +159,15 @@ struct avar
map = &StructAfter<SegmentMaps> (*map);
}
+#ifndef HB_NO_VARIATIONS2
+ if (version.major < 2)
+ return_trace (true);
+
+ const auto &v2 = * (const avarV2Tail *) map;
+ if (unlikely (!v2.sanitize (c, this)))
+ return_trace (false);
+#endif
+
return_trace (true);
}
@@ -136,6 +181,37 @@ struct avar
coords[i] = map->map (coords[i]);
map = &StructAfter<SegmentMaps> (*map);
}
+
+#ifndef HB_NO_VARIATIONS2
+ if (version.major < 2)
+ return;
+
+ for (; count < axisCount; count++)
+ map = &StructAfter<SegmentMaps> (*map);
+
+ const auto &v2 = * (const avarV2Tail *) map;
+
+ const auto &varidx_map = this+v2.varIdxMap;
+ const auto &var_store = this+v2.varStore;
+ auto *var_store_cache = var_store.create_cache ();
+
+ hb_vector_t<int> out;
+ out.alloc (coords_length);
+ for (unsigned i = 0; i < coords_length; i++)
+ {
+ int v = coords[i];
+ uint32_t varidx = varidx_map.map (i);
+ float delta = var_store.get_delta (varidx, coords, coords_length, var_store_cache);
+ v += roundf (delta);
+ v = hb_clamp (v, -(1<<14), +(1<<14));
+ out.push (v);
+ }
+
+ OT::VariationStore::destroy_cache (var_store_cache);
+
+ for (unsigned i = 0; i < coords_length; i++)
+ coords[i] = out[i];
+#endif
}
void unmap_coords (int *coords, unsigned int coords_length) const
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-common.hh b/thirdparty/harfbuzz/src/hb-ot-var-common.hh
index 0eafb949d5..1d29e3e4f9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-common.hh
@@ -31,12 +31,13 @@
namespace OT {
-struct DeltaSetIndexMapFormat0
+template <typename MapCountT>
+struct DeltaSetIndexMapFormat01
{
friend struct DeltaSetIndexMap;
private:
- DeltaSetIndexMapFormat0* copy (hb_serialize_context_t *c) const
+ DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
auto *out = c->start_embed (this);
@@ -128,56 +129,12 @@ struct DeltaSetIndexMapFormat0
HBUINT8 format; /* Format identifier--format = 0 */
HBUINT8 entryFormat; /* A packed field that describes the compressed
* representation of delta-set indices. */
- HBUINT16 mapCount; /* The number of mapping entries. */
+ MapCountT mapCount; /* The number of mapping entries. */
UnsizedArrayOf<HBUINT8>
mapDataZ; /* The delta-set index mapping data. */
public:
- DEFINE_SIZE_ARRAY (4, mapDataZ);
-};
-
-struct DeltaSetIndexMapFormat1
-{
- friend struct DeltaSetIndexMap;
-
- private:
- DeltaSetIndexMapFormat1* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->start_embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- unsigned total_size = min_size + mapCount * get_width ();
- HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
- if (unlikely (!p)) return_trace (nullptr);
-
- memcpy (p, this, HBUINT8::static_size * total_size);
- return_trace (out);
- }
-
- unsigned get_map_count () const { return mapCount; }
- unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; }
- unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- c->check_range (mapDataZ.arrayZ,
- mapCount,
- get_width ()));
- }
-
- protected:
- HBUINT8 format; /* Format identifier--format = 1 */
- HBUINT8 entryFormat; /* A packed field that describes the compressed
- * representation of delta-set indices. */
- HBUINT32 mapCount; /* The number of mapping entries. */
- UnsizedArrayOf<HBUINT8>
- mapDataZ; /* The delta-set index mapping data. */
-
- public:
- DEFINE_SIZE_ARRAY (6, mapDataZ);
+ DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
};
struct DeltaSetIndexMap
@@ -186,8 +143,11 @@ struct DeltaSetIndexMap
bool serialize (hb_serialize_context_t *c, const T &plan)
{
TRACE_SERIALIZE (this);
+ unsigned length = plan.get_output_map ().length;
+ u.format = length <= 0xFFFF ? 0 : 1;
switch (u.format) {
case 0: return_trace (u.format0.serialize (c, plan));
+ case 1: return_trace (u.format1.serialize (c, plan));
default:return_trace (false);
}
}
@@ -196,6 +156,7 @@ struct DeltaSetIndexMap
{
switch (u.format) {
case 0: return (u.format0.map (v));
+ case 1: return (u.format1.map (v));
default:return v;
}
}
@@ -250,9 +211,9 @@ struct DeltaSetIndexMap
protected:
union {
- HBUINT8 format; /* Format identifier */
- DeltaSetIndexMapFormat0 format0;
- DeltaSetIndexMapFormat1 format1;
+ HBUINT8 format; /* Format identifier */
+ DeltaSetIndexMapFormat01<HBUINT16> format0;
+ DeltaSetIndexMapFormat01<HBUINT32> format1;
} u;
public:
DEFINE_SIZE_UNION (1, format);
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
index e066558683..b9b49f2287 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
@@ -96,6 +96,8 @@ struct AxisRecord
info->reserved = 0;
}
+ hb_tag_t get_axis_tag () const { return axisTag; }
+
int normalize_axis_value (float v) const
{
float min_value, default_value, max_value;
@@ -133,7 +135,6 @@ struct AxisRecord
return_trace (c->check_struct (this));
}
- protected:
void get_coordinates (float &min, float &default_, float &max) const
{
default_ = defaultValue / 65536.f;
@@ -142,6 +143,11 @@ struct AxisRecord
max = hb_max (default_, maxValue / 65536.f);
}
+ float get_default () const
+ {
+ return defaultValue / 65536.f;
+ }
+
public:
Tag axisTag; /* Tag identifying the design variation for the axis. */
protected:
@@ -213,7 +219,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 +227,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
@@ -270,24 +276,49 @@ struct fvar
return axisCount;
}
- void collect_name_ids (hb_set_t *nameids) const
+ void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ hb_set_t *nameids /* IN/OUT */) const
{
if (!has_data ()) return;
+ hb_map_t pinned_axes;
- + get_axes ()
- | hb_map (&AxisRecord::get_name_id)
- | hb_sink (nameids)
- ;
-
- + hb_range ((unsigned) instanceCount)
- | hb_map ([this] (const unsigned _) { return get_instance_subfamily_name_id (_); })
- | hb_sink (nameids)
- ;
+ auto axis_records = get_axes ();
+ for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
+ {
+ hb_tag_t axis_tag = axis_records[i].get_axis_tag ();
+ if (user_axes_location->has (axis_tag))
+ {
+ pinned_axes.set (i, axis_tag);
+ continue;
+ }
+
+ nameids->add (axis_records[i].get_name_id ());
+ }
- + hb_range ((unsigned) instanceCount)
- | hb_map ([this] (const unsigned _) { return get_instance_postscript_name_id (_); })
- | hb_sink (nameids)
- ;
+ for (unsigned i = 0 ; i < (unsigned)instanceCount; i++)
+ {
+ const InstanceRecord *instance = get_instance (i);
+
+ if (hb_any (+ hb_zip (instance->get_coordinates (axisCount), hb_range ((unsigned)axisCount))
+ | hb_filter (pinned_axes, hb_second)
+ | hb_map ([&] (const hb_pair_t<const HBFixed&, unsigned>& _)
+ {
+ hb_tag_t axis_tag = pinned_axes.get (_.second);
+ float location = user_axes_location->get (axis_tag);
+ if (fabs ((double)location - (double)_.first.to_float ()) > 0.001) return true;
+ return false;
+ })
+ ))
+ continue;
+
+ nameids->add (instance->subfamilyNameID);
+
+ if (instanceSize >= axisCount * 4 + 6)
+ {
+ unsigned post_script_name_id = StructAfter<NameID> (instance->get_coordinates (axisCount));
+ if (post_script_name_id != HB_OT_NAME_ID_INVALID) nameids->add (post_script_name_id);
+ }
+ }
}
public:
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..53355c5077 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
@@ -319,23 +319,27 @@ 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_delta_unscaled (hb_codepoint_t glyph,
+ const int *coords, unsigned int coord_count,
+ 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,
+ coords, coord_count,
+ store_cache);
}
- float get_side_bearing_var (hb_codepoint_t glyph,
- const int *coords, unsigned int coord_count) const
+ bool get_lsb_delta_unscaled (hb_codepoint_t glyph,
+ const int *coords, unsigned int coord_count,
+ float *lsb) const
{
- if (!has_side_bearing_deltas ()) return 0.f;
+ if (!lsbMap) return false;
uint32_t varidx = (this+lsbMap).map (glyph);
- return (this+varStore).get_delta (varidx, coords, coord_count);
+ *lsb = (this+varStore).get_delta (varidx, coords, coord_count);
+ return true;
}
- 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>
@@ -387,6 +391,16 @@ struct VVAR : HVARVVAR {
bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); }
+ bool get_vorg_delta_unscaled (hb_codepoint_t glyph,
+ const int *coords, unsigned int coord_count,
+ float *delta) const
+ {
+ if (!vorgMap) return false;
+ uint32_t varidx = (this+vorgMap).map (glyph);
+ *delta = (this+varStore).get_delta (varidx, coords, coord_count);
+ return true;
+ }
+
protected:
Offset32To<DeltaSetIndexMap>
vorgMap; /* Offset to vertical-origin var-idx mapping. */
diff --git a/thirdparty/harfbuzz/src/hb-ot-var.cc b/thirdparty/harfbuzz/src/hb-ot-var.cc
index 0376e26b4a..f000f27263 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-var.cc
@@ -56,7 +56,7 @@
*
* Tests whether a face includes any OpenType variation data in the `fvar` table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.4.2
**/
@@ -162,7 +162,7 @@ hb_ot_var_get_axis_infos (hb_face_t *face,
* Fetches the variation-axis information corresponding to the specified axis tag
* in the specified face.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.2.0
**/
diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh
index ce9ff90bb4..61b142238e 100644
--- a/thirdparty/harfbuzz/src/hb-repacker.hh
+++ b/thirdparty/harfbuzz/src/hb-repacker.hh
@@ -29,1036 +29,157 @@
#include "hb-open-type.hh"
#include "hb-map.hh"
-#include "hb-priority-queue.hh"
-#include "hb-serialize.hh"
#include "hb-vector.hh"
+#include "graph/graph.hh"
+#include "graph/gsubgpos-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);
- }
+struct lookup_size_t
+{
+ unsigned lookup_index;
+ size_t size;
+ unsigned num_subtables;
- /*
- * 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)
+ static int cmp (const void* a, const void* b)
{
- 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);
- }
+ return cmp ((const lookup_size_t*) a,
+ (const lookup_size_t*) b);
}
- /*
- * Creates a copy of node_idx and returns it's new index.
- */
- unsigned duplicate (unsigned node_idx)
+ static int cmp (const lookup_size_t* a, const lookup_size_t* b)
{
- positions_invalid = true;
- distance_invalid = true;
-
- auto* clone = vertices_.push ();
- auto& child = vertices_[node_idx];
- if (vertices_.in_error ()) {
- return -1;
+ double subtables_per_byte_a = (double) a->num_subtables / (double) a->size;
+ double subtables_per_byte_b = (double) b->num_subtables / (double) b->size;
+ if (subtables_per_byte_a == subtables_per_byte_b) {
+ return b->lookup_index - a->lookup_index;
}
- 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;
+ double cmp = subtables_per_byte_b - subtables_per_byte_a;
+ if (cmp < 0) return -1;
+ if (cmp > 0) return 1;
+ return 0;
}
+};
- /*
- * 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);
+static inline
+bool _presplit_subtables_if_needed (graph::gsubgpos_graph_context_t& ext_context)
+{
+ // For each lookup this will check the size of subtables and split them as needed
+ // so that no subtable is at risk of overflowing. (where we support splitting for
+ // that subtable type).
+ //
+ // TODO(grieger): de-dup newly added nodes as necessary. Probably just want a full de-dup
+ // pass after this processing is done. Not super necessary as splits are
+ // only done where overflow is likely, so de-dup probably will get undone
+ // later anyways.
+ for (unsigned lookup_index : ext_context.lookups.keys ())
+ {
+ graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
+ if (!lookup->split_subtables_if_needed (ext_context, lookup_index))
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;
- }
+ return true;
+}
- /*
- * Returns the numbers of incoming edges that are 32bits wide.
- */
- unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
- {
- unsigned count = 0;
+/*
+ * Analyze the lookups in a GSUB/GPOS table and decide if any should be promoted
+ * to extension lookups.
+ */
+static inline
+bool _promote_extensions_if_needed (graph::gsubgpos_graph_context_t& ext_context)
+{
+ // Simple Algorithm (v1, current):
+ // 1. Calculate how many bytes each non-extension lookup consumes.
+ // 2. Select up to 64k of those to remain as non-extension (greedy, highest subtables per byte first)
+ // 3. Promote the rest.
+ //
+ // Advanced Algorithm (v2, not implemented):
+ // 1. Perform connected component analysis using lookups as roots.
+ // 2. Compute size of each connected component.
+ // 3. Select up to 64k worth of connected components to remain as non-extensions.
+ // (greedy, highest subtables per byte first)
+ // 4. Promote the rest.
+
+ // TODO(garretrieger): support extension demotion, then consider all lookups. Requires advanced algo.
+ // TODO(garretrieger): also support extension promotion during iterative resolution phase, then
+ // we can use a less conservative threshold here.
+ // TODO(grieger): skip this for the 24 bit case.
+ if (!ext_context.lookups) return true;
+
+ hb_vector_t<lookup_size_t> lookup_sizes;
+ lookup_sizes.alloc (ext_context.lookups.get_population ());
+
+ for (unsigned lookup_index : ext_context.lookups.keys ())
+ {
+ const graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
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;
+ lookup_sizes.push (lookup_size_t {
+ lookup_index,
+ ext_context.graph.find_subgraph_size (lookup_index, visited),
+ lookup->number_of_subtables (),
+ });
}
- 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;
+ lookup_sizes.qsort ();
- 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);
- }
- }
+ size_t lookup_list_size = ext_context.graph.vertices_[ext_context.lookup_list_index].table_size ();
+ size_t l2_l3_size = lookup_list_size; // Lookup List + Lookups
+ size_t l3_l4_size = 0; // Lookups + SubTables
+ size_t l4_plus_size = 0; // SubTables + their descendants
- /*
- * 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)
+ // Start by assuming all lookups are using extension subtables, this size will be removed later
+ // if it's decided to not make a lookup extension.
+ for (auto p : lookup_sizes)
{
- unsigned old_idx = link.objidx;
- link.objidx = new_idx;
- vertices_[old_idx].remove_parent (parent_idx);
- vertices_[new_idx].parents.push (parent_idx);
+ unsigned subtables_size = p.num_subtables * 8;
+ l3_l4_size += subtables_size;
+ l4_plus_size += subtables_size;
}
- /*
- * 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)
+ bool layers_full = false;
+ for (auto p : lookup_sizes)
{
- 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]);
- }
- }
- }
+ const graph::Lookup* lookup = ext_context.lookups.get(p.lookup_index);
+ if (lookup->is_extension (ext_context.table_tag))
+ // already an extension so size is counted by the loop above.
+ continue;
- /*
- * 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++)
+ if (!layers_full)
{
- (*sorted_graph)[i].remap_parents (id_map);
- for (auto& link : (*sorted_graph)[i].obj.all_links_writer ())
- {
- link.objidx = id_map[link.objidx];
- }
- }
- }
+ size_t lookup_size = ext_context.graph.vertices_[p.lookup_index].table_size ();
+ hb_set_t visited;
+ size_t subtables_size = ext_context.graph.find_subgraph_size (p.lookup_index, visited, 1) - lookup_size;
+ size_t remaining_size = p.size - subtables_size - lookup_size;
- 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);
- }
+ l2_l3_size += lookup_size;
+ l3_l4_size += lookup_size + subtables_size;
+ l3_l4_size -= p.num_subtables * 8;
+ l4_plus_size += subtables_size + remaining_size;
- 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);
- }
- }
+ if (l2_l3_size < (1 << 16)
+ && l3_l4_size < (1 << 16)
+ && l4_plus_size < (1 << 16)) continue; // this lookup fits within all layers groups
- /*
- * 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);
+ layers_full = true;
}
- 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);
+ if (!ext_context.lookups.get(p.lookup_index)->make_extension (ext_context, p.lookup_index))
+ return false;
}
- 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_;
-};
+ return true;
+}
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 +187,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 +229,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 +238,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 ())
{
@@ -1172,39 +293,60 @@ template<typename T>
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.
+ unsigned max_rounds = 20,
+ bool recalculate_extensions = false) {
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 ();
-
+ graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph);
if ((table_tag == HB_OT_TAG_GPOS
|| table_tag == HB_OT_TAG_GSUB)
- && sorted_graph.will_overflow ())
+ && will_overflow)
{
+ if (recalculate_extensions)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
+ if (!_presplit_subtables_if_needed (ext_context)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Subtable splitting failed.");
+ return nullptr;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Promoting lookups to extensions if needed.");
+ if (!_promote_extensions_if_needed (ext_context)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Extensions promotion failed.");
+ return nullptr;
+ }
+ }
+
DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs.");
- if (sorted_graph.assign_32bit_spaces ())
+ if (sorted_graph.assign_spaces ())
sorted_graph.sort_shortest_distance ();
+ else
+ sorted_graph.sort_shortest_distance_if_needed ();
}
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)
- && round++ < max_rounds) {
+ && 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;
if (!_try_isolating_subgraphs (overflows, sorted_graph))
{
+ // Don't count space isolation towards round limit. Only increment
+ // round counter if space isolation made no changes.
+ round++;
if (!_process_overflows (overflows, priority_bumped_parents, sorted_graph))
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :(");
@@ -1221,13 +363,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..0270b21998 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.
*
@@ -56,8 +56,6 @@ hb_set_create ()
if (!(set = hb_object_create<hb_set_t> ()))
return hb_set_get_empty ();
- set->init_shallow ();
-
return set;
}
@@ -107,8 +105,6 @@ hb_set_destroy (hb_set_t *set)
{
if (!hb_object_destroy (set)) return;
- set->fini_shallow ();
-
hb_free (set);
}
@@ -122,7 +118,7 @@ hb_set_destroy (hb_set_t *set)
*
* Attaches a user-data key/data pair to the specified set.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -149,7 +145,7 @@ hb_set_set_user_data (hb_set_t *set,
* Since: 0.9.2
**/
void *
-hb_set_get_user_data (hb_set_t *set,
+hb_set_get_user_data (const hb_set_t *set,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (set, key);
@@ -162,7 +158,7 @@ hb_set_get_user_data (hb_set_t *set,
*
* Tests whether memory allocation for a set was successful.
*
- * Return value: %true if allocation succeeded, %false otherwise
+ * Return value: `true` if allocation succeeded, `false` otherwise
*
* Since: 0.9.2
**/
@@ -186,6 +182,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;
}
@@ -211,7 +208,7 @@ hb_set_clear (hb_set_t *set)
*
* Tests whether a set is empty (contains no elements).
*
- * Return value: %true if @set is empty
+ * Return value: `true` if @set is empty
*
* Since: 0.9.7
**/
@@ -228,7 +225,7 @@ hb_set_is_empty (const hb_set_t *set)
*
* Tests whether @codepoint belongs to @set.
*
- * Return value: %true if @codepoint is in @set, %false otherwise
+ * Return value: `true` if @codepoint is in @set, `false` otherwise
*
* Since: 0.9.2
**/
@@ -347,7 +344,7 @@ hb_set_del_range (hb_set_t *set,
* Tests whether @set and @other are equal (contain the same
* elements).
*
- * Return value: %true if the two sets are equal, %false otherwise.
+ * Return value: `true` if the two sets are equal, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -359,13 +356,30 @@ 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
*
* Tests whether @set is a subset of @larger_set.
*
- * Return value: %true if the @set is a subset of (or equal to) @larger_set, %false otherwise.
+ * Return value: `true` if the @set is a subset of (or equal to) @larger_set, `false` otherwise.
*
* Since: 1.8.1
**/
@@ -535,7 +549,7 @@ hb_set_get_max (const hb_set_t *set)
*
* Set @codepoint to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a next value, %false otherwise
+ * Return value: `true` if there was a next value, `false` otherwise
*
* Since: 0.9.2
**/
@@ -556,7 +570,7 @@ hb_set_next (const hb_set_t *set,
*
* Set @codepoint to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a previous value, %false otherwise
+ * Return value: `true` if there was a previous value, `false` otherwise
*
* Since: 1.8.0
**/
@@ -579,7 +593,7 @@ hb_set_previous (const hb_set_t *set,
*
* Set @last to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a next range, %false otherwise
+ * Return value: `true` if there was a next range, `false` otherwise
*
* Since: 0.9.7
**/
@@ -603,7 +617,7 @@ hb_set_next_range (const hb_set_t *set,
*
* Set @first to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a previous range, %false otherwise
+ * Return value: `true` if there was a previous range, `false` otherwise
*
* Since: 1.8.0
**/
diff --git a/thirdparty/harfbuzz/src/hb-set.h b/thirdparty/harfbuzz/src/hb-set.h
index 10ce7c10d4..93636ab5d7 100644
--- a/thirdparty/harfbuzz/src/hb-set.h
+++ b/thirdparty/harfbuzz/src/hb-set.h
@@ -77,7 +77,7 @@ hb_set_set_user_data (hb_set_t *set,
hb_bool_t replace);
HB_EXTERN void *
-hb_set_get_user_data (hb_set_t *set,
+hb_set_get_user_data (const hb_set_t *set,
hb_user_data_key_t *key);
@@ -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..5d5576cb9e 100644
--- a/thirdparty/harfbuzz/src/hb-set.hh
+++ b/thirdparty/harfbuzz/src/hb-set.hh
@@ -59,17 +59,15 @@ struct hb_sparseset_t
hb_copy (o, *this);
}
- void init_shallow () { s.init (); }
void init ()
{
hb_object_init (this);
- init_shallow ();
+ s.init ();
}
- void fini_shallow () { s.fini (); }
void fini ()
{
hb_object_fini (this);
- fini_shallow ();
+ s.fini ();
}
explicit operator bool () const { return !is_empty (); }
@@ -166,7 +164,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..9e513c0458 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.cc
@@ -117,7 +117,7 @@ hb_shape_plan_key_t::init (bool copy,
}
else
{
- const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+ const HB_UNUSED hb_shaper_entry_t *shapers = _hb_shapers_get ();
for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
if (false)
;
@@ -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;
@@ -317,10 +318,6 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
{
if (!hb_object_destroy (shape_plan)) return;
-#ifndef HB_NO_OT_SHAPE
- shape_plan->ot.fini ();
-#endif
- shape_plan->key.fini ();
hb_free (shape_plan);
}
@@ -334,7 +331,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
*
* Attaches a user-data key/data pair to the given shaping plan.
*
- * Return value: %true if success, %false otherwise.
+ * Return value: `true` if success, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -361,8 +358,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
* Since: 0.9.7
**/
void *
-hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
- hb_user_data_key_t *key)
+hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan,
+ hb_user_data_key_t *key)
{
return hb_object_get_user_data (shape_plan, key);
}
@@ -439,7 +436,7 @@ _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan,
* Executes the given shaping plan on the specified buffer, using
* the given @font and @features.
*
- * Return value: %true if success, %false otherwise.
+ * Return value: `true` if success, `false` otherwise.
*
* Since: 0.9.7
**/
diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.h b/thirdparty/harfbuzz/src/hb-shape-plan.h
index fc7c041899..aaf5cf9c45 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.h
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.h
@@ -102,8 +102,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
hb_bool_t replace);
HB_EXTERN void *
-hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
- hb_user_data_key_t *key);
+hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan,
+ hb_user_data_key_t *key);
HB_EXTERN hb_bool_t
diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.hh b/thirdparty/harfbuzz/src/hb-shape-plan.hh
index 8cb4ddb927..6fc73939b3 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.hh
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.hh
@@ -55,7 +55,7 @@ struct hb_shape_plan_key_t
unsigned int num_coords,
const char * const *shaper_list);
- HB_INTERNAL void fini () { hb_free ((void *) user_features); }
+ HB_INTERNAL void fini () { hb_free ((void *) user_features); user_features = nullptr; }
HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other);
@@ -64,6 +64,7 @@ struct hb_shape_plan_key_t
struct hb_shape_plan_t
{
+ ~hb_shape_plan_t () { key.fini (); }
hb_object_header_t header;
hb_face_t *face_unsafe; /* We don't carry a reference to face. */
hb_shape_plan_key_t key;
diff --git a/thirdparty/harfbuzz/src/hb-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc
index 3407e1af42..547d0afc47 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;
@@ -106,12 +106,12 @@ hb_shape_list_shapers ()
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
* @features: (array length=num_features) (nullable): an array of user
- * specified #hb_feature_t or %NULL
+ * specified #hb_feature_t or `NULL`
* @num_features: the length of @features array
- * @shaper_list: (array zero-terminated=1) (nullable): a %NULL-terminated
- * array of shapers to use or %NULL
+ * @shaper_list: (array zero-terminated=1) (nullable): a `NULL`-terminated
+ * array of shapers to use or `NULL`
*
- * See hb_shape() for details. If @shaper_list is not %NULL, the specified
+ * See hb_shape() for details. If @shaper_list is not `NULL`, the specified
* shapers will be used in the given order, otherwise the default shapers list
* will be used.
*
@@ -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;
}
@@ -159,11 +173,11 @@ hb_shape_full (hb_font_t *font,
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
* @features: (array length=num_features) (nullable): an array of user
- * specified #hb_feature_t or %NULL
+ * specified #hb_feature_t or `NULL`
* @num_features: the length of @features array
*
* Shapes @buffer using @font turning its Unicode characters content to
- * positioned glyphs. If @features is not %NULL, it will be used to control the
+ * positioned glyphs. If @features is not `NULL`, it will be used to control the
* features applied during shaping. If two @features have the same tag but
* overlapping ranges the value of the feature with the higher index takes
* precedence.
diff --git a/thirdparty/harfbuzz/src/hb-shaper.cc b/thirdparty/harfbuzz/src/hb-shaper.cc
index a11ed83afd..a900ac6991 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_CONST (_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..af95615c16 100644
--- a/thirdparty/harfbuzz/src/hb-static.cc
+++ b/thirdparty/harfbuzz/src/hb-static.cc
@@ -46,17 +46,19 @@ uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof
DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF};
DEFINE_NULL_NAMESPACE_BYTES (OT, VarIdx) = {0xFF,0xFF,0xFF,0xFF};
DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
-DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x01};
DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
-/* Hand-coded because Lookup is a template. Sad. */
-const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
+DEFINE_NULL_NAMESPACE_BYTES (AAT, Lookup) = {0xFF,0xFF};
+/* hb_map_t */
+
+const hb_codepoint_t minus_1 = -1;
/* hb_face_t */
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
static inline unsigned
load_num_glyphs_from_loca (const hb_face_t *face)
{
@@ -86,7 +88,7 @@ hb_face_t::load_num_glyphs () const
{
unsigned ret = 0;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
ret = hb_max (ret, load_num_glyphs_from_loca (this));
#endif
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..7d19496275 100644
--- a/thirdparty/harfbuzz/src/hb-subset-input.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-input.cc
@@ -32,7 +32,7 @@
*
* Creates a new subset input object.
*
- * Return value: (transfer full): New subset input, or %NULL if failed. Destroy
+ * Return value: (transfer full): New subset input, or `NULL` if failed. Destroy
* with hb_subset_input_destroy().
*
* Since: 1.8.0
@@ -48,7 +48,9 @@ hb_subset_input_create_or_fail (void)
for (auto& set : input->sets_iter ())
set = hb_set_create ();
- if (input->in_error ())
+ input->axes_location = hb_hashmap_create<hb_tag_t, float> ();
+
+ if (!input->axes_location || input->in_error ())
{
hb_subset_input_destroy (input);
return nullptr;
@@ -96,7 +98,6 @@ hb_subset_input_create_or_fail (void)
HB_TAG ('D', 'S', 'I', 'G'),
HB_TAG ('M', 'V', 'A', 'R'),
HB_TAG ('c', 'v', 'a', 'r'),
- HB_TAG ('S', 'T', 'A', 'T'),
};
input->sets.no_subset_tables->add_array (default_no_subset_tables,
ARRAY_LENGTH (default_no_subset_tables));
@@ -140,7 +141,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'),
@@ -190,6 +204,8 @@ hb_subset_input_create_or_fail (void)
input->sets.layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features));
+ input->sets.layout_scripts->invert (); // Default to all scripts.
+
if (input->in_error ())
{
hb_subset_input_destroy (input);
@@ -231,6 +247,8 @@ hb_subset_input_destroy (hb_subset_input_t *input)
for (hb_set_t* set : input->sets_iter ())
hb_set_destroy (set);
+ hb_hashmap_destroy (input->axes_location);
+
hb_free (input);
}
@@ -329,7 +347,7 @@ hb_subset_input_set_flags (hb_subset_input_t *input,
*
* Attaches a user-data key/data pair to the given subset input object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 2.9.0
**/
@@ -361,3 +379,56 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input,
{
return hb_object_get_user_data (input, key);
}
+
+#ifdef HB_EXPERIMENTAL_API
+#ifndef HB_NO_VAR
+/**
+ * hb_subset_input_pin_axis_to_default: (skip)
+ * @input: a #hb_subset_input_t object.
+ * @axis_tag: Tag of the axis to be pinned
+ *
+ * Pin an axis to its default location in the given subset input object.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: REPLACEME
+ **/
+hb_bool_t
+hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag)
+{
+ hb_ot_var_axis_info_t axis_info;
+ if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+ return false;
+
+ return input->axes_location->set (axis_tag, axis_info.default_value);
+}
+
+/**
+ * hb_subset_input_pin_axis_location: (skip)
+ * @input: a #hb_subset_input_t object.
+ * @axis_tag: Tag of the axis to be pinned
+ * @axis_value: Location on the axis to be pinned at
+ *
+ * Pin an axis to a fixed location in the given subset input object.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: REPLACEME
+ **/
+hb_bool_t
+hb_subset_input_pin_axis_location (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag,
+ float axis_value)
+{
+ hb_ot_var_axis_info_t axis_info;
+ if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+ return false;
+
+ float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value);
+ return input->axes_location->set (axis_tag, val);
+}
+#endif
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-subset-input.hh b/thirdparty/harfbuzz/src/hb-subset-input.hh
index 07c0e22676..2335f0634f 100644
--- a/thirdparty/harfbuzz/src/hb-subset-input.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-input.hh
@@ -50,6 +50,7 @@ struct hb_subset_input_t
hb_set_t *name_ids;
hb_set_t *name_languages;
hb_set_t *layout_features;
+ hb_set_t *layout_scripts;
};
union {
@@ -58,6 +59,7 @@ struct hb_subset_input_t
};
unsigned flags;
+ hb_hashmap_t<hb_tag_t, float> *axes_location;
inline unsigned num_sets () const
{
@@ -76,7 +78,8 @@ struct hb_subset_input_t
if (unlikely (set_ptrs[i]->in_error ()))
return true;
}
- return false;
+
+ return axes_location->in_error ();
}
};
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc
index a62ae8e024..7ff66333a8 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc
@@ -37,13 +37,14 @@
#include "hb-ot-color-colr-table.hh"
#include "hb-ot-color-colrv1-closure.hh"
#include "hb-ot-var-fvar-table.hh"
+#include "hb-ot-var-avar-table.hh"
#include "hb-ot-stat-table.hh"
#include "hb-ot-math-table.hh"
-using OT::Layout::GSUB::GSUB;
+using OT::Layout::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,
@@ -91,100 +92,171 @@ _remap_indexes (const hb_set_t *indexes,
typedef void (*layout_collect_func_t) (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, const hb_tag_t *languages, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */);
+/*
+ * Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates.
+ * Returns true if anything was removed (not including duplicates).
+ */
+static bool _filter_tag_list(hb_vector_t<hb_tag_t>* tags, /* IN/OUT */
+ const hb_set_t* filter)
+{
+ hb_vector_t<hb_tag_t> out;
+ out.alloc (tags->get_size() + 1); // +1 is to allocate room for the null terminator.
+
+ bool removed = false;
+ hb_set_t visited;
+
+ for (hb_tag_t tag : *tags)
+ {
+ if (!tag) continue;
+ if (visited.has (tag)) continue;
+
+ if (!filter->has (tag))
+ {
+ removed = true;
+ continue;
+ }
+
+ visited.add (tag);
+ out.push (tag);
+ }
+
+ // The collect function needs a null element to signal end of the array.
+ out.push (HB_TAG_NONE);
+
+ hb_swap (out, *tags);
+ return removed;
+}
+
template <typename T>
-static void _collect_layout_indices (hb_face_t *face,
+static void _collect_layout_indices (hb_subset_plan_t *plan,
const T& table,
- const hb_set_t *layout_features_to_retain,
layout_collect_func_t layout_collect_func,
hb_set_t *indices /* OUT */)
{
+ unsigned num_features = table.get_feature_count ();
hb_vector_t<hb_tag_t> features;
- if (!features.alloc (table.get_feature_count () + 1))
+ if (!plan->check_success (features.resize (num_features))) return;
+ table.get_feature_tags (0, &num_features, features.arrayZ);
+ bool retain_all_features = !_filter_tag_list (&features, plan->layout_features);
+
+ unsigned num_scripts = table.get_script_count ();
+ hb_vector_t<hb_tag_t> scripts;
+ if (!plan->check_success (scripts.resize (num_scripts))) return;
+ table.get_script_tags (0, &num_scripts, scripts.arrayZ);
+ bool retain_all_scripts = !_filter_tag_list (&scripts, plan->layout_scripts);
+
+ if (!plan->check_success (!features.in_error ()) || !features
+ || !plan->check_success (!scripts.in_error ()) || !scripts)
return;
- hb_set_t visited_features;
- bool retain_all_features = true;
- for (unsigned i = 0; i < table.get_feature_count (); i++)
+ layout_collect_func (plan->source,
+ T::tableTag,
+ retain_all_scripts ? nullptr : scripts.arrayZ,
+ nullptr,
+ retain_all_features ? nullptr : features.arrayZ,
+ indices);
+}
+
+
+static inline void
+_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
+ const hb_map_t *lookup_indices,
+ const hb_set_t *feature_indices,
+ hb_map_t *duplicate_feature_map /* OUT */)
+{
+ if (feature_indices->is_empty ()) return;
+ 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 ())
{
- hb_tag_t tag = table.get_feature_tag (i);
- if (!tag) continue;
- if (!layout_features_to_retain->has (tag))
+ hb_tag_t t = g.get_feature_tag (i);
+ if (t == HB_MAP_VALUE_INVALID) continue;
+ if (!unique_features.has (t))
{
- retain_all_features = false;
+ if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
+ return;
+ if (unique_features.has (t))
+ unique_features.get (t)->add (i);
+ duplicate_feature_map->set (i, i);
continue;
}
- if (visited_features.has (tag))
- continue;
+ bool found = false;
- features.push (tag);
- visited_features.add (tag);
- }
+ hb_set_t* same_tag_features = unique_features.get (t);
+ for (unsigned other_f_index : same_tag_features->iter ())
+ {
+ const OT::Feature& f = g.get_feature (i);
+ const OT::Feature& other_f = g.get_feature (other_f_index);
- if (!features)
- return;
+ auto f_iter =
+ + hb_iter (f.lookupIndex)
+ | hb_filter (lookup_indices)
+ ;
- // The collect function needs a null element to signal end of the array.
- features.push (0);
+ auto other_f_iter =
+ + hb_iter (other_f.lookupIndex)
+ | hb_filter (lookup_indices)
+ ;
- if (retain_all_features)
- {
- // Looking for all features, trigger the faster collection method.
- layout_collect_func (face,
- T::tableTag,
- nullptr,
- nullptr,
- nullptr,
- indices);
- return;
- }
+ bool is_equal = true;
+ for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
+ {
+ unsigned a = *f_iter;
+ unsigned b = *other_f_iter;
+ if (a != b) { is_equal = false; break; }
+ }
- layout_collect_func (face,
- T::tableTag,
- nullptr,
- nullptr,
- features.arrayZ,
- indices);
+ if (is_equal == false || f_iter || other_f_iter) continue;
+
+ found = true;
+ duplicate_feature_map->set (i, other_f_index);
+ break;
+ }
+
+ if (found == false)
+ {
+ same_tag_features->add (i);
+ duplicate_feature_map->set (i, i);
+ }
+ }
}
template <typename T>
static inline void
-_closure_glyphs_lookups_features (hb_face_t *face,
+_closure_glyphs_lookups_features (hb_subset_plan_t *plan,
hb_set_t *gids_to_retain,
- const hb_set_t *layout_features_to_retain,
hb_map_t *lookups,
hb_map_t *features,
script_langsys_map *langsys_map)
{
- hb_blob_ptr_t<T> table = hb_sanitize_context_t ().reference_table<T> (face);
+ hb_blob_ptr_t<T> table = plan->source_table<T> ();
hb_tag_t table_tag = table->tableTag;
hb_set_t lookup_indices;
- _collect_layout_indices<T> (face,
+ _collect_layout_indices<T> (plan,
*table,
- layout_features_to_retain,
hb_ot_layout_collect_lookups,
&lookup_indices);
if (table_tag == HB_OT_TAG_GSUB)
- hb_ot_layout_lookups_substitute_closure (face,
- &lookup_indices,
+ hb_ot_layout_lookups_substitute_closure (plan->source,
+ &lookup_indices,
gids_to_retain);
- table->closure_lookups (face,
+ table->closure_lookups (plan->source,
gids_to_retain,
- &lookup_indices);
+ &lookup_indices);
_remap_indexes (&lookup_indices, lookups);
// Collect and prune features
hb_set_t feature_indices;
- _collect_layout_indices<T> (face,
+ _collect_layout_indices<T> (plan,
*table,
- layout_features_to_retain,
hb_ot_layout_collect_features,
&feature_indices);
table->prune_features (lookups, &feature_indices);
hb_map_t duplicate_feature_map;
- table->find_duplicate_features (lookups, &feature_indices, &duplicate_feature_map);
+ _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, &duplicate_feature_map);
feature_indices.clear ();
table->prune_langsys (&duplicate_feature_map, langsys_map, &feature_indices);
@@ -197,14 +269,14 @@ _closure_glyphs_lookups_features (hb_face_t *face,
#ifndef HB_NO_VAR
static inline void
- _collect_layout_variation_indices (hb_face_t *face,
- const hb_set_t *glyphset,
- const hb_map_t *gpos_lookups,
- hb_set_t *layout_variation_indices,
- hb_map_t *layout_variation_idx_map)
+_collect_layout_variation_indices (hb_subset_plan_t* plan,
+ const hb_set_t *glyphset,
+ const hb_map_t *gpos_lookups,
+ hb_set_t *layout_variation_indices,
+ 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<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
+ hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
if (!gdef->has_data ())
{
@@ -215,7 +287,7 @@ static inline void
OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups);
gdef->collect_variation_indices (&c);
- if (hb_ot_layout_has_positioning (face))
+ if (hb_ot_layout_has_positioning (plan->source))
gpos->collect_variation_indices (&c);
gdef->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map);
@@ -242,22 +314,16 @@ static void _colr_closure (hb_face_t *face,
OT::COLR::accelerator_t colr (face);
if (!colr.is_valid ()) return;
- unsigned iteration_count = 0;
hb_set_t palette_indices, layer_indices;
- unsigned glyphs_num;
- {
- glyphs_num = glyphs_colred->get_population ();
- // Collect all glyphs referenced by COLRv0
- hb_set_t glyphset_colrv0;
- for (hb_codepoint_t gid : glyphs_colred->iter ())
- colr.closure_glyphs (gid, &glyphset_colrv0);
+ // Collect all glyphs referenced by COLRv0
+ hb_set_t glyphset_colrv0;
+ for (hb_codepoint_t gid : *glyphs_colred)
+ colr.closure_glyphs (gid, &glyphset_colrv0);
- glyphs_colred->union_ (glyphset_colrv0);
+ glyphs_colred->union_ (glyphset_colrv0);
- //closure for COLRv1
- colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
- } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
- glyphs_num != glyphs_colred->get_population ());
+ //closure for COLRv1
+ colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
_remap_indexes (&layer_indices, layers_map);
@@ -265,10 +331,10 @@ static void _colr_closure (hb_face_t *face,
}
static inline void
-_math_closure (hb_face_t *face,
- hb_set_t *glyphset)
+_math_closure (hb_subset_plan_t *plan,
+ hb_set_t *glyphset)
{
- hb_blob_ptr_t<OT::MATH> math = hb_sanitize_context_t ().reference_table<OT::MATH> (face);
+ hb_blob_ptr_t<OT::MATH> math = plan->source_table<OT::MATH> ();
if (math->has_data ())
math->closure_glyphs (glyphset);
math.destroy ();
@@ -347,13 +413,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.get_gid (),
+ 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
@@ -366,18 +461,16 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
if (close_over_gsub)
// closure all glyphs/lookups/features needed for GSUB substitutions.
_closure_glyphs_lookups_features<GSUB> (
- plan->source,
+ plan,
plan->_glyphset_gsub,
- plan->layout_features,
plan->gsub_lookups,
plan->gsub_features,
plan->gsub_langsys);
if (close_over_gpos)
- _closure_glyphs_lookups_features<OT::GPOS> (
- plan->source,
+ _closure_glyphs_lookups_features<GPOS> (
+ plan,
plan->_glyphset_gsub,
- plan->layout_features,
plan->gpos_lookups,
plan->gpos_features,
plan->gpos_langsys);
@@ -385,7 +478,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
- _math_closure (plan->source, plan->_glyphset_mathed);
+ _math_closure (plan, plan->_glyphset_mathed);
_remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
hb_set_t cur_glyphset = *plan->_glyphset_mathed;
@@ -398,7 +491,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
@@ -412,7 +506,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
#ifndef HB_NO_VAR
if (close_over_gdef)
- _collect_layout_variation_indices (plan->source,
+ _collect_layout_variation_indices (plan,
plan->_glyphset_gsub,
plan->gpos_lookups,
plan->layout_variation_indices,
@@ -476,16 +570,62 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
static void
_nameid_closure (hb_face_t *face,
- hb_set_t *nameids)
+ hb_set_t *nameids,
+ bool all_axes_pinned,
+ hb_hashmap_t<hb_tag_t, float> *user_axes_location)
{
#ifndef HB_NO_STYLE
- face->table.STAT->collect_name_ids (nameids);
+ face->table.STAT->collect_name_ids (user_axes_location, nameids);
#endif
#ifndef HB_NO_VAR
- face->table.fvar->collect_name_ids (nameids);
+ if (!all_axes_pinned)
+ face->table.fvar->collect_name_ids (user_axes_location, nameids);
#endif
}
+#ifndef HB_NO_VAR
+static void
+_normalize_axes_location (hb_face_t *face,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ hb_hashmap_t<hb_tag_t, int> *normalized_axes_location, /* OUT */
+ bool &all_axes_pinned)
+{
+ if (user_axes_location->is_empty ())
+ return;
+
+ hb_array_t<const OT::AxisRecord> axes = face->table.fvar->get_axes ();
+
+ bool has_avar = face->table.avar->has_data ();
+ const OT::SegmentMaps *seg_maps = nullptr;
+ if (has_avar)
+ seg_maps = face->table.avar->get_segment_maps ();
+
+ bool axis_not_pinned = false;
+ unsigned axis_count = 0;
+ for (const auto& axis : axes)
+ {
+ hb_tag_t axis_tag = axis.get_axis_tag ();
+ if (!user_axes_location->has (axis_tag))
+ {
+ axis_not_pinned = true;
+ }
+ else
+ {
+ int normalized_v = axis.normalize_axis_value (user_axes_location->get (axis_tag));
+ if (has_avar && axis_count < face->table.avar->get_axis_count ())
+ {
+ normalized_v = seg_maps->map (normalized_v);
+ }
+ normalized_axes_location->set (axis_tag, normalized_v);
+ }
+ if (has_avar)
+ seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
+
+ axis_count++;
+ }
+ all_axes_pinned = !axis_not_pinned;
+}
+#endif
/**
* hb_subset_plan_create_or_fail:
* @face: font face to create the plan for.
@@ -516,9 +656,9 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->unicode_to_new_gid_list.init ();
plan->name_ids = hb_set_copy (input->sets.name_ids);
- _nameid_closure (face, plan->name_ids);
plan->name_languages = hb_set_copy (input->sets.name_languages);
plan->layout_features = hb_set_copy (input->sets.layout_features);
+ plan->layout_scripts = hb_set_copy (input->sets.layout_scripts);
plan->glyphs_requested = hb_set_copy (input->sets.glyphs);
plan->drop_tables = hb_set_copy (input->sets.drop_tables);
plan->no_subset_tables = hb_set_copy (input->sets.no_subset_tables);
@@ -536,10 +676,8 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->gsub_lookups = hb_map_create ();
plan->gpos_lookups = hb_map_create ();
- if (plan->check_success (plan->gsub_langsys = hb_object_create<script_langsys_map> ()))
- plan->gsub_langsys->init_shallow ();
- if (plan->check_success (plan->gpos_langsys = hb_object_create<script_langsys_map> ()))
- plan->gpos_langsys->init_shallow ();
+ plan->check_success (plan->gsub_langsys = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ());
+ plan->check_success (plan->gpos_langsys = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ());
plan->gsub_features = hb_map_create ();
plan->gpos_features = hb_map_create ();
@@ -548,6 +686,13 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->layout_variation_indices = hb_set_create ();
plan->layout_variation_idx_map = hb_map_create ();
+ plan->check_success (plan->sanitized_table_cache = hb_hashmap_create<hb_tag_t, hb::unique_ptr<hb_blob_t>> ());
+ plan->check_success (plan->axes_location = hb_hashmap_create<hb_tag_t, int> ());
+ plan->check_success (plan->user_axes_location = hb_hashmap_create<hb_tag_t, float> ());
+ if (plan->user_axes_location && input->axes_location)
+ *plan->user_axes_location = *input->axes_location;
+ plan->all_axes_pinned = false;
+
if (unlikely (plan->in_error ())) {
hb_subset_plan_destroy (plan);
return nullptr;
@@ -580,6 +725,14 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->glyph_map->get(plan->unicode_to_new_gid_list.arrayZ[i].second);
}
+#ifndef HB_NO_VAR
+ _normalize_axes_location (face,
+ input->axes_location,
+ plan->axes_location,
+ plan->all_axes_pinned);
+#endif
+
+ _nameid_closure (face, plan->name_ids, plan->all_axes_pinned, plan->user_axes_location);
if (unlikely (plan->in_error ())) {
hb_subset_plan_destroy (plan);
return nullptr;
@@ -602,10 +755,10 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
if (!hb_object_destroy (plan)) return;
hb_set_destroy (plan->unicodes);
- plan->unicode_to_new_gid_list.fini ();
hb_set_destroy (plan->name_ids);
hb_set_destroy (plan->name_languages);
hb_set_destroy (plan->layout_features);
+ hb_set_destroy (plan->layout_scripts);
hb_set_destroy (plan->glyphs_requested);
hb_set_destroy (plan->drop_tables);
hb_set_destroy (plan->no_subset_tables);
@@ -628,24 +781,15 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_set_destroy (plan->layout_variation_indices);
hb_map_destroy (plan->layout_variation_idx_map);
- 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);
- }
+ hb_hashmap_destroy (plan->gsub_langsys);
+ hb_hashmap_destroy (plan->gpos_langsys);
+ hb_hashmap_destroy (plan->axes_location);
+ hb_hashmap_destroy (plan->sanitized_table_cache);
- if (plan->gpos_langsys)
+ if (plan->user_axes_location)
{
- 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);
+ hb_object_destroy (plan->user_axes_location);
+ hb_free (plan->user_axes_location);
}
hb_free (plan);
@@ -731,7 +875,7 @@ hb_subset_plan_reference (hb_subset_plan_t *plan)
*
* Attaches a user-data key/data pair to the given subset plan object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 4.0.0
**/
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh
index cb567b769e..8912ae70d5 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh
@@ -55,6 +55,9 @@ struct hb_subset_plan_t
//layout features which will be preserved
hb_set_t *layout_features;
+ // layout scripts which will be preserved.
+ hb_set_t *layout_scripts;
+
//glyph ids requested to retain
hb_set_t *glyphs_requested;
@@ -87,8 +90,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;
@@ -103,8 +106,34 @@ struct hb_subset_plan_t
//Old -> New layout item variation store delta set index mapping
hb_map_t *layout_variation_idx_map;
+ hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache;
+ //normalized axes location map
+ hb_hashmap_t<hb_tag_t, int> *axes_location;
+ //user specified axes location map
+ hb_hashmap_t<hb_tag_t, float> *user_axes_location;
+ bool all_axes_pinned;
+
public:
+ template<typename T>
+ hb_blob_ptr_t<T> source_table()
+ {
+ if (sanitized_table_cache
+ && !sanitized_table_cache->in_error ()
+ && sanitized_table_cache->has (T::tableTag)) {
+ return hb_blob_reference (sanitized_table_cache->get (T::tableTag).get ());
+ }
+
+ hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)};
+ hb_blob_t* ret = hb_blob_reference (table_blob.get ());
+
+ if (likely (sanitized_table_cache))
+ sanitized_table_cache->set (T::tableTag,
+ std::move (table_blob));
+
+ return ret;
+ }
+
bool in_error () const { return !successful; }
bool check_success(bool success)
diff --git a/thirdparty/harfbuzz/src/hb-subset-repacker.cc b/thirdparty/harfbuzz/src/hb-subset-repacker.cc
index 2447d296b8..55ca48d709 100644
--- a/thirdparty/harfbuzz/src/hb-subset-repacker.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-repacker.cc
@@ -25,25 +25,34 @@
#include "hb-repacker.hh"
#ifdef HB_EXPERIMENTAL_API
+
/**
* hb_subset_repack_or_fail:
+ * @table_tag: tag of the table being packed, needed to allow table specific optimizations.
* @hb_objects: raw array of struct hb_object_t, which provides
* object graph info
* @num_hb_objs: number of hb_object_t in the hb_objects array.
*
* Given the input object graph info, repack a table to eliminate
* offset overflows. A nullptr is returned if the repacking attempt fails.
+ * Table specific optimizations (eg. extension promotion in GSUB/GPOS) may be performed.
+ * Passing HB_TAG_NONE will disable table specific optimizations.
*
* Since: EXPERIMENTAL
**/
-hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_objs)
+hb_blob_t* hb_subset_repack_or_fail (hb_tag_t table_tag,
+ hb_object_t* hb_objects,
+ unsigned num_hb_objs)
{
hb_vector_t<const hb_object_t *> packed;
packed.alloc (num_hb_objs + 1);
packed.push (nullptr);
for (unsigned i = 0 ; i < num_hb_objs ; i++)
packed.push (&(hb_objects[i]));
- return hb_resolve_overflows (packed, HB_OT_TAG_GSUB);
+
+ return hb_resolve_overflows (packed,
+ table_tag,
+ 20,
+ true);
}
#endif
-
diff --git a/thirdparty/harfbuzz/src/hb-subset-repacker.h b/thirdparty/harfbuzz/src/hb-subset-repacker.h
index f9a2383698..245cf60765 100644
--- a/thirdparty/harfbuzz/src/hb-subset-repacker.h
+++ b/thirdparty/harfbuzz/src/hb-subset-repacker.h
@@ -31,13 +31,13 @@
HB_BEGIN_DECLS
#ifdef HB_EXPERIMENTAL_API
-/**
+/*
* struct hb_link_t
* width: offsetSize in bytes
* position: position of the offset field in bytes
* from beginning of subtable
* objidx: index of subtable
- **/
+ */
struct hb_link_t
{
unsigned width;
@@ -47,7 +47,7 @@ struct hb_link_t
typedef struct hb_link_t hb_link_t;
-/**
+/*
* struct hb_object_t
* head: start of object data
* tail: end of object data
@@ -56,7 +56,7 @@ typedef struct hb_link_t hb_link_t;
* num_virtual_links: num of objects that must be packed
* after current object in the final serialized order
* virtual_links: array of virtual link info
- **/
+ */
struct hb_object_t
{
char *head;
@@ -70,7 +70,8 @@ struct hb_object_t
typedef struct hb_object_t hb_object_t;
HB_EXTERN hb_blob_t*
-hb_subset_repack_or_fail (hb_object_t* hb_objects,
+hb_subset_repack_or_fail (hb_tag_t table_tag,
+ hb_object_t* hb_objects,
unsigned num_hb_objs);
#endif
diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc
index 31ddb4f894..f62e7e895b 100644
--- a/thirdparty/harfbuzz/src/hb-subset.cc
+++ b/thirdparty/harfbuzz/src/hb-subset.cc
@@ -53,9 +53,11 @@
#include "hb-ot-var-gvar-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-ot-math-table.hh"
+#include "hb-ot-stat-table.hh"
#include "hb-repacker.hh"
-using OT::Layout::GSUB::GSUB;
+using OT::Layout::GSUB;
+using OT::Layout::GPOS;
/**
* SECTION:hb-subset
@@ -78,6 +80,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,
@@ -139,10 +243,15 @@ _try_subset (const TableType *table,
unsigned buf_size = buf->allocated;
buf_size = buf_size * 2 + 16;
+
+
+
+
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
HB_UNTAG (c->table_tag), buf_size);
- if (unlikely (!buf->alloc (buf_size)))
+ if (unlikely (buf_size > c->source_blob->length * 16 ||
+ !buf->alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
HB_UNTAG (c->table_tag), buf_size);
@@ -157,15 +266,15 @@ template<typename TableType>
static bool
_subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
{
- hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
- const TableType *table = source_blob->as<TableType> ();
+ hb_blob_ptr_t<TableType> source_blob = plan->source_table<TableType> ();
+ const TableType *table = source_blob.get ();
hb_tag_t tag = TableType::tableTag;
- if (!source_blob->data)
+ if (!source_blob.get_blob()->data)
{
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
- hb_blob_destroy (source_blob);
+ source_blob.destroy ();
return false;
}
@@ -175,23 +284,23 @@ _subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
TableType::tableTag == HB_OT_TAG_GPOS ||
TableType::tableTag == HB_OT_TAG_name;
- unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length, same_size_table);
+ unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob.get_length (), same_size_table);
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
- hb_blob_destroy (source_blob);
+ source_blob.destroy ();
return false;
}
bool needed = false;
hb_serialize_context_t serializer (buf.arrayZ, buf.allocated);
{
- hb_subset_context_t c (source_blob, plan, &serializer, tag);
+ hb_subset_context_t c (source_blob.get_blob (), plan, &serializer, tag);
needed = _try_subset (table, &buf, &c);
}
- hb_blob_destroy (source_blob);
+ source_blob.destroy ();
if (serializer.in_error () && !serializer.only_offset_overflow ())
{
@@ -224,9 +333,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)
@@ -245,6 +362,8 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
switch (tag)
{
case HB_TAG ('c','v','a','r'): /* hint table, fallthrough */
+ return plan->all_axes_pinned || (plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+
case HB_TAG ('c','v','t',' '): /* hint table, fallthrough */
case HB_TAG ('f','p','g','m'): /* hint table, fallthrough */
case HB_TAG ('p','r','e','p'): /* hint table, fallthrough */
@@ -264,6 +383,14 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
return true;
#endif
+ case HB_TAG ('a','v','a','r'):
+ case HB_TAG ('f','v','a','r'):
+ case HB_TAG ('g','v','a','r'):
+ case HB_OT_TAG_HVAR:
+ case HB_OT_TAG_VVAR:
+ case HB_TAG ('M','V','A','R'):
+ return plan->all_axes_pinned;
+
default:
return false;
}
@@ -322,11 +449,16 @@ _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);
#endif
+ case HB_OT_TAG_STAT:
+ /*TODO(qxliu): change the condition as we support more complex
+ * instancing operation*/
+ if (plan->all_axes_pinned) return _subset<const OT::STAT> (plan, buf);
+ else return _passthrough (plan, tag);
default:
if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED)
@@ -388,7 +520,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 +533,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-subset.h b/thirdparty/harfbuzz/src/hb-subset.h
index a2799d91e8..08e52dbd2d 100644
--- a/thirdparty/harfbuzz/src/hb-subset.h
+++ b/thirdparty/harfbuzz/src/hb-subset.h
@@ -100,6 +100,8 @@ typedef enum { /*< flags >*/
* @HB_SUBSET_SETS_NAME_LANG_ID: the set of name lang ids that will be retained.
* @HB_SUBSET_SETS_LAYOUT_FEATURE_TAG: the set of layout feature tags that will be retained
* in the subset.
+ * @HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG: the set of layout script tags that will be retained
+ * in the subset. Defaults to all tags. Since: 5.0.0
*
* List of sets that can be configured on the subset input.
*
@@ -113,6 +115,7 @@ typedef enum {
HB_SUBSET_SETS_NAME_ID,
HB_SUBSET_SETS_NAME_LANG_ID,
HB_SUBSET_SETS_LAYOUT_FEATURE_TAG,
+ HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG,
} hb_subset_sets_t;
HB_EXTERN hb_subset_input_t *
@@ -151,6 +154,21 @@ HB_EXTERN void
hb_subset_input_set_flags (hb_subset_input_t *input,
unsigned value);
+#ifdef HB_EXPERIMENTAL_API
+#ifndef HB_NO_VAR
+HB_EXTERN hb_bool_t
+hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag);
+
+HB_EXTERN hb_bool_t
+hb_subset_input_pin_axis_location (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag,
+ float axis_value);
+#endif
+#endif
+
HB_EXTERN hb_face_t *
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
diff --git a/thirdparty/harfbuzz/src/hb-ucd-table.hh b/thirdparty/harfbuzz/src/hb-ucd-table.hh
index 1a4c89c17f..14734c91ea 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] =
@@ -1067,2860 +1068,6 @@ _hb_ucd_dm2_u64_map[388] =
#ifndef HB_OPTIMIZE_SIZE
static const uint8_t
-_hb_ucd_u8[33120] =
-{
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 28, 26, 29, 30, 31, 32, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 33, 34, 34, 34, 34,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 26, 56, 57, 58, 58, 58, 58, 59, 26, 26, 60, 58, 58, 58, 58, 58,
- 58, 58, 26, 61, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 26, 62, 58, 63, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 64, 26, 26, 65, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 66, 67, 68, 58, 58, 58, 58, 69, 58,
- 58, 58, 58, 58, 58, 58, 58, 70, 71, 72, 73, 74, 75, 76, 58, 77,
- 78, 79, 58, 80, 81, 58, 82, 83, 84, 85, 75, 86, 87, 88, 58, 58,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 89, 26, 26, 26, 26, 26, 26, 26, 90, 91, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 92, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 93, 58, 58, 58, 58, 58, 58, 26, 94, 58, 58,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 95, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 96, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 97,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 98,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 29, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 25, 25, 25, 21,
- 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 21, 18, 24, 16,
- 24, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 25, 18, 25, 0,
- 29, 21, 23, 23, 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24,
- 26, 25, 15, 15, 24, 5, 21, 21, 24, 15, 7, 19, 15, 15, 15, 21,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 25, 9, 9, 9, 9, 9, 9, 9, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 5, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9,
- 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 9, 5, 5,
- 5, 9, 9, 5, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 9, 9,
- 9, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 5, 9, 9, 5, 9,
- 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 5, 9, 5, 9, 9,
- 5, 9, 9, 9, 5, 9, 5, 9, 9, 5, 5, 7, 9, 5, 5, 5,
- 7, 7, 7, 7, 9, 8, 5, 9, 8, 5, 9, 8, 5, 9, 5, 9,
- 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5,
- 5, 9, 8, 5, 9, 5, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 9, 9, 5, 9, 9, 5,
- 5, 9, 5, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 6, 6, 6, 6, 6, 24, 24, 24, 24, 24, 24, 24, 6, 24, 6, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 9, 5, 9, 5, 6, 24, 9, 5, 2, 2, 6, 5, 5, 5, 21, 9,
- 2, 2, 2, 2, 24, 24, 9, 21, 9, 9, 9, 2, 9, 2, 9, 9,
- 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9,
- 5, 5, 9, 9, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 5, 5, 5, 5, 9, 5, 25, 9, 5, 9, 9, 5, 5, 9, 9, 9,
- 9, 5, 26, 12, 12, 12, 12, 12, 11, 11, 9, 5, 9, 5, 9, 5,
- 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5,
- 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 2, 2, 6, 21, 21, 21, 21, 21, 21,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 17, 2, 2, 26, 26, 23,
- 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 17, 12,
- 21, 12, 12, 21, 12, 12, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7,
- 7, 7, 7, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 25, 25, 25, 21, 21, 23, 21, 21, 26, 26,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 1, 21, 21, 21,
- 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 7, 7,
- 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 21, 7, 12, 12, 12, 12, 12, 12, 12, 1, 26, 12,
- 12, 12, 12, 12, 12, 6, 6, 12, 12, 26, 12, 12, 12, 12, 7, 7,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 26, 26, 7,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 1,
- 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 6, 6, 26, 21, 21, 21, 6, 2, 2, 12, 23, 23,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 6, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 6, 12, 12, 12, 6, 12, 12, 12, 12, 12, 2, 2,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 2, 2, 21, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 24, 7, 7, 7, 7, 7, 7, 2,
- 1, 1, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 12, 12, 12, 12, 12, 12,
- 12, 12, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 12, 10, 10,
- 7, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 12, 12, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 21, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7,
- 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7,
- 7, 2, 7, 2, 2, 2, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 7, 2,
- 2, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 7, 7, 2, 7,
- 7, 7, 12, 12, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 7, 7, 23, 23, 15, 15, 15, 15, 15, 15, 26, 23, 7, 21, 12, 2,
- 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7,
- 7, 2, 7, 7, 2, 7, 7, 2, 7, 7, 2, 2, 12, 2, 10, 10,
- 10, 12, 12, 2, 2, 2, 2, 12, 12, 2, 2, 12, 12, 12, 2, 2,
- 2, 12, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 2, 7, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 12, 12, 7, 7, 7, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7,
- 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 12, 2, 12, 12, 10, 2, 10, 10, 12, 2, 2,
- 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 21, 23, 2, 2, 2, 2, 2, 2, 2, 7, 12, 12, 12, 12, 12, 12,
- 2, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7,
- 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12,
- 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 2, 2,
- 2, 2, 2, 2, 2, 12, 12, 10, 2, 2, 2, 2, 7, 7, 2, 7,
- 26, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 12, 7, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7,
- 7, 2, 7, 7, 7, 7, 2, 2, 2, 7, 7, 2, 7, 2, 7, 7,
- 2, 2, 2, 7, 7, 2, 2, 2, 7, 7, 7, 2, 2, 2, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 10, 10,
- 12, 10, 10, 2, 2, 2, 10, 10, 10, 2, 10, 10, 10, 12, 2, 2,
- 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 26, 26, 26, 26, 26, 26, 23, 26, 2, 2, 2, 2, 2,
- 12, 10, 10, 10, 12, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 7, 12, 12,
- 12, 10, 10, 10, 10, 2, 12, 12, 12, 2, 12, 12, 12, 12, 2, 2,
- 2, 2, 2, 2, 2, 12, 12, 2, 7, 7, 7, 2, 2, 7, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 21, 15, 15, 15, 15, 15, 15, 15, 26,
- 7, 12, 10, 10, 21, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12,
- 10, 10, 10, 10, 10, 2, 12, 10, 10, 2, 10, 10, 12, 12, 2, 2,
- 2, 2, 2, 2, 2, 10, 10, 2, 2, 2, 2, 2, 2, 7, 7, 2,
- 2, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 2, 10, 10, 10, 2, 10, 10, 10, 12, 7, 26,
- 2, 2, 2, 2, 7, 7, 7, 10, 15, 15, 15, 15, 15, 15, 15, 7,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 7, 7, 7, 7, 7, 7,
- 2, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7, 7, 7, 7, 7,
- 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 12, 2, 2, 2, 2, 10,
- 10, 10, 12, 12, 12, 2, 12, 2, 10, 10, 10, 10, 10, 10, 10, 10,
- 2, 2, 10, 10, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 23,
- 7, 7, 7, 7, 7, 7, 6, 12, 12, 12, 12, 12, 12, 12, 12, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7,
- 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 2, 2,
- 7, 7, 7, 7, 7, 2, 6, 2, 12, 12, 12, 12, 12, 12, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 7, 7, 7, 7,
- 7, 26, 26, 26, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 26, 21, 26, 26, 26, 12, 12, 26, 26, 26, 26, 26, 26,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 26, 12, 26, 12, 26, 12, 22, 18, 22, 18, 10, 10,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2,
- 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
- 12, 12, 12, 12, 12, 21, 12, 12, 7, 7, 7, 7, 7, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 26, 26,
- 26, 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 2, 26, 26,
- 21, 21, 21, 21, 21, 26, 26, 26, 26, 21, 21, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 12,
- 12, 10, 12, 12, 12, 12, 12, 12, 10, 12, 12, 10, 10, 12, 12, 7,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 21, 21,
- 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 7, 7, 7, 7, 12, 12,
- 12, 7, 10, 10, 10, 7, 7, 10, 10, 10, 10, 10, 10, 10, 7, 7,
- 7, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 12, 10, 10, 12, 12, 10, 10, 10, 10, 10, 10, 12, 7, 10,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 12, 26, 26,
- 9, 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 2, 2, 9, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 6, 5, 5, 5,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 2,
- 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 2,
- 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 2, 2, 5, 5, 5, 5, 5, 5, 2, 2,
- 17, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 26, 21, 7,
- 29, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 22, 18, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 21, 21, 14, 14,
- 14, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 12, 12, 12, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7,
- 7, 7, 12, 12, 10, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 2, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, 10, 10,
- 10, 10, 10, 10, 10, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 21, 21, 21, 6, 21, 21, 21, 23, 7, 12, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2,
- 21, 21, 21, 21, 21, 21, 17, 21, 21, 21, 21, 12, 12, 12, 1, 12,
- 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 7, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2,
- 12, 12, 12, 10, 10, 10, 10, 12, 12, 10, 10, 10, 2, 2, 2, 2,
- 10, 10, 12, 10, 10, 10, 10, 10, 10, 12, 12, 12, 2, 2, 2, 2,
- 26, 2, 2, 2, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2,
- 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 2, 2, 2, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 7, 7, 7, 7, 7, 7, 7, 12, 12, 10, 10, 12, 2, 2, 21, 21,
- 7, 7, 7, 7, 7, 10, 12, 10, 12, 12, 12, 12, 12, 12, 12, 2,
- 12, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12,
- 21, 21, 21, 21, 21, 21, 21, 6, 21, 21, 21, 21, 21, 21, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2,
- 12, 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 12, 10, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10,
- 10, 10, 12, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2,
- 21, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 21, 21, 2,
- 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 12, 12, 12, 7, 7,
- 7, 7, 7, 7, 7, 7, 12, 10, 12, 12, 10, 10, 10, 12, 10, 12,
- 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21,
- 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12,
- 12, 12, 12, 12, 10, 10, 12, 12, 2, 2, 2, 21, 21, 21, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 21, 21,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9,
- 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 10, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 12, 7, 7,
- 7, 7, 7, 7, 12, 7, 7, 10, 12, 12, 7, 2, 2, 2, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
- 9, 5, 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9,
- 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 2, 9, 2, 9, 2, 9, 2, 9,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 8,
- 5, 5, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 5, 24,
- 24, 24, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 24,
- 5, 5, 5, 5, 2, 2, 5, 5, 9, 9, 9, 9, 2, 24, 24, 24,
- 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 24, 24, 24,
- 2, 2, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 2,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 1, 1, 1, 1, 1,
- 17, 17, 17, 17, 17, 17, 21, 21, 20, 19, 22, 20, 20, 19, 22, 20,
- 21, 21, 21, 21, 21, 21, 21, 21, 27, 28, 1, 1, 1, 1, 1, 29,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 21, 21, 21, 21, 16,
- 16, 21, 21, 21, 25, 22, 18, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 25, 21, 16, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 29,
- 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 15, 6, 2, 2, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 6,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 2,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
- 11, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 9, 26, 26, 26, 26, 9, 26, 26, 5, 9, 9, 9, 5, 5,
- 9, 9, 9, 5, 26, 9, 26, 26, 25, 9, 9, 9, 9, 9, 26, 26,
- 26, 26, 26, 26, 9, 26, 9, 26, 9, 26, 9, 9, 9, 9, 26, 5,
- 9, 9, 9, 9, 5, 7, 7, 7, 7, 5, 26, 26, 5, 5, 9, 9,
- 25, 25, 25, 25, 25, 9, 5, 5, 5, 5, 26, 25, 26, 26, 5, 26,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 9, 5, 14, 14, 14, 14, 15, 26, 26, 2, 2, 2, 2,
- 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 25, 25, 26, 26, 26, 26,
- 25, 26, 26, 25, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 25, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25,
- 26, 26, 25, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 26, 26, 26, 26,
- 25, 25, 26, 26, 26, 26, 26, 26, 26, 22, 18, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25,
- 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15,
- 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25,
- 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18,
- 22, 18, 22, 18, 22, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 25, 25, 25, 25, 25, 22, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18,
- 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
- 18, 22, 18, 22, 18, 22, 18, 22, 18, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 25, 25,
- 25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 26, 26, 26,
- 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 9, 5, 9, 9, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9,
- 9, 5, 9, 5, 5, 9, 5, 5, 5, 5, 5, 5, 6, 6, 9, 9,
- 9, 5, 9, 5, 5, 26, 26, 26, 26, 26, 26, 9, 5, 9, 5, 12,
- 12, 12, 9, 5, 2, 2, 2, 2, 2, 21, 21, 21, 21, 15, 21, 21,
- 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 2, 2, 5, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 6,
- 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 2,
- 21, 21, 20, 19, 20, 19, 21, 21, 21, 20, 19, 21, 20, 19, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 17, 21, 21, 17, 21, 20, 19, 21, 21,
- 20, 19, 22, 18, 22, 18, 22, 18, 22, 18, 21, 21, 21, 21, 21, 6,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 17, 17, 21, 21, 21, 21,
- 17, 21, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 26, 26, 21, 21, 21, 22, 18, 22, 18, 22, 18, 22, 18, 17, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2,
- 29, 21, 21, 21, 26, 6, 7, 14, 22, 18, 22, 18, 22, 18, 22, 18,
- 22, 18, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18, 17, 22, 18, 18,
- 26, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 10, 10,
- 17, 6, 6, 6, 6, 6, 26, 26, 14, 14, 14, 6, 7, 21, 26, 26,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 24, 24, 6, 6, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 6, 6, 6, 7,
- 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 26, 26, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15, 15, 15,
- 26, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 21, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 2, 2, 2, 2,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 7, 12,
- 11, 11, 11, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 6,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 6, 6, 12, 12,
- 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 12, 12, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2,
- 24, 24, 24, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 24, 24, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 6, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5, 9, 5, 9, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 6, 24, 24, 9, 5, 9, 5, 7,
- 9, 5, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9, 9, 9, 5,
- 9, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 9, 9, 9, 5, 9, 5, 2, 2, 2, 2, 2,
- 9, 5, 2, 5, 2, 5, 9, 5, 9, 5, 2, 2, 2, 2, 2, 2,
- 2, 2, 6, 6, 6, 9, 5, 7, 6, 6, 5, 7, 7, 7, 7, 7,
- 7, 7, 12, 7, 7, 7, 12, 7, 7, 7, 7, 12, 7, 7, 7, 7,
- 7, 7, 7, 10, 10, 12, 12, 10, 26, 26, 26, 26, 12, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 26, 26, 23, 26, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2,
- 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21,
- 12, 12, 7, 7, 7, 7, 7, 7, 21, 21, 21, 7, 21, 7, 7, 12,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 21, 21,
- 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
- 7, 7, 7, 12, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 10,
- 10, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 6,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 21, 21,
- 7, 7, 7, 7, 7, 12, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 10,
- 10, 12, 12, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 21, 21, 21, 21,
- 6, 7, 7, 7, 7, 7, 7, 26, 26, 26, 7, 10, 12, 10, 7, 7,
- 12, 7, 12, 12, 12, 7, 7, 12, 12, 7, 7, 7, 7, 7, 12, 12,
- 7, 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 6, 21, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 12, 12, 10, 10,
- 21, 21, 7, 6, 6, 10, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 2,
- 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 6, 6, 6, 6,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 24, 24, 2, 2, 2, 2,
- 7, 7, 7, 10, 10, 12, 10, 10, 12, 10, 10, 21, 10, 12, 2, 2,
- 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 7, 12, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 25, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 2,
- 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18, 22,
- 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 26,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 23, 26, 26, 26,
- 21, 21, 21, 21, 21, 21, 21, 22, 18, 21, 2, 2, 2, 2, 2, 2,
- 21, 17, 17, 16, 16, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
- 18, 22, 18, 22, 18, 21, 21, 22, 18, 21, 21, 21, 21, 16, 16, 16,
- 21, 21, 21, 2, 21, 21, 21, 21, 17, 22, 18, 22, 18, 22, 18, 21,
- 21, 21, 25, 17, 25, 25, 25, 2, 21, 23, 21, 21, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 1,
- 2, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 25, 18, 25, 22,
- 18, 21, 22, 18, 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6,
- 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7,
- 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 2, 2, 2,
- 23, 23, 25, 24, 26, 23, 23, 2, 26, 25, 25, 25, 25, 26, 26, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 26, 26, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7,
- 21, 21, 21, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 14, 14, 14, 14, 14, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 26, 26, 26, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2,
- 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 2, 2,
- 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2,
- 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7,
- 7, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 21,
- 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 21, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5,
- 9, 9, 9, 9, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9,
- 9, 9, 9, 2, 9, 9, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 2, 2, 2,
- 6, 6, 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 2, 2, 7, 2, 2, 7,
- 7, 7, 7, 7, 7, 7, 2, 21, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 7, 7, 7, 26, 26, 15, 15, 15, 15, 15, 15, 15,
- 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 2, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 15, 15, 7, 7,
- 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 12, 12, 12, 2, 12, 12, 2, 2, 2, 2, 2, 12, 12, 12, 12,
- 7, 7, 7, 7, 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12, 2, 2, 2, 2, 12,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15,
- 7, 7, 7, 7, 7, 7, 7, 7, 26, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 12, 12, 2, 2, 2, 2, 15, 15, 15, 15, 15,
- 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 2, 2, 21, 21, 21, 21, 21, 21, 21,
- 7, 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15,
- 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 12, 12, 17, 2, 2,
- 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 15, 15, 15, 15, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2,
- 7, 7, 12, 12, 12, 12, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2,
- 10, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 21, 21, 2, 2,
- 15, 15, 15, 15, 15, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 12, 7, 7, 12, 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12,
- 10, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 21, 21, 1, 21, 21,
- 21, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
- 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 10, 12, 12, 12,
- 12, 12, 12, 12, 12, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 21, 21, 21, 21, 7, 10, 10, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 12, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
- 10, 7, 7, 7, 7, 21, 21, 21, 21, 12, 12, 12, 12, 21, 10, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 21, 7, 21, 21, 21,
- 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 12,
- 12, 12, 10, 10, 12, 10, 12, 12, 21, 21, 21, 21, 21, 21, 12, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
- 12, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7,
- 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 12, 12, 7, 10, 10,
- 12, 10, 10, 10, 10, 2, 2, 10, 10, 2, 2, 10, 10, 10, 2, 2,
- 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 7, 7, 7,
- 7, 7, 10, 10, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2,
- 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12,
- 10, 10, 12, 12, 12, 10, 12, 7, 7, 7, 7, 21, 21, 21, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 2, 21, 12, 7,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10, 10, 12,
- 12, 10, 12, 12, 7, 7, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10,
- 10, 10, 12, 12, 12, 12, 2, 2, 10, 10, 10, 10, 12, 12, 10, 12,
- 12, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 7, 7, 7, 7, 12, 12, 2, 2,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 12, 10, 12,
- 12, 21, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 10, 10,
- 12, 12, 12, 12, 12, 12, 10, 12, 7, 21, 2, 2, 2, 2, 2, 2,
- 10, 10, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 21, 21, 21, 26,
- 12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 2, 2, 2, 2,
- 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, 2, 2, 7, 7, 7, 7,
- 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 2, 12, 12, 10, 12, 7,
- 10, 7, 10, 12, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7,
- 7, 10, 10, 10, 12, 12, 12, 12, 2, 2, 12, 12, 10, 10, 10, 10,
- 12, 7, 21, 7, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7,
- 7, 7, 7, 12, 12, 12, 12, 12, 12, 10, 7, 12, 12, 12, 12, 21,
- 21, 21, 21, 21, 21, 21, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 12, 12, 12, 12, 12, 12, 10, 10, 12, 12, 12, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 21, 21, 7, 21, 21,
- 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 10, 12,
- 7, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 2, 10, 12, 12, 12, 12, 12, 12,
- 12, 10, 12, 12, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7,
- 7, 12, 12, 12, 12, 12, 12, 2, 2, 2, 12, 2, 12, 12, 2, 12,
- 12, 12, 12, 12, 12, 12, 7, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10, 2,
- 12, 12, 2, 10, 10, 12, 10, 12, 7, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 12, 12, 10, 10, 21, 21, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 23, 23, 23,
- 23, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2,
- 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 26, 26, 26, 26,
- 6, 6, 6, 6, 21, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 15, 15, 15, 15, 15,
- 15, 15, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 7, 7, 7,
- 15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 12,
- 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 12,
- 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 21, 6, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 2, 6, 6, 2,
- 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 26, 12, 12, 21,
- 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 10, 10, 12, 12, 12, 26, 26, 26, 10, 10, 10,
- 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12,
- 12, 12, 12, 26, 26, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 26, 26,
- 26, 26, 12, 12, 12, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5,
- 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 2, 9, 9,
- 2, 2, 9, 2, 2, 9, 9, 2, 2, 9, 9, 9, 9, 2, 9, 9,
- 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 2, 5, 2, 5, 5, 5,
- 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2, 2, 9, 9, 9,
- 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 2, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2,
- 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 9, 9, 9, 9, 9, 9,
- 9, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5,
- 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25,
- 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 5, 2, 2, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26,
- 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 12, 26, 26, 21, 21, 21, 21, 21, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
- 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12,
- 12, 12, 2, 12, 12, 2, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 7, 26,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 23,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 7, 2,
- 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 5, 5, 5, 5, 12, 12, 12, 12, 12, 12, 12, 6, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15, 15, 15,
- 23, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2,
- 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2, 7, 2, 2, 2, 2,
- 2, 2, 7, 2, 2, 2, 2, 7, 2, 7, 2, 7, 2, 7, 7, 7,
- 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 2, 7, 2, 7, 2, 7,
- 2, 7, 7, 2, 7, 2, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7,
- 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7,
- 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7,
- 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2,
- 2, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 24, 24, 24, 24, 24,
- 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 2, 2, 2, 26, 26, 26, 26, 26, 2, 2, 2,
- 26, 26, 26, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 12, 12, 13, 14, 12, 15, 16, 17, 18, 19, 20,
- 21, 22, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 24, 25,
- 0, 26, 27, 0, 28, 29, 30, 31, 32, 33, 0, 34, 0, 0, 0, 0,
- 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 38, 0, 0, 0, 0,
- 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0,
- 43, 44, 45, 46, 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 50, 0, 0, 0,
- 0, 0, 0, 51, 0, 52, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 54, 55, 0, 0, 0, 0, 56, 0, 0, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 0, 67, 68, 0, 69, 70, 71, 72, 0,
- 61, 0, 73, 74, 75, 76, 0, 0, 70, 0, 77, 78, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 79, 80, 0, 0, 0, 0, 0, 0, 0, 0, 81,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 83, 84, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 86, 0, 80, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 1, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 21, 0, 0, 0, 0, 0, 22, 23, 24,
- 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27,
- 28, 29, 0, 0, 0, 0, 30, 0, 0, 0, 31, 32, 33, 34, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 13, 35, 36, 0, 0, 26, 37, 38, 39, 0, 0, 0, 0, 0, 40,
- 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 42, 43, 1,
- 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 50, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0,
- 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 52, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 49, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 56, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 58, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, 0, 0, 0, 0,
- 0, 0, 62, 63, 64, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 67, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,
- 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 70, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 71,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 74, 75, 0, 0, 0, 0, 0, 0, 0, 0,
- 76, 0, 68, 77, 0, 0, 0, 0, 0, 0, 78, 79, 80, 81, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 70, 0, 0, 0,
- 0, 82, 83, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0,
- 85, 0, 84, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 87,
- 88, 89, 90, 91, 0, 0, 0, 0, 0, 0, 0, 0, 92, 93, 94, 1,
- 1, 1, 95, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 98,
- 99,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 74, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0, 0, 0, 0, 0,103, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 74,105,106, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 91, 0,107, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0,
- 1, 1, 91, 0, 0, 0, 0, 0, 0,108, 0, 0, 0, 0,109, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 0, 76, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111,112,113, 0, 0, 0,
- 0, 0,107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 49, 0, 0, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,115,116, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 26,117, 0,118, 0, 0, 0, 0, 0,119, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 120, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,121, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122,123, 75, 0,
- 0, 0, 0, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0, 0, 0,
- 0, 0, 76,102, 0, 0, 0, 0, 0, 0, 0,125, 0, 0, 0, 0,
- 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0,
- 0, 0,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,126, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0,129, 0, 49, 0, 0,
- 26,130,130, 0, 0, 0, 0, 0, 0, 0, 0, 0,131, 0, 0, 51,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,132, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,133, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,134, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,109, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,110, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0,102, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,136, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,137, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,138, 0, 0, 0, 0, 0, 0, 0,139, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,140, 0, 0, 0, 0,141, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 142,143,144,145,146,147, 0, 0, 0,148, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,149, 0, 0, 0,
- 0, 0, 0, 0,139, 1, 1,150,151,117, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0,
- 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,153, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,
- 230,230,230,230,230,230,230,230,230,232,220,220,220,220,232,216,
- 220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
- 220,220,220,220,220,220,220,220, 1, 1, 1, 1, 1,220,220,220,
- 220,230,230,230,230,230,230,230,230,240,230,220,220,220,230,230,
- 230,220,220, 0,230,230,230,220,220,220,220,230,232,220,220,230,
- 233,234,234,233,234,234,233,230,230,230,230,230, 0, 0, 0,230,
- 230,230,230,230, 0,220,230,230,230,230,220,230,230,230,222,220,
- 230,230,230,230,230,230,220,220,220,220,220,220,230,230,220,230,
- 230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
- 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0,
- 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,
- 230,220,220,230,230,230,230,230,220,230,230,220, 35, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,230,230,
- 230, 0, 0,230,230,230,230,220,230, 0, 0,230,230, 0,220,230,
- 230,220, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0,230,220,230,230,
- 220,230,230,220,220,220,230,220,220,230,220,230,230,230,220,230,
- 220,230,220,230,220,230,230, 0, 0, 0, 0, 0,230,230,220,230,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0, 0,230,230, 0,230,
- 230,230,230,230,230,230,230,230, 0,230,230,230, 0,230,230,230,
- 230,230, 0, 0, 0,220,220,220, 0, 0, 0, 0,230,220,220,220,
- 230,230,230,230, 0, 0,230,230,230,230,230,220,220,220,220,220,
- 230,230,230,230,230,230, 0,220,230,230,220,230,230,220,230,230,
- 230,220,220,220, 27, 28, 29,230,230,230,220,230,230,220,220,230,
- 230,230,230,230, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,
- 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,230, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 9,
- 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,103,103, 9, 0,
- 0, 0, 0, 0,107,107,107,107, 0, 0, 0, 0,118,118, 9, 0,
- 0, 0, 0, 0,122,122,122,122, 0, 0, 0, 0,220,220, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,220, 0,216, 0, 0,
- 0, 0, 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130,
- 130,130, 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0, 0, 0,
- 0, 0,220, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230, 0, 0, 0, 0,
- 9, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
- 0,230, 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0,222,230,220,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,220, 0, 0, 0,
- 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,
- 230, 0, 0,220,230,230,230,230,230,220,220,220,220,220,220,230,
- 230,220, 0,220,220,230,230,220,220,230,230,230,230,230,220,230,
- 230,230,230, 0, 0, 0, 0,230,220,230,230,230,230,230,230,230,
- 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 7, 0,230,230,230, 0, 1,220,220,220,220,220,230,230,
- 220,220,220,220,230, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- 0,220, 0, 0, 0, 0, 0, 0,230, 0, 0, 0,230,230, 0, 0,
- 0, 0, 0, 0,230,230,220,230,230,230,230,230,230,230,220,230,
- 230,234,214,220,202,230,230,230,230,230,230,230,230,230,230,230,
- 230,230,232,228,228,220,218,230,233,220,230,220,230,230, 1, 1,
- 230,230,230,230, 1, 1, 1,230,230, 0, 0, 0, 0,230, 0, 0,
- 0, 1, 1,230,220,230, 1, 1,220,220,220,220,230, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,218,228,
- 232,222,224,224, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 230,230,230,230,230,230,230,230,230,230, 0, 0, 0, 0, 0, 0,
- 0, 0, 9, 0, 0, 0, 0,220,220,220, 0, 0, 0, 0, 0, 9,
- 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,230, 0,230,230,
- 220, 0, 0,230,230, 0, 0, 0, 0, 0,230,230, 0,230, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0,230,230,230,230,
- 230,230,230,220,220,220,220,220,220,220,230,230,230,230,230, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,230,230, 1,220, 0,
- 0, 0, 0, 9, 0, 0, 0, 0, 0,230,220, 0, 0, 0, 0,230,
- 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,220,220,230,230,230,220,
- 230,220,220,220, 0, 0,230,220,230,220, 0, 0, 0, 9, 7, 0,
- 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7,
- 7, 0, 0, 0,230,230,230,230,230, 0, 0, 0, 0, 0, 9, 0,
- 0, 0, 7, 0, 0, 0, 9, 7, 0, 0, 0, 0, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0,
- 0, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
- 9, 9, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,230,230,230,230,
- 230,230,230, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0, 0, 0, 0,216,216, 1, 1, 1, 0, 0,
- 0,226,216,216,216,216,216, 0, 0, 0, 0, 0, 0, 0, 0,220,
- 220,220,220,220,220,220,220, 0, 0,230,230,230,230,230,220,220,
- 0, 0, 0, 0, 0, 0,230,230,230,230, 0, 0, 0, 0,230,230,
- 230, 0, 0, 0,230, 0, 0,230,230,230,230,230,230,230, 0,230,
- 230, 0,230,230,220,220,220,220,220,220,220, 0,230,230, 7, 0,
- 0, 0, 0, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
- 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17,237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0,
- 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 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, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 7, 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, 8, 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, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 10, 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, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0,
- 0, 0, 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7,
- 20, 20, 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0,
- 20, 20, 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1,
- 28, 29, 30, 31, 0, 0, 20, 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, 20, 20,
- 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20,
- 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0,
- 0, 40, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 21,
- 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
- 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45,
- 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 34, 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, 20, 20, 1, 20, 20, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 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, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0,
- 0, 0, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 17, 19, 20, 21, 22, 23, 24, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 27, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
- 51, 52, 53, 54, 55, 56, 57, 34, 34, 34, 34, 58, 59, 59, 60, 34,
- 34, 34, 34, 34, 34, 34, 61, 62, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 63, 64, 34, 65, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 67, 66, 68, 69, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 70, 71, 72, 34, 34,
- 34, 34, 73, 34, 34, 34, 34, 34, 34, 34, 34, 74, 75, 76, 77, 78,
- 79, 80, 34, 81, 82, 83, 34, 84, 85, 34, 86, 87, 88, 89, 17, 90,
- 91, 92, 34, 34, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 93, 25, 25, 25, 25, 25, 25, 25, 94,
- 95, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 96, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 97, 34, 34, 34, 34, 34, 34,
- 25, 98, 34, 34, 25, 25, 25, 25, 25, 25, 25, 25, 25, 99, 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, 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, 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, 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, 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,
- 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, 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, 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, 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, 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, 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, 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, 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,
- 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, 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, 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, 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, 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, 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, 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, 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,
- 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, 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, 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, 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, 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, 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, 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, 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,
- 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, 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, 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, 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, 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, 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, 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, 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,
- 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, 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, 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, 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, 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, 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, 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, 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,
- 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, 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, 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, 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, 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, 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, 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, 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,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
- 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0,
- 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2,
- 9, 9, 9, 9, 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9,
- 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 2, 2, 4, 4, 4, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2,
- 2, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,
- 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 0, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 0, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 2, 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, 2, 2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 2, 2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 2, 2, 95, 2, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5,
- 5, 5, 5, 2, 2, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
- 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5,
- 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2,
- 2, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2,
- 2, 2, 5, 5, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 2, 2, 11, 11, 11, 2, 11, 11, 11, 11, 11,
- 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2,
- 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11,
- 2, 2, 11, 2, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2,
- 2, 11, 11, 11, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11,
- 11, 11, 11, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2,
- 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10,
- 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10,
- 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 10,
- 10, 10, 10, 10, 10, 10, 2, 21, 21, 21, 2, 21, 21, 21, 21, 21,
- 21, 21, 21, 2, 2, 21, 21, 2, 2, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2,
- 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21,
- 2, 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2,
- 2, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 2, 2,
- 2, 2, 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22,
- 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22,
- 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22,
- 22, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 2, 2, 2, 2, 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2,
- 22, 22, 22, 22, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2,
- 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 2, 23, 23,
- 23, 2, 2, 23, 2, 2, 23, 23, 23, 23, 2, 2, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 2, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16,
- 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2,
- 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 2, 2,
- 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 2, 16, 16, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2,
- 20, 20, 20, 20, 20, 20, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 2, 36, 36, 36, 2, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 2, 36, 2, 2, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,
- 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 36, 36,
- 36, 36, 36, 36, 36, 36, 2, 2, 2, 2, 2, 2, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18,
- 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18,
- 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 2, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25,
- 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2,
- 2, 2, 2, 8, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 0, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2,
- 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 2,
- 30, 30, 30, 30, 2, 2, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30,
- 30, 30, 30, 30, 30, 2, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 2, 2, 29, 29,
- 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 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,
- 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 0, 0, 0, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 2,
- 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 2, 46, 46, 46, 2, 46, 46, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 2, 2, 2, 2, 2, 2, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2,
- 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 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, 48,
- 48, 48, 48, 48, 48, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 2, 2, 52, 52, 52, 52, 52, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 2, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 2, 2, 2, 2, 2, 2,
- 2, 2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 2, 2,
- 2, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2,
- 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 2, 2, 8, 8, 8, 76, 76, 76, 76, 76, 76, 76, 76, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
- 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9,
- 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 9, 9, 9, 9,
- 9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 6, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9,
- 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9,
- 2, 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9,
- 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
- 19, 19, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
- 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 2, 2, 2, 2, 2, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 2, 2, 2, 2, 2, 55,
- 55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 2, 2,
- 2, 2, 2, 2, 2, 61, 61, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 61, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
- 30, 30, 30, 30, 30, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 1, 1, 1, 1, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13,
- 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1,
- 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 0, 0, 17, 17, 17, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0,
- 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 2, 2, 2, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
- 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0,
- 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 2, 2, 2, 2, 2, 19, 19, 2, 19, 2, 19, 19, 19, 19, 19,
- 2, 2, 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 2, 2, 2, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 2, 2,
- 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2,
- 2, 2, 2, 2, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
- 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 74, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 2, 0, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 2, 2, 2, 2, 84, 84, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 2, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 92, 92, 92, 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 2, 2, 30,
- 30, 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 19, 19, 19, 19,
- 0, 0, 2, 2, 2, 2, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 2, 2, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2,
- 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2,
- 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 14, 14,
- 14, 14, 14, 2, 14, 2, 14, 14, 2, 14, 14, 2, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2,
- 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
- 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2,
- 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2,
- 12, 12, 12, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
- 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
- 0, 0, 0, 0, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 2, 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, 49, 2, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 2, 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118,
- 118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,
- 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 2, 2, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135,
- 135,135,135,135,135,135,135,135,135,135, 2, 2, 2, 2,135,135,
- 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
- 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,106,106,
- 106,106,106,106,106,106,106,106,106,106,106,106,106,106, 2, 2,
- 2, 2, 2, 2, 2, 2,104,104,104,104,104,104,104,104,104,104,
- 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161,
- 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161,
- 161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161,161,
- 161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161,161,
- 2,161,161, 2, 2, 2,110,110,110,110,110,110,110,110,110,110,
- 110,110,110,110,110,110,110,110,110,110,110,110,110, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,110,110,110,110,110,110, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,110,110,110,110,110,110,110,110, 2, 2,
- 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 2, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 2, 2, 2, 2, 2, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2,
- 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, 2, 47, 47, 2,
- 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81, 81, 81,
- 81, 81, 81, 81, 81, 81,120,120,120,120,120,120,120,120,120,120,
- 120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116,
- 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
- 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,116,116,
- 116,116,116,116,116,116,128,128,128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2,
- 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
- 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
- 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
- 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 2, 2,
- 2, 2, 97, 97, 97, 97, 2, 2, 97, 97, 97, 97, 97, 97, 97, 97,
- 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2,
- 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2, 2, 57, 57,
- 57, 2, 2, 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2,
- 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88,117,117,117,117,117,117,117,117,117,117,
- 117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112,
- 112,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2,
- 2,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
- 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78,
- 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 2, 2, 83, 83,
- 83, 83, 83, 83, 83, 83, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 2, 2, 2, 2, 2, 82, 82,
- 82, 82, 82, 82, 82, 82,122,122,122,122,122,122,122,122,122,122,
- 122,122,122,122,122,122,122,122, 2, 2, 2, 2, 2, 2, 2,122,
- 122,122,122, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,122,
- 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
- 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2,
- 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130,
- 130,130,130,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,130,130,130, 2, 2, 2, 2, 2, 2, 2,
- 130,130,130,130,130,130,144,144,144,144,144,144,144,144,144,144,
- 144,144,144,144,144,144,144,144,144,144,144,144,144,144, 2, 2,
- 2, 2, 2, 2, 2, 2,144,144,144,144,144,144,144,144,144,144,
- 2, 2, 2, 2, 2, 2,156,156,156,156,156,156,156,156,156,156,
- 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
- 2,156,156,156, 2, 2,156,156, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,147,147,147,147,147,147,147,147,147,147,
- 147,147,147,147,147,147,147,147,147,147,147,147,147,147, 2, 2,
- 2, 2, 2, 2, 2, 2,148,148,148,148,148,148,148,148,148,148,
- 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
- 2, 2, 2, 2, 2, 2,158,158,158,158,158,158,158,158,158,158,
- 158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,
- 2, 2, 2, 2, 2, 2,153,153,153,153,153,153,153,153,153,153,
- 153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
- 153,153, 2, 2, 2, 2,149,149,149,149,149,149,149,149,149,149,
- 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101,101,
- 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, 2,
- 2, 2, 2, 2, 2, 2,101,101,101,101,101,101,101,101,101,101,
- 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 2,
- 2, 2, 2, 2, 2, 2,111,111,111,111,111,111,111,111,111,111,
- 111,111,111,111,111,111,111,111,111,111,111,111,111, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,100,100,100,100,100,100,100,100,100,100,
- 100,100,100,100,100,100, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,108,108,108,108,108,108,108,108,108,108,
- 108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108,
- 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
- 108,108,108,108,108, 2,129,129,129,129,129,129,129, 2,129, 2,
- 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129,
- 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129,
- 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109,
- 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
- 109, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109,
- 2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107,
- 107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107,
- 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2,
- 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107,
- 2, 1,107,107,107,107,107,107,107,107,107, 2, 2,107,107, 2,
- 2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2,
- 2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107,
- 107,107,107, 2, 2, 2,107,107,107,107,107, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,137,137,137,137,137,137,137,137,137,137,
- 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
- 137,137, 2,137,137,137,137,137, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124,
- 124,124,124,124,124,124,124,124,124,124,124,124,124,124, 2, 2,
- 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124,
- 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123,
- 123,123,123,123,123,123,123,123,123,123,123,123, 2, 2,123,123,
- 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,
- 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114,
- 114,114,114,114,114,114,114,114,114,114,114, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,114,114,114,114,114,114,114,114,114,114,
- 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102,102,
- 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
- 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126,
- 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
- 126, 2, 2,126,126,126,126,126,126,126,126,126,126,126,126,126,
- 126,126, 2, 2, 2, 2,126,126,126,126,126,126,126, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,142,142,142,142,142,142,142,142,142,142,
- 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
- 142,142, 2, 2, 2, 2,125,125,125,125,125,125,125,125,125,125,
- 125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2,125,154,154,154,154,154,154,154, 2, 2,154,
- 2, 2,154,154,154,154,154,154,154,154, 2,154,154, 2,154,154,
- 154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
- 154,154,154,154,154,154,154,154,154,154,154,154, 2,154,154, 2,
- 2,154,154,154,154,154,154,154,154,154,154,154,154, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,154,154,154,154,154,154,154,154,154,154,
- 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,150,150, 2, 2,
- 150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
- 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,141,141,141,141,141,141,141,141,141,141,
- 141,141,141,141,141,141,141,141,141,141,141,141,141,141, 2, 2,
- 2, 2, 2, 2, 2, 2,140,140,140,140,140,140,140,140,140,140,
- 140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121,121,
- 121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, 2,
- 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2,
- 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
- 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133,
- 133,133,133,133,133,133,133,133,133,133,133,133, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133,133,
- 133,133,133, 2, 2, 2,134,134,134,134,134,134,134,134,134,134,
- 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134,134,134,
- 134,134,134,134,134,134,134,134,134,134,134,134,134,134, 2,134,
- 134,134,134,134,134,134,134,134,134,134,134,134,134, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,138,138,138,138,138,138,138, 2,138,138,
- 2,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,
- 138,138,138,138,138,138,138,138,138,138,138,138,138, 2, 2, 2,
- 138, 2,138,138, 2,138,138,138,138,138,138,138,138,138, 2, 2,
- 2, 2, 2, 2, 2, 2,138,138,138,138,138,138,138,138,138,138,
- 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2,
- 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
- 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
- 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2,
- 2, 2, 2, 2, 2, 2,143,143,143,143,143,143,143,143,143,143,
- 2, 2, 2, 2, 2, 2,145,145,145,145,145,145,145,145,145,145,
- 145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, 2,
- 2, 2, 2, 2, 2, 2, 86, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 2, 63, 63, 63, 63, 63, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,157,157,157,157,157,157,157,157,157,157,
- 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2,
- 2, 2, 2, 2, 2, 2,127,127,127,127,127,127,127,127,127,127,
- 127,127,127,127,127,127,127,127,127,127,127,127,127, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 79, 2,
- 2, 2, 2, 2, 2, 2,115,115,115,115,115,115,115,115,115,115,
- 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 115,115,115,115,115, 2,115,115,115,115,115,115,115,115,115,115,
- 2, 2, 2, 2,115,115,159,159,159,159,159,159,159,159,159,159,
- 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,
- 159,159,159,159,159, 2,159,159,159,159,159,159,159,159,159,159,
- 2, 2, 2, 2, 2, 2,103,103,103,103,103,103,103,103,103,103,
- 103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,
- 103,103,103,103, 2, 2,103,103,103,103,103,103, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,119,119,119,119,119,119,119,119,119,119,
- 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,119,119,119,119,119,119,119,119,119,119,
- 2,119,119,119,119,119,119,119, 2,119,119,119,119,119,119,119,
- 119,119,119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,
- 2, 2, 2,119,119,119,146,146,146,146,146,146,146,146,146,146,
- 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,
- 146, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2,
- 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136,136,
- 136,136,136,136,136,136,136,136,136,136,136,136,136,136, 2, 2,
- 2, 2, 2, 2, 2, 2,155,155,155,155,155,155,155,155,155,155,
- 155,155,155,155,155,155,155,155,155,155,155,155, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136, 2,
- 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 17, 17, 17, 17, 17,
- 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 2,
- 2, 2, 2, 2, 2, 2,139,139,139,139,139,139,139,139,139,139,
- 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,
- 139,139, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105,
- 105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
- 105, 2, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105,
- 105,105,105, 2, 2, 2,105,105,105,105,105,105,105,105,105, 2,
- 2, 2, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105,
- 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0, 0, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 2, 0, 0, 2, 2, 0, 2, 2, 0, 0, 2, 2, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
- 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2,
- 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 2, 2, 0, 0,131,131,131,131,131,131,131,131,131,131,
- 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
- 131,131, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2,131,131,131,131,131, 2,131,131,131,131,131,131,131,131,131,
- 131,131,131,131,131,131, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 2,
- 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56,
- 56, 2, 2, 2, 2, 2,151,151,151,151,151,151,151,151,151,151,
- 151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,
- 151,151,151, 2, 2, 2,151,151,151,151,151,151,151,151,151,151,
- 151,151,151,151, 2, 2,151,151,151,151,151,151,151,151,151,151,
- 2, 2, 2, 2,151,151,160,160,160,160,160,160,160,160,160,160,
- 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
- 160,160,160,160,160, 2,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 2, 2, 2, 2, 2,152, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
- 30, 30, 2, 30, 30, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 2,113,113,113,113,113,113,113,113,113,113,
- 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113,
- 113,113,113,113,113,113,113,113,113,113,113,113,113, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,132,132,132,132,132,132,132,132,132,132,
- 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
- 132,132, 2, 2, 2, 2,132,132,132,132,132,132,132,132,132,132,
- 2, 2, 2, 2,132,132, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
- 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3,
- 2, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3,
- 2, 3, 2, 3, 2, 3, 2, 3, 3, 2, 3, 2, 2, 3, 3, 3,
- 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
- 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3,
- 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
- 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0,
- 0, 0, 0, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2,
- 2, 2, 2, 2, 2, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 2, 3, 4, 5, 6, 0,
- 0, 0, 0, 7, 8, 9, 10, 11, 0, 12, 0, 0, 0, 0, 13, 0,
- 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 0, 17, 18, 19,
- 0, 0, 0, 20, 21, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 0,
- 0, 0, 0, 27, 28, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33,
- 34, 35, 36, 37, 38, 39, 40, 0, 0, 0, 41, 0, 42, 43, 44, 45,
- 46, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 64, 0, 0, 0, 0, 0,
- 0, 0, 0, 65, 0, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 71, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 72, 73, 74, 75, 76, 77, 78, 79, 80, 0,
-};
-static const uint16_t
-_hb_ucd_u16[11584] =
-{
- 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12,
- 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23,
- 13, 13, 13, 24, 25, 11, 11, 11, 11, 26, 11, 27, 28, 29, 30, 31,
- 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 11, 37, 38, 13, 39,
- 9, 9, 9, 11, 11, 11, 13, 13, 40, 13, 13, 13, 41, 13, 13, 13,
- 13, 13, 13, 42, 9, 43, 11, 11, 44, 45, 32, 46, 47, 48, 49, 50,
- 51, 52, 48, 48, 53, 32, 54, 55, 48, 48, 48, 48, 48, 56, 57, 58,
- 59, 60, 48, 32, 61, 48, 48, 48, 48, 48, 62, 63, 64, 48, 65, 66,
- 48, 67, 68, 69, 48, 70, 71, 48, 72, 73, 48, 48, 74, 32, 75, 32,
- 76, 48, 48, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 90, 83, 84, 91, 92, 93, 94, 95, 96, 97, 84, 98, 99, 100, 88, 101,
- 102, 83, 84, 103, 104, 105, 88, 106, 107, 108, 109, 110, 111, 112, 94, 113,
- 114, 115, 84, 116, 117, 118, 88, 119, 120, 115, 84, 121, 122, 123, 88, 124,
- 125, 115, 48, 126, 127, 128, 88, 129, 130, 131, 48, 132, 133, 134, 94, 135,
- 136, 48, 48, 137, 138, 139, 140, 140, 141, 48, 142, 143, 144, 145, 140, 140,
- 146, 147, 148, 149, 150, 48, 151, 152, 153, 154, 32, 155, 156, 157, 140, 140,
- 48, 48, 158, 159, 160, 161, 162, 163, 164, 165, 9, 9, 166, 11, 11, 167,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 168, 169, 48, 48, 168, 48, 48, 170, 171, 172, 48, 48,
- 48, 171, 48, 48, 48, 173, 174, 175, 48, 176, 9, 9, 9, 9, 9, 177,
- 178, 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, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 179, 48, 180, 181, 48, 48, 48, 48, 182, 183,
- 48, 184, 48, 185, 48, 186, 187, 188, 48, 48, 48, 189, 190, 191, 192, 193,
- 194, 192, 48, 48, 195, 48, 48, 196, 197, 48, 198, 48, 48, 48, 48, 199,
- 48, 200, 201, 202, 203, 48, 204, 205, 48, 48, 206, 48, 207, 208, 209, 209,
- 48, 210, 48, 48, 48, 211, 212, 213, 192, 192, 214, 215, 216, 140, 140, 140,
- 217, 48, 48, 218, 219, 160, 220, 221, 222, 48, 223, 64, 48, 48, 224, 225,
- 48, 48, 226, 227, 228, 64, 48, 229, 230, 9, 9, 231, 232, 233, 234, 235,
- 11, 11, 236, 27, 27, 27, 237, 238, 11, 239, 27, 27, 32, 32, 32, 32,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 240, 13, 13, 13, 13, 13, 13,
- 241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
- 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
- 266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
- 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
- 280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209,
- 209, 209, 287, 140, 288, 140, 271, 271, 271, 289, 209, 209, 209, 209, 290, 271,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 291, 292, 209, 209, 293,
- 209, 209, 209, 209, 209, 209, 294, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 279, 279, 279, 279, 279, 279, 279, 279, 300, 301, 279, 279, 279, 302, 279, 303,
- 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
- 209, 209, 209, 279, 304, 209, 209, 305, 209, 306, 209, 209, 209, 209, 209, 209,
- 9, 9, 9, 11, 11, 11, 307, 308, 13, 13, 13, 13, 13, 13, 309, 310,
- 11, 11, 311, 48, 48, 48, 312, 313, 48, 314, 315, 315, 315, 315, 32, 32,
- 316, 317, 318, 319, 320, 321, 140, 140, 209, 322, 209, 209, 209, 209, 209, 323,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 324, 140, 325,
- 326, 327, 328, 329, 136, 48, 48, 48, 48, 330, 178, 48, 48, 48, 48, 331,
- 332, 48, 48, 136, 48, 48, 48, 48, 200, 333, 48, 48, 209, 209, 323, 48,
- 209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 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, 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, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 209, 209, 209, 209,
- 48, 338, 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, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 151, 209, 209, 209, 287, 48, 48, 229,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 339, 48, 340, 140, 13, 13, 341, 342, 13, 343, 48, 48, 48, 48, 344, 345,
- 31, 346, 347, 348, 13, 13, 13, 349, 350, 351, 352, 353, 354, 355, 140, 356,
- 357, 48, 358, 359, 48, 48, 48, 360, 361, 48, 48, 362, 363, 192, 32, 364,
- 64, 48, 365, 48, 366, 367, 48, 151, 76, 48, 48, 368, 369, 370, 371, 372,
- 48, 48, 373, 374, 375, 376, 48, 377, 48, 48, 48, 378, 379, 380, 381, 382,
- 383, 384, 315, 11, 11, 385, 386, 11, 11, 11, 11, 11, 48, 48, 387, 192,
- 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, 48, 388, 48, 389, 48, 48, 206,
- 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
- 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 207, 140, 140,
- 392, 393, 394, 395, 396, 48, 48, 48, 48, 48, 48, 397, 398, 399, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 400, 209, 48, 48, 48, 48, 401, 48, 48, 402, 140, 140, 403,
- 32, 404, 32, 405, 406, 407, 408, 409, 48, 48, 48, 48, 48, 48, 48, 410,
- 411, 2, 3, 4, 5, 412, 413, 414, 48, 415, 48, 200, 416, 417, 418, 419,
- 420, 48, 172, 421, 204, 204, 140, 140, 48, 48, 48, 48, 48, 48, 48, 71,
- 422, 271, 271, 423, 272, 272, 272, 424, 425, 426, 427, 140, 140, 209, 209, 428,
- 140, 140, 140, 140, 140, 140, 140, 140, 48, 151, 48, 48, 48, 100, 429, 430,
- 48, 48, 431, 48, 432, 48, 48, 433, 48, 434, 48, 48, 435, 436, 140, 140,
- 9, 9, 437, 11, 11, 48, 48, 48, 48, 204, 192, 9, 9, 438, 11, 439,
- 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 314, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140,
- 448, 48, 48, 449, 48, 450, 48, 451, 48, 200, 452, 140, 140, 140, 48, 453,
- 48, 454, 48, 455, 140, 140, 140, 140, 48, 48, 48, 456, 271, 457, 271, 271,
- 458, 459, 48, 460, 461, 462, 48, 463, 48, 464, 140, 140, 465, 48, 466, 467,
- 48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474,
- 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 271, 476, 48, 48, 477, 478, 140, 140, 140, 140,
- 48, 464, 479, 48, 62, 480, 140, 48, 481, 140, 140, 48, 482, 140, 48, 314,
- 483, 48, 48, 484, 485, 457, 486, 487, 222, 48, 48, 488, 489, 48, 196, 192,
- 490, 48, 491, 492, 493, 48, 48, 494, 222, 48, 48, 495, 496, 497, 498, 499,
- 48, 97, 500, 501, 140, 140, 140, 140, 502, 503, 504, 48, 48, 505, 506, 192,
- 507, 83, 84, 508, 509, 510, 511, 512, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 513, 514, 515, 478, 140, 48, 48, 48, 516, 517, 192, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 518, 519, 520, 521, 140, 140,
- 48, 48, 48, 522, 523, 192, 524, 140, 48, 48, 525, 526, 192, 140, 140, 140,
- 48, 173, 527, 528, 314, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 500, 529, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 530,
- 531, 532, 48, 533, 534, 192, 140, 140, 140, 140, 535, 48, 48, 536, 537, 140,
- 538, 48, 48, 539, 540, 541, 48, 48, 542, 543, 544, 48, 48, 48, 48, 196,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 84, 48, 518, 545, 546, 148, 175, 547, 48, 548, 549, 550, 140, 140, 140, 140,
- 551, 48, 48, 552, 553, 192, 554, 48, 555, 556, 192, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 557,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 100, 271, 558, 559, 560,
- 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, 207, 140, 140, 140, 140, 140, 140,
- 272, 272, 272, 272, 272, 272, 561, 562, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 563,
- 48, 48, 200, 564, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 314, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 565,
- 48, 48, 48, 566, 567, 568, 569, 570, 48, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 9, 9, 11, 11, 271, 571, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 572, 573, 574, 574, 575, 576, 140, 140, 140, 140, 577, 578,
- 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, 48, 48, 48, 48, 48, 48, 440,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 199, 140, 140,
- 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 579,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 580, 140, 140, 580, 581, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 206,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 48, 48, 71, 151, 196, 582, 583, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 32, 32, 584, 32, 585, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 324,
- 209, 209, 586, 209, 209, 209, 587, 588, 589, 209, 590, 209, 209, 209, 288, 140,
- 209, 209, 209, 209, 591, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 592,
- 209, 209, 209, 209, 209, 287, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140,
- 9, 593, 11, 594, 595, 596, 241, 9, 597, 598, 599, 600, 601, 9, 593, 11,
- 602, 603, 11, 604, 605, 606, 607, 9, 608, 11, 9, 593, 11, 594, 595, 11,
- 241, 9, 597, 607, 9, 608, 11, 9, 593, 11, 609, 9, 610, 611, 612, 613,
- 11, 614, 9, 615, 616, 617, 618, 11, 619, 9, 620, 11, 621, 622, 622, 622,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 32, 32, 32, 623, 32, 32, 624, 625, 626, 627, 45, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 628, 629, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 630, 631, 632, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 151, 633, 634, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 635, 140, 48, 48, 636, 637,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 638, 200,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 639, 585, 140, 140,
- 9, 9, 597, 11, 640, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 498, 271, 271, 641, 642, 140, 140, 140, 140,
- 498, 271, 643, 644, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 645, 48, 646, 647, 648, 649, 650, 651, 652, 206, 653, 206, 140, 140, 140, 654,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 655, 655, 655, 209, 324,
- 656, 209, 209, 209, 209, 209, 209, 209, 209, 209, 657, 140, 140, 140, 658, 209,
- 659, 209, 209, 325, 660, 661, 324, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 662,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 663, 426, 426,
- 209, 209, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 660, 325, 427,
- 325, 209, 209, 209, 664, 176, 209, 209, 664, 209, 657, 661, 140, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 323, 657, 665, 287, 209, 426, 288, 324, 176, 664, 287,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 666, 209, 209, 288, 140, 140, 192,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 140, 140,
- 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, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 196, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 204, 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, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 478, 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, 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, 48, 100, 140,
- 48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 71, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 667, 140, 668, 668, 668, 668, 668, 668, 140, 140, 140, 140, 140, 140, 140, 140,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 669,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 670,
- 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, 4, 5, 4, 5,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0,
- 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 11, 11, 11, 13, 11,
- 14, 14, 14, 14, 14, 14, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 16, 17, 18, 17, 17, 19, 20, 21, 21, 22, 21, 23, 24,
- 25, 26, 27, 27, 28, 29, 27, 30, 27, 27, 27, 27, 27, 31, 27, 27,
- 32, 33, 33, 33, 34, 27, 27, 27, 35, 35, 35, 36, 37, 37, 37, 38,
- 39, 39, 40, 41, 42, 43, 44, 27, 45, 46, 27, 27, 27, 27, 47, 27,
- 48, 48, 48, 48, 48, 49, 50, 48, 51, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 63, 64, 65, 66, 67, 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, 100, 101, 102, 103, 104, 105, 106,
- 107, 108, 109, 109, 110, 111, 112, 109, 113, 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 122, 123, 122, 124, 125, 125, 126, 127, 128, 129, 130, 131, 125, 125,
- 132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137, 125, 125,
- 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143,
- 143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153,
- 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170,
- 171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176,
- 177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168,
- 188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194, 8, 195, 125, 125, 125,
- 196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201,
- 202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211,
- 4, 4, 212, 4, 4, 213, 214, 215, 4, 4, 4, 216, 8, 8, 8, 8,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 11, 217, 11, 11, 217, 218, 11, 219, 11, 11, 11, 220, 220, 221, 11, 222,
- 223, 0, 0, 0, 0, 0, 224, 225, 226, 227, 0, 0, 228, 8, 8, 229,
- 0, 0, 230, 231, 232, 0, 4, 4, 233, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 234, 125, 235, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 237, 0, 238, 0, 0, 0, 0, 0, 0,
- 239, 239, 239, 239, 239, 239, 4, 4, 240, 240, 240, 240, 240, 240, 240, 241,
- 139, 139, 140, 242, 242, 242, 243, 244, 143, 245, 246, 246, 246, 246, 14, 14,
- 0, 0, 0, 0, 0, 247, 125, 125, 248, 249, 248, 248, 248, 248, 248, 250,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 125, 252,
- 253, 0, 254, 255, 256, 257, 257, 257, 257, 258, 259, 260, 260, 260, 260, 261,
- 262, 263, 263, 264, 142, 142, 142, 142, 265, 0, 263, 263, 0, 0, 266, 260,
- 142, 265, 0, 0, 0, 0, 142, 267, 0, 0, 0, 0, 0, 260, 260, 268,
- 260, 260, 260, 260, 260, 269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 0, 0, 0, 0,
- 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,
- 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,
- 270, 270, 270, 270, 270, 270, 270, 270, 271, 270, 270, 270, 272, 273, 273, 273,
- 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274,
- 274, 274, 275, 125, 14, 14, 14, 14, 14, 14, 276, 276, 276, 276, 276, 277,
- 0, 0, 278, 4, 4, 4, 4, 4, 279, 4, 4, 4, 280, 281, 125, 282,
- 283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290, 48, 48,
- 291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299,
- 300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308,
- 309, 310, 246, 4, 4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 315, 142, 316, 142, 142, 317,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319, 125, 125,
- 320, 321, 21, 322, 323, 27, 27, 27, 27, 27, 27, 27, 324, 325, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 326, 27, 27, 27, 27, 27, 327, 27, 27, 328, 125, 125, 27,
- 8, 285, 329, 0, 0, 330, 331, 332, 27, 27, 27, 27, 27, 27, 27, 333,
- 334, 0, 1, 2, 1, 2, 335, 259, 260, 336, 142, 265, 337, 338, 339, 340,
- 341, 342, 343, 344, 345, 345, 125, 125, 342, 342, 342, 342, 342, 342, 342, 346,
- 347, 0, 0, 348, 11, 11, 11, 11, 349, 350, 351, 125, 125, 0, 0, 352,
- 125, 125, 125, 125, 125, 125, 125, 125, 353, 354, 355, 355, 355, 356, 357, 252,
- 358, 358, 359, 360, 361, 362, 362, 363, 364, 365, 366, 366, 367, 368, 125, 125,
- 369, 369, 369, 369, 369, 370, 370, 370, 371, 372, 373, 374, 374, 375, 374, 376,
- 377, 377, 378, 379, 379, 379, 380, 381, 381, 382, 383, 384, 125, 125, 125, 125,
- 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385,
- 385, 385, 385, 386, 385, 387, 388, 125, 389, 4, 4, 390, 125, 125, 125, 125,
- 391, 392, 392, 393, 394, 395, 396, 396, 397, 398, 399, 125, 125, 125, 400, 401,
- 402, 403, 404, 405, 125, 125, 125, 125, 406, 406, 407, 408, 407, 409, 407, 407,
- 410, 411, 412, 413, 414, 414, 415, 415, 416, 416, 125, 125, 417, 417, 418, 419,
- 420, 420, 420, 421, 422, 423, 424, 425, 426, 427, 428, 125, 125, 125, 125, 125,
- 429, 429, 429, 429, 430, 125, 125, 125, 431, 431, 431, 432, 431, 431, 431, 433,
- 434, 434, 435, 436, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 27, 45, 437, 437, 438, 439, 125, 125, 125, 125,
- 440, 440, 441, 442, 442, 443, 125, 444, 445, 125, 125, 446, 447, 125, 448, 449,
- 450, 450, 450, 450, 451, 452, 450, 453, 454, 454, 454, 454, 455, 456, 457, 458,
- 459, 459, 459, 460, 461, 462, 462, 463, 464, 464, 464, 464, 464, 464, 465, 466,
- 467, 468, 467, 469, 125, 125, 125, 125, 470, 471, 472, 473, 473, 473, 474, 475,
- 476, 477, 478, 479, 480, 481, 482, 483, 125, 125, 125, 125, 125, 125, 125, 125,
- 484, 484, 484, 484, 484, 485, 486, 125, 487, 487, 487, 487, 488, 489, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 490, 490, 490, 491, 490, 492, 125, 125,
- 493, 493, 493, 493, 494, 495, 496, 125, 497, 497, 497, 498, 498, 125, 125, 125,
- 499, 500, 501, 499, 502, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 503, 503, 503, 504, 125, 125, 125, 125, 125, 125, 505, 505, 505, 505, 505, 506,
- 507, 508, 509, 510, 511, 512, 125, 125, 125, 125, 513, 514, 514, 513, 515, 125,
- 516, 516, 516, 516, 517, 518, 518, 518, 518, 518, 519, 154, 520, 520, 520, 521,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 522, 523, 523, 524, 525, 523, 526, 527, 527, 528, 529, 530, 125, 125, 125, 125,
- 531, 532, 532, 533, 534, 535, 536, 537, 538, 539, 540, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 541, 542,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 543, 544, 544, 544, 545,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 547, 125, 125, 125, 125, 125, 125,
- 546, 546, 546, 546, 546, 546, 548, 549, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 550, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 551, 551, 551, 551, 551, 551, 552,
- 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553,
- 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553,
- 553, 553, 554, 555, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556,
- 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556,
- 556, 556, 556, 556, 557, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 558, 559, 560, 561, 562, 562, 562, 562, 563, 564, 565, 566, 567,
- 568, 568, 568, 568, 569, 570, 571, 572, 568, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 573, 573, 573, 573, 573, 574, 125, 125, 125, 125, 125, 125,
- 575, 575, 575, 575, 576, 575, 575, 575, 577, 575, 125, 125, 125, 125, 578, 579,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 581,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582,
- 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, 125, 125,
- 584, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 585,
- 586, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 587, 125, 125, 588, 589, 590, 590, 590, 590, 590, 590, 590, 590, 590,
- 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 591,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 592, 592, 592, 592, 592, 592, 593, 594, 595, 596, 266, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 8, 8, 597, 8, 598, 0, 0, 0, 0, 0, 0, 0, 266, 125, 125, 125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 599,
- 0, 0, 600, 0, 0, 0, 601, 602, 603, 0, 604, 0, 0, 0, 235, 125,
- 11, 11, 11, 11, 605, 125, 125, 125, 125, 125, 125, 125, 125, 125, 0, 266,
- 0, 0, 0, 0, 0, 234, 0, 606, 125, 125, 125, 125, 125, 125, 125, 125,
- 0, 0, 0, 0, 0, 224, 0, 0, 0, 607, 608, 609, 610, 0, 0, 0,
- 611, 612, 0, 613, 614, 615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 616, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 617, 0, 0, 0,
- 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618,
- 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618,
- 618, 618, 618, 618, 618, 618, 618, 618, 619, 620, 621, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 4, 622, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 623, 624, 625, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 626, 626, 627, 628, 629, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 630, 631, 125, 632, 632, 632, 633,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 634, 635,
- 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 637, 638, 125, 125,
- 639, 639, 639, 639, 640, 641, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 334, 0, 0, 0, 642, 125, 125, 125, 125,
- 334, 0, 0, 247, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 643, 27, 644, 645, 646, 647, 648, 649, 650, 651, 652, 651, 125, 125, 125, 653,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 0, 0, 252, 0, 0, 0, 0, 0, 0, 266, 226, 334, 334, 334, 0, 599,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 125, 125, 125, 654, 0,
- 655, 0, 0, 252, 606, 656, 599, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 657, 350, 350,
- 0, 0, 0, 0, 0, 0, 0, 266, 0, 0, 0, 0, 0, 606, 252, 228,
- 252, 0, 0, 0, 658, 285, 0, 0, 658, 0, 247, 656, 125, 125, 125, 125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 266, 247, 659, 234, 0, 350, 235, 599, 285, 658, 234,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 330, 0, 0, 235, 125, 125, 285,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 125, 125,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 660, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 579, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 661, 125,
- 248, 318, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 662, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 663, 125, 0, 0, 0, 0, 0, 0, 125, 125, 125, 125, 125, 125, 125, 125,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
- 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0,
- 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
- 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303,
- 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
- 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
- 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199,
- 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0,
- 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231,
- 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
- 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275,
- 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093,
- 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010,
- 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347,
- 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
- 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365,
- 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
- 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182,
- 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
- 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0,
- 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461,
- 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486,
- 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0,
- 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553,
- 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560,
- 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0,
- 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0,
- 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0,
- 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0,
- 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0,
- 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0,
- 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
- 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
- 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
- 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
- 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
- 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
- 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
- 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
- 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
- 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0,
- 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
- 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
- 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
- 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
- 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
- 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0,
- 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
- 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0,
- 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
- 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
- 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0,
- 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793,
- 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
- 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0,
- 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
- 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
- 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
- 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0,
- 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828,
- 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833,
- 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3,
- 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0,
- 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938,
- 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0,
- 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0,
- 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0,
- 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0,
- 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0,
- 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0,
- 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0,
- 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0,
- 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
- 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
- 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
- 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
- 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
- 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
- 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
- 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
- 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
- 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
- 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
- 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
- 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
- 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
- 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
- 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
- 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0,
- 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0,
- 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773,
- 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
- 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
- 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
- 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0,
- 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
- 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
- 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
- 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
- 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
- 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
- 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575,
- 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0,
- 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950,
- 1951,1952,1953,1954,1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959,
- 1961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131,
- 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37,
- 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
- 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
- 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
- 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
- 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259,
- 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
- 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934,
- 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312,
- 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
- 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
- 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381,
- 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399,
- 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417,
- 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
- 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460,
- 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
- 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505,
- 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64,
- 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538,
- 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567,
- 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592,
- 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
- 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627,
- 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
- 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83,
- 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85,
- 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696,
- 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
- 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90,
- 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787,
- 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807,
- 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 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 int16_t
-_hb_ucd_i16[196] =
-{
- 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2,
- 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1,
- 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3,
- -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0,
- 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0,
- 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0,
- 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0,
- 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0,
- 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1,
- -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0,
- 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106,
- -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1,
- -1, 0, 1, -1,
-};
-
-static inline uint_fast8_t
-_hb_ucd_gc (unsigned u)
-{
- return u<1114110u?_hb_ucd_u8[2176+(((_hb_ucd_u16[((_hb_ucd_u8[u>>4>>5])<<5)+((u>>4)&31u)])<<4)+((u)&15u))]:2;
-}
-static inline uint_fast8_t
-_hb_ucd_ccc (unsigned u)
-{
- return u<125259u?_hb_ucd_u8[15332+(((_hb_ucd_u8[13892+(((_hb_ucd_u8[12912+(u>>3>>4)])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:0;
-}
-static inline unsigned
-_hb_ucd_b4 (const uint8_t* a, unsigned i)
-{
- return (a[i>>1]>>((i&1u)<<2))&15u;
-}
-static inline int_fast16_t
-_hb_ucd_bmg (unsigned u)
-{
- return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[16692+(((_hb_ucd_b4(16564+_hb_ucd_u8,u>>2>>6))<<6)+((u>>2)&63u))])<<2)+((u)&3u)]:0;
-}
-static inline uint_fast8_t
-_hb_ucd_sc (unsigned u)
-{
- return u<918000u?_hb_ucd_u8[19446+(((_hb_ucd_u16[3168+(((_hb_ucd_u8[17652+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:2;
-}
-static inline uint_fast16_t
-_hb_ucd_dm (unsigned u)
-{
- return u<195102u?_hb_ucd_u16[6400+(((_hb_ucd_u8[30070+(u>>6)])<<6)+((u)&63u))]:0;
-}
-
-
-#elif !defined(HB_NO_UCD_UNASSIGNED)
-
-static const uint8_t
_hb_ucd_u8[17936] =
{
0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
@@ -5674,10 +2821,1743 @@ _hb_ucd_dm (unsigned u)
}
+#elif !defined(HB_NO_UCD_UNASSIGNED)
+
+static const uint8_t
+_hb_ucd_u8[17564] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 11, 12, 13, 13, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24, 7, 7,
+ 25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 22, 42,
+ 7, 7, 43, 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, 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, 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, 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, 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,
+ 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, 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, 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, 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, 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, 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, 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, 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, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 44, 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, 22, 22, 22, 22, 22, 22,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
+ 69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
+ 84, 85, 86, 87, 88, 89, 69, 69, 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, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
+ 91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96,
+ 97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105,
+ 106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+ 107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117,
+ 118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
+ 132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
+ 147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
+ 160,161,162,163,164,165,122,122,166,167,168,169,122,170,122,171,
+ 34, 34, 34, 34, 34, 34, 34,172,173, 34,174,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,175,
+ 34, 34, 34, 34, 34, 34, 34, 34,176,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122, 34, 34, 34, 34,177,122,122,122,
+ 34, 34, 34, 34,178,179,180,181,122,122,122,122,182,183,184,185,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,186,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34,187,188,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,189,
+ 34, 34,190, 34, 34,191,122,122,122,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,192,193,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,194,195,
+ 69,196,197,198,199,200,201,122,202,203,204,205,206,207,208,209,
+ 69, 69, 69, 69,210,211,122,122,122,122,122,122,122,122,212,122,
+ 213,122,214,122,122,215,122,122,122,122,122,122,122,122,122,216,
+ 34,217,218,122,122,122,122,122,219,220,221,122,222,223,122,122,
+ 224,225,226,227,228,122, 69,229, 69, 69, 69, 69, 69,230,231,232,
+ 233,234, 69, 69,235,236, 69,237,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,238, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,239, 34,
+ 240, 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, 34, 34,241, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34,242,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34,243,122,122,122,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34, 34, 34,244,122,122,122,122,122,122,122,122,122,
+ 245,122,246,247,122,122,122,122,122,122,122,122,122,122,122,122,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,248,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,249,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2,
+ 7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 17, 18, 19, 1, 20, 20, 21, 22, 23, 24, 25,
+ 26, 27, 15, 2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32,
+ 32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11,
+ 11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11,
+ 34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34,
+ 34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32,
+ 32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32,
+ 16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41,
+ 40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41,
+ 43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 44, 45, 16, 10,
+ 44, 44, 41, 46, 11, 47, 47, 11, 34, 11, 11, 11, 11, 11, 11, 11,
+ 11, 48, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34,
+ 16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 49, 34, 32, 34, 11,
+ 32, 50, 43, 43, 51, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16,
+ 48, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 47, 52, 2, 2, 2,
+ 16, 16, 16, 16, 53, 54, 55, 56, 57, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 58, 59, 60, 43, 59, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 62,
+ 36, 63, 64, 44, 44, 44, 44, 44, 65, 65, 65, 8, 9, 66, 2, 67,
+ 43, 43, 43, 43, 43, 60, 68, 2, 69, 36, 36, 36, 36, 70, 43, 43,
+ 7, 7, 7, 7, 7, 2, 2, 36, 71, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 72, 43, 43, 43, 73, 50, 43, 43, 74, 75, 76, 43, 43, 36,
+ 7, 7, 7, 7, 7, 36, 77, 78, 2, 2, 2, 2, 2, 2, 2, 79,
+ 70, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 80, 62, 36,
+ 36, 36, 36, 43, 43, 43, 43, 43, 71, 44, 44, 44, 44, 44, 44, 44,
+ 7, 7, 7, 7, 7, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43,
+ 43, 43, 40, 21, 2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
+ 43, 43, 75, 43, 75, 43, 43, 44, 2, 2, 2, 2, 2, 2, 2, 64,
+ 36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
+ 36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43,
+ 36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43,
+ 43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86,
+ 87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36,
+ 36, 43, 2, 7, 7, 7, 7, 7, 88, 36, 36, 36, 36, 36, 36, 36,
+ 70, 86, 62, 36, 36, 36, 61, 62, 61, 62, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 61, 36, 36, 36, 61, 61, 44, 36, 36, 44, 71, 86,
+ 87, 43, 80, 89, 90, 89, 87, 61, 44, 44, 44, 89, 44, 44, 36, 62,
+ 36, 43, 44, 7, 7, 7, 7, 7, 36, 20, 27, 27, 27, 56, 63, 80,
+ 57, 85, 62, 36, 36, 61, 44, 62, 61, 36, 62, 61, 36, 44, 80, 86,
+ 87, 80, 44, 57, 80, 57, 43, 44, 57, 44, 44, 44, 62, 36, 61, 61,
+ 44, 44, 44, 7, 7, 7, 7, 7, 43, 36, 70, 64, 44, 44, 44, 44,
+ 57, 85, 62, 36, 36, 36, 36, 62, 36, 62, 36, 36, 36, 36, 36, 36,
+ 61, 36, 62, 36, 36, 44, 71, 86, 87, 43, 43, 57, 85, 89, 87, 44,
+ 61, 44, 44, 44, 44, 44, 44, 44, 66, 44, 44, 44, 62, 43, 43, 43,
+ 57, 86, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 44, 71, 87,
+ 87, 43, 80, 89, 90, 89, 87, 44, 44, 44, 57, 85, 44, 44, 36, 62,
+ 78, 27, 27, 27, 44, 44, 44, 44, 44, 71, 62, 36, 36, 61, 44, 36,
+ 61, 36, 36, 44, 62, 61, 61, 36, 44, 62, 61, 44, 36, 61, 44, 36,
+ 36, 36, 36, 36, 36, 44, 44, 86, 85, 90, 44, 86, 90, 86, 87, 44,
+ 61, 44, 44, 89, 44, 44, 44, 44, 27, 91, 67, 67, 56, 92, 44, 44,
+ 85, 86, 71, 36, 36, 36, 61, 36, 61, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 44, 71, 43, 85, 86, 90, 43, 80, 43, 43, 44,
+ 44, 44, 57, 80, 36, 61, 62, 44, 44, 44, 44, 93, 27, 27, 27, 91,
+ 70, 86, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 87,
+ 86, 86, 90, 85, 90, 86, 43, 44, 44, 44, 89, 90, 44, 44, 62, 61,
+ 62, 61, 44, 44, 44, 44, 44, 44, 43, 86, 36, 36, 36, 36, 61, 36,
+ 36, 36, 36, 36, 36, 70, 71, 86, 87, 43, 80, 86, 90, 86, 87, 77,
+ 44, 44, 36, 94, 27, 27, 27, 95, 27, 27, 27, 27, 91, 36, 36, 36,
+ 57, 86, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36,
+ 36, 62, 36, 36, 36, 36, 62, 44, 36, 36, 36, 61, 44, 80, 44, 89,
+ 86, 43, 80, 80, 86, 86, 86, 86, 44, 86, 64, 44, 44, 44, 44, 44,
+ 62, 36, 36, 36, 36, 36, 36, 36, 70, 36, 43, 43, 43, 80, 44, 96,
+ 36, 36, 36, 75, 43, 43, 43, 60, 7, 7, 7, 7, 7, 2, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 61, 36, 36, 61, 36, 36,
+ 36, 36, 62, 62, 36, 36, 36, 36, 70, 36, 43, 43, 43, 43, 71, 44,
+ 36, 36, 61, 81, 43, 43, 43, 44, 7, 7, 7, 7, 7, 44, 36, 36,
+ 77, 67, 2, 2, 2, 2, 2, 2, 2, 97, 97, 67, 43, 67, 67, 67,
+ 7, 7, 7, 7, 7, 27, 27, 27, 27, 27, 50, 50, 50, 4, 4, 86,
+ 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44,
+ 57, 43, 43, 43, 43, 43, 43, 85, 43, 43, 60, 43, 36, 36, 70, 43,
+ 43, 43, 43, 43, 57, 43, 43, 43, 43, 43, 43, 43, 43, 43, 80, 67,
+ 67, 67, 67, 76, 67, 67, 92, 67, 2, 2, 97, 67, 21, 64, 44, 44,
+ 36, 36, 36, 36, 36, 94, 87, 43, 85, 43, 43, 43, 87, 85, 87, 71,
+ 7, 7, 7, 7, 7, 2, 2, 2, 36, 36, 36, 86, 43, 36, 36, 43,
+ 71, 86, 98, 94, 86, 86, 86, 36, 70, 43, 71, 36, 36, 36, 36, 36,
+ 36, 85, 87, 85, 86, 86, 87, 94, 7, 7, 7, 7, 7, 86, 87, 67,
+ 11, 11, 11, 48, 44, 44, 48, 44, 16, 16, 16, 16, 16, 53, 45, 16,
+ 36, 36, 36, 36, 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44,
+ 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44, 36, 36, 36, 36,
+ 36, 36, 36, 61, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 57, 43,
+ 2, 2, 2, 2, 99, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44,
+ 67, 67, 67, 67, 67, 44, 44, 44, 11, 11, 11, 44, 16, 16, 16, 44,
+ 101, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 77, 72,
+ 102, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,103,104, 44,
+ 36, 36, 36, 36, 36, 63, 2,105,106, 36, 36, 36, 61, 44, 44, 44,
+ 36, 43, 85, 44, 44, 44, 44, 62, 36, 43,107, 64, 44, 44, 44, 44,
+ 36, 43, 44, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 61, 36,
+ 61, 43, 44, 44, 44, 44, 44, 44, 36, 36, 43, 87, 43, 43, 43, 86,
+ 86, 86, 86, 85, 87, 43, 43, 43, 43, 43, 2, 88, 2, 66, 70, 44,
+ 7, 7, 7, 7, 7, 44, 44, 44, 27, 27, 27, 27, 27, 44, 44, 44,
+ 2, 2, 2,108, 2, 59, 43, 84, 36, 83, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 61, 44, 44, 44, 36, 36, 70, 71, 36, 36, 36, 36,
+ 36, 36, 36, 36, 70, 61, 44, 44, 36, 36, 36, 44, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 61, 43, 85, 86, 87, 85, 86, 44, 44,
+ 86, 85, 86, 86, 87, 43, 44, 44, 92, 44, 2, 7, 7, 7, 7, 7,
+ 36, 36, 36, 36, 36, 36, 36, 44, 36, 36, 61, 44, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 44, 44, 36, 36, 36, 36, 36, 44, 44, 44,
+ 7, 7, 7, 7, 7,100, 44, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 36, 36, 36, 70, 85, 87, 44, 2, 36, 36, 94, 85, 43, 43, 43, 80,
+ 85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57,
+ 2, 2, 2, 88, 2, 2, 2, 44, 43, 43, 43, 43, 43, 43, 43,109,
+ 43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36,
+ 36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44,
+ 97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64,
+ 43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36,
+ 36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44, 2, 2,
+ 36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93, 2, 2,
+ 7, 7, 7, 7, 7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40, 2,
+ 16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
+ 2, 2, 2, 2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
+ 85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44,
+ 16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
+ 16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16,111, 40, 40,
+ 32, 32, 32, 16, 16, 16, 16, 32, 16, 16, 16, 16, 11, 11, 11, 11,
+ 16, 16, 16, 44, 11, 11, 11, 44, 16, 16, 16, 16, 48, 48, 48, 48,
+ 16, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16, 16,112,112,112,112,
+ 16, 16,110, 16, 11, 11,113,114, 41, 16,110, 16, 11, 11,113, 41,
+ 16, 16, 44, 16, 11, 11,115, 41, 16, 16, 16, 16, 11, 11,116, 41,
+ 44, 16,110, 16, 11, 11,113,117,118,118,118,118,118,119, 65, 65,
+ 120,120,120, 2,121,122,121,122, 2, 2, 2, 2,123, 65, 65,124,
+ 2, 2, 2, 2,125,126, 2,127,128, 2,129,130, 2, 2, 2, 2,
+ 2, 9,128, 2, 2, 2, 2,131, 65, 65,132, 65, 65, 65, 65, 65,
+ 133, 44, 27, 27, 27, 8,129,134, 27, 27, 27, 27, 27, 8,129,104,
+ 40, 40, 40, 40, 40, 40, 81, 44, 20, 20, 20, 20, 20, 20, 20, 20,
+ 135, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43,136, 51,
+ 109, 51,109, 43, 43, 43, 43, 43, 80, 44, 44, 44, 44, 44, 44, 44,
+ 67,137, 67,138, 67, 34, 11, 16, 11, 32,138, 67, 49, 11, 11, 67,
+ 67, 67,137,137,137, 11, 11,139, 11, 11, 35, 36, 39, 67, 16, 11,
+ 8, 8, 49, 16, 16, 26, 67,140, 27, 27, 27, 27, 27, 27, 27, 27,
+ 105,105,105,105,105,105,105,105,105,141,142,105,143, 67, 44, 44,
+ 8, 8,144, 67, 67, 8, 67, 67,144, 26, 67,144, 67, 67, 67,144,
+ 67, 67, 67, 67, 67, 67, 67, 8, 67,144,144, 67, 67, 67, 67, 67,
+ 67, 67, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 67, 67, 67, 67, 4, 4, 67, 67, 8, 67, 67, 67,145,146, 67, 67,
+ 67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26, 8, 8,
+ 8, 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8,
+ 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
+ 67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
+ 26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, 8, 8,
+ 67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67, 4, 4, 4, 4,
+ 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
+ 8, 8,129,147, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4,
+ 8,129,148,148,148,148,148,148,148,148,148,148,147, 8, 8, 8,
+ 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8,
+ 8, 8,144, 26, 8, 8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67,
+ 67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11,
+ 32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149,
+ 43, 32, 44, 44, 93, 2, 99, 2, 16, 16, 16,150, 44, 44,150, 44,
+ 36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
+ 36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
+ 2,121,121, 2,125,126,121, 2, 2, 2, 2, 6, 2,108,121, 2,
+ 121, 4, 4, 4, 4, 2, 2, 88, 2, 2, 2, 2, 2,120, 2, 2,
+ 108,151, 2, 2, 2, 2, 2, 2, 67, 2,152,148,148,148,153, 44,
+ 67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44,
+ 1, 2,154,155, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4,156,157,
+ 158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67,
+ 36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69,
+ 44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67,
+ 67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27,
+ 36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164, 2,
+ 7, 7, 7, 7, 7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70,
+ 51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43,
+ 36, 36, 36,105,105,105,105,105, 43, 2, 2, 2, 44, 44, 44, 44,
+ 41, 41, 41,162, 40, 40, 40, 40, 41, 32, 32, 32, 32, 32, 32, 32,
+ 16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32,
+ 32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
+ 32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44,
+ 44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
+ 36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44,
+ 36, 36, 2, 2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 86, 86, 86, 86, 86, 86, 86, 86, 43, 44, 44, 44, 44, 2,
+ 43, 36, 36, 36, 2, 72, 72, 70, 36, 36, 36, 43, 43, 43, 43, 2,
+ 36, 36, 36, 70, 43, 43, 43, 43, 43, 86, 44, 44, 44, 44, 44, 93,
+ 36, 70, 86, 43, 43, 86, 43, 86,107, 2, 2, 2, 2, 2, 2, 52,
+ 7, 7, 7, 7, 7, 44, 44, 2, 36, 36, 70, 69, 36, 36, 36, 36,
+ 7, 7, 7, 7, 7, 36, 36, 61, 36, 36, 36, 36, 70, 43, 43, 85,
+ 87, 85, 87, 80, 44, 44, 44, 44, 36, 70, 36, 36, 36, 36, 85, 44,
+ 7, 7, 7, 7, 7, 44, 2, 2, 69, 36, 36, 77, 67, 94, 85, 36,
+ 71, 43, 71, 70, 71, 36, 36, 43, 70, 61, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 62, 83, 2, 36, 36, 36, 36, 36, 94, 43, 86,
+ 2, 83,169, 80, 44, 44, 44, 44, 62, 36, 36, 61, 62, 36, 36, 61,
+ 62, 36, 36, 61, 44, 44, 44, 44, 16, 16, 16, 16, 16,114, 40, 40,
+ 16, 16, 16, 16,111, 41, 44, 44, 36, 94, 87, 86, 85,107, 87, 44,
+ 36, 36, 44, 44, 44, 44, 44, 44, 36, 36, 36, 61, 44, 62, 36, 36,
+ 170,170,170,170,170,170,170,170,171,171,171,171,171,171,171,171,
+ 16, 16, 16,110, 44, 44, 44, 44, 44,150, 16, 16, 44, 44, 62, 71,
+ 36, 36, 36, 36,172, 36, 36, 36, 36, 36, 36, 61, 36, 36, 61, 61,
+ 36, 62, 61, 36, 36, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
+ 41,117, 44, 44, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36,148, 44, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 44, 44, 44, 55, 36, 36, 36, 36, 36, 36,168, 67,
+ 2, 2, 2,152,130, 44, 44, 44, 6,173,174,148,148,148,148,148,
+ 148,148,130,152,130, 2,127,175, 2, 64, 2, 2,156,148,148,130,
+ 2,176, 8,177, 66, 2, 44, 44, 36, 36, 61, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 61, 79, 93, 2, 3, 2, 4, 5, 6, 2,
+ 16, 16, 16, 16, 16, 17, 18,129,130, 4, 2, 36, 36, 36, 36, 36,
+ 69, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40,
+ 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 61, 44,
+ 20,178, 56,135, 26, 8,144, 92, 44, 44, 44, 44, 79, 65, 67, 44,
+ 36, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 61, 36, 62,
+ 2, 64, 44,179, 27, 27, 27, 27, 27, 27, 44, 55, 67, 67, 67, 67,
+ 105,105,143, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 27, 67, 92,
+ 67, 67, 67, 67, 67, 67, 92, 44, 92, 44, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 67, 50, 44,180, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 44, 44, 27, 27, 44, 44, 44, 44, 62, 36,
+ 155, 36, 36, 36, 36,181, 44, 44, 36, 36, 36, 43, 43, 80, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 93, 36, 36, 44, 44, 36, 36, 36, 36,
+ 182,105,105, 44, 44, 44, 44, 44, 11, 11, 11, 11, 16, 16, 16, 16,
+ 11, 11, 44, 44, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 44, 44,
+ 36, 36, 36, 36, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44, 44, 93,
+ 11, 11, 11, 11, 11, 47, 11, 11, 11, 47, 11,150, 16, 16, 16, 16,
+ 16,150, 16, 16, 16, 16, 16, 16, 16,150, 16, 16, 16,150,110, 44,
+ 40, 40, 40, 52, 40, 40, 40, 40, 81, 40, 40, 40, 40, 81, 44, 44,
+ 36, 36, 36, 44, 61, 36, 36, 36, 36, 36, 36, 62, 61, 44, 61, 62,
+ 36, 36, 36, 93, 27, 27, 27, 27, 36, 36, 36, 77,163, 27, 27, 27,
+ 44, 44, 44,179, 27, 27, 27, 27, 36, 61, 36, 44, 44,179, 27, 27,
+ 36, 36, 36, 27, 27, 27, 44, 93, 36, 36, 36, 36, 36, 44, 44, 93,
+ 36, 36, 36, 36, 44, 44, 27, 36, 44, 27, 27, 27, 27, 27, 27, 27,
+ 70, 43, 57, 80, 44, 44, 43, 43, 36, 36, 62, 36, 62, 36, 36, 36,
+ 36, 36, 36, 44, 43, 80, 44, 57, 27, 27, 27, 27,100, 44, 44, 44,
+ 2, 2, 2, 2, 64, 44, 44, 44, 36, 36, 36, 36, 36, 36,183, 30,
+ 36, 36, 36, 36, 36, 36,183, 27, 36, 36, 36, 36, 78, 36, 36, 36,
+ 36, 36, 70, 80, 44,179, 27, 27, 2, 2, 2, 64, 44, 44, 44, 44,
+ 36, 36, 36, 44, 93, 2, 2, 2, 36, 36, 36, 44, 27, 27, 27, 27,
+ 36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93, 2, 64, 44,
+ 44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
+ 16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
+ 27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
+ 36, 44, 44, 44, 44, 44, 44, 44, 27, 27, 27, 95, 44, 44, 44, 44,
+ 180, 27, 30, 2, 2, 44, 44, 44, 36, 43, 43, 2, 2, 44, 44, 44,
+ 36, 36,183, 27, 27, 27, 44, 44, 87, 98, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 43, 60, 2, 2, 2, 44,
+ 27, 27, 27, 7, 7, 7, 7, 7, 71, 70, 71, 44, 44, 44, 44, 57,
+ 86, 87, 43, 85, 87, 60,185, 2, 2, 80, 44, 44, 44, 44, 79, 44,
+ 43, 71, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43, 87, 43,
+ 43, 43, 80, 7, 7, 7, 7, 7, 2, 2, 94, 98, 44, 44, 44, 44,
+ 36, 70, 2, 61, 44, 44, 44, 44, 36, 94, 86, 43, 43, 43, 43, 85,
+ 98, 36, 63, 2, 59, 43, 60, 87, 7, 7, 7, 7, 7, 63, 63, 2,
+ 179, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 86, 87, 43, 86, 85, 43, 2, 2, 2, 80,
+ 36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62,
+ 36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70,
+ 86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
+ 61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44,
+ 61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44,
+ 43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43,
+ 86, 43, 85, 71, 36, 63, 2, 2, 7, 7, 7, 7, 7, 2, 93, 71,
+ 86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87,
+ 60, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 43, 44,
+ 86, 87, 43, 43, 43, 85, 87, 87, 60, 2, 61, 44, 44, 44, 44, 44,
+ 2, 2, 2, 2, 2, 2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86,
+ 43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44,
+ 7, 7, 7, 7, 7, 27, 2, 97, 43, 43, 43, 43, 87, 60, 44, 44,
+ 27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36,
+ 36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71,
+ 98, 87, 2, 64, 44, 44, 44, 44, 36, 36, 36, 36, 44, 36, 36, 36,
+ 94, 86, 43, 43, 44, 43, 86, 86, 71, 72, 90, 44, 44, 44, 44, 44,
+ 70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 85, 70, 43, 60,
+ 2, 2, 2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
+ 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43, 2, 72, 2,
+ 2, 64, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87,
+ 63, 2, 2, 44, 44, 44, 44, 44, 2, 36, 36, 36, 36, 36, 36, 36,
+ 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43,
+ 85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36,
+ 70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44,
+ 36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90,
+ 43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44,
+ 27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
+ 67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
+ 2, 2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
+ 65, 65, 65, 65,132, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
+ 43, 43, 43, 60, 2, 2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
+ 7, 7, 7, 7, 7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30, 2, 64, 44, 44,
+ 36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
+ 43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
+ 86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
+ 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
+ 43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
+ 67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
+ 86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67,
+ 67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44,
+ 27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
+ 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
+ 16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
+ 11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16,
+ 16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
+ 16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
+ 47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
+ 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
+ 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
+ 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
+ 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
+ 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 43, 43, 43, 76, 67, 50, 43, 43,
+ 43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
+ 67, 67, 76, 21, 2, 2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
+ 16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
+ 43, 43, 43, 80, 43, 43, 43, 43, 43, 43, 43, 43, 80, 57, 43, 43,
+ 43, 57, 80, 43, 43, 80, 44, 44, 43, 43, 43, 74, 40, 40, 40, 44,
+ 7, 7, 7, 7, 7, 44, 44, 77, 36, 36, 36, 36, 36, 36, 36, 80,
+ 36, 36, 36, 36, 36, 36, 43, 43, 7, 7, 7, 7, 7, 44, 44, 96,
+ 36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
+ 16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
+ 188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
+ 27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36,
+ 62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44,
+ 44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62,
+ 62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61,
+ 36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36,
+ 8, 44, 44, 44, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67,
+ 27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
+ 44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 55, 67,
+ 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 44, 67, 67, 92, 44,
+ 67, 92, 67, 67, 67, 67, 67, 67, 79, 44, 44, 44, 44, 44, 44, 44,
+ 65, 65, 65, 65, 65, 65, 65, 65,171,171,171,171,171,171,171, 44,
+ 171,171,171,171,171,171,171, 0, 0, 0, 29, 21, 21, 21, 23, 21,
+ 22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21, 9, 9, 9,
+ 9, 22, 21, 18, 24, 16, 24, 5, 5, 5, 5, 22, 25, 18, 25, 0,
+ 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24, 26, 25, 15, 15,
+ 24, 15, 7, 19, 15, 21, 9, 25, 9, 5, 5, 25, 5, 9, 5, 7,
+ 7, 7, 9, 8, 8, 5, 7, 5, 6, 6, 24, 24, 6, 24, 12, 12,
+ 2, 2, 6, 5, 9, 21, 9, 2, 2, 9, 25, 9, 26, 12, 11, 11,
+ 2, 6, 5, 21, 17, 2, 2, 26, 26, 23, 2, 12, 17, 12, 21, 12,
+ 12, 21, 7, 2, 2, 7, 7, 21, 21, 2, 1, 1, 21, 23, 26, 26,
+ 1, 21, 6, 7, 7, 12, 12, 7, 21, 7, 12, 1, 12, 6, 6, 12,
+ 12, 26, 7, 26, 26, 7, 2, 1, 12, 2, 6, 2, 24, 7, 7, 6,
+ 1, 12, 12, 10, 10, 10, 10, 12, 21, 6, 2, 10, 10, 2, 15, 26,
+ 26, 2, 2, 21, 7, 10, 15, 7, 2, 23, 21, 26, 10, 7, 21, 15,
+ 15, 2, 17, 7, 29, 7, 7, 22, 18, 2, 14, 14, 14, 7, 10, 21,
+ 17, 21, 11, 12, 5, 2, 5, 6, 8, 8, 8, 24, 5, 24, 2, 24,
+ 9, 24, 24, 2, 29, 29, 29, 1, 17, 17, 20, 19, 22, 20, 27, 28,
+ 1, 29, 21, 20, 19, 21, 21, 16, 16, 21, 25, 22, 18, 21, 21, 29,
+ 1, 2, 15, 6, 18, 6, 23, 2, 12, 11, 9, 26, 26, 9, 26, 5,
+ 5, 26, 14, 9, 5, 14, 14, 15, 25, 26, 26, 22, 18, 26, 18, 25,
+ 18, 22, 5, 12, 2, 5, 22, 21, 21, 22, 18, 17, 26, 6, 7, 14,
+ 17, 22, 18, 18, 26, 14, 17, 6, 14, 6, 12, 24, 24, 6, 26, 15,
+ 6, 21, 11, 21, 24, 9, 6, 9, 23, 26, 6, 10, 4, 4, 3, 3,
+ 7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25, 2, 25, 24, 2, 15,
+ 12, 15, 14, 2, 21, 14, 7, 15, 12, 17, 21, 1, 26, 10, 10, 1,
+ 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12,
+ 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20,
+ 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 34, 0, 35, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0,
+ 0, 0, 39, 40, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 5,
+ 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, 16, 17, 16, 18,
+ 16, 19, 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, 21, 19, 0, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35,
+ 0, 0, 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0,
+ 0, 0, 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, 0, 0, 0, 0,
+ 0, 55, 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, 60, 61, 62, 63,
+ 0, 0, 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, 67, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,
+ 0, 0, 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, 0, 0, 0, 0,
+ 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 75, 0, 0, 76, 77, 0,
+ 0, 78, 79, 0, 80, 62, 0, 81, 82, 0, 0, 83, 84, 85, 0, 0,
+ 0, 86, 0, 87, 0, 0, 51, 88, 51, 0, 89, 0, 90, 0, 0, 0,
+ 79, 0, 0, 0, 91, 92, 0, 93, 94, 95, 96, 0, 0, 0, 0, 0,
+ 51, 0, 0, 0, 0, 97, 98, 0, 0, 0, 0, 99,100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,101, 0, 0,102, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,103,104, 0, 0,105, 0, 0, 0, 0, 0, 0,
+ 106, 0, 0, 0,100, 0, 0, 0, 0, 0,107,108, 0, 0, 0, 0,
+ 0, 0, 0,109, 0,110, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
+ 5, 6, 7, 0, 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0,
+ 0, 13, 0, 0, 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, 0, 20,
+ 21, 0, 0, 0, 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, 0, 0,
+ 0, 27, 0, 0, 28, 29, 30, 31, 0, 0, 0, 32, 33, 34, 0, 0,
+ 33, 0, 0, 35, 33, 0, 0, 0, 33, 36, 0, 0, 0, 0, 0, 37,
+ 38, 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 41,
+ 42, 0, 0, 0, 0, 43, 0, 44, 0, 0, 0, 45, 46, 0, 0, 0,
+ 47, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 50, 0, 0,
+ 0, 51, 0, 52, 0, 53, 0, 0, 0, 0, 54, 0, 0, 0, 0, 55,
+ 0, 56, 0, 0, 0, 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0,
+ 0, 0, 0, 61, 52, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 66,
+ 0, 0, 0, 67, 0, 68, 69, 70, 71, 72, 1, 73, 0, 74, 75, 76,
+ 0, 0, 77, 78, 0, 0, 0, 79, 0, 0, 1, 1, 0, 0, 80, 0,
+ 0, 81, 0, 0, 0, 0, 77, 82, 0, 83, 0, 0, 0, 0, 0, 78,
+ 84, 0, 85, 0, 52, 0, 1, 78, 0, 0, 86, 0, 0, 87, 0, 0,
+ 0, 0, 0, 88, 57, 0, 0, 0, 0, 0, 0, 89, 90, 0, 0, 84,
+ 0, 0, 33, 0, 0, 91, 0, 0, 0, 0, 92, 0, 0, 0, 0, 49,
+ 0, 0, 93, 0, 0, 0, 0, 94, 95, 0, 0, 96, 0, 0, 97, 0,
+ 0, 0, 98, 0, 0, 0, 99, 0,100, 93, 0, 0,101, 0, 0, 0,
+ 84, 0, 0,102, 0, 0, 0,103,104, 0, 0,105,106, 0, 0, 0,
+ 0, 0, 0,107, 0, 0,108, 0, 0, 0, 0,109, 33, 0,110,111,
+ 112, 35, 0, 0,113, 0, 0, 0,114, 0, 0, 0, 0, 0, 0,115,
+ 0, 0,116, 0, 0, 0, 0,117, 88, 0, 0, 0, 0, 0, 57, 0,
+ 0, 0, 0, 52,118, 0, 0, 0, 0,119, 0, 0,120, 0, 0, 0,
+ 0,118, 0, 0, 0, 0, 0,121, 0, 0, 0,122, 0, 0, 0,123,
+ 0,124, 0, 0, 0, 0,125,126,127, 0,128, 0,129, 0, 0, 0,
+ 130,131,132, 0, 0, 0, 35, 0, 0, 0,133, 0, 0,134, 0, 0,
+ 135, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4,
+ 5, 6, 7, 4, 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17,
+ 18, 1, 1, 1, 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24,
+ 25, 26, 27, 28, 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33,
+ 34, 35, 1, 36, 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41,
+ 42, 0, 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 19, 1,
+ 21, 0, 0, 47, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 51, 0,
+ 0, 0, 52, 1, 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52,
+ 54, 21, 35, 1, 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0,
+ 0, 0, 0, 59, 0, 60, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0,
+ 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 67, 0,
+ 0, 0, 68, 0, 0, 69, 70, 0, 71, 72, 73, 74, 75, 76, 0, 0,
+ 0, 77, 0, 0, 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 49,
+ 0, 80, 0, 0, 0, 62, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0,
+ 0, 0, 83, 0, 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85,
+ 1, 52, 15, 86, 36, 10, 21, 87, 0, 55, 0, 0, 0, 0, 19, 10,
+ 1, 0, 0, 0, 0, 0, 88, 0, 0, 89, 0, 0, 88, 0, 0, 0,
+ 0, 78, 0, 0, 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0,
+ 21, 1, 21, 92, 93, 1, 1, 1, 1, 94, 95, 96, 97, 1, 98, 58,
+ 81, 99,100, 4, 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0,
+ 0, 0, 0, 61, 0, 0,101,102, 0, 0,103, 0, 0, 1, 1, 50,
+ 0, 0, 0, 38, 0, 63, 0, 0, 0, 0, 0, 62, 0, 0,104, 68,
+ 61, 0, 0, 0, 78, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0,
+ 0, 0, 0,107, 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 87, 0,
+ 0, 0, 0,108, 0, 0,109, 61, 0,110, 0, 0, 0, 1, 0, 0,
+ 0, 0, 19, 58, 0,111, 14, 52,112, 41, 0, 0, 62, 0, 0, 61,
+ 0, 0,113, 0, 87, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0,
+ 0,113, 0, 0, 0, 0,114, 0, 0, 0, 78, 55, 0, 38, 1, 58,
+ 1, 58, 0, 0, 63, 89, 0, 0,115, 0, 0, 0, 55, 0, 0, 0,
+ 0,115, 0, 0, 0, 0, 61, 0, 0, 0, 0, 79, 0, 61, 0, 0,
+ 0, 0, 56, 0, 89, 80, 0, 0, 8, 91, 0, 0, 1, 87, 0, 0,
+ 116, 0, 0, 0, 0, 0, 0,117, 0,118,119,120,121, 0,104, 4,
+ 122, 49, 23, 0, 0, 0, 38, 50, 38, 58, 0, 0, 1, 87, 1, 1,
+ 1, 1, 39, 1, 48,105, 87, 0, 0, 0, 0, 1, 4,122, 0, 0,
+ 0, 1,123, 0, 0, 0, 0, 0,230,230,230,230,230,232,220,220,
+ 220,220,232,216,220,220,220,220,220,202,202,220,220,220,220,202,
+ 202,220,220,220, 1, 1, 1, 1, 1,220,220,220,220,230,230,230,
+ 230,240,230,220,220,220,230,230,230,220,220, 0,230,230,230,220,
+ 220,220,220,230,232,220,220,230,233,234,234,233,234,234,233,230,
+ 0, 0, 0,230, 0,220,230,230,230,230,220,230,230,230,222,220,
+ 230,230,220,220,230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18,
+ 30, 31, 32, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,
+ 230,220,220,230,220,230,230,220, 35, 0, 0, 0, 0, 0,230,230,
+ 230, 0, 0,230,230, 0,220,230,230,220, 0, 0, 0, 36, 0, 0,
+ 230,220,230,230,220,220,230,220,220,230,220,230,220,230,230, 0,
+ 0,220, 0, 0,230,230, 0,230, 0,230,230,230,230,230, 0, 0,
+ 0,220,220,220,230,220,220,220,230,230, 0,220, 27, 28, 29,230,
+ 7, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0,
+ 0, 0,230, 0, 0, 84, 91, 0, 0, 0, 0, 9, 9, 0, 0, 0,
+ 0, 0, 9, 0,103,103, 9, 0,107,107,107,107,118,118, 9, 0,
+ 122,122,122,122,220,220, 0, 0, 0,220, 0,220, 0,216, 0, 0,
+ 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130,130,130, 0, 0,
+ 130, 0,230,230, 9, 0,230,230, 0, 0,220, 0, 0, 0, 0, 7,
+ 0, 9, 9, 0, 9, 9, 0, 0, 0,230, 0, 0, 0,228, 0, 0,
+ 0,222,230,220,220, 0, 0, 0,230, 0, 0,220,230,220, 0,220,
+ 230,230,230, 0, 0, 0, 9, 9, 0, 0, 7, 0,230, 0, 1, 1,
+ 1, 0, 0, 0,230,234,214,220,202,230,230,230,230,230,232,228,
+ 228,220,218,230,233,220,230,220,230,230, 1, 1, 1, 1, 1,230,
+ 0, 1, 1,230,220,230, 1, 1, 0, 0,218,228,232,222,224,224,
+ 0, 8, 8, 0, 0, 0, 0,220,230, 0,230,230,220, 0, 0,230,
+ 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0, 0,230,220, 0,
+ 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0, 0, 7, 9, 0,
+ 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0, 0,216,216, 1,
+ 1, 1, 0, 0, 0,226,216,216,216,216,216, 0,220,220,220, 0,
+ 230,230, 7, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
+ 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17,237, 0, 1, 2, 2, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 0, 6, 7, 8, 9, 0, 0, 0, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20,
+ 0, 0, 21, 22, 0, 0, 0, 0, 23, 24, 25, 26, 0, 27, 0, 28,
+ 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 33, 34, 35, 36, 0,
+ 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39,
+ 0, 0, 0, 0, 1, 2, 40, 41, 0, 1, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+ 0, 0, 3, 4, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+ 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0,
+ 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 11, 12,
+ 0, 13, 0, 14, 15, 16, 0, 0, 0, 0, 0, 1, 17, 18, 0, 19,
+ 7, 1, 0, 0, 0, 20, 20, 7, 20, 20, 20, 20, 20, 20, 20, 8,
+ 21, 0, 22, 0, 7, 23, 24, 0, 20, 20, 25, 0, 0, 0, 26, 27,
+ 1, 7, 20, 20, 20, 20, 20, 1, 28, 29, 30, 31, 0, 0, 20, 0,
+ 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 20, 20,
+ 20, 1, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20,
+ 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20,
+ 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0,
+ 0, 40, 1, 1, 0, 0, 8, 21, 0, 1, 0, 1, 0, 1, 0, 0,
+ 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45,
+ 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 46, 7, 1, 10, 1,
+ 0, 0, 0, 1, 20, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 34, 9, 0, 0, 20, 20, 1, 20, 20, 0, 0, 0, 0, 0,
+ 0, 0, 26, 21, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3,
+ 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13,
+ 13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 13, 42, 7, 7, 43, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 44, 0, 0, 1,
+ 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 2, 2, 53, 54, 55, 56,
+ 57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61,
+ 59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109,
+ 110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123,
+ 124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138,
+ 139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151,
+ 152,153,154,155, 96, 96,156,157,158,159, 96,160, 96,161,162,162,
+ 162,162,162,162,162,163,164,162,165, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,166,167,167,
+ 167,167,167,167,167,167,168, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96,169,169,169,169,170, 96, 96, 96,171,171,
+ 171,171,172,173,174,175, 96, 96, 96, 96,176,177,178,179,180,180,
+ 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
+ 180,180,180,180,180,180,180,180,180,180,180,180,180,181,180,180,
+ 180,180,180,180,182,182,182,183,184, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,185,186,187,
+ 188,189,189,190, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96,191,192, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194, 59,195,
+ 196,197,198,199,200, 96,201,202,203, 59, 59,204, 59,205,206,206,
+ 206,206,206,207, 96, 96, 96, 96, 96, 96, 96, 96,208, 96,209, 96,
+ 210, 96, 96,211, 96, 96, 96, 96, 96, 96, 96, 96, 96,212,213,214,
+ 215, 96, 96, 96, 96, 96,216,217,218, 96,219,220, 96, 96,221,222,
+ 59,223,224, 96, 59, 59, 59, 59, 59, 59, 59,225,226,227,228,229,
+ 59, 59,230,231, 59,232, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,233, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,234, 70,235, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,236, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70,237, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70,238, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70, 70, 70,239, 96, 96, 96, 96, 96, 96, 96, 96, 96,240, 96,
+ 241,242, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0,
+ 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 0, 19, 0,
+ 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0,
+ 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9,
+ 9, 9, 0, 9, 9, 9, 2, 2, 9, 9, 9, 9, 0, 9, 2, 2,
+ 2, 2, 9, 0, 9, 0, 9, 9, 9, 2, 9, 2, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 2, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 2, 4, 4, 4, 2, 2, 4, 4, 4, 2, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2,
+ 2, 2, 2, 2, 2, 2, 14, 14, 14, 2, 2, 2, 2, 14, 14, 14,
+ 14, 14, 14, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,
+ 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 3,
+ 3, 3, 3, 3, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64, 64, 64, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90,
+ 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 2, 2, 95, 2, 37, 37, 37, 2, 2, 2, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3,
+ 0, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1,
+ 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 5, 5,
+ 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2,
+ 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
+ 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5,
+ 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 2, 2, 2,
+ 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5, 5, 2, 5, 5, 5,
+ 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 11,
+ 11, 11, 2, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2,
+ 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2,
+ 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11,
+ 2, 2, 11, 2, 11, 11, 11, 2, 2, 11, 11, 11, 2, 2, 2, 11,
+ 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, 2, 11, 2, 2, 2,
+ 2, 2, 2, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 10,
+ 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10,
+ 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2,
+ 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10,
+ 2, 2, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 2, 2, 10, 2,
+ 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10,
+ 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 2, 21,
+ 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2,
+ 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2,
+ 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21,
+ 2, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 2, 2, 2, 2,
+ 2, 2, 2, 21, 21, 21, 2, 2, 2, 2, 21, 21, 2, 21, 21, 21,
+ 21, 21, 2, 2, 21, 21, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22,
+ 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22,
+ 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 22, 22, 22, 2,
+ 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22,
+ 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23,
+ 2, 2, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 2,
+ 2, 2, 2, 23, 23, 2, 23, 23, 23, 2, 2, 23, 2, 2, 23, 23,
+ 23, 23, 2, 2, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16,
+ 2, 2, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 2, 2, 2, 2,
+ 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 2, 16,
+ 16, 2, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 2, 2,
+ 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 2, 36,
+ 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, 36,
+ 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, 2,
+ 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2,
+ 2, 2, 2, 2, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 2, 2, 2, 2, 2, 18,
+ 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18,
+ 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18,
+ 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 25, 25,
+ 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25,
+ 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2,
+ 2, 2, 2, 8, 2, 2, 8, 8, 8, 0, 8, 8, 8, 8, 12, 12,
+ 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2,
+ 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
+ 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, 30, 30,
+ 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 2,
+ 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 46, 46, 46, 2,
+ 46, 46, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 2, 2, 31, 31, 2, 2, 2, 2, 2, 2, 32, 32,
+ 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 2, 2, 2, 2, 2, 2, 32, 2, 2, 2, 2, 2, 2, 2, 32, 32,
+ 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 2, 48, 48,
+ 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 2, 2, 52, 52,
+ 52, 52, 52, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 2, 2, 2, 2, 58, 58, 2, 2, 2, 2, 2, 2, 58, 58,
+ 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 2, 2, 91, 91, 91,
+ 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 2, 2, 1, 1,
+ 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 2, 76, 76,
+ 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 2, 2, 2, 2, 2, 2, 2, 2, 93, 93, 93, 93, 70, 70,
+ 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 70, 70, 70, 70,
+ 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 6, 2,
+ 2, 2, 2, 2, 2, 2, 8, 8, 8, 2, 2, 8, 8, 8, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9,
+ 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, 9,
+ 19, 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 19, 6, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9,
+ 9, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 2, 9, 9, 9,
+ 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9,
+ 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 2, 19, 19,
+ 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
+ 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0,
+ 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 27, 27,
+ 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55,
+ 55, 55, 2, 2, 2, 2, 2, 55, 55, 55, 55, 55, 55, 55, 61, 61,
+ 61, 61, 61, 61, 61, 61, 2, 2, 2, 2, 2, 2, 2, 61, 61, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 2, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 0, 0,
+ 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 13, 13,
+ 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1,
+ 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 2, 2,
+ 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12,
+ 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 0, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39,
+ 39, 39, 39, 39, 39, 2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 2, 2, 2, 2, 79, 79,
+ 79, 79, 79, 79, 79, 79, 0, 0, 19, 19, 19, 19, 19, 19, 0, 0,
+ 0, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 19, 19,
+ 2, 19, 2, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2,
+ 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 65, 65,
+ 65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+ 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75,
+ 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 12, 12,
+ 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2, 84, 84, 33, 33,
+ 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 2, 68, 68, 68, 68, 68, 68, 2, 2, 68, 68,
+ 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 2, 2, 2, 2, 2, 2, 2, 2, 92, 92, 92, 92, 92, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 30,
+ 30, 30, 30, 30, 30, 2, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 9, 19, 19, 19, 19, 0, 0, 2, 2, 2, 2, 87, 87,
+ 87, 87, 87, 87, 2, 2, 87, 87, 2, 2, 2, 2, 2, 2, 12, 12,
+ 12, 12, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 13, 13,
+ 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2,
+ 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 2, 14, 14, 14, 14, 14, 2, 14, 2, 14, 14,
+ 2, 14, 14, 2, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 2,
+ 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 1, 1,
+ 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 3, 3,
+ 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17,
+ 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2,
+ 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49,
+ 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0,
+ 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 2,
+ 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118,
+ 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 2, 2, 2, 2, 59, 59, 59, 59, 59, 59, 2, 2, 40, 40,
+ 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 2, 2, 50, 50,
+ 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135,
+ 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,104,104,
+ 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161,
+ 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161,
+ 2,161,161,161,161,161,161,161, 2,161,161, 2, 2, 2,110,110,
+ 110,110,110,110,110,110,110,110,110,110,110,110,110, 2,110,110,
+ 110,110,110,110, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 2,
+ 19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81,120,120,
+ 120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116,
+ 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,128,128,
+ 128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2,
+ 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
+ 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97,
+ 97, 97, 97, 97, 97, 97, 2, 2, 2, 2, 97, 97, 97, 97, 2, 2,
+ 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2,
+ 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+ 57, 57, 57, 57, 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2,
+ 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88,117,117,
+ 117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112,
+ 112,112,112,112,112, 2, 2, 2, 2,112,112,112,112,112, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78,
+ 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
+ 82, 2, 2, 2, 2, 2,122,122,122,122,122,122,122,122,122,122,
+ 2, 2, 2, 2, 2, 2, 2,122,122,122,122, 2, 2, 2, 2,122,
+ 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2,
+ 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130,
+ 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,144,144,
+ 144,144,144,144,144,144,144,144, 2, 2, 2, 2, 2, 2,156,156,
+ 156,156,156,156,156,156,156,156, 2,156,156,156, 2, 2,156,156,
+ 2, 2, 2, 2, 2, 2,147,147,147,147,147,147,147,147,148,148,
+ 148,148,148,148,148,148,148,148, 2, 2, 2, 2, 2, 2,158,158,
+ 158,158,158,158,158,158,158,158, 2, 2, 2, 2, 2, 2,153,153,
+ 153,153,153,153,153,153,153,153,153,153, 2, 2, 2, 2,149,149,
+ 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2,
+ 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 2, 2, 2, 94, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101, 2,
+ 2, 2, 2, 2, 2, 2,101,101, 2, 2, 2, 2, 2, 2, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96,111,111,
+ 111,111,111,111,111,111,111,111,111,111,111,111,111, 2,100,100,
+ 100,100,100,100,100,100, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 2, 2, 2,108,108,108,108,108,108,108,108,108,108,
+ 2,108,108,108,108,108,108,108,108,108,108,108,108, 2,129,129,
+ 129,129,129,129,129, 2,129, 2,129,129,129,129, 2,129,129,129,
+ 129,129,129,129,129,129,129,129,129,129,129,129, 2,129,129,129,
+ 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109,
+ 109, 2, 2, 2, 2, 2,109,109, 2, 2, 2, 2, 2, 2,107,107,
+ 107,107, 2,107,107,107,107,107,107,107,107, 2, 2,107,107, 2,
+ 2,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2,
+ 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107,
+ 2, 1,107,107,107,107,107, 2, 2,107,107,107, 2, 2,107, 2,
+ 2, 2, 2, 2, 2,107, 2, 2, 2, 2, 2,107,107,107,107,107,
+ 107,107, 2, 2,107,107,107,107,107,107,107, 2, 2, 2,137,137,
+ 137,137,137,137,137,137,137,137,137,137, 2,137,137,137,137,137,
+ 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124,
+ 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123,
+ 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114,
+ 114,114,114, 2, 2, 2,114,114, 2, 2, 2, 2, 2, 2, 32, 32,
+ 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102,102,
+ 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126,
+ 126, 2, 2,126,126,126,126,126,126,126, 2, 2, 2, 2,126,126,
+ 126,126,126,126,126, 2,142,142,142,142,142,142,142,142,142,142,
+ 142,142, 2, 2, 2, 2,125,125,125,125,125,125,125,125,125,125,
+ 125, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,125,154,154,
+ 154,154,154,154,154, 2, 2,154, 2, 2,154,154,154,154,154,154,
+ 154,154, 2,154,154, 2,154,154,154,154,154,154,154,154,154,154,
+ 154,154,154,154, 2,154,154, 2, 2,154,154,154,154,154,154,154,
+ 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,150,150, 2, 2,
+ 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2,141,141,
+ 141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,
+ 140, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121, 2,
+ 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2,
+ 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133,
+ 133,133,133,133, 2, 2,133,133,133,133,133, 2, 2, 2,134,134,
+ 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134, 2,134,
+ 134,134,134,134,134,134,134,134,134,134,134,134,134, 2,138,138,
+ 138,138,138,138,138, 2,138,138, 2,138,138,138,138,138,138,138,
+ 138,138,138,138,138,138, 2, 2,138, 2,138,138, 2,138,138,138,
+ 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2,
+ 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
+ 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2,
+ 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2, 2, 2,145,145,
+ 145,145,145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2, 86, 2,
+ 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63,
+ 63, 63, 63, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2,157,157,
+ 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, 80, 2,
+ 2, 2, 2, 2, 2, 2,127,127,127,127,127,127,127,127,127,127,
+ 127,127,127,127,127, 2, 79, 2, 2, 2, 2, 2, 2, 2,115,115,
+ 115,115,115,115,115,115,115,115,115,115,115,115,115, 2,115,115,
+ 2, 2, 2, 2,115,115,159,159,159,159,159,159,159,159,159,159,
+ 159,159,159,159,159, 2,159,159, 2, 2, 2, 2, 2, 2,103,103,
+ 103,103,103,103,103,103,103,103,103,103,103,103, 2, 2,119,119,
+ 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,119,119,
+ 2,119,119,119,119,119, 2, 2, 2, 2, 2,119,119,119,146,146,
+ 146,146,146,146,146,146,146,146,146, 2, 2, 2, 2, 2, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99, 2, 2,
+ 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2,136,136,
+ 136,136,136,136,136,136,155,155,155,155,155,155,155,155,155,155,
+ 155,155,155,155, 2, 2,136, 2, 2, 2, 2, 2, 2, 2, 17, 17,
+ 17, 17, 2, 17, 17, 17, 17, 17, 17, 17, 2, 17, 17, 2, 17, 15,
+ 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2, 2, 2, 15, 15,
+ 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,139,139,
+ 139,139,139,139,139,139,139,139,139,139, 2, 2, 2, 2,105,105,
+ 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105,
+ 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105,
+ 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2,
+ 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+ 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,131,131,131,131,
+ 131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131,
+ 131,131,131,131,131,131, 56, 56, 56, 56, 56, 56, 56, 2, 56, 2,
+ 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56,
+ 56, 2, 2, 2, 2, 2,151,151,151,151,151,151,151,151,151,151,
+ 151,151,151, 2, 2, 2,151,151,151,151,151,151, 2, 2,151,151,
+ 2, 2, 2, 2,151,151,160,160,160,160,160,160,160,160,160,160,
+ 160,160,160,160,160, 2,152,152,152,152,152,152,152,152,152,152,
+ 2, 2, 2, 2, 2,152, 30, 30, 30, 30, 2, 30, 30, 2,113,113,
+ 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113,
+ 113,113,113,113,113, 2,132,132,132,132,132,132,132,132,132,132,
+ 132,132, 2, 2, 2, 2,132,132, 2, 2, 2, 2,132,132, 3, 3,
+ 3, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
+ 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3,
+ 2, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 3, 3, 3, 2, 3, 2, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 2,
+ 2, 2, 2, 2, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 0, 0, 13, 2, 2, 2, 2, 2, 2, 2, 13, 13,
+ 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13,
+ 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33,
+ 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44,
+ 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48,
+ 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69,
+ 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,100,101,102,103, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0,
+ 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0,
+ 110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131,
+ 132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,
+ 148,149,150,151,152,153,154,155,156,157, 0, 0, 0,158,159,160,
+ 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,175,176,
+ 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
+ 193,194,195,196,197,198,199,200,201,202,203,204,205,206, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
+};
+static const uint16_t
+_hb_ucd_u16[9200] =
+{
+ 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12,
+ 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23,
+ 13, 13, 13, 24, 25, 11, 11, 11, 11, 26, 11, 27, 28, 29, 30, 31,
+ 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 11, 37, 38, 13, 39,
+ 9, 9, 9, 11, 11, 11, 13, 13, 40, 13, 13, 13, 41, 13, 13, 13,
+ 13, 13, 13, 42, 9, 43, 11, 11, 44, 45, 32, 46, 47, 48, 49, 50,
+ 51, 52, 48, 48, 53, 32, 54, 55, 48, 48, 48, 48, 48, 56, 57, 58,
+ 59, 60, 48, 32, 61, 48, 48, 48, 48, 48, 62, 63, 64, 48, 65, 66,
+ 48, 67, 68, 69, 48, 70, 71, 48, 72, 73, 48, 48, 74, 32, 75, 32,
+ 76, 48, 48, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 83, 84, 91, 92, 93, 94, 95, 96, 97, 84, 98, 99, 100, 88, 101,
+ 102, 83, 84, 103, 104, 105, 88, 106, 107, 108, 109, 110, 111, 112, 94, 113,
+ 114, 115, 84, 116, 117, 118, 88, 119, 120, 115, 84, 121, 122, 123, 88, 124,
+ 125, 115, 48, 126, 127, 128, 88, 129, 130, 131, 48, 132, 133, 134, 94, 135,
+ 136, 48, 48, 137, 138, 139, 140, 140, 141, 48, 142, 143, 144, 145, 140, 140,
+ 146, 147, 148, 149, 150, 48, 151, 152, 153, 154, 32, 155, 156, 157, 140, 140,
+ 48, 48, 158, 159, 160, 161, 162, 163, 164, 165, 9, 9, 166, 11, 11, 167,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 168, 169, 48, 48,
+ 168, 48, 48, 170, 171, 172, 48, 48, 48, 171, 48, 48, 48, 173, 174, 175,
+ 48, 176, 9, 9, 9, 9, 9, 177, 178, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 179, 48, 180, 181, 48, 48, 48, 48, 182, 183,
+ 48, 184, 48, 185, 48, 186, 187, 188, 48, 48, 48, 189, 190, 191, 192, 193,
+ 194, 192, 48, 48, 195, 48, 48, 196, 197, 48, 198, 48, 48, 48, 48, 199,
+ 48, 200, 201, 202, 203, 48, 204, 205, 48, 48, 206, 48, 207, 208, 209, 209,
+ 48, 210, 48, 48, 48, 211, 212, 213, 192, 192, 214, 215, 216, 140, 140, 140,
+ 217, 48, 48, 218, 219, 160, 220, 221, 222, 48, 223, 64, 48, 48, 224, 225,
+ 48, 48, 226, 227, 228, 64, 48, 229, 230, 9, 9, 231, 232, 233, 234, 235,
+ 11, 11, 236, 27, 27, 27, 237, 238, 11, 239, 27, 27, 32, 32, 32, 32,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 240, 13, 13, 13, 13, 13, 13,
+ 241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
+ 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
+ 279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282,
+ 209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271,
+ 271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209,
+ 209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209,
+ 209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
+ 300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305,
+ 209, 306, 209, 209, 209, 209, 209, 209, 9, 9, 9, 11, 11, 11, 307, 308,
+ 13, 13, 13, 13, 13, 13, 309, 310, 11, 11, 311, 48, 48, 48, 312, 313,
+ 48, 314, 315, 315, 315, 315, 32, 32, 316, 317, 318, 319, 320, 321, 140, 140,
+ 209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 325,
+ 326, 327, 328, 329, 136, 48, 48, 48, 48, 330, 178, 48, 48, 48, 48, 331,
+ 332, 48, 48, 136, 48, 48, 48, 48, 200, 333, 48, 48, 209, 209, 323, 48,
+ 209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
+ 48, 48, 48, 48, 209, 209, 209, 209, 48, 338, 48, 48, 48, 48, 48, 48,
+ 151, 209, 209, 209, 287, 48, 48, 229, 339, 48, 340, 140, 13, 13, 341, 342,
+ 13, 343, 48, 48, 48, 48, 344, 345, 31, 346, 347, 348, 13, 13, 13, 349,
+ 350, 351, 352, 353, 354, 355, 140, 356, 357, 48, 358, 359, 48, 48, 48, 360,
+ 361, 48, 48, 362, 363, 192, 32, 364, 64, 48, 365, 48, 366, 367, 48, 151,
+ 76, 48, 48, 368, 369, 370, 371, 372, 48, 48, 373, 374, 375, 376, 48, 377,
+ 48, 48, 48, 378, 379, 380, 381, 382, 383, 384, 315, 11, 11, 385, 386, 11,
+ 11, 11, 11, 11, 48, 48, 387, 192, 48, 48, 388, 48, 389, 48, 48, 206,
+ 390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391,
+ 48, 48, 48, 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 207, 140, 140,
+ 392, 393, 394, 395, 396, 48, 48, 48, 48, 48, 48, 397, 398, 399, 48, 48,
+ 48, 48, 48, 400, 209, 48, 48, 48, 48, 401, 48, 48, 402, 140, 140, 403,
+ 32, 404, 32, 405, 406, 407, 408, 409, 48, 48, 48, 48, 48, 48, 48, 410,
+ 411, 2, 3, 4, 5, 412, 413, 414, 48, 415, 48, 200, 416, 417, 418, 419,
+ 420, 48, 172, 421, 204, 204, 140, 140, 48, 48, 48, 48, 48, 48, 48, 71,
+ 422, 271, 271, 423, 272, 272, 272, 424, 425, 426, 427, 140, 140, 209, 209, 428,
+ 140, 140, 140, 140, 140, 140, 140, 140, 48, 151, 48, 48, 48, 100, 429, 430,
+ 48, 48, 431, 48, 432, 48, 48, 433, 48, 434, 48, 48, 435, 436, 140, 140,
+ 9, 9, 437, 11, 11, 48, 48, 48, 48, 204, 192, 9, 9, 438, 11, 439,
+ 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
+ 48, 48, 48, 314, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140,
+ 448, 48, 48, 449, 48, 450, 48, 451, 48, 200, 452, 140, 140, 140, 48, 453,
+ 48, 454, 48, 455, 140, 140, 140, 140, 48, 48, 48, 456, 271, 457, 271, 271,
+ 458, 459, 48, 460, 461, 462, 48, 463, 48, 464, 140, 140, 465, 48, 466, 467,
+ 48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140,
+ 48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474,
+ 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
+ 48, 48, 477, 478, 140, 140, 140, 140, 48, 464, 479, 48, 62, 480, 140, 48,
+ 481, 140, 140, 48, 482, 140, 48, 314, 483, 48, 48, 484, 485, 457, 486, 487,
+ 222, 48, 48, 488, 489, 48, 196, 192, 490, 48, 491, 492, 493, 48, 48, 494,
+ 222, 48, 48, 495, 496, 497, 498, 499, 48, 97, 500, 501, 140, 140, 140, 140,
+ 502, 503, 504, 48, 48, 505, 506, 192, 507, 83, 84, 508, 509, 510, 511, 512,
+ 48, 48, 48, 513, 514, 515, 478, 140, 48, 48, 48, 516, 517, 192, 140, 140,
+ 48, 48, 518, 519, 520, 521, 140, 140, 48, 48, 48, 522, 523, 192, 524, 140,
+ 48, 48, 525, 526, 192, 140, 140, 140, 48, 173, 527, 528, 314, 140, 140, 140,
+ 48, 48, 500, 529, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 530,
+ 531, 532, 48, 533, 534, 192, 140, 140, 140, 140, 535, 48, 48, 536, 537, 140,
+ 538, 48, 48, 539, 540, 541, 48, 48, 542, 543, 544, 48, 48, 48, 48, 196,
+ 84, 48, 518, 545, 546, 148, 175, 547, 48, 548, 549, 550, 140, 140, 140, 140,
+ 551, 48, 48, 552, 553, 192, 554, 48, 555, 556, 192, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 48, 557, 140, 140, 140, 100, 271, 558, 559, 560,
+ 48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 561, 562,
+ 48, 48, 48, 48, 388, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 563,
+ 48, 48, 200, 564, 140, 140, 140, 140, 48, 48, 48, 48, 314, 140, 140, 140,
+ 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 565,
+ 48, 48, 48, 566, 567, 568, 569, 570, 48, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 9, 9, 11, 11, 271, 571, 140, 140, 140, 140, 140, 140,
+ 48, 48, 48, 48, 572, 573, 574, 574, 575, 576, 140, 140, 140, 140, 577, 578,
+ 48, 48, 48, 48, 48, 48, 48, 440, 48, 48, 48, 48, 48, 199, 140, 140,
+ 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 579,
+ 48, 48, 580, 140, 140, 580, 581, 48, 48, 48, 48, 48, 48, 48, 48, 206,
+ 48, 48, 48, 48, 48, 48, 71, 151, 196, 582, 583, 140, 140, 140, 140, 140,
+ 32, 32, 584, 32, 585, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
+ 209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 586, 209, 209, 209, 587, 588,
+ 589, 209, 590, 209, 209, 209, 288, 140, 209, 209, 209, 209, 591, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 271, 592, 209, 209, 209, 209, 209, 287, 271, 461,
+ 9, 593, 11, 594, 595, 596, 241, 9, 597, 598, 599, 600, 601, 9, 593, 11,
+ 602, 603, 11, 604, 605, 606, 607, 9, 608, 11, 9, 593, 11, 594, 595, 11,
+ 241, 9, 597, 607, 9, 608, 11, 9, 593, 11, 609, 9, 610, 611, 612, 613,
+ 11, 614, 9, 615, 616, 617, 618, 11, 619, 9, 620, 11, 621, 622, 622, 622,
+ 32, 32, 32, 623, 32, 32, 624, 625, 626, 627, 45, 140, 140, 140, 140, 140,
+ 628, 629, 140, 140, 140, 140, 140, 140, 630, 631, 632, 140, 140, 140, 140, 140,
+ 48, 48, 151, 633, 634, 140, 140, 140, 140, 48, 635, 140, 48, 48, 636, 637,
+ 140, 140, 140, 140, 140, 140, 638, 200, 48, 48, 48, 48, 639, 585, 140, 140,
+ 9, 9, 597, 11, 640, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 498,
+ 271, 271, 641, 642, 140, 140, 140, 140, 498, 271, 643, 644, 140, 140, 140, 140,
+ 645, 48, 646, 647, 648, 649, 650, 651, 652, 206, 653, 206, 140, 140, 140, 654,
+ 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 655, 655, 655, 209, 324,
+ 656, 209, 209, 209, 209, 209, 209, 209, 209, 209, 657, 140, 140, 140, 658, 209,
+ 659, 209, 209, 325, 660, 661, 324, 140, 209, 209, 209, 209, 209, 209, 209, 662,
+ 209, 209, 209, 209, 209, 663, 426, 426, 209, 209, 209, 209, 209, 209, 209, 323,
+ 209, 209, 209, 209, 209, 660, 325, 427, 325, 209, 209, 209, 664, 176, 209, 209,
+ 664, 209, 657, 661, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 657, 665,
+ 287, 209, 426, 288, 324, 176, 664, 287, 209, 666, 209, 209, 288, 140, 140, 192,
+ 48, 48, 48, 48, 48, 48, 140, 140, 48, 48, 48, 196, 48, 48, 48, 48,
+ 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 478, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 100, 140, 48, 204, 140, 140, 140, 140, 140, 140,
+ 48, 48, 48, 48, 71, 140, 140, 140, 667, 140, 668, 668, 668, 668, 668, 668,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140,
+ 391, 391, 391, 391, 391, 391, 391, 669, 391, 391, 391, 391, 391, 391, 391, 670,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3,
+ 0, 0, 0, 0, 0, 4, 0, 4, 2, 2, 5, 2, 2, 2, 5, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 6, 0, 0, 0, 0, 7, 8, 0, 0,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 11,
+ 12, 13, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, 16, 17, 14, 14,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 20, 21, 21, 21, 22, 20, 21, 21, 21, 21,
+ 21, 23, 24, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 27, 28, 26,
+ 29, 30, 31, 32, 31, 31, 31, 31, 33, 34, 35, 31, 31, 31, 36, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 29, 31, 31, 31, 31,
+ 37, 38, 37, 37, 37, 37, 37, 37, 37, 39, 31, 31, 31, 31, 31, 31,
+ 40, 40, 40, 40, 40, 40, 41, 26, 42, 42, 42, 42, 42, 42, 42, 43,
+ 44, 44, 44, 44, 44, 45, 44, 46, 47, 47, 47, 48, 37, 49, 31, 31,
+ 31, 50, 51, 31, 31, 31, 31, 31, 31, 31, 31, 31, 52, 31, 31, 31,
+ 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 53, 55, 53, 53, 53,
+ 56, 57, 58, 59, 59, 60, 61, 62, 57, 63, 64, 65, 66, 59, 59, 67,
+ 68, 69, 70, 71, 71, 72, 73, 74, 69, 75, 76, 77, 78, 71, 79, 26,
+ 80, 81, 82, 83, 83, 84, 85, 86, 81, 87, 88, 26, 89, 83, 90, 91,
+ 92, 93, 94, 95, 95, 96, 97, 98, 93, 99, 100, 101, 102, 95, 95, 26,
+ 103, 104, 105, 106, 107, 104, 108, 109, 104, 105, 110, 26, 111, 108, 108, 112,
+ 113, 114, 115, 113, 113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113,
+ 122, 123, 124, 122, 122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130, 26,
+ 131, 132, 133, 131, 131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131,
+ 136, 137, 138, 139, 137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145, 26,
+ 146, 147, 147, 147, 147, 147, 147, 148, 147, 147, 147, 149, 26, 26, 26, 26,
+ 150, 151, 152, 152, 153, 152, 152, 154, 155, 154, 152, 156, 26, 26, 26, 26,
+ 157, 157, 157, 157, 157, 157, 157, 157, 157, 158, 157, 157, 157, 159, 158, 157,
+ 157, 157, 157, 158, 157, 157, 157, 160, 157, 160, 161, 162, 26, 26, 26, 26,
+ 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
+ 163, 163, 163, 163, 164, 164, 164, 164, 165, 166, 164, 164, 164, 164, 164, 167,
+ 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+ 169, 169, 169, 169, 169, 169, 169, 169, 169, 170, 171, 170, 169, 169, 169, 169,
+ 169, 170, 169, 169, 169, 169, 170, 171, 170, 169, 171, 169, 169, 169, 169, 169,
+ 169, 169, 170, 169, 169, 169, 169, 169, 169, 169, 169, 172, 169, 169, 169, 173,
+ 169, 169, 169, 174, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 176,
+ 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
+ 178, 178, 178, 179, 180, 180, 180, 180, 180, 180, 180, 180, 180, 181, 180, 182,
+ 183, 183, 184, 185, 186, 186, 187, 26, 188, 188, 189, 26, 190, 191, 192, 26,
+ 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 194, 193, 195, 193, 195,
+ 196, 197, 197, 198, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 199,
+ 197, 197, 197, 197, 197, 200, 177, 177, 177, 177, 177, 177, 177, 177, 201, 26,
+ 202, 202, 202, 203, 202, 204, 202, 204, 205, 202, 206, 206, 206, 207, 208, 26,
+ 209, 209, 209, 209, 209, 210, 209, 209, 209, 211, 209, 212, 193, 193, 193, 193,
+ 213, 213, 213, 214, 215, 215, 215, 215, 215, 215, 215, 216, 215, 215, 215, 217,
+ 215, 218, 215, 218, 215, 219, 9, 9, 9, 220, 26, 26, 26, 26, 26, 26,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 222, 221, 221, 221, 221, 221, 223,
+ 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227,
+ 228, 228, 228, 228, 228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231,
+ 18, 232, 164, 164, 164, 164, 164, 233, 224, 26, 234, 9, 235, 236, 237, 238,
+ 2, 2, 2, 2, 239, 240, 2, 2, 2, 2, 2, 241, 242, 243, 2, 244,
+ 2, 2, 2, 2, 2, 2, 2, 245, 9, 9, 9, 9, 9, 9, 9, 9,
+ 14, 14, 246, 246, 14, 14, 14, 14, 246, 246, 14, 247, 14, 14, 14, 246,
+ 14, 14, 14, 14, 14, 14, 248, 14, 248, 14, 249, 250, 14, 14, 251, 252,
+ 0, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 255, 256,
+ 0, 257, 2, 258, 0, 0, 0, 0, 259, 26, 9, 9, 9, 9, 260, 26,
+ 0, 0, 0, 0, 261, 262, 4, 0, 0, 263, 0, 0, 2, 2, 2, 2,
+ 2, 264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 257, 26, 26, 26, 0, 265, 26, 26, 0, 0, 0, 0,
+ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 0,
+ 0, 0, 268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 2, 2, 2, 2,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 270, 271,
+ 164, 164, 164, 164, 165, 166, 272, 272, 272, 272, 272, 272, 272, 273, 274, 273,
+ 169, 169, 171, 26, 171, 171, 171, 171, 171, 171, 171, 171, 18, 18, 18, 18,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 26, 26, 26, 26,
+ 276, 276, 276, 277, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 278, 26,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 279, 26, 26, 26, 0, 280,
+ 281, 0, 0, 0, 282, 283, 0, 284, 285, 286, 286, 286, 286, 286, 286, 286,
+ 286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291,
+ 292, 293, 293, 293, 293, 293, 294, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+ 168, 295, 0, 0, 293, 293, 293, 293, 0, 0, 0, 0, 280, 26, 290, 290,
+ 168, 168, 168, 295, 0, 0, 0, 0, 0, 0, 0, 0, 168, 168, 168, 296,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 290, 290, 290, 290, 297,
+ 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 0, 0, 0, 0, 0,
+ 276, 276, 276, 276, 276, 276, 276, 276, 0, 0, 0, 0, 0, 0, 0, 0,
+ 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298,
+ 298, 299, 298, 298, 298, 298, 298, 298, 300, 26, 301, 301, 301, 301, 301, 301,
+ 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
+ 302, 302, 302, 302, 302, 303, 26, 26, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 26,
+ 0, 0, 0, 0, 305, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 306, 2, 2, 2, 2, 2, 2, 2, 307, 308, 309, 26, 26, 310, 2,
+ 311, 311, 311, 311, 311, 312, 0, 313, 314, 314, 314, 314, 314, 314, 314, 26,
+ 315, 315, 315, 315, 315, 315, 315, 315, 316, 317, 315, 318, 53, 53, 53, 53,
+ 319, 319, 319, 319, 319, 320, 321, 321, 321, 321, 322, 323, 168, 168, 168, 324,
+ 325, 325, 325, 325, 325, 325, 325, 325, 325, 326, 325, 327, 163, 163, 163, 328,
+ 329, 329, 329, 329, 329, 329, 330, 26, 329, 331, 329, 332, 163, 163, 163, 163,
+ 333, 333, 333, 333, 333, 333, 333, 333, 334, 26, 26, 335, 336, 336, 337, 26,
+ 338, 338, 338, 26, 171, 171, 2, 2, 2, 2, 2, 339, 340, 341, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 336, 336, 336, 336, 336, 342, 336, 343,
+ 168, 168, 168, 168, 344, 26, 168, 168, 295, 345, 168, 168, 168, 168, 168, 344,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 279, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 346, 26, 26, 26, 26,
+ 347, 26, 348, 349, 25, 25, 350, 351, 352, 25, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 353, 26, 354, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 355, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 356, 31, 31, 31, 31, 31, 31, 357, 26, 26, 26, 26, 31, 31,
+ 9, 9, 0, 313, 9, 358, 0, 0, 0, 0, 359, 0, 257, 280, 360, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 361,
+ 362, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, 363, 290, 289, 290,
+ 290, 290, 290, 364, 168, 168, 168, 295, 365, 365, 365, 366, 257, 257, 26, 367,
+ 368, 369, 368, 368, 370, 368, 368, 371, 368, 372, 368, 372, 26, 26, 26, 26,
+ 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 373,
+ 374, 0, 0, 0, 0, 0, 375, 0, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 252, 0, 376, 377, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 378,
+ 379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382, 26, 383, 0, 0, 280,
+ 384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390,
+ 391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395, 26, 26, 26, 26, 26,
+ 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, 397,
+ 398, 398, 398, 399, 398, 400, 401, 401, 401, 401, 402, 401, 401, 401, 401, 402,
+ 403, 403, 403, 403, 403, 26, 404, 404, 404, 404, 404, 404, 405, 406, 407, 408,
+ 407, 408, 409, 407, 410, 407, 410, 411, 26, 26, 26, 26, 26, 26, 26, 26,
+ 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412,
+ 412, 412, 412, 412, 412, 412, 413, 26, 412, 412, 414, 26, 412, 26, 26, 26,
+ 415, 2, 2, 2, 2, 2, 416, 307, 26, 26, 26, 26, 26, 26, 26, 26,
+ 417, 418, 419, 419, 419, 419, 420, 421, 422, 422, 423, 422, 424, 424, 424, 424,
+ 425, 425, 425, 426, 427, 425, 26, 26, 26, 26, 26, 26, 428, 428, 429, 430,
+ 431, 431, 431, 432, 433, 433, 433, 434, 26, 26, 26, 26, 26, 26, 26, 26,
+ 435, 435, 435, 435, 436, 436, 436, 437, 436, 436, 438, 436, 436, 436, 436, 436,
+ 439, 440, 441, 442, 443, 443, 444, 445, 443, 446, 443, 446, 447, 447, 447, 447,
+ 448, 448, 448, 448, 26, 26, 26, 26, 449, 449, 449, 449, 450, 451, 450, 26,
+ 452, 452, 452, 452, 452, 452, 453, 454, 455, 455, 456, 455, 457, 457, 458, 457,
+ 459, 459, 460, 461, 26, 462, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 463, 463, 463, 463, 463, 463, 463, 463, 463, 464, 26, 26, 26, 26, 26, 26,
+ 465, 465, 465, 465, 465, 465, 466, 26, 465, 465, 465, 465, 465, 465, 466, 467,
+ 468, 468, 468, 468, 468, 26, 468, 469, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 50,
+ 470, 470, 470, 470, 470, 471, 472, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 473, 473, 473, 473, 473, 26, 474, 474, 474, 474, 474, 475, 26, 26, 476, 476,
+ 476, 477, 26, 26, 26, 26, 478, 478, 478, 479, 26, 26, 480, 480, 481, 26,
+ 482, 482, 482, 482, 482, 482, 482, 482, 482, 483, 484, 482, 482, 482, 483, 485,
+ 486, 486, 486, 486, 486, 486, 486, 486, 487, 488, 489, 489, 489, 490, 489, 491,
+ 492, 492, 492, 492, 492, 492, 493, 492, 492, 26, 494, 494, 494, 494, 495, 26,
+ 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 497, 137, 498, 26,
+ 499, 499, 500, 499, 499, 499, 499, 501, 26, 26, 26, 26, 26, 26, 26, 26,
+ 502, 503, 504, 505, 504, 506, 507, 507, 507, 507, 507, 507, 507, 508, 507, 509,
+ 510, 511, 512, 513, 513, 514, 515, 516, 511, 517, 518, 519, 520, 521, 521, 26,
+ 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 523, 524, 26, 26, 26,
+ 525, 525, 525, 525, 525, 525, 525, 525, 525, 26, 525, 526, 26, 26, 26, 26,
+ 527, 527, 527, 527, 527, 527, 528, 527, 527, 527, 527, 528, 26, 26, 26, 26,
+ 529, 529, 529, 529, 529, 529, 529, 529, 530, 26, 529, 531, 197, 532, 26, 26,
+ 533, 533, 533, 533, 533, 533, 533, 534, 533, 534, 26, 26, 26, 26, 26, 26,
+ 535, 535, 535, 536, 535, 537, 535, 535, 538, 26, 26, 26, 26, 26, 26, 26,
+ 539, 539, 539, 539, 539, 539, 539, 540, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 542, 543,
+ 544, 545, 546, 547, 547, 547, 548, 549, 544, 26, 547, 550, 26, 26, 26, 26,
+ 26, 26, 26, 26, 551, 552, 551, 551, 551, 551, 551, 552, 553, 26, 26, 26,
+ 554, 554, 554, 554, 554, 554, 554, 554, 554, 26, 555, 555, 555, 555, 555, 555,
+ 555, 555, 555, 555, 556, 26, 177, 177, 557, 557, 557, 557, 557, 557, 557, 558,
+ 559, 560, 559, 559, 559, 559, 561, 559, 562, 26, 559, 559, 559, 563, 564, 564,
+ 564, 564, 565, 564, 564, 566, 567, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 568, 569, 570, 570, 570, 570, 568, 571, 570, 26, 570, 572, 573, 574, 575, 575,
+ 575, 576, 577, 578, 575, 579, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 580, 580, 580, 581,
+ 26, 26, 26, 26, 26, 26, 582, 26, 108, 108, 108, 108, 108, 108, 583, 584,
+ 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585,
+ 585, 585, 585, 586, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 587, 588, 26,
+ 585, 585, 585, 585, 585, 585, 585, 585, 589, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 591, 26,
+ 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592,
+ 592, 592, 592, 592, 592, 593, 592, 594, 26, 26, 26, 26, 26, 26, 26, 26,
+ 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595,
+ 595, 595, 595, 595, 595, 595, 595, 595, 596, 26, 26, 26, 26, 26, 26, 26,
+ 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304,
+ 304, 304, 304, 304, 304, 304, 304, 597, 598, 598, 598, 599, 598, 600, 601, 601,
+ 601, 601, 601, 601, 601, 601, 601, 602, 601, 603, 604, 604, 604, 605, 605, 26,
+ 606, 606, 606, 606, 606, 606, 606, 606, 607, 26, 606, 608, 608, 606, 606, 609,
+ 606, 606, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 610, 610, 610, 610, 610, 610, 610, 610,
+ 610, 610, 610, 611, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 612, 612, 612, 612, 612, 612, 612, 612, 612, 613, 612, 612, 612, 612, 612, 612,
+ 612, 614, 612, 612, 26, 26, 26, 26, 26, 26, 26, 26, 615, 26, 346, 26,
+ 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616,
+ 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 26,
+ 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617,
+ 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 618, 26, 26, 26, 26, 26,
+ 616, 619, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 620, 621,
+ 622, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
+ 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
+ 286, 286, 286, 286, 623, 26, 26, 26, 26, 26, 624, 26, 625, 26, 626, 626,
+ 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626,
+ 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 627,
+ 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 629, 628, 630,
+ 628, 631, 628, 632, 280, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 9, 9, 9, 9, 9, 633, 9, 9, 220, 26, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 280, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 26,
+ 0, 0, 0, 0, 257, 362, 0, 0, 0, 0, 0, 0, 634, 635, 0, 636,
+ 637, 638, 0, 0, 0, 639, 0, 0, 0, 0, 0, 0, 0, 265, 26, 26,
+ 14, 14, 14, 14, 14, 14, 14, 14, 246, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 280, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 257, 26, 0, 0, 0, 259,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0,
+ 0, 0, 0, 254, 640, 641, 0, 642, 643, 0, 0, 0, 0, 0, 0, 0,
+ 268, 644, 254, 254, 0, 0, 0, 645, 646, 647, 648, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 0, 0, 0, 0, 0, 0,
+ 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649,
+ 649, 650, 26, 651, 652, 649, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 2, 2, 2, 347, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 653, 269, 269, 654, 655, 656, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 657, 657, 657, 657, 657, 658, 657, 659, 657, 660, 26, 26, 26, 26, 26, 26,
+ 26, 26, 661, 661, 661, 662, 26, 26, 663, 663, 663, 663, 663, 663, 663, 664,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 171, 665, 169, 171,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 667, 666, 668, 26, 26, 26, 26, 26,
+ 669, 669, 669, 669, 669, 669, 669, 669, 669, 670, 669, 671, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 362, 0,
+ 0, 0, 0, 0, 0, 0, 376, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 362, 0, 0, 0, 0, 0, 0, 275, 26, 26, 26, 26, 26, 26, 26, 26,
+ 672, 31, 31, 31, 673, 674, 675, 676, 677, 678, 673, 679, 673, 675, 675, 680,
+ 31, 681, 31, 682, 683, 681, 31, 682, 26, 26, 26, 26, 26, 26, 51, 26,
+ 0, 0, 0, 0, 0, 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 280, 26, 0, 257, 362, 0, 362, 0, 362, 0, 0, 0, 275, 26,
+ 0, 0, 0, 0, 0, 275, 26, 26, 26, 26, 26, 26, 684, 0, 0, 0,
+ 685, 26, 0, 0, 0, 0, 0, 280, 0, 259, 313, 26, 275, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 686, 0, 376, 0, 376,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259, 0, 280, 259, 26,
+ 0, 280, 0, 0, 0, 0, 0, 0, 0, 26, 0, 313, 0, 0, 0, 0,
+ 0, 26, 0, 0, 0, 275, 313, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280, 26, 0, 275, 376, 376,
+ 257, 26, 0, 0, 0, 376, 0, 265, 275, 26, 0, 313, 0, 26, 257, 26,
+ 0, 0, 359, 0, 0, 0, 0, 0, 0, 265, 26, 26, 26, 26, 0, 313,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 26, 26, 26, 26,
+ 276, 276, 276, 276, 276, 276, 276, 687, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 279, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 346, 26, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 687, 26, 26, 26,
+ 276, 276, 276, 279, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 688, 26, 26, 26, 26, 26, 26,
+ 689, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
+ 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0,
+ 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
+ 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303,
+ 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
+ 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
+ 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199,
+ 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0,
+ 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231,
+ 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
+ 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275,
+ 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0,
+ 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093,
+ 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010,
+ 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347,
+ 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
+ 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365,
+ 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
+ 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182,
+ 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
+ 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 8, 9, 0, 10,1425, 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, 1, 0,
+ 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461,
+ 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486,
+ 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0,
+ 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0,
+ 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0,
+ 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553,
+ 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560,
+ 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0,
+ 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0,
+ 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627,
+ 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0,
+ 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0,
+ 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0,
+ 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0,
+ 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0,
+ 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0,
+ 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0,
+ 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0,
+ 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
+ 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
+ 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
+ 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
+ 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
+ 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
+ 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
+ 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
+ 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
+ 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0,
+ 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
+ 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
+ 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
+ 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
+ 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
+ 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0,
+ 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
+ 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0,
+ 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
+ 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
+ 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0,
+ 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793,
+ 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
+ 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0,
+ 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
+ 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
+ 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
+ 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0,
+ 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828,
+ 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833,
+ 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3,
+ 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0,
+ 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838,
+ 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0,
+ 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0,
+ 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938,
+ 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0,
+ 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870,
+ 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0,
+ 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0,
+ 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0,
+ 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0,
+ 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0,
+ 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0,
+ 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0,
+ 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0,
+ 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0,
+ 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
+ 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
+ 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
+ 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
+ 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
+ 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
+ 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
+ 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
+ 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
+ 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
+ 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
+ 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
+ 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
+ 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
+ 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
+ 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
+ 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0,
+ 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0,
+ 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773,
+ 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
+ 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
+ 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
+ 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0,
+ 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
+ 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
+ 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
+ 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
+ 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
+ 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
+ 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575,
+ 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0,
+ 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950,
+ 1951,1952,1953,1954,1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959,
+ 1961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131,
+ 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37,
+ 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
+ 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
+ 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
+ 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
+ 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259,
+ 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
+ 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934,
+ 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312,
+ 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
+ 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
+ 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381,
+ 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399,
+ 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417,
+ 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
+ 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460,
+ 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
+ 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505,
+ 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64,
+ 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538,
+ 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567,
+ 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592,
+ 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
+ 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627,
+ 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
+ 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83,
+ 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85,
+ 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696,
+ 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
+ 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90,
+ 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787,
+ 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807,
+ 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0,
+};
+static const int16_t
+_hb_ucd_i16[196] =
+{
+ 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2,
+ 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1,
+ 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3,
+ -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0,
+ 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0,
+ 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0,
+ 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0,
+ 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0,
+ 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1,
+ -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0,
+ 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106,
+ -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1,
+ -1, 0, 1, -1,
+};
+
+static inline uint_fast8_t
+_hb_ucd_gc (unsigned u)
+{
+ return u<1114110u?_hb_ucd_u8[6664+(((_hb_ucd_u8[1296+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+}
+static inline uint_fast8_t
+_hb_ucd_ccc (unsigned u)
+{
+ return u<125259u?_hb_ucd_u8[8612+(((_hb_ucd_u8[8068+(((_hb_ucd_u8[7624+(((_hb_ucd_u8[7288+(((_hb_ucd_u8[7042+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+}
+static inline unsigned
+_hb_ucd_b4 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline int_fast16_t
+_hb_ucd_bmg (unsigned u)
+{
+ return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9356+(((_hb_ucd_u8[9236+(((_hb_ucd_b4(9108+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
+}
+static inline uint_fast8_t
+_hb_ucd_sc (unsigned u)
+{
+ return u<918000u?_hb_ucd_u8[10862+(((_hb_ucd_u16[2000+(((_hb_ucd_u8[10142+(((_hb_ucd_u8[9692+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
+}
+static inline uint_fast16_t
+_hb_ucd_dm (unsigned u)
+{
+ return u<195102u?_hb_ucd_u16[5888+(((_hb_ucd_u8[16764+(((_hb_ucd_u8[16382+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+}
+
+
#else
static const uint8_t
-_hb_ucd_u8[13602] =
+_hb_ucd_u8[13246] =
{
0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 7, 11, 12, 12, 12, 13,
@@ -6145,331 +5025,309 @@ _hb_ucd_u8[13602] =
220, 0, 0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9,
7, 0, 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0,
1, 0, 0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,
- 216, 0,220,220,220, 0,230,230, 7, 0, 16, 17, 17, 17, 17, 17,
- 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,129,169,
- 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 216, 0,220,220,220, 0,230,230, 7, 0, 16, 17, 17, 33, 17, 49,
+ 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17,177, 0, 1, 2, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3,
+ 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 6, 7, 8, 3, 3, 3,
+ 3, 3, 9, 10, 11, 12, 13, 3, 3, 3, 3, 3, 3, 3, 3, 14,
+ 3, 15, 3, 3, 3, 3, 3, 3, 16, 17, 18, 19, 20, 21, 3, 3,
+ 3, 22, 23, 24, 3, 3, 3, 3, 3, 3, 25, 3, 3, 3, 3, 3,
+ 3, 3, 3, 26, 3, 3, 27, 28, 0, 1, 0, 0, 0, 0, 0, 1,
+ 0, 2, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4,
+ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 9, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 10, 11, 12, 13, 0, 0, 14, 15, 16, 6, 0, 17, 18,
+ 19, 19, 19, 20, 21, 22, 23, 24, 19, 25, 0, 26, 27, 19, 19, 28,
+ 29, 30, 0, 31, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 19,
+ 28, 0, 32, 33, 9, 34, 35, 19, 0, 0, 36, 37, 38, 39, 40, 19,
+ 0, 41, 42, 43, 44, 31, 0, 1, 45, 42, 0, 0, 0, 0, 0, 32,
+ 14, 14, 0, 0, 0, 0, 14, 0, 0, 46, 47, 47, 47, 47, 48, 49,
+ 47, 47, 47, 47, 50, 51, 52, 53, 43, 21, 0, 0, 0, 0, 0, 0,
+ 0, 54, 6, 55, 0, 14, 19, 1, 0, 0, 0, 0, 56, 57, 0, 0,
+ 0, 0, 0, 19, 58, 31, 0, 0, 0, 0, 0, 0, 0, 59, 14, 0,
+ 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 60, 61, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3, 0, 4,
+ 5, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 1, 1, 0, 0, 8,
+ 9, 0, 8, 9, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0, 0, 0,
+ 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 1, 0, 0, 18,
+ 19, 0, 0, 0, 20, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 0, 8, 21, 9, 0, 0, 22, 0, 0, 0, 0, 1,
+ 0, 23, 24, 25, 0, 0, 26, 0, 0, 0, 8, 21, 27, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0, 1, 28, 29, 30, 0, 31, 32, 20, 1, 1,
+ 0, 0, 0, 8, 21, 9, 1, 4, 5, 0, 0, 0, 33, 9, 0, 1,
+ 1, 1, 0, 8, 21, 21, 21, 21, 34, 1, 35, 21, 21, 21, 9, 36,
+ 0, 0, 37, 38, 1, 0, 39, 0, 0, 0, 1, 0, 1, 0, 0, 0,
+ 0, 8, 21, 9, 1, 0, 0, 0, 40, 0, 8, 21, 21, 21, 21, 21,
+ 21, 21, 21, 9, 0, 1, 1, 1, 1, 8, 21, 21, 21, 9, 0, 0,
+ 0, 41, 0, 42, 43, 0, 0, 0, 1, 44, 0, 0, 0, 45, 8, 9,
+ 1, 0, 0, 0, 8, 21, 21, 21, 9, 0, 1, 0, 1, 1, 8, 21,
+ 21, 9, 0, 4, 5, 8, 9, 1, 0, 0, 0, 1, 2, 3, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 3, 3, 3, 3, 3, 3,
+ 3, 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17,237, 0, 1, 2, 2, 0, 3,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 7, 8, 9, 0,
- 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 20, 0, 0, 21, 22, 0, 0, 0, 0, 23, 24,
- 25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0,
- 0, 33, 34, 35, 36, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 1, 2, 40, 41, 0, 1,
- 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
- 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 5, 0, 0, 0,
- 6, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0,
- 8, 9, 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0,
- 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0, 0, 0,
- 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7, 20, 20,
- 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0, 20, 20,
- 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1, 28, 29,
- 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0,
- 0, 0, 0, 0, 20, 20, 20, 1, 0, 0, 8, 21, 32, 4, 0, 10,
- 0, 33, 7, 20, 20, 20, 0, 0, 0, 0, 8, 34, 34, 35, 36, 34,
- 37, 0, 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8, 21, 1,
- 20, 0, 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 8, 21, 0, 1,
- 0, 1, 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,
- 0, 42, 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0, 0, 0,
- 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 20, 20, 1, 20,
- 20, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 11, 12, 12, 12,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 12, 21, 12, 12, 12, 12, 22,
- 23, 23, 23, 24, 12, 12, 12, 25, 26, 27, 12, 28, 29, 30, 31, 32,
- 33, 34, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 35,
- 12, 36, 7, 7, 37, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 38, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 29, 30, 31, 32, 32, 33, 33, 33, 34, 35, 35, 35, 35,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
- 2, 2, 51, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 57, 57, 56, 56, 56, 56, 56, 56, 58, 59, 60, 61,
- 56, 62, 62, 63, 64, 65, 66, 67, 68, 69, 70, 56, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 71,
- 62, 62, 62, 62, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 74, 74,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 62, 62, 62, 62, 88, 89, 89, 89, 90, 89,
- 91, 92, 93, 94, 95, 95, 96, 97, 87, 98, 99,100,101,102,103,104,
- 105,105,105, 2,106,107,108,109,110,111,112,113,114,115,116, 87,
- 89,117,118,119,120,121,122,123,124,125,126, 87,127,128, 87,129,
- 130,131,132, 87,133,134,135,136,137,138, 87, 87,139,140,141,142,
- 87,143, 87,144,145,145,145,145,145,145,145,145,145,145,145, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87,146,147,147,147,147,147,147,147,147,147, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,148,148,148,148,
- 148, 87, 87, 87,149,149,149,149,150,151,152,152, 87, 87, 87, 87,
- 153,153,154,155,156,156,156,156,156,156,156,156,156,156,156,156,
- 156,156,156,156,156,156,156,156,156,156,157,157,157,157,156, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87,158,159,160,161,162,162,162, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,163,164, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87,165, 56, 56, 56,166,167, 51, 56, 56, 87, 56, 56, 56, 56,
- 56, 56, 56, 56,168,168,168,168,168,168, 87, 87, 87, 87, 87, 87,
- 87, 87, 2, 87,169, 87,170, 87, 87,171, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 33,172,172,173, 87, 87, 87, 87, 87, 56, 56, 56, 87,
- 89, 89, 87, 87, 56, 56, 56, 56,174, 87, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 87, 87, 87, 87,
- 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87,
- 87, 87, 87, 87, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 56, 87,175,175, 0, 1, 2, 2, 0, 1, 2, 2,
- 2, 3, 4, 5, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3,
- 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6,
- 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11,
- 11, 11, 12, 11, 13, 13, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 15, 16, 16, 16, 16, 16, 17, 18, 18,
- 18, 18, 18, 18, 19, 20, 21, 21, 22, 23, 21, 24, 21, 21, 21, 21,
- 21, 25, 21, 21, 26, 26, 26, 26, 26, 21, 21, 21, 27, 27, 27, 27,
- 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 26, 21, 21, 21, 21, 21,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 0, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 17,
+ 18, 17, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 24, 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, 25, 25, 26, 27,
+ 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 31,
+ 31, 31, 31, 54, 55, 55, 56, 31, 31, 31, 31, 31, 31, 31, 57, 58,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 59, 60, 31, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 63, 64, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 65, 66, 67, 31, 31, 31, 31, 68, 31, 31, 31, 31, 31,
+ 31, 31, 31, 69, 70, 71, 17, 17, 72, 73, 31, 74, 75, 76, 31, 77,
+ 78, 31, 79, 80, 17, 81, 17, 17, 17, 17, 31, 31, 23, 23, 23, 23,
+ 23, 23, 31, 31, 31, 31, 31, 31, 23, 82, 31, 31, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 83, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 84, 0, 0, 1,
+ 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3,
+ 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 11,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 19, 27,
+ 28, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36,
+ 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 42, 43, 44, 44, 45, 46,
+ 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 49, 50, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 51,
+ 60, 61, 62, 63, 64, 65, 66, 7, 67, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 7, 4, 4, 4, 4, 77, 77, 77, 77, 78, 79, 80, 81,
+ 82, 83, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85,
+ 0, 0, 0, 0, 86, 87, 88, 88, 89, 90, 48, 91, 0, 0, 92, 92,
+ 92, 92, 92, 93, 94, 95, 96, 97, 98, 47, 99,100,101,102, 0,103,
+ 104,105, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 0,106,106,106,106,106,106,106,106,106,106,106,107,
+ 108,108,108,108,108, 11,109,110,111, 4,112, 4,113,114,115,116,
+ 117,118,119,120,121,122,123,124,125,126, 50,127, 47, 47, 47, 47,
+ 47, 47, 47, 47,128,128,128,128,128,128,128,128,128,128,128,128,
+ 92, 92, 92, 92, 92, 92, 92, 92,129,130, 19, 19, 19, 19, 19, 19,
+ 131, 19, 19, 19,132,133, 19,134,135,136,137,101,138,138,138,138,
+ 0, 77,139,140,128,128,141,142,143,144,145,146,147,148,149,150,
+ 151,152,153,153,154,154,154,154,154,154, 4, 4,155,156,157,158,
+ 159,160,161,162,163,164,165,166,167,168,169,169,170,170,171,171,
+ 172,172,128,128, 19, 19,173,173,174,175,176,177,178,178,179,180,
+ 181,182,183,184,185,185,186,187,188,189,128,128,190,190,191,191,
+ 128,128,192,192,193,194,195,195,196,196,128,128,197,197,198,198,
+ 199,199,200,200,201,202,203,204,128,128,128,128,205,206,207,207,
+ 208,209,210,210,128,128,211,211,128,128,212, 34,213,213,213,213,
+ 213,213,213,213,213,213,213,213,213,213,128,128,128,128,128,128,
+ 128,128,214,214,215,215,215,215,215,215,215,215,215,215,128,128,
+ 128,128,128,128,216,216,216,216,216,216,216,216,216,216,128,128,
+ 128,128,128,128,110,110,110,110,110,110,110,110,110,217,218,219,
+ 220,220,220,220,221,221,221,221,222,222,222,223,224,224,224,224,
+ 224,224,224,224,224,224,224,224,225,225,225,225,225,225,225,225,
+ 224,224,128,128,128,128,128,128,128,128,104,104,226,227,227,227,
+ 228,229,230,230,230,230,230,230,128,128,128,128,231,231,232, 0,
+ 128,128,128,128,128,128,128,128, 7,233, 0, 0, 0, 0, 0, 0,
+ 0,234,235, 0, 77, 77, 0, 0, 0, 0,128,128,236,236,236,236,
+ 236,236,236,236,236,236,236,236,128,128,128,128,128,128,128,128,
+ 4, 4,128,128, 86, 86,128,128,237,237,128,128,128,128,238,239,
+ 128,128,128,128,128,128,128,128,128,128, 48, 48,240,240,240,240,
+ 241,241,128,128, 0, 0, 0, 0, 0, 0,128,128, 19, 19, 19, 19,
+ 128,128,128,128,242, 0,128,128, 0, 0, 0, 0, 92, 92,128,128,
+ 128,128,128,128, 92, 92, 92, 92, 92, 92,128,128, 0, 0,128,128,
+ 7, 7, 7, 7, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3,
+ 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0,
+ 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, 11, 11, 12, 11,
+ 13, 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 15, 16, 16, 16, 16,
+ 16, 17, 18, 18, 18, 18, 18, 18, 19, 20, 21, 21, 22, 23, 21, 24,
+ 21, 21, 21, 21, 21, 25, 21, 21, 26, 26, 26, 26, 26, 21, 21, 21,
+ 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 26, 21,
21, 21, 31, 21, 32, 32, 32, 32, 32, 33, 34, 32, 35, 35, 35, 35,
- 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37,
- 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39,
- 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41,
- 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43,
- 43, 43, 43, 43, 44, 44, 44, 45, 44, 44, 44, 44, 46, 46, 46, 46,
- 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 48, 47, 47, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50,
- 50, 50, 50, 51, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55,
+ 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39,
+ 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43,
+ 44, 44, 44, 45, 44, 44, 44, 44, 46, 46, 46, 46, 47, 47, 47, 47,
+ 47, 48, 47, 47, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51,
+ 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54,
55, 55, 55, 55, 56, 56, 57, 57, 57, 57, 58, 57, 59, 59, 60, 61,
- 62, 62, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 65, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 55, 55, 55, 55, 55, 67, 67, 67, 67,
- 67, 68, 68, 68, 69, 69, 69, 69, 69, 69, 64, 64, 70, 70, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 8, 8, 8, 8, 8, 72, 72, 72, 72,
+ 62, 62, 63, 63, 64, 64, 64, 64, 65, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 55, 67, 67, 67, 67, 67, 68, 68, 68, 69, 69, 69, 69,
+ 69, 69, 64, 64, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 8,
72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75,
75, 76, 76, 76, 13, 50, 50, 50, 73, 77, 78, 79, 4, 4, 80, 4,
- 4, 81, 82, 83, 4, 4, 4, 84, 8, 8, 8, 8, 11, 11, 11, 11,
- 11, 11, 11, 11, 85, 0, 0, 0, 0, 0, 0, 86, 0, 4, 0, 0,
- 0, 8, 8, 8, 0, 0, 87, 88, 89, 0, 4, 4, 6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 90, 90, 90,
- 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 4, 4, 92, 92, 92, 92,
- 92, 92, 92, 92, 50, 50, 50, 93, 93, 93, 93, 93, 53, 53, 53, 53,
- 53, 53, 13, 13, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 0, 95, 0, 96, 97, 98, 99, 99, 99, 99,100,101,102,
- 102,102,102,103,104,104,104,105, 52, 52, 52, 52, 52, 0,104,104,
- 0, 0, 0,102, 52, 52, 0, 0, 0, 0, 52,106, 0, 0, 0, 0,
- 0,102,102,107,102,102,102,102,102,108, 0, 0, 94, 94, 94, 94,
- 0, 0, 0, 0,109,109,109,109,109,109,109,109,109,109,109,109,
- 109,110,110,110,111,111,111,111,111,111,111,111,111,111,111,111,
- 13, 13, 13, 13, 13, 13,112,112,112,112,112,112, 0, 0,113, 4,
- 4, 4, 4, 4,114, 4, 4, 4, 4, 4, 4, 4,115,115,115, 0,
- 116,116,116,116,117,117,117,117,117,117, 32, 32,118,118,119,120,
- 120,120, 52, 52,121,121,121,121,122,121, 49, 49,123,123,123,123,
- 123,123, 49, 49,124,124,124,124,124,124,125,125, 53, 53, 53, 4,
- 4,126,127, 54, 54, 54, 54, 54,125,125,125,125,128,128,128,128,
- 128,128,128,128, 4,129, 18, 18, 18, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21,130, 21, 21, 21, 21, 8, 0,131, 0,
- 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21,132, 0, 0, 1, 2,
- 1, 2,133,101,102,134, 52, 52, 52, 52, 0, 0,135,135,135,135,
- 135,135,135,135, 0, 0, 0, 0, 11, 11, 11, 11, 11, 0, 11, 11,
- 11, 0, 0,136,137,137,138,138,138,138,139, 0,140,140,140,141,
- 141,142,142,142,143,143,144,144,144,144,144,144,145,145,145,145,
- 145,146,146,146,147,147,147,148,148,148,148,148,149,149,149,150,
- 150,150,150,151,151,151,151,151,151,151,151,151,152,152,152,152,
- 152,152,152,152,153,153,153,153,154,154,155,155,156,156,156,156,
- 156,156,157,157,158,158,159,159,159,159,159,159,160,160,161,161,
- 161,161,161,161,162,162,162,162,162,162,163,163,164,164,164,164,
- 165,165,165,165,166,166,166,166,167,167,168,168,169,169,169,169,
- 169,169,169,169,170,170,170,170,170,170,170,170,171,171,171,171,
- 171,171,171,171,172,172,172,172,172,172,172,172,173,173,173,173,
- 173,173,173,173,174,174,174,175,175,175,175,176,176,176,176,177,
- 177,177,178,178,179,179,179,179,179,179,179,179,180,180,180,180,
- 180,181,181,181,182,182,182,182,182,183,183,183,184,184,184,184,
- 184,184,185, 43,186,186,186,186,186,186,186,186,187,187,187,188,
+ 4, 81, 82, 83, 4, 4, 4, 84, 11, 11, 11, 11, 85, 0, 0, 0,
+ 0, 0, 0, 86, 0, 4, 0, 0, 0, 8, 8, 8, 0, 0, 87, 88,
+ 89, 0, 4, 4, 6, 0, 0, 0, 90, 90, 90, 90, 91, 91, 91, 91,
+ 91, 91, 4, 4, 92, 92, 92, 92, 50, 50, 50, 93, 93, 93, 93, 93,
+ 53, 53, 13, 13, 94, 94, 94, 94, 94, 94, 94, 0, 95, 0, 96, 97,
+ 98, 99, 99, 99, 99,100,101,102,102,102,102,103,104,104,104,105,
+ 52, 0,104,104, 0, 0, 0,102, 52, 52, 0, 0, 0, 0, 52,106,
+ 0,102,102,107,102,102,102,102,102,108, 0, 0,109,109,109,109,
+ 109,110,110,110,111,111,111,111, 13, 13,112,112,112,112,112,112,
+ 0, 0,113, 4,114, 4, 4, 4,115,115,115, 0,116,116,116,116,
+ 117,117,117,117,117,117, 32, 32,118,118,119,120,120,120, 52, 52,
+ 121,121,121,121,122,121, 49, 49,123,123,123,123,123,123, 49, 49,
+ 124,124,124,124,124,124,125,125, 53, 53, 53, 4, 4,126,127, 54,
+ 125,125,125,125,128,128,128,128, 4,129, 18, 18, 18, 21, 21, 21,
+ 21, 21, 21,130, 8, 0,131, 0, 0, 0, 0, 21, 21, 21, 21,132,
+ 0, 0, 1, 2, 1, 2,133,101,102,134, 52, 52,135,135,135,135,
+ 11, 0, 11, 11, 11, 0, 0,136,137,137,138,138,138,138,139, 0,
+ 140,140,140,141,141,142,142,142,143,143,144,144,144,144,144,144,
+ 145,145,145,145,145,146,146,146,147,147,147,148,148,148,148,148,
+ 149,149,149,150,150,150,150,151,151,151,151,151,152,152,152,152,
+ 153,153,153,153,154,154,155,155,156,156,156,156,156,156,157,157,
+ 158,158,159,159,159,159,159,159,160,160,161,161,161,161,161,161,
+ 162,162,162,162,162,162,163,163,164,164,164,164,165,165,165,165,
+ 166,166,166,166,167,167,168,168,169,169,169,169,170,170,170,170,
+ 171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,175,
+ 175,175,175,176,176,176,176,177,177,177,178,178,179,179,179,179,
+ 180,180,180,180,180,181,181,181,182,182,182,182,182,183,183,183,
+ 184,184,184,184,184,184,185, 43,186,186,186,186,187,187,187,188,
188,188,188,188,189,189,189,190,189,189,189,189,191,191,191,191,
- 191,191,191,191,192,192,192,192,192,192,192,192,193,193,193,193,
- 193,193,193,193,194,194,194,194,194,194, 66, 66,195,195,195,195,
- 195,195,195,195,196,196,196,196,196,196,196,196,197,197,197,197,
- 197,197,197,197,198,198,198,198,198,198,198,198,199,199,199,199,
- 199,199,199,199,200,200,200,200,200,200,200,200,201,201,201,201,
- 201,202,202,202,202,202,202, 55,203,203,203,203,204,204,204,204,
- 204,204,204,205,205,205,205,205,205,205,205,205,206,206,206,206,
- 206,206,207,207,207,207,207,207,207,207,207,207,208,208,208,208,
- 208,208,208,208,110,110,110,110, 39, 39, 39, 39,209,209,209,209,
- 209,209,209,209,210,210,210,210,210,210,210,210,211,211,211,211,
- 211,211,211,211,212,212,212,212,212,212,212,212,112,112,112,112,
- 112,112,112,112,112,112,112,112,213,213,213,214,214,214,214,214,
- 214,215,215,215,216,216,216,216,216,216,216,216,217,217,217,217,
- 217,217,217,217,218,218,218,218,218,218,218,218,218,218,218,218,
- 218,218,219, 94,220,220,220,220,220,220,220,220,221,221,221,221,
- 221,221,221,221,102,102,102,102,102,102,102,102,222, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,102,102,
- 102, 99,223,224,224,224,224,224,224,224,224,224,225,225,225,225,
- 225,225,225,225,225,225, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
- 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,226,227,228, 0,229, 0,
- 0, 0, 0, 0,230,230,230,230,230,230,230,230, 91, 91, 91, 91,
- 91, 91, 91, 91,231,231,231,231,231,231,231,231,232,232,232,232,
- 233,233,233,233,234,234,234,234,234,234,234,234,235,235,235,235,
- 235,235,235,235,236, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
- 8, 8, 8, 8, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0,
- 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0,
- 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8,
- 8, 8, 8, 8, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 14, 14,
- 16, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 19, 19, 19, 19, 19,
- 20, 21, 20, 22, 20, 20, 23, 23, 20, 20, 20, 20, 22, 20, 24, 7,
- 7, 25, 20, 20, 26, 20, 20, 20, 20, 20, 20, 21, 27, 27, 27, 27,
- 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,
- 32, 20, 20, 20, 33, 33, 33, 33, 34, 35, 33, 33, 33, 36, 33, 33,
- 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40,
- 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44,
- 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 47, 48, 48, 48, 48,
- 49, 49, 49, 49, 49, 50, 51, 49, 52, 52, 52, 52, 53, 53, 53, 53,
- 53, 53, 54, 53, 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57,
- 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 61, 62,
- 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 0, 0, 66, 66, 66, 66,
- 67, 67, 67, 67, 68, 68, 68, 68, 69, 70, 71, 71, 71, 71, 71, 71,
- 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75,
- 76, 76, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79,
- 80, 80, 80, 80, 81, 81, 81, 81, 82, 7, 7, 7, 83, 7, 84, 85,
- 0, 84, 86, 0, 2, 87, 88, 2, 2, 2, 2, 89, 90, 87, 91, 2,
- 2, 2, 92, 2, 2, 2, 2, 93, 0, 0, 0, 86, 1, 0, 0, 94,
- 0, 95, 96, 0, 4, 0, 0, 0, 0, 0, 0, 4, 97, 97, 97, 97,
- 98, 98, 98, 98, 13, 13, 13, 13, 99, 99, 99, 99,100,100,100,100,
- 0,101, 0, 0,102,100,103,104, 0, 0,100, 0,105,106,106,106,
- 106,106,106,106,106,106,107,105,108,109,109,109,109,109,109,109,
- 109,109,110,108,111,111,111,111,112, 55, 55, 55, 55, 55, 55,113,
- 109,109,109,110,109,109, 0, 0,114,114,114,114,115,115,115,115,
- 116,116,116,116,117,117,117,117, 96, 2, 2, 2, 2, 2, 94, 2,
- 118,118,118,118,119,119,119,119,120,120,120,120,121,121,121,121,
- 121,121,121,122,123,123,123,123,124,124,124,124,124,124,124,125,
- 126,126,126,126,127,127,127,127,128,128,128,128, 2, 2, 3, 2,
- 2,129,130, 0,131,131,131,131,132, 17, 17, 18, 20, 20, 20,133,
- 7, 7, 7,134, 20, 20, 20, 23, 0,135,109,109,109,109,109,136,
- 137,137,137,137, 0, 0, 0,138,139,139,139,139,140,140,140,140,
- 84, 0, 0, 0,141,141,141,141,142,142,142,142,143,143,143,143,
- 144,144,144,144,145,145,145,145,146,146,146,146,147,147,147,147,
- 148,148,148,148,149,149,149,149,150,150,150,150,151,151,151,151,
- 152,152,152,152,153,153,153,153,154,154,154,154,155,155,155,155,
- 156,156,156,156,157,157,157,157,158,158,158,158,159,159,159,159,
- 160,160,160,160,161,161,161,161,162,162,162,162,163,163,163,163,
- 164,164,164,164,165,165,165,165,166,166,166,166,167,167,167,167,
- 168,168,168,168,169,169,169,169,170,170,170,170,171,171,171,171,
- 172,172,172,172,173,173,173,173,174,174,174,174,175,175,175,175,
- 176,176,176,176,177,177,177,177,178,178,178,178,179,179,179,179,
- 180,180,180,180,181,181,181,181,182,182,182,182,183,183,183,183,
- 184,184,184,184,185,185,185,185,186, 45, 45, 45,187,187,187,187,
- 188,188,188,188,189,189,189,189,190,190,190,190,190,190,191,190,
- 192,192,192,192,193,193,193,193,194,194,194,194,195,195,195,195,
- 196,196,196,196,197,197,197,197,198,198,198,198,199,199,199,199,
- 200,200,200,200,201,201,201,201,202,202,202,202,203,203,203,203,
- 204,204,204,204,205,205,205,205,206,206,206,206,207,207,207,207,
- 208,208,208,208,209,209,209,209,210,210,210,210,211,211,211,211,
- 212,212,212,212,213,213,213,213,214,214,214,214,215,215,215,215,
- 216,216,216,216,217,217,217,217,218,218,218,218,219,219,219,219,
- 220,221,221,221,222,222,222,222,221,221,221,221,223,106,106,106,
- 106,109,109,109,224,224,224,224,225,225,225,225, 0,226, 86, 0,
- 0, 0,226, 7, 82,138, 7, 0, 0, 0,227, 86,228,228,228,228,
- 229,229,229,229,230,230,230,230,231,231,231,231,232,232,232,232,
- 233,233,233,233,234, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0,
- 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9,
- 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55, 55, 55, 55, 55,
- 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4, 4, 4, 4, 4,
- 4, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 0, 3, 3,
- 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 1, 1, 1, 3, 3,
- 1, 3, 3, 3, 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64,
- 90, 90, 90, 90, 95, 95, 95, 95, 3, 3, 0, 3, 7, 7, 7, 7,
- 7, 1, 1, 1, 1, 7, 7, 7, 0, 0, 7, 7, 5, 5, 5, 5,
- 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22,
- 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36,
- 24, 24, 24, 24, 24, 24, 24, 0, 18, 18, 18, 18, 25, 25, 25, 25,
- 25, 0, 0, 0, 0, 25, 25, 25, 33, 33, 33, 33, 8, 8, 8, 8,
- 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29,
- 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 0,
- 0, 0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44, 44, 0, 0, 0,
- 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31, 32, 32, 0, 0,
- 32, 0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52,
- 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62,
- 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73,
- 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0,
- 1, 1, 0, 0, 19, 19, 9, 9, 9, 9, 9, 6, 19, 9, 9, 9,
- 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19, 19, 19, 19, 9,
- 0, 0, 0, 19, 0, 0, 9, 0, 0, 0, 19, 19, 27, 27, 27, 27,
- 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13, 0, 13, 0, 13,
- 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 0, 15, 15, 15,
- 15, 15, 15, 15, 15, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 0, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12, 0,
- 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79,
- 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69,
- 69, 69, 0, 69, 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84, 0,
- 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87, 19, 9, 19, 19,
- 19, 19, 0, 0, 2, 2, 2, 2, 19, 19, 19, 4, 3, 3, 0, 0,
- 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0, 49, 49, 49, 49,
- 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42,
- 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59,
- 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135,
- 106,106,106,106,104,104,104,104,161,161,161,161,110,110,110,110,
- 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120,116,116,116,116,
- 128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98,
- 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117,
- 112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82,
- 122,122,122,122, 89, 89, 89, 89,130,130,130,130,144,144,144,144,
- 156,156,156,156,147,147,147,147,148,148,148,148,158,158,158,158,
- 153,153,153,153,149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,
- 101,101,101,101, 96, 96, 96, 96,111,111,111,111,100,100,100,100,
- 100, 36, 36, 36,108,108,108,108,129,129,129,129,109,109,109,109,
- 107,107,107,107,107,107,107, 1,137,137,137,137,124,124,124,124,
- 123,123,123,123,114,114,114,114,102,102,102,102,126,126,126,126,
- 142,142,142,142,125,125,125,125,154,154,154,154,150,150,150,150,
- 141,141,141,141,140,140,140,140,121,121,121,121,133,133,133,133,
- 134,134,134,134,138,138,138,138,143,143,143,143,145,145,145,145,
- 63, 63, 63, 63,157,157,157,157, 80, 80, 80, 80,127,127,127,127,
- 115,115,115,115,159,159,159,159,103,103,103,103,119,119,119,119,
- 146,146,146,146, 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,
- 136,136,136,136, 17, 15, 15, 15,139,139,139,139,105,105,105,105,
- 0, 0, 0, 1, 0, 0, 1, 1,131,131,131,131,151,151,151,151,
- 160,160,160,160,152,152,152,152,113,113,113,113,132,132,132,132,
- 15, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9,
- 9, 10, 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9,
+ 192,192,192,192,193,193,193,193,194,194,194,194,194,194, 66, 66,
+ 195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198,
+ 199,199,199,199,200,200,200,200,201,201,201,201,201,202,202,202,
+ 202,202,202, 55,203,203,203,203,204,204,204,204,204,204,204,205,
+ 205,205,205,205,206,206,206,206,206,206,207,207,207,207,207,207,
+ 208,208,208,208,110,110,110,110,209,209,209,209,210,210,210,210,
+ 211,211,211,211,212,212,212,212,213,213,213,214,214,214,214,214,
+ 214,215,215,215,216,216,216,216,217,217,217,217,218,218,218,218,
+ 218,218,219, 94,220,220,220,220,221,221,221,221,222, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99,102,102,102, 99,223,224,224,224,224,224,
+ 225,225,225,225,225,225, 0, 0, 8, 0, 0, 0, 0, 0,226,227,
+ 228, 0,229, 0,230,230,230,230,231,231,231,231,232,232,232,232,
+ 233,233,233,233,234,234,234,234,235,235,235,235,236, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, 0, 0, 4, 0,
+ 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0, 2, 5, 6, 0,
+ 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8, 8, 8, 8, 8,
+ 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 14, 14, 16, 17, 17, 17,
+ 17, 17, 17, 17, 18, 19, 19, 19, 19, 19, 19, 19, 20, 21, 20, 22,
+ 20, 20, 23, 23, 20, 20, 20, 20, 22, 20, 24, 7, 7, 25, 20, 20,
+ 26, 20, 20, 20, 20, 20, 20, 21, 27, 27, 27, 27, 28, 28, 28, 28,
+ 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 20, 20, 20,
+ 33, 33, 33, 33, 34, 35, 33, 33, 33, 36, 33, 33, 37, 37, 37, 37,
+ 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41,
+ 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45,
+ 46, 46, 46, 46, 46, 46, 46, 47, 48, 48, 48, 48, 49, 49, 49, 49,
+ 49, 50, 51, 49, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 54, 53,
+ 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58,
+ 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 61, 62, 63, 63, 63, 63,
+ 64, 64, 64, 64, 64, 65, 0, 0, 66, 66, 66, 66, 67, 67, 67, 67,
+ 68, 68, 68, 68, 69, 70, 71, 71, 71, 71, 71, 71, 72, 72, 72, 72,
+ 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 76, 76, 76, 76,
+ 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79, 80, 80, 80, 80,
+ 81, 81, 81, 81, 82, 7, 7, 7, 83, 7, 84, 85, 0, 84, 86, 0,
+ 2, 87, 88, 2, 2, 2, 2, 89, 90, 87, 91, 2, 2, 2, 92, 2,
+ 2, 2, 2, 93, 0, 0, 0, 86, 1, 0, 0, 94, 0, 95, 96, 0,
+ 4, 0, 0, 0, 0, 0, 0, 4, 97, 97, 97, 97, 98, 98, 98, 98,
+ 13, 13, 13, 13, 99, 99, 99, 99,100,100,100,100, 0,101, 0, 0,
+ 102,100,103,104, 0, 0,100, 0,105,106,106,106,106,106,106,106,
+ 106,106,107,105,108,109,109,109,109,109,109,109,109,109,110,108,
+ 111,111,111,111,112, 55, 55, 55, 55, 55, 55,113,109,109,109,110,
+ 109,109, 0, 0,114,114,114,114,115,115,115,115,116,116,116,116,
+ 117,117,117,117, 96, 2, 2, 2, 2, 2, 94, 2,118,118,118,118,
+ 119,119,119,119,120,120,120,120,121,121,121,121,121,121,121,122,
+ 123,123,123,123,124,124,124,124,124,124,124,125,126,126,126,126,
+ 127,127,127,127,128,128,128,128, 2, 2, 3, 2, 2,129,130, 0,
+ 131,131,131,131,132, 17, 17, 18, 20, 20, 20,133, 7, 7, 7,134,
+ 20, 20, 20, 23, 0,135,109,109,109,109,109,136,137,137,137,137,
+ 0, 0, 0,138,139,139,139,139,140,140,140,140, 84, 0, 0, 0,
+ 141,141,141,141,142,142,142,142,143,143,143,143,144,144,144,144,
+ 145,145,145,145,146,146,146,146,147,147,147,147,148,148,148,148,
+ 149,149,149,149,150,150,150,150,151,151,151,151,152,152,152,152,
+ 153,153,153,153,154,154,154,154,155,155,155,155,156,156,156,156,
+ 157,157,157,157,158,158,158,158,159,159,159,159,160,160,160,160,
+ 161,161,161,161,162,162,162,162,163,163,163,163,164,164,164,164,
+ 165,165,165,165,166,166,166,166,167,167,167,167,168,168,168,168,
+ 169,169,169,169,170,170,170,170,171,171,171,171,172,172,172,172,
+ 173,173,173,173,174,174,174,174,175,175,175,175,176,176,176,176,
+ 177,177,177,177,178,178,178,178,179,179,179,179,180,180,180,180,
+ 181,181,181,181,182,182,182,182,183,183,183,183,184,184,184,184,
+ 185,185,185,185,186, 45, 45, 45,187,187,187,187,188,188,188,188,
+ 189,189,189,189,190,190,190,190,190,190,191,190,192,192,192,192,
+ 193,193,193,193,194,194,194,194,195,195,195,195,196,196,196,196,
+ 197,197,197,197,198,198,198,198,199,199,199,199,200,200,200,200,
+ 201,201,201,201,202,202,202,202,203,203,203,203,204,204,204,204,
+ 205,205,205,205,206,206,206,206,207,207,207,207,208,208,208,208,
+ 209,209,209,209,210,210,210,210,211,211,211,211,212,212,212,212,
+ 213,213,213,213,214,214,214,214,215,215,215,215,216,216,216,216,
+ 217,217,217,217,218,218,218,218,219,219,219,219,220,221,221,221,
+ 222,222,222,222,221,221,221,221,223,106,106,106,106,109,109,109,
+ 224,224,224,224,225,225,225,225, 0,226, 86, 0, 0, 0,226, 7,
+ 82,138, 7, 0, 0, 0,227, 86,228,228,228,228,229,229,229,229,
+ 230,230,230,230,231,231,231,231,232,232,232,232,233,233,233,233,
+ 234, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0, 0, 0, 26, 26,
+ 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 9,
+ 9, 0, 9, 0, 9, 9, 55, 55, 55, 55, 55, 55, 6, 6, 6, 6,
+ 6, 1, 1, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 14, 14, 14,
+ 14, 14, 14, 14, 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 1, 1, 1, 3, 3, 1, 3, 3, 3,
+ 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64, 90, 90, 90, 90,
+ 95, 95, 95, 95, 3, 3, 0, 3, 7, 7, 7, 7, 7, 1, 1, 1,
+ 1, 7, 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, 11, 11, 11, 11,
+ 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,
+ 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36, 24, 24, 24, 24,
+ 24, 24, 24, 0, 18, 18, 18, 18, 25, 25, 25, 25, 25, 0, 0, 0,
+ 0, 25, 25, 25, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 0,
+ 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28,
+ 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35,
+ 45, 45, 45, 45, 44, 44, 44, 44, 44, 0, 0, 0, 43, 43, 43, 43,
+ 46, 46, 46, 46, 31, 31, 31, 31, 32, 32, 0, 0, 32, 0, 32, 32,
+ 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52, 58, 58, 58, 58,
+ 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62, 76, 76, 76, 76,
+ 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73, 1, 1, 1, 0,
+ 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0,
+ 19, 19, 9, 9, 9, 9, 9, 6, 19, 9, 9, 9, 9, 9, 19, 19,
+ 9, 9, 9, 19, 6, 19, 19, 19, 19, 19, 19, 9, 0, 0, 0, 19,
+ 0, 0, 9, 0, 0, 0, 19, 19, 27, 27, 27, 27, 56, 56, 56, 56,
+ 61, 61, 61, 61, 13, 13, 13, 13, 0, 13, 0, 13, 0, 13, 13, 13,
+ 13, 13, 1, 1, 1, 1, 12, 12, 0, 15, 15, 15, 15, 15, 15, 15,
+ 15, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0,
+ 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12, 0, 39, 39, 39, 39,
+ 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79, 60, 60, 60, 60,
+ 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69, 69, 69, 0, 69,
+ 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84, 0, 68, 68, 68, 68,
+ 92, 92, 92, 92, 87, 87, 87, 87, 19, 9, 19, 19, 19, 19, 0, 0,
+ 2, 2, 2, 2, 19, 19, 19, 4, 3, 3, 0, 0, 1, 1, 6, 6,
+ 0, 0, 17, 17, 17, 17, 0, 0, 49, 49, 49, 49, 0, 1, 1, 1,
+ 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42, 41, 41, 41, 41,
+ 118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59, 40, 40, 40, 40,
+ 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135,106,106,106,106,
+ 104,104,104,104,161,161,161,161,110,110,110,110, 47, 47, 47, 47,
+ 81, 81, 81, 81,120,120,120,120,116,116,116,116,128,128,128,128,
+ 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98, 97, 97, 97, 97,
+ 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117,112,112,112,112,
+ 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82,122,122,122,122,
+ 89, 89, 89, 89,130,130,130,130,144,144,144,144,156,156,156,156,
+ 147,147,147,147,148,148,148,148,158,158,158,158,153,153,153,153,
+ 149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101,
+ 96, 96, 96, 96,111,111,111,111,100,100,100,100,100, 36, 36, 36,
+ 108,108,108,108,129,129,129,129,109,109,109,109,107,107,107,107,
+ 107,107,107, 1,137,137,137,137,124,124,124,124,123,123,123,123,
+ 114,114,114,114,102,102,102,102,126,126,126,126,142,142,142,142,
+ 125,125,125,125,154,154,154,154,150,150,150,150,141,141,141,141,
+ 140,140,140,140,121,121,121,121,133,133,133,133,134,134,134,134,
+ 138,138,138,138,143,143,143,143,145,145,145,145, 63, 63, 63, 63,
+ 157,157,157,157, 80, 80, 80, 80,127,127,127,127,115,115,115,115,
+ 159,159,159,159,103,103,103,103,119,119,119,119,146,146,146,146,
+ 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,136,136,136,136,
+ 17, 15, 15, 15,139,139,139,139,105,105,105,105, 0, 0, 0, 1,
+ 0, 0, 1, 1,131,131,131,131,151,151,151,151,160,160,160,160,
+ 152,152,152,152,113,113,113,113,132,132,132,132, 15, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11,
+ 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 16, 17, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, 20, 9,
- 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
@@ -6478,58 +5336,57 @@ _hb_ucd_u8[13602] =
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30,
- 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37,
- 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32,
+ 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0,
+ 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0,
+ 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47,
- 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0,
- 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0,
- 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57,
+ 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0,
+ 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0,
- 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68,
+ 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,100,101,102,103, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,
+ 109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,
+ 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 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,100,
- 101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0,
- 0, 0,108, 0,109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,
- 115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117,
+ 0, 0,118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,118,119,120,121, 0,122,123,124,125,126,
- 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,129,
+ 130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,
+ 146,147,148,149,150,151,152,153,154,155,156,157, 0, 0, 0,158,
+ 159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,
+ 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,128,129,130,131,132,133,134,135,136,137,138,139,140,141,
- 142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,
- 0, 0, 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0,
- 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0,
+ 0,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,
+ 175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,
+ 191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,169,170, 0, 0, 0, 0,171,172, 0,
- 0, 0,173,174,175,176,177,178,179,180,181,182,183,184,185,186,
- 187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,
- 203,204,205,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
- 3, 4,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
};
static const uint16_t
_hb_ucd_u16[4888] =
@@ -6842,21 +5699,14 @@ _hb_ucd_u16[4888] =
817, 818, 819, 820, 821, 935, 0, 0,
};
static const int16_t
-_hb_ucd_i16[196] =
+_hb_ucd_i16[92] =
{
- 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2,
- 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1,
- 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3,
- -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0,
- 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0,
- 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0,
- 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0,
- 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0,
- 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1,
- -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0,
- 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106,
- -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1,
- -1, 0, 1, -1,
+ 0, 0, 1, -1, 2, 0, -2, 0, 0, 2, 0, -2, 0, 16, 0, -16,
+ 0, 1, -1, 0, 3, 3, 3, -3, -3, -3, 0, 2016, 0, 2527, 1923, 1914,
+ 1918, 0, 2250, 0, 0, 138, 0, 7, -7, 0, -1, 1, 1824, 0, 2104, 0,
+ 2108, 2106, 0, 2106, 1316, 0, -1, -138, 8, 8, 8, 0, 7, 7, -8, -8,
+ -8, -7,-1316, 1, -1, 3, -3, 1, 0,-1914,-1918, 0, 0,-1923,-1824, 0,
+ 0,-2016,-2104, 0, 0,-2106,-2108,-2106,-2250, 0,-2527, 0,
};
static inline uint_fast8_t
@@ -6877,17 +5727,17 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i)
static inline int_fast16_t
_hb_ucd_bmg (unsigned u)
{
- return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7714+(((_hb_ucd_u8[7594+(((_hb_ucd_b4(7466+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
+ return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7858+(((_hb_ucd_u8[7626+(((_hb_ucd_u8[7530+(((_hb_ucd_b4(7466+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
}
static inline uint_fast8_t
_hb_ucd_sc (unsigned u)
{
- return u<918016u?_hb_ucd_u8[11480+(((_hb_ucd_u8[10532+(((_hb_ucd_u8[9124+(((_hb_ucd_u8[8500+(((_hb_ucd_u8[8050+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
+ return u<918016u?_hb_ucd_u8[11124+(((_hb_ucd_u8[10176+(((_hb_ucd_u8[9204+(((_hb_ucd_u8[8524+(((_hb_ucd_u8[8220+(((_hb_ucd_u8[8106+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
}
static inline uint_fast16_t
_hb_ucd_dm (unsigned u)
{
- return u<195102u?_hb_ucd_u16[1576+(((_hb_ucd_u8[12802+(((_hb_ucd_u8[12420+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+ return u<195102u?_hb_ucd_u16[1576+(((_hb_ucd_u8[12446+(((_hb_ucd_u8[12064+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
}
#endif
diff --git a/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh b/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh
index c216379201..036c71a424 100644
--- a/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh
+++ b/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh
@@ -24,42 +24,37 @@
#include "hb-unicode.hh"
static const uint8_t
-_hb_emoji_u8[544] =
+_hb_emoji_u8[464] =
{
16, 17, 17, 17, 50, 20, 21, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,118,152,
- 0, 0, 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,
- 2, 3, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 6, 0, 7, 8,
- 0, 0, 0, 9, 0, 0, 10, 11, 12, 13, 14, 13, 15, 16, 17, 0,
- 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 19, 20, 0, 0,
- 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0,
- 13, 13, 13, 13, 23, 24, 25, 26, 27, 28, 13, 13, 13, 13, 13, 29,
- 13, 13, 13, 13, 30, 31, 13, 13, 13, 32, 13, 13, 0, 33, 0, 34,
- 35, 36, 37, 13, 38, 39, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 30,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 16, 0, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 4, 0, 0, 2, 0, 0,240, 3, 0, 6, 0, 0,
- 0, 0, 0, 12, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
- 0,128, 0, 0, 0,254, 15, 7, 4, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0, 0, 0, 0,120,
- 191,255,247,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 63, 0,255,255,255,255,255,255, 63,255, 87, 32, 2, 1, 24, 0,
- 144, 80,184, 0,248, 0, 0, 0, 0, 0,224, 0, 2, 0, 1,128,
- 0, 0, 0, 0, 0, 0, 48, 0,224, 0, 0, 24, 0, 0, 0, 0,
- 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32,
- 0, 0,128, 2, 0, 0, 0, 0, 0,224, 0, 0, 0,128, 0, 0,
- 0, 0, 0, 0, 0,240, 3,192, 0, 64,254, 7, 0,224,255,255,
- 255,255,255,255, 63, 0, 0, 0,254,255, 0, 4, 0,128,252,247,
- 0,254,255,255,255,255,255,255,255,255,255,255,255,255,255, 7,
- 255,255,255,255,255,255,255, 63,192,255,255,255,255,255,255,255,
- 255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,255,
- 0, 0,224,255,255,255,255,255, 0,240, 0, 0, 0, 0, 0, 0,
- 0,255, 0,252, 0, 0, 0, 0, 0,255, 0, 0, 0,192,255,255,
- 0,240,255,255,255,255,255,247,191,255,255,255,255,255,255,255,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 3, 4, 0, 0, 5, 6, 0, 7, 0, 8, 9, 10, 11, 12,
+ 0, 0, 13, 0, 0, 0, 14, 0, 15, 0, 0, 0, 0, 16, 0, 0,
+ 17, 17, 18, 19, 20, 17, 17, 21, 17, 17, 22, 17, 23, 17, 24, 25,
+ 26, 27, 28, 17, 17, 17, 0, 0, 17, 17, 17, 17, 17, 17, 17, 29,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 4, 0, 0,
+ 5, 6, 0, 0, 7, 8, 0, 0, 8, 0, 9, 10, 0, 0, 11, 0,
+ 0, 12, 13, 14, 15, 16, 16, 16, 17, 16, 16, 16, 18, 19, 20, 21,
+ 22, 23, 0, 0, 0, 24, 0, 0, 25, 0, 26, 0, 0, 27, 0, 0,
+ 28, 0, 0, 0, 16, 16, 16, 16, 29, 9, 0, 30, 31, 32, 16, 33,
+ 34, 35, 36, 16, 16, 16, 16, 37, 16, 38, 39, 16, 16, 16, 40, 0,
+ 0, 0, 0, 41, 0, 0, 42, 16, 43, 0, 44, 0, 45, 46, 16, 16,
+ 47, 48, 49, 16, 16, 16, 16, 38, 0, 0, 0, 0, 0, 66, 0, 0,
+ 0, 0, 0, 16, 0, 2, 0, 0, 4, 0, 0, 2, 0, 0,240, 3,
+ 0, 6, 0, 0, 0, 0, 0, 12, 0, 1, 0, 0, 0,128, 0, 0,
+ 0,254, 15, 7, 4, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0,
+ 0, 0, 0,120,191,255,247,255,255,255,255,255, 63, 0,255,255,
+ 63,255, 87, 32, 2, 1, 24, 0,144, 80,184, 0,248, 0, 0, 0,
+ 0, 0,224, 0, 2, 0, 1,128, 0, 0, 48, 0,224, 0, 0, 24,
+ 0, 0, 33, 0, 0, 0, 1, 32, 0, 0,128, 2, 0,224, 0, 0,
+ 0,240, 3,192, 0, 64,254, 7, 0,224,255,255, 63, 0, 0, 0,
+ 254,255, 0, 4, 0,128,252,247, 0,254,255,255,255,255,255, 7,
+ 255,255,255, 63,192,255,255,255,255,255, 0, 0, 0, 0,240,255,
+ 0, 0,224,255, 0,240, 0, 0, 0,255, 0,252, 0,255, 0, 0,
+ 0,192,255,255, 0,240,255,255,255,255,255,247,191,255,255,255,
};
static inline unsigned
@@ -75,7 +70,7 @@ _hb_emoji_b1 (const uint8_t* a, unsigned i)
static inline uint_fast8_t
_hb_emoji_is_Extended_Pictographic (unsigned u)
{
- return u<131070u?_hb_emoji_b1(224+_hb_emoji_u8,((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>6>>4))<<4)+((u>>6)&15u))])<<6)+((u)&63u)):0;
+ return u<131070u?_hb_emoji_b1(264+_hb_emoji_u8,((_hb_emoji_u8[144+(((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>5>>2>>3))<<3)+((u>>5>>2)&7u))])<<2)+((u>>5)&3u))])<<5)+((u)&31u)):0;
}
diff --git a/thirdparty/harfbuzz/src/hb-unicode.cc b/thirdparty/harfbuzz/src/hb-unicode.cc
index 83ead6398b..c1795dc7f2 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.
@@ -281,7 +281,7 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
*
* Attaches a user-data key/data pair to the specified Unicode-functions structure.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -308,8 +308,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
* Since: 0.9.2
**/
void *
-hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
- hb_user_data_key_t *key)
+hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key)
{
return hb_object_get_user_data (ufuncs, key);
}
@@ -340,7 +340,7 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
* Tests whether the specified Unicode-functions structure
* is immutable.
*
- * Return value: %true if @ufuncs is immutable, %false otherwise
+ * Return value: `true` if @ufuncs is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -421,7 +421,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
* Calls the composition function of the specified
* Unicode-functions structure @ufuncs.
*
- * Return value: %true if @a and @b composed, %false otherwise
+ * Return value: `true` if @a and @b composed, `false` otherwise
*
* Since: 0.9.2
**/
@@ -446,7 +446,7 @@ hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
* Calls the decomposition function of the specified
* Unicode-functions structure @ufuncs.
*
- * Return value: %true if @ab was decomposed, %false otherwise
+ * Return value: `true` if @ab was decomposed, `false` otherwise
*
* Since: 0.9.2
**/
diff --git a/thirdparty/harfbuzz/src/hb-unicode.h b/thirdparty/harfbuzz/src/hb-unicode.h
index c04ee15a09..faa8d67924 100644
--- a/thirdparty/harfbuzz/src/hb-unicode.h
+++ b/thirdparty/harfbuzz/src/hb-unicode.h
@@ -317,8 +317,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
HB_EXTERN void *
-hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
- hb_user_data_key_t *key);
+hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key);
HB_EXTERN void
@@ -429,7 +429,7 @@ typedef hb_script_t (*hb_unicode_script_func_t) (hb_unicode_funcs_t *ufuncs,
* The method must return an #hb_bool_t indicating the success
* of the composition.
*
- * Return value: %true is @a,@b composed, %false otherwise
+ * Return value: `true` is @a,@b composed, `false` otherwise
*
**/
typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs,
@@ -453,7 +453,7 @@ typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs,
* output parameters (if successful). The method must return an
* #hb_bool_t indicating the success of the composition.
*
- * Return value: %true if @ab decomposed, %false otherwise
+ * Return value: `true` if @ab decomposed, `false` otherwise
*
**/
typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs,
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-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh
index 7b08e3b4d2..a6d9f6b3fb 100644
--- a/thirdparty/harfbuzz/src/hb-vector.hh
+++ b/thirdparty/harfbuzz/src/hb-vector.hh
@@ -43,7 +43,6 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
using c_array_t = typename std::conditional<sorted, hb_sorted_array_t<const Type>, hb_array_t<const Type>>::type;
hb_vector_t () = default;
- hb_vector_t (std::nullptr_t) : hb_vector_t () {}
hb_vector_t (std::initializer_list<Type> lst) : hb_vector_t ()
{
alloc (lst.size ());
diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h
index ae707cde6c..a1586a58b6 100644
--- a/thirdparty/harfbuzz/src/hb-version.h
+++ b/thirdparty/harfbuzz/src/hb-version.h
@@ -41,13 +41,13 @@ HB_BEGIN_DECLS
*
* The major component of the library version available at compile-time.
*/
-#define HB_VERSION_MAJOR 4
+#define HB_VERSION_MAJOR 5
/**
* HB_VERSION_MINOR:
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 3
+#define HB_VERSION_MINOR 1
/**
* HB_VERSION_MICRO:
*
@@ -60,7 +60,7 @@ HB_BEGIN_DECLS
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "4.3.0"
+#define HB_VERSION_STRING "5.1.0"
/**
* 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"
diff --git a/thirdparty/icu4c/godot_data.json b/thirdparty/icu4c/godot_data.json
index 3a9c28af4c..e36e2b078b 100644
--- a/thirdparty/icu4c/godot_data.json
+++ b/thirdparty/icu4c/godot_data.json
@@ -6,5 +6,6 @@
brkitr_tree: include
misc: include
normalization: include
+ confusables: include
}
-} \ No newline at end of file
+}
diff --git a/thirdparty/icu4c/i18n/scriptset.cpp b/thirdparty/icu4c/i18n/scriptset.cpp
new file mode 100644
index 0000000000..6a1db8c01c
--- /dev/null
+++ b/thirdparty/icu4c/i18n/scriptset.cpp
@@ -0,0 +1,313 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+**********************************************************************
+* Copyright (C) 2014, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+*
+* scriptset.cpp
+*
+* created on: 2013 Jan 7
+* created by: Andy Heninger
+*/
+
+#include "unicode/utypes.h"
+
+#include "unicode/uchar.h"
+#include "unicode/unistr.h"
+
+#include "scriptset.h"
+#include "uassert.h"
+#include "cmemory.h"
+
+U_NAMESPACE_BEGIN
+
+//----------------------------------------------------------------------------
+//
+// ScriptSet implementation
+//
+//----------------------------------------------------------------------------
+ScriptSet::ScriptSet() {
+ uprv_memset(bits, 0, sizeof(bits));
+}
+
+ScriptSet::~ScriptSet() {
+}
+
+ScriptSet::ScriptSet(const ScriptSet &other) {
+ *this = other;
+}
+
+ScriptSet & ScriptSet::operator =(const ScriptSet &other) {
+ uprv_memcpy(bits, other.bits, sizeof(bits));
+ return *this;
+}
+
+bool ScriptSet::operator == (const ScriptSet &other) const {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ if (bits[i] != other.bits[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+UBool ScriptSet::test(UScriptCode script, UErrorCode &status) const {
+ if (U_FAILURE(status)) {
+ return FALSE;
+ }
+ if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return FALSE;
+ }
+ uint32_t index = script / 32;
+ uint32_t bit = 1 << (script & 31);
+ return ((bits[index] & bit) != 0);
+}
+
+
+ScriptSet &ScriptSet::set(UScriptCode script, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return *this;
+ }
+ if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return *this;
+ }
+ uint32_t index = script / 32;
+ uint32_t bit = 1 << (script & 31);
+ bits[index] |= bit;
+ return *this;
+}
+
+ScriptSet &ScriptSet::reset(UScriptCode script, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return *this;
+ }
+ if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return *this;
+ }
+ uint32_t index = script / 32;
+ uint32_t bit = 1 << (script & 31);
+ bits[index] &= ~bit;
+ return *this;
+}
+
+
+
+ScriptSet &ScriptSet::Union(const ScriptSet &other) {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ bits[i] |= other.bits[i];
+ }
+ return *this;
+}
+
+ScriptSet &ScriptSet::intersect(const ScriptSet &other) {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ bits[i] &= other.bits[i];
+ }
+ return *this;
+}
+
+ScriptSet &ScriptSet::intersect(UScriptCode script, UErrorCode &status) {
+ ScriptSet t;
+ t.set(script, status);
+ if (U_SUCCESS(status)) {
+ this->intersect(t);
+ }
+ return *this;
+}
+
+UBool ScriptSet::intersects(const ScriptSet &other) const {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ if ((bits[i] & other.bits[i]) != 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+UBool ScriptSet::contains(const ScriptSet &other) const {
+ ScriptSet t(*this);
+ t.intersect(other);
+ return (t == other);
+}
+
+
+ScriptSet &ScriptSet::setAll() {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ bits[i] = 0xffffffffu;
+ }
+ return *this;
+}
+
+
+ScriptSet &ScriptSet::resetAll() {
+ uprv_memset(bits, 0, sizeof(bits));
+ return *this;
+}
+
+int32_t ScriptSet::countMembers() const {
+ // This bit counter is good for sparse numbers of '1's, which is
+ // very much the case that we will usually have.
+ int32_t count = 0;
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ uint32_t x = bits[i];
+ while (x > 0) {
+ count++;
+ x &= (x - 1); // and off the least significant one bit.
+ }
+ }
+ return count;
+}
+
+int32_t ScriptSet::hashCode() const {
+ int32_t hash = 0;
+ for (int32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ hash ^= bits[i];
+ }
+ return hash;
+}
+
+int32_t ScriptSet::nextSetBit(int32_t fromIndex) const {
+ // TODO: Wants a better implementation.
+ if (fromIndex < 0) {
+ return -1;
+ }
+ UErrorCode status = U_ZERO_ERROR;
+ for (int32_t scriptIndex = fromIndex; scriptIndex < SCRIPT_LIMIT; scriptIndex++) {
+ if (test((UScriptCode)scriptIndex, status)) {
+ return scriptIndex;
+ }
+ }
+ return -1;
+}
+
+UBool ScriptSet::isEmpty() const {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ if (bits[i] != 0) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+UnicodeString &ScriptSet::displayScripts(UnicodeString &dest) const {
+ UBool firstTime = TRUE;
+ for (int32_t i = nextSetBit(0); i >= 0; i = nextSetBit(i + 1)) {
+ if (!firstTime) {
+ dest.append((UChar)0x20);
+ }
+ firstTime = FALSE;
+ const char *scriptName = uscript_getShortName((UScriptCode(i)));
+ dest.append(UnicodeString(scriptName, -1, US_INV));
+ }
+ return dest;
+}
+
+ScriptSet &ScriptSet::parseScripts(const UnicodeString &scriptString, UErrorCode &status) {
+ resetAll();
+ if (U_FAILURE(status)) {
+ return *this;
+ }
+ UnicodeString oneScriptName;
+ for (int32_t i=0; i<scriptString.length();) {
+ UChar32 c = scriptString.char32At(i);
+ i = scriptString.moveIndex32(i, 1);
+ if (!u_isUWhiteSpace(c)) {
+ oneScriptName.append(c);
+ if (i < scriptString.length()) {
+ continue;
+ }
+ }
+ if (oneScriptName.length() > 0) {
+ char buf[40];
+ oneScriptName.extract(0, oneScriptName.length(), buf, sizeof(buf)-1, US_INV);
+ buf[sizeof(buf)-1] = 0;
+ int32_t sc = u_getPropertyValueEnum(UCHAR_SCRIPT, buf);
+ if (sc == UCHAR_INVALID_CODE) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ } else {
+ this->set((UScriptCode)sc, status);
+ }
+ if (U_FAILURE(status)) {
+ return *this;
+ }
+ oneScriptName.remove();
+ }
+ }
+ return *this;
+}
+
+void ScriptSet::setScriptExtensions(UChar32 codePoint, UErrorCode& status) {
+ if (U_FAILURE(status)) { return; }
+ static const int32_t FIRST_GUESS_SCRIPT_CAPACITY = 20;
+ MaybeStackArray<UScriptCode,FIRST_GUESS_SCRIPT_CAPACITY> scripts;
+ UErrorCode internalStatus = U_ZERO_ERROR;
+ int32_t script_count = -1;
+
+ while (TRUE) {
+ script_count = uscript_getScriptExtensions(
+ codePoint, scripts.getAlias(), scripts.getCapacity(), &internalStatus);
+ if (internalStatus == U_BUFFER_OVERFLOW_ERROR) {
+ // Need to allocate more space
+ if (scripts.resize(script_count) == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ internalStatus = U_ZERO_ERROR;
+ } else {
+ break;
+ }
+ }
+
+ // Check if we failed for some reason other than buffer overflow
+ if (U_FAILURE(internalStatus)) {
+ status = internalStatus;
+ return;
+ }
+
+ // Load the scripts into the ScriptSet and return
+ for (int32_t i = 0; i < script_count; i++) {
+ this->set(scripts[i], status);
+ if (U_FAILURE(status)) { return; }
+ }
+}
+
+U_NAMESPACE_END
+
+U_CAPI UBool U_EXPORT2
+uhash_equalsScriptSet(const UElement key1, const UElement key2) {
+ icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer);
+ icu::ScriptSet *s2 = static_cast<icu::ScriptSet *>(key2.pointer);
+ return (*s1 == *s2);
+}
+
+U_CAPI int8_t U_EXPORT2
+uhash_compareScriptSet(UElement key0, UElement key1) {
+ icu::ScriptSet *s0 = static_cast<icu::ScriptSet *>(key0.pointer);
+ icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer);
+ int32_t diff = s0->countMembers() - s1->countMembers();
+ if (diff != 0) return static_cast<UBool>(diff);
+ int32_t i0 = s0->nextSetBit(0);
+ int32_t i1 = s1->nextSetBit(0);
+ while ((diff = i0-i1) == 0 && i0 > 0) {
+ i0 = s0->nextSetBit(i0+1);
+ i1 = s1->nextSetBit(i1+1);
+ }
+ return (int8_t)diff;
+}
+
+U_CAPI int32_t U_EXPORT2
+uhash_hashScriptSet(const UElement key) {
+ icu::ScriptSet *s = static_cast<icu::ScriptSet *>(key.pointer);
+ return s->hashCode();
+}
+
+U_CAPI void U_EXPORT2
+uhash_deleteScriptSet(void *obj) {
+ icu::ScriptSet *s = static_cast<icu::ScriptSet *>(obj);
+ delete s;
+}
diff --git a/thirdparty/icu4c/i18n/scriptset.h b/thirdparty/icu4c/i18n/scriptset.h
new file mode 100644
index 0000000000..51980ab7b3
--- /dev/null
+++ b/thirdparty/icu4c/i18n/scriptset.h
@@ -0,0 +1,86 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+**********************************************************************
+* Copyright (C) 2013, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+*
+* scriptset.h
+*
+* created on: 2013 Jan 7
+* created by: Andy Heninger
+*/
+
+#ifndef __SCRIPTSET_H__
+#define __SCRIPTSET_H__
+
+#include "unicode/utypes.h"
+#include "unicode/uobject.h"
+#include "unicode/uscript.h"
+
+#include "uelement.h"
+
+U_NAMESPACE_BEGIN
+
+//-------------------------------------------------------------------------------
+//
+// ScriptSet - A bit set representing a set of scripts.
+//
+// This class was originally used exclusively with script sets appearing
+// as part of the spoof check whole script confusable binary data. Its
+// use has since become more general, but the continued use to wrap
+// prebuilt binary data does constrain the design.
+//
+//-------------------------------------------------------------------------------
+class U_I18N_API ScriptSet: public UMemory {
+ public:
+ static constexpr int32_t SCRIPT_LIMIT = 224; // multiple of 32!
+
+ ScriptSet();
+ ScriptSet(const ScriptSet &other);
+ ~ScriptSet();
+
+ bool operator == (const ScriptSet &other) const;
+ bool operator != (const ScriptSet &other) const {return !(*this == other);}
+ ScriptSet & operator = (const ScriptSet &other);
+
+ UBool test(UScriptCode script, UErrorCode &status) const;
+ ScriptSet &Union(const ScriptSet &other);
+ ScriptSet &set(UScriptCode script, UErrorCode &status);
+ ScriptSet &reset(UScriptCode script, UErrorCode &status);
+ ScriptSet &intersect(const ScriptSet &other);
+ ScriptSet &intersect(UScriptCode script, UErrorCode &status);
+ UBool intersects(const ScriptSet &other) const; // Sets contain at least one script in common.
+ UBool contains(const ScriptSet &other) const; // All set bits in other are also set in this.
+
+ ScriptSet &setAll();
+ ScriptSet &resetAll();
+ int32_t countMembers() const;
+ int32_t hashCode() const;
+ int32_t nextSetBit(int32_t script) const;
+
+ UBool isEmpty() const;
+
+ UnicodeString &displayScripts(UnicodeString &dest) const; // append script names to dest string.
+ ScriptSet & parseScripts(const UnicodeString &scriptsString, UErrorCode &status); // Replaces ScriptSet contents.
+
+ // Wraps around UScript::getScriptExtensions() and adds the corresponding scripts to this instance.
+ void setScriptExtensions(UChar32 codePoint, UErrorCode& status);
+
+ private:
+ uint32_t bits[SCRIPT_LIMIT / 32];
+};
+
+U_NAMESPACE_END
+
+U_CAPI UBool U_EXPORT2
+uhash_compareScriptSet(const UElement key1, const UElement key2);
+
+U_CAPI int32_t U_EXPORT2
+uhash_hashScriptSet(const UElement key);
+
+U_CAPI void U_EXPORT2
+uhash_deleteScriptSet(void *obj);
+
+#endif // __SCRIPTSET_H__
diff --git a/thirdparty/icu4c/i18n/ucln_in.cpp b/thirdparty/icu4c/i18n/ucln_in.cpp
new file mode 100644
index 0000000000..f29cbe41dd
--- /dev/null
+++ b/thirdparty/icu4c/i18n/ucln_in.cpp
@@ -0,0 +1,65 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+******************************************************************************
+* *
+* Copyright (C) 2001-2014, International Business Machines *
+* Corporation and others. All Rights Reserved. *
+* *
+******************************************************************************
+* file name: ucln_in.cpp
+* encoding: UTF-8
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2001July05
+* created by: George Rhoten
+*/
+
+#include "ucln.h"
+#include "ucln_in.h"
+#include "mutex.h"
+#include "uassert.h"
+
+/** Auto-client for UCLN_I18N **/
+#define UCLN_TYPE UCLN_I18N
+#include "ucln_imp.h"
+
+/* Leave this copyright notice here! It needs to go somewhere in this library. */
+static const char copyright[] = U_COPYRIGHT_STRING;
+
+static cleanupFunc *gCleanupFunctions[UCLN_I18N_COUNT];
+
+static UBool U_CALLCONV i18n_cleanup(void)
+{
+ int32_t libType = UCLN_I18N_START;
+ (void)copyright; /* Suppress unused variable warning with clang. */
+
+ while (++libType<UCLN_I18N_COUNT) {
+ if (gCleanupFunctions[libType])
+ {
+ gCleanupFunctions[libType]();
+ gCleanupFunctions[libType] = NULL;
+ }
+ }
+#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
+ ucln_unRegisterAutomaticCleanup();
+#endif
+ return TRUE;
+}
+
+void ucln_i18n_registerCleanup(ECleanupI18NType type,
+ cleanupFunc *func) {
+ U_ASSERT(UCLN_I18N_START < type && type < UCLN_I18N_COUNT);
+ {
+ icu::Mutex m; // See ticket 10295 for discussion.
+ ucln_registerCleanup(UCLN_I18N, i18n_cleanup);
+ if (UCLN_I18N_START < type && type < UCLN_I18N_COUNT) {
+ gCleanupFunctions[type] = func;
+ }
+ }
+#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
+ ucln_registerAutomaticCleanup();
+#endif
+}
+
diff --git a/thirdparty/icu4c/i18n/ucln_in.h b/thirdparty/icu4c/i18n/ucln_in.h
new file mode 100644
index 0000000000..765cdd559f
--- /dev/null
+++ b/thirdparty/icu4c/i18n/ucln_in.h
@@ -0,0 +1,74 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+******************************************************************************
+* Copyright (C) 2001-2016, International Business Machines
+* Corporation and others. All Rights Reserved.
+******************************************************************************
+* file name: ucln_in.h
+* encoding: UTF-8
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2001July05
+* created by: George Rhoten
+*/
+
+#ifndef __UCLN_IN_H__
+#define __UCLN_IN_H__
+
+#include "unicode/utypes.h"
+#include "ucln.h"
+
+/*
+Please keep the order of enums declared in same order
+as the functions are suppose to be called.
+It's usually best to have child dependencies called first. */
+typedef enum ECleanupI18NType {
+ UCLN_I18N_START = -1,
+ UCLN_I18N_UNIT_EXTRAS,
+ UCLN_I18N_NUMBER_SKELETONS,
+ UCLN_I18N_CURRENCY_SPACING,
+ UCLN_I18N_SPOOF,
+ UCLN_I18N_SPOOFDATA,
+ UCLN_I18N_TRANSLITERATOR,
+ UCLN_I18N_REGEX,
+ UCLN_I18N_JAPANESE_CALENDAR,
+ UCLN_I18N_ISLAMIC_CALENDAR,
+ UCLN_I18N_CHINESE_CALENDAR,
+ UCLN_I18N_HEBREW_CALENDAR,
+ UCLN_I18N_ASTRO_CALENDAR,
+ UCLN_I18N_DANGI_CALENDAR,
+ UCLN_I18N_CALENDAR,
+ UCLN_I18N_TIMEZONEFORMAT,
+ UCLN_I18N_TZDBTIMEZONENAMES,
+ UCLN_I18N_TIMEZONEGENERICNAMES,
+ UCLN_I18N_TIMEZONENAMES,
+ UCLN_I18N_ZONEMETA,
+ UCLN_I18N_TIMEZONE,
+ UCLN_I18N_DIGITLIST,
+ UCLN_I18N_DECFMT,
+ UCLN_I18N_NUMFMT,
+ UCLN_I18N_ALLOWED_HOUR_FORMATS,
+ UCLN_I18N_DAYPERIODRULES,
+ UCLN_I18N_SMPDTFMT,
+ UCLN_I18N_USEARCH,
+ UCLN_I18N_COLLATOR,
+ UCLN_I18N_UCOL_RES,
+ UCLN_I18N_CSDET,
+ UCLN_I18N_COLLATION_ROOT,
+ UCLN_I18N_GENDERINFO,
+ UCLN_I18N_CDFINFO,
+ UCLN_I18N_REGION,
+ UCLN_I18N_LIST_FORMATTER,
+ UCLN_I18N_NUMSYS,
+ UCLN_I18N_COUNT /* This must be last */
+} ECleanupI18NType;
+
+/* Main library cleanup registration function. */
+/* See common/ucln.h for details on adding a cleanup function. */
+/* Note: the global mutex must not be held when calling this function. */
+U_CFUNC void U_EXPORT2 ucln_i18n_registerCleanup(ECleanupI18NType type,
+ cleanupFunc *func);
+
+#endif
diff --git a/thirdparty/icu4c/i18n/unicode/uspoof.h b/thirdparty/icu4c/i18n/unicode/uspoof.h
new file mode 100644
index 0000000000..b674c91b2c
--- /dev/null
+++ b/thirdparty/icu4c/i18n/unicode/uspoof.h
@@ -0,0 +1,1577 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+***************************************************************************
+* Copyright (C) 2008-2016, International Business Machines Corporation
+* and others. All Rights Reserved.
+***************************************************************************
+* file name: uspoof.h
+* encoding: UTF-8
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2008Feb13
+* created by: Andy Heninger
+*
+* Unicode Spoof Detection
+*/
+
+#ifndef USPOOF_H
+#define USPOOF_H
+
+#include "unicode/utypes.h"
+#include "unicode/uset.h"
+#include "unicode/parseerr.h"
+
+#if !UCONFIG_NO_NORMALIZATION
+
+
+#if U_SHOW_CPLUSPLUS_API
+#include "unicode/localpointer.h"
+#include "unicode/unistr.h"
+#include "unicode/uniset.h"
+#endif
+
+
+/**
+ * \file
+ * \brief Unicode Security and Spoofing Detection, C API.
+ *
+ * <p>
+ * This class, based on <a href="http://unicode.org/reports/tr36">Unicode Technical Report #36</a> and
+ * <a href="http://unicode.org/reports/tr39">Unicode Technical Standard #39</a>, has two main functions:
+ *
+ * <ol>
+ * <li>Checking whether two strings are visually <em>confusable</em> with each other, such as "Harvest" and
+ * &quot;&Eta;arvest&quot;, where the second string starts with the Greek capital letter Eta.</li>
+ * <li>Checking whether an individual string is likely to be an attempt at confusing the reader (<em>spoof
+ * detection</em>), such as "paypal" with some Latin characters substituted with Cyrillic look-alikes.</li>
+ * </ol>
+ *
+ * <p>
+ * Although originally designed as a method for flagging suspicious identifier strings such as URLs,
+ * <code>USpoofChecker</code> has a number of other practical use cases, such as preventing attempts to evade bad-word
+ * content filters.
+ *
+ * <p>
+ * The functions of this class are exposed as C API, with a handful of syntactical conveniences for C++.
+ *
+ * <h2>Confusables</h2>
+ *
+ * <p>
+ * The following example shows how to use <code>USpoofChecker</code> to check for confusability between two strings:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str1 = (UChar*) u"Harvest";
+ * UChar* str2 = (UChar*) u"\u0397arvest"; // with U+0397 GREEK CAPITAL LETTER ETA
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status);
+ *
+ * int32_t bitmask = uspoof_areConfusable(sc, str1, -1, str2, -1, &status);
+ * UBool result = bitmask != 0;
+ * // areConfusable: 1 (status: U_ZERO_ERROR)
+ * printf("areConfusable: %d (status: %s)\n", result, u_errorName(status));
+ * uspoof_close(sc);
+ * \endcode
+ *
+ * <p>
+ * The call to {@link uspoof_open} creates a <code>USpoofChecker</code> object; the call to {@link uspoof_setChecks}
+ * enables confusable checking and disables all other checks; the call to {@link uspoof_areConfusable} performs the
+ * confusability test; and the following line extracts the result out of the return value. For best performance,
+ * the instance should be created once (e.g., upon application startup), and the efficient
+ * {@link uspoof_areConfusable} method can be used at runtime.
+ *
+ * <p>
+ * The type {@link LocalUSpoofCheckerPointer} is exposed for C++ programmers. It will automatically call
+ * {@link uspoof_close} when the object goes out of scope:
+ *
+ * \code{.cpp}
+ * UErrorCode status = U_ZERO_ERROR;
+ * LocalUSpoofCheckerPointer sc(uspoof_open(&status));
+ * uspoof_setChecks(sc.getAlias(), USPOOF_CONFUSABLE, &status);
+ * // ...
+ * \endcode
+ *
+ * UTS 39 defines two strings to be <em>confusable</em> if they map to the same <em>skeleton string</em>. A skeleton can
+ * be thought of as a "hash code". {@link uspoof_getSkeleton} computes the skeleton for a particular string, so
+ * the following snippet is equivalent to the example above:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str1 = (UChar*) u"Harvest";
+ * UChar* str2 = (UChar*) u"\u0397arvest"; // with U+0397 GREEK CAPITAL LETTER ETA
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status);
+ *
+ * // Get skeleton 1
+ * int32_t skel1Len = uspoof_getSkeleton(sc, 0, str1, -1, NULL, 0, &status);
+ * UChar* skel1 = (UChar*) malloc(++skel1Len * sizeof(UChar));
+ * status = U_ZERO_ERROR;
+ * uspoof_getSkeleton(sc, 0, str1, -1, skel1, skel1Len, &status);
+ *
+ * // Get skeleton 2
+ * int32_t skel2Len = uspoof_getSkeleton(sc, 0, str2, -1, NULL, 0, &status);
+ * UChar* skel2 = (UChar*) malloc(++skel2Len * sizeof(UChar));
+ * status = U_ZERO_ERROR;
+ * uspoof_getSkeleton(sc, 0, str2, -1, skel2, skel2Len, &status);
+ *
+ * // Are the skeletons the same?
+ * UBool result = u_strcmp(skel1, skel2) == 0;
+ * // areConfusable: 1 (status: U_ZERO_ERROR)
+ * printf("areConfusable: %d (status: %s)\n", result, u_errorName(status));
+ * uspoof_close(sc);
+ * free(skel1);
+ * free(skel2);
+ * \endcode
+ *
+ * If you need to check if a string is confusable with any string in a dictionary of many strings, rather than calling
+ * {@link uspoof_areConfusable} many times in a loop, {@link uspoof_getSkeleton} can be used instead, as shown below:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * #define DICTIONARY_LENGTH 2
+ * UChar* dictionary[DICTIONARY_LENGTH] = { (UChar*) u"lorem", (UChar*) u"ipsum" };
+ * UChar* skeletons[DICTIONARY_LENGTH];
+ * UChar* str = (UChar*) u"1orern";
+ *
+ * // Setup:
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status);
+ * for (size_t i=0; i<DICTIONARY_LENGTH; i++) {
+ * UChar* word = dictionary[i];
+ * int32_t len = uspoof_getSkeleton(sc, 0, word, -1, NULL, 0, &status);
+ * skeletons[i] = (UChar*) malloc(++len * sizeof(UChar));
+ * status = U_ZERO_ERROR;
+ * uspoof_getSkeleton(sc, 0, word, -1, skeletons[i], len, &status);
+ * }
+ *
+ * // Live Check:
+ * {
+ * int32_t len = uspoof_getSkeleton(sc, 0, str, -1, NULL, 0, &status);
+ * UChar* skel = (UChar*) malloc(++len * sizeof(UChar));
+ * status = U_ZERO_ERROR;
+ * uspoof_getSkeleton(sc, 0, str, -1, skel, len, &status);
+ * UBool result = false;
+ * for (size_t i=0; i<DICTIONARY_LENGTH; i++) {
+ * result = u_strcmp(skel, skeletons[i]) == 0;
+ * if (result == true) { break; }
+ * }
+ * // Has confusable in dictionary: 1 (status: U_ZERO_ERROR)
+ * printf("Has confusable in dictionary: %d (status: %s)\n", result, u_errorName(status));
+ * free(skel);
+ * }
+ *
+ * for (size_t i=0; i<DICTIONARY_LENGTH; i++) {
+ * free(skeletons[i]);
+ * }
+ * uspoof_close(sc);
+ * \endcode
+ *
+ * <b>Note:</b> Since the Unicode confusables mapping table is frequently updated, confusable skeletons are <em>not</em>
+ * guaranteed to be the same between ICU releases. We therefore recommend that you always compute confusable skeletons
+ * at runtime and do not rely on creating a permanent, or difficult to update, database of skeletons.
+ *
+ * <h2>Spoof Detection</h2>
+ *
+ * The following snippet shows a minimal example of using <code>USpoofChecker</code> to perform spoof detection on a
+ * string:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str = (UChar*) u"p\u0430ypal"; // with U+0430 CYRILLIC SMALL LETTER A
+ *
+ * // Get the default set of allowable characters:
+ * USet* allowed = uset_openEmpty();
+ * uset_addAll(allowed, uspoof_getRecommendedSet(&status));
+ * uset_addAll(allowed, uspoof_getInclusionSet(&status));
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setAllowedChars(sc, allowed, &status);
+ * uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE);
+ *
+ * int32_t bitmask = uspoof_check(sc, str, -1, NULL, &status);
+ * UBool result = bitmask != 0;
+ * // fails checks: 1 (status: U_ZERO_ERROR)
+ * printf("fails checks: %d (status: %s)\n", result, u_errorName(status));
+ * uspoof_close(sc);
+ * uset_close(allowed);
+ * \endcode
+ *
+ * As in the case for confusability checking, it is good practice to create one <code>USpoofChecker</code> instance at
+ * startup, and call the cheaper {@link uspoof_check} online. We specify the set of
+ * allowed characters to be those with type RECOMMENDED or INCLUSION, according to the recommendation in UTS 39.
+ *
+ * In addition to {@link uspoof_check}, the function {@link uspoof_checkUTF8} is exposed for UTF8-encoded char* strings,
+ * and {@link uspoof_checkUnicodeString} is exposed for C++ programmers.
+ *
+ * If the {@link USPOOF_AUX_INFO} check is enabled, a limited amount of information on why a string failed the checks
+ * is available in the returned bitmask. For complete information, use the {@link uspoof_check2} class of functions
+ * with a {@link USpoofCheckResult} parameter:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str = (UChar*) u"p\u0430ypal"; // with U+0430 CYRILLIC SMALL LETTER A
+ *
+ * // Get the default set of allowable characters:
+ * USet* allowed = uset_openEmpty();
+ * uset_addAll(allowed, uspoof_getRecommendedSet(&status));
+ * uset_addAll(allowed, uspoof_getInclusionSet(&status));
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setAllowedChars(sc, allowed, &status);
+ * uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE);
+ *
+ * USpoofCheckResult* checkResult = uspoof_openCheckResult(&status);
+ * int32_t bitmask = uspoof_check2(sc, str, -1, checkResult, &status);
+ *
+ * int32_t failures1 = bitmask;
+ * int32_t failures2 = uspoof_getCheckResultChecks(checkResult, &status);
+ * assert(failures1 == failures2);
+ * // checks that failed: 0x00000010 (status: U_ZERO_ERROR)
+ * printf("checks that failed: %#010x (status: %s)\n", failures1, u_errorName(status));
+ *
+ * // Cleanup:
+ * uspoof_close(sc);
+ * uset_close(allowed);
+ * uspoof_closeCheckResult(checkResult);
+ * \endcode
+ *
+ * C++ users can take advantage of a few syntactical conveniences. The following snippet is functionally
+ * equivalent to the one above:
+ *
+ * \code{.cpp}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UnicodeString str((UChar*) u"p\u0430ypal"); // with U+0430 CYRILLIC SMALL LETTER A
+ *
+ * // Get the default set of allowable characters:
+ * UnicodeSet allowed;
+ * allowed.addAll(*uspoof_getRecommendedUnicodeSet(&status));
+ * allowed.addAll(*uspoof_getInclusionUnicodeSet(&status));
+ *
+ * LocalUSpoofCheckerPointer sc(uspoof_open(&status));
+ * uspoof_setAllowedChars(sc.getAlias(), allowed.toUSet(), &status);
+ * uspoof_setRestrictionLevel(sc.getAlias(), USPOOF_MODERATELY_RESTRICTIVE);
+ *
+ * LocalUSpoofCheckResultPointer checkResult(uspoof_openCheckResult(&status));
+ * int32_t bitmask = uspoof_check2UnicodeString(sc.getAlias(), str, checkResult.getAlias(), &status);
+ *
+ * int32_t failures1 = bitmask;
+ * int32_t failures2 = uspoof_getCheckResultChecks(checkResult.getAlias(), &status);
+ * assert(failures1 == failures2);
+ * // checks that failed: 0x00000010 (status: U_ZERO_ERROR)
+ * printf("checks that failed: %#010x (status: %s)\n", failures1, u_errorName(status));
+ *
+ * // Explicit cleanup not necessary.
+ * \endcode
+ *
+ * The return value is a bitmask of the checks that failed. In this case, there was one check that failed:
+ * {@link USPOOF_RESTRICTION_LEVEL}, corresponding to the fifth bit (16). The possible checks are:
+ *
+ * <ul>
+ * <li><code>RESTRICTION_LEVEL</code>: flags strings that violate the
+ * <a href="http://unicode.org/reports/tr39/#Restriction_Level_Detection">Restriction Level</a> test as specified in UTS
+ * 39; in most cases, this means flagging strings that contain characters from multiple different scripts.</li>
+ * <li><code>INVISIBLE</code>: flags strings that contain invisible characters, such as zero-width spaces, or character
+ * sequences that are likely not to display, such as multiple occurrences of the same non-spacing mark.</li>
+ * <li><code>CHAR_LIMIT</code>: flags strings that contain characters outside of a specified set of acceptable
+ * characters. See {@link uspoof_setAllowedChars} and {@link uspoof_setAllowedLocales}.</li>
+ * <li><code>MIXED_NUMBERS</code>: flags strings that contain digits from multiple different numbering systems.</li>
+ * </ul>
+ *
+ * <p>
+ * These checks can be enabled independently of each other. For example, if you were interested in checking for only the
+ * INVISIBLE and MIXED_NUMBERS conditions, you could do:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str = (UChar*) u"8\u09EA"; // 8 mixed with U+09EA BENGALI DIGIT FOUR
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setChecks(sc, USPOOF_INVISIBLE | USPOOF_MIXED_NUMBERS, &status);
+ *
+ * int32_t bitmask = uspoof_check2(sc, str, -1, NULL, &status);
+ * UBool result = bitmask != 0;
+ * // fails checks: 1 (status: U_ZERO_ERROR)
+ * printf("fails checks: %d (status: %s)\n", result, u_errorName(status));
+ * uspoof_close(sc);
+ * \endcode
+ *
+ * Here is an example in C++ showing how to compute the restriction level of a string:
+ *
+ * \code{.cpp}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UnicodeString str((UChar*) u"p\u0430ypal"); // with U+0430 CYRILLIC SMALL LETTER A
+ *
+ * // Get the default set of allowable characters:
+ * UnicodeSet allowed;
+ * allowed.addAll(*uspoof_getRecommendedUnicodeSet(&status));
+ * allowed.addAll(*uspoof_getInclusionUnicodeSet(&status));
+ *
+ * LocalUSpoofCheckerPointer sc(uspoof_open(&status));
+ * uspoof_setAllowedChars(sc.getAlias(), allowed.toUSet(), &status);
+ * uspoof_setRestrictionLevel(sc.getAlias(), USPOOF_MODERATELY_RESTRICTIVE);
+ * uspoof_setChecks(sc.getAlias(), USPOOF_RESTRICTION_LEVEL | USPOOF_AUX_INFO, &status);
+ *
+ * LocalUSpoofCheckResultPointer checkResult(uspoof_openCheckResult(&status));
+ * int32_t bitmask = uspoof_check2UnicodeString(sc.getAlias(), str, checkResult.getAlias(), &status);
+ *
+ * URestrictionLevel restrictionLevel = uspoof_getCheckResultRestrictionLevel(checkResult.getAlias(), &status);
+ * // Since USPOOF_AUX_INFO was enabled, the restriction level is also available in the upper bits of the bitmask:
+ * assert((restrictionLevel & bitmask) == restrictionLevel);
+ * // Restriction level: 0x50000000 (status: U_ZERO_ERROR)
+ * printf("Restriction level: %#010x (status: %s)\n", restrictionLevel, u_errorName(status));
+ * \endcode
+ *
+ * The code '0x50000000' corresponds to the restriction level USPOOF_MINIMALLY_RESTRICTIVE. Since
+ * USPOOF_MINIMALLY_RESTRICTIVE is weaker than USPOOF_MODERATELY_RESTRICTIVE, the string fails the check.
+ *
+ * <b>Note:</b> The Restriction Level is the most powerful of the checks. The full logic is documented in
+ * <a href="http://unicode.org/reports/tr39/#Restriction_Level_Detection">UTS 39</a>, but the basic idea is that strings
+ * are restricted to contain characters from only a single script, <em>except</em> that most scripts are allowed to have
+ * Latin characters interspersed. Although the default restriction level is <code>HIGHLY_RESTRICTIVE</code>, it is
+ * recommended that users set their restriction level to <code>MODERATELY_RESTRICTIVE</code>, which allows Latin mixed
+ * with all other scripts except Cyrillic, Greek, and Cherokee, with which it is often confusable. For more details on
+ * the levels, see UTS 39 or {@link URestrictionLevel}. The Restriction Level test is aware of the set of
+ * allowed characters set in {@link uspoof_setAllowedChars}. Note that characters which have script code
+ * COMMON or INHERITED, such as numbers and punctuation, are ignored when computing whether a string has multiple
+ * scripts.
+ *
+ * <h2>Additional Information</h2>
+ *
+ * A <code>USpoofChecker</code> instance may be used repeatedly to perform checks on any number of identifiers.
+ *
+ * <b>Thread Safety:</b> The test functions for checking a single identifier, or for testing whether
+ * two identifiers are possible confusable, are thread safe. They may called concurrently, from multiple threads,
+ * using the same USpoofChecker instance.
+ *
+ * More generally, the standard ICU thread safety rules apply: functions that take a const USpoofChecker parameter are
+ * thread safe. Those that take a non-const USpoofChecker are not thread safe..
+ *
+ * @stable ICU 4.6
+ */
+
+U_CDECL_BEGIN
+
+struct USpoofChecker;
+/**
+ * @stable ICU 4.2
+ */
+typedef struct USpoofChecker USpoofChecker; /**< typedef for C of USpoofChecker */
+
+struct USpoofCheckResult;
+/**
+ * @see uspoof_openCheckResult
+ * @stable ICU 58
+ */
+typedef struct USpoofCheckResult USpoofCheckResult;
+
+/**
+ * Enum for the kinds of checks that USpoofChecker can perform.
+ * These enum values are used both to select the set of checks that
+ * will be performed, and to report results from the check function.
+ *
+ * @stable ICU 4.2
+ */
+typedef enum USpoofChecks {
+ /**
+ * When performing the two-string {@link uspoof_areConfusable} test, this flag in the return value indicates
+ * that the two strings are visually confusable and that they are from the same script, according to UTS 39 section
+ * 4.
+ *
+ * @see uspoof_areConfusable
+ * @stable ICU 4.2
+ */
+ USPOOF_SINGLE_SCRIPT_CONFUSABLE = 1,
+
+ /**
+ * When performing the two-string {@link uspoof_areConfusable} test, this flag in the return value indicates
+ * that the two strings are visually confusable and that they are <b>not</b> from the same script, according to UTS
+ * 39 section 4.
+ *
+ * @see uspoof_areConfusable
+ * @stable ICU 4.2
+ */
+ USPOOF_MIXED_SCRIPT_CONFUSABLE = 2,
+
+ /**
+ * When performing the two-string {@link uspoof_areConfusable} test, this flag in the return value indicates
+ * that the two strings are visually confusable and that they are not from the same script but both of them are
+ * single-script strings, according to UTS 39 section 4.
+ *
+ * @see uspoof_areConfusable
+ * @stable ICU 4.2
+ */
+ USPOOF_WHOLE_SCRIPT_CONFUSABLE = 4,
+
+ /**
+ * Enable this flag in {@link uspoof_setChecks} to turn on all types of confusables. You may set
+ * the checks to some subset of SINGLE_SCRIPT_CONFUSABLE, MIXED_SCRIPT_CONFUSABLE, or WHOLE_SCRIPT_CONFUSABLE to
+ * make {@link uspoof_areConfusable} return only those types of confusables.
+ *
+ * @see uspoof_areConfusable
+ * @see uspoof_getSkeleton
+ * @stable ICU 58
+ */
+ USPOOF_CONFUSABLE = USPOOF_SINGLE_SCRIPT_CONFUSABLE | USPOOF_MIXED_SCRIPT_CONFUSABLE | USPOOF_WHOLE_SCRIPT_CONFUSABLE,
+
+#ifndef U_HIDE_DEPRECATED_API
+ /**
+ * This flag is deprecated and no longer affects the behavior of SpoofChecker.
+ *
+ * @deprecated ICU 58 Any case confusable mappings were removed from UTS 39; the corresponding ICU API was deprecated.
+ */
+ USPOOF_ANY_CASE = 8,
+#endif /* U_HIDE_DEPRECATED_API */
+
+ /**
+ * Check that an identifier is no looser than the specified RestrictionLevel.
+ * The default if {@link uspoof_setRestrictionLevel} is not called is HIGHLY_RESTRICTIVE.
+ *
+ * If USPOOF_AUX_INFO is enabled the actual restriction level of the
+ * identifier being tested will also be returned by uspoof_check().
+ *
+ * @see URestrictionLevel
+ * @see uspoof_setRestrictionLevel
+ * @see USPOOF_AUX_INFO
+ *
+ * @stable ICU 51
+ */
+ USPOOF_RESTRICTION_LEVEL = 16,
+
+#ifndef U_HIDE_DEPRECATED_API
+ /** Check that an identifier contains only characters from a
+ * single script (plus chars from the common and inherited scripts.)
+ * Applies to checks of a single identifier check only.
+ * @deprecated ICU 51 Use RESTRICTION_LEVEL instead.
+ */
+ USPOOF_SINGLE_SCRIPT = USPOOF_RESTRICTION_LEVEL,
+#endif /* U_HIDE_DEPRECATED_API */
+
+ /** Check an identifier for the presence of invisible characters,
+ * such as zero-width spaces, or character sequences that are
+ * likely not to display, such as multiple occurrences of the same
+ * non-spacing mark. This check does not test the input string as a whole
+ * for conformance to any particular syntax for identifiers.
+ */
+ USPOOF_INVISIBLE = 32,
+
+ /** Check that an identifier contains only characters from a specified set
+ * of acceptable characters. See {@link uspoof_setAllowedChars} and
+ * {@link uspoof_setAllowedLocales}. Note that a string that fails this check
+ * will also fail the {@link USPOOF_RESTRICTION_LEVEL} check.
+ */
+ USPOOF_CHAR_LIMIT = 64,
+
+ /**
+ * Check that an identifier does not mix numbers from different numbering systems.
+ * For more information, see UTS 39 section 5.3.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_MIXED_NUMBERS = 128,
+
+ /**
+ * Check that an identifier does not have a combining character following a character in which that
+ * combining character would be hidden; for example 'i' followed by a U+0307 combining dot.
+ *
+ * More specifically, the following characters are forbidden from preceding a U+0307:
+ * <ul>
+ * <li>Those with the Soft_Dotted Unicode property (which includes 'i' and 'j')</li>
+ * <li>Latin lowercase letter 'l'</li>
+ * <li>Dotless 'i' and 'j' ('ı' and 'ȷ', U+0131 and U+0237)</li>
+ * <li>Any character whose confusable prototype ends with such a character
+ * (Soft_Dotted, 'l', 'ı', or 'ȷ')</li>
+ * </ul>
+ * In addition, combining characters are allowed between the above characters and U+0307 except those
+ * with combining class 0 or combining class "Above" (230, same class as U+0307).
+ *
+ * This list and the number of combing characters considered by this check may grow over time.
+ *
+ * @stable ICU 62
+ */
+ USPOOF_HIDDEN_OVERLAY = 256,
+
+ /**
+ * Enable all spoof checks.
+ *
+ * @stable ICU 4.6
+ */
+ USPOOF_ALL_CHECKS = 0xFFFF,
+
+ /**
+ * Enable the return of auxiliary (non-error) information in the
+ * upper bits of the check results value.
+ *
+ * If this "check" is not enabled, the results of {@link uspoof_check} will be
+ * zero when an identifier passes all of the enabled checks.
+ *
+ * If this "check" is enabled, (uspoof_check() & {@link USPOOF_ALL_CHECKS}) will
+ * be zero when an identifier passes all checks.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_AUX_INFO = 0x40000000
+
+ } USpoofChecks;
+
+
+ /**
+ * Constants from UAX #39 for use in {@link uspoof_setRestrictionLevel}, and
+ * for returned identifier restriction levels in check results.
+ *
+ * @stable ICU 51
+ *
+ * @see uspoof_setRestrictionLevel
+ * @see uspoof_check
+ */
+ typedef enum URestrictionLevel {
+ /**
+ * All characters in the string are in the identifier profile and all characters in the string are in the
+ * ASCII range.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_ASCII = 0x10000000,
+ /**
+ * The string classifies as ASCII-Only, or all characters in the string are in the identifier profile and
+ * the string is single-script, according to the definition in UTS 39 section 5.1.
+ *
+ * @stable ICU 53
+ */
+ USPOOF_SINGLE_SCRIPT_RESTRICTIVE = 0x20000000,
+ /**
+ * The string classifies as Single Script, or all characters in the string are in the identifier profile and
+ * the string is covered by any of the following sets of scripts, according to the definition in UTS 39
+ * section 5.1:
+ * <ul>
+ * <li>Latin + Han + Bopomofo (or equivalently: Latn + Hanb)</li>
+ * <li>Latin + Han + Hiragana + Katakana (or equivalently: Latn + Jpan)</li>
+ * <li>Latin + Han + Hangul (or equivalently: Latn +Kore)</li>
+ * </ul>
+ * This is the default restriction in ICU.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_HIGHLY_RESTRICTIVE = 0x30000000,
+ /**
+ * The string classifies as Highly Restrictive, or all characters in the string are in the identifier profile
+ * and the string is covered by Latin and any one other Recommended or Aspirational script, except Cyrillic,
+ * Greek, and Cherokee.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_MODERATELY_RESTRICTIVE = 0x40000000,
+ /**
+ * All characters in the string are in the identifier profile. Allow arbitrary mixtures of scripts.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_MINIMALLY_RESTRICTIVE = 0x50000000,
+ /**
+ * Any valid identifiers, including characters outside of the Identifier Profile.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_UNRESTRICTIVE = 0x60000000,
+ /**
+ * Mask for selecting the Restriction Level bits from the return value of {@link uspoof_check}.
+ *
+ * @stable ICU 53
+ */
+ USPOOF_RESTRICTION_LEVEL_MASK = 0x7F000000,
+#ifndef U_HIDE_INTERNAL_API
+ /**
+ * An undefined restriction level.
+ * @internal
+ */
+ USPOOF_UNDEFINED_RESTRICTIVE = -1
+#endif /* U_HIDE_INTERNAL_API */
+ } URestrictionLevel;
+
+/**
+ * Create a Unicode Spoof Checker, configured to perform all
+ * checks except for USPOOF_LOCALE_LIMIT and USPOOF_CHAR_LIMIT.
+ * Note that additional checks may be added in the future,
+ * resulting in the changes to the default checking behavior.
+ *
+ * @param status The error code, set if this function encounters a problem.
+ * @return the newly created Spoof Checker
+ * @stable ICU 4.2
+ */
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_open(UErrorCode *status);
+
+
+/**
+ * Open a Spoof checker from its serialized form, stored in 32-bit-aligned memory.
+ * Inverse of uspoof_serialize().
+ * The memory containing the serialized data must remain valid and unchanged
+ * as long as the spoof checker, or any cloned copies of the spoof checker,
+ * are in use. Ownership of the memory remains with the caller.
+ * The spoof checker (and any clones) must be closed prior to deleting the
+ * serialized data.
+ *
+ * @param data a pointer to 32-bit-aligned memory containing the serialized form of spoof data
+ * @param length the number of bytes available at data;
+ * can be more than necessary
+ * @param pActualLength receives the actual number of bytes at data taken up by the data;
+ * can be NULL
+ * @param pErrorCode ICU error code
+ * @return the spoof checker.
+ *
+ * @see uspoof_open
+ * @see uspoof_serialize
+ * @stable ICU 4.2
+ */
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_openFromSerialized(const void *data, int32_t length, int32_t *pActualLength,
+ UErrorCode *pErrorCode);
+
+/**
+ * Open a Spoof Checker from the source form of the spoof data.
+ * The input corresponds to the Unicode data file confusables.txt
+ * as described in Unicode UAX #39. The syntax of the source data
+ * is as described in UAX #39 for this file, and the content of
+ * this file is acceptable input.
+ *
+ * The character encoding of the (char *) input text is UTF-8.
+ *
+ * @param confusables a pointer to the confusable characters definitions,
+ * as found in file confusables.txt from unicode.org.
+ * @param confusablesLen The length of the confusables text, or -1 if the
+ * input string is zero terminated.
+ * @param confusablesWholeScript
+ * Deprecated in ICU 58. No longer used.
+ * @param confusablesWholeScriptLen
+ * Deprecated in ICU 58. No longer used.
+ * @param errType In the event of an error in the input, indicates
+ * which of the input files contains the error.
+ * The value is one of USPOOF_SINGLE_SCRIPT_CONFUSABLE or
+ * USPOOF_WHOLE_SCRIPT_CONFUSABLE, or
+ * zero if no errors are found.
+ * @param pe In the event of an error in the input, receives the position
+ * in the input text (line, offset) of the error.
+ * @param status an in/out ICU UErrorCode. Among the possible errors is
+ * U_PARSE_ERROR, which is used to report syntax errors
+ * in the input.
+ * @return A spoof checker that uses the rules from the input files.
+ * @stable ICU 4.2
+ */
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_openFromSource(const char *confusables, int32_t confusablesLen,
+ const char *confusablesWholeScript, int32_t confusablesWholeScriptLen,
+ int32_t *errType, UParseError *pe, UErrorCode *status);
+
+
+/**
+ * Close a Spoof Checker, freeing any memory that was being held by
+ * its implementation.
+ * @stable ICU 4.2
+ */
+U_CAPI void U_EXPORT2
+uspoof_close(USpoofChecker *sc);
+
+/**
+ * Clone a Spoof Checker. The clone will be set to perform the same checks
+ * as the original source.
+ *
+ * @param sc The source USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return
+ * @stable ICU 4.2
+ */
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_clone(const USpoofChecker *sc, UErrorCode *status);
+
+
+/**
+ * Specify the bitmask of checks that will be performed by {@link uspoof_check}. Calling this method
+ * overwrites any checks that may have already been enabled. By default, all checks are enabled.
+ *
+ * To enable specific checks and disable all others,
+ * OR together only the bit constants for the desired checks.
+ * For example, to fail strings containing characters outside of
+ * the set specified by {@link uspoof_setAllowedChars} and
+ * also strings that contain digits from mixed numbering systems:
+ *
+ * <pre>
+ * {@code
+ * uspoof_setChecks(USPOOF_CHAR_LIMIT | USPOOF_MIXED_NUMBERS);
+ * }
+ * </pre>
+ *
+ * To disable specific checks and enable all others,
+ * start with ALL_CHECKS and "AND away" the not-desired checks.
+ * For example, if you are not planning to use the {@link uspoof_areConfusable} functionality,
+ * it is good practice to disable the CONFUSABLE check:
+ *
+ * <pre>
+ * {@code
+ * uspoof_setChecks(USPOOF_ALL_CHECKS & ~USPOOF_CONFUSABLE);
+ * }
+ * </pre>
+ *
+ * Note that methods such as {@link uspoof_setAllowedChars}, {@link uspoof_setAllowedLocales}, and
+ * {@link uspoof_setRestrictionLevel} will enable certain checks when called. Those methods will OR the check they
+ * enable onto the existing bitmask specified by this method. For more details, see the documentation of those
+ * methods.
+ *
+ * @param sc The USpoofChecker
+ * @param checks The set of checks that this spoof checker will perform.
+ * The value is a bit set, obtained by OR-ing together
+ * values from enum USpoofChecks.
+ * @param status The error code, set if this function encounters a problem.
+ * @stable ICU 4.2
+ *
+ */
+U_CAPI void U_EXPORT2
+uspoof_setChecks(USpoofChecker *sc, int32_t checks, UErrorCode *status);
+
+/**
+ * Get the set of checks that this Spoof Checker has been configured to perform.
+ *
+ * @param sc The USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return The set of checks that this spoof checker will perform.
+ * The value is a bit set, obtained by OR-ing together
+ * values from enum USpoofChecks.
+ * @stable ICU 4.2
+ *
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_getChecks(const USpoofChecker *sc, UErrorCode *status);
+
+/**
+ * Set the loosest restriction level allowed for strings. The default if this is not called is
+ * {@link USPOOF_HIGHLY_RESTRICTIVE}. Calling this method enables the {@link USPOOF_RESTRICTION_LEVEL} and
+ * {@link USPOOF_MIXED_NUMBERS} checks, corresponding to Sections 5.1 and 5.2 of UTS 39. To customize which checks are
+ * to be performed by {@link uspoof_check}, see {@link uspoof_setChecks}.
+ *
+ * @param sc The USpoofChecker
+ * @param restrictionLevel The loosest restriction level allowed.
+ * @see URestrictionLevel
+ * @stable ICU 51
+ */
+U_CAPI void U_EXPORT2
+uspoof_setRestrictionLevel(USpoofChecker *sc, URestrictionLevel restrictionLevel);
+
+
+/**
+ * Get the Restriction Level that will be tested if the checks include {@link USPOOF_RESTRICTION_LEVEL}.
+ *
+ * @return The restriction level
+ * @see URestrictionLevel
+ * @stable ICU 51
+ */
+U_CAPI URestrictionLevel U_EXPORT2
+uspoof_getRestrictionLevel(const USpoofChecker *sc);
+
+/**
+ * Limit characters that are acceptable in identifiers being checked to those
+ * normally used with the languages associated with the specified locales.
+ * Any previously specified list of locales is replaced by the new settings.
+ *
+ * A set of languages is determined from the locale(s), and
+ * from those a set of acceptable Unicode scripts is determined.
+ * Characters from this set of scripts, along with characters from
+ * the "common" and "inherited" Unicode Script categories
+ * will be permitted.
+ *
+ * Supplying an empty string removes all restrictions;
+ * characters from any script will be allowed.
+ *
+ * The {@link USPOOF_CHAR_LIMIT} test is automatically enabled for this
+ * USpoofChecker when calling this function with a non-empty list
+ * of locales.
+ *
+ * The Unicode Set of characters that will be allowed is accessible
+ * via the uspoof_getAllowedChars() function. uspoof_setAllowedLocales()
+ * will <i>replace</i> any previously applied set of allowed characters.
+ *
+ * Adjustments, such as additions or deletions of certain classes of characters,
+ * can be made to the result of uspoof_setAllowedLocales() by
+ * fetching the resulting set with uspoof_getAllowedChars(),
+ * manipulating it with the Unicode Set API, then resetting the
+ * spoof detectors limits with uspoof_setAllowedChars().
+ *
+ * @param sc The USpoofChecker
+ * @param localesList A list list of locales, from which the language
+ * and associated script are extracted. The locales
+ * are comma-separated if there is more than one.
+ * White space may not appear within an individual locale,
+ * but is ignored otherwise.
+ * The locales are syntactically like those from the
+ * HTTP Accept-Language header.
+ * If the localesList is empty, no restrictions will be placed on
+ * the allowed characters.
+ *
+ * @param status The error code, set if this function encounters a problem.
+ * @stable ICU 4.2
+ */
+U_CAPI void U_EXPORT2
+uspoof_setAllowedLocales(USpoofChecker *sc, const char *localesList, UErrorCode *status);
+
+/**
+ * Get a list of locales for the scripts that are acceptable in strings
+ * to be checked. If no limitations on scripts have been specified,
+ * an empty string will be returned.
+ *
+ * uspoof_setAllowedChars() will reset the list of allowed to be empty.
+ *
+ * The format of the returned list is the same as that supplied to
+ * uspoof_setAllowedLocales(), but returned list may not be identical
+ * to the originally specified string; the string may be reformatted,
+ * and information other than languages from
+ * the originally specified locales may be omitted.
+ *
+ * @param sc The USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return A string containing a list of locales corresponding
+ * to the acceptable scripts, formatted like an
+ * HTTP Accept Language value.
+ *
+ * @stable ICU 4.2
+ */
+U_CAPI const char * U_EXPORT2
+uspoof_getAllowedLocales(USpoofChecker *sc, UErrorCode *status);
+
+
+/**
+ * Limit the acceptable characters to those specified by a Unicode Set.
+ * Any previously specified character limit is
+ * is replaced by the new settings. This includes limits on
+ * characters that were set with the uspoof_setAllowedLocales() function.
+ *
+ * The USPOOF_CHAR_LIMIT test is automatically enabled for this
+ * USpoofChecker by this function.
+ *
+ * @param sc The USpoofChecker
+ * @param chars A Unicode Set containing the list of
+ * characters that are permitted. Ownership of the set
+ * remains with the caller. The incoming set is cloned by
+ * this function, so there are no restrictions on modifying
+ * or deleting the USet after calling this function.
+ * @param status The error code, set if this function encounters a problem.
+ * @stable ICU 4.2
+ */
+U_CAPI void U_EXPORT2
+uspoof_setAllowedChars(USpoofChecker *sc, const USet *chars, UErrorCode *status);
+
+
+/**
+ * Get a USet for the characters permitted in an identifier.
+ * This corresponds to the limits imposed by the Set Allowed Characters
+ * functions. Limitations imposed by other checks will not be
+ * reflected in the set returned by this function.
+ *
+ * The returned set will be frozen, meaning that it cannot be modified
+ * by the caller.
+ *
+ * Ownership of the returned set remains with the Spoof Detector. The
+ * returned set will become invalid if the spoof detector is closed,
+ * or if a new set of allowed characters is specified.
+ *
+ *
+ * @param sc The USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return A USet containing the characters that are permitted by
+ * the USPOOF_CHAR_LIMIT test.
+ * @stable ICU 4.2
+ */
+U_CAPI const USet * U_EXPORT2
+uspoof_getAllowedChars(const USpoofChecker *sc, UErrorCode *status);
+
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * \note
+ * Consider using the newer API, {@link uspoof_check2}, instead.
+ * The newer API exposes additional information from the check procedure
+ * and is otherwise identical to this method.
+ *
+ * @param sc The USpoofChecker
+ * @param id The identifier to be checked for possible security issues,
+ * in UTF-16 format.
+ * @param length the length of the string to be checked, expressed in
+ * 16 bit UTF-16 code units, or -1 if the string is
+ * zero terminated.
+ * @param position Deprecated in ICU 51. Always returns zero.
+ * Originally, an out parameter for the index of the first
+ * string position that failed a check.
+ * This parameter may be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks.
+ * @see uspoof_check2
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_check(const USpoofChecker *sc,
+ const UChar *id, int32_t length,
+ int32_t *position,
+ UErrorCode *status);
+
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * \note
+ * Consider using the newer API, {@link uspoof_check2UTF8}, instead.
+ * The newer API exposes additional information from the check procedure
+ * and is otherwise identical to this method.
+ *
+ * @param sc The USpoofChecker
+ * @param id A identifier to be checked for possible security issues, in UTF8 format.
+ * @param length the length of the string to be checked, or -1 if the string is
+ * zero terminated.
+ * @param position Deprecated in ICU 51. Always returns zero.
+ * Originally, an out parameter for the index of the first
+ * string position that failed a check.
+ * This parameter may be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * If the input contains invalid UTF-8 sequences,
+ * a status of U_INVALID_CHAR_FOUND will be returned.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks.
+ * @see uspoof_check2UTF8
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_checkUTF8(const USpoofChecker *sc,
+ const char *id, int32_t length,
+ int32_t *position,
+ UErrorCode *status);
+
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * @param sc The USpoofChecker
+ * @param id The identifier to be checked for possible security issues,
+ * in UTF-16 format.
+ * @param length the length of the string to be checked, or -1 if the string is
+ * zero terminated.
+ * @param checkResult An instance of USpoofCheckResult to be filled with
+ * details about the identifier. Can be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks. Any information in this bitmask will be
+ * consistent with the information saved in the optional
+ * checkResult parameter.
+ * @see uspoof_openCheckResult
+ * @see uspoof_check2UTF8
+ * @see uspoof_check2UnicodeString
+ * @stable ICU 58
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_check2(const USpoofChecker *sc,
+ const UChar* id, int32_t length,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status);
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * This version of {@link uspoof_check} accepts a USpoofCheckResult, which
+ * returns additional information about the identifier. For more
+ * information, see {@link uspoof_openCheckResult}.
+ *
+ * @param sc The USpoofChecker
+ * @param id A identifier to be checked for possible security issues, in UTF8 format.
+ * @param length the length of the string to be checked, or -1 if the string is
+ * zero terminated.
+ * @param checkResult An instance of USpoofCheckResult to be filled with
+ * details about the identifier. Can be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks. Any information in this bitmask will be
+ * consistent with the information saved in the optional
+ * checkResult parameter.
+ * @see uspoof_openCheckResult
+ * @see uspoof_check2
+ * @see uspoof_check2UnicodeString
+ * @stable ICU 58
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_check2UTF8(const USpoofChecker *sc,
+ const char *id, int32_t length,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status);
+
+/**
+ * Create a USpoofCheckResult, used by the {@link uspoof_check2} class of functions to return
+ * information about the identifier. Information includes:
+ * <ul>
+ * <li>A bitmask of the checks that failed</li>
+ * <li>The identifier's restriction level (UTS 39 section 5.2)</li>
+ * <li>The set of numerics in the string (UTS 39 section 5.3)</li>
+ * </ul>
+ * The data held in a USpoofCheckResult is cleared whenever it is passed into a new call
+ * of {@link uspoof_check2}.
+ *
+ * @param status The error code, set if this function encounters a problem.
+ * @return the newly created USpoofCheckResult
+ * @see uspoof_check2
+ * @see uspoof_check2UTF8
+ * @see uspoof_check2UnicodeString
+ * @stable ICU 58
+ */
+U_CAPI USpoofCheckResult* U_EXPORT2
+uspoof_openCheckResult(UErrorCode *status);
+
+/**
+ * Close a USpoofCheckResult, freeing any memory that was being held by
+ * its implementation.
+ *
+ * @param checkResult The instance of USpoofCheckResult to close
+ * @stable ICU 58
+ */
+U_CAPI void U_EXPORT2
+uspoof_closeCheckResult(USpoofCheckResult *checkResult);
+
+/**
+ * Indicates which of the spoof check(s) have failed. The value is a bitwise OR of the constants for the tests
+ * in question: USPOOF_RESTRICTION_LEVEL, USPOOF_CHAR_LIMIT, and so on.
+ *
+ * @param checkResult The instance of USpoofCheckResult created by {@link uspoof_openCheckResult}
+ * @param status The error code, set if an error occurred.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks.
+ * @see uspoof_setChecks
+ * @stable ICU 58
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_getCheckResultChecks(const USpoofCheckResult *checkResult, UErrorCode *status);
+
+/**
+ * Gets the restriction level that the text meets, if the USPOOF_RESTRICTION_LEVEL check
+ * was enabled; otherwise, undefined.
+ *
+ * @param checkResult The instance of USpoofCheckResult created by {@link uspoof_openCheckResult}
+ * @param status The error code, set if an error occurred.
+ * @return The restriction level contained in the USpoofCheckResult
+ * @see uspoof_setRestrictionLevel
+ * @stable ICU 58
+ */
+U_CAPI URestrictionLevel U_EXPORT2
+uspoof_getCheckResultRestrictionLevel(const USpoofCheckResult *checkResult, UErrorCode *status);
+
+/**
+ * Gets the set of numerics found in the string, if the USPOOF_MIXED_NUMBERS check was enabled;
+ * otherwise, undefined. The set will contain the zero digit from each decimal number system found
+ * in the input string. Ownership of the returned USet remains with the USpoofCheckResult.
+ * The USet will be free'd when {@link uspoof_closeCheckResult} is called.
+ *
+ * @param checkResult The instance of USpoofCheckResult created by {@link uspoof_openCheckResult}
+ * @return The set of numerics contained in the USpoofCheckResult
+ * @param status The error code, set if an error occurred.
+ * @stable ICU 58
+ */
+U_CAPI const USet* U_EXPORT2
+uspoof_getCheckResultNumerics(const USpoofCheckResult *checkResult, UErrorCode *status);
+
+
+/**
+ * Check the whether two specified strings are visually confusable.
+ *
+ * If the strings are confusable, the return value will be nonzero, as long as
+ * {@link USPOOF_CONFUSABLE} was enabled in uspoof_setChecks().
+ *
+ * The bits in the return value correspond to flags for each of the classes of
+ * confusables applicable to the two input strings. According to UTS 39
+ * section 4, the possible flags are:
+ *
+ * <ul>
+ * <li>{@link USPOOF_SINGLE_SCRIPT_CONFUSABLE}</li>
+ * <li>{@link USPOOF_MIXED_SCRIPT_CONFUSABLE}</li>
+ * <li>{@link USPOOF_WHOLE_SCRIPT_CONFUSABLE}</li>
+ * </ul>
+ *
+ * If one or more of the above flags were not listed in uspoof_setChecks(), this
+ * function will never report that class of confusable. The check
+ * {@link USPOOF_CONFUSABLE} enables all three flags.
+ *
+ *
+ * @param sc The USpoofChecker
+ * @param id1 The first of the two identifiers to be compared for
+ * confusability. The strings are in UTF-16 format.
+ * @param length1 the length of the first identifier, expressed in
+ * 16 bit UTF-16 code units, or -1 if the string is
+ * nul terminated.
+ * @param id2 The second of the two identifiers to be compared for
+ * confusability. The identifiers are in UTF-16 format.
+ * @param length2 The length of the second identifiers, expressed in
+ * 16 bit UTF-16 code units, or -1 if the string is
+ * nul terminated.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Confusability of the identifiers is not reported here,
+ * but through this function's return value.
+ * @return An integer value with bit(s) set corresponding to
+ * the type of confusability found, as defined by
+ * enum USpoofChecks. Zero is returned if the identifiers
+ * are not confusable.
+ *
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusable(const USpoofChecker *sc,
+ const UChar *id1, int32_t length1,
+ const UChar *id2, int32_t length2,
+ UErrorCode *status);
+
+
+
+/**
+ * A version of {@link uspoof_areConfusable} accepting strings in UTF-8 format.
+ *
+ * @param sc The USpoofChecker
+ * @param id1 The first of the two identifiers to be compared for
+ * confusability. The strings are in UTF-8 format.
+ * @param length1 the length of the first identifiers, in bytes, or -1
+ * if the string is nul terminated.
+ * @param id2 The second of the two identifiers to be compared for
+ * confusability. The strings are in UTF-8 format.
+ * @param length2 The length of the second string in bytes, or -1
+ * if the string is nul terminated.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Confusability of the strings is not reported here,
+ * but through this function's return value.
+ * @return An integer value with bit(s) set corresponding to
+ * the type of confusability found, as defined by
+ * enum USpoofChecks. Zero is returned if the strings
+ * are not confusable.
+ *
+ * @stable ICU 4.2
+ *
+ * @see uspoof_areConfusable
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusableUTF8(const USpoofChecker *sc,
+ const char *id1, int32_t length1,
+ const char *id2, int32_t length2,
+ UErrorCode *status);
+
+
+
+
+/**
+ * Get the "skeleton" for an identifier.
+ * Skeletons are a transformation of the input identifier;
+ * Two identifiers are confusable if their skeletons are identical.
+ * See Unicode UAX #39 for additional information.
+ *
+ * Using skeletons directly makes it possible to quickly check
+ * whether an identifier is confusable with any of some large
+ * set of existing identifiers, by creating an efficiently
+ * searchable collection of the skeletons.
+ *
+ * @param sc The USpoofChecker
+ * @param type Deprecated in ICU 58. You may pass any number.
+ * Originally, controlled which of the Unicode confusable data
+ * tables to use.
+ * @param id The input identifier whose skeleton will be computed.
+ * @param length The length of the input identifier, expressed in 16 bit
+ * UTF-16 code units, or -1 if the string is zero terminated.
+ * @param dest The output buffer, to receive the skeleton string.
+ * @param destCapacity The length of the output buffer, in 16 bit units.
+ * The destCapacity may be zero, in which case the function will
+ * return the actual length of the skeleton.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * @return The length of the skeleton string. The returned length
+ * is always that of the complete skeleton, even when the
+ * supplied buffer is too small (or of zero length)
+ *
+ * @stable ICU 4.2
+ * @see uspoof_areConfusable
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_getSkeleton(const USpoofChecker *sc,
+ uint32_t type,
+ const UChar *id, int32_t length,
+ UChar *dest, int32_t destCapacity,
+ UErrorCode *status);
+
+/**
+ * Get the "skeleton" for an identifier.
+ * Skeletons are a transformation of the input identifier;
+ * Two identifiers are confusable if their skeletons are identical.
+ * See Unicode UAX #39 for additional information.
+ *
+ * Using skeletons directly makes it possible to quickly check
+ * whether an identifier is confusable with any of some large
+ * set of existing identifiers, by creating an efficiently
+ * searchable collection of the skeletons.
+ *
+ * @param sc The USpoofChecker
+ * @param type Deprecated in ICU 58. You may pass any number.
+ * Originally, controlled which of the Unicode confusable data
+ * tables to use.
+ * @param id The UTF-8 format identifier whose skeleton will be computed.
+ * @param length The length of the input string, in bytes,
+ * or -1 if the string is zero terminated.
+ * @param dest The output buffer, to receive the skeleton string.
+ * @param destCapacity The length of the output buffer, in bytes.
+ * The destCapacity may be zero, in which case the function will
+ * return the actual length of the skeleton.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check. Possible Errors include U_INVALID_CHAR_FOUND
+ * for invalid UTF-8 sequences, and
+ * U_BUFFER_OVERFLOW_ERROR if the destination buffer is too small
+ * to hold the complete skeleton.
+ * @return The length of the skeleton string, in bytes. The returned length
+ * is always that of the complete skeleton, even when the
+ * supplied buffer is too small (or of zero length)
+ *
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_getSkeletonUTF8(const USpoofChecker *sc,
+ uint32_t type,
+ const char *id, int32_t length,
+ char *dest, int32_t destCapacity,
+ UErrorCode *status);
+
+/**
+ * Get the set of Candidate Characters for Inclusion in Identifiers, as defined
+ * in http://unicode.org/Public/security/latest/xidmodifications.txt
+ * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms.
+ *
+ * The returned set is frozen. Ownership of the set remains with the ICU library; it must not
+ * be deleted by the caller.
+ *
+ * @param status The error code, set if a problem occurs while creating the set.
+ *
+ * @stable ICU 51
+ */
+U_CAPI const USet * U_EXPORT2
+uspoof_getInclusionSet(UErrorCode *status);
+
+/**
+ * Get the set of characters from Recommended Scripts for Inclusion in Identifiers, as defined
+ * in http://unicode.org/Public/security/latest/xidmodifications.txt
+ * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms.
+ *
+ * The returned set is frozen. Ownership of the set remains with the ICU library; it must not
+ * be deleted by the caller.
+ *
+ * @param status The error code, set if a problem occurs while creating the set.
+ *
+ * @stable ICU 51
+ */
+U_CAPI const USet * U_EXPORT2
+uspoof_getRecommendedSet(UErrorCode *status);
+
+/**
+ * Serialize the data for a spoof detector into a chunk of memory.
+ * The flattened spoof detection tables can later be used to efficiently
+ * instantiate a new Spoof Detector.
+ *
+ * The serialized spoof checker includes only the data compiled from the
+ * Unicode data tables by uspoof_openFromSource(); it does not include
+ * include any other state or configuration that may have been set.
+ *
+ * @param sc the Spoof Detector whose data is to be serialized.
+ * @param data a pointer to 32-bit-aligned memory to be filled with the data,
+ * can be NULL if capacity==0
+ * @param capacity the number of bytes available at data,
+ * or 0 for preflighting
+ * @param status an in/out ICU UErrorCode; possible errors include:
+ * - U_BUFFER_OVERFLOW_ERROR if the data storage block is too small for serialization
+ * - U_ILLEGAL_ARGUMENT_ERROR the data or capacity parameters are bad
+ * @return the number of bytes written or needed for the spoof data
+ *
+ * @see utrie2_openFromSerialized()
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_serialize(USpoofChecker *sc,
+ void *data, int32_t capacity,
+ UErrorCode *status);
+
+U_CDECL_END
+
+#if U_SHOW_CPLUSPLUS_API
+
+U_NAMESPACE_BEGIN
+
+/**
+ * \class LocalUSpoofCheckerPointer
+ * "Smart pointer" class, closes a USpoofChecker via uspoof_close().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 4.4
+ */
+/**
+ * \cond
+ * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER.
+ * For now, suppress with a Doxygen cond
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckerPointer, USpoofChecker, uspoof_close);
+/** \endcond */
+
+/**
+ * \class LocalUSpoofCheckResultPointer
+ * "Smart pointer" class, closes a USpoofCheckResult via `uspoof_closeCheckResult()`.
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 58
+ */
+
+/**
+ * \cond
+ * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER.
+ * For now, suppress with a Doxygen cond
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckResultPointer, USpoofCheckResult, uspoof_closeCheckResult);
+/** \endcond */
+
+U_NAMESPACE_END
+
+/**
+ * Limit the acceptable characters to those specified by a Unicode Set.
+ * Any previously specified character limit is
+ * is replaced by the new settings. This includes limits on
+ * characters that were set with the uspoof_setAllowedLocales() function.
+ *
+ * The USPOOF_CHAR_LIMIT test is automatically enabled for this
+ * USoofChecker by this function.
+ *
+ * @param sc The USpoofChecker
+ * @param chars A Unicode Set containing the list of
+ * characters that are permitted. Ownership of the set
+ * remains with the caller. The incoming set is cloned by
+ * this function, so there are no restrictions on modifying
+ * or deleting the UnicodeSet after calling this function.
+ * @param status The error code, set if this function encounters a problem.
+ * @stable ICU 4.2
+ */
+U_CAPI void U_EXPORT2
+uspoof_setAllowedUnicodeSet(USpoofChecker *sc, const icu::UnicodeSet *chars, UErrorCode *status);
+
+
+/**
+ * Get a UnicodeSet for the characters permitted in an identifier.
+ * This corresponds to the limits imposed by the Set Allowed Characters /
+ * UnicodeSet functions. Limitations imposed by other checks will not be
+ * reflected in the set returned by this function.
+ *
+ * The returned set will be frozen, meaning that it cannot be modified
+ * by the caller.
+ *
+ * Ownership of the returned set remains with the Spoof Detector. The
+ * returned set will become invalid if the spoof detector is closed,
+ * or if a new set of allowed characters is specified.
+ *
+ *
+ * @param sc The USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return A UnicodeSet containing the characters that are permitted by
+ * the USPOOF_CHAR_LIMIT test.
+ * @stable ICU 4.2
+ */
+U_CAPI const icu::UnicodeSet * U_EXPORT2
+uspoof_getAllowedUnicodeSet(const USpoofChecker *sc, UErrorCode *status);
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * \note
+ * Consider using the newer API, {@link uspoof_check2UnicodeString}, instead.
+ * The newer API exposes additional information from the check procedure
+ * and is otherwise identical to this method.
+ *
+ * @param sc The USpoofChecker
+ * @param id A identifier to be checked for possible security issues.
+ * @param position Deprecated in ICU 51. Always returns zero.
+ * Originally, an out parameter for the index of the first
+ * string position that failed a check.
+ * This parameter may be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks.
+ * @see uspoof_check2UnicodeString
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_checkUnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id,
+ int32_t *position,
+ UErrorCode *status);
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * @param sc The USpoofChecker
+ * @param id A identifier to be checked for possible security issues.
+ * @param checkResult An instance of USpoofCheckResult to be filled with
+ * details about the identifier. Can be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks. Any information in this bitmask will be
+ * consistent with the information saved in the optional
+ * checkResult parameter.
+ * @see uspoof_openCheckResult
+ * @see uspoof_check2
+ * @see uspoof_check2UTF8
+ * @stable ICU 58
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_check2UnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status);
+
+/**
+ * A version of {@link uspoof_areConfusable} accepting UnicodeStrings.
+ *
+ * @param sc The USpoofChecker
+ * @param s1 The first of the two identifiers to be compared for
+ * confusability. The strings are in UTF-8 format.
+ * @param s2 The second of the two identifiers to be compared for
+ * confusability. The strings are in UTF-8 format.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Confusability of the identifiers is not reported here,
+ * but through this function's return value.
+ * @return An integer value with bit(s) set corresponding to
+ * the type of confusability found, as defined by
+ * enum USpoofChecks. Zero is returned if the identifiers
+ * are not confusable.
+ *
+ * @stable ICU 4.2
+ *
+ * @see uspoof_areConfusable
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusableUnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &s1,
+ const icu::UnicodeString &s2,
+ UErrorCode *status);
+
+/**
+ * Get the "skeleton" for an identifier.
+ * Skeletons are a transformation of the input identifier;
+ * Two identifiers are confusable if their skeletons are identical.
+ * See Unicode UAX #39 for additional information.
+ *
+ * Using skeletons directly makes it possible to quickly check
+ * whether an identifier is confusable with any of some large
+ * set of existing identifiers, by creating an efficiently
+ * searchable collection of the skeletons.
+ *
+ * @param sc The USpoofChecker.
+ * @param type Deprecated in ICU 58. You may pass any number.
+ * Originally, controlled which of the Unicode confusable data
+ * tables to use.
+ * @param id The input identifier whose skeleton will be computed.
+ * @param dest The output identifier, to receive the skeleton string.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * @return A reference to the destination (skeleton) string.
+ *
+ * @stable ICU 4.2
+ */
+U_I18N_API icu::UnicodeString & U_EXPORT2
+uspoof_getSkeletonUnicodeString(const USpoofChecker *sc,
+ uint32_t type,
+ const icu::UnicodeString &id,
+ icu::UnicodeString &dest,
+ UErrorCode *status);
+
+/**
+ * Get the set of Candidate Characters for Inclusion in Identifiers, as defined
+ * in http://unicode.org/Public/security/latest/xidmodifications.txt
+ * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms.
+ *
+ * The returned set is frozen. Ownership of the set remains with the ICU library; it must not
+ * be deleted by the caller.
+ *
+ * @param status The error code, set if a problem occurs while creating the set.
+ *
+ * @stable ICU 51
+ */
+U_CAPI const icu::UnicodeSet * U_EXPORT2
+uspoof_getInclusionUnicodeSet(UErrorCode *status);
+
+/**
+ * Get the set of characters from Recommended Scripts for Inclusion in Identifiers, as defined
+ * in http://unicode.org/Public/security/latest/xidmodifications.txt
+ * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms.
+ *
+ * The returned set is frozen. Ownership of the set remains with the ICU library; it must not
+ * be deleted by the caller.
+ *
+ * @param status The error code, set if a problem occurs while creating the set.
+ *
+ * @stable ICU 51
+ */
+U_CAPI const icu::UnicodeSet * U_EXPORT2
+uspoof_getRecommendedUnicodeSet(UErrorCode *status);
+
+#endif /* U_SHOW_CPLUSPLUS_API */
+
+#endif /* UCONFIG_NO_NORMALIZATION */
+
+#endif /* USPOOF_H */
diff --git a/thirdparty/icu4c/i18n/uspoof.cpp b/thirdparty/icu4c/i18n/uspoof.cpp
new file mode 100644
index 0000000000..dd4618baa7
--- /dev/null
+++ b/thirdparty/icu4c/i18n/uspoof.cpp
@@ -0,0 +1,839 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+***************************************************************************
+* Copyright (C) 2008-2015, International Business Machines Corporation
+* and others. All Rights Reserved.
+***************************************************************************
+* file name: uspoof.cpp
+* encoding: UTF-8
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2008Feb13
+* created by: Andy Heninger
+*
+* Unicode Spoof Detection
+*/
+#include "unicode/utypes.h"
+#include "unicode/normalizer2.h"
+#include "unicode/uspoof.h"
+#include "unicode/ustring.h"
+#include "unicode/utf16.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "mutex.h"
+#include "scriptset.h"
+#include "uassert.h"
+#include "ucln_in.h"
+#include "uspoof_impl.h"
+#include "umutex.h"
+
+
+#if !UCONFIG_NO_NORMALIZATION
+
+U_NAMESPACE_USE
+
+
+//
+// Static Objects used by the spoof impl, their thread safe initialization and their cleanup.
+//
+static UnicodeSet *gInclusionSet = NULL;
+static UnicodeSet *gRecommendedSet = NULL;
+static const Normalizer2 *gNfdNormalizer = NULL;
+static UInitOnce gSpoofInitStaticsOnce = U_INITONCE_INITIALIZER;
+
+namespace {
+
+UBool U_CALLCONV
+uspoof_cleanup(void) {
+ delete gInclusionSet;
+ gInclusionSet = NULL;
+ delete gRecommendedSet;
+ gRecommendedSet = NULL;
+ gNfdNormalizer = NULL;
+ gSpoofInitStaticsOnce.reset();
+ return TRUE;
+}
+
+void U_CALLCONV initializeStatics(UErrorCode &status) {
+ static const char16_t *inclusionPat =
+ u"['\\-.\\:\\u00B7\\u0375\\u058A\\u05F3\\u05F4\\u06FD\\u06FE\\u0F0B\\u200C"
+ u"\\u200D\\u2010\\u2019\\u2027\\u30A0\\u30FB]";
+ gInclusionSet = new UnicodeSet(UnicodeString(inclusionPat), status);
+ if (gInclusionSet == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ gInclusionSet->freeze();
+
+ // Note: data from IdentifierStatus.txt & IdentifierType.txt
+ // There is tooling to generate this constant in the unicodetools project:
+ // org.unicode.text.tools.RecommendedSetGenerator
+ // It will print the Java and C++ code to the console for easy copy-paste into this file.
+ static const char16_t *recommendedPat =
+ u"[0-9A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u0131\\u0134-\\u013E"
+ u"\\u0141-\\u0148\\u014A-\\u017E\\u018F\\u01A0\\u01A1\\u01AF\\u01B0\\u01CD-"
+ u"\\u01DC\\u01DE-\\u01E3\\u01E6-\\u01F0\\u01F4\\u01F5\\u01F8-\\u021B\\u021E"
+ u"\\u021F\\u0226-\\u0233\\u0259\\u02BB\\u02BC\\u02EC\\u0300-\\u0304\\u0306-"
+ u"\\u030C\\u030F-\\u0311\\u0313\\u0314\\u031B\\u0323-\\u0328\\u032D\\u032E"
+ u"\\u0330\\u0331\\u0335\\u0338\\u0339\\u0342\\u0345\\u037B-\\u037D\\u0386"
+ u"\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03CE\\u03FC-\\u045F\\u048A-"
+ u"\\u04FF\\u0510-\\u0529\\u052E\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0586"
+ u"\\u05B4\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u063F\\u0641-\\u0655\\u0660-"
+ u"\\u0669\\u0670-\\u0672\\u0674\\u0679-\\u068D\\u068F-\\u06A0\\u06A2-\\u06D3"
+ u"\\u06D5\\u06E5\\u06E6\\u06EE-\\u06FC\\u06FF\\u0750-\\u07B1\\u0870-\\u0887"
+ u"\\u0889-\\u088E\\u08A0-\\u08AC\\u08B2\\u08B5-\\u08C9\\u0901-\\u094D\\u094F"
+ u"\\u0950\\u0956\\u0957\\u0960-\\u0963\\u0966-\\u096F\\u0971-\\u0977\\u0979-"
+ u"\\u097F\\u0981-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-"
+ u"\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE"
+ u"\\u09D7\\u09E0-\\u09E3\\u09E6-\\u09F1\\u09FE\\u0A01-\\u0A03\\u0A05-\\u0A0A"
+ u"\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A35\\u0A38\\u0A39"
+ u"\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A5C\\u0A66-\\u0A74"
+ u"\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0"
+ u"\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD"
+ u"\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0AFA-\\u0AFF\\u0B01-\\u0B03\\u0B05-"
+ u"\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-"
+ u"\\u0B39\\u0B3C-\\u0B43\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B55-\\u0B57\\u0B5F-"
+ u"\\u0B61\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90"
+ u"\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-"
+ u"\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0"
+ u"\\u0BD7\\u0BE6-\\u0BEF\\u0C01-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-"
+ u"\\u0C33\\u0C35-\\u0C39\\u0C3C-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55"
+ u"\\u0C56\\u0C5D\\u0C60\\u0C61\\u0C66-\\u0C6F\\u0C80\\u0C82\\u0C83\\u0C85-"
+ u"\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-"
+ u"\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDD\\u0CE0-\\u0CE3"
+ u"\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D00\\u0D02\\u0D03\\u0D05-\\u0D0C\\u0D0E-"
+ u"\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D43\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D54-"
+ u"\\u0D57\\u0D60\\u0D61\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-"
+ u"\\u0D8E\\u0D91-\\u0D96\\u0D9A-\\u0DA5\\u0DA7-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD"
+ u"\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDE\\u0DF2\\u0E01-"
+ u"\\u0E32\\u0E34-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84"
+ u"\\u0E86-\\u0E8A\\u0E8C-\\u0EA3\\u0EA5\\u0EA7-\\u0EB2\\u0EB4-\\u0EBD\\u0EC0-"
+ u"\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDE\\u0EDF\\u0F00\\u0F20-"
+ u"\\u0F29\\u0F35\\u0F37\\u0F3E-\\u0F42\\u0F44-\\u0F47\\u0F49-\\u0F4C\\u0F4E-"
+ u"\\u0F51\\u0F53-\\u0F56\\u0F58-\\u0F5B\\u0F5D-\\u0F68\\u0F6A-\\u0F6C\\u0F71"
+ u"\\u0F72\\u0F74\\u0F7A-\\u0F80\\u0F82-\\u0F84\\u0F86-\\u0F92\\u0F94-\\u0F97"
+ u"\\u0F99-\\u0F9C\\u0F9E-\\u0FA1\\u0FA3-\\u0FA6\\u0FA8-\\u0FAB\\u0FAD-\\u0FB8"
+ u"\\u0FBA-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10C7\\u10CD\\u10D0-"
+ u"\\u10F0\\u10F7-\\u10FA\\u10FD-\\u10FF\\u1200-\\u1248\\u124A-\\u124D\\u1250-"
+ u"\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0"
+ u"\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-"
+ u"\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u1780-"
+ u"\\u17A2\\u17A5-\\u17A7\\u17A9-\\u17B3\\u17B6-\\u17CD\\u17D0\\u17D2\\u17D7"
+ u"\\u17DC\\u17E0-\\u17E9\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1E00-\\u1E99\\u1E9E"
+ u"\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D"
+ u"\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F70\\u1F72\\u1F74\\u1F76"
+ u"\\u1F78\\u1F7A\\u1F7C\\u1F80-\\u1FB4\\u1FB6-\\u1FBA\\u1FBC\\u1FC2-\\u1FC4"
+ u"\\u1FC6-\\u1FC8\\u1FCA\\u1FCC\\u1FD0-\\u1FD2\\u1FD6-\\u1FDA\\u1FE0-\\u1FE2"
+ u"\\u1FE4-\\u1FEA\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FF8\\u1FFA\\u1FFC\\u2D27"
+ u"\\u2D2D\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-"
+ u"\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u3005-"
+ u"\\u3007\\u3041-\\u3096\\u3099\\u309A\\u309D\\u309E\\u30A1-\\u30FA\\u30FC-"
+ u"\\u30FE\\u3105-\\u312D\\u312F\\u31A0-\\u31BF\\u3400-\\u4DBF\\u4E00-\\u9FFF"
+ u"\\uA67F\\uA717-\\uA71F\\uA788\\uA78D\\uA792\\uA793\\uA7AA\\uA7AE\\uA7B8"
+ u"\\uA7B9\\uA7C0-\\uA7CA\\uA7D0\\uA7D1\\uA7D3\\uA7D5-\\uA7D9\\uA9E7-\\uA9FE"
+ u"\\uAA60-\\uAA76\\uAA7A-\\uAA7F\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16"
+ u"\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB66\\uAB67\\uAC00-\\uD7A3\\uFA0E\\uFA0F"
+ u"\\uFA11\\uFA13\\uFA14\\uFA1F\\uFA21\\uFA23\\uFA24\\uFA27-\\uFA29\\U00011301"
+ u"\\U00011303\\U0001133B\\U0001133C\\U00016FF0\\U00016FF1\\U0001B11F-"
+ u"\\U0001B122\\U0001B150-\\U0001B152\\U0001B164-\\U0001B167\\U0001DF00-"
+ u"\\U0001DF1E\\U0001E7E0-\\U0001E7E6\\U0001E7E8-\\U0001E7EB\\U0001E7ED"
+ u"\\U0001E7EE\\U0001E7F0-\\U0001E7FE\\U00020000-\\U0002A6DF\\U0002A700-"
+ u"\\U0002B738\\U0002B740-\\U0002B81D\\U0002B820-\\U0002CEA1\\U0002CEB0-"
+ u"\\U0002EBE0\\U00030000-\\U0003134A]";
+
+ gRecommendedSet = new UnicodeSet(UnicodeString(recommendedPat), status);
+ if (gRecommendedSet == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ delete gInclusionSet;
+ return;
+ }
+ gRecommendedSet->freeze();
+ gNfdNormalizer = Normalizer2::getNFDInstance(status);
+ ucln_i18n_registerCleanup(UCLN_I18N_SPOOF, uspoof_cleanup);
+}
+
+} // namespace
+
+U_CFUNC void uspoof_internalInitStatics(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+}
+
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_open(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ if (U_FAILURE(*status)) {
+ return NULL;
+ }
+ SpoofImpl *si = new SpoofImpl(*status);
+ if (si == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ if (U_FAILURE(*status)) {
+ delete si;
+ return NULL;
+ }
+ return si->asUSpoofChecker();
+}
+
+
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_openFromSerialized(const void *data, int32_t length, int32_t *pActualLength,
+ UErrorCode *status) {
+ if (U_FAILURE(*status)) {
+ return NULL;
+ }
+
+ if (data == NULL) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return NULL;
+ }
+
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ if (U_FAILURE(*status))
+ {
+ return NULL;
+ }
+
+ SpoofData *sd = new SpoofData(data, length, *status);
+ if (sd == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+
+ if (U_FAILURE(*status)) {
+ delete sd;
+ return NULL;
+ }
+
+ SpoofImpl *si = new SpoofImpl(sd, *status);
+ if (si == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ delete sd; // explicit delete as the destructor for si won't be called.
+ return NULL;
+ }
+
+ if (U_FAILURE(*status)) {
+ delete si; // no delete for sd, as the si destructor will delete it.
+ return NULL;
+ }
+
+ if (pActualLength != NULL) {
+ *pActualLength = sd->size();
+ }
+ return si->asUSpoofChecker();
+}
+
+
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_clone(const USpoofChecker *sc, UErrorCode *status) {
+ const SpoofImpl *src = SpoofImpl::validateThis(sc, *status);
+ if (src == NULL) {
+ return NULL;
+ }
+ SpoofImpl *result = new SpoofImpl(*src, *status); // copy constructor
+ if (result == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ if (U_FAILURE(*status)) {
+ delete result;
+ result = NULL;
+ }
+ return result->asUSpoofChecker();
+}
+
+
+U_CAPI void U_EXPORT2
+uspoof_close(USpoofChecker *sc) {
+ UErrorCode status = U_ZERO_ERROR;
+ SpoofImpl *This = SpoofImpl::validateThis(sc, status);
+ delete This;
+}
+
+
+U_CAPI void U_EXPORT2
+uspoof_setChecks(USpoofChecker *sc, int32_t checks, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return;
+ }
+
+ // Verify that the requested checks are all ones (bits) that
+ // are acceptable, known values.
+ if (checks & ~(USPOOF_ALL_CHECKS | USPOOF_AUX_INFO)) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+
+ This->fChecks = checks;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_getChecks(const USpoofChecker *sc, UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return 0;
+ }
+ return This->fChecks;
+}
+
+U_CAPI void U_EXPORT2
+uspoof_setRestrictionLevel(USpoofChecker *sc, URestrictionLevel restrictionLevel) {
+ UErrorCode status = U_ZERO_ERROR;
+ SpoofImpl *This = SpoofImpl::validateThis(sc, status);
+ if (This != NULL) {
+ This->fRestrictionLevel = restrictionLevel;
+ This->fChecks |= USPOOF_RESTRICTION_LEVEL;
+ }
+}
+
+U_CAPI URestrictionLevel U_EXPORT2
+uspoof_getRestrictionLevel(const USpoofChecker *sc) {
+ UErrorCode status = U_ZERO_ERROR;
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, status);
+ if (This == NULL) {
+ return USPOOF_UNRESTRICTIVE;
+ }
+ return This->fRestrictionLevel;
+}
+
+U_CAPI void U_EXPORT2
+uspoof_setAllowedLocales(USpoofChecker *sc, const char *localesList, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return;
+ }
+ This->setAllowedLocales(localesList, *status);
+}
+
+U_CAPI const char * U_EXPORT2
+uspoof_getAllowedLocales(USpoofChecker *sc, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return NULL;
+ }
+ return This->getAllowedLocales(*status);
+}
+
+
+U_CAPI const USet * U_EXPORT2
+uspoof_getAllowedChars(const USpoofChecker *sc, UErrorCode *status) {
+ const UnicodeSet *result = uspoof_getAllowedUnicodeSet(sc, status);
+ return result->toUSet();
+}
+
+U_CAPI const UnicodeSet * U_EXPORT2
+uspoof_getAllowedUnicodeSet(const USpoofChecker *sc, UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return NULL;
+ }
+ return This->fAllowedCharsSet;
+}
+
+
+U_CAPI void U_EXPORT2
+uspoof_setAllowedChars(USpoofChecker *sc, const USet *chars, UErrorCode *status) {
+ const UnicodeSet *set = UnicodeSet::fromUSet(chars);
+ uspoof_setAllowedUnicodeSet(sc, set, status);
+}
+
+
+U_CAPI void U_EXPORT2
+uspoof_setAllowedUnicodeSet(USpoofChecker *sc, const UnicodeSet *chars, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return;
+ }
+ if (chars->isBogus()) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ UnicodeSet *clonedSet = chars->clone();
+ if (clonedSet == NULL || clonedSet->isBogus()) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ clonedSet->freeze();
+ delete This->fAllowedCharsSet;
+ This->fAllowedCharsSet = clonedSet;
+ This->fChecks |= USPOOF_CHAR_LIMIT;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_check(const USpoofChecker *sc,
+ const UChar *id, int32_t length,
+ int32_t *position,
+ UErrorCode *status) {
+
+ // Backwards compatibility:
+ if (position != NULL) {
+ *position = 0;
+ }
+
+ // Delegate to uspoof_check2
+ return uspoof_check2(sc, id, length, NULL, status);
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_check2(const USpoofChecker *sc,
+ const UChar* id, int32_t length,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status) {
+
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return 0;
+ }
+ if (length < -1) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+ UnicodeString idStr((length == -1), id, length); // Aliasing constructor.
+ int32_t result = uspoof_check2UnicodeString(sc, idStr, checkResult, status);
+ return result;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_checkUTF8(const USpoofChecker *sc,
+ const char *id, int32_t length,
+ int32_t *position,
+ UErrorCode *status) {
+
+ // Backwards compatibility:
+ if (position != NULL) {
+ *position = 0;
+ }
+
+ // Delegate to uspoof_check2
+ return uspoof_check2UTF8(sc, id, length, NULL, status);
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_check2UTF8(const USpoofChecker *sc,
+ const char *id, int32_t length,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status) {
+
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ UnicodeString idStr = UnicodeString::fromUTF8(StringPiece(id, length>=0 ? length : static_cast<int32_t>(uprv_strlen(id))));
+ int32_t result = uspoof_check2UnicodeString(sc, idStr, checkResult, status);
+ return result;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusable(const USpoofChecker *sc,
+ const UChar *id1, int32_t length1,
+ const UChar *id2, int32_t length2,
+ UErrorCode *status) {
+ SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ if (length1 < -1 || length2 < -1) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ UnicodeString id1Str((length1==-1), id1, length1); // Aliasing constructor
+ UnicodeString id2Str((length2==-1), id2, length2); // Aliasing constructor
+ return uspoof_areConfusableUnicodeString(sc, id1Str, id2Str, status);
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusableUTF8(const USpoofChecker *sc,
+ const char *id1, int32_t length1,
+ const char *id2, int32_t length2,
+ UErrorCode *status) {
+ SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ if (length1 < -1 || length2 < -1) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+ UnicodeString id1Str = UnicodeString::fromUTF8(StringPiece(id1, length1>=0? length1 : static_cast<int32_t>(uprv_strlen(id1))));
+ UnicodeString id2Str = UnicodeString::fromUTF8(StringPiece(id2, length2>=0? length2 : static_cast<int32_t>(uprv_strlen(id2))));
+ int32_t results = uspoof_areConfusableUnicodeString(sc, id1Str, id2Str, status);
+ return results;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusableUnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id1,
+ const icu::UnicodeString &id2,
+ UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ //
+ // See section 4 of UAX 39 for the algorithm for checking whether two strings are confusable,
+ // and for definitions of the types (single, whole, mixed-script) of confusables.
+
+ // We only care about a few of the check flags. Ignore the others.
+ // If no tests relevant to this function have been specified, return an error.
+ // TODO: is this really the right thing to do? It's probably an error on the caller's part,
+ // but logically we would just return 0 (no error).
+ if ((This->fChecks & USPOOF_CONFUSABLE) == 0) {
+ *status = U_INVALID_STATE_ERROR;
+ return 0;
+ }
+
+ // Compute the skeletons and check for confusability.
+ UnicodeString id1Skeleton;
+ uspoof_getSkeletonUnicodeString(sc, 0 /* deprecated */, id1, id1Skeleton, status);
+ UnicodeString id2Skeleton;
+ uspoof_getSkeletonUnicodeString(sc, 0 /* deprecated */, id2, id2Skeleton, status);
+ if (U_FAILURE(*status)) { return 0; }
+ if (id1Skeleton != id2Skeleton) {
+ return 0;
+ }
+
+ // If we get here, the strings are confusable. Now we just need to set the flags for the appropriate classes
+ // of confusables according to UTS 39 section 4.
+ // Start by computing the resolved script sets of id1 and id2.
+ ScriptSet id1RSS;
+ This->getResolvedScriptSet(id1, id1RSS, *status);
+ ScriptSet id2RSS;
+ This->getResolvedScriptSet(id2, id2RSS, *status);
+
+ // Turn on all applicable flags
+ int32_t result = 0;
+ if (id1RSS.intersects(id2RSS)) {
+ result |= USPOOF_SINGLE_SCRIPT_CONFUSABLE;
+ } else {
+ result |= USPOOF_MIXED_SCRIPT_CONFUSABLE;
+ if (!id1RSS.isEmpty() && !id2RSS.isEmpty()) {
+ result |= USPOOF_WHOLE_SCRIPT_CONFUSABLE;
+ }
+ }
+
+ // Turn off flags that the user doesn't want
+ if ((This->fChecks & USPOOF_SINGLE_SCRIPT_CONFUSABLE) == 0) {
+ result &= ~USPOOF_SINGLE_SCRIPT_CONFUSABLE;
+ }
+ if ((This->fChecks & USPOOF_MIXED_SCRIPT_CONFUSABLE) == 0) {
+ result &= ~USPOOF_MIXED_SCRIPT_CONFUSABLE;
+ }
+ if ((This->fChecks & USPOOF_WHOLE_SCRIPT_CONFUSABLE) == 0) {
+ result &= ~USPOOF_WHOLE_SCRIPT_CONFUSABLE;
+ }
+
+ return result;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_checkUnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id,
+ int32_t *position,
+ UErrorCode *status) {
+
+ // Backwards compatibility:
+ if (position != NULL) {
+ *position = 0;
+ }
+
+ // Delegate to uspoof_check2
+ return uspoof_check2UnicodeString(sc, id, NULL, status);
+}
+
+namespace {
+
+int32_t checkImpl(const SpoofImpl* This, const UnicodeString& id, CheckResult* checkResult, UErrorCode* status) {
+ U_ASSERT(This != NULL);
+ U_ASSERT(checkResult != NULL);
+ checkResult->clear();
+ int32_t result = 0;
+
+ if (0 != (This->fChecks & USPOOF_RESTRICTION_LEVEL)) {
+ URestrictionLevel idRestrictionLevel = This->getRestrictionLevel(id, *status);
+ if (idRestrictionLevel > This->fRestrictionLevel) {
+ result |= USPOOF_RESTRICTION_LEVEL;
+ }
+ checkResult->fRestrictionLevel = idRestrictionLevel;
+ }
+
+ if (0 != (This->fChecks & USPOOF_MIXED_NUMBERS)) {
+ UnicodeSet numerics;
+ This->getNumerics(id, numerics, *status);
+ if (numerics.size() > 1) {
+ result |= USPOOF_MIXED_NUMBERS;
+ }
+ checkResult->fNumerics = numerics; // UnicodeSet::operator=
+ }
+
+ if (0 != (This->fChecks & USPOOF_HIDDEN_OVERLAY)) {
+ int32_t index = This->findHiddenOverlay(id, *status);
+ if (index != -1) {
+ result |= USPOOF_HIDDEN_OVERLAY;
+ }
+ }
+
+
+ if (0 != (This->fChecks & USPOOF_CHAR_LIMIT)) {
+ int32_t i;
+ UChar32 c;
+ int32_t length = id.length();
+ for (i=0; i<length ;) {
+ c = id.char32At(i);
+ i += U16_LENGTH(c);
+ if (!This->fAllowedCharsSet->contains(c)) {
+ result |= USPOOF_CHAR_LIMIT;
+ break;
+ }
+ }
+ }
+
+ if (0 != (This->fChecks & USPOOF_INVISIBLE)) {
+ // This check needs to be done on NFD input
+ UnicodeString nfdText;
+ gNfdNormalizer->normalize(id, nfdText, *status);
+ int32_t nfdLength = nfdText.length();
+
+ // scan for more than one occurrence of the same non-spacing mark
+ // in a sequence of non-spacing marks.
+ int32_t i;
+ UChar32 c;
+ UChar32 firstNonspacingMark = 0;
+ UBool haveMultipleMarks = FALSE;
+ UnicodeSet marksSeenSoFar; // Set of combining marks in a single combining sequence.
+
+ for (i=0; i<nfdLength ;) {
+ c = nfdText.char32At(i);
+ i += U16_LENGTH(c);
+ if (u_charType(c) != U_NON_SPACING_MARK) {
+ firstNonspacingMark = 0;
+ if (haveMultipleMarks) {
+ marksSeenSoFar.clear();
+ haveMultipleMarks = FALSE;
+ }
+ continue;
+ }
+ if (firstNonspacingMark == 0) {
+ firstNonspacingMark = c;
+ continue;
+ }
+ if (!haveMultipleMarks) {
+ marksSeenSoFar.add(firstNonspacingMark);
+ haveMultipleMarks = TRUE;
+ }
+ if (marksSeenSoFar.contains(c)) {
+ // report the error, and stop scanning.
+ // No need to find more than the first failure.
+ result |= USPOOF_INVISIBLE;
+ break;
+ }
+ marksSeenSoFar.add(c);
+ }
+ }
+
+ checkResult->fChecks = result;
+ return checkResult->toCombinedBitmask(This->fChecks);
+}
+
+} // namespace
+
+U_CAPI int32_t U_EXPORT2
+uspoof_check2UnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return FALSE;
+ }
+
+ if (checkResult != NULL) {
+ CheckResult* ThisCheckResult = CheckResult::validateThis(checkResult, *status);
+ if (ThisCheckResult == NULL) {
+ return FALSE;
+ }
+ return checkImpl(This, id, ThisCheckResult, status);
+ } else {
+ // Stack-allocate the checkResult since this method doesn't return it
+ CheckResult stackCheckResult;
+ return checkImpl(This, id, &stackCheckResult, status);
+ }
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_getSkeleton(const USpoofChecker *sc,
+ uint32_t type,
+ const UChar *id, int32_t length,
+ UChar *dest, int32_t destCapacity,
+ UErrorCode *status) {
+
+ SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ if (length<-1 || destCapacity<0 || (destCapacity==0 && dest!=NULL)) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ UnicodeString idStr((length==-1), id, length); // Aliasing constructor
+ UnicodeString destStr;
+ uspoof_getSkeletonUnicodeString(sc, type, idStr, destStr, status);
+ destStr.extract(dest, destCapacity, *status);
+ return destStr.length();
+}
+
+
+
+U_I18N_API UnicodeString & U_EXPORT2
+uspoof_getSkeletonUnicodeString(const USpoofChecker *sc,
+ uint32_t /*type*/,
+ const UnicodeString &id,
+ UnicodeString &dest,
+ UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return dest;
+ }
+
+ UnicodeString nfdId;
+ gNfdNormalizer->normalize(id, nfdId, *status);
+
+ // Apply the skeleton mapping to the NFD normalized input string
+ // Accumulate the skeleton, possibly unnormalized, in a UnicodeString.
+ int32_t inputIndex = 0;
+ UnicodeString skelStr;
+ int32_t normalizedLen = nfdId.length();
+ for (inputIndex=0; inputIndex < normalizedLen; ) {
+ UChar32 c = nfdId.char32At(inputIndex);
+ inputIndex += U16_LENGTH(c);
+ This->fSpoofData->confusableLookup(c, skelStr);
+ }
+
+ gNfdNormalizer->normalize(skelStr, dest, *status);
+ return dest;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_getSkeletonUTF8(const USpoofChecker *sc,
+ uint32_t type,
+ const char *id, int32_t length,
+ char *dest, int32_t destCapacity,
+ UErrorCode *status) {
+ SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ if (length<-1 || destCapacity<0 || (destCapacity==0 && dest!=NULL)) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ UnicodeString srcStr = UnicodeString::fromUTF8(StringPiece(id, length>=0 ? length : static_cast<int32_t>(uprv_strlen(id))));
+ UnicodeString destStr;
+ uspoof_getSkeletonUnicodeString(sc, type, srcStr, destStr, status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+
+ int32_t lengthInUTF8 = 0;
+ u_strToUTF8(dest, destCapacity, &lengthInUTF8,
+ destStr.getBuffer(), destStr.length(), status);
+ return lengthInUTF8;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_serialize(USpoofChecker *sc,void *buf, int32_t capacity, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ U_ASSERT(U_FAILURE(*status));
+ return 0;
+ }
+
+ return This->fSpoofData->serialize(buf, capacity, *status);
+}
+
+U_CAPI const USet * U_EXPORT2
+uspoof_getInclusionSet(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ return gInclusionSet->toUSet();
+}
+
+U_CAPI const USet * U_EXPORT2
+uspoof_getRecommendedSet(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ return gRecommendedSet->toUSet();
+}
+
+U_I18N_API const UnicodeSet * U_EXPORT2
+uspoof_getInclusionUnicodeSet(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ return gInclusionSet;
+}
+
+U_I18N_API const UnicodeSet * U_EXPORT2
+uspoof_getRecommendedUnicodeSet(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ return gRecommendedSet;
+}
+
+//------------------
+// CheckResult APIs
+//------------------
+
+U_CAPI USpoofCheckResult* U_EXPORT2
+uspoof_openCheckResult(UErrorCode *status) {
+ CheckResult* checkResult = new CheckResult();
+ if (checkResult == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ return checkResult->asUSpoofCheckResult();
+}
+
+U_CAPI void U_EXPORT2
+uspoof_closeCheckResult(USpoofCheckResult* checkResult) {
+ UErrorCode status = U_ZERO_ERROR;
+ CheckResult* This = CheckResult::validateThis(checkResult, status);
+ delete This;
+}
+
+U_CAPI int32_t U_EXPORT2
+uspoof_getCheckResultChecks(const USpoofCheckResult *checkResult, UErrorCode *status) {
+ const CheckResult* This = CheckResult::validateThis(checkResult, *status);
+ if (U_FAILURE(*status)) { return 0; }
+ return This->fChecks;
+}
+
+U_CAPI URestrictionLevel U_EXPORT2
+uspoof_getCheckResultRestrictionLevel(const USpoofCheckResult *checkResult, UErrorCode *status) {
+ const CheckResult* This = CheckResult::validateThis(checkResult, *status);
+ if (U_FAILURE(*status)) { return USPOOF_UNRESTRICTIVE; }
+ return This->fRestrictionLevel;
+}
+
+U_CAPI const USet* U_EXPORT2
+uspoof_getCheckResultNumerics(const USpoofCheckResult *checkResult, UErrorCode *status) {
+ const CheckResult* This = CheckResult::validateThis(checkResult, *status);
+ if (U_FAILURE(*status)) { return NULL; }
+ return This->fNumerics.toUSet();
+}
+
+
+
+#endif // !UCONFIG_NO_NORMALIZATION
diff --git a/thirdparty/icu4c/i18n/uspoof_impl.cpp b/thirdparty/icu4c/i18n/uspoof_impl.cpp
new file mode 100644
index 0000000000..b283d81321
--- /dev/null
+++ b/thirdparty/icu4c/i18n/uspoof_impl.cpp
@@ -0,0 +1,959 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+**********************************************************************
+* Copyright (C) 2008-2016, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+*/
+
+#include "unicode/utypes.h"
+#include "unicode/uspoof.h"
+#include "unicode/uchar.h"
+#include "unicode/uniset.h"
+#include "unicode/utf16.h"
+#include "utrie2.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "scriptset.h"
+#include "umutex.h"
+#include "udataswp.h"
+#include "uassert.h"
+#include "ucln_in.h"
+#include "uspoof_impl.h"
+
+#if !UCONFIG_NO_NORMALIZATION
+
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SpoofImpl)
+
+SpoofImpl::SpoofImpl(SpoofData *data, UErrorCode& status) {
+ construct(status);
+ fSpoofData = data;
+}
+
+SpoofImpl::SpoofImpl(UErrorCode& status) {
+ construct(status);
+
+ // TODO: Call this method where it is actually needed, instead of in the
+ // constructor, to allow for lazy data loading. See #12696.
+ fSpoofData = SpoofData::getDefault(status);
+}
+
+SpoofImpl::SpoofImpl() {
+ UErrorCode status = U_ZERO_ERROR;
+ construct(status);
+
+ // TODO: Call this method where it is actually needed, instead of in the
+ // constructor, to allow for lazy data loading. See #12696.
+ fSpoofData = SpoofData::getDefault(status);
+}
+
+void SpoofImpl::construct(UErrorCode& status) {
+ fChecks = USPOOF_ALL_CHECKS;
+ fSpoofData = NULL;
+ fAllowedCharsSet = NULL;
+ fAllowedLocales = NULL;
+ fRestrictionLevel = USPOOF_HIGHLY_RESTRICTIVE;
+
+ if (U_FAILURE(status)) { return; }
+
+ UnicodeSet *allowedCharsSet = new UnicodeSet(0, 0x10ffff);
+ fAllowedCharsSet = allowedCharsSet;
+ fAllowedLocales = uprv_strdup("");
+ if (fAllowedCharsSet == NULL || fAllowedLocales == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ allowedCharsSet->freeze();
+}
+
+
+// Copy Constructor, used by the user level clone() function.
+SpoofImpl::SpoofImpl(const SpoofImpl &src, UErrorCode &status) :
+ fChecks(USPOOF_ALL_CHECKS), fSpoofData(NULL), fAllowedCharsSet(NULL) ,
+ fAllowedLocales(NULL) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ fChecks = src.fChecks;
+ if (src.fSpoofData != NULL) {
+ fSpoofData = src.fSpoofData->addReference();
+ }
+ fAllowedCharsSet = src.fAllowedCharsSet->clone();
+ fAllowedLocales = uprv_strdup(src.fAllowedLocales);
+ if (fAllowedCharsSet == NULL || fAllowedLocales == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ fRestrictionLevel = src.fRestrictionLevel;
+}
+
+SpoofImpl::~SpoofImpl() {
+ if (fSpoofData != NULL) {
+ fSpoofData->removeReference(); // Will delete if refCount goes to zero.
+ }
+ delete fAllowedCharsSet;
+ uprv_free((void *)fAllowedLocales);
+}
+
+// Cast this instance as a USpoofChecker for the C API.
+USpoofChecker *SpoofImpl::asUSpoofChecker() {
+ return exportForC();
+}
+
+//
+// Incoming parameter check on Status and the SpoofChecker object
+// received from the C API.
+//
+const SpoofImpl *SpoofImpl::validateThis(const USpoofChecker *sc, UErrorCode &status) {
+ auto* This = validate(sc, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ if (This->fSpoofData != NULL && !This->fSpoofData->validateDataVersion(status)) {
+ return NULL;
+ }
+ return This;
+}
+
+SpoofImpl *SpoofImpl::validateThis(USpoofChecker *sc, UErrorCode &status) {
+ return const_cast<SpoofImpl *>
+ (SpoofImpl::validateThis(const_cast<const USpoofChecker *>(sc), status));
+}
+
+
+void SpoofImpl::setAllowedLocales(const char *localesList, UErrorCode &status) {
+ UnicodeSet allowedChars;
+ UnicodeSet *tmpSet = NULL;
+ const char *locStart = localesList;
+ const char *locEnd = NULL;
+ const char *localesListEnd = localesList + uprv_strlen(localesList);
+ int32_t localeListCount = 0; // Number of locales provided by caller.
+
+ // Loop runs once per locale from the localesList, a comma separated list of locales.
+ do {
+ locEnd = uprv_strchr(locStart, ',');
+ if (locEnd == NULL) {
+ locEnd = localesListEnd;
+ }
+ while (*locStart == ' ') {
+ locStart++;
+ }
+ const char *trimmedEnd = locEnd-1;
+ while (trimmedEnd > locStart && *trimmedEnd == ' ') {
+ trimmedEnd--;
+ }
+ if (trimmedEnd <= locStart) {
+ break;
+ }
+ const char *locale = uprv_strndup(locStart, (int32_t)(trimmedEnd + 1 - locStart));
+ localeListCount++;
+
+ // We have one locale from the locales list.
+ // Add the script chars for this locale to the accumulating set of allowed chars.
+ // If the locale is no good, we will be notified back via status.
+ addScriptChars(locale, &allowedChars, status);
+ uprv_free((void *)locale);
+ if (U_FAILURE(status)) {
+ break;
+ }
+ locStart = locEnd + 1;
+ } while (locStart < localesListEnd);
+
+ // If our caller provided an empty list of locales, we disable the allowed characters checking
+ if (localeListCount == 0) {
+ uprv_free((void *)fAllowedLocales);
+ fAllowedLocales = uprv_strdup("");
+ tmpSet = new UnicodeSet(0, 0x10ffff);
+ if (fAllowedLocales == NULL || tmpSet == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ tmpSet->freeze();
+ delete fAllowedCharsSet;
+ fAllowedCharsSet = tmpSet;
+ fChecks &= ~USPOOF_CHAR_LIMIT;
+ return;
+ }
+
+
+ // Add all common and inherited characters to the set of allowed chars.
+ UnicodeSet tempSet;
+ tempSet.applyIntPropertyValue(UCHAR_SCRIPT, USCRIPT_COMMON, status);
+ allowedChars.addAll(tempSet);
+ tempSet.applyIntPropertyValue(UCHAR_SCRIPT, USCRIPT_INHERITED, status);
+ allowedChars.addAll(tempSet);
+
+ // If anything went wrong, we bail out without changing
+ // the state of the spoof checker.
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ // Store the updated spoof checker state.
+ tmpSet = allowedChars.clone();
+ const char *tmpLocalesList = uprv_strdup(localesList);
+ if (tmpSet == NULL || tmpLocalesList == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ uprv_free((void *)fAllowedLocales);
+ fAllowedLocales = tmpLocalesList;
+ tmpSet->freeze();
+ delete fAllowedCharsSet;
+ fAllowedCharsSet = tmpSet;
+ fChecks |= USPOOF_CHAR_LIMIT;
+}
+
+
+const char * SpoofImpl::getAllowedLocales(UErrorCode &/*status*/) {
+ return fAllowedLocales;
+}
+
+
+// Given a locale (a language), add all the characters from all of the scripts used with that language
+// to the allowedChars UnicodeSet
+
+void SpoofImpl::addScriptChars(const char *locale, UnicodeSet *allowedChars, UErrorCode &status) {
+ UScriptCode scripts[30];
+
+ int32_t numScripts = uscript_getCode(locale, scripts, UPRV_LENGTHOF(scripts), &status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (status == U_USING_DEFAULT_WARNING) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ UnicodeSet tmpSet;
+ int32_t i;
+ for (i=0; i<numScripts; i++) {
+ tmpSet.applyIntPropertyValue(UCHAR_SCRIPT, scripts[i], status);
+ allowedChars->addAll(tmpSet);
+ }
+}
+
+// Computes the augmented script set for a code point, according to UTS 39 section 5.1.
+void SpoofImpl::getAugmentedScriptSet(UChar32 codePoint, ScriptSet& result, UErrorCode& status) {
+ result.resetAll();
+ result.setScriptExtensions(codePoint, status);
+ if (U_FAILURE(status)) { return; }
+
+ // Section 5.1 step 1
+ if (result.test(USCRIPT_HAN, status)) {
+ result.set(USCRIPT_HAN_WITH_BOPOMOFO, status);
+ result.set(USCRIPT_JAPANESE, status);
+ result.set(USCRIPT_KOREAN, status);
+ }
+ if (result.test(USCRIPT_HIRAGANA, status)) {
+ result.set(USCRIPT_JAPANESE, status);
+ }
+ if (result.test(USCRIPT_KATAKANA, status)) {
+ result.set(USCRIPT_JAPANESE, status);
+ }
+ if (result.test(USCRIPT_HANGUL, status)) {
+ result.set(USCRIPT_KOREAN, status);
+ }
+ if (result.test(USCRIPT_BOPOMOFO, status)) {
+ result.set(USCRIPT_HAN_WITH_BOPOMOFO, status);
+ }
+
+ // Section 5.1 step 2
+ if (result.test(USCRIPT_COMMON, status) || result.test(USCRIPT_INHERITED, status)) {
+ result.setAll();
+ }
+}
+
+// Computes the resolved script set for a string, according to UTS 39 section 5.1.
+void SpoofImpl::getResolvedScriptSet(const UnicodeString& input, ScriptSet& result, UErrorCode& status) const {
+ getResolvedScriptSetWithout(input, USCRIPT_CODE_LIMIT, result, status);
+}
+
+// Computes the resolved script set for a string, omitting characters having the specified script.
+// If USCRIPT_CODE_LIMIT is passed as the second argument, all characters are included.
+void SpoofImpl::getResolvedScriptSetWithout(const UnicodeString& input, UScriptCode script, ScriptSet& result, UErrorCode& status) const {
+ result.setAll();
+
+ ScriptSet temp;
+ UChar32 codePoint;
+ for (int32_t i = 0; i < input.length(); i += U16_LENGTH(codePoint)) {
+ codePoint = input.char32At(i);
+
+ // Compute the augmented script set for the character
+ getAugmentedScriptSet(codePoint, temp, status);
+ if (U_FAILURE(status)) { return; }
+
+ // Intersect the augmented script set with the resolved script set, but only if the character doesn't
+ // have the script specified in the function call
+ if (script == USCRIPT_CODE_LIMIT || !temp.test(script, status)) {
+ result.intersect(temp);
+ }
+ }
+}
+
+// Computes the set of numerics for a string, according to UTS 39 section 5.3.
+void SpoofImpl::getNumerics(const UnicodeString& input, UnicodeSet& result, UErrorCode& /*status*/) const {
+ result.clear();
+
+ UChar32 codePoint;
+ for (int32_t i = 0; i < input.length(); i += U16_LENGTH(codePoint)) {
+ codePoint = input.char32At(i);
+
+ // Store a representative character for each kind of decimal digit
+ if (u_charType(codePoint) == U_DECIMAL_DIGIT_NUMBER) {
+ // Store the zero character as a representative for comparison.
+ // Unicode guarantees it is codePoint - value
+ result.add(codePoint - (UChar32)u_getNumericValue(codePoint));
+ }
+ }
+}
+
+// Computes the restriction level of a string, according to UTS 39 section 5.2.
+URestrictionLevel SpoofImpl::getRestrictionLevel(const UnicodeString& input, UErrorCode& status) const {
+ // Section 5.2 step 1:
+ if (!fAllowedCharsSet->containsAll(input)) {
+ return USPOOF_UNRESTRICTIVE;
+ }
+
+ // Section 5.2 step 2
+ // Java use a static UnicodeSet for this test. In C++, avoid the static variable
+ // and just do a simple for loop.
+ UBool allASCII = TRUE;
+ for (int32_t i=0, length=input.length(); i<length; i++) {
+ if (input.charAt(i) > 0x7f) {
+ allASCII = FALSE;
+ break;
+ }
+ }
+ if (allASCII) {
+ return USPOOF_ASCII;
+ }
+
+ // Section 5.2 steps 3:
+ ScriptSet resolvedScriptSet;
+ getResolvedScriptSet(input, resolvedScriptSet, status);
+ if (U_FAILURE(status)) { return USPOOF_UNRESTRICTIVE; }
+
+ // Section 5.2 step 4:
+ if (!resolvedScriptSet.isEmpty()) {
+ return USPOOF_SINGLE_SCRIPT_RESTRICTIVE;
+ }
+
+ // Section 5.2 step 5:
+ ScriptSet resolvedNoLatn;
+ getResolvedScriptSetWithout(input, USCRIPT_LATIN, resolvedNoLatn, status);
+ if (U_FAILURE(status)) { return USPOOF_UNRESTRICTIVE; }
+
+ // Section 5.2 step 6:
+ if (resolvedNoLatn.test(USCRIPT_HAN_WITH_BOPOMOFO, status)
+ || resolvedNoLatn.test(USCRIPT_JAPANESE, status)
+ || resolvedNoLatn.test(USCRIPT_KOREAN, status)) {
+ return USPOOF_HIGHLY_RESTRICTIVE;
+ }
+
+ // Section 5.2 step 7:
+ if (!resolvedNoLatn.isEmpty()
+ && !resolvedNoLatn.test(USCRIPT_CYRILLIC, status)
+ && !resolvedNoLatn.test(USCRIPT_GREEK, status)
+ && !resolvedNoLatn.test(USCRIPT_CHEROKEE, status)) {
+ return USPOOF_MODERATELY_RESTRICTIVE;
+ }
+
+ // Section 5.2 step 8:
+ return USPOOF_MINIMALLY_RESTRICTIVE;
+}
+
+int32_t SpoofImpl::findHiddenOverlay(const UnicodeString& input, UErrorCode&) const {
+ bool sawLeadCharacter = false;
+ for (int32_t i=0; i<input.length();) {
+ UChar32 cp = input.char32At(i);
+ if (sawLeadCharacter && cp == 0x0307) {
+ return i;
+ }
+ uint8_t combiningClass = u_getCombiningClass(cp);
+ // Skip over characters except for those with combining class 0 (non-combining characters) or with
+ // combining class 230 (same class as U+0307)
+ U_ASSERT(u_getCombiningClass(0x0307) == 230);
+ if (combiningClass == 0 || combiningClass == 230) {
+ sawLeadCharacter = isIllegalCombiningDotLeadCharacter(cp);
+ }
+ i += U16_LENGTH(cp);
+ }
+ return -1;
+}
+
+static inline bool isIllegalCombiningDotLeadCharacterNoLookup(UChar32 cp) {
+ return cp == u'i' || cp == u'j' || cp == u'ı' || cp == u'ȷ' || cp == u'l' ||
+ u_hasBinaryProperty(cp, UCHAR_SOFT_DOTTED);
+}
+
+bool SpoofImpl::isIllegalCombiningDotLeadCharacter(UChar32 cp) const {
+ if (isIllegalCombiningDotLeadCharacterNoLookup(cp)) {
+ return true;
+ }
+ UnicodeString skelStr;
+ fSpoofData->confusableLookup(cp, skelStr);
+ UChar32 finalCp = skelStr.char32At(skelStr.moveIndex32(skelStr.length(), -1));
+ if (finalCp != cp && isIllegalCombiningDotLeadCharacterNoLookup(finalCp)) {
+ return true;
+ }
+ return false;
+}
+
+
+
+// Convert a text format hex number. Utility function used by builder code. Static.
+// Input: UChar *string text. Output: a UChar32
+// Input has been pre-checked, and will have no non-hex chars.
+// The number must fall in the code point range of 0..0x10ffff
+// Static Function.
+UChar32 SpoofImpl::ScanHex(const UChar *s, int32_t start, int32_t limit, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return 0;
+ }
+ U_ASSERT(limit-start > 0);
+ uint32_t val = 0;
+ int i;
+ for (i=start; i<limit; i++) {
+ int digitVal = s[i] - 0x30;
+ if (digitVal>9) {
+ digitVal = 0xa + (s[i] - 0x41); // Upper Case 'A'
+ }
+ if (digitVal>15) {
+ digitVal = 0xa + (s[i] - 0x61); // Lower Case 'a'
+ }
+ U_ASSERT(digitVal <= 0xf);
+ val <<= 4;
+ val += digitVal;
+ }
+ if (val > 0x10ffff) {
+ status = U_PARSE_ERROR;
+ val = 0;
+ }
+ return (UChar32)val;
+}
+
+
+//-----------------------------------------
+//
+// class CheckResult Implementation
+//
+//-----------------------------------------
+
+CheckResult::CheckResult() {
+ clear();
+}
+
+USpoofCheckResult* CheckResult::asUSpoofCheckResult() {
+ return exportForC();
+}
+
+//
+// Incoming parameter check on Status and the CheckResult object
+// received from the C API.
+//
+const CheckResult* CheckResult::validateThis(const USpoofCheckResult *ptr, UErrorCode &status) {
+ return validate(ptr, status);
+}
+
+CheckResult* CheckResult::validateThis(USpoofCheckResult *ptr, UErrorCode &status) {
+ return validate(ptr, status);
+}
+
+void CheckResult::clear() {
+ fChecks = 0;
+ fNumerics.clear();
+ fRestrictionLevel = USPOOF_UNDEFINED_RESTRICTIVE;
+}
+
+int32_t CheckResult::toCombinedBitmask(int32_t enabledChecks) {
+ if ((enabledChecks & USPOOF_AUX_INFO) != 0 && fRestrictionLevel != USPOOF_UNDEFINED_RESTRICTIVE) {
+ return fChecks | fRestrictionLevel;
+ } else {
+ return fChecks;
+ }
+}
+
+CheckResult::~CheckResult() {
+}
+
+//----------------------------------------------------------------------------------------------
+//
+// class SpoofData Implementation
+//
+//----------------------------------------------------------------------------------------------
+
+
+UBool SpoofData::validateDataVersion(UErrorCode &status) const {
+ if (U_FAILURE(status) ||
+ fRawData == NULL ||
+ fRawData->fMagic != USPOOF_MAGIC ||
+ fRawData->fFormatVersion[0] != USPOOF_CONFUSABLE_DATA_FORMAT_VERSION ||
+ fRawData->fFormatVersion[1] != 0 ||
+ fRawData->fFormatVersion[2] != 0 ||
+ fRawData->fFormatVersion[3] != 0) {
+ status = U_INVALID_FORMAT_ERROR;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static UBool U_CALLCONV
+spoofDataIsAcceptable(void *context,
+ const char * /* type */, const char * /*name*/,
+ const UDataInfo *pInfo) {
+ if(
+ pInfo->size >= 20 &&
+ pInfo->isBigEndian == U_IS_BIG_ENDIAN &&
+ pInfo->charsetFamily == U_CHARSET_FAMILY &&
+ pInfo->dataFormat[0] == 0x43 && // dataFormat="Cfu "
+ pInfo->dataFormat[1] == 0x66 &&
+ pInfo->dataFormat[2] == 0x75 &&
+ pInfo->dataFormat[3] == 0x20 &&
+ pInfo->formatVersion[0] == USPOOF_CONFUSABLE_DATA_FORMAT_VERSION
+ ) {
+ UVersionInfo *version = static_cast<UVersionInfo *>(context);
+ if(version != NULL) {
+ uprv_memcpy(version, pInfo->dataVersion, 4);
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+// Methods for the loading of the default confusables data file. The confusable
+// data is loaded only when it is needed.
+//
+// SpoofData::getDefault() - Return the default confusables data, and call the
+// initOnce() if it is not available. Adds a reference
+// to the SpoofData that the caller is responsible for
+// decrementing when they are done with the data.
+//
+// uspoof_loadDefaultData - Called once, from initOnce(). The resulting SpoofData
+// is shared by all spoof checkers using the default data.
+//
+// uspoof_cleanupDefaultData - Called during cleanup.
+//
+
+static UInitOnce gSpoofInitDefaultOnce = U_INITONCE_INITIALIZER;
+static SpoofData* gDefaultSpoofData;
+
+static UBool U_CALLCONV
+uspoof_cleanupDefaultData(void) {
+ if (gDefaultSpoofData) {
+ // Will delete, assuming all user-level spoof checkers were closed.
+ gDefaultSpoofData->removeReference();
+ gDefaultSpoofData = nullptr;
+ gSpoofInitDefaultOnce.reset();
+ }
+ return TRUE;
+}
+
+static void U_CALLCONV uspoof_loadDefaultData(UErrorCode& status) {
+ UDataMemory *udm = udata_openChoice(nullptr, "cfu", "confusables",
+ spoofDataIsAcceptable,
+ nullptr, // context, would receive dataVersion if supplied.
+ &status);
+ if (U_FAILURE(status)) { return; }
+ gDefaultSpoofData = new SpoofData(udm, status);
+ if (U_FAILURE(status)) {
+ delete gDefaultSpoofData;
+ gDefaultSpoofData = nullptr;
+ return;
+ }
+ if (gDefaultSpoofData == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ ucln_i18n_registerCleanup(UCLN_I18N_SPOOFDATA, uspoof_cleanupDefaultData);
+}
+
+SpoofData* SpoofData::getDefault(UErrorCode& status) {
+ umtx_initOnce(gSpoofInitDefaultOnce, &uspoof_loadDefaultData, status);
+ if (U_FAILURE(status)) { return NULL; }
+ gDefaultSpoofData->addReference();
+ return gDefaultSpoofData;
+}
+
+
+
+SpoofData::SpoofData(UDataMemory *udm, UErrorCode &status)
+{
+ reset();
+ if (U_FAILURE(status)) {
+ return;
+ }
+ fUDM = udm;
+ // fRawData is non-const because it may be constructed by the data builder.
+ fRawData = reinterpret_cast<SpoofDataHeader *>(
+ const_cast<void *>(udata_getMemory(udm)));
+ validateDataVersion(status);
+ initPtrs(status);
+}
+
+
+SpoofData::SpoofData(const void *data, int32_t length, UErrorCode &status)
+{
+ reset();
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if ((size_t)length < sizeof(SpoofDataHeader)) {
+ status = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+ if (data == NULL) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ void *ncData = const_cast<void *>(data);
+ fRawData = static_cast<SpoofDataHeader *>(ncData);
+ if (length < fRawData->fLength) {
+ status = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+ validateDataVersion(status);
+ initPtrs(status);
+}
+
+
+// Spoof Data constructor for use from data builder.
+// Initializes a new, empty data area that will be populated later.
+SpoofData::SpoofData(UErrorCode &status) {
+ reset();
+ if (U_FAILURE(status)) {
+ return;
+ }
+ fDataOwned = true;
+
+ // The spoof header should already be sized to be a multiple of 16 bytes.
+ // Just in case it's not, round it up.
+ uint32_t initialSize = (sizeof(SpoofDataHeader) + 15) & ~15;
+ U_ASSERT(initialSize == sizeof(SpoofDataHeader));
+
+ fRawData = static_cast<SpoofDataHeader *>(uprv_malloc(initialSize));
+ fMemLimit = initialSize;
+ if (fRawData == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ uprv_memset(fRawData, 0, initialSize);
+
+ fRawData->fMagic = USPOOF_MAGIC;
+ fRawData->fFormatVersion[0] = USPOOF_CONFUSABLE_DATA_FORMAT_VERSION;
+ fRawData->fFormatVersion[1] = 0;
+ fRawData->fFormatVersion[2] = 0;
+ fRawData->fFormatVersion[3] = 0;
+ initPtrs(status);
+}
+
+// reset() - initialize all fields.
+// Should be updated if any new fields are added.
+// Called by constructors to put things in a known initial state.
+void SpoofData::reset() {
+ fRawData = NULL;
+ fDataOwned = FALSE;
+ fUDM = NULL;
+ fMemLimit = 0;
+ fRefCount = 1;
+ fCFUKeys = NULL;
+ fCFUValues = NULL;
+ fCFUStrings = NULL;
+}
+
+
+// SpoofData::initPtrs()
+// Initialize the pointers to the various sections of the raw data.
+//
+// This function is used both during the Trie building process (multiple
+// times, as the individual data sections are added), and
+// during the opening of a Spoof Checker from prebuilt data.
+//
+// The pointers for non-existent data sections (identified by an offset of 0)
+// are set to NULL.
+//
+// Note: During building the data, adding each new data section
+// reallocs the raw data area, which likely relocates it, which
+// in turn requires reinitializing all of the pointers into it, hence
+// multiple calls to this function during building.
+//
+void SpoofData::initPtrs(UErrorCode &status) {
+ fCFUKeys = NULL;
+ fCFUValues = NULL;
+ fCFUStrings = NULL;
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fRawData->fCFUKeys != 0) {
+ fCFUKeys = (int32_t *)((char *)fRawData + fRawData->fCFUKeys);
+ }
+ if (fRawData->fCFUStringIndex != 0) {
+ fCFUValues = (uint16_t *)((char *)fRawData + fRawData->fCFUStringIndex);
+ }
+ if (fRawData->fCFUStringTable != 0) {
+ fCFUStrings = (UChar *)((char *)fRawData + fRawData->fCFUStringTable);
+ }
+}
+
+
+SpoofData::~SpoofData() {
+ if (fDataOwned) {
+ uprv_free(fRawData);
+ }
+ fRawData = NULL;
+ if (fUDM != NULL) {
+ udata_close(fUDM);
+ }
+ fUDM = NULL;
+}
+
+
+void SpoofData::removeReference() {
+ if (umtx_atomic_dec(&fRefCount) == 0) {
+ delete this;
+ }
+}
+
+
+SpoofData *SpoofData::addReference() {
+ umtx_atomic_inc(&fRefCount);
+ return this;
+}
+
+
+void *SpoofData::reserveSpace(int32_t numBytes, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ if (!fDataOwned) {
+ UPRV_UNREACHABLE_EXIT;
+ }
+
+ numBytes = (numBytes + 15) & ~15; // Round up to a multiple of 16
+ uint32_t returnOffset = fMemLimit;
+ fMemLimit += numBytes;
+ fRawData = static_cast<SpoofDataHeader *>(uprv_realloc(fRawData, fMemLimit));
+ fRawData->fLength = fMemLimit;
+ uprv_memset((char *)fRawData + returnOffset, 0, numBytes);
+ initPtrs(status);
+ return (char *)fRawData + returnOffset;
+}
+
+int32_t SpoofData::serialize(void *buf, int32_t capacity, UErrorCode &status) const {
+ int32_t dataSize = fRawData->fLength;
+ if (capacity < dataSize) {
+ status = U_BUFFER_OVERFLOW_ERROR;
+ return dataSize;
+ }
+ uprv_memcpy(buf, fRawData, dataSize);
+ return dataSize;
+}
+
+int32_t SpoofData::size() const {
+ return fRawData->fLength;
+}
+
+//-------------------------------
+//
+// Front-end APIs for SpoofData
+//
+//-------------------------------
+
+int32_t SpoofData::confusableLookup(UChar32 inChar, UnicodeString &dest) const {
+ // Perform a binary search.
+ // [lo, hi), i.e lo is inclusive, hi is exclusive.
+ // The result after the loop will be in lo.
+ int32_t lo = 0;
+ int32_t hi = length();
+ do {
+ int32_t mid = (lo + hi) / 2;
+ if (codePointAt(mid) > inChar) {
+ hi = mid;
+ } else if (codePointAt(mid) < inChar) {
+ lo = mid;
+ } else {
+ // Found result. Break early.
+ lo = mid;
+ break;
+ }
+ } while (hi - lo > 1);
+
+ // Did we find an entry? If not, the char maps to itself.
+ if (codePointAt(lo) != inChar) {
+ dest.append(inChar);
+ return 1;
+ }
+
+ // Add the element to the string builder and return.
+ return appendValueTo(lo, dest);
+}
+
+int32_t SpoofData::length() const {
+ return fRawData->fCFUKeysSize;
+}
+
+UChar32 SpoofData::codePointAt(int32_t index) const {
+ return ConfusableDataUtils::keyToCodePoint(fCFUKeys[index]);
+}
+
+int32_t SpoofData::appendValueTo(int32_t index, UnicodeString& dest) const {
+ int32_t stringLength = ConfusableDataUtils::keyToLength(fCFUKeys[index]);
+
+ // Value is either a char (for strings of length 1) or
+ // an index into the string table (for longer strings)
+ uint16_t value = fCFUValues[index];
+ if (stringLength == 1) {
+ dest.append((UChar)value);
+ } else {
+ dest.append(fCFUStrings + value, stringLength);
+ }
+
+ return stringLength;
+}
+
+
+U_NAMESPACE_END
+
+U_NAMESPACE_USE
+
+//-----------------------------------------------------------------------------
+//
+// uspoof_swap - byte swap and char encoding swap of spoof data
+//
+//-----------------------------------------------------------------------------
+U_CAPI int32_t U_EXPORT2
+uspoof_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData,
+ UErrorCode *status) {
+
+ if (status == NULL || U_FAILURE(*status)) {
+ return 0;
+ }
+ if(ds==NULL || inData==NULL || length<-1 || (length>0 && outData==NULL)) {
+ *status=U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ //
+ // Check that the data header is for spoof data.
+ // (Header contents are defined in gencfu.cpp)
+ //
+ const UDataInfo *pInfo = (const UDataInfo *)((const char *)inData+4);
+ if(!( pInfo->dataFormat[0]==0x43 && /* dataFormat="Cfu " */
+ pInfo->dataFormat[1]==0x66 &&
+ pInfo->dataFormat[2]==0x75 &&
+ pInfo->dataFormat[3]==0x20 &&
+ pInfo->formatVersion[0]==USPOOF_CONFUSABLE_DATA_FORMAT_VERSION &&
+ pInfo->formatVersion[1]==0 &&
+ pInfo->formatVersion[2]==0 &&
+ pInfo->formatVersion[3]==0 )) {
+ udata_printError(ds, "uspoof_swap(): data format %02x.%02x.%02x.%02x "
+ "(format version %02x %02x %02x %02x) is not recognized\n",
+ pInfo->dataFormat[0], pInfo->dataFormat[1],
+ pInfo->dataFormat[2], pInfo->dataFormat[3],
+ pInfo->formatVersion[0], pInfo->formatVersion[1],
+ pInfo->formatVersion[2], pInfo->formatVersion[3]);
+ *status=U_UNSUPPORTED_ERROR;
+ return 0;
+ }
+
+ //
+ // Swap the data header. (This is the generic ICU Data Header, not the uspoof Specific
+ // header). This swap also conveniently gets us
+ // the size of the ICU d.h., which lets us locate the start
+ // of the uspoof specific data.
+ //
+ int32_t headerSize=udata_swapDataHeader(ds, inData, length, outData, status);
+
+
+ //
+ // Get the Spoof Data Header, and check that it appears to be OK.
+ //
+ //
+ const uint8_t *inBytes =(const uint8_t *)inData+headerSize;
+ SpoofDataHeader *spoofDH = (SpoofDataHeader *)inBytes;
+ if (ds->readUInt32(spoofDH->fMagic) != USPOOF_MAGIC ||
+ ds->readUInt32(spoofDH->fLength) < sizeof(SpoofDataHeader))
+ {
+ udata_printError(ds, "uspoof_swap(): Spoof Data header is invalid.\n");
+ *status=U_UNSUPPORTED_ERROR;
+ return 0;
+ }
+
+ //
+ // Prefight operation? Just return the size
+ //
+ int32_t spoofDataLength = ds->readUInt32(spoofDH->fLength);
+ int32_t totalSize = headerSize + spoofDataLength;
+ if (length < 0) {
+ return totalSize;
+ }
+
+ //
+ // Check that length passed in is consistent with length from Spoof data header.
+ //
+ if (length < totalSize) {
+ udata_printError(ds, "uspoof_swap(): too few bytes (%d after ICU Data header) for spoof data.\n",
+ spoofDataLength);
+ *status=U_INDEX_OUTOFBOUNDS_ERROR;
+ return 0;
+ }
+
+
+ //
+ // Swap the Data. Do the data itself first, then the Spoof Data Header, because
+ // we need to reference the header to locate the data, and an
+ // inplace swap of the header leaves it unusable.
+ //
+ uint8_t *outBytes = (uint8_t *)outData + headerSize;
+ SpoofDataHeader *outputDH = (SpoofDataHeader *)outBytes;
+
+ int32_t sectionStart;
+ int32_t sectionLength;
+
+ //
+ // If not swapping in place, zero out the output buffer before starting.
+ // Gaps may exist between the individual sections, and these must be zeroed in
+ // the output buffer. The simplest way to do that is to just zero the whole thing.
+ //
+ if (inBytes != outBytes) {
+ uprv_memset(outBytes, 0, spoofDataLength);
+ }
+
+ // Confusables Keys Section (fCFUKeys)
+ sectionStart = ds->readUInt32(spoofDH->fCFUKeys);
+ sectionLength = ds->readUInt32(spoofDH->fCFUKeysSize) * 4;
+ ds->swapArray32(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status);
+
+ // String Index Section
+ sectionStart = ds->readUInt32(spoofDH->fCFUStringIndex);
+ sectionLength = ds->readUInt32(spoofDH->fCFUStringIndexSize) * 2;
+ ds->swapArray16(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status);
+
+ // String Table Section
+ sectionStart = ds->readUInt32(spoofDH->fCFUStringTable);
+ sectionLength = ds->readUInt32(spoofDH->fCFUStringTableLen) * 2;
+ ds->swapArray16(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status);
+
+ // And, last, swap the header itself.
+ // int32_t fMagic // swap this
+ // uint8_t fFormatVersion[4] // Do not swap this, just copy
+ // int32_t fLength and all the rest // Swap the rest, all is 32 bit stuff.
+ //
+ uint32_t magic = ds->readUInt32(spoofDH->fMagic);
+ ds->writeUInt32((uint32_t *)&outputDH->fMagic, magic);
+
+ if (outputDH->fFormatVersion != spoofDH->fFormatVersion) {
+ uprv_memcpy(outputDH->fFormatVersion, spoofDH->fFormatVersion, sizeof(spoofDH->fFormatVersion));
+ }
+ // swap starting at fLength
+ ds->swapArray32(ds, &spoofDH->fLength, sizeof(SpoofDataHeader)-8 /* minus magic and fFormatVersion[4] */, &outputDH->fLength, status);
+
+ return totalSize;
+}
+
+#endif
+
+
diff --git a/thirdparty/icu4c/i18n/uspoof_impl.h b/thirdparty/icu4c/i18n/uspoof_impl.h
new file mode 100644
index 0000000000..e75ae262bd
--- /dev/null
+++ b/thirdparty/icu4c/i18n/uspoof_impl.h
@@ -0,0 +1,343 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+***************************************************************************
+* Copyright (C) 2008-2013, International Business Machines Corporation
+* and others. All Rights Reserved.
+***************************************************************************
+*
+* uspoof_impl.h
+*
+* Implementation header for spoof detection
+*
+*/
+
+#ifndef USPOOFIM_H
+#define USPOOFIM_H
+
+#include "uassert.h"
+#include "unicode/utypes.h"
+#include "unicode/uspoof.h"
+#include "unicode/uscript.h"
+#include "unicode/udata.h"
+#include "udataswp.h"
+#include "utrie2.h"
+
+#if !UCONFIG_NO_NORMALIZATION
+
+#ifdef __cplusplus
+
+#include "capi_helper.h"
+
+U_NAMESPACE_BEGIN
+
+// The maximum length (in UTF-16 UChars) of the skeleton replacement string resulting from
+// a single input code point. This is function of the unicode.org data.
+#define USPOOF_MAX_SKELETON_EXPANSION 20
+
+// The default stack buffer size for copies or conversions or normalizations
+// of input strings being checked. (Used in multiple places.)
+#define USPOOF_STACK_BUFFER_SIZE 100
+
+// Magic number for sanity checking spoof data.
+#define USPOOF_MAGIC 0x3845fdef
+
+// Magic number for sanity checking spoof checkers.
+#define USPOOF_CHECK_MAGIC 0x2734ecde
+
+class ScriptSet;
+class SpoofData;
+struct SpoofDataHeader;
+class ConfusableDataUtils;
+
+/**
+ * Class SpoofImpl corresponds directly to the plain C API opaque type
+ * USpoofChecker. One can be cast to the other.
+ */
+class SpoofImpl : public UObject,
+ public IcuCApiHelper<USpoofChecker, SpoofImpl, USPOOF_MAGIC> {
+public:
+ SpoofImpl(SpoofData *data, UErrorCode& status);
+ SpoofImpl(UErrorCode& status);
+ SpoofImpl();
+ void construct(UErrorCode& status);
+ virtual ~SpoofImpl();
+
+ /** Copy constructor, used by the user level uspoof_clone() function.
+ */
+ SpoofImpl(const SpoofImpl &src, UErrorCode &status);
+
+ USpoofChecker *asUSpoofChecker();
+ static SpoofImpl *validateThis(USpoofChecker *sc, UErrorCode &status);
+ static const SpoofImpl *validateThis(const USpoofChecker *sc, UErrorCode &status);
+
+ /** Set and Get AllowedLocales, implementations of the corresponding API */
+ void setAllowedLocales(const char *localesList, UErrorCode &status);
+ const char * getAllowedLocales(UErrorCode &status);
+
+ // Add (union) to the UnicodeSet all of the characters for the scripts used for
+ // the specified locale. Part of the implementation of setAllowedLocales.
+ void addScriptChars(const char *locale, UnicodeSet *allowedChars, UErrorCode &status);
+
+ // Functions implementing the features of UTS 39 section 5.
+ static void getAugmentedScriptSet(UChar32 codePoint, ScriptSet& result, UErrorCode& status);
+ void getResolvedScriptSet(const UnicodeString& input, ScriptSet& result, UErrorCode& status) const;
+ void getResolvedScriptSetWithout(const UnicodeString& input, UScriptCode script, ScriptSet& result, UErrorCode& status) const;
+ void getNumerics(const UnicodeString& input, UnicodeSet& result, UErrorCode& status) const;
+ URestrictionLevel getRestrictionLevel(const UnicodeString& input, UErrorCode& status) const;
+
+ int32_t findHiddenOverlay(const UnicodeString& input, UErrorCode& status) const;
+ bool isIllegalCombiningDotLeadCharacter(UChar32 cp) const;
+
+ /** parse a hex number. Untility used by the builders. */
+ static UChar32 ScanHex(const UChar *s, int32_t start, int32_t limit, UErrorCode &status);
+
+ static UClassID U_EXPORT2 getStaticClassID(void);
+ virtual UClassID getDynamicClassID(void) const override;
+
+ //
+ // Data Members
+ //
+
+ int32_t fChecks; // Bit vector of checks to perform.
+
+ SpoofData *fSpoofData;
+
+ const UnicodeSet *fAllowedCharsSet; // The UnicodeSet of allowed characters.
+ // for this Spoof Checker. Defaults to all chars.
+
+ const char *fAllowedLocales; // The list of allowed locales.
+ URestrictionLevel fRestrictionLevel; // The maximum restriction level for an acceptable identifier.
+};
+
+/**
+ * Class CheckResult corresponds directly to the plain C API opaque type
+ * USpoofCheckResult. One can be cast to the other.
+ */
+class CheckResult : public UObject,
+ public IcuCApiHelper<USpoofCheckResult, CheckResult, USPOOF_CHECK_MAGIC> {
+public:
+ CheckResult();
+ virtual ~CheckResult();
+
+ USpoofCheckResult *asUSpoofCheckResult();
+ static CheckResult *validateThis(USpoofCheckResult *ptr, UErrorCode &status);
+ static const CheckResult *validateThis(const USpoofCheckResult *ptr, UErrorCode &status);
+
+ void clear();
+
+ // Used to convert this CheckResult to the older int32_t return value API
+ int32_t toCombinedBitmask(int32_t expectedChecks);
+
+ // Data Members
+ int32_t fChecks; // Bit vector of checks that were failed.
+ UnicodeSet fNumerics; // Set of numerics found in the string.
+ URestrictionLevel fRestrictionLevel; // The restriction level of the string.
+};
+
+
+//
+// Confusable Mappings Data Structures, version 2.0
+//
+// For the confusable data, we are essentially implementing a map,
+// key: a code point
+// value: a string. Most commonly one char in length, but can be more.
+//
+// The keys are stored as a sorted array of 32 bit ints.
+// bits 0-23 a code point value
+// bits 24-31 length of value string, in UChars (between 1 and 256 UChars).
+// The key table is sorted in ascending code point order. (not on the
+// 32 bit int value, the flag bits do not participate in the sorting.)
+//
+// Lookup is done by means of a binary search in the key table.
+//
+// The corresponding values are kept in a parallel array of 16 bit ints.
+// If the value string is of length 1, it is literally in the value array.
+// For longer strings, the value array contains an index into the strings table.
+//
+// String Table:
+// The strings table contains all of the value strings (those of length two or greater)
+// concatenated together into one long UChar (UTF-16) array.
+//
+// There is no nul character or other mark between adjacent strings.
+//
+//----------------------------------------------------------------------------
+//
+// Changes from format version 1 to format version 2:
+// 1) Removal of the whole-script confusable data tables.
+// 2) Removal of the SL/SA/ML/MA and multi-table flags in the key bitmask.
+// 3) Expansion of string length value in the key bitmask from 2 bits to 8 bits.
+// 4) Removal of the string lengths table since 8 bits is sufficient for the
+// lengths of all entries in confusables.txt.
+
+
+
+// Internal functions for manipulating confusable data table keys
+#define USPOOF_CONFUSABLE_DATA_FORMAT_VERSION 2 // version for ICU 58
+class ConfusableDataUtils {
+public:
+ inline static UChar32 keyToCodePoint(int32_t key) {
+ return key & 0x00ffffff;
+ }
+ inline static int32_t keyToLength(int32_t key) {
+ return ((key & 0xff000000) >> 24) + 1;
+ }
+ inline static int32_t codePointAndLengthToKey(UChar32 codePoint, int32_t length) {
+ U_ASSERT((codePoint & 0x00ffffff) == codePoint);
+ U_ASSERT(length <= 256);
+ return codePoint | ((length - 1) << 24);
+ }
+};
+
+
+//-------------------------------------------------------------------------------------
+//
+// SpoofData
+//
+// A small class that wraps the raw (usually memory mapped) spoof data.
+// Serves two primary functions:
+// 1. Convenience. Contains real pointers to the data, to avoid dealing with
+// the offsets in the raw data.
+// 2. Reference counting. When a spoof checker is cloned, the raw data is shared
+// and must be retained until all checkers using the data are closed.
+// Nothing in this struct includes state that is specific to any particular
+// USpoofDetector object.
+//
+//---------------------------------------------------------------------------------------
+class SpoofData: public UMemory {
+ public:
+ static SpoofData* getDefault(UErrorCode &status); // Get standard ICU spoof data.
+ static void releaseDefault(); // Cleanup reference to default spoof data.
+
+ SpoofData(UErrorCode &status); // Create new spoof data wrapper.
+ // Only used when building new data from rules.
+
+ // Constructor for use when creating from prebuilt default data.
+ // A UDataMemory is what the ICU internal data loading functions provide.
+ // The udm is adopted by the SpoofData.
+ SpoofData(UDataMemory *udm, UErrorCode &status);
+
+ // Constructor for use when creating from serialized data.
+ //
+ SpoofData(const void *serializedData, int32_t length, UErrorCode &status);
+
+ // Check raw Spoof Data Version compatibility.
+ // Return true it looks good.
+ UBool validateDataVersion(UErrorCode &status) const;
+
+ ~SpoofData(); // Destructor not normally used.
+ // Use removeReference() instead.
+ // Reference Counting functions.
+ // Clone of a user-level spoof detector increments the ref count on the data.
+ // Close of a user-level spoof detector decrements the ref count.
+ // If the data is owned by us, it will be deleted when count goes to zero.
+ SpoofData *addReference();
+ void removeReference();
+
+ // Reset all fields to an initial state.
+ // Called from the top of all constructors.
+ void reset();
+
+ // Copy this instance's raw data buffer to the specified address.
+ int32_t serialize(void *buf, int32_t capacity, UErrorCode &status) const;
+
+ // Get the total number of bytes of data backed by this SpoofData.
+ // Not to be confused with length, which returns the number of confusable entries.
+ int32_t size() const;
+
+ // Get the confusable skeleton transform for a single code point.
+ // The result is a string with a length between 1 and 18 as of Unicode 9.
+ // This is the main public endpoint for this class.
+ // @return The length in UTF-16 code units of the substitution string.
+ int32_t confusableLookup(UChar32 inChar, UnicodeString &dest) const;
+
+ // Get the number of confusable entries in this SpoofData.
+ int32_t length() const;
+
+ // Get the code point (key) at the specified index.
+ UChar32 codePointAt(int32_t index) const;
+
+ // Get the confusable skeleton (value) at the specified index.
+ // Append it to the specified UnicodeString&.
+ // @return The length in UTF-16 code units of the skeleton string.
+ int32_t appendValueTo(int32_t index, UnicodeString& dest) const;
+
+ private:
+ // Reserve space in the raw data. For use by builder when putting together a
+ // new set of data. Init the new storage to zero, to prevent inconsistent
+ // results if it is not all otherwise set by the requester.
+ // Return:
+ // pointer to the new space that was added by this function.
+ void *reserveSpace(int32_t numBytes, UErrorCode &status);
+
+ // initialize the pointers from this object to the raw data.
+ void initPtrs(UErrorCode &status);
+
+ SpoofDataHeader *fRawData; // Ptr to the raw memory-mapped data
+ UBool fDataOwned; // True if the raw data is owned, and needs
+ // to be deleted when refcount goes to zero.
+ UDataMemory *fUDM; // If not NULL, our data came from a
+ // UDataMemory, which we must close when
+ // we are done.
+
+ uint32_t fMemLimit; // Limit of available raw data space
+ u_atomic_int32_t fRefCount;
+
+ // Confusable data
+ int32_t *fCFUKeys;
+ uint16_t *fCFUValues;
+ UChar *fCFUStrings;
+
+ friend class ConfusabledataBuilder;
+};
+
+//---------------------------------------------------------------------------------------
+//
+// Raw Binary Data Formats, as loaded from the ICU data file,
+// or as built by the builder.
+//
+//---------------------------------------------------------------------------------------
+struct SpoofDataHeader {
+ int32_t fMagic; // (0x3845fdef)
+ uint8_t fFormatVersion[4]; // Data Format. Same as the value in struct UDataInfo
+ // if there is one associated with this data.
+ int32_t fLength; // Total length in bytes of this spoof data,
+ // including all sections, not just the header.
+
+ // The following four sections refer to data representing the confusable data
+ // from the Unicode.org data from "confusables.txt"
+
+ int32_t fCFUKeys; // byte offset to Keys table (from SpoofDataHeader *)
+ int32_t fCFUKeysSize; // number of entries in keys table (32 bits each)
+
+ // TODO: change name to fCFUValues, for consistency.
+ int32_t fCFUStringIndex; // byte offset to String Indexes table
+ int32_t fCFUStringIndexSize; // number of entries in String Indexes table (16 bits each)
+ // (number of entries must be same as in Keys table
+
+ int32_t fCFUStringTable; // byte offset of String table
+ int32_t fCFUStringTableLen; // length of string table (in 16 bit UChars)
+
+ // The following sections are for data from xidmodifications.txt
+
+ int32_t unused[15]; // Padding, Room for Expansion
+};
+
+
+
+U_NAMESPACE_END
+#endif /* __cplusplus */
+
+/**
+ * Endianness swap function for binary spoof data.
+ * @internal
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData,
+ UErrorCode *status);
+
+
+#endif
+
+#endif /* USPOOFIM_H */
+
diff --git a/thirdparty/icu4c/icudt71l.dat b/thirdparty/icu4c/icudt71l.dat
index 4c2c1c4d16..3fa3af9c23 100644
--- a/thirdparty/icu4c/icudt71l.dat
+++ b/thirdparty/icu4c/icudt71l.dat
Binary files differ
diff --git a/thirdparty/mbedtls/LICENSE b/thirdparty/mbedtls/LICENSE
index e15ea821d2..d645695673 100644
--- a/thirdparty/mbedtls/LICENSE
+++ b/thirdparty/mbedtls/LICENSE
@@ -1,5 +1,202 @@
-Unless specifically indicated otherwise in a file, Mbed TLS files are provided
-under the Apache License 2.0, or the GNU General Public License v2.0 or later
-(SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later).
-A copy of these licenses can be found in apache-2.0.txt and gpl-2.0.txt
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/thirdparty/mbedtls/apache-2.0.txt b/thirdparty/mbedtls/apache-2.0.txt
deleted file mode 100644
index d645695673..0000000000
--- a/thirdparty/mbedtls/apache-2.0.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/thirdparty/mbedtls/include/mbedtls/aes.h b/thirdparty/mbedtls/include/mbedtls/aes.h
index e280dbb1c6..401ac39de8 100644
--- a/thirdparty/mbedtls/include/mbedtls/aes.h
+++ b/thirdparty/mbedtls/include/mbedtls/aes.h
@@ -564,7 +564,7 @@ int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
* for example, with 96-bit random nonces, you should not encrypt
* more than 2**32 messages with the same key.
*
- * Note that for both stategies, sizes are measured in blocks and
+ * Note that for both strategies, sizes are measured in blocks and
* that an AES block is 16 bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
diff --git a/thirdparty/mbedtls/include/mbedtls/aria.h b/thirdparty/mbedtls/include/mbedtls/aria.h
index 226e2dbf3c..d294c47f2d 100644
--- a/thirdparty/mbedtls/include/mbedtls/aria.h
+++ b/thirdparty/mbedtls/include/mbedtls/aria.h
@@ -44,7 +44,7 @@
#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */
#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */
-#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */
+#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maximum number of rounds in ARIA. */
#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
@@ -321,7 +321,7 @@ int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx,
* for example, with 96-bit random nonces, you should not encrypt
* more than 2**32 messages with the same key.
*
- * Note that for both stategies, sizes are measured in blocks and
+ * Note that for both strategies, sizes are measured in blocks and
* that an ARIA block is 16 bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
diff --git a/thirdparty/mbedtls/include/mbedtls/asn1.h b/thirdparty/mbedtls/include/mbedtls/asn1.h
index 10f7905b7e..5117fc7a41 100644
--- a/thirdparty/mbedtls/include/mbedtls/asn1.h
+++ b/thirdparty/mbedtls/include/mbedtls/asn1.h
@@ -61,7 +61,7 @@
/** Buffer too small when writing ASN.1 data structure. */
#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C
-/* \} name */
+/** \} name ASN1 Error codes */
/**
* \name DER constants
@@ -121,8 +121,7 @@
#define MBEDTLS_ASN1_TAG_PC_MASK 0x20
#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F
-/* \} name */
-/* \} addtogroup asn1_module */
+/** \} name DER constants */
/** Returns the size of the binary string, without the trailing \\0 */
#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1)
@@ -210,7 +209,7 @@ mbedtls_asn1_named_data;
* \return 0 if successful.
* \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
* would end beyond \p end.
- * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable.
*/
int mbedtls_asn1_get_len( unsigned char **p,
const unsigned char *end,
@@ -235,7 +234,7 @@ int mbedtls_asn1_get_len( unsigned char **p,
* with the requested tag.
* \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
* would end beyond \p end.
- * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable.
*/
int mbedtls_asn1_get_tag( unsigned char **p,
const unsigned char *end,
@@ -607,6 +606,9 @@ void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry );
*/
void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head );
+/** \} name Functions to parse ASN.1 data structures */
+/** \} addtogroup asn1_module */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h
index 9d2cff3275..dd594c512d 100644
--- a/thirdparty/mbedtls/include/mbedtls/bignum.h
+++ b/thirdparty/mbedtls/include/mbedtls/bignum.h
@@ -989,7 +989,7 @@ MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
* generate yourself and that are supposed to be prime, then
* \p rounds should be at least the half of the security
* strength of the cryptographic algorithm. On the other hand,
- * if \p X is chosen uniformly or non-adversially (as is the
+ * if \p X is chosen uniformly or non-adversarially (as is the
* case when mbedtls_mpi_gen_prime calls this function), then
* \p rounds can be much lower.
*
diff --git a/thirdparty/mbedtls/include/mbedtls/blowfish.h b/thirdparty/mbedtls/include/mbedtls/blowfish.h
index 77dca70d31..d5f809921f 100644
--- a/thirdparty/mbedtls/include/mbedtls/blowfish.h
+++ b/thirdparty/mbedtls/include/mbedtls/blowfish.h
@@ -185,7 +185,7 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
* #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
* #MBEDTLS_BLOWFISH_DECRYPT for decryption.
* \param length The length of the input data in Bytes.
- * \param iv_off The offset in the initialiation vector.
+ * \param iv_off The offset in the initialization vector.
* The value pointed to must be smaller than \c 8 Bytes.
* It is updated by this function to support the aforementioned
* streaming usage.
@@ -246,7 +246,7 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
* The recommended way to ensure uniqueness is to use a message
* counter.
*
- * Note that for both stategies, sizes are measured in blocks and
+ * Note that for both strategies, sizes are measured in blocks and
* that a Blowfish block is 8 bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
diff --git a/thirdparty/mbedtls/include/mbedtls/camellia.h b/thirdparty/mbedtls/include/mbedtls/camellia.h
index 925a623e47..d39d932fa2 100644
--- a/thirdparty/mbedtls/include/mbedtls/camellia.h
+++ b/thirdparty/mbedtls/include/mbedtls/camellia.h
@@ -273,7 +273,7 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
* encrypted: for example, with 96-bit random nonces, you should
* not encrypt more than 2**32 messages with the same key.
*
- * Note that for both stategies, sizes are measured in blocks and
+ * Note that for both strategies, sizes are measured in blocks and
* that a CAMELLIA block is \c 16 Bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
diff --git a/thirdparty/mbedtls/include/mbedtls/chachapoly.h b/thirdparty/mbedtls/include/mbedtls/chachapoly.h
index c4ec7b5f2a..ed568bc98b 100644
--- a/thirdparty/mbedtls/include/mbedtls/chachapoly.h
+++ b/thirdparty/mbedtls/include/mbedtls/chachapoly.h
@@ -161,7 +161,7 @@ int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
* \param ctx The ChaCha20-Poly1305 context. This must be initialized
* and bound to a key.
* \param nonce The nonce/IV to use for the message.
- * This must be a redable buffer of length \c 12 Bytes.
+ * This must be a readable buffer of length \c 12 Bytes.
* \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or
* #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning).
*
diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h
index 396fe7dfc2..be5c548e56 100644
--- a/thirdparty/mbedtls/include/mbedtls/check_config.h
+++ b/thirdparty/mbedtls/include/mbedtls/check_config.h
@@ -173,7 +173,11 @@
#endif
#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C)
-#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites"
+#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PKCS5_C) && !defined(MBEDTLS_MD_C)
+#error "MBEDTLS_PKCS5_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \
@@ -214,11 +218,32 @@
#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too"
#endif
+#if defined(MBEDTLS_CCM_C) && ( \
+ !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) )
+#error "MBEDTLS_CCM_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_CCM_C) && !defined(MBEDTLS_CIPHER_C)
+#error "MBEDTLS_CCM_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_GCM_C) && ( \
- !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) )
+ !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) )
+#error "MBEDTLS_GCM_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_GCM_C) && !defined(MBEDTLS_CIPHER_C)
#error "MBEDTLS_GCM_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_CHACHA20_C)
+#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_POLY1305_C)
+#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)
#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites"
#endif
@@ -338,11 +363,11 @@
#endif
#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites"
+#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites"
+#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
@@ -619,6 +644,18 @@
#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO."
#endif
+#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO) && \
+ !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_ECDSA_C)
+#error "MBEDTLS_PK_C in configuration with MBEDTLS_USE_PSA_CRYPTO and \
+ MBEDTLS_ECDSA_C requires MBEDTLS_PK_WRITE_C to be defined."
+#endif
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V15) && \
+ !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_PSA_CRYPTO_C)
+#error "MBEDTLS_PSA_CRYPTO_C, MBEDTLS_RSA_C and MBEDTLS_PKCS1_V15 defined, \
+ but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) )
#error "MBEDTLS_RSA_C defined, but not all prerequisites"
@@ -761,14 +798,14 @@
!defined(MBEDTLS_SSL_PROTO_TLS1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites"
+#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \
!defined(MBEDTLS_SSL_PROTO_TLS1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites"
+#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C)
diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h
index 87b4e9192e..1cd6eb6634 100644
--- a/thirdparty/mbedtls/include/mbedtls/config.h
+++ b/thirdparty/mbedtls/include/mbedtls/config.h
@@ -128,7 +128,12 @@
* MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and
* MBEDTLS_PLATFORM_STD_TIME.
*
- * Comment if your system does not support time functions
+ * Comment if your system does not support time functions.
+ *
+ * \note If MBEDTLS_TIMING_C is set - to enable the semi-portable timing
+ * interface - timing.c will include time.h on suitable platforms
+ * regardless of the setting of MBEDTLS_HAVE_TIME, unless
+ * MBEDTLS_TIMING_ALT is used. See timing.c for more information.
*/
#define MBEDTLS_HAVE_TIME
@@ -321,7 +326,7 @@
*/
//#define MBEDTLS_CHECK_PARAMS_ASSERT
-/* \} name SECTION: System support */
+/** \} name SECTION: System support */
/**
* \name SECTION: mbed TLS feature support
@@ -395,7 +400,7 @@
//#define MBEDTLS_XTEA_ALT
/*
- * When replacing the elliptic curve module, pleace consider, that it is
+ * When replacing the elliptic curve module, please consider, that it is
* implemented with two .c files:
* - ecp.c
* - ecp_curves.c
@@ -1493,7 +1498,7 @@
* Enable an implementation of SHA-256 that has lower ROM footprint but also
* lower performance.
*
- * The default implementation is meant to be a reasonnable compromise between
+ * The default implementation is meant to be a reasonable compromise between
* performance and size. This version optimizes more aggressively for size at
* the expense of performance. Eg on Cortex-M4 it reduces the size of
* mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
@@ -1658,7 +1663,7 @@
* Enable support for RFC 7627: Session Hash and Extended Master Secret
* Extension.
*
- * This was introduced as "the proper fix" to the Triple Handshake familiy of
+ * This was introduced as "the proper fix" to the Triple Handshake family of
* attacks, but it is recommended to always use it (even if you disable
* renegotiation), since it actually fixes a more fundamental issue in the
* original SSL/TLS design, and has implications beyond Triple Handshake.
@@ -1704,7 +1709,7 @@
* \note This option has no influence on the protection against the
* triple handshake attack. Even if it is disabled, Mbed TLS will
* still ensure that certificates do not change during renegotiation,
- * for exaple by keeping a hash of the peer's certificate.
+ * for example by keeping a hash of the peer's certificate.
*
* Comment this macro to disable storing the peer's certificate
* after the handshake.
@@ -1909,7 +1914,7 @@
* unless you know for sure amplification cannot be a problem in the
* environment in which your server operates.
*
- * \warning Disabling this can ba a security risk! (see above)
+ * \warning Disabling this can be a security risk! (see above)
*
* Requires: MBEDTLS_SSL_PROTO_DTLS
*
@@ -2162,8 +2167,19 @@
* This setting allows support for cryptographic mechanisms through the PSA
* API to be configured separately from support through the mbedtls API.
*
- * Uncomment this to enable use of PSA Crypto configuration settings which
- * can be found in include/psa/crypto_config.h.
+ * When this option is disabled, the PSA API exposes the cryptographic
+ * mechanisms that can be implemented on top of the `mbedtls_xxx` API
+ * configured with `MBEDTLS_XXX` symbols.
+ *
+ * When this option is enabled, the PSA API exposes the cryptographic
+ * mechanisms requested by the `PSA_WANT_XXX` symbols defined in
+ * include/psa/crypto_config.h. The corresponding `MBEDTLS_XXX` settings are
+ * automatically enabled if required (i.e. if no PSA driver provides the
+ * mechanism). You may still freely enable additional `MBEDTLS_XXX` symbols
+ * in config.h.
+ *
+ * If the symbol #MBEDTLS_PSA_CRYPTO_CONFIG_FILE is defined, it specifies
+ * an alternative header to include instead of include/psa/crypto_config.h.
*
* If you enable this option and write your own configuration file, you must
* include mbedtls/config_psa.h in your configuration file. The default
@@ -2289,7 +2305,7 @@
* Uncomment to enable use of ZLIB
*/
//#define MBEDTLS_ZLIB_SUPPORT
-/* \} name SECTION: mbed TLS feature support */
+/** \} name SECTION: mbed TLS feature support */
/**
* \name SECTION: mbed TLS modules
@@ -2902,7 +2918,7 @@
*
* Requires: MBEDTLS_MD_C
*
- * Uncomment to enable the HMAC_DRBG random number geerator.
+ * Uncomment to enable the HMAC_DRBG random number generator.
*/
#define MBEDTLS_HMAC_DRBG_C
@@ -3096,7 +3112,7 @@
/**
* \def MBEDTLS_PK_C
*
- * Enable the generic public (asymetric) key layer.
+ * Enable the generic public (asymmetric) key layer.
*
* Module: library/pk.c
* Caller: library/ssl_tls.c
@@ -3112,7 +3128,7 @@
/**
* \def MBEDTLS_PK_PARSE_C
*
- * Enable the generic public (asymetric) key parser.
+ * Enable the generic public (asymmetric) key parser.
*
* Module: library/pkparse.c
* Caller: library/x509_crt.c
@@ -3127,7 +3143,7 @@
/**
* \def MBEDTLS_PK_WRITE_C
*
- * Enable the generic public (asymetric) key writer.
+ * Enable the generic public (asymmetric) key writer.
*
* Module: library/pkwrite.c
* Caller: library/x509write.c
@@ -3466,6 +3482,10 @@
* your own implementation of the whole module by setting
* \c MBEDTLS_TIMING_ALT in the current file.
*
+ * \note The timing module will include time.h on suitable platforms
+ * regardless of the setting of MBEDTLS_HAVE_TIME, unless
+ * MBEDTLS_TIMING_ALT is used. See timing.c for more information.
+ *
* \note See also our Knowledge Base article about porting to a new
* environment:
* https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
@@ -3598,7 +3618,88 @@
*/
#define MBEDTLS_XTEA_C
-/* \} name SECTION: mbed TLS modules */
+/** \} name SECTION: mbed TLS modules */
+
+/**
+ * \name SECTION: General configuration options
+ *
+ * This section contains Mbed TLS build settings that are not associated
+ * with a particular module.
+ *
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included instead of
+ * `"mbedtls/config.h"`.
+ * This header file specifies the compile-time configuration of Mbed TLS.
+ * Unlike other configuration options, this one must be defined on the
+ * compiler command line: a definition in `config.h` would have no effect.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_CONFIG_FILE "mbedtls/config.h"
+
+/**
+ * \def MBEDTLS_USER_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included after
+ * `"mbedtls/config.h"` or #MBEDTLS_CONFIG_FILE.
+ * This allows you to modify the default configuration, including the ability
+ * to undefine options that are enabled by default.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_USER_CONFIG_FILE "/dev/null"
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included instead of
+ * `"psa/crypto_config.h"`.
+ * This header file specifies which cryptographic mechanisms are available
+ * through the PSA API when #MBEDTLS_PSA_CRYPTO_CONFIG is enabled, and
+ * is not used when #MBEDTLS_PSA_CRYPTO_CONFIG is disabled.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "psa/crypto_config.h"
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included after
+ * `"psa/crypto_config.h"` or #MBEDTLS_PSA_CRYPTO_CONFIG_FILE.
+ * This allows you to modify the default configuration, including the ability
+ * to undefine options that are enabled by default.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE "/dev/null"
+
+/** \} name SECTION: General configuration options */
/**
* \name SECTION: Module configuration options
@@ -3609,11 +3710,15 @@
*
* Our advice is to enable options and change their values here
* only if you have a good reason and know the consequences.
- *
- * Please check the respective header file for documentation on these
- * parameters (to prevent duplicate documentation).
* \{
*/
+/* The Doxygen documentation here is used when a user comments out a
+ * setting and runs doxygen themselves. On the other hand, when we typeset
+ * the full documentation including disabled settings, the documentation
+ * in specific modules' header files is used if present. When editing this
+ * file, make sure that each option is documented in exactly one place,
+ * plus optionally a same-line Doxygen comment here if there is a Doxygen
+ * comment in the specific module. */
/* MPI / BIGNUM options */
//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */
@@ -4002,7 +4107,7 @@
*/
//#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
-/* \} name SECTION: Customisation configuration options */
+/** \} name SECTION: Module configuration options */
/* Target and application specific configurations
*
diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
index dc4adc896d..e68237a439 100644
--- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
@@ -138,7 +138,7 @@
/**< The maximum size of seed or reseed buffer in bytes. */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#define MBEDTLS_CTR_DRBG_PR_OFF 0
/**< Prediction resistance is disabled. */
diff --git a/thirdparty/mbedtls/include/mbedtls/debug.h b/thirdparty/mbedtls/include/mbedtls/debug.h
index 3c08244f3d..4fc4662d9a 100644
--- a/thirdparty/mbedtls/include/mbedtls/debug.h
+++ b/thirdparty/mbedtls/include/mbedtls/debug.h
@@ -139,7 +139,7 @@ extern "C" {
* discarded.
* (Default value: 0 = No debug )
*
- * \param threshold theshold level of messages to filter on. Messages at a
+ * \param threshold threshold level of messages to filter on. Messages at a
* higher level will be discarded.
* - Debug levels
* - 0 No debug
diff --git a/thirdparty/mbedtls/include/mbedtls/ecjpake.h b/thirdparty/mbedtls/include/mbedtls/ecjpake.h
index 891705d8c4..3564ff8dd3 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecjpake.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecjpake.h
@@ -68,7 +68,7 @@ typedef enum {
* (KeyExchange) as defined by the Thread spec.
*
* In order to benefit from this symmetry, we choose a different naming
- * convetion from the Thread v1.0 spec. Correspondance is indicated in the
+ * convention from the Thread v1.0 spec. Correspondence is indicated in the
* description as a pair C: client name, S: server name
*/
typedef struct mbedtls_ecjpake_context
diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h
index 0924341e00..64a0bccda0 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecp.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecp.h
@@ -315,7 +315,7 @@ mbedtls_ecp_group;
#if !defined(MBEDTLS_ECP_WINDOW_SIZE)
/*
* Maximum "window" size used for point multiplication.
- * Default: a point where higher memory usage yields disminishing performance
+ * Default: a point where higher memory usage yields diminishing performance
* returns.
* Minimum value: 2. Maximum value: 7.
*
@@ -351,7 +351,7 @@ mbedtls_ecp_group;
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */
#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#else /* MBEDTLS_ECP_ALT */
#include "ecp_alt.h"
diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h
index deb3c50300..40259ebc8a 100644
--- a/thirdparty/mbedtls/include/mbedtls/entropy.h
+++ b/thirdparty/mbedtls/include/mbedtls/entropy.h
@@ -75,7 +75,7 @@
#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */
diff --git a/thirdparty/mbedtls/include/mbedtls/hkdf.h b/thirdparty/mbedtls/include/mbedtls/hkdf.h
index 223004b8ed..111d960e56 100644
--- a/thirdparty/mbedtls/include/mbedtls/hkdf.h
+++ b/thirdparty/mbedtls/include/mbedtls/hkdf.h
@@ -39,7 +39,7 @@
*/
/** Bad input parameters to function. */
#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80
-/* \} name */
+/** \} name */
#ifdef __cplusplus
extern "C" {
diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
index 79132d4d91..6d372b9788 100644
--- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
@@ -74,7 +74,7 @@
#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */
#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */
@@ -207,7 +207,7 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
size_t len );
/**
- * \brief Initilisation of simpified HMAC_DRBG (never reseeds).
+ * \brief Initialisation of simplified HMAC_DRBG (never reseeds).
*
* This function is meant for use in algorithms that need a pseudorandom
* input such as deterministic ECDSA.
diff --git a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h
index 233977252a..3954b36ab5 100644
--- a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h
+++ b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h
@@ -42,7 +42,7 @@
#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#define MBEDTLS_MEMORY_VERIFY_NONE 0
#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0)
diff --git a/thirdparty/mbedtls/include/mbedtls/oid.h b/thirdparty/mbedtls/include/mbedtls/oid.h
index 1c39186a49..0186217804 100644
--- a/thirdparty/mbedtls/include/mbedtls/oid.h
+++ b/thirdparty/mbedtls/include/mbedtls/oid.h
@@ -143,7 +143,7 @@
#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */
#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */
#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */
-#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */
+#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */
#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */
#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */
diff --git a/thirdparty/mbedtls/include/mbedtls/pem.h b/thirdparty/mbedtls/include/mbedtls/pem.h
index dfb4ff218e..daa71c886b 100644
--- a/thirdparty/mbedtls/include/mbedtls/pem.h
+++ b/thirdparty/mbedtls/include/mbedtls/pem.h
@@ -54,7 +54,7 @@
#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400
/** Bad input parameters to function. */
#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480
-/* \} name */
+/** \} name PEM Error codes */
#ifdef __cplusplus
extern "C" {
diff --git a/thirdparty/mbedtls/include/mbedtls/pk.h b/thirdparty/mbedtls/include/mbedtls/pk.h
index 8f2abf2a60..c9a13f484e 100644
--- a/thirdparty/mbedtls/include/mbedtls/pk.h
+++ b/thirdparty/mbedtls/include/mbedtls/pk.h
@@ -217,32 +217,6 @@ typedef struct
typedef void mbedtls_pk_restart_ctx;
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
-#if defined(MBEDTLS_RSA_C)
-/**
- * Quick access to an RSA context inside a PK context.
- *
- * \warning You must make sure the PK context actually holds an RSA context
- * before using this function!
- */
-static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk )
-{
- return( (mbedtls_rsa_context *) (pk).pk_ctx );
-}
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_ECP_C)
-/**
- * Quick access to an EC context inside a PK context.
- *
- * \warning You must make sure the PK context actually holds an EC context
- * before using this function!
- */
-static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk )
-{
- return( (mbedtls_ecp_keypair *) (pk).pk_ctx );
-}
-#endif /* MBEDTLS_ECP_C */
-
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/**
* \brief Types for RSA-alt abstraction
@@ -656,6 +630,55 @@ const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx );
*/
mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx );
+#if defined(MBEDTLS_RSA_C)
+/**
+ * Quick access to an RSA context inside a PK context.
+ *
+ * \warning This function can only be used when the type of the context, as
+ * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA.
+ * Ensuring that is the caller's responsibility.
+ * Alternatively, you can check whether this function returns NULL.
+ *
+ * \return The internal RSA context held by the PK context, or NULL.
+ */
+static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk )
+{
+ switch( mbedtls_pk_get_type( &pk ) )
+ {
+ case MBEDTLS_PK_RSA:
+ return( (mbedtls_rsa_context *) (pk).pk_ctx );
+ default:
+ return( NULL );
+ }
+}
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_ECP_C)
+/**
+ * Quick access to an EC context inside a PK context.
+ *
+ * \warning This function can only be used when the type of the context, as
+ * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY,
+ * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA.
+ * Ensuring that is the caller's responsibility.
+ * Alternatively, you can check whether this function returns NULL.
+ *
+ * \return The internal EC context held by the PK context, or NULL.
+ */
+static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk )
+{
+ switch( mbedtls_pk_get_type( &pk ) )
+ {
+ case MBEDTLS_PK_ECKEY:
+ case MBEDTLS_PK_ECKEY_DH:
+ case MBEDTLS_PK_ECDSA:
+ return( (mbedtls_ecp_keypair *) (pk).pk_ctx );
+ default:
+ return( NULL );
+ }
+}
+#endif /* MBEDTLS_ECP_C */
+
#if defined(MBEDTLS_PK_PARSE_C)
/** \ingroup pk_module */
/**
diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h
index bdef07498d..06dd192eab 100644
--- a/thirdparty/mbedtls/include/mbedtls/platform.h
+++ b/thirdparty/mbedtls/include/mbedtls/platform.h
@@ -70,7 +70,9 @@ extern "C" {
#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#include <stdio.h>
#include <stdlib.h>
+#if defined(MBEDTLS_HAVE_TIME)
#include <time.h>
+#endif
#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)
#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */
@@ -127,7 +129,7 @@ extern "C" {
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
/*
* The function pointers for calloc and free.
diff --git a/thirdparty/mbedtls/include/mbedtls/platform_time.h b/thirdparty/mbedtls/include/mbedtls/platform_time.h
index 7e7daab692..94055711b2 100644
--- a/thirdparty/mbedtls/include/mbedtls/platform_time.h
+++ b/thirdparty/mbedtls/include/mbedtls/platform_time.h
@@ -32,14 +32,6 @@
extern "C" {
#endif
-/**
- * \name SECTION: Module settings
- *
- * The configuration options you can set for this module are in this section.
- * Either change them in config.h or define them on the compiler command line.
- * \{
- */
-
/*
* The time_t datatype
*/
diff --git a/thirdparty/mbedtls/include/mbedtls/platform_util.h b/thirdparty/mbedtls/include/mbedtls/platform_util.h
index f982db8c01..cd112ab58e 100644
--- a/thirdparty/mbedtls/include/mbedtls/platform_util.h
+++ b/thirdparty/mbedtls/include/mbedtls/platform_util.h
@@ -67,7 +67,7 @@ extern "C" {
* \brief User supplied callback function for parameter validation failure.
* See #MBEDTLS_CHECK_PARAMS for context.
*
- * This function will be called unless an alternative treatement
+ * This function will be called unless an alternative treatment
* is defined through the #MBEDTLS_PARAM_FAILED macro.
*
* This function can return, and the operation will be aborted, or
@@ -198,7 +198,7 @@ MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t;
*
* This macro has an empty expansion. It exists for documentation purposes:
* a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function
- * has been analyzed for return-check usefuless, whereas the lack of
+ * has been analyzed for return-check usefulness, whereas the lack of
* an annotation indicates that the function has not been analyzed and its
* return-check usefulness is unknown.
*/
diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h
index 3c481e12a1..062df73aa0 100644
--- a/thirdparty/mbedtls/include/mbedtls/rsa.h
+++ b/thirdparty/mbedtls/include/mbedtls/rsa.h
@@ -88,7 +88,7 @@
/*
* The above constants may be used even if the RSA module is compile out,
- * eg for alternative (PKCS#11) RSA implemenations in the PK layers.
+ * eg for alternative (PKCS#11) RSA implementations in the PK layers.
*/
#ifdef __cplusplus
@@ -552,7 +552,7 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
*
* \note Blinding is used if and only if a PRNG is provided.
*
- * \note If blinding is used, both the base of exponentation
+ * \note If blinding is used, both the base of exponentiation
* and the exponent are blinded, providing protection
* against some side-channel attacks.
*
@@ -687,7 +687,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead
* return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
*
- * \param ctx The initnialized RSA context to use.
+ * \param ctx The initialized RSA context to use.
* \param f_rng The RNG function to use. This is needed for padding
* generation and must be provided.
* \param p_rng The RNG context to be passed to \p f_rng. This may
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h
index 209dbf6053..5064ec5689 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl.h
@@ -349,7 +349,7 @@
#define MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY 1
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
/*
* Length of the verify data for secure renegotiation
@@ -1152,7 +1152,7 @@ struct mbedtls_ssl_config
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
- /** Callback to create & write a cookie for ClientHello veirifcation */
+ /** Callback to create & write a cookie for ClientHello verification */
int (*f_cookie_write)( void *, unsigned char **, unsigned char *,
const unsigned char *, size_t );
/** Callback to verify validity of a ClientHello cookie */
@@ -1405,7 +1405,7 @@ struct mbedtls_ssl_context
unsigned char *compress_buf; /*!< zlib data buffer */
#endif /* MBEDTLS_ZLIB_SUPPORT */
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
- signed char split_done; /*!< current record already splitted? */
+ signed char split_done; /*!< current record already split? */
#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
/*
@@ -1688,7 +1688,7 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf,
*
* \note The two most common use cases are:
* - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL
- * - blocking I/O, f_recv == NULL, f_recv_timout != NULL
+ * - blocking I/O, f_recv == NULL, f_recv_timeout != NULL
*
* \note For DTLS, you need to provide either a non-NULL
* f_recv_timeout callback, or a f_recv that doesn't block.
@@ -1846,7 +1846,7 @@ int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
/**
- * \brief Set the Maximum Tranport Unit (MTU).
+ * \brief Set the Maximum Transport Unit (MTU).
* Special value: 0 means unset (no limit).
* This represents the maximum size of a datagram payload
* handled by the transport layer (usually UDP) as determined
@@ -2387,7 +2387,7 @@ void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode );
* ones going through the authentication-decryption phase.
*
* \note This is a security trade-off related to the fact that it's
- * often relatively easy for an active attacker ot inject UDP
+ * often relatively easy for an active attacker to inject UDP
* datagrams. On one hand, setting a low limit here makes it
* easier for such an attacker to forcibly terminated a
* connection. On the other hand, a high limit or no limit
@@ -2498,7 +2498,7 @@ void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min,
* successfully cached, return 1 otherwise.
*
* \param conf SSL configuration
- * \param p_cache parmater (context) for both callbacks
+ * \param p_cache parameter (context) for both callbacks
* \param f_get_cache session get callback
* \param f_set_cache session set callback
*/
@@ -2529,7 +2529,7 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session
/**
* \brief Load serialized session data into a session structure.
* On client, this can be used for loading saved sessions
- * before resuming them with mbedstls_ssl_set_session().
+ * before resuming them with mbedtls_ssl_set_session().
* On server, this can be used for alternative implementations
* of session cache or session tickets.
*
@@ -2793,7 +2793,7 @@ void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf,
*
* \note On client, only the first call has any effect. That is,
* only one client certificate can be provisioned. The
- * server's preferences in its CertficateRequest message will
+ * server's preferences in its CertificateRequest message will
* be ignored and our only cert will be sent regardless of
* whether it matches those preferences - the server can then
* decide what it wants to do with it.
@@ -3241,7 +3241,7 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
* \param protos Pointer to a NULL-terminated list of supported protocols,
* in decreasing preference order. The pointer to the list is
* recorded by the library for later reference as required, so
- * the lifetime of the table must be atleast as long as the
+ * the lifetime of the table must be at least as long as the
* lifetime of the SSL configuration structure.
*
* \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA.
@@ -3255,7 +3255,7 @@ int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **prot
*
* \param ssl SSL context
*
- * \return Protcol name, or NULL if no protocol was negotiated.
+ * \return Protocol name, or NULL if no protocol was negotiated.
*/
const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_ALPN */
@@ -3338,7 +3338,7 @@ int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl,
unsigned char *mki_value,
uint16_t mki_len );
/**
- * \brief Get the negotiated DTLS-SRTP informations:
+ * \brief Get the negotiated DTLS-SRTP information:
* Protection profile and MKI value.
*
* \warning This function must be called after the handshake is
@@ -3346,7 +3346,7 @@ int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl,
* not be trusted or acted upon before the handshake completes.
*
* \param ssl The SSL context to query.
- * \param dtls_srtp_info The negotiated DTLS-SRTP informations:
+ * \param dtls_srtp_info The negotiated DTLS-SRTP information:
* - Protection profile in use.
* A direct mapping of the iana defined value for protection
* profile on an uint16_t.
@@ -3508,7 +3508,7 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf,
* \c mbedtls_ssl_get_record_expansion().
*
* \note For DTLS, it is also possible to set a limit for the total
- * size of daragrams passed to the transport layer, including
+ * size of datagrams passed to the transport layer, including
* record overhead, see \c mbedtls_ssl_set_mtu().
*
* \param conf SSL configuration
@@ -3568,7 +3568,7 @@ void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets
* initiated by peer
* (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED)
*
- * \warning It is recommended to always disable renegotation unless you
+ * \warning It is recommended to always disable renegotiation unless you
* know you need it and you know what you're doing. In the
* past, there have been several issues associated with
* renegotiation or a poor understanding of its properties.
@@ -3631,7 +3631,7 @@ void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_
* scenario.
*
* \note With DTLS and server-initiated renegotiation, the
- * HelloRequest is retransmited every time mbedtls_ssl_read() times
+ * HelloRequest is retransmitted every time mbedtls_ssl_read() times
* out or receives Application Data, until:
* - max_records records have beens seen, if it is >= 0, or
* - the number of retransmits that would happen during an
@@ -4263,7 +4263,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl );
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small.
* \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed
- * while reseting the context.
+ * while resetting the context.
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in
* progress, or there is pending data for reading or sending,
* or the connection does not use DTLS 1.2 with an AEAD
@@ -4357,7 +4357,7 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl,
void mbedtls_ssl_config_init( mbedtls_ssl_config *conf );
/**
- * \brief Load reasonnable default SSL configuration values.
+ * \brief Load reasonable default SSL configuration values.
* (You need to call mbedtls_ssl_config_init() first.)
*
* \param conf SSL configuration context
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h
index c6ef2960f4..02eab96d45 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h
@@ -50,7 +50,7 @@
#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#ifdef __cplusplus
extern "C" {
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h
index 0a238708e5..2aa373177b 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h
@@ -45,7 +45,7 @@
#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#ifdef __cplusplus
extern "C" {
@@ -84,7 +84,7 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx,
* \brief Set expiration delay for cookies
* (Default MBEDTLS_SSL_COOKIE_TIMEOUT)
*
- * \param ctx Cookie contex
+ * \param ctx Cookie context
* \param delay Delay, in seconds if HAVE_TIME, or in number of cookies
* issued in the meantime.
* 0 to disable expiration (NOT recommended)
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
index 6913dc0f66..46ade67b9c 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
@@ -934,16 +934,22 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform );
*/
void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl );
void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl );
void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl );
void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
@@ -1023,27 +1029,39 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
* following the above definition.
*
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
unsigned update_hs_digest );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl );
void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl,
const mbedtls_ssl_ciphersuite_t *ciphersuite_info );
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex );
/**
@@ -1108,13 +1126,18 @@ mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig );
mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash );
unsigned char mbedtls_ssl_hash_from_md_alg( int md );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md );
#if defined(MBEDTLS_ECP_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id );
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id );
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl,
mbedtls_md_type_t md );
#endif
@@ -1170,6 +1193,7 @@ static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl )
*
* Return 0 if everything is OK, -1 if not.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
const mbedtls_ssl_ciphersuite_t *ciphersuite,
int cert_endpoint,
@@ -1218,21 +1242,26 @@ static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_PROTO_DTLS)
void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl );
void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_resend( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl );
#endif
/* Visible for testing purposes only */
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl );
void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl );
#endif
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
const mbedtls_ssl_session *src );
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
unsigned char *output,
unsigned char *data, size_t data_len );
@@ -1242,6 +1271,7 @@ int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
unsigned char *hash, size_t *hashlen,
unsigned char *data, size_t data_len,
@@ -1254,11 +1284,13 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
#endif
void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
mbedtls_ssl_transform *transform,
mbedtls_record *rec,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
mbedtls_ssl_transform *transform,
mbedtls_record *rec );
@@ -1276,10 +1308,12 @@ static inline size_t mbedtls_ssl_ep_len( const mbedtls_ssl_context *ssl )
}
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_PROTO_DTLS */
void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl );
void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
@@ -1287,6 +1321,7 @@ void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl,
mbedtls_ssl_transform *transform );
void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial );
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
@@ -1296,6 +1331,7 @@ void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl );
void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_RENEGOTIATION */
@@ -1305,4 +1341,12 @@ void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl );
void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight );
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+#if defined(MBEDTLS_TEST_HOOKS)
+int mbedtls_ssl_check_dtls_clihlo_cookie(
+ mbedtls_ssl_context *ssl,
+ const unsigned char *cli_id, size_t cli_id_len,
+ const unsigned char *in, size_t in_len,
+ unsigned char *obuf, size_t buf_len, size_t *olen );
+#endif
+
#endif /* ssl_internal.h */
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
index a882eed23b..8221051b24 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
@@ -101,7 +101,7 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx );
* supported. Usually that means a 256-bit key.
*
* \note The lifetime of the keys is twice the lifetime of tickets.
- * It is recommended to pick a reasonnable lifetime so as not
+ * It is recommended to pick a reasonable lifetime so as not
* to negate the benefits of forward secrecy.
*
* \return 0 if successful,
diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h
index b1a92b2bcf..44adcbfe03 100644
--- a/thirdparty/mbedtls/include/mbedtls/version.h
+++ b/thirdparty/mbedtls/include/mbedtls/version.h
@@ -38,16 +38,16 @@
*/
#define MBEDTLS_VERSION_MAJOR 2
#define MBEDTLS_VERSION_MINOR 28
-#define MBEDTLS_VERSION_PATCH 0
+#define MBEDTLS_VERSION_PATCH 1
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x021C0000
-#define MBEDTLS_VERSION_STRING "2.28.0"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.0"
+#define MBEDTLS_VERSION_NUMBER 0x021C0100
+#define MBEDTLS_VERSION_STRING "2.28.1"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.1"
#if defined(MBEDTLS_VERSION_C)
diff --git a/thirdparty/mbedtls/include/mbedtls/x509.h b/thirdparty/mbedtls/include/mbedtls/x509.h
index c177501430..31b78df32f 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509.h
@@ -96,7 +96,7 @@
#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980
/** A fatal error occurred, eg the chain is too long or the vrfy callback failed. */
#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000
-/* \} name */
+/** \} name X509 Error codes */
/**
* \name X509 Verify codes
@@ -124,8 +124,8 @@
#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */
#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */
-/* \} name */
-/* \} addtogroup x509_module */
+/** \} name X509 Verify codes */
+/** \} addtogroup x509_module */
/*
* X.509 v3 Subject Alternative Name types.
@@ -255,7 +255,6 @@ typedef struct mbedtls_x509_time
mbedtls_x509_time;
/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */
-/** \} addtogroup x509_module */
/**
* \brief Store the certificate DN in printable form into buf;
@@ -311,6 +310,8 @@ int mbedtls_x509_time_is_past( const mbedtls_x509_time *to );
*/
int mbedtls_x509_time_is_future( const mbedtls_x509_time *from );
+/** \} addtogroup x509_module */
+
#if defined(MBEDTLS_SELF_TEST)
/**
diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crl.h b/thirdparty/mbedtls/include/mbedtls/x509_crl.h
index 7e9e8885f4..9222009019 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509_crl.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509_crl.h
@@ -162,8 +162,8 @@ void mbedtls_x509_crl_init( mbedtls_x509_crl *crl );
*/
void mbedtls_x509_crl_free( mbedtls_x509_crl *crl );
-/* \} name */
-/* \} addtogroup x509_module */
+/** \} name Structures and functions for parsing CRLs */
+/** \} addtogroup x509_module */
#ifdef __cplusplus
}
diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crt.h b/thirdparty/mbedtls/include/mbedtls/x509_crt.h
index 64ccb433ba..0f2885a7ee 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509_crt.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509_crt.h
@@ -107,7 +107,7 @@ mbedtls_x509_crt;
typedef struct mbedtls_x509_san_other_name
{
/**
- * The type_id is an OID as deifned in RFC 5280.
+ * The type_id is an OID as defined in RFC 5280.
* To check the value of the type id, you should use
* \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
*/
@@ -159,7 +159,9 @@ mbedtls_x509_subject_alternative_name;
typedef struct mbedtls_x509_crt_profile
{
uint32_t allowed_mds; /**< MDs for signatures */
- uint32_t allowed_pks; /**< PK algs for signatures */
+ uint32_t allowed_pks; /**< PK algs for public keys;
+ * this applies to all certificates
+ * in the provided chain. */
uint32_t allowed_curves; /**< Elliptic curves for ECDSA */
uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */
}
@@ -850,8 +852,7 @@ void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
-/* \} name */
-/* \} addtogroup x509_module */
+/** \} name Structures and functions for parsing and writing X.509 certificates */
#if defined(MBEDTLS_X509_CRT_WRITE_C)
/**
@@ -862,7 +863,7 @@ void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx );
/**
- * \brief Set the verion for a Certificate
+ * \brief Set the version for a Certificate
* Default: MBEDTLS_X509_CRT_VERSION_3
*
* \param ctx CRT context to use
@@ -978,7 +979,7 @@ int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
* \param is_ca is this a CA certificate
* \param max_pathlen maximum length of certificate chains below this
* certificate (only for CA certificates, -1 is
- * inlimited)
+ * unlimited)
*
* \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED
*/
@@ -1087,6 +1088,8 @@ int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf,
#endif /* MBEDTLS_PEM_WRITE_C */
#endif /* MBEDTLS_X509_CRT_WRITE_C */
+/** \} addtogroup x509_module */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/x509_csr.h b/thirdparty/mbedtls/include/mbedtls/x509_csr.h
index b1dfc21f1f..2a1c046131 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509_csr.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509_csr.h
@@ -151,8 +151,7 @@ void mbedtls_x509_csr_init( mbedtls_x509_csr *csr );
void mbedtls_x509_csr_free( mbedtls_x509_csr *csr );
#endif /* MBEDTLS_X509_CSR_PARSE_C */
-/* \} name */
-/* \} addtogroup x509_module */
+/** \} name Structures and functions for X.509 Certificate Signing Requests (CSR) */
#if defined(MBEDTLS_X509_CSR_WRITE_C)
/**
@@ -182,7 +181,7 @@ int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx,
* private key used to sign the CSR when writing it)
*
* \param ctx CSR context to use
- * \param key Asymetric key to include
+ * \param key Asymmetric key to include
*/
void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key );
@@ -298,6 +297,8 @@ int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, s
#endif /* MBEDTLS_PEM_WRITE_C */
#endif /* MBEDTLS_X509_CSR_WRITE_C */
+/** \} addtogroup x509_module */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c
index 31824e75cf..03d8b7ea61 100644
--- a/thirdparty/mbedtls/library/aes.c
+++ b/thirdparty/mbedtls/library/aes.c
@@ -1106,7 +1106,7 @@ typedef unsigned char mbedtls_be128[16];
*
* This function multiplies a field element by x in the polynomial field
* representation. It uses 64-bit word operations to gain speed but compensates
- * for machine endianess and hence works correctly on both big and little
+ * for machine endianness and hence works correctly on both big and little
* endian machines.
*/
static void mbedtls_gf128mul_x_ble( unsigned char r[16],
@@ -1206,7 +1206,7 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
unsigned char *prev_output = output - 16;
/* Copy ciphertext bytes from the previous block to our output for each
- * byte of cyphertext we won't steal. At the same time, copy the
+ * byte of ciphertext we won't steal. At the same time, copy the
* remainder of the input for this final round (since the loop bounds
* are the same). */
for( i = 0; i < leftover; i++ )
diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c
index 3811ef27a3..afa26a6be9 100644
--- a/thirdparty/mbedtls/library/asn1write.c
+++ b/thirdparty/mbedtls/library/asn1write.c
@@ -133,6 +133,11 @@ int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedt
//
len = mbedtls_mpi_size( X );
+ /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not
+ * as 0 digits. We need to end up with 020100, not with 0200. */
+ if( len == 0 )
+ len = 1;
+
if( *p < start || (size_t)( *p - start ) < len )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
@@ -472,7 +477,7 @@ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
cur->val.len = val_len;
}
- if( val != NULL )
+ if( val != NULL && val_len != 0 )
memcpy( cur->val.p, val, val_len );
return( cur );
diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c
index 62e7f76727..32578e2c68 100644
--- a/thirdparty/mbedtls/library/bignum.c
+++ b/thirdparty/mbedtls/library/bignum.c
@@ -1829,7 +1829,7 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_
/*
* handle trivial cases
*/
- if( b == 1 )
+ if( b == 1 || A->n == 0 )
{
*r = 0;
return( 0 );
@@ -2317,7 +2317,7 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
* TA-TB is even so the division by 2 has an integer result.
* Invariant (I) is preserved since any odd divisor of both TA and TB
* also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
- * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
+ * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
* divides TA.
*/
if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c
index 4ec40d2cac..f3b4bd29ce 100644
--- a/thirdparty/mbedtls/library/cipher.c
+++ b/thirdparty/mbedtls/library/cipher.c
@@ -386,6 +386,12 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
#if defined(MBEDTLS_CHACHA20_C)
if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
{
+ /* Even though the actual_iv_size is overwritten with a correct value
+ * of 12 from the cipher info, return an error to indicate that
+ * the input iv_len is wrong. */
+ if( iv_len != 12 )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
iv,
0U ) ) /* Initial counter value */
@@ -393,6 +399,11 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
}
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 &&
+ iv_len != 12 )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#endif
#endif
if ( actual_iv_size != 0 )
diff --git a/thirdparty/mbedtls/library/constant_time.c b/thirdparty/mbedtls/library/constant_time.c
index 18f1b20daa..e276d23ca0 100644
--- a/thirdparty/mbedtls/library/constant_time.c
+++ b/thirdparty/mbedtls/library/constant_time.c
@@ -489,6 +489,12 @@ int mbedtls_ct_hmac( mbedtls_md_context_t *ctx,
MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) );
MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) );
+ /* Fill the hash buffer in advance with something that is
+ * not a valid hash (barring an attack on the hash and
+ * deliberately-crafted input), in case the caller doesn't
+ * check the return status properly. */
+ memset( output, '!', hash_size );
+
/* For each possible length, compute the hash up to that point */
for( offset = min_data_len; offset <= max_data_len; offset++ )
{
@@ -533,6 +539,13 @@ cleanup:
* about whether the assignment was made or not.
* (Leaking information about the respective sizes of X and Y is ok however.)
*/
+#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
+/*
+ * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
+ * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
+ */
+__declspec(noinline)
+#endif
int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X,
const mbedtls_mpi *Y,
unsigned char assign )
@@ -562,7 +575,7 @@ cleanup:
/*
* Conditionally swap X and Y, without leaking information
* about whether the swap was made or not.
- * Here it is not ok to simply swap the pointers, which whould lead to
+ * Here it is not ok to simply swap the pointers, which would lead to
* different memory access patterns when X and Y are used afterwards.
*/
int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X,
diff --git a/thirdparty/mbedtls/library/constant_time_internal.h b/thirdparty/mbedtls/library/constant_time_internal.h
index bbb3a90670..a550b38fa5 100644
--- a/thirdparty/mbedtls/library/constant_time_internal.h
+++ b/thirdparty/mbedtls/library/constant_time_internal.h
@@ -221,6 +221,13 @@ void mbedtls_ct_memcpy_if_eq( unsigned char *dest,
* offset_secret, but only on \p offset_min, \p offset_max and \p len.
* Functionally equivalent to `memcpy(dst, src + offset_secret, len)`.
*
+ * \note This function reads from \p dest, but the value that
+ * is read does not influence the result and this
+ * function's behavior is well-defined regardless of the
+ * contents of the buffers. This may result in false
+ * positives from static or dynamic analyzers, especially
+ * if \p dest is not initialized.
+ *
* \param dest The destination buffer. This must point to a writable
* buffer of at least \p len bytes.
* \param src The base of the source buffer. This must point to a
diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c
index a604ec0761..a00d66ce87 100644
--- a/thirdparty/mbedtls/library/ctr_drbg.c
+++ b/thirdparty/mbedtls/library/ctr_drbg.c
@@ -828,7 +828,7 @@ static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
return( 1 ); \
}
-#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
+#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
/*
* Checkup routine
@@ -854,7 +854,7 @@ int mbedtls_ctr_drbg_self_test( int verbose )
(void *) entropy_source_pr,
pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
- CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
+ CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
@@ -879,7 +879,7 @@ int mbedtls_ctr_drbg_self_test( int verbose )
(void *) entropy_source_nopr,
pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
- CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
+ CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
diff --git a/thirdparty/mbedtls/library/ecdh.c b/thirdparty/mbedtls/library/ecdh.c
index 9dfa868063..60c6e429de 100644
--- a/thirdparty/mbedtls/library/ecdh.c
+++ b/thirdparty/mbedtls/library/ecdh.c
@@ -399,7 +399,7 @@ static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
}
/*
- * Read the ServerKeyExhange parameters (RFC 4492)
+ * Read the ServerKeyExchange parameters (RFC 4492)
* struct {
* ECParameters curve_params;
* ECPoint public;
diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c
index 368b6c7124..0b9bffb93e 100644
--- a/thirdparty/mbedtls/library/ecjpake.c
+++ b/thirdparty/mbedtls/library/ecjpake.c
@@ -435,7 +435,7 @@ cleanup:
/*
* Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
- * Ouputs: verified peer public keys Xa, Xb
+ * Outputs: verified peer public keys Xa, Xb
*/
static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
const mbedtls_ecp_group *grp,
diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c
index 7f9e1045d4..890f364a08 100644
--- a/thirdparty/mbedtls/library/ecp.c
+++ b/thirdparty/mbedtls/library/ecp.c
@@ -1307,7 +1307,7 @@ cleanup:
* For curves in short Weierstrass form, we do all the internal operations in
* Jacobian coordinates.
*
- * For multiplication, we'll use a comb method with coutermeasueres against
+ * For multiplication, we'll use a comb method with countermeasures against
* SPA, hence timing attacks.
*/
@@ -2251,7 +2251,7 @@ static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
* This function is mainly responsible for administrative work:
* - managing the restart context if enabled
* - managing the table of precomputed points (passed between the below two
- * functions): allocation, computation, ownership tranfer, freeing.
+ * functions): allocation, computation, ownership transfer, freeing.
*
* It delegates the actual arithmetic work to:
* ecp_precompute_comb() and ecp_mul_comb_with_precomp()
@@ -2422,7 +2422,7 @@ cleanup:
/*
* For Montgomery curves, we do all the internal arithmetic in projective
* coordinates. Import/export of points uses only the x coordinates, which is
- * internaly represented as X / Z.
+ * internally represented as X / Z.
*
* For scalar multiplication, we'll use a Montgomery ladder.
*/
@@ -2592,7 +2592,7 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
mbedtls_mpi_free( &R->Y );
- /* RP.X might be sligtly larger than P, so reduce it */
+ /* RP.X might be slightly larger than P, so reduce it */
MOD_ADD( RP.X );
/* Randomize coordinates of the starting point */
diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c
index ff26a18e8f..2199be6461 100644
--- a/thirdparty/mbedtls/library/ecp_curves.c
+++ b/thirdparty/mbedtls/library/ecp_curves.c
@@ -755,6 +755,8 @@ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id )
ECP_VALIDATE_RET( grp != NULL );
mbedtls_ecp_group_free( grp );
+ mbedtls_ecp_group_init( grp );
+
grp->id = id;
switch( id )
diff --git a/thirdparty/mbedtls/library/memory_buffer_alloc.c b/thirdparty/mbedtls/library/memory_buffer_alloc.c
index 0d5d27d3de..cc62324bdc 100644
--- a/thirdparty/mbedtls/library/memory_buffer_alloc.c
+++ b/thirdparty/mbedtls/library/memory_buffer_alloc.c
@@ -555,8 +555,8 @@ static void *buffer_alloc_calloc_mutexed( size_t n, size_t size )
static void buffer_alloc_free_mutexed( void *ptr )
{
- /* We have to good option here, but corrupting the heap seems
- * worse than loosing memory. */
+ /* We have no good option here, but corrupting the heap seems
+ * worse than losing memory. */
if( mbedtls_mutex_lock( &heap.mutex ) )
return;
buffer_alloc_free( ptr );
diff --git a/thirdparty/mbedtls/library/mps_common.h b/thirdparty/mbedtls/library/mps_common.h
index d20776f159..668876ccfc 100644
--- a/thirdparty/mbedtls/library/mps_common.h
+++ b/thirdparty/mbedtls/library/mps_common.h
@@ -51,7 +51,7 @@
* the function's behavior is entirely undefined.
* In addition to state integrity, all MPS structures have a more refined
* notion of abstract state that the API operates on. For example, all layers
- * have a notion of 'abtract read state' which indicates if incoming data has
+ * have a notion of 'abstract read state' which indicates if incoming data has
* been passed to the user, e.g. through mps_l2_read_start() for Layer 2
* or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to
* call these reading functions again until the incoming data has been
diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c
index 5fbe1f764a..8c765e1c8c 100644
--- a/thirdparty/mbedtls/library/net_sockets.c
+++ b/thirdparty/mbedtls/library/net_sockets.c
@@ -107,7 +107,9 @@ static int wsa_init_done = 0;
#include <stdio.h>
+#if defined(MBEDTLS_HAVE_TIME)
#include <time.h>
+#endif
#include <stdint.h>
diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c
index 535ed70eb1..ea5c6b69cb 100644
--- a/thirdparty/mbedtls/library/pkparse.c
+++ b/thirdparty/mbedtls/library/pkparse.c
@@ -474,7 +474,7 @@ static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *g
}
/*
- * grp may already be initilialized; if so, make sure IDs match
+ * grp may already be initialized; if so, make sure IDs match
*/
if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
@@ -807,7 +807,7 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
goto cleanup;
#else
- /* Verify existance of the CRT params */
+ /* Verify existence of the CRT params */
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 )
@@ -1463,10 +1463,16 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
{
p = pem.buf;
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
+ {
+ mbedtls_pem_free( &pem );
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
+ }
if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
+ {
+ mbedtls_pem_free( &pem );
return( ret );
+ }
if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 )
mbedtls_pk_free( ctx );
diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c
index 8a5d40ff1e..d1f6ddb177 100644
--- a/thirdparty/mbedtls/library/rsa.c
+++ b/thirdparty/mbedtls/library/rsa.c
@@ -832,10 +832,10 @@ cleanup:
* the more bits of the key can be recovered. See [3].
*
* Collecting n collisions with m bit long blinding value requires 2^(m-m/n)
- * observations on avarage.
+ * observations on average.
*
* For example with 28 byte blinding to achieve 2 collisions the adversary has
- * to make 2^112 observations on avarage.
+ * to make 2^112 observations on average.
*
* (With the currently (as of 2017 April) known best algorithms breaking 2048
* bit RSA requires approximately as much time as trying out 2^112 random keys.
diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c
index 3826ad27fa..ceec77efb0 100644
--- a/thirdparty/mbedtls/library/ssl_ciphersuites.c
+++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c
@@ -2181,6 +2181,7 @@ const int *mbedtls_ssl_list_ciphersuites( void )
static int supported_ciphersuites[MAX_CIPHERSUITES];
static int supported_init = 0;
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info )
{
(void)cs_info;
diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c
index b87879ce6a..72351c9757 100644
--- a/thirdparty/mbedtls/library/ssl_cli.c
+++ b/thirdparty/mbedtls/library/ssl_cli.c
@@ -53,6 +53,7 @@
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf )
{
if( conf->psk_identity == NULL ||
@@ -73,6 +74,7 @@ static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf )
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf )
{
if( conf->psk_identity == NULL ||
@@ -91,6 +93,7 @@ static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf )
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -161,6 +164,7 @@ static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#if defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -204,6 +208,7 @@ static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
*/
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -302,6 +307,7 @@ static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -373,6 +379,7 @@ static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -404,6 +411,7 @@ static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -477,6 +485,7 @@ static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_cid_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -523,6 +532,7 @@ static int ssl_write_cid_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -555,6 +565,7 @@ static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -585,6 +596,7 @@ static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -616,6 +628,7 @@ static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -647,6 +660,7 @@ static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -689,6 +703,7 @@ static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -748,6 +763,7 @@ static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ALPN */
#if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -868,6 +884,7 @@ static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
/*
* Generate random bytes for ClientHello
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_generate_random( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -917,6 +934,7 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl )
*
* \return 0 if valid, else 1
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_validate_ciphersuite(
const mbedtls_ssl_ciphersuite_t * suite_info,
const mbedtls_ssl_context * ssl,
@@ -960,6 +978,7 @@ static int ssl_validate_ciphersuite(
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1450,6 +1469,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1494,6 +1514,7 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
}
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1520,6 +1541,7 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1545,6 +1567,7 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1601,6 +1624,7 @@ static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1627,6 +1651,7 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1653,6 +1678,7 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1679,6 +1705,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1724,6 +1751,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1758,6 +1786,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
@@ -1828,6 +1857,7 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ALPN */
#if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1948,6 +1978,7 @@ static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
* Parse HelloVerifyRequest. Only called after verifying the HS type.
*/
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
{
const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
@@ -2031,6 +2062,7 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
{
int ret, i;
@@ -2276,16 +2308,6 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
else
{
ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
-
- if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
- mbedtls_ssl_send_alert_message(
- ssl,
- MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
- return( ret );
- }
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
@@ -2538,6 +2560,24 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
}
/*
+ * mbedtls_ssl_derive_keys() has to be called after the parsing of the
+ * extensions. It sets the transform data for the resumed session which in
+ * case of DTLS includes the server CID extracted from the CID extension.
+ */
+ if( ssl->handshake->resume )
+ {
+ if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
+ mbedtls_ssl_send_alert_message(
+ ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+ return( ret );
+ }
+ }
+
+ /*
* Renegotiation security checks
*/
if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
@@ -2591,6 +2631,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end )
@@ -2637,6 +2678,7 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
{
const mbedtls_ecp_curve_info *curve_info;
@@ -2678,6 +2720,7 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) )
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end )
@@ -2703,6 +2746,10 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
tls_id <<= 8;
tls_id |= *(*p)++;
+ /* Check it's a curve we offered */
+ if( mbedtls_ssl_check_curve_tls_id( ssl, tls_id ) != 0 )
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+
/* Convert EC group to PSA key type. */
if( ( handshake->ecdh_psa_type =
mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 )
@@ -2740,6 +2787,7 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end )
@@ -2779,6 +2827,7 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end )
@@ -2825,6 +2874,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
/*
* Generate a pre-master secret and encrypt it with the server's RSA key
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
size_t offset, size_t *olen,
size_t pms_offset )
@@ -2912,6 +2962,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end,
@@ -2978,6 +3029,7 @@ static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2996,6 +3048,8 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
peer_pk = &ssl->session_negotiate->peer_cert->pk;
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ /* This is a public key, so it can't be opaque, so can_do() is a good
+ * enough check to ensure pk_ec() is safe to use below. */
if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
@@ -3029,6 +3083,7 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3147,7 +3202,7 @@ start_processing:
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
- } /* FALLTROUGH */
+ } /* FALLTHROUGH */
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \
@@ -3435,6 +3490,7 @@ exit:
}
#if ! defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -3453,6 +3509,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3624,6 +3681,7 @@ exit:
}
#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3663,6 +3721,7 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3718,7 +3777,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
{
- psa_status_t status;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_attributes_t key_attributes;
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
@@ -3761,13 +3821,19 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
own_pubkey, sizeof( own_pubkey ),
&own_pubkey_len );
if( status != PSA_SUCCESS )
+ {
+ psa_destroy_key( handshake->ecdh_psa_privkey );
+ handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
if( mbedtls_psa_tls_psa_ec_to_ecpoint( own_pubkey,
own_pubkey_len,
&own_pubkey_ecpoint,
&own_pubkey_ecpoint_len ) != 0 )
{
+ psa_destroy_key( handshake->ecdh_psa_privkey );
+ handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
}
@@ -3787,13 +3853,12 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
ssl->handshake->premaster,
sizeof( ssl->handshake->premaster ),
&ssl->handshake->pmslen );
- if( status != PSA_SUCCESS )
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
- status = psa_destroy_key( handshake->ecdh_psa_privkey );
- if( status != PSA_SUCCESS )
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ destruction_status = psa_destroy_key( handshake->ecdh_psa_privkey );
handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+
+ if( status != PSA_SUCCESS || destruction_status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
}
else
#endif /* MBEDTLS_USE_PSA_CRYPTO &&
@@ -3918,7 +3983,10 @@ ecdh_calc_secret:
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only suites. */
if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = ssl_write_encrypted_pms( ssl, header_len,
@@ -3933,7 +4001,10 @@ ecdh_calc_secret:
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only suites. */
if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/*
@@ -3970,7 +4041,10 @@ ecdh_calc_secret:
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only suites. */
if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/*
@@ -4080,6 +4154,7 @@ ecdh_calc_secret:
}
#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -4105,6 +4180,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -4277,6 +4353,7 @@ sign:
#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
diff --git a/thirdparty/mbedtls/library/ssl_cookie.c b/thirdparty/mbedtls/library/ssl_cookie.c
index abf29ae717..3781796b72 100644
--- a/thirdparty/mbedtls/library/ssl_cookie.c
+++ b/thirdparty/mbedtls/library/ssl_cookie.c
@@ -63,7 +63,7 @@
/*
* Cookies are formed of a 4-bytes timestamp (or serial number) and
- * an HMAC of timestemp and client ID.
+ * an HMAC of timestamp and client ID.
*/
#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN )
@@ -122,6 +122,7 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx,
/*
* Generate the HMAC part of a cookie
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx,
const unsigned char time[4],
unsigned char **p, unsigned char *end,
diff --git a/thirdparty/mbedtls/library/ssl_msg.c b/thirdparty/mbedtls/library/ssl_msg.c
index 0b696dd561..e47c538888 100644
--- a/thirdparty/mbedtls/library/ssl_msg.c
+++ b/thirdparty/mbedtls/library/ssl_msg.c
@@ -91,6 +91,7 @@ int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl )
}
#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
unsigned char *buf,
size_t len,
@@ -165,11 +166,16 @@ exit:
static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
uint8_t slot );
static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
mbedtls_record const *rec );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
@@ -187,6 +193,7 @@ static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
return( out_buf_len );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
{
size_t const bytes_written = ssl->out_left;
@@ -203,6 +210,7 @@ static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
return( (int) ( mtu - bytes_written ) );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -254,6 +262,7 @@ static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl
* Double the retransmit timeout value, within the allowed range,
* returning -1 if the maximum value has already been reached.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
{
uint32_t new_timeout;
@@ -353,6 +362,7 @@ static size_t ssl_compute_padding_length( size_t len,
* - A negative error code if `max_len` didn't offer enough space
* for the expansion.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_build_inner_plaintext( unsigned char *content,
size_t *content_size,
size_t remaining,
@@ -380,6 +390,7 @@ static int ssl_build_inner_plaintext( unsigned char *content,
/* This function parses a (D)TLSInnerPlaintext structure.
* See ssl_build_inner_plaintext() for details. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_inner_plaintext( unsigned char const *content,
size_t *content_size,
uint8_t *rec_type )
@@ -474,6 +485,7 @@ static void ssl_extract_add_data_from_record( unsigned char* add_data,
/*
* SSLv3.0 MAC functions
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_mac( mbedtls_md_context_t *md_ctx,
const unsigned char *secret,
const unsigned char *buf, size_t len,
@@ -541,6 +553,7 @@ static int ssl_mac( mbedtls_md_context_t *md_ctx,
#if defined(MBEDTLS_GCM_C) || \
defined(MBEDTLS_CCM_C) || \
defined(MBEDTLS_CHACHAPOLY_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_transform_aead_dynamic_iv_is_explicit(
mbedtls_ssl_transform const *transform )
{
@@ -1245,7 +1258,7 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
add_data, add_data_len );
/* Because of the check above, we know that there are
- * explicit_iv_len Bytes preceeding data, and taglen
+ * explicit_iv_len Bytes preceding data, and taglen
* bytes following data + data_len. This justifies
* the debug message and the invocation of
* mbedtls_cipher_auth_decrypt() below. */
@@ -1590,8 +1603,8 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
if( auth_done == 0 )
{
- unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
- unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD];
+ unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 };
+ unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 };
/* If the initial value of padlen was such that
* data_len < maclen + padlen + 1, then padlen
@@ -1738,6 +1751,7 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
/*
* Compression/decompression functions
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_compress_buf( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1790,6 +1804,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2149,6 +2164,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
/*
* Append current handshake message to current outgoing flight
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_flight_append( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_flight_item *msg;
@@ -2215,6 +2231,7 @@ void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight )
/*
* Swap transform_out and out_ctr with the alternative ones
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_swap_epochs( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_transform *tmp_transform;
@@ -2857,6 +2874,7 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
{
if( ssl->in_msglen < ssl->in_hslen ||
@@ -2882,6 +2900,7 @@ static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
ssl->in_msg[8] );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
{
uint32_t msg_len, frag_off, frag_len;
@@ -2948,6 +2967,7 @@ static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len )
/*
* Check that bitmask is full
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_bitmask_check( unsigned char *mask, size_t len )
{
size_t i;
@@ -3147,6 +3167,7 @@ static inline uint64_t ssl_load_six_bytes( unsigned char *buf )
( (uint64_t) buf[5] ) );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3229,8 +3250,8 @@ void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
/*
- * Without any SSL context, check if a datagram looks like a ClientHello with
- * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message.
+ * Check if a datagram looks like a ClientHello with a valid cookie,
+ * and if it doesn't, generate a HelloVerifyRequest message.
* Both input and output include full DTLS headers.
*
* - if cookie is valid, return 0
@@ -3239,10 +3260,10 @@ void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
* return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
* - otherwise return a specific error code
*/
-static int ssl_check_dtls_clihlo_cookie(
- mbedtls_ssl_cookie_write_t *f_cookie_write,
- mbedtls_ssl_cookie_check_t *f_cookie_check,
- void *p_cookie,
+MBEDTLS_CHECK_RETURN_CRITICAL
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ssl_check_dtls_clihlo_cookie(
+ mbedtls_ssl_context *ssl,
const unsigned char *cli_id, size_t cli_id_len,
const unsigned char *in, size_t in_len,
unsigned char *obuf, size_t buf_len, size_t *olen )
@@ -3276,26 +3297,53 @@ static int ssl_check_dtls_clihlo_cookie(
*
* Minimum length is 61 bytes.
*/
- if( in_len < 61 ||
- in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: in_len=%u",
+ (unsigned) in_len ) );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "cli_id", cli_id, cli_id_len );
+ if( in_len < 61 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: record too short" ) );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ if( in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
in[3] != 0 || in[4] != 0 ||
in[19] != 0 || in[20] != 0 || in[21] != 0 )
{
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: not a good ClientHello" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( " type=%u epoch=%u fragment_offset=%u",
+ in[0],
+ (unsigned) in[3] << 8 | in[4],
+ (unsigned) in[19] << 16 | in[20] << 8 | in[21] ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
sid_len = in[59];
- if( sid_len > in_len - 61 )
+ if( 59 + 1 + sid_len + 1 > in_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: sid_len=%u > %u",
+ (unsigned) sid_len,
+ (unsigned) in_len - 61 ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ MBEDTLS_SSL_DEBUG_BUF( 4, "sid received from network",
+ in + 60, sid_len );
cookie_len = in[60 + sid_len];
- if( cookie_len > in_len - 60 )
+ if( 59 + 1 + sid_len + 1 + cookie_len > in_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: cookie_len=%u > %u",
+ (unsigned) cookie_len,
+ (unsigned) ( in_len - sid_len - 61 ) ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
- if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len,
- cli_id, cli_id_len ) == 0 )
+ MBEDTLS_SSL_DEBUG_BUF( 4, "cookie received from network",
+ in + sid_len + 61, cookie_len );
+ if( ssl->conf->f_cookie_check( ssl->conf->p_cookie,
+ in + sid_len + 61, cookie_len,
+ cli_id, cli_id_len ) == 0 )
{
- /* Valid cookie */
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: valid" ) );
return( 0 );
}
@@ -3330,8 +3378,9 @@ static int ssl_check_dtls_clihlo_cookie(
/* Generate and write actual cookie */
p = obuf + 28;
- if( f_cookie_write( p_cookie,
- &p, obuf + buf_len, cli_id, cli_id_len ) != 0 )
+ if( ssl->conf->f_cookie_write( ssl->conf->p_cookie,
+ &p, obuf + buf_len,
+ cli_id, cli_id_len ) != 0 )
{
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
@@ -3370,6 +3419,7 @@ static int ssl_check_dtls_clihlo_cookie(
* includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected
* errors, and is the right thing to do in both cases).
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3385,15 +3435,13 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
return( 0 );
}
- ret = ssl_check_dtls_clihlo_cookie(
- ssl->conf->f_cookie_write,
- ssl->conf->f_cookie_check,
- ssl->conf->p_cookie,
+ ret = mbedtls_ssl_check_dtls_clihlo_cookie(
+ ssl,
ssl->cli_id, ssl->cli_id_len,
ssl->in_buf, ssl->in_left,
ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
- MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
+ MBEDTLS_SSL_DEBUG_RET( 2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret );
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
{
@@ -3427,6 +3475,7 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
}
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_record_type( uint8_t record_type )
{
if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&
@@ -3459,6 +3508,7 @@ static int ssl_check_record_type( uint8_t record_type )
* Point 2 is needed when the peer is resending, and we have already received
* the first record from a datagram but are still waiting for the others.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
unsigned char *buf,
size_t len,
@@ -3571,7 +3621,6 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
/*
* Parse and validate record version
*/
-
rec->ver[0] = buf[ rec_hdr_version_offset + 0 ];
rec->ver[1] = buf[ rec_hdr_version_offset + 1 ];
mbedtls_ssl_read_version( &major_ver, &minor_ver,
@@ -3580,16 +3629,19 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
if( major_ver != ssl->major_ver )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch: got %u, expected %u",
+ (unsigned) major_ver,
+ (unsigned) ssl->major_ver ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
if( minor_ver > ssl->conf->max_minor_ver )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch: got %u, expected max %u",
+ (unsigned) minor_ver,
+ (unsigned) ssl->conf->max_minor_ver ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
-
/*
* Parse/Copy record sequence number.
*/
@@ -3692,6 +3744,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
{
unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
@@ -3721,6 +3774,7 @@ static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
/*
* If applicable, decrypt record content
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
mbedtls_record *rec )
{
@@ -3854,7 +3908,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
/* Check actual (decrypted) record content length against
* configured maximum. */
- if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
+ if( rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3872,8 +3926,11 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
*/
/* Helper functions for mbedtls_ssl_read_record(). */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_next_record( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
@@ -3961,6 +4018,7 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
}
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
{
if( ssl->in_left > ssl->next_record_offset )
@@ -3969,6 +4027,7 @@ static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_handshake_params * const hs = ssl->handshake;
@@ -4066,6 +4125,7 @@ exit:
return( ret );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
size_t desired )
{
@@ -4108,6 +4168,7 @@ static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
return( -1 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_message( mbedtls_ssl_context *ssl )
{
int ret = 0;
@@ -4312,6 +4373,7 @@ exit:
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
{
/*
@@ -4399,6 +4461,7 @@ static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
{
if( ssl->in_msglen > 0 )
@@ -4425,6 +4488,7 @@ static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
}
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_handshake_params * const hs = ssl->handshake;
@@ -4482,6 +4546,7 @@ exit:
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
mbedtls_record const *rec )
{
@@ -4540,6 +4605,7 @@ static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_next_record( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -4918,6 +4984,9 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
if( ssl == NULL || ssl->conf == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ if( ssl->out_left != 0 )
+ return( mbedtls_ssl_flush_output( ssl ) );
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message ));
@@ -5287,6 +5356,7 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
/*
* Check record counters and renegotiate if they're above the limit.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
{
size_t ep_len = mbedtls_ssl_ep_len( ssl );
@@ -5637,6 +5707,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
* Therefore, it is possible that the input message length is 0 and the
* corresponding return code is 0 on success.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_real( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
@@ -5708,6 +5779,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
* remember whether we already did the split or not.
*/
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_split( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
@@ -5790,9 +5862,6 @@ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
- if( ssl->out_left != 0 )
- return( mbedtls_ssl_flush_output( ssl ) );
-
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
{
if( ( ret = mbedtls_ssl_send_alert_message( ssl,
diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c
index 1a63173204..2efb13cc33 100644
--- a/thirdparty/mbedtls/library/ssl_srv.c
+++ b/thirdparty/mbedtls/library/ssl_srv.c
@@ -78,6 +78,7 @@ void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf,
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -147,6 +148,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf )
{
if( conf->f_psk != NULL )
@@ -167,6 +169,7 @@ static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf )
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
{
if( ssl->conf->f_psk != NULL )
@@ -188,6 +191,7 @@ static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -239,6 +243,7 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
* This needs to be done at a later stage.
*
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -317,6 +322,7 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -383,6 +389,7 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -425,6 +432,7 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -454,6 +462,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -473,6 +482,7 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -545,6 +555,7 @@ static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -567,6 +578,7 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -592,6 +604,7 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -617,6 +630,7 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
size_t len )
@@ -691,6 +705,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
@@ -779,6 +794,7 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ALPN */
#if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -907,6 +923,7 @@ static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
* Return 0 if the given key uses one of the acceptable curves, -1 otherwise
*/
#if defined(MBEDTLS_ECDSA_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_key_curve( mbedtls_pk_context *pk,
const mbedtls_ecp_curve_info **curves )
{
@@ -928,6 +945,7 @@ static int ssl_check_key_curve( mbedtls_pk_context *pk,
* Try picking a certificate for this ciphersuite,
* return 0 on success and -1 on failure.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_pick_cert( mbedtls_ssl_context *ssl,
const mbedtls_ssl_ciphersuite_t * ciphersuite_info )
{
@@ -1032,6 +1050,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
* Check if a given ciphersuite is suitable for use with our config/keys/etc
* Sets ciphersuite_info only if the suite matches.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
const mbedtls_ssl_ciphersuite_t **ciphersuite_info )
{
@@ -1147,6 +1166,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
}
#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl )
{
int ret, got_common_suite;
@@ -1410,6 +1430,7 @@ have_ciphersuite_v2:
/* This function doesn't alert on errors that happen early during
ClientHello parsing because they might indicate that the client is
not talking SSL/TLS at all and would not understand our alert. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_hello( mbedtls_ssl_context *ssl )
{
int ret, got_common_suite;
@@ -1583,7 +1604,7 @@ read_record_header:
* Handshake layer:
* 0 . 0 handshake type
* 1 . 3 handshake length
- * 4 . 5 DTLS only: message seqence number
+ * 4 . 5 DTLS only: message sequence number
* 6 . 8 DTLS only: fragment offset
* 9 . 11 DTLS only: fragment length
*/
@@ -1604,11 +1625,19 @@ read_record_header:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
+ if( buf[1] != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != 0",
+ (unsigned) buf[1] ) );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
/* We don't support fragmentation of ClientHello (yet?) */
- if( buf[1] != 0 ||
- msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) )
+ if( msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != %u + %u",
+ (unsigned) msg_len,
+ (unsigned) mbedtls_ssl_hs_hdr_len( ssl ),
+ (unsigned) ( buf[2] << 8 ) | buf[3] ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
@@ -1649,6 +1678,11 @@ read_record_header:
* For now we don't support fragmentation, so make sure
* fragment_offset == 0 and fragment_length == length
*/
+ MBEDTLS_SSL_DEBUG_MSG(
+ 4, ( "fragment_offset=%u fragment_length=%u length=%u",
+ (unsigned) ( ssl->in_msg[6] << 16 | ssl->in_msg[7] << 8 | ssl->in_msg[8] ),
+ (unsigned) ( ssl->in_msg[9] << 16 | ssl->in_msg[10] << 8 | ssl->in_msg[11] ),
+ (unsigned) ( ssl->in_msg[1] << 16 | ssl->in_msg[2] << 8 | ssl->in_msg[3] ) ) );
if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 ||
memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 )
{
@@ -2354,12 +2388,8 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
const mbedtls_ssl_ciphersuite_t *suite = NULL;
const mbedtls_cipher_info_t *cipher = NULL;
- if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
- ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- *olen = 0;
- return;
- }
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
+ ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;
/*
* RFC 7366: "If a server receives an encrypt-then-MAC request extension
@@ -2372,6 +2402,11 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL ||
cipher->mode != MBEDTLS_MODE_CBC )
{
+ ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;
+ }
+
+ if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED )
+ {
*olen = 0;
return;
}
@@ -2685,6 +2720,7 @@ static void ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_SRTP */
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2805,6 +2841,7 @@ exit:
mbedtls_ssl_session_free( &session_tmp );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
{
#if defined(MBEDTLS_HAVE_TIME)
@@ -3035,6 +3072,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
}
#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -3053,6 +3091,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -3222,18 +3261,23 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ mbedtls_pk_context *own_key = mbedtls_ssl_own_key( ssl );
- if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) )
+ /* Check if the key is a transparent ECDH key.
+ * This also ensures that it is safe to call mbedtls_pk_ec(). */
+ if( mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY &&
+ mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY_DH )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
}
if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx,
- mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ),
+ mbedtls_pk_ec( *own_key ),
MBEDTLS_ECDH_OURS ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret );
@@ -3247,6 +3291,7 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \
defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
size_t *signature_len )
{
@@ -3274,6 +3319,7 @@ static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
/* Prepare the ServerKeyExchange message, up to and including
* calculating the signature if any, but excluding formatting the
* signature and sending the message. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
size_t *signature_len )
{
@@ -3643,6 +3689,7 @@ curve_matching_done:
* that do not include a ServerKeyExchange message, do nothing. Either
* way, if successful, move on to the next step in the SSL state
* machine. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3664,7 +3711,12 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
{
- ssl_get_ecdh_params_from_cert( ssl );
+ ret = ssl_get_ecdh_params_from_cert( ssl );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
+ return( ret );
+ }
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */
@@ -3740,6 +3792,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3779,6 +3832,7 @@ static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p,
const unsigned char *end )
{
@@ -3822,6 +3876,7 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char *
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
unsigned char *peer_pms,
size_t *peer_pmslen,
@@ -3839,6 +3894,7 @@ static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
@@ -3931,6 +3987,7 @@ static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
return( ret );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
@@ -4020,6 +4077,7 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p,
const unsigned char *end )
{
@@ -4080,6 +4138,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -4207,7 +4266,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
- /* For opaque PSKs, we perform the PSK-to-MS derivation atomatically
+ /* For opaque PSKs, we perform the PSK-to-MS derivation automatically
* and skip the intermediate PMS. */
if( ssl_use_opaque_psk( ssl ) == 1 )
MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) );
@@ -4247,7 +4306,10 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only. */
if( ssl_use_opaque_psk( ssl ) == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif
if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 )
@@ -4282,7 +4344,10 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only. */
if( ssl_use_opaque_psk( ssl ) == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif
if( p != end )
@@ -4319,7 +4384,10 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only. */
if( ssl_use_opaque_psk( ssl ) == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
@@ -4386,6 +4454,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
}
#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -4404,6 +4473,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -4597,6 +4667,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
diff --git a/thirdparty/mbedtls/library/ssl_ticket.c b/thirdparty/mbedtls/library/ssl_ticket.c
index 046ed1b2ff..e0126cc9d1 100644
--- a/thirdparty/mbedtls/library/ssl_ticket.c
+++ b/thirdparty/mbedtls/library/ssl_ticket.c
@@ -37,7 +37,7 @@
#include <string.h>
/*
- * Initialze context
+ * Initialize context
*/
void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
{
@@ -66,6 +66,7 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
/*
* Generate/update a key
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
unsigned char index )
{
@@ -96,6 +97,7 @@ static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
/*
* Rotate/generate keys if necessary
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
{
#if !defined(MBEDTLS_HAVE_TIME)
diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c
index 2e6469de83..7badec51ae 100644
--- a/thirdparty/mbedtls/library/ssl_tls.c
+++ b/thirdparty/mbedtls/library/ssl_tls.c
@@ -245,6 +245,7 @@ int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
}
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int resize_buffer( unsigned char **buffer, size_t len_new, size_t *len_old )
{
unsigned char* resized_buffer = mbedtls_calloc( 1, len_new );
@@ -337,6 +338,7 @@ static void handle_buffer_resizing( mbedtls_ssl_context *ssl, int downsizing,
* Key material generation
*/
#if defined(MBEDTLS_SSL_PROTO_SSL3)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl3_prf( const unsigned char *secret, size_t slen,
const char *label,
const unsigned char *random, size_t rlen,
@@ -398,6 +400,7 @@ exit:
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls1_prf( const unsigned char *secret, size_t slen,
const char *label,
const unsigned char *random, size_t rlen,
@@ -605,6 +608,7 @@ static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* de
return( PSA_SUCCESS );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_generic( mbedtls_md_type_t md_type,
const unsigned char *secret, size_t slen,
const char *label,
@@ -679,6 +683,7 @@ static int tls_prf_generic( mbedtls_md_type_t md_type,
#else /* MBEDTLS_USE_PSA_CRYPTO */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_generic( mbedtls_md_type_t md_type,
const unsigned char *secret, size_t slen,
const char *label,
@@ -770,6 +775,7 @@ exit:
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_SHA256_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_sha256( const unsigned char *secret, size_t slen,
const char *label,
const unsigned char *random, size_t rlen,
@@ -781,6 +787,7 @@ static int tls_prf_sha256( const unsigned char *secret, size_t slen,
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_sha384( const unsigned char *secret, size_t slen,
const char *label,
const unsigned char *random, size_t rlen,
@@ -825,6 +832,7 @@ static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && \
defined(MBEDTLS_USE_PSA_CRYPTO)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
{
if( ssl->conf->f_psk != NULL )
@@ -949,6 +957,7 @@ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *,
* - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys
* - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_populate_transform( mbedtls_ssl_transform *transform,
int ciphersuite,
const unsigned char master[48],
@@ -990,6 +999,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \
!defined(MBEDTLS_SSL_EXPORT_KEYS) && \
+ !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
!defined(MBEDTLS_DEBUG_C)
ssl = NULL; /* make sure we don't use it except for those cases */
(void) ssl;
@@ -1361,7 +1371,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
* the structure field for the IV, which the PSA-based
* implementation currently doesn't. */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc,
cipher_info, transform->taglen );
@@ -1404,7 +1414,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
* the structure field for the IV, which the PSA-based
* implementation currently doesn't. */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec,
cipher_info, transform->taglen );
@@ -1511,6 +1521,7 @@ end:
* Outputs:
* - the tls_prf, calc_verify and calc_finished members of handshake structure
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake,
int minor_ver,
mbedtls_md_type_t hash )
@@ -1580,6 +1591,7 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake,
* EMS: passed to calc_verify (debug + (SSL3) session_negotiate)
* PSA-PSA: minor_ver, conf
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake,
unsigned char *master,
const mbedtls_ssl_context *ssl )
@@ -2108,6 +2120,7 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_hello_request( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -2323,6 +2336,7 @@ write_msg:
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
unsigned char *crt_buf,
size_t crt_buf_len )
@@ -2338,6 +2352,7 @@ static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) );
}
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
unsigned char *crt_buf,
size_t crt_buf_len )
@@ -2372,6 +2387,7 @@ static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
* Once the certificate message is read, parse it into a cert chain and
* perform basic checks, but leave actual verification to the caller
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *chain )
{
@@ -2521,6 +2537,7 @@ static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
}
#if defined(MBEDTLS_SSL_SRV_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
{
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
@@ -2570,6 +2587,7 @@ static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
*/
#define SSL_CERTIFICATE_EXPECTED 0
#define SSL_CERTIFICATE_SKIP 1
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
int authmode )
{
@@ -2599,6 +2617,7 @@ static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
return( SSL_CERTIFICATE_EXPECTED );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
int authmode,
mbedtls_x509_crt *chain,
@@ -2696,7 +2715,9 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
{
const mbedtls_pk_context *pk = &chain->pk;
- /* If certificate uses an EC key, make sure the curve is OK */
+ /* If certificate uses an EC key, make sure the curve is OK.
+ * This is a public key, so it can't be opaque, so can_do() is a good
+ * enough check to ensure pk_ec() is safe to use here. */
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
{
@@ -2787,6 +2808,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
}
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
unsigned char *start, size_t len )
{
@@ -2818,6 +2840,7 @@ static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
return( ret );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl,
unsigned char *start, size_t len )
{
@@ -3428,7 +3451,7 @@ void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl )
ssl->handshake = NULL;
/*
- * Free the previous transform and swith in the current one
+ * Free the previous transform and switch in the current one
*/
if( ssl->transform )
{
@@ -3796,6 +3819,7 @@ void mbedtls_ssl_session_init( mbedtls_ssl_session *session )
memset( session, 0, sizeof(mbedtls_ssl_session) );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_handshake_init( mbedtls_ssl_context *ssl )
{
/* Clear old handshake information if present */
@@ -3873,6 +3897,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
/* Dummy cookie callbacks for defaults */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_cookie_write_dummy( void *ctx,
unsigned char **p, unsigned char *end,
const unsigned char *cli_id, size_t cli_id_len )
@@ -3886,6 +3911,7 @@ static int ssl_cookie_write_dummy( void *ctx,
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_cookie_check_dummy( void *ctx,
const unsigned char *cookie, size_t cookie_len,
const unsigned char *cli_id, size_t cli_id_len )
@@ -4303,6 +4329,7 @@ void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf,
}
/* Append a new keycert entry to a (possibly empty) list */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_append_key_cert( mbedtls_ssl_key_cert **head,
mbedtls_x509_crt *cert,
mbedtls_pk_context *key )
@@ -4471,6 +4498,7 @@ static void ssl_conf_remove_psk( mbedtls_ssl_config *conf )
* It checks that the provided identity is well-formed and attempts
* to make a copy of it in the SSL config.
* On failure, the PSK identity in the config remains unset. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf,
unsigned char const *psk_identity,
size_t psk_identity_len )
@@ -4632,6 +4660,9 @@ int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ mbedtls_mpi_free( &conf->dhm_P );
+ mbedtls_mpi_free( &conf->dhm_G );
+
if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 ||
( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 )
{
@@ -4647,6 +4678,9 @@ int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ mbedtls_mpi_free( &conf->dhm_P );
+ mbedtls_mpi_free( &conf->dhm_G );
+
if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 ||
( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 )
{
@@ -5384,6 +5418,7 @@ static unsigned char ssl_serialized_session_header[] = {
* verify_result is put before peer_cert so that all mandatory fields come
* together in one block.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_session_save( const mbedtls_ssl_session *session,
unsigned char omit_header,
unsigned char *buf,
@@ -5583,6 +5618,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session,
* This internal version is wrapped by a public function that cleans up in
* case of error, and has an extra option omit_header.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_session_load( mbedtls_ssl_session *session,
unsigned char omit_header,
const unsigned char *buf,
@@ -5886,6 +5922,7 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl )
/*
* Write HelloRequest to request renegotiation on server
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -6497,6 +6534,7 @@ static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id )
* This internal version is wrapped by a public function that cleans up in
* case of error.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_context_load( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -7320,6 +7358,18 @@ int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_i
return( -1 );
}
+
+/*
+ * Same as mbedtls_ssl_check_curve() but takes a TLS ID for the curve.
+ */
+int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id )
+{
+ const mbedtls_ecp_curve_info *curve_info =
+ mbedtls_ecp_curve_info_from_tls_id( tls_id );
+ if( curve_info == NULL )
+ return( -1 );
+ return( mbedtls_ssl_check_curve( ssl, curve_info->grp_id ) );
+}
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c
index 2de117f52a..5e0aaa4f21 100644
--- a/thirdparty/mbedtls/library/threading.c
+++ b/thirdparty/mbedtls/library/threading.c
@@ -113,7 +113,7 @@ int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_
int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread;
/*
- * With phtreads we can statically initialize mutexes
+ * With pthreads we can statically initialize mutexes
*/
#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 }
diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c
index eb41461320..57bc9bcc12 100644
--- a/thirdparty/mbedtls/library/timing.c
+++ b/thirdparty/mbedtls/library/timing.c
@@ -56,15 +56,15 @@ struct _hr_time
#include <unistd.h>
#include <sys/types.h>
-#include <sys/time.h>
#include <signal.h>
+/* time.h should be included independently of MBEDTLS_HAVE_TIME. If the
+ * platform matches the ifdefs above, it will be used. */
#include <time.h>
-
+#include <sys/time.h>
struct _hr_time
{
struct timeval start;
};
-
#endif /* _WIN32 && !EFIX64 && !EFI32 */
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
@@ -364,7 +364,6 @@ int mbedtls_timing_get_delay( void *data )
return( 0 );
}
-#endif /* !MBEDTLS_TIMING_ALT */
#if defined(MBEDTLS_SELF_TEST)
@@ -526,5 +525,5 @@ hard_test_done:
}
#endif /* MBEDTLS_SELF_TEST */
-
+#endif /* !MBEDTLS_TIMING_ALT */
#endif /* MBEDTLS_TIMING_C */
diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c
index f21e9e6944..3997ebd1f3 100644
--- a/thirdparty/mbedtls/library/x509.c
+++ b/thirdparty/mbedtls/library/x509.c
@@ -741,7 +741,7 @@ int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t i, n;
+ size_t i, j, n;
unsigned char c, merge = 0;
const mbedtls_x509_name *name;
const char *short_name = NULL;
@@ -775,17 +775,24 @@ int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
ret = mbedtls_snprintf( p, n, "\?\?=" );
MBEDTLS_X509_SAFE_SNPRINTF;
- for( i = 0; i < name->val.len; i++ )
+ for( i = 0, j = 0; i < name->val.len; i++, j++ )
{
- if( i >= sizeof( s ) - 1 )
- break;
+ if( j >= sizeof( s ) - 1 )
+ return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
c = name->val.p[i];
+ // Special characters requiring escaping, RFC 1779
+ if( c && strchr( ",=+<>#;\"\\", c ) )
+ {
+ if( j + 1 >= sizeof( s ) - 1 )
+ return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+ s[j++] = '\\';
+ }
if( c < 32 || c >= 127 )
- s[i] = '?';
- else s[i] = c;
+ s[j] = '?';
+ else s[j] = c;
}
- s[i] = '\0';
+ s[j] = '\0';
ret = mbedtls_snprintf( p, n, "%s", s );
MBEDTLS_X509_SAFE_SNPRINTF;
diff --git a/thirdparty/mbedtls/library/x509_crl.c b/thirdparty/mbedtls/library/x509_crl.c
index ac4fc75de3..d2d8042029 100644
--- a/thirdparty/mbedtls/library/x509_crl.c
+++ b/thirdparty/mbedtls/library/x509_crl.c
@@ -52,11 +52,13 @@
#define mbedtls_snprintf snprintf
#endif
+#if defined(MBEDTLS_HAVE_TIME)
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
#include <windows.h>
#else
#include <time.h>
#endif
+#endif
#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
#include <stdio.h>
diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c
index 60312bf2f5..96477e4c9d 100644
--- a/thirdparty/mbedtls/library/x509_crt.c
+++ b/thirdparty/mbedtls/library/x509_crt.c
@@ -63,6 +63,7 @@
#include "mbedtls/threading.h"
#endif
+#if defined(MBEDTLS_HAVE_TIME)
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
#include <windows.h>
#if defined(_MSC_VER) && _MSC_VER <= 1600
@@ -81,6 +82,7 @@
#else
#include <time.h>
#endif
+#endif
#if defined(MBEDTLS_FS_IO)
#include <stdio.h>
diff --git a/thirdparty/mbedtls/library/x509write_crt.c b/thirdparty/mbedtls/library/x509write_crt.c
index 184c90cd33..0c5e991834 100644
--- a/thirdparty/mbedtls/library/x509write_crt.c
+++ b/thirdparty/mbedtls/library/x509write_crt.c
@@ -299,7 +299,7 @@ static int x509_write_time( unsigned char **p, unsigned char *start,
/*
* write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
*/
- if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
+ if( t[0] < '2' || ( t[0] == '2' && t[1] == '0' && t[2] < '5' ) )
{
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
(const unsigned char *) t + 2,
diff --git a/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
index c15736e255..ae81f141c4 100644
--- a/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
+++ b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
@@ -70,6 +70,7 @@ typedef enum SpvSourceLanguage_ {
SpvSourceLanguageOpenCL_CPP = 4,
SpvSourceLanguageHLSL = 5,
SpvSourceLanguageCPP_for_OpenCL = 6,
+ SpvSourceLanguageSYCL = 7,
SpvSourceLanguageMax = 0x7fffffff,
} SpvSourceLanguage;
@@ -184,6 +185,7 @@ typedef enum SpvExecutionMode_ {
SpvExecutionModeNoGlobalOffsetINTEL = 5895,
SpvExecutionModeNumSIMDWorkitemsINTEL = 5896,
SpvExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
+ SpvExecutionModeNamedBarrierCountINTEL = 6417,
SpvExecutionModeMax = 0x7fffffff,
} SpvExecutionMode;
@@ -546,6 +548,8 @@ typedef enum SpvDecoration_ {
SpvDecorationPrefetchINTEL = 5902,
SpvDecorationStallEnableINTEL = 5905,
SpvDecorationFuseLoopsInFunctionINTEL = 5907,
+ SpvDecorationAliasScopeINTEL = 5914,
+ SpvDecorationNoAliasINTEL = 5915,
SpvDecorationBufferLocationINTEL = 5921,
SpvDecorationIOPipeStorageINTEL = 5944,
SpvDecorationFunctionFloatingPointModeINTEL = 6080,
@@ -677,6 +681,7 @@ typedef enum SpvBuiltIn_ {
SpvBuiltInSMCountNV = 5375,
SpvBuiltInWarpIDNV = 5376,
SpvBuiltInSMIDNV = 5377,
+ SpvBuiltInCullMaskKHR = 6021,
SpvBuiltInMax = 0x7fffffff,
} SpvBuiltIn;
@@ -804,6 +809,8 @@ typedef enum SpvMemoryAccessShift_ {
SpvMemoryAccessMakePointerVisibleKHRShift = 4,
SpvMemoryAccessNonPrivatePointerShift = 5,
SpvMemoryAccessNonPrivatePointerKHRShift = 5,
+ SpvMemoryAccessAliasScopeINTELMaskShift = 16,
+ SpvMemoryAccessNoAliasINTELMaskShift = 17,
SpvMemoryAccessMax = 0x7fffffff,
} SpvMemoryAccessShift;
@@ -818,6 +825,8 @@ typedef enum SpvMemoryAccessMask_ {
SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010,
SpvMemoryAccessNonPrivatePointerMask = 0x00000020,
SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020,
+ SpvMemoryAccessAliasScopeINTELMaskMask = 0x00010000,
+ SpvMemoryAccessNoAliasINTELMaskMask = 0x00020000,
} SpvMemoryAccessMask;
typedef enum SpvScope_ {
@@ -1059,6 +1068,7 @@ typedef enum SpvCapability_ {
SpvCapabilityFPGAMemoryAccessesINTEL = 5898,
SpvCapabilityFPGAClusterAttributesINTEL = 5904,
SpvCapabilityLoopFuseINTEL = 5906,
+ SpvCapabilityMemoryAccessAliasingINTEL = 5910,
SpvCapabilityFPGABufferLocationINTEL = 5920,
SpvCapabilityArbitraryPrecisionFixedPointINTEL = 5922,
SpvCapabilityUSMStorageClassesINTEL = 5935,
@@ -1073,13 +1083,17 @@ typedef enum SpvCapability_ {
SpvCapabilityDotProductInput4x8BitPackedKHR = 6018,
SpvCapabilityDotProduct = 6019,
SpvCapabilityDotProductKHR = 6019,
+ SpvCapabilityRayCullMaskKHR = 6020,
SpvCapabilityBitInstructions = 6025,
+ SpvCapabilityGroupNonUniformRotateKHR = 6026,
SpvCapabilityAtomicFloat32AddEXT = 6033,
SpvCapabilityAtomicFloat64AddEXT = 6034,
SpvCapabilityLongConstantCompositeINTEL = 6089,
SpvCapabilityOptNoneINTEL = 6094,
SpvCapabilityAtomicFloat16AddEXT = 6095,
SpvCapabilityDebugInfoModuleINTEL = 6114,
+ SpvCapabilitySplitBarrierINTEL = 6141,
+ SpvCapabilityGroupUniformArithmeticKHR = 6400,
SpvCapabilityMax = 0x7fffffff,
} SpvCapability;
@@ -1535,6 +1549,7 @@ typedef enum SpvOp_ {
SpvOpSubgroupAllKHR = 4428,
SpvOpSubgroupAnyKHR = 4429,
SpvOpSubgroupAllEqualKHR = 4430,
+ SpvOpGroupNonUniformRotateKHR = 4431,
SpvOpSubgroupReadInvocationKHR = 4432,
SpvOpTraceRayKHR = 4445,
SpvOpExecuteCallableKHR = 4446,
@@ -1801,6 +1816,9 @@ typedef enum SpvOp_ {
SpvOpArbitraryFloatPowRINTEL = 5881,
SpvOpArbitraryFloatPowNINTEL = 5882,
SpvOpLoopControlINTEL = 5887,
+ SpvOpAliasDomainDeclINTEL = 5911,
+ SpvOpAliasScopeDeclINTEL = 5912,
+ SpvOpAliasScopeListDeclINTEL = 5913,
SpvOpFixedSqrtINTEL = 5923,
SpvOpFixedRecipINTEL = 5924,
SpvOpFixedRsqrtINTEL = 5925,
@@ -1839,10 +1857,23 @@ typedef enum SpvOp_ {
SpvOpTypeStructContinuedINTEL = 6090,
SpvOpConstantCompositeContinuedINTEL = 6091,
SpvOpSpecConstantCompositeContinuedINTEL = 6092,
+ SpvOpControlBarrierArriveINTEL = 6142,
+ SpvOpControlBarrierWaitINTEL = 6143,
+ SpvOpGroupIMulKHR = 6401,
+ SpvOpGroupFMulKHR = 6402,
+ SpvOpGroupBitwiseAndKHR = 6403,
+ SpvOpGroupBitwiseOrKHR = 6404,
+ SpvOpGroupBitwiseXorKHR = 6405,
+ SpvOpGroupLogicalAndKHR = 6406,
+ SpvOpGroupLogicalOrKHR = 6407,
+ SpvOpGroupLogicalXorKHR = 6408,
SpvOpMax = 0x7fffffff,
} SpvOp;
#ifdef SPV_ENABLE_UTILITY_CODE
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultType) {
*hasResult = *hasResultType = false;
switch (opcode) {
@@ -2197,6 +2228,7 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
case SpvOpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupNonUniformRotateKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpTraceRayKHR: *hasResult = false; *hasResultType = false; break;
case SpvOpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break;
@@ -2452,6 +2484,9 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
case SpvOpArbitraryFloatPowRINTEL: *hasResult = true; *hasResultType = true; break;
case SpvOpArbitraryFloatPowNINTEL: *hasResult = true; *hasResultType = true; break;
case SpvOpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
+ case SpvOpAliasDomainDeclINTEL: *hasResult = true; *hasResultType = false; break;
+ case SpvOpAliasScopeDeclINTEL: *hasResult = true; *hasResultType = false; break;
+ case SpvOpAliasScopeListDeclINTEL: *hasResult = true; *hasResultType = false; break;
case SpvOpFixedSqrtINTEL: *hasResult = true; *hasResultType = true; break;
case SpvOpFixedRecipINTEL: *hasResult = true; *hasResultType = true; break;
case SpvOpFixedRsqrtINTEL: *hasResult = true; *hasResultType = true; break;
@@ -2490,9 +2525,18 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
case SpvOpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break;
case SpvOpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
case SpvOpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+ case SpvOpControlBarrierArriveINTEL: *hasResult = false; *hasResultType = false; break;
+ case SpvOpControlBarrierWaitINTEL: *hasResult = false; *hasResultType = false; break;
+ case SpvOpGroupIMulKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupFMulKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupBitwiseAndKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupBitwiseOrKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupBitwiseXorKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupLogicalAndKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupLogicalOrKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupLogicalXorKHR: *hasResult = true; *hasResultType = true; break;
}
}
#endif /* SPV_ENABLE_UTILITY_CODE */
#endif
-
diff --git a/thirdparty/spirv-reflect/patches/specialization-constants.patch b/thirdparty/spirv-reflect/patches/specialization-constants.patch
index 9bb5f97cd3..99815c9162 100644
--- a/thirdparty/spirv-reflect/patches/specialization-constants.patch
+++ b/thirdparty/spirv-reflect/patches/specialization-constants.patch
@@ -1,8 +1,8 @@
diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c
-index e9b11bf495..f181df5fa2 100644
+index cdcf3ca663..c174ae1900 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.c
+++ b/thirdparty/spirv-reflect/spirv_reflect.c
-@@ -125,6 +125,9 @@ typedef struct SpvReflectPrvDecorations {
+@@ -126,6 +126,9 @@ typedef struct SpvReflectPrvDecorations {
SpvReflectPrvNumberDecoration location;
SpvReflectPrvNumberDecoration offset;
SpvReflectPrvNumberDecoration uav_counter_buffer;
@@ -12,7 +12,7 @@ index e9b11bf495..f181df5fa2 100644
SpvReflectPrvStringDecoration semantic;
uint32_t array_stride;
uint32_t matrix_stride;
-@@ -631,6 +634,9 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
+@@ -639,6 +642,9 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE;
p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE;
p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE;
@@ -22,7 +22,7 @@ index e9b11bf495..f181df5fa2 100644
}
// Mark source file id node
p_parser->source_file_id = (uint32_t)INVALID_VALUE;
-@@ -821,10 +827,16 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
+@@ -829,10 +835,16 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
}
break;
@@ -41,7 +41,7 @@ index e9b11bf495..f181df5fa2 100644
case SpvOpSpecConstantComposite:
case SpvOpSpecConstantOp: {
CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
-@@ -856,7 +868,7 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
+@@ -864,7 +876,7 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
CHECKED_READU32(p_parser, p_node->word_offset + 3, p_access_chain->base_id);
//
// SPIRV_ACCESS_CHAIN_INDEX_OFFSET (4) is the number of words up until the first index:
@@ -50,7 +50,7 @@ index e9b11bf495..f181df5fa2 100644
//
p_access_chain->index_count = (node_word_count - SPIRV_ACCESS_CHAIN_INDEX_OFFSET);
if (p_access_chain->index_count > 0) {
-@@ -1338,6 +1350,9 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
+@@ -1346,6 +1358,9 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
skip = true;
}
break;
@@ -60,7 +60,7 @@ index e9b11bf495..f181df5fa2 100644
case SpvDecorationRelaxedPrecision:
case SpvDecorationBlock:
case SpvDecorationBufferBlock:
-@@ -1481,7 +1496,14 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
+@@ -1495,7 +1510,14 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
p_target_decorations->input_attachment_index.word_offset = word_offset;
}
break;
@@ -76,7 +76,7 @@ index e9b11bf495..f181df5fa2 100644
case SpvReflectDecorationHlslCounterBufferGOOGLE: {
uint32_t word_offset = p_node->word_offset + member_offset+ 3;
CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value);
-@@ -1789,6 +1811,13 @@ static SpvReflectResult ParseType(
+@@ -1803,6 +1825,13 @@ static SpvReflectResult ParseType(
p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE;
}
break;
@@ -90,7 +90,7 @@ index e9b11bf495..f181df5fa2 100644
}
if (result == SPV_REFLECT_RESULT_SUCCESS) {
-@@ -3269,6 +3298,69 @@ static SpvReflectResult ParseExecutionModes(
+@@ -3332,6 +3361,69 @@ static SpvReflectResult ParseExecutionModes(
return SPV_REFLECT_RESULT_SUCCESS;
}
@@ -160,7 +160,7 @@ index e9b11bf495..f181df5fa2 100644
static SpvReflectResult ParsePushConstantBlocks(
SpvReflectPrvParser* p_parser,
SpvReflectShaderModule* p_module)
-@@ -3650,6 +3742,12 @@ static SpvReflectResult CreateShaderModule(
+@@ -3717,6 +3809,12 @@ static SpvReflectResult CreateShaderModule(
result = ParsePushConstantBlocks(&parser, p_module);
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
}
@@ -173,8 +173,8 @@ index e9b11bf495..f181df5fa2 100644
if (result == SPV_REFLECT_RESULT_SUCCESS) {
result = ParseEntryPoints(&parser, p_module);
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
-@@ -3807,6 +3905,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
- SafeFree(p_entry->used_push_constants);
+@@ -3875,6 +3973,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
+ SafeFree(p_entry->execution_modes);
}
SafeFree(p_module->entry_points);
+// -- GODOT begin --
@@ -183,7 +183,7 @@ index e9b11bf495..f181df5fa2 100644
// Push constants
for (size_t i = 0; i < p_module->push_constant_block_count; ++i) {
-@@ -4077,6 +4178,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(
+@@ -4145,6 +4246,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(
return SPV_REFLECT_RESULT_SUCCESS;
}
@@ -223,10 +223,10 @@ index e9b11bf495..f181df5fa2 100644
const SpvReflectShaderModule* p_module,
uint32_t* p_count,
diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h
-index e9e4c40755..948533d3c0 100644
+index 02b81613a1..02850f8811 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.h
+++ b/thirdparty/spirv-reflect/spirv_reflect.h
-@@ -323,6 +323,28 @@ typedef struct SpvReflectTypeDescription {
+@@ -329,6 +329,28 @@ typedef struct SpvReflectTypeDescription {
struct SpvReflectTypeDescription* members;
} SpvReflectTypeDescription;
@@ -255,7 +255,7 @@ index e9e4c40755..948533d3c0 100644
/*! @struct SpvReflectInterfaceVariable
-@@ -472,6 +494,10 @@ typedef struct SpvReflectShaderModule {
+@@ -483,6 +505,10 @@ typedef struct SpvReflectShaderModule {
SpvReflectInterfaceVariable* interface_variables; // Uses value(s) from first entry point
uint32_t push_constant_block_count; // Uses value(s) from first entry point
SpvReflectBlockVariable* push_constant_blocks; // Uses value(s) from first entry point
@@ -266,7 +266,7 @@ index e9e4c40755..948533d3c0 100644
struct Internal {
SpvReflectModuleFlags module_flags;
-@@ -744,6 +770,33 @@ SpvReflectResult spvReflectEnumerateInputVariables(
+@@ -755,6 +781,33 @@ SpvReflectResult spvReflectEnumerateInputVariables(
SpvReflectInterfaceVariable** pp_variables
);
diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c
index f181df5fa2..c174ae1900 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.c
+++ b/thirdparty/spirv-reflect/spirv_reflect.c
@@ -119,6 +119,7 @@ typedef struct SpvReflectPrvDecorations {
bool is_noperspective;
bool is_flat;
bool is_non_writable;
+ bool is_non_readable;
SpvReflectPrvNumberDecoration set;
SpvReflectPrvNumberDecoration binding;
SpvReflectPrvNumberDecoration input_attachment_index;
@@ -306,7 +307,12 @@ static SpvReflectResult IntersectSortedUint32(
size_t* res_size
)
{
+ *pp_res = NULL;
*res_size = 0;
+ if (IsNull(p_arr0) || IsNull(p_arr1)) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
const uint32_t* arr0_end = p_arr0 + arr0_size;
const uint32_t* arr1_end = p_arr1 + arr1_size;
@@ -324,7 +330,6 @@ static SpvReflectResult IntersectSortedUint32(
}
}
- *pp_res = NULL;
if (*res_size > 0) {
*pp_res = (uint32_t*)calloc(*res_size, sizeof(**pp_res));
if (IsNull(*pp_res)) {
@@ -488,6 +493,9 @@ static SpvReflectDecorationFlags ApplyDecorations(const SpvReflectPrvDecorations
if (p_decoration_fields->is_non_writable) {
decorations |= SPV_REFLECT_DECORATION_NON_WRITABLE;
}
+ if (p_decoration_fields->is_non_readable) {
+ decorations |= SPV_REFLECT_DECORATION_NON_READABLE;
+ }
return decorations;
}
@@ -1364,6 +1372,7 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
case SpvDecorationNoPerspective:
case SpvDecorationFlat:
case SpvDecorationNonWritable:
+ case SpvDecorationNonReadable:
case SpvDecorationLocation:
case SpvDecorationBinding:
case SpvDecorationDescriptorSet:
@@ -1462,6 +1471,11 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
}
break;
+ case SpvDecorationNonReadable: {
+ p_target_decorations->is_non_readable = true;
+ }
+ break;
+
case SpvDecorationLocation: {
uint32_t word_offset = p_node->word_offset + member_offset + 3;
CHECKED_READU32(p_parser, word_offset, p_target_decorations->location.value);
@@ -1970,6 +1984,7 @@ static SpvReflectResult ParseDescriptorBindings(
p_descriptor->count = 1;
p_descriptor->uav_counter_id = p_node->decorations.uav_counter_buffer.value;
p_descriptor->type_description = p_type;
+ p_descriptor->decoration_flags = ApplyDecorations(&p_node->decorations);
// If this is in the StorageBuffer storage class, it's for sure a storage
// buffer descriptor. We need to handle this case earlier because in SPIR-V
@@ -3208,8 +3223,8 @@ static SpvReflectResult ParseExecutionModes(
// Read entry point id
uint32_t entry_point_id = 0;
CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id);
-
- // Find entry point
+
+ // Find entry point
SpvReflectEntryPoint* p_entry_point = NULL;
for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) {
if (p_module->entry_points[entry_point_idx].id == entry_point_id) {
@@ -3221,7 +3236,7 @@ static SpvReflectResult ParseExecutionModes(
if (IsNull(p_entry_point)) {
return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT;
}
-
+
// Read execution mode
uint32_t execution_mode = (uint32_t)INVALID_VALUE;
CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode);
@@ -3288,12 +3303,60 @@ static SpvReflectResult ParseExecutionModes(
case SpvExecutionModeLocalSizeId:
case SpvExecutionModeLocalSizeHintId:
case SpvExecutionModePostDepthCoverage:
+ case SpvExecutionModeDenormPreserve:
+ case SpvExecutionModeDenormFlushToZero:
+ case SpvExecutionModeSignedZeroInfNanPreserve:
+ case SpvExecutionModeRoundingModeRTE:
+ case SpvExecutionModeRoundingModeRTZ:
case SpvExecutionModeStencilRefReplacingEXT:
+ case SpvExecutionModeOutputLinesNV:
case SpvExecutionModeOutputPrimitivesNV:
case SpvExecutionModeOutputTrianglesNV:
break;
}
+ p_entry_point->execution_mode_count++;
+ }
+ uint32_t* indices = (uint32_t*)calloc(p_module->entry_point_count, sizeof(indices));
+ if (IsNull(indices)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
}
+ for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) {
+ SpvReflectEntryPoint* p_entry_point = &p_module->entry_points[entry_point_idx];
+ p_entry_point->execution_modes =
+ (SpvExecutionMode*)calloc(p_entry_point->execution_mode_count, sizeof(*p_entry_point->execution_modes));
+ if (IsNull(p_entry_point->execution_modes)) {
+ SafeFree(indices);
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+ for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) {
+ SpvReflectPrvNode* p_node = &(p_parser->nodes[node_idx]);
+ if (p_node->op != SpvOpExecutionMode) {
+ continue;
+ }
+
+ // Read entry point id
+ uint32_t entry_point_id = 0;
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id);
+
+ // Find entry point
+ SpvReflectEntryPoint* p_entry_point = NULL;
+ uint32_t* idx = NULL;
+ for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) {
+ if (p_module->entry_points[entry_point_idx].id == entry_point_id) {
+ p_entry_point = &p_module->entry_points[entry_point_idx];
+ idx = &indices[entry_point_idx];
+ break;
+ }
+ }
+
+ // Read execution mode
+ uint32_t execution_mode = (uint32_t)INVALID_VALUE;
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode);
+ p_entry_point->execution_modes[(*idx)++] = (SpvExecutionMode)execution_mode;
+ }
+ SafeFree(indices);
}
return SPV_REFLECT_RESULT_SUCCESS;
}
@@ -3649,7 +3712,11 @@ static SpvReflectResult CreateShaderModule(
if (flags & SPV_REFLECT_MODULE_FLAG_NO_COPY) {
// Set internal size and pointer to args passed in
p_module->_internal->spirv_size = size;
+#if defined(__cplusplus)
+ p_module->_internal->spirv_code = const_cast<uint32_t*>(static_cast<const uint32_t*>(p_code)); // cast that const away
+#else
p_module->_internal->spirv_code = (void*)p_code; // cast that const away
+#endif
p_module->_internal->spirv_word_count = (uint32_t)(size / SPIRV_WORD_SIZE);
}
else {
@@ -3903,6 +3970,7 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
SafeFree(p_entry->interface_variables);
SafeFree(p_entry->used_uniforms);
SafeFree(p_entry->used_push_constants);
+ SafeFree(p_entry->execution_modes);
}
SafeFree(p_module->entry_points);
// -- GODOT begin --
@@ -5093,6 +5161,7 @@ const char* spvReflectSourceLanguage(SpvSourceLanguage source_lang)
case SpvSourceLanguageOpenCL_CPP : return "OpenCL_CPP";
case SpvSourceLanguageHLSL : return "HLSL";
case SpvSourceLanguageCPP_for_OpenCL : return "CPP_for_OpenCL";
+ case SpvSourceLanguageSYCL : return "SYCL";
case SpvSourceLanguageMax:
break;
}
diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h
index 948533d3c0..02850f8811 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.h
+++ b/thirdparty/spirv-reflect/spirv_reflect.h
@@ -30,7 +30,12 @@ VERSION HISTORY
#ifndef SPIRV_REFLECT_H
#define SPIRV_REFLECT_H
+#if defined(SPIRV_REFLECT_USE_SYSTEM_SPIRV_H)
+#include <spirv/unified1/spirv.h>
+#else
#include "./include/spirv/unified1/spirv.h"
+#endif
+
#include <stdint.h>
#include <string.h>
@@ -139,6 +144,7 @@ typedef enum SpvReflectDecorationFlagBits {
SPV_REFLECT_DECORATION_FLAT = 0x00000040,
SPV_REFLECT_DECORATION_NON_WRITABLE = 0x00000080,
SPV_REFLECT_DECORATION_RELAXED_PRECISION = 0x00000100,
+ SPV_REFLECT_DECORATION_NON_READABLE = 0x00000200,
} SpvReflectDecorationFlagBits;
typedef uint32_t SpvReflectDecorationFlags;
@@ -422,6 +428,8 @@ typedef struct SpvReflectDescriptorBinding {
uint32_t binding;
uint32_t set;
} word_offset;
+
+ SpvReflectDecorationFlags decoration_flags;
} SpvReflectDescriptorBinding;
/*! @struct SpvReflectDescriptorSet
@@ -458,6 +466,9 @@ typedef struct SpvReflectEntryPoint {
uint32_t used_push_constant_count;
uint32_t* used_push_constants;
+ uint32_t execution_mode_count;
+ SpvExecutionMode* execution_modes;
+
struct LocalSize {
uint32_t x;
uint32_t y;